Files
RasadDam_Frontend/src/partials/LiveStock/quota/QuotaLevel1.tsx

549 lines
18 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 { Controller, useForm } from "react-hook-form";
import { Grid } from "../../../components/Grid/Grid";
import { FormApiBasedAutoComplete } from "../../../components/FormItems/FormApiBasedAutoComplete";
import {
zValidateAutoComplete,
zValidateAutoCompleteOptional,
zValidateNumber,
zValidateString,
} from "../../../data/getFormTypeErrors";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import AutoComplete from "../../../components/AutoComplete/AutoComplete";
import { getMonthsList } from "../../../data/getMonths";
import { RadioGroup } from "../../../components/RadioButton/RadioGroup";
import { useEffect, useRef, useState } from "react";
import ToggleButton from "../../../components/ToggleButton/ToggleButton";
import Typography from "../../../components/Typography/Typography";
import Textfield from "../../../components/Textfeild/Textfeild";
import { useApiRequest } from "../../../utils/useApiRequest";
type Props = {
item: any;
getData: () => void;
onSubmit: (data: any) => void;
setFormRef: (ref: HTMLFormElement | null) => void;
visible: boolean;
};
const saleTypes = [
{ value: "gov", label: "دولتی" },
{ value: "free", label: "آزاد" },
];
const groupTypes = [
{ value: "روستایی", key: "rural", disabled: false },
{ value: "صنعتی", key: "industrial", disabled: false },
{ value: "عشایری", key: "nomadic", disabled: true },
];
const posSaleTypes = [
{ value: "هردو", key: "all", disabled: false },
{ value: "بر اساس وزن", key: "weight", disabled: false },
{ value: "بر اساس تعداد راس دام", key: "count", disabled: false },
];
export const QuotaLevel1 = ({ item, onSubmit, setFormRef, visible }: Props) => {
const [hasDistributionLimit, setHasDistributionLimit] = useState(
item?.distribution_mode?.length ? true : false,
);
const internalRef = useRef<HTMLFormElement>(null);
const [livestockTypes, setLivestockTypes] = useState<
Array<{
livestock_group: string;
livestock_type: any;
weight_type: any;
quantity_kg: number;
fa: string;
}>
>([]);
useEffect(() => {
if (visible) {
setFormRef(internalRef.current);
}
}, [visible]);
const schema = z.object({
product: zValidateNumber("محصول"),
month_choices: zValidateAutoComplete("سهمیه ماه"),
distribution_mode: hasDistributionLimit
? zValidateAutoComplete("محدودیت توزیع دوره")
: zValidateAutoCompleteOptional(),
sale_license: zValidateAutoComplete("مجوز فروش"),
pos_sale_type: zValidateString("نوع فروش در دستگاه"),
sale_type: zValidateString("نوع فروش"),
group: zValidateAutoComplete("گروه"),
quota_weight: zValidateNumber("وزن سهمیه"),
sale_unit: zValidateNumber("نوع مولفه"),
});
type FormValues = z.infer<typeof schema>;
const {
control,
handleSubmit,
setValue,
getValues,
trigger,
formState: { errors },
} = useForm<FormValues>({
resolver: zodResolver(schema),
defaultValues: {
product: item?.product ? item?.product?.product_id : "",
month_choices: item?.month_choices || [],
distribution_mode: item?.distribution_mode || [],
sale_license: item?.sale_license || [],
sale_type: item?.sale_type || "gov",
group: item?.group || [],
pos_sale_type: item?.pos_sale_type || "all",
quota_weight: item?.quota_weight || 0,
sale_unit: item?.sale_unit ? item?.sale_unit?.id : "",
},
});
const { data: livestockData } = useApiRequest({
api: "/livestock/web/api/v1/livestock_type/",
method: "get",
params: { page: 1, page_size: 100 },
queryKey: ["livestockTypes"],
});
useEffect(() => {
if (livestockData?.results) {
const getQuantity = (allocate: any, group: string) => {
const result = item?.livestock_allocations?.find(
(option: any) =>
option?.livestock_type?.weight_type === allocate?.weight_type &&
option?.livestock_group === group &&
option?.livestock_type?.name === allocate?.name,
);
return result?.quantity_kg || 0;
};
const formattedData = livestockData.results.flatMap((item: any) => [
{
livestock_group: "rural",
livestock_type: item.id,
weight_type: item.weight_type,
quantity_kg: getQuantity(item, "rural"),
fa: item.name,
},
{
livestock_group: "industrial",
livestock_type: item.id,
weight_type: item.weight_type,
quantity_kg: getQuantity(item, "industrial"),
fa: item.name,
},
]);
setLivestockTypes(formattedData);
}
}, [livestockData, item]);
const handleQuantityChange = (index: number, value: number) => {
setLivestockTypes((prev) => {
const newTypes = [...prev];
newTypes[index] = { ...newTypes[index], quantity_kg: value };
return newTypes;
});
};
const findLivestockIndex = (
group: string,
weightType: string,
fa: string,
) => {
return livestockTypes.findIndex(
(item) =>
item.livestock_group === group &&
item.weight_type === weightType &&
item.fa === fa,
);
};
const handleSubmitForm = (data: FormValues) => {
onSubmit({ ...data, livestockTypes, hasDistributionLimit });
};
return (
<form ref={internalRef} onSubmit={handleSubmit(handleSubmitForm)}>
<Grid container column>
<Grid className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-3 mt-8 gap-4 items-start">
<Controller
name="product"
control={control}
render={() => (
<>
<FormApiBasedAutoComplete
defaultKey={item?.product?.product_id}
title="انتخاب محصول"
api={`product/web/api/v1/product`}
keyField="id"
valueField="name"
error={!!errors.product}
errorMessage={errors.product?.message}
onChange={(r) => {
setValue("product", r);
trigger("product");
}}
/>
</>
)}
/>
<Controller
name="quota_weight"
control={control}
render={({ field }) => (
<Textfield
formattedNumber
fullWidth
placeholder="وزن سهمیه"
value={field.value}
onChange={field.onChange}
error={!!errors.quota_weight}
helperText={errors.quota_weight?.message}
/>
)}
/>
<Controller
name="month_choices"
control={control}
render={({ field }) => (
<AutoComplete
data={getMonthsList}
selectField
selectedKeys={field.value}
multiselect
onChange={(keys: (string | number)[]) => {
setValue("month_choices", keys);
trigger("month_choices");
}}
error={!!errors.month_choices}
helperText={errors.month_choices?.message}
title="سهمیه ماه"
/>
)}
/>
<Controller
name="sale_license"
control={control}
render={({ field }) => (
<AutoComplete
selectField
data={getMonthsList}
selectedKeys={field.value}
multiselect
onChange={(keys: (string | number)[]) => {
setValue("sale_license", keys);
trigger("sale_license");
}}
error={!!errors.sale_license}
helperText={errors.sale_license?.message}
title="مجوز فروش"
/>
)}
/>
<Grid
container
className="p-2 border-1 rounded-lg items-center border-gray-200"
>
<Controller
name="sale_type"
control={control}
render={({ field }) => (
<RadioGroup
groupTitle="نوع فروش"
className="mr-2"
direction="row"
options={saleTypes}
value={field.value}
onChange={(e) => {
setValue("sale_type", e.target.value);
}}
/>
)}
/>
</Grid>
<Controller
name="group"
control={control}
render={({ field }) => (
<AutoComplete
selectField
data={groupTypes}
selectedKeys={field.value}
multiselect
onChange={(keys: (string | number)[]) => {
setValue("group", keys);
trigger("group");
}}
error={!!errors.group}
helperText={errors.group?.message}
title="گروه"
/>
)}
/>
<Controller
name="product"
control={control}
render={() => (
<>
<FormApiBasedAutoComplete
selectField
defaultKey={item?.sale_unit?.id}
title="نوع مولفه"
api={`product/web/api/v1/sale_unit`}
keyField="id"
valueField="unit"
error={!!errors.sale_unit}
errorMessage={errors.sale_unit?.message}
onChange={(r) => {
setValue("sale_unit", r);
trigger("sale_unit");
}}
/>
</>
)}
/>
<Grid
container
column
className="p-2 border-1 rounded-lg border-gray-200 items-start gap-2"
>
<ToggleButton
type="button"
isActive={hasDistributionLimit}
onClick={() => {
if (!hasDistributionLimit) {
setValue("distribution_mode", []);
trigger("distribution_mode");
}
setHasDistributionLimit(!hasDistributionLimit);
}}
title="محدودیت توزیع دوره"
aria-label="Toggle like"
/>
{hasDistributionLimit && (
<Controller
name="distribution_mode"
control={control}
render={({ field }) => (
<AutoComplete
data={getMonthsList}
selectedKeys={field.value || []}
multiselect
onChange={(keys: (string | number)[]) => {
setValue("distribution_mode", keys);
trigger("distribution_mode");
}}
error={!!errors.distribution_mode}
helperText={errors.distribution_mode?.message}
title="محدودیت توزیع دوره"
/>
)}
/>
)}
</Grid>
<Controller
name="pos_sale_type"
control={control}
render={({ field }) => (
<AutoComplete
selectField
data={posSaleTypes}
selectedKeys={[field.value]}
onChange={(keys: (string | number)[]) => {
setValue("pos_sale_type", keys.toString());
trigger("pos_sale_type");
}}
error={!!errors.pos_sale_type}
helperText={errors.pos_sale_type?.message}
title="نوع فروش در دستگاه"
/>
)}
/>
</Grid>
{getValues("group")?.includes("rural") && (
<>
<Typography
color="text-gray-600 dark:text-dark-100 my-4"
variant="body2"
>
سهمیه دام روستایی
</Typography>
<Grid className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-3 gap-4 items-start">
<Grid className="grid gap-2 p-2 border-1 border-gray-200 rounded-xl">
<Typography
color="text-gray-600 dark:text-dark-100"
className="flex justify-center select-none"
variant="caption"
>
سنگین
</Typography>
{livestockTypes
?.filter(
(option) =>
option.livestock_group === "rural" &&
option?.weight_type === "H",
)
.map((item, i) => {
const index = findLivestockIndex("rural", "H", item.fa);
return (
<Textfield
value={item.quantity_kg}
key={i}
start={item.fa}
end="کیلوگرم"
formattedNumber
onChange={(e) => {
const value =
parseInt(e.target.value.replace(/,/g, "")) || 0;
if (index !== -1) {
handleQuantityChange(index, value);
}
}}
/>
);
})}
</Grid>
<Grid className="grid gap-2 p-2 border-1 border-gray-200 rounded-xl">
<Typography
color="text-gray-600 dark:text-dark-100"
className="flex justify-center select-none"
variant="caption"
>
سبک
</Typography>
{livestockTypes
?.filter(
(option) =>
option.livestock_group === "rural" &&
option?.weight_type === "L",
)
.map((item, i) => {
const index = findLivestockIndex("rural", "L", item.fa);
return (
<Textfield
key={i}
start={item.fa}
end="کیلوگرم"
formattedNumber
value={item.quantity_kg}
onChange={(e) => {
const value =
parseInt(e.target.value.replace(/,/g, "")) || 0;
if (index !== -1) {
handleQuantityChange(index, value);
}
}}
/>
);
})}
</Grid>
</Grid>
</>
)}
{getValues("group")?.includes("industrial") && (
<>
<Typography
color="text-gray-600 dark:text-dark-100 my-4"
variant="body2"
>
سهمیه دام صنعتی
</Typography>
<Grid className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-3 gap-4 items-start">
<Grid className="grid gap-2 p-2 border-1 border-gray-200 rounded-xl">
<Typography
color="text-gray-600 dark:text-dark-100"
className="flex justify-center select-none"
variant="caption"
>
سنگین
</Typography>
{livestockTypes
?.filter(
(option) =>
option.livestock_group === "industrial" &&
option?.weight_type === "H",
)
.map((item, i) => {
const index = findLivestockIndex(
"industrial",
"H",
item.fa,
);
return (
<Textfield
value={item.quantity_kg}
key={i}
start={item.fa}
end="کیلوگرم"
formattedNumber
onChange={(e) => {
const value =
parseInt(e.target.value.replace(/,/g, "")) || 0;
if (index !== -1) {
handleQuantityChange(index, value);
}
}}
/>
);
})}
</Grid>
<Grid className="grid gap-2 p-2 border-1 border-gray-200 rounded-xl">
<Typography
color="text-gray-600 dark:text-dark-100"
className="flex justify-center select-none"
variant="caption"
>
سبک
</Typography>
{livestockTypes
?.filter(
(option) =>
option.livestock_group === "industrial" &&
option?.weight_type === "L",
)
.map((item, i) => {
const index = findLivestockIndex(
"industrial",
"L",
item.fa,
);
return (
<Textfield
key={i}
start={item.fa}
end="کیلوگرم"
formattedNumber
value={item.quantity_kg}
onChange={(e) => {
const value =
parseInt(e.target.value.replace(/,/g, "")) || 0;
if (index !== -1) {
handleQuantityChange(index, value);
}
}}
/>
);
})}
</Grid>
</Grid>
</>
)}
</Grid>
</form>
);
};