Files
dmenu-admin/src/pages/shipmentMethod/Update.tsx
T
hamid zarghami c404ac14be
deploy to danak / build_and_deploy (push) Has been cancelled
deliverfee can be zero
2026-06-03 10:54:11 +03:30

393 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Button from "@/components/Button";
import Input from "@/components/Input";
import RadioGroup from "@/components/RadioGroup";
import Select from "@/components/Select";
import Switch from "@/components/Switch";
import Textarea from "@/components/Textarea";
import { extractErrorMessage } from "@/config/func";
import { Pages } from "@/config/Pages";
import type { ErrorType } from "@/helpers/types";
import { useFormik } from "formik";
import { TickCircle } from "iconsax-react";
import { type FC, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate, useParams } from "react-router-dom";
import { toast } from "react-toastify";
import * as Yup from "yup";
import { DeliveryFeeTypeEnum, DeliveryMethodEnum } from "./enum/Enum";
import {
useGetRestaurantShipmentMethod,
useUpdateRestaurantShipmentMethod,
} from "./hooks/useShipmentMethodData";
import type { CreateShipmentMethodType } from "./types/Types";
const UpdateShipmentMethod: FC = () => {
const { t } = useTranslation("global");
const navigate = useNavigate();
const { id } = useParams<{ id: string }>();
const { mutate: updateRestaurantShipmentMethod, isPending } =
useUpdateRestaurantShipmentMethod();
const { data: shipmentMethodData, isLoading } =
useGetRestaurantShipmentMethod(id || "");
const [deliveryFeeType, setDeliveryFeeType] = useState<string>(
DeliveryFeeTypeEnum.FIXED,
);
const shipmentMethods = [
{
label: t(`shipment.${DeliveryMethodEnum.DineIn}`),
value: DeliveryMethodEnum.DineIn,
},
{
label: t(`shipment.${DeliveryMethodEnum.CustomerPickup}`),
value: DeliveryMethodEnum.CustomerPickup,
},
{
label: t(`shipment.${DeliveryMethodEnum.DeliveryCar}`),
value: DeliveryMethodEnum.DeliveryCar,
},
{
label: t(`shipment.${DeliveryMethodEnum.DeliveryCourier}`),
value: DeliveryMethodEnum.DeliveryCourier,
},
];
const initialValues = useMemo<CreateShipmentMethodType>(() => {
if (shipmentMethodData?.data) {
const data = shipmentMethodData.data;
return {
method: data.method,
deliveryFee: data.deliveryFee,
minOrderPrice: data.minOrderPrice,
description: data.description,
enabled: data.enabled,
order: data.order,
perKilometerFee: data.perKilometerFee ?? 0,
distanceBasedMinCost: data.distanceBasedMinCost ?? 0,
};
}
return {
method: "",
deliveryFee: 0,
minOrderPrice: 0,
description: "",
enabled: true,
order: 0,
perKilometerFee: 0,
distanceBasedMinCost: 0,
};
}, [shipmentMethodData]);
useEffect(() => {
if (shipmentMethodData?.data) {
const data = shipmentMethodData.data;
const hasDistanceBased = data.perKilometerFee && data.perKilometerFee > 0;
if (hasDistanceBased) {
setDeliveryFeeType(DeliveryFeeTypeEnum.DISTANCE_BASED);
} else {
setDeliveryFeeType(DeliveryFeeTypeEnum.FIXED);
}
}
}, [shipmentMethodData]);
const isFixedDeliveryFee = deliveryFeeType === DeliveryFeeTypeEnum.FIXED;
const formik = useFormik<CreateShipmentMethodType>({
initialValues,
enableReinitialize: true,
validationSchema: Yup.object().shape({
method: Yup.string().required("روش ارسال الزامی است"),
deliveryFee: Yup.number().min(0, "هزینه ارسال باید مثبت باشد"),
perKilometerFee: Yup.number().min(
0,
"هزینه ارسال به ازای هر کیلومتر باید مثبت باشد",
),
distanceBasedMinCost: Yup.number().min(
0,
"حداقل هزینه برای روش کیلوتری باید مثبت باشد",
),
minOrderPrice: Yup.number()
.required("حداقل قیمت سفارش الزامی است")
.min(0, "حداقل قیمت سفارش باید مثبت باشد"),
// description: Yup.string().required('توضیحات الزامی است'),
enabled: Yup.boolean(),
order: Yup.number()
.required("ترتیب الزامی است")
.min(0, "ترتیب باید مثبت باشد"),
}),
validate: (values) => {
const errors: Record<string, string> = {};
if (values.method === DeliveryMethodEnum.DeliveryCourier) {
if (isFixedDeliveryFee) {
if (values.deliveryFee == null || values.deliveryFee < 0) {
errors.deliveryFee = "هزینه ارسال الزامی است";
}
} else {
if (!values.perKilometerFee || values.perKilometerFee <= 0) {
errors.perKilometerFee =
"هزینه ارسال به ازای هر کیلومتر الزامی است";
}
if (
!values.distanceBasedMinCost ||
values.distanceBasedMinCost <= 0
) {
errors.distanceBasedMinCost =
"حداقل هزینه برای روش کیلوتری الزامی است";
}
}
} else {
if (values.deliveryFee == null || values.deliveryFee < 0) {
errors.deliveryFee = "هزینه ارسال الزامی است";
}
}
return errors;
},
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="flex">
<Switch
active={formik.values.enabled}
onChange={(value) => formik.setFieldValue("enabled", value)}
label="فعال"
/>
</div>
<div className="my-4">
<Select
label="روش ارسال"
name="method"
value={formik.values.method}
onChange={(e) => {
formik.handleChange(e);
if (e.target.value !== DeliveryMethodEnum.DeliveryCourier) {
setDeliveryFeeType(DeliveryFeeTypeEnum.FIXED);
formik.setFieldValue("perKilometerFee", 0);
formik.setFieldValue("distanceBasedMinCost", 0);
}
}}
items={shipmentMethods}
placeholder="روش ارسال را انتخاب کنید"
error_text={
formik.touched.method && formik.errors.method
? formik.errors.method
: ""
}
/>
</div>
{formik.values.method && (
<>
{formik.values.method === DeliveryMethodEnum.DeliveryCourier ? (
<>
<div className="mt-6">
<div className="text-sm mb-3">تحویل با پیک</div>
<RadioGroup
items={[
{ label: "ثابت", value: DeliveryFeeTypeEnum.FIXED },
{
label: "بر اساس مسافت",
value: DeliveryFeeTypeEnum.DISTANCE_BASED,
},
]}
selected={deliveryFeeType}
onChange={(value) => {
setDeliveryFeeType(value as string);
if (value === DeliveryFeeTypeEnum.FIXED) {
formik.setFieldValue("perKilometerFee", 0);
formik.setFieldValue("distanceBasedMinCost", 0);
} else {
formik.setFieldValue("deliveryFee", 0);
}
formik.validateForm();
}}
/>
</div>
{isFixedDeliveryFee ? (
<div className="mt-6">
<Input
label="هزینه ارسال"
name="deliveryFee"
type="number"
value={formik.values.deliveryFee ?? ""}
onChange={(e) => {
const value =
e.target.value === "" ? 0 : Number(e.target.value);
formik.setFieldValue("deliveryFee", value);
}}
error_text={
formik.touched.deliveryFee &&
formik.errors.deliveryFee
? formik.errors.deliveryFee
: ""
}
/>
</div>
) : (
<>
<div className="mt-6">
<Input
label="هزینه ارسال به ازای هر کیلومتر"
name="perKilometerFee"
type="number"
value={formik.values.perKilometerFee ?? ""}
onChange={(e) => {
const value =
e.target.value === ""
? 0
: Number(e.target.value);
formik.setFieldValue("perKilometerFee", value);
}}
error_text={
formik.touched.perKilometerFee &&
formik.errors.perKilometerFee
? formik.errors.perKilometerFee
: ""
}
/>
</div>
<div className="mt-6">
<Input
label="حداقل هزینه برای روش کیلوتری"
name="distanceBasedMinCost"
type="number"
value={formik.values.distanceBasedMinCost ?? ""}
onChange={(e) => {
const value =
e.target.value === ""
? 0
: Number(e.target.value);
formik.setFieldValue("distanceBasedMinCost", value);
}}
error_text={
formik.touched.distanceBasedMinCost &&
formik.errors.distanceBasedMinCost
? formik.errors.distanceBasedMinCost
: ""
}
/>
</div>
</>
)}
</>
) : (
<div className="mt-6">
<Input
label="هزینه ارسال"
name="deliveryFee"
type="number"
value={formik.values.deliveryFee ?? ""}
onChange={(e) => {
const value =
e.target.value === "" ? 0 : Number(e.target.value);
formik.setFieldValue("deliveryFee", value);
}}
error_text={
formik.touched.deliveryFee && formik.errors.deliveryFee
? formik.errors.deliveryFee
: ""
}
/>
</div>
)}
</>
)}
<div className="mt-6">
<Input
label="حداقل قیمت سفارش"
name="minOrderPrice"
type="number"
value={formik.values.minOrderPrice ?? ""}
onChange={(e) => {
const value =
e.target.value === "" ? 0 : Number(e.target.value);
formik.setFieldValue("minOrderPrice", value);
}}
error_text={
formik.touched.minOrderPrice && formik.errors.minOrderPrice
? formik.errors.minOrderPrice
: ""
}
/>
</div>
<div className="mt-6">
<Textarea
label="توضیحات"
name="description"
value={formik.values.description}
onChange={formik.handleChange}
error_text={
formik.touched.description && formik.errors.description
? formik.errors.description
: ""
}
/>
</div>
<div className="mt-6">
<Input
label="ترتیب"
name="order"
type="number"
value={formik.values.order ?? ""}
onChange={(e) => {
const value =
e.target.value === "" ? 0 : Number(e.target.value);
formik.setFieldValue("order", value);
}}
error_text={
formik.touched.order && formik.errors.order
? formik.errors.order
: ""
}
/>
</div>
</div>
</div>
</div>
);
};
export default UpdateShipmentMethod;