From 002e45de0b7474563f64a75ee5e226499c49d02f Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Sat, 21 Feb 2026 12:45:34 +0330 Subject: [PATCH] invoice list --- src/pages/invoice/ProformaInvoice.tsx | 44 +++++------ src/pages/invoice/hooks/useInvoiceData.ts | 11 ++- src/pages/invoice/service/InvoiceService.ts | 9 ++- src/pages/invoice/types/Types.ts | 84 +++++++++++++++++++++ 4 files changed, 124 insertions(+), 24 deletions(-) diff --git a/src/pages/invoice/ProformaInvoice.tsx b/src/pages/invoice/ProformaInvoice.tsx index bf1fac8..1d29e1d 100644 --- a/src/pages/invoice/ProformaInvoice.tsx +++ b/src/pages/invoice/ProformaInvoice.tsx @@ -6,23 +6,22 @@ import Table from '@/components/Table' import { Eye, Add } from 'iconsax-react' import { Link } from 'react-router-dom' import { Paths } from '@/config/Paths' -import { useGetOrdersInvoiced } from '../order/hooks/useOrderData' import moment from 'moment-jalaali' -import type { OrderType } from '../order/types/Types' import type { FilterValues } from '@/components/Filters' -import { OrderStatusEnum } from '../order/enum/OrderEnum' +import { useGetInvoice } from './hooks/useInvoiceData' +import type { InvoiceType } from './types/Types' -const isInvoiceConfirmed = (status: OrderStatusEnum) => - status !== OrderStatusEnum.WAITING_to_CONFIRM_INVOICE && - status !== OrderStatusEnum.CREATED && - status !== OrderStatusEnum.CANCELED +const isInvoiceConfirmed = (item: InvoiceType) => { + const items = item.items ?? [] + return items.length > 0 && items.every((i) => !!i.confirmedAt) +} const ProformaInvoice: FC = () => { const [activeTab, setActiveTab] = useState(ProformaInvoiceStatusEnum.ALL) const [page, setPage] = useState(1) const [filters, setFilters] = useState({}) - const { data, isLoading } = useGetOrdersInvoiced(page) + const { data, isLoading } = useGetInvoice(page) const meta = data?.meta @@ -30,10 +29,10 @@ const ProformaInvoice: FC = () => { const list = data?.data ?? [] if (activeTab === ProformaInvoiceStatusEnum.CONFIRMED) { - return list.filter((o) => isInvoiceConfirmed(o.status)) + return list.filter((o) => isInvoiceConfirmed(o)) } if (activeTab === ProformaInvoiceStatusEnum.NOT_CONFIRMED) { - return list.filter((o) => o.status === OrderStatusEnum.WAITING_to_CONFIRM_INVOICE) + return list.filter((o) => !isInvoiceConfirmed(o)) } let result = list @@ -43,7 +42,7 @@ const ProformaInvoice: FC = () => { const lower = search.toLowerCase() result = result.filter( (o) => - String(o.orderNumber).includes(search) || + String(o.invoiceNumber).includes(search) || o.user?.firstName?.toLowerCase().includes(lower) || o.user?.lastName?.toLowerCase().includes(lower) || o.user?.phone?.includes(search) @@ -54,7 +53,7 @@ const ProformaInvoice: FC = () => { if (dateFilter) { const filterDate = moment(dateFilter, 'jYYYY/jMM/jDD').format('YYYY-MM-DD') result = result.filter((o) => { - const d = o.invoicedAt || o.createdAt + const d = o.createdAt return d && moment(d).format('YYYY-MM-DD') === filterDate }) } @@ -62,7 +61,7 @@ const ProformaInvoice: FC = () => { return result }, [data?.data, activeTab, filters.search, filters.date]) - const getPaymentStatus = (item: OrderType) => { + const getPaymentStatus = (item: InvoiceType) => { const total = Number(item.total) || 0 const paid = Number(item.paidAmount) || 0 if (total <= 0) return '-' @@ -71,7 +70,7 @@ const ProformaInvoice: FC = () => { return 'پرداخت نشده' } - const getServiceLabel = (item: OrderType) => { + const getServiceLabel = (item: InvoiceType) => { if (!item.items?.length) return '-' if (item.items.length === 1) return item.items[0].product?.title ?? '-' return `${item.items.length} خدمت` @@ -123,9 +122,9 @@ const ProformaInvoice: FC = () => { item.orderNumber, + render: (item) => item.invoiceNumber, }, { key: 'service', @@ -136,14 +135,17 @@ const ProformaInvoice: FC = () => { key: 'issueDate', title: 'تاریخ صدور', render: (item) => - item.invoicedAt - ? moment(item.invoicedAt).format('jYYYY/jMM/jDD') - : moment(item.createdAt).format('jYYYY/jMM/jDD'), + item.createdAt + ? moment(item.createdAt).format('jYYYY/jMM/jDD') + : '-', }, { key: 'lastConfirmDate', title: 'آخرین مهلت تایید', - render: () => '-', + render: (item) => + item.approvalDeadline + ? moment(item.approvalDeadline).format('jYYYY/jMM/jDD') + : '-', }, { key: 'total', @@ -157,7 +159,7 @@ const ProformaInvoice: FC = () => { key: 'confirmStatus', title: 'وضعیت تایید', render: (item) => { - const confirmed = isInvoiceConfirmed(item.status) + const confirmed = isInvoiceConfirmed(item) return ( { @@ -7,7 +7,14 @@ export const useCreateInvoice = () => { return useMutation({ mutationFn: api.createInvoice, onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ["orders-invoiced"] }); + queryClient.invalidateQueries({ queryKey: ["invoice"] }); }, }); }; + +export const useGetInvoice = (page = 1) => { + return useQuery({ + queryKey: ["invoice", page], + queryFn: () => api.getInvoice(page), + }); +}; diff --git a/src/pages/invoice/service/InvoiceService.ts b/src/pages/invoice/service/InvoiceService.ts index d12bd60..811f6fd 100644 --- a/src/pages/invoice/service/InvoiceService.ts +++ b/src/pages/invoice/service/InvoiceService.ts @@ -1,7 +1,14 @@ import axios from "@/config/axios"; -import type { CreatePreInvoiceType } from "../types/Types"; +import type { CreatePreInvoiceType, GetInvoiceResponseType } from "../types/Types"; export const createInvoice = async (params: CreatePreInvoiceType) => { const { data } = await axios.post("/admin/invoice", params); return data; }; + +export const getInvoice = async (page = 1): Promise => { + const { data } = await axios.get("/admin/invoice", { + params: { page }, + }); + return data; +}; diff --git a/src/pages/invoice/types/Types.ts b/src/pages/invoice/types/Types.ts index 395d150..eec8f80 100644 --- a/src/pages/invoice/types/Types.ts +++ b/src/pages/invoice/types/Types.ts @@ -21,3 +21,87 @@ export type CreatePreInvoiceType = { notes?: string; attachments?: InvoiceAttachmentType[]; }; + +// API Response Types +export type InvoiceUserType = { + id: string; + createdAt: string; + deletedAt: string | null; + firstName: string | null; + lastName: string | null; + isActive: boolean; + gender: boolean; + maxCredit: number; + addresse: string | null; + phone: string; +}; + +export type InvoiceRequestType = { + id: string; + createdAt: string; + deletedAt: string | null; + user: string; + requestNumber: number; + status: string; +}; + +export type InvoiceProductType = { + id: string; + createdAt: string; + deletedAt: string | null; + category: string; + title: string; + desc: string; + quantities: number[]; + linkUrl: string | null; + isActive: boolean; + images: string[]; + order: number; +}; + +export type InvoiceItemType = { + id: string; + createdAt: string; + deletedAt: string | null; + invoice: string; + product: InvoiceProductType; + quantity: number; + unitPrice: number; + subTotal: number | null; + discount: number | null; + total: number | null; + description: string; + confirmedAt: string | null; +}; + +export type InvoiceType = { + id: string; + createdAt: string; + deletedAt: string | null; + user: InvoiceUserType; + request: InvoiceRequestType; + invoiceNumber: number; + discount: number; + subTotal: number; + taxAmount: number; + total: number; + paidAmount: number; + balance: number; + enableTax: boolean; + approvalDeadline: string; + attachments: InvoiceAttachmentType[]; + paymentMethod: string; + items: InvoiceItemType[]; +}; + +export type GetInvoiceResponseType = { + statusCode: number; + success: boolean; + data: InvoiceType[]; + meta: { + total: number; + page: number; + limit: number; + totalPages: number; + }; +};