diff --git a/src/pages/order/OrderDetail.tsx b/src/pages/order/OrderDetail.tsx
index 8c03892..119aaf1 100644
--- a/src/pages/order/OrderDetail.tsx
+++ b/src/pages/order/OrderDetail.tsx
@@ -1,21 +1,42 @@
import { type FC } from 'react'
import { Link, useParams } from 'react-router-dom'
import { 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 { useGetOrderDetails } from './hooks/useOrderData'
+import { extractErrorMessage } from '@/config/func'
+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'
const OrderDetail: FC = () => {
const { id } = useParams()
const { data, refetch, isFetching, isPending } = useGetOrderDetails(id!)
+ const { mutate: updateOrderStatus, isPending: isUpdatingStatus } =
+ useUpdateOrderStatus()
const order = data?.data as OrderDetailDataType | undefined
+ const handleUpdateStatus = (status: OrderStatusEnum) => {
+ if (!id) return
+ updateOrderStatus(
+ { orderId: id, status },
+ {
+ onSuccess: () => {
+ refetch()
+ toast.success('وضعیت سفارش با موفقیت بهروزرسانی شد')
+ },
+ onError: (error) => {
+ toast.error(extractErrorMessage(error))
+ },
+ },
+ )
+ }
+
if (isPending) {
return (
@@ -75,7 +96,11 @@ const OrderDetail: FC = () => {
diff --git a/src/pages/order/components/OrderDetailSidebar.tsx b/src/pages/order/components/OrderDetailSidebar.tsx
index a508e7a..d1b0f92 100644
--- a/src/pages/order/components/OrderDetailSidebar.tsx
+++ b/src/pages/order/components/OrderDetailSidebar.tsx
@@ -1,6 +1,6 @@
-import { type FC } from 'react'
+import { type FC, useState } from 'react'
import { Link } from 'react-router-dom'
-import { Call, Edit2, Location, Paperclip2, Profile2User, User } from 'iconsax-react'
+import { Call, Edit2, Location, Paperclip2, Profile2User, Receipt21, User } from 'iconsax-react'
import { clx } from '@/helpers/utils'
import { getFileNameAndExtensionFromUrl } from '@/config/func'
import { Paths } from '@/config/Paths'
@@ -14,10 +14,14 @@ import {
getOrderStatusBadgeClass,
getOrderStatusLabel,
} from '../constants/orderStatus'
+import { OrderStatusEnum } from '../enum/OrderEnum'
import type { OrderDetailDataType } from '../types/Types'
+import OrderStatusModal from './OrderStatusModal'
type Props = {
order?: OrderDetailDataType
+ onUpdateStatus?: (status: OrderStatusEnum) => void
+ isUpdatingStatus?: boolean
}
type InfoRowProps = {
@@ -72,10 +76,24 @@ const PersonCard: FC<{
)
-const OrderDetailSidebar: FC = ({ order }) => {
+const OrderDetailSidebar: FC = ({
+ order,
+ onUpdateStatus,
+ isUpdatingStatus,
+}) => {
const attachments = (order?.attachments ?? [])
.map(getAttachmentUrl)
.filter((url): url is string => Boolean(url))
+ const [isStatusModalOpen, setIsStatusModalOpen] = useState(false)
+ const [selectedStatus, setSelectedStatus] = useState(
+ (order?.status as OrderStatusEnum) ?? OrderStatusEnum.CREATED,
+ )
+
+ const handleOpenStatusModal = () => {
+ if (!order?.status) return
+ setSelectedStatus(order.status as OrderStatusEnum)
+ setIsStatusModalOpen(true)
+ }
return (
@@ -98,14 +116,24 @@ const OrderDetailSidebar: FC
= ({ order }) => {
)}
{order?.status && (
-
- {getOrderStatusLabel(order.status)}
-
+ <>
+
+
+ {getOrderStatusLabel(order.status)}
+
+ >
)}
@@ -191,6 +219,18 @@ const OrderDetailSidebar: FC = ({ order }) => {
)}
+
+ setIsStatusModalOpen(false)}
+ initialStatus={selectedStatus}
+ inputName={`order-detail-status-${order?.id ?? 'unknown'}`}
+ isLoading={isUpdatingStatus}
+ onSubmit={(status) => {
+ setSelectedStatus(status)
+ onUpdateStatus?.(status)
+ }}
+ />
)
}
diff --git a/src/pages/order/components/OrderListActions.tsx b/src/pages/order/components/OrderListActions.tsx
index 71ba345..0556f25 100644
--- a/src/pages/order/components/OrderListActions.tsx
+++ b/src/pages/order/components/OrderListActions.tsx
@@ -1,15 +1,12 @@
-import { type FC, useMemo, useState } from "react";
+import { type FC, useState } from "react";
import { Link } from "react-router-dom";
import { DocumentText, Edit2, Eye, Printer, Receipt21 } from "iconsax-react";
import TrashWithConfrim from "@/components/TrashWithConfrim";
-import DefaulModal from "@/components/DefaulModal";
-import Select from "@/components/Select";
-import Button from "@/components/Button";
import { Paths } from "@/config/Paths";
import { getOrderInvoiceItemRef } from "../utils/orderListUtils";
import type { OrderListItemType } from "../types/Types";
import { OrderStatusEnum } from "../enum/OrderEnum";
-import { getOrderStatusLabel } from "../constants/orderStatus";
+import OrderStatusModal from "./OrderStatusModal";
type Props = {
item: OrderListItemType;
@@ -31,25 +28,12 @@ const OrderListActions: FC = ({
item.status as OrderStatusEnum,
);
const invoiceRef = getOrderInvoiceItemRef(item);
- const statusOptions = useMemo(
- () =>
- Object.values(OrderStatusEnum).map((status) => ({
- value: status,
- label: getOrderStatusLabel(status),
- })),
- [],
- );
const handleOpenStatusModal = () => {
setSelectedStatus(item.status as OrderStatusEnum);
setIsStatusModalOpen(true);
};
- const handleSubmitStatus = () => {
- onUpdateStatus(item.id, selectedStatus);
- setIsStatusModalOpen(false);
- };
-
return (
@@ -79,9 +63,9 @@ const OrderListActions: FC
= ({
type="button"
title="تغییر وضعیت سفارش"
onClick={handleOpenStatusModal}
- className="inline-flex"
+ className="inline-flex items-center gap-1 rounded-full px-1 py-1 text-xs font-medium text-[#0037FF] "
>
-
+
= ({
colorIcon="red"
/>
- setIsStatusModalOpen(false)}
- title_header="تغییر وضعیت سفارش"
- isHeader
- >
-
-
-
+ initialStatus={selectedStatus}
+ inputName={`order-status-${item.id}`}
+ isLoading={isUpdatingStatus}
+ onSubmit={(status) => {
+ setSelectedStatus(status);
+ onUpdateStatus(item.id, status);
+ }}
+ />
);
};
diff --git a/src/pages/order/components/OrderStatusModal.tsx b/src/pages/order/components/OrderStatusModal.tsx
new file mode 100644
index 0000000..657962f
--- /dev/null
+++ b/src/pages/order/components/OrderStatusModal.tsx
@@ -0,0 +1,78 @@
+import { type FC, useEffect, useMemo, useState } from "react";
+import DefaulModal from "@/components/DefaulModal";
+import Button from "@/components/Button";
+import { getOrderStatusLabel, orderStatusCategories } from "../constants/orderStatus";
+import { OrderStatusEnum } from "../enum/OrderEnum";
+
+type Props = {
+ open: boolean;
+ close: () => void;
+ initialStatus: OrderStatusEnum;
+ inputName: string;
+ isLoading?: boolean;
+ onSubmit: (status: OrderStatusEnum) => void;
+};
+
+const OrderStatusModal: FC = ({
+ open,
+ close,
+ initialStatus,
+ inputName,
+ isLoading,
+ onSubmit,
+}) => {
+ const [selectedStatus, setSelectedStatus] = useState(initialStatus);
+ const categorizedStatuses = useMemo(() => orderStatusCategories, []);
+
+ useEffect(() => {
+ if (open) {
+ setSelectedStatus(initialStatus);
+ }
+ }, [initialStatus, open]);
+
+ const handleSubmitStatus = () => {
+ onSubmit(selectedStatus);
+ close();
+ };
+
+ return (
+
+
+
+ {categorizedStatuses.map((category) => (
+
+
{category.label}
+
+ {category.statuses.map((status) => (
+
+ ))}
+
+
+ ))}
+
+
+
+
+
+
+
+ );
+};
+
+export default OrderStatusModal;
diff --git a/src/pages/order/constants/orderStatus.ts b/src/pages/order/constants/orderStatus.ts
index 5019280..0ff7398 100644
--- a/src/pages/order/constants/orderStatus.ts
+++ b/src/pages/order/constants/orderStatus.ts
@@ -29,7 +29,6 @@ export const orderListTabs = [
export const orderStatusLabels: Record = {
[OrderStatusEnum.CREATED]: 'ایجاد شده',
[OrderStatusEnum.INVOICED]: 'فاکتور شده',
- [OrderStatusEnum.WAITING_to_CONFIRM_INVOICE]: 'در انتظار تایید فاکتور',
[OrderStatusEnum.DESIGN_INITIATED]: 'شروع طراحی',
[OrderStatusEnum.DESIGN_FINISHED]: 'طراحی تمام شده',
[OrderStatusEnum.DESIGN_REVISION]: 'بازنگری طراحی',
@@ -47,7 +46,6 @@ export const orderStatusLabels: Record = {
export const orderStatusBadgeClass: Record = {
[OrderStatusEnum.CREATED]: 'bg-blue-100 text-blue-800',
[OrderStatusEnum.INVOICED]: 'bg-green-100 text-green-800',
- [OrderStatusEnum.WAITING_to_CONFIRM_INVOICE]: 'bg-amber-100 text-amber-800',
[OrderStatusEnum.DESIGN_INITIATED]: 'bg-blue-100 text-blue-800',
[OrderStatusEnum.DESIGN_FINISHED]: 'bg-green-100 text-green-800',
[OrderStatusEnum.DESIGN_REVISION]: 'bg-amber-100 text-amber-800',
@@ -62,6 +60,34 @@ export const orderStatusBadgeClass: Record = {
[OrderStatusEnum.CANCELED]: 'bg-red-100 text-red-800',
}
+export const orderStatusCategories: {
+ key: TabOrderListEnum
+ label: string
+ statuses: OrderStatusEnum[]
+}[] = [
+ {
+ key: TabOrderListEnum.IN_PROGRESS,
+ label: 'جاری',
+ statuses: orderListTabStatuses[TabOrderListEnum.IN_PROGRESS],
+ },
+
+ {
+ key: TabOrderListEnum.FINISHED,
+ label: 'پایان یافته',
+ statuses: orderListTabStatuses[TabOrderListEnum.FINISHED],
+ },
+ {
+ key: TabOrderListEnum.CANCELED,
+ label: 'لغو شده',
+ statuses: orderListTabStatuses[TabOrderListEnum.CANCELED],
+ },
+ {
+ key: TabOrderListEnum.INVOICED,
+ label: 'فاکتور شده',
+ statuses: orderListTabStatuses[TabOrderListEnum.INVOICED],
+ },
+]
+
export const getOrderStatusLabel = (status: string) =>
orderStatusLabels[status as OrderStatusEnum] ?? status
diff --git a/src/pages/order/enum/OrderEnum.ts b/src/pages/order/enum/OrderEnum.ts
index ed4bd37..1cec631 100644
--- a/src/pages/order/enum/OrderEnum.ts
+++ b/src/pages/order/enum/OrderEnum.ts
@@ -9,7 +9,6 @@ export enum OrderStatusEnum {
CREATED = "created",
INVOICED = "invoiced",
- WAITING_to_CONFIRM_INVOICE = "waiting_to_confirm_invoice",
DESIGN_INITIATED = "design_initiated",
DESIGN_FINISHED = "design_finished",