update shipment

This commit is contained in:
hamid zarghami
2025-11-25 09:24:03 +03:30
parent d77e83c08d
commit 2f6a339cee
6 changed files with 213 additions and 5 deletions
+153
View File
@@ -0,0 +1,153 @@
import { type FC, useMemo } from 'react'
import { useFormik } from 'formik'
import * as Yup from 'yup'
import { TickCircle } from 'iconsax-react'
import { toast } from 'react-toastify'
import { useNavigate, useParams } from 'react-router-dom'
import Button from '@/components/Button'
import Input from '@/components/Input'
import Select from '@/components/Select'
import Switch from '@/components/Switch'
import type { CreateShipmentMethodType, ShipmentMethod } from './types/Types'
import { useUpdateRestaurantShipmentMethod, useGetRestaurantShipmentMethod, useGetShipmentMethods } from './hooks/useShipmentMethodData'
import { Pages } from '@/config/Pages'
import type { ErrorType } from '@/helpers/types'
import { extractErrorMessage } from '@/config/func'
const UpdateShipmentMethod: FC = () => {
const navigate = useNavigate()
const { id } = useParams<{ id: string }>()
const { mutate: updateRestaurantShipmentMethod, isPending } = useUpdateRestaurantShipmentMethod()
const { data: shipmentMethodData, isLoading } = useGetRestaurantShipmentMethod(id || '')
const { data: shipmentMethodsData } = useGetShipmentMethods()
const shipmentMethods = shipmentMethodsData?.data?.map((method: ShipmentMethod) => ({
label: method.title,
value: method.id
})) || []
const initialValues = useMemo<CreateShipmentMethodType>(() => {
if (shipmentMethodData?.data) {
const data = shipmentMethodData.data
return {
shipmentMethodId: data.shipmentMethod.id,
price: data.price,
minOrderPrice: data.minOrderPrice,
isActive: data.isActive,
}
}
return {
shipmentMethodId: '',
price: null,
minOrderPrice: null,
isActive: true,
}
}, [shipmentMethodData])
const formik = useFormik<CreateShipmentMethodType>({
initialValues,
enableReinitialize: true,
validationSchema: Yup.object().shape({
shipmentMethodId: Yup.string().required('روش ارسال الزامی است'),
price: Yup.number().nullable().required('قیمت الزامی است').min(0, 'قیمت باید مثبت باشد'),
minOrderPrice: Yup.number().nullable().required('حداقل قیمت سفارش الزامی است').min(0, 'حداقل قیمت سفارش باید مثبت باشد'),
isActive: Yup.boolean(),
}),
onSubmit: (values) => {
if (!id) return
updateRestaurantShipmentMethod(
{ id, params: values },
{
onSuccess: () => {
toast.success('روش ارسال با موفقیت ویرایش شد')
navigate(Pages.shipment_methods.list)
},
onError: (error: ErrorType) => {
toast.error(extractErrorMessage(error))
},
}
)
},
})
if (isLoading) {
return (
<div className='mt-5'>
<div className='text-lg font-light'>در حال بارگذاری...</div>
</div>
)
}
return (
<div className='mt-5'>
<div className='flex w-full justify-between items-center'>
<div className='text-lg font-light'>
ویرایش روش ارسال
</div>
<div>
<Button
className='px-5'
onClick={() => formik.handleSubmit()}
isloading={isPending}
>
<div className='flex gap-2 items-center'>
<TickCircle className='size-5' color='white' />
<div>ثبت تغییرات</div>
</div>
</Button>
</div>
</div>
<div className='mt-6'>
<div className='bg-white rounded-3xl p-6'>
<div className='mb-4'>
<Select
label='روش ارسال'
name='shipmentMethodId'
value={formik.values.shipmentMethodId}
onChange={formik.handleChange}
items={shipmentMethods}
placeholder='روش ارسال را انتخاب کنید'
error_text={formik.touched.shipmentMethodId && formik.errors.shipmentMethodId ? formik.errors.shipmentMethodId : ''}
/>
</div>
<div className='mt-6'>
<Input
label='قیمت'
name='price'
type='number'
value={formik.values.price ?? ''}
onChange={(e) => {
const value = e.target.value === '' ? null : Number(e.target.value)
formik.setFieldValue('price', value)
}}
error_text={formik.touched.price && formik.errors.price ? formik.errors.price : ''}
/>
</div>
<div className='mt-6'>
<Input
label='حداقل قیمت سفارش'
name='minOrderPrice'
type='number'
value={formik.values.minOrderPrice ?? ''}
onChange={(e) => {
const value = e.target.value === '' ? null : Number(e.target.value)
formik.setFieldValue('minOrderPrice', value)
}}
error_text={formik.touched.minOrderPrice && formik.errors.minOrderPrice ? formik.errors.minOrderPrice : ''}
/>
</div>
<div className='mt-6'>
<Switch
active={formik.values.isActive}
onChange={(value) => formik.setFieldValue('isActive', value)}
label='فعال'
/>
</div>
</div>
</div>
</div>
)
}
export default UpdateShipmentMethod
@@ -31,7 +31,7 @@ export const getShipmentMethodTableColumns = ({ onDelete, isDeleting }: GetShipm
key: 'price',
title: 'قیمت',
render: (item: RestaurantShipmentMethod) => {
return item.price ? `${item.price.toLocaleString()} تومان` : '-'
return item.price ? `${item.price.toLocaleString()} تومان` : 'رایگان'
}
},
{
@@ -1,6 +1,9 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import * as api from "../service/ShipmentMethodService";
import type { GetRestaurantShipmentMethodsParams } from "../types/Types";
import type {
CreateShipmentMethodType,
GetRestaurantShipmentMethodsParams,
} from "../types/Types";
export const useGetRestaurantShipmentMethods = (
params?: GetRestaurantShipmentMethodsParams
@@ -41,3 +44,29 @@ export const useDeleteRestaurantShipmentMethod = () => {
},
});
};
export const useGetRestaurantShipmentMethod = (id: string) => {
return useQuery({
queryKey: ["restaurant-shipment-method", id],
queryFn: () => api.getRestaurantShipmentMethod(id),
enabled: !!id,
});
};
export const useUpdateRestaurantShipmentMethod = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({
id,
params,
}: {
id: string;
params: CreateShipmentMethodType;
}) => api.updateRestaurantShipmentMethod(id, params),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["restaurant-shipment-methods"],
});
},
});
};
@@ -3,6 +3,7 @@ import type {
CreateShipmentMethodType,
GetShipmentMethodsResponseType,
GetRestaurantShipmentMethodsResponseType,
GetRestaurantShipmentMethodResponseType,
GetRestaurantShipmentMethodsParams,
} from "../types/Types";
@@ -16,7 +17,7 @@ export const getShipmentMethods = async (): Promise<
export const getRestaurantShipmentMethods = async (
params?: GetRestaurantShipmentMethodsParams
): Promise<GetRestaurantShipmentMethodsResponseType> => {
const { data } = await axios.get("/admin/restaurant-shipment-methods", {
const { data } = await axios.get("/admin/shipment-methods/restaurant", {
params,
});
return data;
@@ -26,7 +27,7 @@ export const createRestaurantShipmentMethod = async (
params: CreateShipmentMethodType
) => {
const { data } = await axios.post(
"/admin/restaurant-shipment-methods",
"/admin/shipment-methods/restaurant",
params
);
return data;
@@ -34,7 +35,25 @@ export const createRestaurantShipmentMethod = async (
export const deleteRestaurantShipmentMethod = async (id: string) => {
const { data } = await axios.delete(
`/admin/restaurant-shipment-methods/${id}`
`/admin/shipment-methods/restaurant/${id}`
);
return data;
};
export const getRestaurantShipmentMethod = async (
id: string
): Promise<GetRestaurantShipmentMethodResponseType> => {
const { data } = await axios.get(`/admin/shipment-methods/restaurant/${id}`);
return data;
};
export const updateRestaurantShipmentMethod = async (
id: string,
params: CreateShipmentMethodType
) => {
const { data } = await axios.patch(
`/admin/shipment-methods/restaurant/${id}`,
params
);
return data;
};
+5
View File
@@ -22,6 +22,7 @@ export type CreateShipmentMethodType = {
export type RestaurantShipmentMethod = {
id: string;
restaurant: string;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
@@ -35,6 +36,10 @@ export type GetRestaurantShipmentMethodsResponseType = IResponse<
RestaurantShipmentMethod[]
>;
export type GetRestaurantShipmentMethodResponseType = IResponse<
RestaurantShipmentMethod
>;
export type GetRestaurantShipmentMethodsParams = {
page?: number;
limit?: number;
+2
View File
@@ -32,6 +32,7 @@ import CreateAdmin from '@/pages/admin/Create'
import UpdateAdmin from '@/pages/admin/Update'
import ShipmentMethodList from '@/pages/shipmentMethod/List'
import CreateShipmentMethod from '@/pages/shipmentMethod/Create'
import UpdateShipmentMethod from '@/pages/shipmentMethod/Update'
const MainRouter: FC = () => {
const { hasSubMenu } = useSharedStore()
@@ -78,6 +79,7 @@ const MainRouter: FC = () => {
<Route path={Pages.shipment_methods.list} element={<ShipmentMethodList />} />
<Route path={Pages.shipment_methods.add} element={<CreateShipmentMethod />} />
<Route path={Pages.shipment_methods.update + ':id'} element={<UpdateShipmentMethod />} />
</Routes>
</div>
</div>