215 lines
9.5 KiB
TypeScript
215 lines
9.5 KiB
TypeScript
'use client';
|
||
|
||
import { useParams, useRouter } from 'next/navigation';
|
||
import React from 'react';
|
||
import Button from '@/components/button/PrimaryButton';
|
||
import { Skeleton } from '@/components/ui/skeleton';
|
||
import { Clock } from 'iconsax-react';
|
||
import clsx from 'clsx';
|
||
import useToggle from '@/hooks/helpers/useToggle';
|
||
import Prompt from '@/components/utils/Prompt';
|
||
import { useCancelOrder, useGetOrderDetail } from '../../checkout/hooks/useOrderData';
|
||
import ordersTranslations from '@/locales/fa/orders.json';
|
||
import { toast } from '@/components/Toast';
|
||
import { extractErrorMessage } from '@/lib/func';
|
||
import { useQueryClient } from '@tanstack/react-query';
|
||
|
||
const getDeliveryMethodTitle = (method: string) => {
|
||
switch (method) {
|
||
case 'deliveryCourier':
|
||
return 'ارسال توسط پیک';
|
||
case 'deliveryCar':
|
||
return 'تحویل به خودرو';
|
||
case 'pickup':
|
||
return 'تحویل حضوری';
|
||
case 'dineIn':
|
||
return 'سرو در رستوران';
|
||
default:
|
||
return 'روش ارسال';
|
||
}
|
||
};
|
||
|
||
// const getStatusPercentage = (status: string) => {
|
||
// switch (status) {
|
||
// case 'new':
|
||
// case 'pendingPayment':
|
||
// return 0;
|
||
// case 'paid':
|
||
// case 'confirmed':
|
||
// return 20;
|
||
// case 'preparing':
|
||
// return 40;
|
||
// case 'ready':
|
||
// return 60;
|
||
// case 'shipped':
|
||
// case 'delivering':
|
||
// return 80;
|
||
// case 'completed':
|
||
// case 'delivered':
|
||
// return 100;
|
||
// default:
|
||
// return 0;
|
||
// }
|
||
// };
|
||
|
||
const getStatusText = (status: string): string => {
|
||
const statusKey = status as keyof typeof ordersTranslations.status;
|
||
return ordersTranslations.status[statusKey] || 'نامشخص';
|
||
};
|
||
|
||
const formatDate = (dateString: string): string => {
|
||
const date = new Date(dateString);
|
||
return date.toLocaleDateString('fa-IR', {
|
||
year: 'numeric',
|
||
month: 'long',
|
||
day: 'numeric'
|
||
});
|
||
};
|
||
|
||
// const formatTime = (dateString: string): string => {
|
||
// const date = new Date(dateString);
|
||
// return date.toLocaleTimeString('fa-IR', {
|
||
// hour: '2-digit',
|
||
// minute: '2-digit'
|
||
// });
|
||
// };
|
||
|
||
function OrderTrackingPage() {
|
||
const { id, name } = useParams();
|
||
const router = useRouter();
|
||
const queryClient = useQueryClient();
|
||
const { state: cancelModal, toggle: toggleCancelModal } = useToggle();
|
||
const { data: orderDetail, isLoading } = useGetOrderDetail(id as string);
|
||
const { mutate: cancelOrder } = useCancelOrder();
|
||
|
||
const onCancelOrder = (e: React.MouseEvent | null) => {
|
||
if (!e || !id) return;
|
||
|
||
cancelOrder(id as string, {
|
||
onSuccess: () => {
|
||
toggleCancelModal();
|
||
queryClient.invalidateQueries({ queryKey: ['order-detail', id] });
|
||
toast('سفارش با موفقیت لغو شد', 'success');
|
||
},
|
||
onError: (error) => {
|
||
toast(extractErrorMessage(error), 'error');
|
||
}
|
||
});
|
||
};
|
||
|
||
return (
|
||
<div className="fixed inset-0 bg-container flex flex-col">
|
||
<div className='flex-1 overflow-y-auto px-4 py-6'>
|
||
<div className='max-w-2xl mx-auto flex flex-col gap-6'>
|
||
{isLoading ? (
|
||
<>
|
||
<Skeleton className='h-6 w-48 mx-auto' />
|
||
<div className='flex flex-col gap-4'>
|
||
<Skeleton className='h-5 w-full' />
|
||
<Skeleton className='h-5 w-full' />
|
||
<Skeleton className='h-20 w-full' />
|
||
<Skeleton className='h-5 w-full' />
|
||
</div>
|
||
</>
|
||
) : orderDetail?.data ? (
|
||
<>
|
||
<h1 className='text-lg font-semibold text-center'>
|
||
{getDeliveryMethodTitle(orderDetail.data.deliveryMethod.method)}
|
||
</h1>
|
||
|
||
<div className='flex flex-col'>
|
||
<div className='flex justify-between items-center h-16 border-b border-border'>
|
||
<span className='text-sm text-muted-foreground flex items-center gap-2'>
|
||
<Clock className='stroke-current' size={16} />
|
||
زمان سفارش
|
||
</span>
|
||
<div className='flex items-end gap-0.5'>
|
||
<span className='text-sm font-semibold'>{formatDate(orderDetail.data.createdAt)}</span>
|
||
{/* <span className='text-xs text-muted-foreground'>{formatTime(orderDetail.data.createdAt)}</span> */}
|
||
</div>
|
||
</div>
|
||
<div className='flex justify-between items-center h-16 border-b border-border'>
|
||
<span className='text-sm text-muted-foreground'>نوع ارسال</span>
|
||
<span className='text-sm font-semibold'>{orderDetail.data?.deliveryMethod?.description}</span>
|
||
</div>
|
||
<div className='flex justify-between items-center h-16 border-b border-border'>
|
||
<span className='text-sm text-muted-foreground'>شماره سفارش</span>
|
||
<span className='text-sm font-semibold'>#{orderDetail.data.orderNumber}</span>
|
||
</div>
|
||
<div className='flex justify-between items-center h-16 border-b border-border'>
|
||
<span className='text-sm text-muted-foreground'>وضعیت سفارش</span>
|
||
<span className='text-sm font-semibold'>{getStatusText(orderDetail.data.status)}</span>
|
||
</div>
|
||
|
||
{orderDetail.data.tableNumber && (
|
||
<div className='flex justify-between items-center h-16 border-b border-border'>
|
||
<span className='text-sm text-muted-foreground'>شماره میز</span>
|
||
<span className='text-sm font-semibold'>#{orderDetail.data.tableNumber}</span>
|
||
</div>
|
||
)}
|
||
|
||
{orderDetail.data.userAddress && (
|
||
<div className='py-3 border-b border-border'>
|
||
<div className='text-sm text-muted-foreground mb-1'>آدرس تحویل</div>
|
||
<div className='text-sm'>{orderDetail.data.userAddress.address}</div>
|
||
</div>
|
||
)}
|
||
|
||
<div className='flex justify-between items-center py-4 border-t border-border'>
|
||
<span className='text-sm font-medium'>مجموع سفارش</span>
|
||
<span className='text-sm font-bold text-primary'>
|
||
{orderDetail.data.total.toLocaleString('fa-IR')} تومان
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</>
|
||
) : (
|
||
<div className='text-center text-muted-foreground py-12'>
|
||
اطلاعات سفارش یافت نشد
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
|
||
<div className='p-4 border-t border-border bg-container'>
|
||
<div className='max-w-2xl mx-auto grid grid-cols-2 gap-4'>
|
||
<Button
|
||
onClick={() => router.push(`/${name}`)}
|
||
type='button'>
|
||
بازگشت به منو
|
||
</Button>
|
||
<Button
|
||
type='submit'
|
||
onClick={toggleCancelModal}
|
||
className='bg-disabled! text-foreground!'
|
||
disabled={
|
||
orderDetail?.data?.status === 'cancelled' ||
|
||
orderDetail?.data?.status === 'delivered' ||
|
||
orderDetail?.data?.status === 'delivering'
|
||
}
|
||
>
|
||
لغو سفارش
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
|
||
<div className={clsx(
|
||
'fixed inset-0 z-1001',
|
||
!cancelModal && 'pointer-events-none'
|
||
)}>
|
||
<Prompt
|
||
title={'لغو سفارش'}
|
||
description={'آیا از درخواست خود اطمینان دارید؟'}
|
||
textConfirm={'بله'}
|
||
textCancel={'منصرف شدم'}
|
||
onConfirm={onCancelOrder}
|
||
visible={cancelModal}
|
||
onClick={toggleCancelModal}
|
||
onCancel={toggleCancelModal}
|
||
/>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default OrderTrackingPage; |