2026-05-02 06:23:34 +03:30
|
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
|
|
import { useMemo, useState } from "react";
|
|
|
|
|
|
import { useRouter } from "next/navigation";
|
|
|
|
|
|
|
|
|
|
|
|
import Alert from "@mui/material/Alert";
|
|
|
|
|
|
import Box from "@mui/material/Box";
|
|
|
|
|
|
import Button from "@mui/material/Button";
|
|
|
|
|
|
import Card from "@mui/material/Card";
|
|
|
|
|
|
import CardContent from "@mui/material/CardContent";
|
|
|
|
|
|
import Chip from "@mui/material/Chip";
|
|
|
|
|
|
import Divider from "@mui/material/Divider";
|
|
|
|
|
|
import IconButton from "@mui/material/IconButton";
|
|
|
|
|
|
import Stack from "@mui/material/Stack";
|
|
|
|
|
|
import Table from "@mui/material/Table";
|
|
|
|
|
|
import TableBody from "@mui/material/TableBody";
|
|
|
|
|
|
import TableCell from "@mui/material/TableCell";
|
|
|
|
|
|
import TableContainer from "@mui/material/TableContainer";
|
|
|
|
|
|
import TableHead from "@mui/material/TableHead";
|
|
|
|
|
|
import TableRow from "@mui/material/TableRow";
|
|
|
|
|
|
import Tooltip from "@mui/material/Tooltip";
|
|
|
|
|
|
import Typography from "@mui/material/Typography";
|
|
|
|
|
|
|
2026-04-30 04:00:19 +03:30
|
|
|
|
import FertilizationPlanParserPage from "@views/dashboards/farm/fertilizationPlanParser/FertilizationPlanParserPage";
|
2026-05-02 06:23:34 +03:30
|
|
|
|
import RelatedPlanSelector, {
|
|
|
|
|
|
type RelatedPlanItem,
|
|
|
|
|
|
} from "@views/dashboards/farm/planSelector/RelatedPlanSelector";
|
|
|
|
|
|
|
|
|
|
|
|
import CustomTextField from "@core/components/mui/TextField";
|
|
|
|
|
|
|
|
|
|
|
|
type FertilizationPlanRow = {
|
|
|
|
|
|
id: number;
|
|
|
|
|
|
planName: string;
|
|
|
|
|
|
finalProduct: string;
|
|
|
|
|
|
harvestTime: string;
|
|
|
|
|
|
outputTon: number;
|
|
|
|
|
|
fertilizerType: string;
|
|
|
|
|
|
status: "active" | "draft";
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const mockFertilizationPlans: FertilizationPlanRow[] = [
|
|
|
|
|
|
{
|
|
|
|
|
|
id: 1,
|
|
|
|
|
|
planName: "برنامه کوددهی گوجه فرنگی گلخانهای",
|
|
|
|
|
|
finalProduct: "گوجه فرنگی ممتاز",
|
|
|
|
|
|
harvestTime: "۱۴۰۴/۰۶/۱۲",
|
|
|
|
|
|
outputTon: 52,
|
|
|
|
|
|
fertilizerType: "NPK 20-20-20",
|
|
|
|
|
|
status: "active",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
id: 2,
|
|
|
|
|
|
planName: "برنامه کوددهی فلفل دلمهای",
|
|
|
|
|
|
finalProduct: "فلفل دلمهای رنگی",
|
|
|
|
|
|
harvestTime: "۱۴۰۴/۰۵/۲۰",
|
|
|
|
|
|
outputTon: 34,
|
|
|
|
|
|
fertilizerType: "نیترات کلسیم",
|
|
|
|
|
|
status: "draft",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
id: 3,
|
|
|
|
|
|
planName: "برنامه کوددهی خیار گلخانهای",
|
|
|
|
|
|
finalProduct: "خیار ممتاز صادراتی",
|
|
|
|
|
|
harvestTime: "۱۴۰۴/۰۴/۲۸",
|
|
|
|
|
|
outputTon: 41,
|
|
|
|
|
|
fertilizerType: "سولفات پتاسیم",
|
|
|
|
|
|
status: "draft",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
id: 4,
|
|
|
|
|
|
planName: "برنامه کوددهی هندوانه",
|
|
|
|
|
|
finalProduct: "هندوانه شیرین بازارپسند",
|
|
|
|
|
|
harvestTime: "۱۴۰۴/۰۵/۲۹",
|
|
|
|
|
|
outputTon: 57,
|
|
|
|
|
|
fertilizerType: "اوره + هیومیک اسید",
|
|
|
|
|
|
status: "draft",
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
const relatedIrrigationPlans: RelatedPlanItem[] = [
|
|
|
|
|
|
{
|
|
|
|
|
|
id: 301,
|
|
|
|
|
|
title: "آبیاری قطرهای صبحگاهی",
|
|
|
|
|
|
finalProduct: "گوجه فرنگی ممتاز",
|
|
|
|
|
|
harvestTime: "۱۴۰۴/۰۶/۰۸",
|
|
|
|
|
|
outputTon: 45,
|
|
|
|
|
|
methodLabel: "روش آبیاری: قطرهای",
|
|
|
|
|
|
status: "active",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
id: 302,
|
|
|
|
|
|
title: "آبیاری تنظیمشده مرحله گلدهی",
|
|
|
|
|
|
finalProduct: "گوجه فرنگی ممتاز",
|
|
|
|
|
|
harvestTime: "۱۴۰۴/۰۶/۱۰",
|
|
|
|
|
|
outputTon: 49,
|
|
|
|
|
|
methodLabel: "روش آبیاری: تیپ",
|
|
|
|
|
|
status: "draft",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
id: 303,
|
|
|
|
|
|
title: "آبیاری تقویتی پیش از برداشت",
|
|
|
|
|
|
finalProduct: "گوجه فرنگی ممتاز",
|
|
|
|
|
|
harvestTime: "۱۴۰۴/۰۶/۱۴",
|
|
|
|
|
|
outputTon: 53,
|
|
|
|
|
|
methodLabel: "روش آبیاری: بارانی سبک",
|
|
|
|
|
|
status: "draft",
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
2026-04-30 04:00:19 +03:30
|
|
|
|
|
|
|
|
|
|
const FertilizationPlanPage = () => {
|
2026-05-02 06:23:34 +03:30
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
const [plans, setPlans] = useState(mockFertilizationPlans);
|
|
|
|
|
|
const [minOutputTon, setMinOutputTon] = useState("0");
|
|
|
|
|
|
const [selectedPlan, setSelectedPlan] = useState<FertilizationPlanRow | null>(
|
|
|
|
|
|
mockFertilizationPlans[0],
|
|
|
|
|
|
);
|
|
|
|
|
|
const [detailsOpen, setDetailsOpen] = useState(false);
|
|
|
|
|
|
const [selectedRelatedPlanId, setSelectedRelatedPlanId] = useState<number | null>(
|
|
|
|
|
|
relatedIrrigationPlans[0]?.id ?? null,
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const filteredPlans = useMemo(() => {
|
|
|
|
|
|
const minTon = Number(minOutputTon);
|
|
|
|
|
|
|
|
|
|
|
|
return plans
|
|
|
|
|
|
.filter((plan) => plan.outputTon >= minTon)
|
|
|
|
|
|
.sort((firstPlan, secondPlan) => secondPlan.outputTon - firstPlan.outputTon);
|
|
|
|
|
|
}, [minOutputTon, plans]);
|
|
|
|
|
|
|
|
|
|
|
|
const handleActivate = (planId: number) => {
|
|
|
|
|
|
setPlans((currentPlans) =>
|
|
|
|
|
|
currentPlans.map((plan) => ({
|
|
|
|
|
|
...plan,
|
|
|
|
|
|
status: plan.id === planId ? "active" : "draft",
|
|
|
|
|
|
})),
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const activePlan = plans.find((plan) => plan.id === planId);
|
|
|
|
|
|
|
|
|
|
|
|
if (activePlan) {
|
|
|
|
|
|
setSelectedPlan({ ...activePlan, status: "active" });
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleDelete = (planId: number) => {
|
|
|
|
|
|
setPlans((currentPlans) => currentPlans.filter((plan) => plan.id !== planId));
|
|
|
|
|
|
|
|
|
|
|
|
if (selectedPlan?.id === planId) {
|
|
|
|
|
|
setSelectedPlan(null);
|
|
|
|
|
|
setDetailsOpen(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleShowDetails = (plan: FertilizationPlanRow) => {
|
|
|
|
|
|
setSelectedPlan(plan);
|
|
|
|
|
|
setSelectedRelatedPlanId(relatedIrrigationPlans[0]?.id ?? null);
|
|
|
|
|
|
setDetailsOpen(true);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleConfirmRelatedPlan = (relatedPlan: RelatedPlanItem) => {
|
|
|
|
|
|
setDetailsOpen(false);
|
|
|
|
|
|
if (!selectedPlan) return;
|
|
|
|
|
|
|
|
|
|
|
|
const query = new URLSearchParams({
|
|
|
|
|
|
from: "fertilization-plan",
|
|
|
|
|
|
planType: "fertilization",
|
|
|
|
|
|
planId: String(selectedPlan.id),
|
|
|
|
|
|
planName: selectedPlan.planName,
|
|
|
|
|
|
relatedType: "irrigation",
|
|
|
|
|
|
relatedPlanId: String(relatedPlan.id),
|
|
|
|
|
|
relatedPlanName: relatedPlan.title,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
router.push(`/yield-harvest?${query.toString()}`);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<>
|
|
|
|
|
|
<Stack spacing={6}>
|
|
|
|
|
|
<FertilizationPlanParserPage />
|
|
|
|
|
|
|
|
|
|
|
|
<Card>
|
|
|
|
|
|
<CardContent>
|
|
|
|
|
|
<Stack spacing={4}>
|
|
|
|
|
|
<Stack
|
|
|
|
|
|
direction={{ xs: "column", md: "row" }}
|
|
|
|
|
|
spacing={3}
|
|
|
|
|
|
alignItems={{ xs: "stretch", md: "center" }}
|
|
|
|
|
|
justifyContent="space-between"
|
|
|
|
|
|
>
|
|
|
|
|
|
<Box>
|
|
|
|
|
|
<Typography variant="h5">لیست برنامههای کوددهی</Typography>
|
|
|
|
|
|
<Typography color="text.secondary">
|
|
|
|
|
|
نمایش همه برنامهها با داده ماک و امکان فیلتر بر اساس بیشترین تن خروجی محصول
|
|
|
|
|
|
</Typography>
|
|
|
|
|
|
</Box>
|
|
|
|
|
|
|
|
|
|
|
|
<CustomTextField
|
|
|
|
|
|
select
|
|
|
|
|
|
value={minOutputTon}
|
|
|
|
|
|
onChange={(event) => setMinOutputTon(event.target.value)}
|
|
|
|
|
|
label="فیلتر تن خروجی محصول"
|
|
|
|
|
|
sx={{ minWidth: { xs: "100%", md: 260 } }}
|
|
|
|
|
|
SelectProps={{ native: true }}
|
|
|
|
|
|
>
|
|
|
|
|
|
<option value="0">همه برنامهها</option>
|
|
|
|
|
|
<option value="30">بیشتر از ۳۰ تن</option>
|
|
|
|
|
|
<option value="40">بیشتر از ۴۰ تن</option>
|
|
|
|
|
|
<option value="50">بیشتر از ۵۰ تن</option>
|
|
|
|
|
|
</CustomTextField>
|
|
|
|
|
|
</Stack>
|
|
|
|
|
|
|
|
|
|
|
|
<TableContainer>
|
|
|
|
|
|
<Table>
|
|
|
|
|
|
<TableHead>
|
|
|
|
|
|
<TableRow>
|
|
|
|
|
|
<TableCell>نام برنامه</TableCell>
|
|
|
|
|
|
<TableCell>محصول نهایی</TableCell>
|
|
|
|
|
|
<TableCell>زمان برداشت</TableCell>
|
|
|
|
|
|
<TableCell>تن خروجی</TableCell>
|
|
|
|
|
|
<TableCell>نوع کود</TableCell>
|
|
|
|
|
|
<TableCell>وضعیت</TableCell>
|
|
|
|
|
|
<TableCell align="center">عملیات</TableCell>
|
|
|
|
|
|
</TableRow>
|
|
|
|
|
|
</TableHead>
|
|
|
|
|
|
<TableBody>
|
|
|
|
|
|
{filteredPlans.map((plan) => (
|
|
|
|
|
|
<TableRow hover key={plan.id}>
|
|
|
|
|
|
<TableCell>{plan.planName}</TableCell>
|
|
|
|
|
|
<TableCell>{plan.finalProduct}</TableCell>
|
|
|
|
|
|
<TableCell>{plan.harvestTime}</TableCell>
|
|
|
|
|
|
<TableCell>{plan.outputTon} تن</TableCell>
|
|
|
|
|
|
<TableCell>{plan.fertilizerType}</TableCell>
|
|
|
|
|
|
<TableCell>
|
|
|
|
|
|
<Chip
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
label={plan.status === "active" ? "فعال" : "پیشنویس"}
|
|
|
|
|
|
color={plan.status === "active" ? "success" : "default"}
|
|
|
|
|
|
variant={plan.status === "active" ? "filled" : "tonal"}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</TableCell>
|
|
|
|
|
|
<TableCell align="center">
|
|
|
|
|
|
<Stack direction="row" spacing={1} justifyContent="center">
|
|
|
|
|
|
<Tooltip title="فعالسازی برنامه">
|
|
|
|
|
|
<span>
|
|
|
|
|
|
<IconButton
|
|
|
|
|
|
color="success"
|
|
|
|
|
|
onClick={() => handleActivate(plan.id)}
|
|
|
|
|
|
disabled={plan.status === "active"}
|
|
|
|
|
|
>
|
|
|
|
|
|
<i className="tabler-player-play text-[20px]" />
|
|
|
|
|
|
</IconButton>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</Tooltip>
|
|
|
|
|
|
|
|
|
|
|
|
<Tooltip title="مشاهده جزئیات">
|
|
|
|
|
|
<IconButton
|
|
|
|
|
|
color="primary"
|
|
|
|
|
|
onClick={() => handleShowDetails(plan)}
|
|
|
|
|
|
>
|
|
|
|
|
|
<i className="tabler-eye text-[20px]" />
|
|
|
|
|
|
</IconButton>
|
|
|
|
|
|
</Tooltip>
|
|
|
|
|
|
|
|
|
|
|
|
<Tooltip title="حذف برنامه">
|
|
|
|
|
|
<IconButton
|
|
|
|
|
|
color="error"
|
|
|
|
|
|
onClick={() => handleDelete(plan.id)}
|
|
|
|
|
|
>
|
|
|
|
|
|
<i className="tabler-trash text-[20px]" />
|
|
|
|
|
|
</IconButton>
|
|
|
|
|
|
</Tooltip>
|
|
|
|
|
|
</Stack>
|
|
|
|
|
|
</TableCell>
|
|
|
|
|
|
</TableRow>
|
|
|
|
|
|
))}
|
|
|
|
|
|
|
|
|
|
|
|
{filteredPlans.length === 0 ? (
|
|
|
|
|
|
<TableRow>
|
|
|
|
|
|
<TableCell colSpan={7}>
|
|
|
|
|
|
<Alert severity="info">
|
|
|
|
|
|
برنامهای با این فیلتر پیدا نشد.
|
|
|
|
|
|
</Alert>
|
|
|
|
|
|
</TableCell>
|
|
|
|
|
|
</TableRow>
|
|
|
|
|
|
) : null}
|
|
|
|
|
|
</TableBody>
|
|
|
|
|
|
</Table>
|
|
|
|
|
|
</TableContainer>
|
|
|
|
|
|
|
|
|
|
|
|
<Divider />
|
|
|
|
|
|
|
|
|
|
|
|
<Stack spacing={2}>
|
|
|
|
|
|
<Typography variant="h6">جزئیات برنامه انتخابشده</Typography>
|
|
|
|
|
|
|
|
|
|
|
|
{selectedPlan ? (
|
|
|
|
|
|
<Stack
|
|
|
|
|
|
direction={{ xs: "column", md: "row" }}
|
|
|
|
|
|
spacing={2}
|
|
|
|
|
|
useFlexGap
|
|
|
|
|
|
flexWrap="wrap"
|
|
|
|
|
|
>
|
|
|
|
|
|
<Chip label={`محصول نهایی: ${selectedPlan.finalProduct}`} variant="tonal" />
|
|
|
|
|
|
<Chip label={`زمان برداشت: ${selectedPlan.harvestTime}`} variant="tonal" />
|
|
|
|
|
|
<Chip label={`تن خروجی: ${selectedPlan.outputTon} تن`} variant="tonal" />
|
|
|
|
|
|
<Chip label={`نوع کود: ${selectedPlan.fertilizerType}`} variant="tonal" />
|
|
|
|
|
|
<Button
|
|
|
|
|
|
variant="outlined"
|
|
|
|
|
|
color="primary"
|
|
|
|
|
|
startIcon={<i className="tabler-list-details" />}
|
|
|
|
|
|
onClick={() => handleShowDetails(selectedPlan)}
|
|
|
|
|
|
>
|
|
|
|
|
|
مشاهده و انتخاب برنامه آبیاری
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
<Button
|
|
|
|
|
|
variant="contained"
|
|
|
|
|
|
color="success"
|
|
|
|
|
|
startIcon={<i className="tabler-check" />}
|
|
|
|
|
|
onClick={() => handleActivate(selectedPlan.id)}
|
|
|
|
|
|
>
|
|
|
|
|
|
فعال کردن این برنامه
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</Stack>
|
|
|
|
|
|
) : (
|
|
|
|
|
|
<Alert severity="warning">
|
|
|
|
|
|
برای دیدن جزئیات، یکی از برنامههای کوددهی را انتخاب کنید.
|
|
|
|
|
|
</Alert>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</Stack>
|
|
|
|
|
|
</Stack>
|
|
|
|
|
|
</CardContent>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
</Stack>
|
|
|
|
|
|
|
|
|
|
|
|
{selectedPlan ? (
|
|
|
|
|
|
<RelatedPlanSelector
|
|
|
|
|
|
open={detailsOpen}
|
|
|
|
|
|
onClose={() => setDetailsOpen(false)}
|
|
|
|
|
|
title="جزییات برنامه کوددهی"
|
|
|
|
|
|
description="برای تکمیل اجرای این برنامه کوددهی، یکی از برنامههای آبیاری مرتبط را انتخاب کنید."
|
|
|
|
|
|
currentPlanName={selectedPlan.planName}
|
|
|
|
|
|
currentPlanStatus={selectedPlan.status === "active" ? "برنامه فعال" : "آماده برای فعالسازی"}
|
|
|
|
|
|
currentPlanOutput={`خروجی هدف: ${selectedPlan.outputTon} تن محصول نهایی`}
|
|
|
|
|
|
summaryItems={[
|
|
|
|
|
|
{ label: "محصول نهایی", value: selectedPlan.finalProduct },
|
|
|
|
|
|
{ label: "زمان برداشت", value: selectedPlan.harvestTime },
|
|
|
|
|
|
{ label: "نوع کود", value: selectedPlan.fertilizerType },
|
|
|
|
|
|
]}
|
|
|
|
|
|
relatedTitle="برنامههای آبیاری پیشنهادی"
|
|
|
|
|
|
relatedDescription="از بین برنامههای زیر، مناسبترین برنامه آبیاری را برای این برنامه کوددهی انتخاب کنید."
|
|
|
|
|
|
relatedPlans={relatedIrrigationPlans}
|
|
|
|
|
|
selectedRelatedPlanId={selectedRelatedPlanId}
|
|
|
|
|
|
onSelectRelatedPlan={setSelectedRelatedPlanId}
|
|
|
|
|
|
onConfirm={handleConfirmRelatedPlan}
|
|
|
|
|
|
/>
|
|
|
|
|
|
) : null}
|
|
|
|
|
|
</>
|
|
|
|
|
|
);
|
2026-04-30 04:00:19 +03:30
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export default FertilizationPlanPage;
|