From b76b4704debd85c7de86073bb5380453b2a5b524 Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Thu, 2 Jul 2026 19:41:27 +0330 Subject: [PATCH] update order page --- src/pages/invoice/DetailPerfomaInvoice.tsx | 1 - src/pages/invoice/hooks/useInvoiceData.ts | 8 ++ src/pages/invoice/service/InvoiceService.ts | 8 ++ src/pages/invoice/types/Types.ts | 4 + src/pages/order/ConvertToOrders.tsx | 109 ++++++++++++++++++-- src/pages/order/List.tsx | 24 ++--- 6 files changed, 130 insertions(+), 24 deletions(-) diff --git a/src/pages/invoice/DetailPerfomaInvoice.tsx b/src/pages/invoice/DetailPerfomaInvoice.tsx index 1a9b607..62446fa 100644 --- a/src/pages/invoice/DetailPerfomaInvoice.tsx +++ b/src/pages/invoice/DetailPerfomaInvoice.tsx @@ -92,7 +92,6 @@ const DetailPerfomaInvoice: FC = () => { const lineTotal = item.total ?? 0; const convertToOrderUrl = `${Paths.convertToOrder}?${new URLSearchParams({ invoiceItemId: item.id, - productId: item.product?.id ?? '', }).toString()}`; return ( diff --git a/src/pages/invoice/hooks/useInvoiceData.ts b/src/pages/invoice/hooks/useInvoiceData.ts index c551361..f3ec09d 100644 --- a/src/pages/invoice/hooks/useInvoiceData.ts +++ b/src/pages/invoice/hooks/useInvoiceData.ts @@ -28,6 +28,14 @@ export const useGetInvoiceDetail = (id: string | undefined) => { }); }; +export const useGetInvoiceItem = (id: string | null) => { + return useQuery({ + queryKey: ["invoice-item", id], + queryFn: () => api.getInvoiceItemById(id!), + enabled: !!id, + }); +}; + export const useUpdateInvoice = () => { const queryClient = useQueryClient(); diff --git a/src/pages/invoice/service/InvoiceService.ts b/src/pages/invoice/service/InvoiceService.ts index 24855cf..b41ea12 100644 --- a/src/pages/invoice/service/InvoiceService.ts +++ b/src/pages/invoice/service/InvoiceService.ts @@ -2,6 +2,7 @@ import axios from "@/config/axios"; import type { CreatePreInvoiceType, GetInvoiceResponseType, + InvoiceItemDetailType, InvoiceType, UpdatePreInvoiceType, } from "../types/Types"; @@ -23,6 +24,13 @@ export const getInvoiceById = async (id: string) => { return data; }; +export const getInvoiceItemById = async (id: string) => { + const { data } = await axios.get<{ data: InvoiceItemDetailType }>( + `/admin/invoice/item/${id}`, + ); + return data; +}; + export const updateInvoice = async (id: string, params: UpdatePreInvoiceType) => { const { data } = await axios.patch(`/admin/invoice/${id}`, params); return data; diff --git a/src/pages/invoice/types/Types.ts b/src/pages/invoice/types/Types.ts index 0980d0e..a62609b 100644 --- a/src/pages/invoice/types/Types.ts +++ b/src/pages/invoice/types/Types.ts @@ -97,6 +97,10 @@ export type InvoiceItemType = { confirmedAt: string | null; }; +export type InvoiceItemDetailType = Omit & { + invoice: Pick; +}; + export type InvoiceType = { id: string; createdAt: string; diff --git a/src/pages/order/ConvertToOrders.tsx b/src/pages/order/ConvertToOrders.tsx index b3bc192..0766d91 100644 --- a/src/pages/order/ConvertToOrders.tsx +++ b/src/pages/order/ConvertToOrders.tsx @@ -1,6 +1,8 @@ import { useState, type FC } from 'react' import { useFormik } from 'formik' import * as Yup from 'yup' +import moment from 'moment-jalaali' +import { Link, useNavigate, useSearchParams } from 'react-router-dom' import Input from '@/components/Input' import Textarea from '@/components/Textarea' import Select from '@/components/Select' @@ -11,18 +13,19 @@ import type { ConvertToOrderItemType } from './types/Types' import { useConverToOrder, useGetProducts } from './hooks/useOrderData' import { useGetCategory } from '@/pages/product/hooks/useProductData' import { useGetUsers } from '@/pages/user/hooks/useUserData' -import { useNavigate, useSearchParams } from 'react-router-dom' import { toast } from 'react-toastify' import { Paths } from '@/config/Paths' import { extractErrorMessage } from '@/config/func' import { useGetAdmins } from '../admin/hooks/useAdminData' +import { useGetInvoiceItem } from '@/pages/invoice/hooks/useInvoiceData' +import { formatItemDiscountDisplay } from '@/pages/invoice/utils/invoiceItem' -const getInitialValues = ( - invoiceItemId: string | null, - productId: string | null -): ConvertToOrderItemType => ({ +const formatAmount = (amount: number) => + Number(amount).toLocaleString('fa-IR') + ' ریال' + +const getInitialValues = (invoiceItemId: string | null): ConvertToOrderItemType => ({ invoiceItemId: invoiceItemId ?? '', - productId: productId ?? '', + productId: '', userId: '', typeId: '', estimatedDays: 0, @@ -49,18 +52,19 @@ const ConvertToOrders: FC = () => { const navigate = useNavigate() const [searchParams] = useSearchParams() const invoiceItemId = searchParams.get('invoiceItemId') - const productId = searchParams.get('productId') const multiUpload = useMultiUpload() const [attachmentFiles, setAttachmentFiles] = useState([]) const { data: categories } = useGetCategory() const { data: users } = useGetUsers() const { data: products } = useGetProducts() const { data: admins } = useGetAdmins(1, 50) + const { data: invoiceItemData, isLoading: isInvoiceItemLoading } = useGetInvoiceItem(invoiceItemId) + const invoiceItem = invoiceItemData?.data const { mutate: converToOrder, isPending } = useConverToOrder() const formik = useFormik({ - initialValues: getInitialValues(invoiceItemId, productId), + initialValues: getInitialValues(invoiceItemId), validationSchema: getValidationSchema(invoiceItemId), enableReinitialize: true, onSubmit: async (values) => { @@ -76,7 +80,9 @@ const ConvertToOrders: FC = () => { const payload: ConvertToOrderItemType = { ...values, invoiceItemId: invoiceItemId ?? values.invoiceItemId ?? '', - productId: values.productId || undefined, + productId: invoiceItemId + ? invoiceItem?.product?.id + : values.productId || undefined, userId: invoiceItemId ? undefined : values.userId, estimatedDays: Number(values.estimatedDays), description: values.description || undefined, @@ -95,10 +101,95 @@ const ConvertToOrders: FC = () => { }, }) + const customerName = + invoiceItem?.invoice?.user?.firstName && invoiceItem?.invoice?.user?.lastName + ? `${invoiceItem.invoice.user.firstName} ${invoiceItem.invoice.user.lastName}` + : invoiceItem?.invoice?.user?.phone ?? '-' + + const discounts = invoiceItem ? formatItemDiscountDisplay(invoiceItem) : null + return (

تبدیل به سفارش

+ {invoiceItemId && ( +
+
اطلاعات آیتم پیش فاکتور
+ + {isInvoiceItemLoading ? ( +
+ در حال بارگذاری... +
+ ) : invoiceItem ? ( +
+
+
پیش فاکتور
+ + #{invoiceItem.invoice.invoiceNumber} + +
+
+
مشتری
+
{customerName}
+
+
+
محصول
+
{invoiceItem.product?.title ?? '-'}
+
+
+
تعداد
+
{invoiceItem.quantity ?? '-'}
+
+
+
مبلغ واحد
+
+ {invoiceItem.unitPrice != null + ? formatAmount(invoiceItem.unitPrice) + : '-'} +
+
+
+
تخفیف (مبلغ)
+
{discounts?.value ?? '-'}
+
+
+
تخفیف (درصد)
+
{discounts?.percent ?? '-'}
+
+
+
مبلغ کل
+
+ {formatAmount(invoiceItem.total ?? 0)} +
+
+
+
تاریخ تایید
+
+ {invoiceItem.confirmedAt + ? moment(invoiceItem.confirmedAt).format('jYYYY/jMM/jDD HH:mm') + : '-'} +
+
+ {invoiceItem.description && ( +
+
توضیحات
+
+ {invoiceItem.description} +
+
+ )} +
+ ) : ( +
+ آیتم پیش فاکتور یافت نشد. +
+ )} +
+ )} +
{ { key: 'title', title: 'عنوان', - render: (item) => { - return ( -
- {item.title} -
- ) - } + render: (item) => ( + + {item.title} + + ), }, { key: 'customer', @@ -162,15 +163,10 @@ const OrdersList: FC = () => { color='black' /> - - - - + {/* */}
) }