diff --git a/src/config/Paths.tsx b/src/config/Paths.tsx
index aadcda4..2a0aba5 100644
--- a/src/config/Paths.tsx
+++ b/src/config/Paths.tsx
@@ -30,4 +30,7 @@ export const Paths = {
auth: {
login: '/login',
},
+ payment: {
+ payInvoice: '/payments/invoice/',
+ },
}
\ No newline at end of file
diff --git a/src/pages/invoice/Detail.tsx b/src/pages/invoice/Detail.tsx
index 1641902..2418a70 100644
--- a/src/pages/invoice/Detail.tsx
+++ b/src/pages/invoice/Detail.tsx
@@ -4,12 +4,13 @@ import ModalConfirm from '@/components/ModalConfirm'
import Button from '@/components/Button'
import Table from '@/components/Table'
import type { RowDataType } from '@/components/types/TableTypes'
-import { useParams } from 'react-router-dom'
+import { Link, useParams } from 'react-router-dom'
import { useQueryClient } from '@tanstack/react-query'
import { useConfirmInvoiceItem, useGetInvoiceDetail } from './hooks/useInvoiceData'
import { NumberFormat } from '@/config/func'
import moment from 'moment-jalaali'
import type { InvoiceItem as ApiInvoiceItem } from './types/InvoiceTypes'
+import { Paths } from '@/config/Paths'
interface TableInvoiceItem extends RowDataType {
id: string
@@ -135,7 +136,7 @@ const InvoiceDetail: FC = () => {
)
}
- const isPaid = invoice && invoice.paidAmount >= invoice.total && invoice.total > 0
+ // const isPaid = invoice && invoice.paidAmount >= invoice.total && invoice.total > 0
return (
@@ -152,15 +153,13 @@ const InvoiceDetail: FC = () => {
چاپ
-
+
+
+
diff --git a/src/pages/payment/PayInvoice.tsx b/src/pages/payment/PayInvoice.tsx
new file mode 100644
index 0000000..184e323
--- /dev/null
+++ b/src/pages/payment/PayInvoice.tsx
@@ -0,0 +1,246 @@
+import { type FC, useState } 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'
+const methodItems: ItemsSelectType[] = [
+ { value: PaymentMethodEnum.Online, label: 'آنلاین' },
+ { value: PaymentMethodEnum.Cash, label: 'نقد' },
+ { value: PaymentMethodEnum.Credit, label: 'اعتباری' },
+]
+
+const gatewayItems: ItemsSelectType[] = [
+ { value: PaymentGatewayEnum.ZarinPal, label: 'زرینپال' },
+]
+
+const formatPrice = (num: number) => `${NumberFormat(num)} تومان`
+
+const PayInvoice: FC = () => {
+ const { id } = useParams()
+ const { data, isPending } = useGetInvoiceDetail(id ?? '')
+ const { mutate: payInvoice, isPending: isPaying } = usePayInvoice()
+ const multiUpload = useMultiUpload()
+ const [attachmentFiles, setAttachmentFiles] = useState([])
+
+ const invoice = data?.data
+
+ 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)}
+
+
+
+
+ {/* فرم پرداخت */}
+
+
+ )
+}
+
+export default PayInvoice
diff --git a/src/router/MainRouter.tsx b/src/router/MainRouter.tsx
index 6f0e571..c36f437 100644
--- a/src/router/MainRouter.tsx
+++ b/src/router/MainRouter.tsx
@@ -19,6 +19,7 @@ import AddCriticisms from '@/pages/criticisms/Add'
import LearningList from '@/pages/learning/List'
import LearningDetail from '@/pages/learning/Detail'
import InvoiceDetail from '@/pages/invoice/Detail'
+import PayInvoice from '@/pages/payment/PayInvoice'
const MainRouter: FC = () => {
return (
@@ -47,6 +48,7 @@ const MainRouter: FC = () => {
} />
} />
} />
+ } />