update order detail
deploy to danak / build_and_deploy (push) Has been cancelled

This commit is contained in:
2026-07-17 18:27:25 +03:30
parent 6645809600
commit cdb8f6377b
2 changed files with 15 additions and 156 deletions
+15 -5
View File
@@ -1,16 +1,16 @@
import { type FC } from 'react'
import { Link, useParams } from 'react-router-dom'
import { Edit2, Printer } from 'iconsax-react'
import { DocumentText, Edit2, Printer } from 'iconsax-react'
import { toast } from 'react-toastify'
import BackButton from '@/components/BackButton'
import RefreshButton from '@/components/RefreshButton'
import Button from '@/components/Button'
import { Paths } from '@/config/Paths'
import { extractErrorMessage } from '@/config/func'
import { useGetInvoiceItem } from '@/pages/invoice/hooks/useInvoiceData'
import { useGetOrderDetails, useUpdateOrderStatus } from './hooks/useOrderData'
import TicketSection from './components/TicketSection'
import OrderDetailSidebar from './components/OrderDetailSidebar'
import InvoiceItemDetailSection from './components/InvoiceItemDetailSection'
import type { OrderDetailDataType } from './types/Types'
import { OrderStatusEnum } from './enum/OrderEnum'
@@ -20,6 +20,8 @@ const OrderDetail: FC = () => {
const { mutate: updateOrderStatus, isPending: isUpdatingStatus } =
useUpdateOrderStatus()
const order = data?.data as OrderDetailDataType | undefined
const { data: invoiceItemData } = useGetInvoiceItem(order?.invoiceItem ?? null)
const invoiceId = invoiceItemData?.data?.invoice?.id
const handleUpdateStatus = (status: OrderStatusEnum) => {
if (!id) return
@@ -62,13 +64,23 @@ const OrderDetail: FC = () => {
<div>
<h1 className="text-lg font-light text-gray-900">جزئیات سفارش</h1>
<p className="mt-1 text-sm text-gray-500">
مشاهده اطلاعات سفارش، آیتم پیشفاکتور و گفتگو
مشاهده اطلاعات سفارش و گفتگو
</p>
</div>
</div>
<div className="flex flex-wrap items-center gap-2">
<RefreshButton onClick={() => refetch()} isLoading={isFetching} />
{invoiceId && (
<Link to={Paths.perfomaInvoice.detail + invoiceId}>
<Button className="w-fit px-4 bg-white border border-gray-200 text-gray-800 hover:bg-gray-50">
<div className="flex items-center gap-2">
<DocumentText size={18} color="currentColor" />
پیشفاکتور
</div>
</Button>
</Link>
)}
<Link to={Paths.orderPrint + id}>
<Button className="w-fit px-4 bg-white border border-gray-200 text-gray-800 hover:bg-gray-50">
<div className="flex items-center gap-2">
@@ -90,8 +102,6 @@ const OrderDetail: FC = () => {
<div className="mt-6 flex flex-col-reverse gap-6 xl:flex-row xl:items-start">
<div className="min-w-0 flex-1 space-y-6">
<InvoiceItemDetailSection invoiceItemId={order?.invoiceItem} />
<TicketSection />
</div>
@@ -1,151 +0,0 @@
import { type FC, type ReactNode } from 'react'
import { Link } from 'react-router-dom'
import moment from 'moment-jalaali'
import { DocumentText } from 'iconsax-react'
import PresignedImage from '@/components/PresignedImage'
import { Paths } from '@/config/Paths'
import { useGetInvoiceItem } from '@/pages/invoice/hooks/useInvoiceData'
import { formatItemDiscountDisplay } from '@/pages/invoice/utils/invoiceItem'
import { getUserDisplayName } from '../utils/orderDetailUtils'
type Props = {
invoiceItemId?: string | null
}
const formatAmount = (amount: number) =>
Number(amount).toLocaleString('fa-IR') + ' ریال'
type FieldProps = {
label: string
children: ReactNode
className?: string
}
const Field: FC<FieldProps> = ({ label, children, className }) => (
<div className={className}>
<p className="mb-1.5 text-xs text-gray-500">{label}</p>
<div className="text-sm text-gray-900">{children}</div>
</div>
)
const InvoiceItemDetailSection: FC<Props> = ({ invoiceItemId }) => {
const { data, isLoading, isError } = useGetInvoiceItem(invoiceItemId ?? null)
const invoiceItem = data?.data
const discounts = invoiceItem ? formatItemDiscountDisplay(invoiceItem) : null
const imageUrl = invoiceItem?.product?.images?.[0]
if (!invoiceItemId) {
return (
<section id="invoice-item" className="rounded-3xl bg-white p-8 text-center shadow-sm">
<p className="text-sm text-gray-500">آیتم فاکتوری به این سفارش متصل نیست.</p>
</section>
)
}
if (isLoading) {
return (
<section id="invoice-item" className="overflow-hidden rounded-3xl bg-white shadow-sm animate-pulse">
<div className="border-b border-gray-100 px-5 py-4 md:px-6">
<div className="h-5 w-40 rounded bg-gray-200" />
</div>
<div className="p-5 md:p-6 space-y-4">
<div className="h-24 rounded-2xl bg-gray-100" />
<div className="grid grid-cols-2 gap-4 sm:grid-cols-3">
{Array.from({ length: 6 }).map((_, i) => (
<div key={i} className="h-14 rounded-xl bg-gray-100" />
))}
</div>
</div>
</section>
)
}
if (isError || !invoiceItem) {
return (
<section id="invoice-item" className="rounded-3xl bg-white p-8 text-center shadow-sm">
<p className="text-sm text-red-500">آیتم پیشفاکتور یافت نشد.</p>
</section>
)
}
return (
<section id="invoice-item" className="overflow-hidden rounded-3xl bg-white shadow-sm">
<div className="border-b border-gray-100 px-5 py-4 md:px-6">
<h2 className="text-base font-medium text-gray-900">جزئیات آیتم پیشفاکتور</h2>
<p className="mt-0.5 text-xs text-gray-500">
اطلاعات مالی و محصول مرتبط با این سفارش
</p>
</div>
<div className="p-5 md:p-6">
<div className="flex flex-col gap-5 md:flex-row">
<div className="size-24 shrink-0 overflow-hidden rounded-xl border border-gray-200 bg-gray-50">
{imageUrl ? (
<PresignedImage
src={imageUrl}
alt={invoiceItem.product?.title}
className="size-full object-cover"
/>
) : (
<div className="flex size-full items-center justify-center text-gray-300">
<DocumentText size={32} />
</div>
)}
</div>
<div className="min-w-0 flex-1 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
<Field label="پیش‌فاکتور">
<Link
to={Paths.perfomaInvoice.detail + invoiceItem.invoice.id}
className="font-medium text-[#0037FF] hover:underline"
>
#{invoiceItem.invoice.invoiceNumber}
</Link>
</Field>
<Field label="مشتری">
{getUserDisplayName(invoiceItem.invoice.user)}
</Field>
<Field label="محصول">
{invoiceItem.product?.title ?? '—'}
</Field>
<Field label="تعداد">
{invoiceItem.quantity?.toLocaleString('fa-IR') ?? '—'}
</Field>
<Field label="مبلغ واحد">
{invoiceItem.unitPrice != null
? formatAmount(invoiceItem.unitPrice)
: '—'}
</Field>
<Field label="تخفیف (مبلغ)">
{discounts?.value ?? '—'}
</Field>
<Field label="تخفیف (درصد)">
{discounts?.percent ?? '—'}
</Field>
<Field label="مبلغ کل">
<span className="font-semibold">
{formatAmount(invoiceItem.total ?? 0)}
</span>
</Field>
<Field label="تاریخ تایید">
{invoiceItem.confirmedAt
? moment(invoiceItem.confirmedAt).format('jYYYY/jMM/jDD HH:mm')
: '—'}
</Field>
</div>
</div>
{invoiceItem.description && (
<div className="mt-5 rounded-xl border border-dashed border-gray-200 bg-gray-50/60 px-4 py-3">
<p className="text-xs font-medium text-gray-500 mb-1.5">توضیحات</p>
<p className="whitespace-pre-wrap text-sm leading-7 text-gray-800">
{invoiceItem.description}
</p>
</div>
)}
</div>
</section>
)
}
export default InvoiceItemDetailSection