update status
deploy to danak / build_and_deploy (push) Has been cancelled

This commit is contained in:
2026-07-08 19:40:44 +03:30
parent 311f7f55e5
commit 9684b78b9f
5 changed files with 143 additions and 6 deletions
+34 -4
View File
@@ -15,13 +15,17 @@ import DesignerSearch from "../designer/DesignerSearch";
import CategoriesSelect from "../product/components/CategoriesSelect"; import CategoriesSelect from "../product/components/CategoriesSelect";
import { orderListTabs } from "./constants/orderStatus"; import { orderListTabs } from "./constants/orderStatus";
import { getOrderListColumns } from "./components/OrderListColumns"; import { getOrderListColumns } from "./components/OrderListColumns";
import { useDeleteOrder, useGetOrders } from "./hooks/useOrderData"; import {
useDeleteOrder,
useGetOrders,
useUpdateOrderStatus,
} from "./hooks/useOrderData";
import { import {
ORDER_LIST_FILTER_FIELDS, ORDER_LIST_FILTER_FIELDS,
useOrderListParams, useOrderListParams,
} from "./hooks/useOrderListParams"; } from "./hooks/useOrderListParams";
import type { OrderListItemType } from "./types/Types"; import type { OrderListItemType } from "./types/Types";
import { TabOrderListEnum } from "./enum/OrderEnum"; import { OrderStatusEnum, TabOrderListEnum } from "./enum/OrderEnum";
const countActiveFilters = (params: { const countActiveFilters = (params: {
search?: string; search?: string;
@@ -48,6 +52,8 @@ const OrdersList: FC = () => {
const { data, refetch, isFetching } = useGetOrders(queryParams); const { data, refetch, isFetching } = useGetOrders(queryParams);
const { mutate: deleteOrder, isPending: isDeleting } = useDeleteOrder(); const { mutate: deleteOrder, isPending: isDeleting } = useDeleteOrder();
const { mutate: updateOrderStatus, isPending: isUpdatingStatus } =
useUpdateOrderStatus();
const activeFilterCount = useMemo(() => countActiveFilters(params), [params]); const activeFilterCount = useMemo(() => countActiveFilters(params), [params]);
const hasActiveFilters = activeFilterCount > 0; const hasActiveFilters = activeFilterCount > 0;
@@ -66,9 +72,33 @@ const OrdersList: FC = () => {
[deleteOrder, refetch], [deleteOrder, refetch],
); );
const handleUpdateStatus = useCallback(
(id: string, status: OrderStatusEnum) => {
updateOrderStatus(
{ orderId: id, status },
{
onSuccess: () => {
refetch();
toast.success("وضعیت سفارش با موفقیت به‌روزرسانی شد");
},
onError: (error) => {
toast.error(extractErrorMessage(error));
},
},
);
},
[refetch, updateOrderStatus],
);
const columns = useMemo( const columns = useMemo(
() => getOrderListColumns({ onDelete: handleDelete, isDeleting }), () =>
[handleDelete, isDeleting], getOrderListColumns({
onDelete: handleDelete,
onUpdateStatus: handleUpdateStatus,
isDeleting,
isUpdatingStatus,
}),
[handleDelete, handleUpdateStatus, isDeleting, isUpdatingStatus],
); );
return ( return (
@@ -1,19 +1,54 @@
import { type FC } from "react"; import { type FC, useMemo, useState } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { DocumentText, Edit2, Eye, Printer, Receipt21 } from "iconsax-react"; import { DocumentText, Edit2, Eye, Printer, Receipt21 } from "iconsax-react";
import TrashWithConfrim from "@/components/TrashWithConfrim"; 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 { Paths } from "@/config/Paths";
import { getOrderInvoiceItemRef } from "../utils/orderListUtils"; import { getOrderInvoiceItemRef } from "../utils/orderListUtils";
import type { OrderListItemType } from "../types/Types"; import type { OrderListItemType } from "../types/Types";
import { OrderStatusEnum } from "../enum/OrderEnum";
import { getOrderStatusLabel } from "../constants/orderStatus";
type Props = { type Props = {
item: OrderListItemType; item: OrderListItemType;
onDelete: (id: string) => void; onDelete: (id: string) => void;
onUpdateStatus: (id: string, status: OrderStatusEnum) => void;
isDeleting?: boolean; isDeleting?: boolean;
isUpdatingStatus?: boolean;
}; };
const OrderListActions: FC<Props> = ({ item, onDelete, isDeleting }) => { const OrderListActions: FC<Props> = ({
item,
onDelete,
onUpdateStatus,
isDeleting,
isUpdatingStatus,
}) => {
const [isStatusModalOpen, setIsStatusModalOpen] = useState(false);
const [selectedStatus, setSelectedStatus] = useState<OrderStatusEnum>(
item.status as OrderStatusEnum,
);
const invoiceRef = getOrderInvoiceItemRef(item); 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 ( return (
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@@ -40,11 +75,48 @@ const OrderListActions: FC<Props> = ({ item, onDelete, isDeleting }) => {
<Edit2 size={20} color="#0037FF" /> <Edit2 size={20} color="#0037FF" />
</Link> </Link>
<button
type="button"
title="تغییر وضعیت سفارش"
onClick={handleOpenStatusModal}
className="inline-flex"
>
<Receipt21 size={20} color="#8C90A3" />
</button>
<TrashWithConfrim <TrashWithConfrim
onDelete={() => onDelete(item.id)} onDelete={() => onDelete(item.id)}
isloading={isDeleting} isloading={isDeleting}
colorIcon="red" colorIcon="red"
/> />
<DefaulModal
open={isStatusModalOpen}
close={() => setIsStatusModalOpen(false)}
title_header="تغییر وضعیت سفارش"
isHeader
>
<div className="mt-6 space-y-6">
<Select
label="وضعیت سفارش"
value={selectedStatus}
onChange={(e) => setSelectedStatus(e.target.value as OrderStatusEnum)}
items={statusOptions}
/>
<div className="flex justify-center gap-3">
<Button
label="ثبت"
onClick={handleSubmitStatus}
isLoading={isUpdatingStatus}
/>
<Button
label="لغو"
className="border border-primary bg-transparent text-black"
onClick={() => setIsStatusModalOpen(false)}
/>
</div>
</div>
</DefaulModal>
</div> </div>
); );
}; };
@@ -6,6 +6,7 @@ import {
} from "../constants/orderStatus"; } from "../constants/orderStatus";
import OrderListActions from "./OrderListActions"; import OrderListActions from "./OrderListActions";
import type { OrderListItemType } from "../types/Types"; import type { OrderListItemType } from "../types/Types";
import type { OrderStatusEnum } from "../enum/OrderEnum";
const getCustomerName = (item: OrderListItemType) => { const getCustomerName = (item: OrderListItemType) => {
const user = item.user; const user = item.user;
@@ -27,12 +28,16 @@ const getDesignerName = (item: OrderListItemType) => {
type OrderListColumnsOptions = { type OrderListColumnsOptions = {
onDelete: (id: string) => void; onDelete: (id: string) => void;
onUpdateStatus: (id: string, status: OrderStatusEnum) => void;
isDeleting?: boolean; isDeleting?: boolean;
isUpdatingStatus?: boolean;
}; };
export const getOrderListColumns = ({ export const getOrderListColumns = ({
onDelete, onDelete,
onUpdateStatus,
isDeleting, isDeleting,
isUpdatingStatus,
}: OrderListColumnsOptions): ColumnType<OrderListItemType>[] => [ }: OrderListColumnsOptions): ColumnType<OrderListItemType>[] => [
{ {
key: "orderNumber", key: "orderNumber",
@@ -85,7 +90,9 @@ export const getOrderListColumns = ({
<OrderListActions <OrderListActions
item={item} item={item}
onDelete={onDelete} onDelete={onDelete}
onUpdateStatus={onUpdateStatus}
isDeleting={isDeleting} isDeleting={isDeleting}
isUpdatingStatus={isUpdatingStatus}
/> />
), ),
}, },
+18
View File
@@ -5,6 +5,7 @@ import type {
OrderPrintFormType, OrderPrintFormType,
UpdateOrderType, UpdateOrderType,
} from "../types/Types"; } from "../types/Types";
import type { OrderStatusEnum } from "../enum/OrderEnum";
export const useGetOrders = (params?: api.GetOrdersParams) => { export const useGetOrders = (params?: api.GetOrdersParams) => {
return useQuery({ return useQuery({
@@ -132,3 +133,20 @@ export const useDeleteOrder = () => {
}, },
}); });
}; };
export const useUpdateOrderStatus = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({
orderId,
status,
}: {
orderId: string;
status: OrderStatusEnum;
}) => api.updateOrderStatus(orderId, status),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["orders"] });
},
});
};
+10
View File
@@ -148,3 +148,13 @@ export const deleteOrder = async (orderId: string) => {
const { data } = await axios.delete(`/admin/orders/${orderId}`); const { data } = await axios.delete(`/admin/orders/${orderId}`);
return data; return data;
}; };
export const updateOrderStatus = async (
orderId: string,
status: OrderStatusEnum,
) => {
const { data } = await axios.post(`/admin/orders/${orderId}/status`, {
status,
});
return data;
};