feat: allocate incentive plan to rancher
This commit is contained in:
@@ -61,10 +61,10 @@ export default function LiveStockFarmers() {
|
|||||||
item?.activity === "V"
|
item?.activity === "V"
|
||||||
? "روستایی"
|
? "روستایی"
|
||||||
: item?.activity === "I"
|
: item?.activity === "I"
|
||||||
? "صنعتی"
|
? "صنعتی"
|
||||||
: item?.activity === "R"
|
: item?.activity === "R"
|
||||||
? "عشایری"
|
? "عشایری"
|
||||||
: "-",
|
: "-",
|
||||||
item?.province?.name || "-",
|
item?.province?.name || "-",
|
||||||
item?.city?.name || "-",
|
item?.city?.name || "-",
|
||||||
item?.address,
|
item?.address,
|
||||||
@@ -137,7 +137,7 @@ export default function LiveStockFarmers() {
|
|||||||
"/plans/" +
|
"/plans/" +
|
||||||
item.id +
|
item.id +
|
||||||
"/" +
|
"/" +
|
||||||
item?.ranching_farm;
|
`${item?.first_name.replace(":", " ") || ""} ${item?.last_name || ""} ${item?.ranching_farm ? " (" + item?.ranching_farm + ") " : ""}`;
|
||||||
navigate({ to: path });
|
navigate({ to: path });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -0,0 +1,207 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { useToast } from "../../hooks/useToast";
|
||||||
|
import { useModalStore } from "../../context/zustand-store/appStore";
|
||||||
|
import { useApiMutation, useApiRequest } from "../../utils/useApiRequest";
|
||||||
|
import { Grid } from "../../components/Grid/Grid";
|
||||||
|
import Button from "../../components/Button/Button";
|
||||||
|
import Textfield from "../../components/Textfeild/Textfeild";
|
||||||
|
import AutoComplete from "../../components/AutoComplete/AutoComplete";
|
||||||
|
import { FormApiBasedAutoComplete } from "../../components/FormItems/FormApiBasedAutoComplete";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
getData: () => void;
|
||||||
|
rancher: string | number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type LivestockEntry = {
|
||||||
|
livestock_type: number;
|
||||||
|
allowed_quantity: number | "";
|
||||||
|
};
|
||||||
|
|
||||||
|
type PlanAllocation = {
|
||||||
|
plan: string | number;
|
||||||
|
plan_name: string;
|
||||||
|
livestock_entries: LivestockEntry[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LiveStockRancherAllocateIncentivePlan = ({
|
||||||
|
getData,
|
||||||
|
rancher,
|
||||||
|
}: Props) => {
|
||||||
|
const showToast = useToast();
|
||||||
|
const { closeModal } = useModalStore();
|
||||||
|
|
||||||
|
const [planAllocations, setPlanAllocations] = useState<PlanAllocation[]>([]);
|
||||||
|
|
||||||
|
const { data: speciesData } = useApiRequest({
|
||||||
|
api: "/livestock/web/api/v1/livestock_type",
|
||||||
|
method: "get",
|
||||||
|
params: { page: 1, page_size: 1000 },
|
||||||
|
queryKey: ["livestock_species"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const speciesOptions = () => {
|
||||||
|
return (
|
||||||
|
speciesData?.results?.map((opt: any) => ({
|
||||||
|
key: opt?.id,
|
||||||
|
value: opt?.name,
|
||||||
|
})) ?? []
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mutation = useApiMutation({
|
||||||
|
api: "/product/web/api/v1/rancher_incentive_plan/",
|
||||||
|
method: "post",
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const payload = planAllocations.flatMap((pa) =>
|
||||||
|
pa.livestock_entries.map((entry) => ({
|
||||||
|
plan: pa.plan,
|
||||||
|
rancher: Number(rancher),
|
||||||
|
livestock_type: entry.livestock_type,
|
||||||
|
allowed_quantity: Number(entry.allowed_quantity),
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (payload.length === 0) {
|
||||||
|
showToast("لطفاً حداقل یک طرح و نوع دام انتخاب کنید!", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await mutation.mutateAsync({ data: payload });
|
||||||
|
showToast("تخصیص طرح تشویقی با موفقیت انجام شد", "success");
|
||||||
|
getData();
|
||||||
|
closeModal();
|
||||||
|
} catch (error: any) {
|
||||||
|
showToast(
|
||||||
|
error?.response?.data?.message || "خطا در ثبت اطلاعات!",
|
||||||
|
"error",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<Grid container column className="gap-3">
|
||||||
|
<FormApiBasedAutoComplete
|
||||||
|
title="انتخاب طرح تشویقی"
|
||||||
|
api="product/web/api/v1/incentive_plan/active_plans/"
|
||||||
|
keyField="id"
|
||||||
|
valueField="name"
|
||||||
|
secondaryKey="name"
|
||||||
|
multiple
|
||||||
|
onChange={(items) => {
|
||||||
|
const selectedItems = Array.isArray(items) ? items : [];
|
||||||
|
setPlanAllocations((prev) =>
|
||||||
|
selectedItems.map((item: any) => {
|
||||||
|
const existing = prev.find((pa) => pa.plan === item.key1);
|
||||||
|
return (
|
||||||
|
existing || {
|
||||||
|
plan: item.key1,
|
||||||
|
plan_name: item.key2,
|
||||||
|
livestock_entries: [],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
onChangeValue={(names) => {
|
||||||
|
setPlanAllocations((prev) =>
|
||||||
|
prev.map((pa, i) => ({
|
||||||
|
...pa,
|
||||||
|
plan_name: names[i] || pa.plan_name,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{planAllocations.map((pa, planIndex) => (
|
||||||
|
<Grid
|
||||||
|
key={pa.plan}
|
||||||
|
container
|
||||||
|
column
|
||||||
|
className="gap-2 border p-3 rounded-lg"
|
||||||
|
>
|
||||||
|
<span className="font-bold text-sm">{pa.plan_name}</span>
|
||||||
|
|
||||||
|
{speciesData?.results && (
|
||||||
|
<AutoComplete
|
||||||
|
data={speciesOptions()}
|
||||||
|
multiselect
|
||||||
|
selectedKeys={pa.livestock_entries.map((e) => e.livestock_type)}
|
||||||
|
onChange={(keys: (string | number)[]) => {
|
||||||
|
setPlanAllocations((prev) => {
|
||||||
|
const next = [...prev];
|
||||||
|
next[planIndex] = {
|
||||||
|
...next[planIndex],
|
||||||
|
livestock_entries: keys.map((k) => {
|
||||||
|
const existing = next[planIndex].livestock_entries.find(
|
||||||
|
(e) => e.livestock_type === k,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
livestock_type: k as number,
|
||||||
|
allowed_quantity: existing?.allowed_quantity ?? "",
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
title="نوع دام"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{pa.livestock_entries.map((entry, entryIndex) => (
|
||||||
|
<Textfield
|
||||||
|
key={entry.livestock_type}
|
||||||
|
fullWidth
|
||||||
|
formattedNumber
|
||||||
|
placeholder={`تعداد مجاز ${
|
||||||
|
speciesOptions().find(
|
||||||
|
(s: any) => s.key === entry.livestock_type,
|
||||||
|
)?.value || ""
|
||||||
|
}`}
|
||||||
|
value={entry.allowed_quantity}
|
||||||
|
onChange={(e) => {
|
||||||
|
setPlanAllocations((prev) => {
|
||||||
|
const next = [...prev];
|
||||||
|
const entries = [...next[planIndex].livestock_entries];
|
||||||
|
entries[entryIndex] = {
|
||||||
|
...entries[entryIndex],
|
||||||
|
allowed_quantity: Number(e.target.value),
|
||||||
|
};
|
||||||
|
next[planIndex] = {
|
||||||
|
...next[planIndex],
|
||||||
|
livestock_entries: entries,
|
||||||
|
};
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<Button
|
||||||
|
disabled={
|
||||||
|
planAllocations.length === 0 ||
|
||||||
|
planAllocations.some((pa) => pa.livestock_entries.length === 0) ||
|
||||||
|
planAllocations.some((pa) =>
|
||||||
|
pa.livestock_entries.some(
|
||||||
|
(e) =>
|
||||||
|
e.allowed_quantity === "" || Number(e.allowed_quantity) <= 0,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
ثبت
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user