orders list native with status filter + seller
This commit is contained in:
@@ -140,4 +140,15 @@ export const Pages = {
|
|||||||
update: "/products/warranty/update/",
|
update: "/products/warranty/update/",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
orders: {
|
||||||
|
native: "/orders/native",
|
||||||
|
sellers: "/orders/seller",
|
||||||
|
admin: "/orders/native",
|
||||||
|
completed: "/orders/native?status=Completed",
|
||||||
|
cancelled: "/orders/native?status=Cancelled",
|
||||||
|
pending: "/orders/native?status=Pending",
|
||||||
|
detail: "/orders/native/",
|
||||||
|
cancellationCategories: "/orders/cancellation-categories",
|
||||||
|
returnCategories: "/orders/return-categories",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
import { type FC, useState } from 'react'
|
||||||
|
import PageLoading from '../../components/PageLoading'
|
||||||
|
import Error from '../../components/Error'
|
||||||
|
import PaginationUi from '../../components/PaginationUi'
|
||||||
|
import Td from '../../components/Td'
|
||||||
|
import TrashWithConfrim from '../../components/TrashWithConfrim'
|
||||||
|
import { Edit } from 'iconsax-react'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
import Button from '@/components/Button'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import { type CancellationCategoryType, type PagerType } from './types/Types'
|
||||||
|
|
||||||
|
const CancellationCategories: FC = () => {
|
||||||
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
// TODO: Add category data fetching hook
|
||||||
|
const isLoading = false;
|
||||||
|
const error = null;
|
||||||
|
const refetch = () => { };
|
||||||
|
// TODO: Add delete mutation
|
||||||
|
const deleteCategoryMutation = { isPending: false, mutateAsync: async (_id: string) => { } };
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
// Mock data for now
|
||||||
|
const categories: CancellationCategoryType[] = [];
|
||||||
|
const pager: PagerType = { page: currentPage, limit: 10, totalPages: 1, totalItems: 0, prevPage: null, nextPage: null };
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-[400px]">
|
||||||
|
<PageLoading />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-[400px]">
|
||||||
|
<Error errorText="خطا در بارگذاری دستهبندی کنسلیها" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDeleteCategory = async (categoryId: string) => {
|
||||||
|
await deleteCategoryMutation.mutateAsync(categoryId);
|
||||||
|
refetch()
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className='flex justify-end mt-5'>
|
||||||
|
<Button
|
||||||
|
label='افزودن دستهبندی کنسلی'
|
||||||
|
onClick={() => navigate('/orders/cancellation-categories/create')}
|
||||||
|
className='w-fit'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='relative overflow-x-auto rounded-3xl mt-5 w-full'>
|
||||||
|
<table className='w-full text-sm'>
|
||||||
|
<thead className='thead'>
|
||||||
|
<tr>
|
||||||
|
<Td text={'عنوان'} />
|
||||||
|
<Td text={'توضیحات'} />
|
||||||
|
<Td text={'وضعیت'} />
|
||||||
|
<Td text={'عملیات'} />
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{categories.length === 0 ? (
|
||||||
|
<tr className='tr'>
|
||||||
|
<td colSpan={4} className="text-center py-8 text-gray-500">
|
||||||
|
هیچ دستهبندی کنسلی یافت نشد
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
) : (
|
||||||
|
categories.map((category: any) => (
|
||||||
|
<tr key={category.id} className='tr'>
|
||||||
|
<Td text={category.title} />
|
||||||
|
<Td text={category.description} />
|
||||||
|
<Td text="">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className={`px-2 py-1 rounded-full text-xs`}>
|
||||||
|
{category.status}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Td>
|
||||||
|
<Td text="">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Link to={`/orders/cancellation-categories/${category.id}`}>
|
||||||
|
<Edit color='#8C90A3' size={16} className="cursor-pointer hover:text-blue-500" />
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<TrashWithConfrim
|
||||||
|
onDelete={() => handleDeleteCategory(category.id)}
|
||||||
|
isLoading={deleteCategoryMutation.isPending}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<PaginationUi
|
||||||
|
pager={pager}
|
||||||
|
onPageChange={(page) => {
|
||||||
|
setCurrentPage(page);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CancellationCategories
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
import { type FC, useState } from 'react'
|
||||||
|
import { useSearchParams } from 'react-router-dom'
|
||||||
|
import PageLoading from '../../components/PageLoading'
|
||||||
|
import Error from '../../components/Error'
|
||||||
|
import PaginationUi from '../../components/PaginationUi'
|
||||||
|
import Td from '../../components/Td'
|
||||||
|
import { Eye } from 'iconsax-react'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
import { type NativeOrderType } from '@/pages/orders/types/Types'
|
||||||
|
import { useGetNativeOrders } from '@/pages/orders/hooks/useOrderData'
|
||||||
|
import { Pages } from '@/config/Pages'
|
||||||
|
|
||||||
|
const STATUS_CONFIG = {
|
||||||
|
Cancelled: { label: 'کنسل شده', color: 'bg-red-100 text-red-800' },
|
||||||
|
wait_payment: { label: 'در انتظار پرداخت', color: 'bg-orange-100 text-orange-800' },
|
||||||
|
process_by_sellers: { label: 'در حال پردازش توسط فروشنده', color: 'bg-blue-100 text-blue-800' },
|
||||||
|
cancelled_system: { label: 'کنسل شده توسط سیستم', color: 'bg-red-100 text-red-800' },
|
||||||
|
Delivered: { label: 'تحویل داده شده', color: 'bg-green-100 text-green-800' },
|
||||||
|
} as const
|
||||||
|
|
||||||
|
const getStatusLabel = (status: string): string => STATUS_CONFIG[status as keyof typeof STATUS_CONFIG]?.label || status
|
||||||
|
|
||||||
|
const getStatusColor = (status: string): string => {
|
||||||
|
const statusConfig = STATUS_CONFIG[status as keyof typeof STATUS_CONFIG]
|
||||||
|
return statusConfig && 'color' in statusConfig ? statusConfig.color : 'bg-gray-100 text-gray-800'
|
||||||
|
}
|
||||||
|
|
||||||
|
const Native: FC = () => {
|
||||||
|
const [searchParams] = useSearchParams()
|
||||||
|
const status = searchParams.get('status') || ''
|
||||||
|
const [currentPage, setCurrentPage] = useState(1)
|
||||||
|
|
||||||
|
const { data, isLoading, error } = useGetNativeOrders(currentPage, status)
|
||||||
|
|
||||||
|
const orders = data?.results?.orders || []
|
||||||
|
const pager = data?.results?.pager ? {
|
||||||
|
...data.results.pager,
|
||||||
|
prevPage: data.results.pager.prevPage ? true : null,
|
||||||
|
nextPage: data.results.pager.nextPage ? 'next' : null
|
||||||
|
} : {
|
||||||
|
page: 1,
|
||||||
|
limit: 10,
|
||||||
|
totalPages: 1,
|
||||||
|
totalItems: 0,
|
||||||
|
prevPage: null,
|
||||||
|
nextPage: null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-[400px]">
|
||||||
|
<PageLoading />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-[400px]">
|
||||||
|
<Error errorText={`خطا در بارگذاری ${getStatusLabel(status)}`} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTableHeaders = () => {
|
||||||
|
const headers = [
|
||||||
|
'شماره سفارش',
|
||||||
|
'مشتری',
|
||||||
|
'مبلغ',
|
||||||
|
'وضعیت'
|
||||||
|
]
|
||||||
|
|
||||||
|
headers.push('تاریخ')
|
||||||
|
headers.push('عملیات')
|
||||||
|
|
||||||
|
return headers.map(header => <Td key={header} text={header} />)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTableRow = (order: NativeOrderType) => {
|
||||||
|
const statusColor = getStatusColor(order.orderStatus)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<tr key={order._id} className='tr'>
|
||||||
|
<Td text={`#${order._id}`} />
|
||||||
|
<Td text={order.user?.fullName || 'نامشخص'} />
|
||||||
|
<Td text={(order.payment?.totalPrice || 0).toLocaleString('fa-IR')} />
|
||||||
|
<Td text="">
|
||||||
|
<span className={`px-2 py-1 rounded-full text-xs ${statusColor}`}>
|
||||||
|
{getStatusLabel(order.orderStatus)}
|
||||||
|
</span>
|
||||||
|
</Td>
|
||||||
|
<Td text={order.createdAt || 'نامشخص'} />
|
||||||
|
<Td text="">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Link to={`${Pages.orders.detail}${order._id}?status=${status}`}>
|
||||||
|
<Eye color='#8C90A3' size={16} className="cursor-pointer hover:text-blue-500 transition-colors" />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</Td>
|
||||||
|
</tr>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnCount = 6
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<h1 className="text-2xl font-bold">{getStatusLabel(status)}</h1>
|
||||||
|
|
||||||
|
<div className='relative overflow-x-auto rounded-3xl bg-white shadow-sm'>
|
||||||
|
<table className='w-full text-sm'>
|
||||||
|
<thead className='thead'>
|
||||||
|
<tr>
|
||||||
|
{getTableHeaders()}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{orders.length === 0 ? (
|
||||||
|
<tr className='tr'>
|
||||||
|
<td colSpan={columnCount} className="text-center py-12 text-gray-500">
|
||||||
|
هیچ سفارشی یافت نشد
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
) : (
|
||||||
|
orders.map(order => getTableRow(order))
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{orders.length > 0 && (
|
||||||
|
<PaginationUi
|
||||||
|
pager={pager}
|
||||||
|
onPageChange={setCurrentPage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Native
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
import { type FC, useState } from 'react'
|
||||||
|
import PageLoading from '../../components/PageLoading'
|
||||||
|
import Error from '../../components/Error'
|
||||||
|
import PaginationUi from '../../components/PaginationUi'
|
||||||
|
import Td from '../../components/Td'
|
||||||
|
import TrashWithConfrim from '../../components/TrashWithConfrim'
|
||||||
|
import { Edit } from 'iconsax-react'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
import Button from '@/components/Button'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import { type ReturnCategoryType, type PagerType } from './types/Types'
|
||||||
|
|
||||||
|
const ReturnCategories: FC = () => {
|
||||||
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
// TODO: Add category data fetching hook
|
||||||
|
const isLoading = false;
|
||||||
|
const error = null;
|
||||||
|
const refetch = () => { };
|
||||||
|
// TODO: Add delete mutation
|
||||||
|
const deleteCategoryMutation = { isPending: false, mutateAsync: async (_id: string) => { } };
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
// Mock data for now
|
||||||
|
const categories: ReturnCategoryType[] = [];
|
||||||
|
const pager: PagerType = { page: currentPage, limit: 10, totalPages: 1, totalItems: 0, prevPage: null, nextPage: null };
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-[400px]">
|
||||||
|
<PageLoading />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-[400px]">
|
||||||
|
<Error errorText="خطا در بارگذاری دستهبندی مرجوعیها" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDeleteCategory = async (categoryId: string) => {
|
||||||
|
await deleteCategoryMutation.mutateAsync(categoryId);
|
||||||
|
refetch()
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className='flex justify-end mt-5'>
|
||||||
|
<Button
|
||||||
|
label='افزودن دستهبندی مرجوعی'
|
||||||
|
onClick={() => navigate('/orders/return-categories/create')}
|
||||||
|
className='w-fit'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='relative overflow-x-auto rounded-3xl mt-5 w-full'>
|
||||||
|
<table className='w-full text-sm'>
|
||||||
|
<thead className='thead'>
|
||||||
|
<tr>
|
||||||
|
<Td text={'عنوان'} />
|
||||||
|
<Td text={'توضیحات'} />
|
||||||
|
<Td text={'وضعیت'} />
|
||||||
|
<Td text={'عملیات'} />
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{categories.length === 0 ? (
|
||||||
|
<tr className='tr'>
|
||||||
|
<td colSpan={4} className="text-center py-8 text-gray-500">
|
||||||
|
هیچ دستهبندی مرجوعی یافت نشد
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
) : (
|
||||||
|
categories.map((category: any) => (
|
||||||
|
<tr key={category.id} className='tr'>
|
||||||
|
<Td text={category.title} />
|
||||||
|
<Td text={category.description} />
|
||||||
|
<Td text="">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className={`px-2 py-1 rounded-full text-xs`}>
|
||||||
|
{category.status}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Td>
|
||||||
|
<Td text="">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Link to={`/orders/return-categories/${category.id}`}>
|
||||||
|
<Edit color='#8C90A3' size={16} className="cursor-pointer hover:text-blue-500" />
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<TrashWithConfrim
|
||||||
|
onDelete={() => handleDeleteCategory(category.id)}
|
||||||
|
isLoading={deleteCategoryMutation.isPending}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<PaginationUi
|
||||||
|
pager={pager}
|
||||||
|
onPageChange={(page) => {
|
||||||
|
setCurrentPage(page);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReturnCategories
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
import { type FC, useState } from 'react'
|
||||||
|
import { useSearchParams } from 'react-router-dom'
|
||||||
|
import PageLoading from '../../components/PageLoading'
|
||||||
|
import Error from '../../components/Error'
|
||||||
|
import PaginationUi from '../../components/PaginationUi'
|
||||||
|
import Td from '../../components/Td'
|
||||||
|
import { Eye } from 'iconsax-react'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
import { type NativeOrderType } from '@/pages/orders/types/Types'
|
||||||
|
import { useGetSellerOrders } from '@/pages/orders/hooks/useOrderData'
|
||||||
|
import { Pages } from '@/config/Pages'
|
||||||
|
|
||||||
|
const STATUS_CONFIG = {
|
||||||
|
Cancelled: { label: 'کنسل شده', color: 'bg-red-100 text-red-800' },
|
||||||
|
wait_payment: { label: 'در انتظار پرداخت', color: 'bg-orange-100 text-orange-800' },
|
||||||
|
process_by_sellers: { label: 'در حال پردازش توسط فروشنده', color: 'bg-blue-100 text-blue-800' },
|
||||||
|
cancelled_system: { label: 'کنسل شده توسط سیستم', color: 'bg-red-100 text-red-800' },
|
||||||
|
Delivered: { label: 'تحویل داده شده', color: 'bg-green-100 text-green-800' },
|
||||||
|
} as const
|
||||||
|
|
||||||
|
const getStatusLabel = (status: string): string => STATUS_CONFIG[status as keyof typeof STATUS_CONFIG]?.label || status
|
||||||
|
|
||||||
|
const getStatusColor = (status: string): string => {
|
||||||
|
const statusConfig = STATUS_CONFIG[status as keyof typeof STATUS_CONFIG]
|
||||||
|
return statusConfig && 'color' in statusConfig ? statusConfig.color : 'bg-gray-100 text-gray-800'
|
||||||
|
}
|
||||||
|
|
||||||
|
const OrdersSeller: FC = () => {
|
||||||
|
const [searchParams] = useSearchParams()
|
||||||
|
const status = searchParams.get('status') || ''
|
||||||
|
const [currentPage, setCurrentPage] = useState(1)
|
||||||
|
|
||||||
|
const { data, isLoading, error } = useGetSellerOrders(currentPage, status)
|
||||||
|
|
||||||
|
const orders = data?.results?.orders || []
|
||||||
|
const pager = data?.results?.pager ? {
|
||||||
|
...data.results.pager,
|
||||||
|
prevPage: data.results.pager.prevPage ? true : null,
|
||||||
|
nextPage: data.results.pager.nextPage ? 'next' : null
|
||||||
|
} : {
|
||||||
|
page: 1,
|
||||||
|
limit: 10,
|
||||||
|
totalPages: 1,
|
||||||
|
totalItems: 0,
|
||||||
|
prevPage: null,
|
||||||
|
nextPage: null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-[400px]">
|
||||||
|
<PageLoading />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center min-h-[400px]">
|
||||||
|
<Error errorText={`خطا در بارگذاری ${getStatusLabel(status)}`} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTableHeaders = () => {
|
||||||
|
const headers = [
|
||||||
|
'شماره سفارش',
|
||||||
|
'مشتری',
|
||||||
|
'مبلغ',
|
||||||
|
'وضعیت'
|
||||||
|
]
|
||||||
|
|
||||||
|
headers.push('تاریخ')
|
||||||
|
headers.push('عملیات')
|
||||||
|
|
||||||
|
return headers.map(header => <Td key={header} text={header} />)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTableRow = (order: NativeOrderType) => {
|
||||||
|
const statusColor = getStatusColor(order.orderStatus)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<tr key={order._id} className='tr'>
|
||||||
|
<Td text={`#${order._id}`} />
|
||||||
|
<Td text={order.user?.fullName || 'نامشخص'} />
|
||||||
|
<Td text={(order.payment?.totalPrice || 0).toLocaleString('fa-IR')} />
|
||||||
|
<Td text="">
|
||||||
|
<span className={`px-2 py-1 rounded-full text-xs ${statusColor}`}>
|
||||||
|
{getStatusLabel(order.orderStatus)}
|
||||||
|
</span>
|
||||||
|
</Td>
|
||||||
|
<Td text={order.createdAt || 'نامشخص'} />
|
||||||
|
<Td text="">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Link to={`${Pages.orders.detail}${order._id}?status=${status}`}>
|
||||||
|
<Eye color='#8C90A3' size={16} className="cursor-pointer hover:text-blue-500 transition-colors" />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</Td>
|
||||||
|
</tr>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnCount = 6
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<h1 className="text-2xl font-bold">{getStatusLabel(status)}</h1>
|
||||||
|
|
||||||
|
<div className='relative overflow-x-auto rounded-3xl bg-white shadow-sm'>
|
||||||
|
<table className='w-full text-sm'>
|
||||||
|
<thead className='thead'>
|
||||||
|
<tr>
|
||||||
|
{getTableHeaders()}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{orders.length === 0 ? (
|
||||||
|
<tr className='tr'>
|
||||||
|
<td colSpan={columnCount} className="text-center py-12 text-gray-500">
|
||||||
|
هیچ سفارشی یافت نشد
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
) : (
|
||||||
|
orders.map(order => getTableRow(order))
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{orders.length > 0 && (
|
||||||
|
<PaginationUi
|
||||||
|
pager={pager}
|
||||||
|
onPageChange={setCurrentPage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OrdersSeller
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
export const enum PaymentStatus {
|
||||||
|
Pending = "Pending",
|
||||||
|
Cancelled = "Cancelled",
|
||||||
|
Completed = "Completed",
|
||||||
|
}
|
||||||
|
export const enum OrdersStatus {
|
||||||
|
wait_payment = "wait_payment",
|
||||||
|
process_by_seller = "process_by_sellers",
|
||||||
|
cancelled_system = "cancelled_system",
|
||||||
|
Cancelled = "cancelled",
|
||||||
|
Delivered = "Delivered",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const enum OrderItemsStatus {
|
||||||
|
Processing = "Processing",
|
||||||
|
Shipped = "Shipped",
|
||||||
|
Delivered = "Delivered",
|
||||||
|
cancelled_shop = "cancelled_shop",
|
||||||
|
cancelled_system = "cancelled_system",
|
||||||
|
cancelled_user = "cancelled_user",
|
||||||
|
Returned = "Returned",
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import * as api from "../service/OrderService";
|
||||||
|
|
||||||
|
export const useGetNativeOrders = (
|
||||||
|
page: number = 1,
|
||||||
|
status: string = "all"
|
||||||
|
) => {
|
||||||
|
const { data, isLoading, error } = useQuery({
|
||||||
|
queryKey: ["orders", page, status],
|
||||||
|
queryFn: () => api.getNativeOrders(page, status),
|
||||||
|
});
|
||||||
|
return { data, isLoading, error };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetSellerOrders = (
|
||||||
|
page: number = 1,
|
||||||
|
status: string = "all"
|
||||||
|
) => {
|
||||||
|
const { data, isLoading, error } = useQuery({
|
||||||
|
queryKey: ["orders", page, status],
|
||||||
|
queryFn: () => api.getSellerOrders(page, status),
|
||||||
|
});
|
||||||
|
return { data, isLoading, error };
|
||||||
|
};
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import axios from "../../../config/axios";
|
||||||
|
import type { NativeOrdersResponseType } from "../types/Types";
|
||||||
|
|
||||||
|
export const getNativeOrders = async (
|
||||||
|
page: number = 1,
|
||||||
|
status: string
|
||||||
|
): Promise<NativeOrdersResponseType> => {
|
||||||
|
const { data } = await axios.get("/admin/orders/native", {
|
||||||
|
params: { page, status },
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getSellerOrders = async (
|
||||||
|
page: number = 1,
|
||||||
|
status: string
|
||||||
|
): Promise<NativeOrdersResponseType> => {
|
||||||
|
const { data } = await axios.get("/admin/orders/seller", {
|
||||||
|
params: { page, status },
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
};
|
||||||
@@ -0,0 +1,245 @@
|
|||||||
|
// تایپهای مربوط به سفارشات
|
||||||
|
|
||||||
|
export type OrderType = {
|
||||||
|
_id: string;
|
||||||
|
orderNumber: string;
|
||||||
|
customer: {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
seller?: {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
amount: number;
|
||||||
|
status: "Completed" | "Cancelled" | "Pending" | string;
|
||||||
|
date: string;
|
||||||
|
cancellationReason?: string;
|
||||||
|
cancelledDate?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PaymentType = {
|
||||||
|
_id: string;
|
||||||
|
transaction_id: string | null;
|
||||||
|
payment_method: PaymentMethodType;
|
||||||
|
priceDetails: PriceDetailsType;
|
||||||
|
totalPrice: number;
|
||||||
|
paymentStatus: string;
|
||||||
|
createdAt: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PaymentMethodType = {
|
||||||
|
_id: string;
|
||||||
|
title_fa: string;
|
||||||
|
title_en: string;
|
||||||
|
description: string;
|
||||||
|
provider: string;
|
||||||
|
isActive: boolean;
|
||||||
|
type: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PriceDetailsType = {
|
||||||
|
shipping_cost: number;
|
||||||
|
process_cost: number;
|
||||||
|
total_retail_price: number;
|
||||||
|
total_payable_price: number;
|
||||||
|
total_discount: number;
|
||||||
|
coupon_discount: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type OrderItemsType = {
|
||||||
|
_id: string;
|
||||||
|
order_id: number;
|
||||||
|
shop: ShopType;
|
||||||
|
shipmentItems: ShipmentItemType[];
|
||||||
|
shipper: ShipperType;
|
||||||
|
trackCode: string | null;
|
||||||
|
itemsCount: number;
|
||||||
|
totalPaymentPrice: number;
|
||||||
|
totalRetailPrice: number;
|
||||||
|
totalSellingPrice: number;
|
||||||
|
totalShipmentCost: number;
|
||||||
|
postingDate: string | null;
|
||||||
|
postingReceipt: string | null;
|
||||||
|
status: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ShipmentItemType = {
|
||||||
|
_id: string;
|
||||||
|
product: ProductType;
|
||||||
|
variant: VariantType;
|
||||||
|
quantity: number;
|
||||||
|
cancelled_quantity: number;
|
||||||
|
returned_quantity: number;
|
||||||
|
selling_price: number;
|
||||||
|
retail_price: number;
|
||||||
|
discount_percent: number;
|
||||||
|
shipmentCost: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ProductType = {
|
||||||
|
_id: number;
|
||||||
|
title_fa: string;
|
||||||
|
title_en: string;
|
||||||
|
seoTitle: string | null;
|
||||||
|
seoDescription: string | null;
|
||||||
|
source: string;
|
||||||
|
description: string;
|
||||||
|
metaDescription: string;
|
||||||
|
tags: string[];
|
||||||
|
advantages: string[];
|
||||||
|
disAdvantages: string[];
|
||||||
|
imagesUrl: ImagesUrlType;
|
||||||
|
isFake: string;
|
||||||
|
voice: string | null;
|
||||||
|
specifications: SpecificationType[];
|
||||||
|
brand: BrandType;
|
||||||
|
category: CategoryType;
|
||||||
|
variants: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ImagesUrlType = {
|
||||||
|
cover: string;
|
||||||
|
list: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SpecificationType = {
|
||||||
|
title: string;
|
||||||
|
values: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BrandType = {
|
||||||
|
_id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CategoryType = {
|
||||||
|
_id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type VariantType = {
|
||||||
|
_id: string;
|
||||||
|
market_status: string;
|
||||||
|
price: PriceType;
|
||||||
|
stock: number;
|
||||||
|
postingTime: number;
|
||||||
|
isFreeShip: boolean;
|
||||||
|
isWholeSale: boolean;
|
||||||
|
shop: ShopType;
|
||||||
|
saleFormat: SaleFormatType;
|
||||||
|
warranty: number;
|
||||||
|
size?: number;
|
||||||
|
meterage?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PriceType = {
|
||||||
|
order_limit: number;
|
||||||
|
retailPrice: number;
|
||||||
|
selling_price: number;
|
||||||
|
is_specialSale: boolean;
|
||||||
|
discount_percent: number;
|
||||||
|
specialSale_order_limit: number | null;
|
||||||
|
specialSale_quantity: number | null;
|
||||||
|
specialSale_endDate: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SaleFormatType = {
|
||||||
|
wholeSale: unknown[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ShopType = {
|
||||||
|
_id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ShipperType = {
|
||||||
|
_id: number;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
deliveryTime: number;
|
||||||
|
deliveryType: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ShipmentAddressType = {
|
||||||
|
address: string;
|
||||||
|
city: string;
|
||||||
|
province: string;
|
||||||
|
plaque: string;
|
||||||
|
postalCode: string;
|
||||||
|
phone: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CancellationCategoryType = {
|
||||||
|
_id: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
status: string;
|
||||||
|
deleted: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ReturnCategoryType = {
|
||||||
|
_id: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
status: string;
|
||||||
|
deleted: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
// تایپهای صفحهبندی
|
||||||
|
export type PagerType = {
|
||||||
|
page: number;
|
||||||
|
limit: number;
|
||||||
|
totalItems: number;
|
||||||
|
totalPages: number;
|
||||||
|
prevPage: boolean;
|
||||||
|
nextPage: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type OrdersResponseType = {
|
||||||
|
status: number;
|
||||||
|
success: boolean;
|
||||||
|
results: {
|
||||||
|
orders: OrderType[];
|
||||||
|
pager: PagerType;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CategoriesResponseType = {
|
||||||
|
status: number;
|
||||||
|
success: boolean;
|
||||||
|
results: {
|
||||||
|
categories: CancellationCategoryType[] | ReturnCategoryType[];
|
||||||
|
pager: PagerType;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CreateCategoryType = {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// تایپهای مربوط به سفارشات بومی
|
||||||
|
export type PriceRangeType = {
|
||||||
|
minPrice: number;
|
||||||
|
maxPrice: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UserType = {
|
||||||
|
fullName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NativeOrderType = {
|
||||||
|
_id: number;
|
||||||
|
user: UserType;
|
||||||
|
payment: PaymentType;
|
||||||
|
orderItems: OrderItemsType;
|
||||||
|
shipmentAddress: ShipmentAddressType;
|
||||||
|
orderStatus: string;
|
||||||
|
createdAt: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NativeOrdersResponseType = {
|
||||||
|
status: number;
|
||||||
|
success: boolean;
|
||||||
|
results: {
|
||||||
|
pager: PagerType;
|
||||||
|
orders: NativeOrderType[];
|
||||||
|
priceRange: PriceRangeType;
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -19,6 +19,10 @@ import BrandList from '@/pages/brand/List'
|
|||||||
import BrandCreate from '@/pages/brand/Create'
|
import BrandCreate from '@/pages/brand/Create'
|
||||||
import WarrantyList from '@/pages/warranty/List'
|
import WarrantyList from '@/pages/warranty/List'
|
||||||
import CreateWarranty from '@/pages/warranty/Create'
|
import CreateWarranty from '@/pages/warranty/Create'
|
||||||
|
import Native from '@/pages/orders/Native'
|
||||||
|
import OrdersSeller from '@/pages/orders/Seller'
|
||||||
|
import CancellationCategories from '@/pages/orders/CancellationCategories'
|
||||||
|
import ReturnCategories from '@/pages/orders/ReturnCategories'
|
||||||
|
|
||||||
const MainRouter: FC = () => {
|
const MainRouter: FC = () => {
|
||||||
|
|
||||||
@@ -50,6 +54,13 @@ const MainRouter: FC = () => {
|
|||||||
<Route path={Pages.products.brands.create} element={<BrandCreate />} />
|
<Route path={Pages.products.brands.create} element={<BrandCreate />} />
|
||||||
<Route path={Pages.products.warranty.list} element={<WarrantyList />} />
|
<Route path={Pages.products.warranty.list} element={<WarrantyList />} />
|
||||||
<Route path={Pages.products.warranty.create} element={<CreateWarranty />} />
|
<Route path={Pages.products.warranty.create} element={<CreateWarranty />} />
|
||||||
|
<Route path={Pages.orders.native} element={<Native />} />
|
||||||
|
<Route path={Pages.orders.sellers} element={<OrdersSeller />} />
|
||||||
|
<Route path={Pages.orders.completed} element={<Native />} />
|
||||||
|
<Route path={Pages.orders.cancelled} element={<Native />} />
|
||||||
|
<Route path={Pages.orders.pending} element={<Native />} />
|
||||||
|
<Route path={Pages.orders.cancellationCategories} element={<CancellationCategories />} />
|
||||||
|
<Route path={Pages.orders.returnCategories} element={<ReturnCategories />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+15
-10
@@ -37,7 +37,7 @@ const SideBar: FC = () => {
|
|||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
|
|
||||||
const isActive = (name: string) => {
|
const isActive = (name: string) => {
|
||||||
return location.pathname.includes(name)
|
return window.location.href.includes(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -389,7 +389,7 @@ const ProductsSubMenu: FC = () => {
|
|||||||
|
|
||||||
const OrdersSubMenu: FC = () => {
|
const OrdersSubMenu: FC = () => {
|
||||||
const isActive = (name: string) => {
|
const isActive = (name: string) => {
|
||||||
return location.pathname.includes(name)
|
return window.location.href.includes(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -408,28 +408,33 @@ const OrdersSubMenu: FC = () => {
|
|||||||
<div className='flex flex-col mt-10 gap-4'>
|
<div className='flex flex-col mt-10 gap-4'>
|
||||||
<SubMenuItem
|
<SubMenuItem
|
||||||
title={'لیست سفارشات (فروشندگان)'}
|
title={'لیست سفارشات (فروشندگان)'}
|
||||||
isActive={isActive('sellers')}
|
isActive={isActive('/seller')}
|
||||||
link="/orders/sellers"
|
link={Pages.orders.sellers}
|
||||||
/>
|
/>
|
||||||
<SubMenuItem
|
<SubMenuItem
|
||||||
title={'لیست سفارشات (مدیر)'}
|
title={'لیست سفارشات (مدیر)'}
|
||||||
isActive={isActive('admin')}
|
isActive={isActive('/native')}
|
||||||
link="/orders/admin"
|
link={Pages.orders.admin}
|
||||||
/>
|
/>
|
||||||
<SubMenuItem
|
<SubMenuItem
|
||||||
title={'سفارشات کنسل شده'}
|
title={'سفارشات کنسل شده'}
|
||||||
isActive={isActive('cancelled')}
|
isActive={isActive('Cancelled')}
|
||||||
link="/orders/cancelled"
|
link={Pages.orders.cancelled}
|
||||||
|
/>
|
||||||
|
<SubMenuItem
|
||||||
|
title={'سفارشات تکمیل شده'}
|
||||||
|
isActive={isActive('Completed')}
|
||||||
|
link={Pages.orders.completed}
|
||||||
/>
|
/>
|
||||||
<SubMenuItem
|
<SubMenuItem
|
||||||
title={'دسته بندی کنسلی ها'}
|
title={'دسته بندی کنسلی ها'}
|
||||||
isActive={isActive('cancellation-categories')}
|
isActive={isActive('cancellation-categories')}
|
||||||
link="/orders/cancellation-categories"
|
link={Pages.orders.cancellationCategories}
|
||||||
/>
|
/>
|
||||||
<SubMenuItem
|
<SubMenuItem
|
||||||
title={'دسته بندی مرجوعی ها'}
|
title={'دسته بندی مرجوعی ها'}
|
||||||
isActive={isActive('return-categories')}
|
isActive={isActive('return-categories')}
|
||||||
link="/orders/return-categories"
|
link={Pages.orders.returnCategories}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user