return detail
This commit is contained in:
@@ -188,6 +188,7 @@ export const Pages = {
|
|||||||
detailUser: "/orders/detail-user/",
|
detailUser: "/orders/detail-user/",
|
||||||
detailSeller: "/orders/detail-seller/",
|
detailSeller: "/orders/detail-seller/",
|
||||||
return: "/orders/returns",
|
return: "/orders/returns",
|
||||||
|
returnDetails: "/orders/return-details/",
|
||||||
},
|
},
|
||||||
shipment: {
|
shipment: {
|
||||||
list: "/shipment/list",
|
list: "/shipment/list",
|
||||||
|
|||||||
@@ -0,0 +1,319 @@
|
|||||||
|
import { type FC, useState } from 'react'
|
||||||
|
import { useParams, useNavigate } from 'react-router-dom'
|
||||||
|
import { useGetReturnDetails, useApproveReturn, useRejectReturn } from './hooks/useOrderData'
|
||||||
|
import PageTitle from '@/components/PageTitle'
|
||||||
|
import PageLoading from '@/components/PageLoading'
|
||||||
|
import { formatPrice } from '@/helpers/func'
|
||||||
|
import StatusWithText from '@/components/StatusWithText'
|
||||||
|
import { Calendar, Money3, Box, Location, CloseCircle, TickCircle, Shop } from 'iconsax-react'
|
||||||
|
import Button from '@/components/Button'
|
||||||
|
import { useQueryClient } from '@tanstack/react-query'
|
||||||
|
import ModalConfrim from '@/components/ModalConfrim'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
import { extractErrorMessage } from '@/helpers/utils'
|
||||||
|
|
||||||
|
const ReturnDetails: FC = () => {
|
||||||
|
const { id } = useParams()
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
const { data, isLoading, error } = useGetReturnDetails(id!)
|
||||||
|
const approveReturn = useApproveReturn()
|
||||||
|
const rejectReturn = useRejectReturn()
|
||||||
|
|
||||||
|
const [showApproveModal, setShowApproveModal] = useState(false)
|
||||||
|
const [showRejectModal, setShowRejectModal] = useState(false)
|
||||||
|
|
||||||
|
const handleApprove = async () => {
|
||||||
|
try {
|
||||||
|
await approveReturn.mutateAsync(id!)
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['return-details', id] })
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['order-returns'] })
|
||||||
|
setShowApproveModal(false)
|
||||||
|
navigate('/orders/returns')
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleReject = async () => {
|
||||||
|
await rejectReturn.mutateAsync(id!, {
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['return-details', id] })
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['order-returns'] })
|
||||||
|
setShowRejectModal(false)
|
||||||
|
navigate('/orders/returns')
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast.error(extractErrorMessage(error))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return <PageLoading />
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-96">
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="text-red-500 text-lg mb-2">خطا در بارگذاری دادهها</div>
|
||||||
|
<div className="text-gray-500">لطفا دوباره تلاش کنید</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data?.results?.returnOrder) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-96">
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="text-gray-500 text-lg">مرجوعی یافت نشد</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const returnOrder = data.results.returnOrder
|
||||||
|
|
||||||
|
const getStatusVariant = (status: string): 'success' | 'error' | 'warning' => {
|
||||||
|
switch (status) {
|
||||||
|
case 'Approved':
|
||||||
|
return 'success'
|
||||||
|
case 'Rejected':
|
||||||
|
return 'error'
|
||||||
|
case 'Pending':
|
||||||
|
return 'warning'
|
||||||
|
default:
|
||||||
|
return 'warning'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusText = (status: string): string => {
|
||||||
|
switch (status) {
|
||||||
|
case 'Approved':
|
||||||
|
return 'تایید شده'
|
||||||
|
case 'Rejected':
|
||||||
|
return 'رد شده'
|
||||||
|
case 'Pending':
|
||||||
|
return 'در انتظار'
|
||||||
|
default:
|
||||||
|
return status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='mt-4 space-y-6'>
|
||||||
|
<PageTitle />
|
||||||
|
|
||||||
|
{/* هدر */}
|
||||||
|
<div className='flex justify-between items-center'>
|
||||||
|
<div className='flex items-center gap-3'>
|
||||||
|
<h1 className='text-2xl font-bold'>جزئیات مرجوعی</h1>
|
||||||
|
<StatusWithText
|
||||||
|
variant={getStatusVariant(returnOrder.status)}
|
||||||
|
text={getStatusText(returnOrder.status)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='text-sm text-gray-600'>
|
||||||
|
شماره سفارش: <span className='font-mono'>#{returnOrder.order._id}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* دکمههای عملیات */}
|
||||||
|
{data?.results?.returnOrder?.status === 'Pending' && (
|
||||||
|
<div className='flex gap-3 justify-end'>
|
||||||
|
<Button
|
||||||
|
onClick={() => setShowApproveModal(true)}
|
||||||
|
className='bg-green-600 hover:bg-green-700 text-white w-fit'
|
||||||
|
>
|
||||||
|
<div className='flex items-center gap-2'>
|
||||||
|
<TickCircle color='#fff' size={20} />
|
||||||
|
<div>تایید مرجوعی</div>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => setShowRejectModal(true)}
|
||||||
|
className='bg-red-600 hover:bg-red-700 text-white w-fit'
|
||||||
|
>
|
||||||
|
<div className='flex items-center gap-2'>
|
||||||
|
<CloseCircle color='#fff' size={20} />
|
||||||
|
<div>رد مرجوعی</div>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* کارتهای اطلاعاتی */}
|
||||||
|
<div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6'>
|
||||||
|
{/* اطلاعات فروشگاه */}
|
||||||
|
<div className='bg-white p-6 rounded-3xl'>
|
||||||
|
<div className='flex items-center gap-3 mb-4'>
|
||||||
|
<div className='p-2 bg-blue-100 rounded-xl'>
|
||||||
|
<Shop size={20} color='#3B82F6' />
|
||||||
|
</div>
|
||||||
|
<h3 className='font-medium'>فروشگاه</h3>
|
||||||
|
</div>
|
||||||
|
<div className='space-y-2'>
|
||||||
|
<div className='text-lg font-semibold'>{returnOrder.shopName}</div>
|
||||||
|
<div className='text-sm text-gray-600 flex items-center gap-2'>
|
||||||
|
<Calendar size={14} color='#6B7280' />
|
||||||
|
<div className='mt-1 dltr'>
|
||||||
|
{returnOrder.createdAt}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* مبلغ کل */}
|
||||||
|
<div className='bg-white p-6 rounded-3xl'>
|
||||||
|
<div className='flex items-center gap-3 mb-4'>
|
||||||
|
<div className='p-2 bg-green-100 rounded-xl'>
|
||||||
|
<Money3 size={20} color='#10B981' />
|
||||||
|
</div>
|
||||||
|
<h3 className='font-medium'>مبلغ مرجوعی</h3>
|
||||||
|
</div>
|
||||||
|
<div className='space-y-2'>
|
||||||
|
<div className='text-lg font-bold text-green-600'>
|
||||||
|
{formatPrice(returnOrder.total_price)} تومان
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* آدرس */}
|
||||||
|
<div className='bg-white p-6 rounded-3xl md:col-span-2'>
|
||||||
|
<div className='flex items-center gap-3 mb-4'>
|
||||||
|
<div className='p-2 bg-orange-100 rounded-xl'>
|
||||||
|
<Location size={20} color='#F59E0B' />
|
||||||
|
</div>
|
||||||
|
<h3 className='font-medium'>آدرس</h3>
|
||||||
|
</div>
|
||||||
|
<div className='space-y-3'>
|
||||||
|
<div className='text-sm leading-relaxed'>{returnOrder.order.shipmentAddress.address}</div>
|
||||||
|
<div className='grid grid-cols-2 gap-4 text-sm text-gray-600'>
|
||||||
|
<div>استان: {returnOrder.order.shipmentAddress.province}</div>
|
||||||
|
<div>شهر: {returnOrder.order.shipmentAddress.city}</div>
|
||||||
|
<div>پلاک: {returnOrder.order.shipmentAddress.plaque}</div>
|
||||||
|
<div>کد پستی: <span className='font-mono'>{returnOrder.order.shipmentAddress.postalCode}</span></div>
|
||||||
|
<div className='col-span-2'>تلفن: {returnOrder.order.shipmentAddress.phone}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* آیتمهای مرجوعی */}
|
||||||
|
<div className='bg-white py-8 xl:px-10 px-6 rounded-3xl'>
|
||||||
|
<div className='flex items-center gap-3 mb-6'>
|
||||||
|
<div className='p-2 bg-purple-100 rounded-xl'>
|
||||||
|
<Box size={20} color='#8B5CF6' />
|
||||||
|
</div>
|
||||||
|
<h2 className='text-lg font-medium'>آیتمهای مرجوعی</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='space-y-6'>
|
||||||
|
{returnOrder.returnOrderItems.map((item, index) => (
|
||||||
|
<div key={index} className='border border-gray-100 rounded-xl p-6 bg-gray-50/50'>
|
||||||
|
{/* هدر با وضعیت */}
|
||||||
|
<div className='flex justify-between items-center mb-4'>
|
||||||
|
<h3 className='font-medium text-base'>محصول مرجوعی</h3>
|
||||||
|
<StatusWithText
|
||||||
|
variant={getStatusVariant(item.status)}
|
||||||
|
text={getStatusText(item.status)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* اطلاعات محصول با تصویر */}
|
||||||
|
<div className='bg-white p-4 rounded-lg border border-gray-100 mb-4'>
|
||||||
|
<div className='flex gap-4'>
|
||||||
|
{/* تصویر محصول */}
|
||||||
|
<div className='flex-shrink-0'>
|
||||||
|
<img
|
||||||
|
src={item.shipmentItem.product.imagesUrl?.cover || '/placeholder.png'}
|
||||||
|
alt={item.shipmentItem.product.title_fa}
|
||||||
|
className='w-24 h-24 object-cover rounded-lg'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* جزئیات محصول */}
|
||||||
|
<div className='flex-1'>
|
||||||
|
<h4 className='font-medium text-base mb-3'>{item.shipmentItem.product.title_fa}</h4>
|
||||||
|
<div className='grid grid-cols-2 md:grid-cols-3 gap-3 text-sm'>
|
||||||
|
<div className='text-gray-600'>
|
||||||
|
<span className='font-medium'>تعداد مرجوعی:</span> {item.quantity}
|
||||||
|
</div>
|
||||||
|
<div className='text-gray-600'>
|
||||||
|
<span className='font-medium'>قیمت واحد:</span> {formatPrice(item.shipmentItem.selling_price)} تومان
|
||||||
|
</div>
|
||||||
|
<div className='text-gray-600'>
|
||||||
|
<span className='font-medium'>مبلغ کل:</span> {formatPrice(item.quantity * item.shipmentItem.selling_price)} تومان
|
||||||
|
</div>
|
||||||
|
{item.shipmentItem.discount_percent > 0 && (
|
||||||
|
<div className='text-green-600'>
|
||||||
|
<span className='font-medium'>تخفیف:</span> {item.shipmentItem.discount_percent}%
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className='text-gray-600'>
|
||||||
|
<span className='font-medium'>قیمت خردهفروشی:</span> {formatPrice(item.shipmentItem.retail_price)} تومان
|
||||||
|
</div>
|
||||||
|
<div className='text-gray-600'>
|
||||||
|
<span className='font-medium'>هزینه ارسال:</span> {formatPrice(item.shipmentItem.shipmentCost)} تومان
|
||||||
|
</div>
|
||||||
|
{item.shipmentItem.isFreeShip && (
|
||||||
|
<div className='text-blue-600 font-medium'>
|
||||||
|
ارسال رایگان
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* دلیل مرجوعی */}
|
||||||
|
<div className='bg-white p-4 rounded-lg border border-gray-100 mb-4'>
|
||||||
|
<div className='font-medium text-sm mb-2 text-gray-700'>دلیل مرجوعی:</div>
|
||||||
|
<div className='text-base mb-2'>{item.reason.title}</div>
|
||||||
|
{item.reason.is_mandatory_picture && (
|
||||||
|
<div className='text-xs text-orange-600 flex items-center gap-1'>
|
||||||
|
* نیازمند تصویر
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{item.reason.fineRule && (
|
||||||
|
<div className='mt-2 text-sm text-gray-600'>
|
||||||
|
<span className='font-medium'>جریمه:</span> {item.reason.fineRule.title} ({item.reason.fineRule.fine_percentage}%)
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* توضیحات کاربر */}
|
||||||
|
{item.comment && (
|
||||||
|
<div className='bg-blue-50 p-4 rounded-lg border border-blue-100'>
|
||||||
|
<div className='font-medium text-sm mb-2 text-gray-700'>توضیحات کاربر:</div>
|
||||||
|
<div className='text-sm'>{item.comment}</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* مودالها */}
|
||||||
|
<ModalConfrim
|
||||||
|
isOpen={showApproveModal}
|
||||||
|
close={() => setShowApproveModal(false)}
|
||||||
|
onConfrim={handleApprove}
|
||||||
|
label="آیا از تایید این مرجوعی اطمینان دارید؟"
|
||||||
|
isLoading={approveReturn.isPending}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ModalConfrim
|
||||||
|
isOpen={showRejectModal}
|
||||||
|
close={() => setShowRejectModal(false)}
|
||||||
|
onConfrim={handleReject}
|
||||||
|
label="آیا از رد این مرجوعی اطمینان دارید؟"
|
||||||
|
isLoading={rejectReturn.isPending}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReturnDetails
|
||||||
@@ -10,6 +10,8 @@ import { formatDateShort, formatPrice } from '@/helpers/func'
|
|||||||
import { type ReturnOrderType } from '@/pages/orders/types/ReturnTypes'
|
import { type ReturnOrderType } from '@/pages/orders/types/ReturnTypes'
|
||||||
import { Eye } from 'iconsax-react'
|
import { Eye } from 'iconsax-react'
|
||||||
import ReturnItemsModal from '@/pages/orders/components/ReturnItemsModal'
|
import ReturnItemsModal from '@/pages/orders/components/ReturnItemsModal'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
import { Pages } from '@/config/Pages'
|
||||||
|
|
||||||
const Returns: FC = () => {
|
const Returns: FC = () => {
|
||||||
const [currentPage, setCurrentPage] = useState(1)
|
const [currentPage, setCurrentPage] = useState(1)
|
||||||
@@ -93,13 +95,10 @@ const Returns: FC = () => {
|
|||||||
<Td text={formatDateShort(ret?.createdAt)} />
|
<Td text={formatDateShort(ret?.createdAt)} />
|
||||||
<Td text={String(ret?.returnOrderItems?.quantity ?? 0)} />
|
<Td text={String(ret?.returnOrderItems?.quantity ?? 0)} />
|
||||||
<Td text="">
|
<Td text="">
|
||||||
<button
|
|
||||||
className='h-8 w-8 inline-flex items-center justify-center rounded-lg border border-border hover:bg-accent transition-colors'
|
<Link to={`${Pages.orders.returnDetails}${ret._id}`}>
|
||||||
onClick={() => { setSelectedReturn(ret); setIsModalOpen(true); }}
|
|
||||||
aria-label='نمایش جزئیات'
|
|
||||||
>
|
|
||||||
<Eye size={16} color="#4B5563" />
|
<Eye size={16} color="#4B5563" />
|
||||||
</button>
|
</Link>
|
||||||
</Td>
|
</Td>
|
||||||
</tr>
|
</tr>
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -84,3 +84,23 @@ export const useAddTrackCode = () => {
|
|||||||
mutationFn: api.addTrackCode,
|
mutationFn: api.addTrackCode,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useGetReturnDetails = (id: string) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["return-details", id],
|
||||||
|
queryFn: () => api.getReturnDetails(id),
|
||||||
|
enabled: !!id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useApproveReturn = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.approveReturn,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useRejectReturn = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.rejectReturn,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import type {
|
|||||||
CreateReturnReasonType,
|
CreateReturnReasonType,
|
||||||
NativeOrdersResponseType,
|
NativeOrdersResponseType,
|
||||||
OrderDetailResponseType,
|
OrderDetailResponseType,
|
||||||
|
ReturnOrderDetailResponseType,
|
||||||
ReturnReasonsResponseType,
|
ReturnReasonsResponseType,
|
||||||
} from "../types/Types";
|
} from "../types/Types";
|
||||||
|
|
||||||
@@ -86,3 +87,20 @@ export const addTrackCode = async (params: AddTrackCodeType) => {
|
|||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getReturnDetails = async (
|
||||||
|
id: string
|
||||||
|
): Promise<ReturnOrderDetailResponseType> => {
|
||||||
|
const { data } = await axios.get(`/admin/orders/returns/${id}`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const approveReturn = async (id: string) => {
|
||||||
|
const { data } = await axios.post(`/admin/orders/returns/${id}/approve`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const rejectReturn = async (id: string) => {
|
||||||
|
const { data } = await axios.post(`/admin/orders/returns/${id}/reject`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -337,3 +337,129 @@ export type CreateReturnReasonType = {
|
|||||||
is_mandatory_picture: boolean;
|
is_mandatory_picture: boolean;
|
||||||
fineRule: string;
|
fineRule: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// تایپهای مربوط به جزئیات مرجوعی
|
||||||
|
export type ReturnOrderDetailShipmentItemType = {
|
||||||
|
_id: string;
|
||||||
|
product: number;
|
||||||
|
variant: string;
|
||||||
|
quantity: number;
|
||||||
|
cancelled_quantity: number;
|
||||||
|
returned_quantity: number;
|
||||||
|
selling_price: number;
|
||||||
|
retail_price: number;
|
||||||
|
discount_percent: number;
|
||||||
|
shipmentCost: number;
|
||||||
|
isFreeShip: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ReturnOrderDetailOrderItemType = {
|
||||||
|
_id: string;
|
||||||
|
order: number;
|
||||||
|
shop: string;
|
||||||
|
shipmentItems: ReturnOrderDetailShipmentItemType[];
|
||||||
|
shipper: number;
|
||||||
|
totalSellingPrice: number;
|
||||||
|
totalRetailPrice: number;
|
||||||
|
totalShipmentCost: number;
|
||||||
|
totalCouponDiscount: number;
|
||||||
|
totalPaymentPrice: number;
|
||||||
|
itemsCount: number;
|
||||||
|
trackCode: string | null;
|
||||||
|
postingDate: string | null;
|
||||||
|
postingReceipt: string | null;
|
||||||
|
status: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
__v: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ReturnOrderDetailProductType = {
|
||||||
|
_id: number;
|
||||||
|
title_fa: string;
|
||||||
|
title_en: string;
|
||||||
|
seoTitle: string;
|
||||||
|
seoDescription: string | null;
|
||||||
|
model: string;
|
||||||
|
source: string;
|
||||||
|
description: string;
|
||||||
|
metaDescription: string;
|
||||||
|
tags: string[];
|
||||||
|
advantages: string[];
|
||||||
|
disAdvantages: string[];
|
||||||
|
totalRate: number;
|
||||||
|
category: string;
|
||||||
|
shop: string;
|
||||||
|
brand: string;
|
||||||
|
status: string;
|
||||||
|
adminComments: string | null;
|
||||||
|
step: number;
|
||||||
|
isFake: boolean;
|
||||||
|
variants: string[];
|
||||||
|
voice: string | null;
|
||||||
|
deleted: boolean;
|
||||||
|
specifications: unknown[];
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
__v: number;
|
||||||
|
imagesUrl: ImagesUrlType;
|
||||||
|
rate: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ReturnOrderDetailReturnItemShipmentItemType = {
|
||||||
|
_id: string;
|
||||||
|
product: ReturnOrderDetailProductType;
|
||||||
|
variant: string;
|
||||||
|
quantity: number;
|
||||||
|
cancelled_quantity: number;
|
||||||
|
returned_quantity: number;
|
||||||
|
selling_price: number;
|
||||||
|
retail_price: number;
|
||||||
|
discount_percent: number;
|
||||||
|
shipmentCost: number;
|
||||||
|
isFreeShip: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ReturnOrderDetailReturnItemType = {
|
||||||
|
_id: string;
|
||||||
|
returnOrderId: string;
|
||||||
|
orderItem: ReturnOrderDetailOrderItemType;
|
||||||
|
shipmentItem: ReturnOrderDetailReturnItemShipmentItemType;
|
||||||
|
quantity: number;
|
||||||
|
comment: string;
|
||||||
|
reason: ReturnReasonType;
|
||||||
|
status: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
__v: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ReturnOrderDetailOrderType = {
|
||||||
|
_id: number;
|
||||||
|
user: string;
|
||||||
|
payment: string;
|
||||||
|
shipmentAddress: ShipmentAddressType;
|
||||||
|
orderStatus: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
__v: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ReturnOrderDetailType = {
|
||||||
|
_id: string;
|
||||||
|
order: ReturnOrderDetailOrderType;
|
||||||
|
status: string;
|
||||||
|
total_price: number;
|
||||||
|
shopName: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
returnOrderItems: ReturnOrderDetailReturnItemType[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ReturnOrderDetailResponseType = {
|
||||||
|
status: number;
|
||||||
|
success: boolean;
|
||||||
|
results: {
|
||||||
|
returnOrder: ReturnOrderDetailType;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ import TicketMessages from '@/pages/ticket/TicketMessages'
|
|||||||
import Reviews from '@/pages/products/Reviews'
|
import Reviews from '@/pages/products/Reviews'
|
||||||
import Questions from '@/pages/products/Questions'
|
import Questions from '@/pages/products/Questions'
|
||||||
import Returns from '@/pages/orders/Returns'
|
import Returns from '@/pages/orders/Returns'
|
||||||
|
import ReturnDetails from '@/pages/orders/ReturnDetails'
|
||||||
const MainRouter: FC = () => {
|
const MainRouter: FC = () => {
|
||||||
|
|
||||||
const { hasSubMenu } = useSharedStore()
|
const { hasSubMenu } = useSharedStore()
|
||||||
@@ -199,6 +200,7 @@ const MainRouter: FC = () => {
|
|||||||
<Route path={Pages.blog.category} element={<BlogCategory />} />
|
<Route path={Pages.blog.category} element={<BlogCategory />} />
|
||||||
|
|
||||||
<Route path={Pages.orders.return} element={<Returns />} />
|
<Route path={Pages.orders.return} element={<Returns />} />
|
||||||
|
<Route path={`${Pages.orders.returnDetails}:id`} element={<ReturnDetails />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user