This commit is contained in:
+192
-140
@@ -5,6 +5,9 @@ import {
|
||||
useChangeOrderStatus,
|
||||
useRefundPayment,
|
||||
useUpdateOrderFees,
|
||||
useAddOrderItem,
|
||||
useUpdateOrderItemQuantity,
|
||||
useRemoveOrderItem,
|
||||
} from './hooks/useOrderData'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { formatFaNumber } from '@/helpers/func'
|
||||
@@ -14,10 +17,12 @@ import { DeliveryMethodEnum } from '@/pages/shipmentMethod/enum/Enum'
|
||||
import ModalConfrim from '@/components/ModalConfrim'
|
||||
import CustomerInfo from './components/CustomerInfo'
|
||||
import OrderItemsDetails from './components/OrderItemsDetails'
|
||||
import PaymentsList from './components/PaymentsList'
|
||||
import PaymentInfo from './components/PaymentInfo'
|
||||
import PaymentVerificationBox from './components/PaymentVerificationBox'
|
||||
import OrderActions from './components/OrderActions'
|
||||
import UpdateOrderFeesModal from './components/UpdateOrderFeesModal'
|
||||
import AddOrderItemModal from './components/AddOrderItemModal'
|
||||
import RefundPaymentModal from './components/RefundPaymentModal'
|
||||
import { toast } from 'react-toastify'
|
||||
import { extractErrorMessage } from '@/config/func'
|
||||
import { printOrderReceipt } from './print/orderReceiptPrint'
|
||||
@@ -30,53 +35,32 @@ const OrderDetails: FC = () => {
|
||||
const { mutate: changeOrderStatus, isPending: isChangingStatus } = useChangeOrderStatus()
|
||||
const { mutate: refundPayment, isPending: isRefunding } = useRefundPayment()
|
||||
const { mutate: updateOrderFees, isPending: isUpdatingFees } = useUpdateOrderFees()
|
||||
const { mutate: addOrderItem, isPending: isAddingItem } = useAddOrderItem()
|
||||
const { mutate: updateOrderItemQuantity, isPending: isUpdatingItemQuantity } = useUpdateOrderItemQuantity()
|
||||
const { mutate: removeOrderItem, isPending: isRemovingItem } = useRemoveOrderItem()
|
||||
|
||||
const [showCancelModal, setShowCancelModal] = useState(false)
|
||||
const [showRefundModal, setShowRefundModal] = useState(false)
|
||||
const [refundModal, setRefundModal] = useState<{ defaultAmount: number; maxAmount: number } | null>(null)
|
||||
const [showEditFeesModal, setShowEditFeesModal] = useState(false)
|
||||
const [showAddItemModal, setShowAddItemModal] = useState(false)
|
||||
const [itemIdToRemove, setItemIdToRemove] = useState<string | null>(null)
|
||||
const [verifyingPaymentId, setVerifyingPaymentId] = useState<string | null>(null)
|
||||
|
||||
const order = orderData?.data
|
||||
|
||||
const getStatusColor = (status: string): string => {
|
||||
const colorMap: Record<string, string> = {
|
||||
'pendingPayment': '#FFEECC',
|
||||
'paid': '#E3F2FD',
|
||||
'preparing': '#FFF3E0',
|
||||
'ready': '#E3F2FD',
|
||||
'shipped': '#E3F2FD',
|
||||
'completed': '#E8F5E9',
|
||||
'canceled': '#FFEBEE',
|
||||
pendingPayment: '#FFEECC',
|
||||
paid: '#E3F2FD',
|
||||
preparing: '#FFF3E0',
|
||||
ready: '#E3F2FD',
|
||||
shipped: '#E3F2FD',
|
||||
completed: '#E8F5E9',
|
||||
canceled: '#FFEBEE',
|
||||
}
|
||||
return colorMap[status] || '#FFEECC'
|
||||
}
|
||||
|
||||
const getPaymentStatusColor = (status: string): string => {
|
||||
const colorMap: Record<string, string> = {
|
||||
[PaymentStatusEnum.Paid]: 'bg-green-500',
|
||||
[PaymentStatusEnum.Pending]: 'bg-yellow-500',
|
||||
[PaymentStatusEnum.Failed]: 'bg-red-500',
|
||||
}
|
||||
return colorMap[status] || 'bg-gray-500'
|
||||
}
|
||||
|
||||
const getPaymentStatusTextColor = (status: string): string => {
|
||||
const colorMap: Record<string, string> = {
|
||||
[PaymentStatusEnum.Paid]: 'text-green-500',
|
||||
[PaymentStatusEnum.Pending]: 'text-yellow-500',
|
||||
[PaymentStatusEnum.Failed]: 'text-red-500',
|
||||
}
|
||||
return colorMap[status] || 'text-gray-500'
|
||||
}
|
||||
|
||||
const getPaymentStatusText = (status: string): string => {
|
||||
const textMap: Record<string, string> = {
|
||||
[PaymentStatusEnum.Paid]: 'پرداخت شده',
|
||||
[PaymentStatusEnum.Pending]: 'در انتظار پرداخت',
|
||||
[PaymentStatusEnum.Failed]: 'پرداخت ناموفق',
|
||||
}
|
||||
return textMap[status] || status
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className='mt-5 flex items-center justify-center h-64'>
|
||||
@@ -93,113 +77,113 @@ const OrderDetails: FC = () => {
|
||||
)
|
||||
}
|
||||
|
||||
// منطق نمایش دکمهها
|
||||
const isCashPayment = order.paymentMethod?.method === PaymentMethodEnum.Cash
|
||||
const isCreditCardPayment = order.paymentMethod?.method === PaymentMethodEnum.CreditCard
|
||||
const isPendingPayment = order.status === OrderStatus.NEW
|
||||
const isOrderPaid = order.payments?.some(payment => payment.status === PaymentStatusEnum.Paid)
|
||||
const isOrderPaid = Number(order.paidAmount ?? 0) > 0 || order.payments?.some(
|
||||
(payment) => payment.status === PaymentStatusEnum.Paid
|
||||
)
|
||||
const isPreparing = order.status === OrderStatus.PREPARING
|
||||
const isCanceled = order.status === OrderStatus.CANCELED
|
||||
const isCompleted = order.status === OrderStatus.COMPLETED
|
||||
const isPendingPayment = order.status === OrderStatus.NEW
|
||||
const canEditFees = !isCanceled && !isCompleted
|
||||
const canEditItems = !isCanceled && !isCompleted
|
||||
const isUpdatingItem = isAddingItem || isUpdatingItemQuantity || isRemovingItem
|
||||
const canCompleteOrder = [
|
||||
OrderStatus.DELIVERED_TO_WAITER,
|
||||
OrderStatus.DELIVERED_TO_RECEPTIONIST,
|
||||
OrderStatus.SHIPPED,
|
||||
].includes(order.status as OrderStatus)
|
||||
// بررسی وضعیت پرداخت از payments array یا paymentStatus
|
||||
// ابتدا از paymentStatus استفاده میکنیم، اگر نبود از اولین payment در payments array استفاده میکنیم
|
||||
const paymentStatus = order.paymentStatus || order.payments?.[0]?.status
|
||||
// بررسی وضعیت pending (هم enum و هم string literal)
|
||||
const isPaymentPending = paymentStatus === PaymentStatusEnum.Pending || paymentStatus === 'pending'
|
||||
const isCourierDelivery = order.deliveryMethod?.method === DeliveryMethodEnum.DeliveryCourier
|
||||
const isDineInOrCarDelivery = order.deliveryMethod?.method === DeliveryMethodEnum.DineIn || order.deliveryMethod?.method === DeliveryMethodEnum.DeliveryCar
|
||||
const isDineInOrCarDelivery =
|
||||
order.deliveryMethod?.method === DeliveryMethodEnum.DineIn ||
|
||||
order.deliveryMethod?.method === DeliveryMethodEnum.DeliveryCar
|
||||
const isCustomerPickup = order.deliveryMethod?.method === DeliveryMethodEnum.CustomerPickup
|
||||
|
||||
const payment = order.payments?.[0]
|
||||
const hasPaymentDescription = Boolean(payment?.description)
|
||||
const hasPaymentAttachments = Boolean(payment?.attachments && payment.attachments.length > 0)
|
||||
const showPaymentReceiptBox = isCreditCardPayment && (hasPaymentDescription || hasPaymentAttachments)
|
||||
const showVerifyCashPaymentButton = isCashPayment && isPaymentPending && !isCanceled
|
||||
const showVerifyPaymentButton = (isCashPayment || isCreditCardPayment) && isPaymentPending && !isCanceled
|
||||
const showPaymentVerificationBox = showPaymentReceiptBox || showVerifyCashPaymentButton
|
||||
|
||||
// نمایش دکمه ارسال به آشپزخانه
|
||||
// برای pendingPayment با پرداخت نقدی یا برای paid
|
||||
const showSendToKitchenButton = (isPendingPayment && isCashPayment) || isOrderPaid
|
||||
|
||||
// نمایش دکمه کنسل
|
||||
// همیشه نمایش داده میشود مگر اینکه سفارش قبلاً کنسل شده باشد
|
||||
const showCancelButton = !isCanceled
|
||||
|
||||
const handleVerifyPayment = () => {
|
||||
const paymentId = order.paymentId || order.payments?.[0]?.id
|
||||
if (paymentId) {
|
||||
verifyPayment(paymentId, {
|
||||
onSuccess: () => {
|
||||
// Success handled by query invalidation
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleVerifyPayment = (paymentId: string) => {
|
||||
setVerifyingPaymentId(paymentId)
|
||||
verifyPayment(paymentId, {
|
||||
onSuccess: () => {
|
||||
setVerifyingPaymentId(null)
|
||||
},
|
||||
onError: (error) => {
|
||||
setVerifyingPaymentId(null)
|
||||
toast.error(extractErrorMessage(error))
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const handleSendToKitchen = () => {
|
||||
changeOrderStatus({
|
||||
orderId: order.id,
|
||||
status: OrderStatus.PREPARING
|
||||
}, {
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
changeOrderStatus(
|
||||
{
|
||||
orderId: order.id,
|
||||
status: OrderStatus.PREPARING,
|
||||
},
|
||||
{
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
},
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const handleDeliverToCourier = () => {
|
||||
changeOrderStatus({
|
||||
orderId: order.id,
|
||||
status: OrderStatus.SHIPPED
|
||||
}, {
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
changeOrderStatus(
|
||||
{
|
||||
orderId: order.id,
|
||||
status: OrderStatus.SHIPPED,
|
||||
},
|
||||
{
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
},
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const handleDeliverToWaiter = () => {
|
||||
changeOrderStatus({
|
||||
orderId: order.id,
|
||||
status: OrderStatus.DELIVERED_TO_WAITER
|
||||
}, {
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
changeOrderStatus(
|
||||
{
|
||||
orderId: order.id,
|
||||
status: OrderStatus.DELIVERED_TO_WAITER,
|
||||
},
|
||||
{
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
},
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const handleDeliverToReceptionist = () => {
|
||||
changeOrderStatus({
|
||||
orderId: order.id,
|
||||
status: OrderStatus.DELIVERED_TO_RECEPTIONIST
|
||||
}, {
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
changeOrderStatus(
|
||||
{
|
||||
orderId: order.id,
|
||||
status: OrderStatus.DELIVERED_TO_RECEPTIONIST,
|
||||
},
|
||||
{
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
},
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const handleCancelOrder = (description?: string) => {
|
||||
changeOrderStatus({
|
||||
orderId: order.id,
|
||||
status: OrderStatus.CANCELED,
|
||||
params: description ? { description } : undefined
|
||||
}, {
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
changeOrderStatus(
|
||||
{
|
||||
orderId: order.id,
|
||||
status: OrderStatus.CANCELED,
|
||||
params: description ? { description } : undefined,
|
||||
},
|
||||
{
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
},
|
||||
}
|
||||
})
|
||||
)
|
||||
setShowCancelModal(false)
|
||||
}
|
||||
|
||||
@@ -217,17 +201,22 @@ const OrderDetails: FC = () => {
|
||||
)
|
||||
}
|
||||
|
||||
const handleRefund = (text?: string) => {
|
||||
if (!text) return
|
||||
refundPayment({
|
||||
orderId: order.id,
|
||||
params: { description: text }
|
||||
}, {
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
const handleRefund = (amount: number, description: string) => {
|
||||
refundPayment(
|
||||
{
|
||||
orderId: order.id,
|
||||
params: { amount, description },
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
toast.success('بازگشت وجه با موفقیت انجام شد')
|
||||
setRefundModal(null)
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
},
|
||||
}
|
||||
})
|
||||
setShowRefundModal(false)
|
||||
)
|
||||
}
|
||||
|
||||
const handlePrintOrder = () => {
|
||||
@@ -249,6 +238,48 @@ const OrderDetails: FC = () => {
|
||||
)
|
||||
}
|
||||
|
||||
const handleAddOrderItem = (foodId: string, quantity: number) => {
|
||||
addOrderItem(
|
||||
{ orderId: order.id, params: { foodId, quantity } },
|
||||
{
|
||||
onSuccess: () => {
|
||||
toast.success('آیتم به سفارش اضافه شد')
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const handleUpdateItemQuantity = (itemId: string, quantity: number) => {
|
||||
if (quantity < 1) return
|
||||
updateOrderItemQuantity(
|
||||
{ orderId: order.id, itemId, params: { quantity } },
|
||||
{
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const handleConfirmRemoveItem = () => {
|
||||
if (!itemIdToRemove) return
|
||||
removeOrderItem(
|
||||
{ orderId: order.id, itemId: itemIdToRemove },
|
||||
{
|
||||
onSuccess: () => {
|
||||
toast.success('آیتم از سفارش حذف شد')
|
||||
setItemIdToRemove(null)
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='mt-5'>
|
||||
<div className='flex justify-between items-center'>
|
||||
@@ -260,29 +291,37 @@ const OrderDetails: FC = () => {
|
||||
<div className='flex gap-7 mt-9'>
|
||||
<div className='flex-1 space-y-8'>
|
||||
<CustomerInfo order={order} />
|
||||
<OrderItemsDetails order={order} getStatusColor={getStatusColor} />
|
||||
<OrderItemsDetails
|
||||
order={order}
|
||||
getStatusColor={getStatusColor}
|
||||
canEditItems={canEditItems}
|
||||
isUpdatingItem={isUpdatingItem}
|
||||
onAddItem={() => setShowAddItemModal(true)}
|
||||
onUpdateQuantity={handleUpdateItemQuantity}
|
||||
onRemoveItem={(itemId) => setItemIdToRemove(itemId)}
|
||||
/>
|
||||
<PaymentsList
|
||||
order={order}
|
||||
isVerifyingPayment={isVerifyingPayment}
|
||||
verifyingPaymentId={verifyingPaymentId}
|
||||
onVerifyPayment={handleVerifyPayment}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<PaymentInfo
|
||||
order={order}
|
||||
getPaymentStatusColor={getPaymentStatusColor}
|
||||
getPaymentStatusTextColor={getPaymentStatusTextColor}
|
||||
getPaymentStatusText={getPaymentStatusText}
|
||||
canEditFees={canEditFees}
|
||||
onEditFees={() => setShowEditFeesModal(true)}
|
||||
isRefunding={isRefunding}
|
||||
onRefund={(defaultAmount, maxAmount) =>
|
||||
setRefundModal({ defaultAmount, maxAmount })
|
||||
}
|
||||
/>
|
||||
{showPaymentVerificationBox && (
|
||||
<PaymentVerificationBox
|
||||
order={order}
|
||||
isVerifyingPayment={isVerifyingPayment}
|
||||
onVerifyPayment={handleVerifyPayment}
|
||||
showVerifyButton={showVerifyPaymentButton}
|
||||
/>
|
||||
)}
|
||||
<OrderActions
|
||||
onPrint={handlePrintOrder}
|
||||
showSendToKitchenButton={showSendToKitchenButton}
|
||||
showCancelButton={showCancelButton}
|
||||
showEditFeesButton={canEditFees}
|
||||
isPreparing={isPreparing}
|
||||
isCourierDelivery={isCourierDelivery}
|
||||
isDineInOrCarDelivery={isDineInOrCarDelivery}
|
||||
@@ -296,7 +335,6 @@ const OrderDetails: FC = () => {
|
||||
onDeliverToReceptionist={handleDeliverToReceptionist}
|
||||
onCompleteOrder={handleCompleteOrder}
|
||||
onCancelOrder={() => setShowCancelModal(true)}
|
||||
onEditFees={() => setShowEditFeesModal(true)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -309,7 +347,14 @@ const OrderDetails: FC = () => {
|
||||
onSubmit={handleUpdateOrderFees}
|
||||
/>
|
||||
|
||||
{/* مدال کنسل سفارش */}
|
||||
<AddOrderItemModal
|
||||
isOpen={showAddItemModal}
|
||||
onClose={() => setShowAddItemModal(false)}
|
||||
existingItems={order.items}
|
||||
isLoading={isAddingItem}
|
||||
onAdd={handleAddOrderItem}
|
||||
/>
|
||||
|
||||
<ModalConfrim
|
||||
isOpen={showCancelModal}
|
||||
close={() => setShowCancelModal(false)}
|
||||
@@ -319,17 +364,24 @@ const OrderDetails: FC = () => {
|
||||
isHasDescription
|
||||
/>
|
||||
|
||||
{/* مدال ریفاند */}
|
||||
<RefundPaymentModal
|
||||
isOpen={!!refundModal}
|
||||
onClose={() => setRefundModal(null)}
|
||||
defaultAmount={refundModal?.defaultAmount ?? 0}
|
||||
maxAmount={refundModal?.maxAmount ?? 0}
|
||||
isLoading={isRefunding}
|
||||
onSubmit={handleRefund}
|
||||
/>
|
||||
|
||||
<ModalConfrim
|
||||
isOpen={showRefundModal}
|
||||
close={() => setShowRefundModal(false)}
|
||||
onConfrim={handleRefund}
|
||||
isloading={isRefunding}
|
||||
label='آیا از ریفاند این سفارش مطمئن هستید؟'
|
||||
isHasDescription
|
||||
isOpen={!!itemIdToRemove}
|
||||
close={() => setItemIdToRemove(null)}
|
||||
onConfrim={handleConfirmRemoveItem}
|
||||
isloading={isRemovingItem}
|
||||
label='آیا از حذف این آیتم مطمئن هستید؟'
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default OrderDetails
|
||||
export default OrderDetails
|
||||
|
||||
Reference in New Issue
Block a user