import { type FC, useState, useMemo, useEffect } from 'react' import { useFormik } from 'formik' import * as Yup from 'yup' import { useParams } from 'react-router-dom' import Input from '@/components/Input' import Select from '@/components/Select' import type { ItemsSelectType } from '@/components/Select' import Textarea from '@/components/Textarea' import UploadBox from '@/components/UploadBox' import Button from '@/components/Button' import { TickCircle } from 'iconsax-react' import { useGetInvoiceDetail } from '@/pages/invoice/hooks/useInvoiceData' import { usePayInvoice } from './hooks/usePaymentData' import { useMultiUpload } from '@/pages/uploader/hooks/useUploader' import { NumberFormat } from '@/config/func' import { toast } from '@/shared/toast' import type { ErrorType } from '@/helpers/types' import type { PayInvoiceParamsType } from './types/Types' import { PaymentGatewayEnum, PaymentMethodEnum } from './enum/Enum' import { useGetMe } from '../user/hooks/useUserData' const getMethodItems = (userCredit: number): ItemsSelectType[] => [ { value: PaymentMethodEnum.Online, label: 'آنلاین' }, { value: PaymentMethodEnum.Cash, label: 'نقد' }, { value: PaymentMethodEnum.Credit, label: 'اعتباری', disabled: userCredit <= 0, }, ] const gatewayItems: ItemsSelectType[] = [ { value: PaymentGatewayEnum.ZarinPal, label: 'زرین‌پال' }, ] const formatPrice = (num: number) => `${NumberFormat(num)} تومان` const PayInvoice: FC = () => { const { data: user } = useGetMe() const { id } = useParams() const { data, isPending } = useGetInvoiceDetail(id ?? '') const { mutate: payInvoice, isPending: isPaying } = usePayInvoice() const multiUpload = useMultiUpload() const [attachmentFiles, setAttachmentFiles] = useState([]) const userCredit = user?.maxCredit ?? 0 const methodItems = useMemo(() => getMethodItems(userCredit), [userCredit]) const invoice = data?.data useEffect(() => { if (userCredit <= 0 && formik.values.method === PaymentMethodEnum.Credit) { formik.setFieldValue('method', PaymentMethodEnum.Online) } // eslint-disable-next-line react-hooks/exhaustive-deps -- only run when userCredit is known }, [userCredit]) const formik = useFormik({ initialValues: { amount: invoice?.balance ?? 0, method: PaymentMethodEnum.Online, gateway: PaymentGatewayEnum.ZarinPal, description: '', attachments: [], }, validationSchema: Yup.object({ amount: Yup.number() .required('مبلغ اجباری است') .min(1, 'مبلغ باید بیشتر از صفر باشد'), method: Yup.string().required('روش پرداخت اجباری است'), gateway: Yup.string().when('method', { is: PaymentMethodEnum.Online, then: (schema) => schema.required('درگاه پرداخت اجباری است'), }), description: Yup.string(), attachments: Yup.array().of(Yup.string()), }), enableReinitialize: true, onSubmit: async (values) => { if (!id) return let attachments: string[] = values.attachments ?? [] if (attachmentFiles.length > 0) { try { const uploadResult = await multiUpload.mutateAsync(attachmentFiles) attachments = (uploadResult?.data ?? []).map( (item: { url?: string }) => item?.url ?? '' ).filter(Boolean) } catch (error) { toast((error as ErrorType)?.response?.data?.error?.message?.[0] ?? 'خطا در آپلود فایل‌ها', 'error') return } } payInvoice( { invoiceId: id, params: { ...values, attachments, }, }, { onSuccess: (res) => { const paymentUrl = res?.data?.paymentUrl if (paymentUrl) { toast('در حال انتقال به درگاه پرداخت', 'success') window.location.href = paymentUrl return } toast('پرداخت با موفقیت ثبت شد', 'success') }, onError: (error: ErrorType) => { toast( error?.response?.data?.error?.message?.[0] ?? 'خطا در ثبت پرداخت', 'error' ) }, } ) }, }) if (isPending && !invoice) { return (
در حال بارگذاری...
) } if (!id || !invoice) { return (
صورت حساب یافت نشد
) } return (
پرداخت صورت حساب
{/* خلاصه صورت حساب */}
اطلاعات صورت حساب
شماره صورت حساب: {invoice.invoiceNumber}
مبلغ کل: {formatPrice(invoice.total)}
پرداخت شده: {formatPrice(invoice.paidAmount)}
مانده: {formatPrice(invoice.balance)}
اعتبار: {formatPrice(userCredit)}
{/* فرم پرداخت */}
ثبت پرداخت
formik.setFieldValue( 'amount', Number((e.target.value ?? '').replace(/,/g, '')) || 0 ) } onBlur={formik.handleBlur} seprator error_text={ formik.touched.amount && formik.errors.amount ? formik.errors.amount : '' } /> )} {formik.values.method !== PaymentMethodEnum.Online && ( <>