2026-05-02 06:23:34 +03:30
|
|
|
|
"use client";
|
|
|
|
|
|
|
2026-05-02 16:31:23 +03:30
|
|
|
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
2026-05-02 06:23:34 +03:30
|
|
|
|
|
|
|
|
|
|
import Alert from "@mui/material/Alert";
|
|
|
|
|
|
import Box from "@mui/material/Box";
|
|
|
|
|
|
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";
|
2026-05-02 16:31:23 +03:30
|
|
|
|
import LinearProgress from "@mui/material/LinearProgress";
|
2026-05-02 06:23:34 +03:30
|
|
|
|
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";
|
2026-05-02 16:31:23 +03:30
|
|
|
|
import { useFarmHub } from "@/hooks/useFarmHub";
|
|
|
|
|
|
import {
|
|
|
|
|
|
fertilizationPlanService,
|
|
|
|
|
|
type FertilizationPlanDetail,
|
|
|
|
|
|
type FertilizationPlanListItem,
|
|
|
|
|
|
} from "@/libs/api/services/fertilizationPlanService";
|
|
|
|
|
|
import { irrigationPlanService } from "@/libs/api/services/irrigationPlanService";
|
2026-05-02 06:23:34 +03:30
|
|
|
|
|
|
|
|
|
|
import CustomTextField from "@core/components/mui/TextField";
|
|
|
|
|
|
|
|
|
|
|
|
type FertilizationPlanRow = {
|
2026-05-02 16:31:23 +03:30
|
|
|
|
id: string;
|
2026-05-02 06:23:34 +03:30
|
|
|
|
planName: string;
|
|
|
|
|
|
finalProduct: string;
|
|
|
|
|
|
harvestTime: string;
|
|
|
|
|
|
outputTon: number;
|
|
|
|
|
|
fertilizerType: string;
|
|
|
|
|
|
status: "active" | "draft";
|
2026-05-02 16:31:23 +03:30
|
|
|
|
sourceLabel: string;
|
|
|
|
|
|
growthStage: string;
|
2026-05-02 06:23:34 +03:30
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-02 16:31:23 +03:30
|
|
|
|
const PAGE_SIZE = 10;
|
|
|
|
|
|
|
|
|
|
|
|
const formatDate = (value?: string | null) => {
|
|
|
|
|
|
if (!value) return "—";
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
return new Intl.DateTimeFormat("fa-IR", {
|
|
|
|
|
|
year: "numeric",
|
|
|
|
|
|
month: "2-digit",
|
|
|
|
|
|
day: "2-digit",
|
|
|
|
|
|
}).format(new Date(value));
|
|
|
|
|
|
} catch {
|
|
|
|
|
|
return value;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const mapFertilizationPlanRow = (
|
|
|
|
|
|
plan: FertilizationPlanListItem,
|
|
|
|
|
|
detail?: FertilizationPlanDetail | null,
|
|
|
|
|
|
): FertilizationPlanRow => ({
|
|
|
|
|
|
id: plan.plan_uuid,
|
|
|
|
|
|
planName: plan.title,
|
|
|
|
|
|
finalProduct: plan.plant_name || plan.crop_id || "—",
|
|
|
|
|
|
harvestTime: formatDate(plan.created_at),
|
|
|
|
|
|
outputTon: 0,
|
|
|
|
|
|
fertilizerType: detail?.plan_payload?.items?.[0]?.name || plan.source_label || "—",
|
|
|
|
|
|
status: plan.is_active ? "active" : "draft",
|
|
|
|
|
|
sourceLabel: plan.source_label || "—",
|
|
|
|
|
|
growthStage: plan.growth_stage || "—",
|
|
|
|
|
|
});
|
2026-04-30 04:00:19 +03:30
|
|
|
|
|
|
|
|
|
|
const FertilizationPlanPage = () => {
|
2026-05-02 16:31:23 +03:30
|
|
|
|
const { getFarmUuid } = useFarmHub();
|
|
|
|
|
|
const [plans, setPlans] = useState<FertilizationPlanRow[]>([]);
|
2026-05-02 06:23:34 +03:30
|
|
|
|
const [minOutputTon, setMinOutputTon] = useState("0");
|
2026-05-02 16:31:23 +03:30
|
|
|
|
const [selectedPlan, setSelectedPlan] = useState<FertilizationPlanRow | null>(null);
|
2026-05-02 06:23:34 +03:30
|
|
|
|
const [detailsOpen, setDetailsOpen] = useState(false);
|
2026-05-02 16:31:23 +03:30
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
|
const [detailsLoading, setDetailsLoading] = useState(false);
|
|
|
|
|
|
const [actionLoadingId, setActionLoadingId] = useState<string | null>(null);
|
|
|
|
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
|
|
const [relatedPlans, setRelatedPlans] = useState<RelatedPlanItem[]>([]);
|
|
|
|
|
|
const [selectedRelatedPlanId, setSelectedRelatedPlanId] = useState<number | string | null>(
|
|
|
|
|
|
null,
|
2026-05-02 06:23:34 +03:30
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const filteredPlans = useMemo(() => {
|
|
|
|
|
|
const minTon = Number(minOutputTon);
|
|
|
|
|
|
|
|
|
|
|
|
return plans
|
|
|
|
|
|
.filter((plan) => plan.outputTon >= minTon)
|
|
|
|
|
|
.sort((firstPlan, secondPlan) => secondPlan.outputTon - firstPlan.outputTon);
|
|
|
|
|
|
}, [minOutputTon, plans]);
|
|
|
|
|
|
|
2026-05-02 16:31:23 +03:30
|
|
|
|
const loadPlans = useCallback(async () => {
|
|
|
|
|
|
const farmUuid = getFarmUuid();
|
|
|
|
|
|
|
|
|
|
|
|
if (!farmUuid) {
|
|
|
|
|
|
setError("ابتدا مزرعه فعال را انتخاب کنید.");
|
|
|
|
|
|
setPlans([]);
|
|
|
|
|
|
setSelectedPlan(null);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
setLoading(true);
|
|
|
|
|
|
setError(null);
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const response = await fertilizationPlanService.getPlans(farmUuid, 1, PAGE_SIZE);
|
|
|
|
|
|
const mappedPlans = response.data.map((plan) => mapFertilizationPlanRow(plan));
|
|
|
|
|
|
|
|
|
|
|
|
setPlans(mappedPlans);
|
|
|
|
|
|
setSelectedPlan((current) =>
|
|
|
|
|
|
mappedPlans.find((plan) => plan.id === current?.id) ?? mappedPlans[0] ?? null,
|
|
|
|
|
|
);
|
|
|
|
|
|
} catch (loadError) {
|
|
|
|
|
|
setError(
|
|
|
|
|
|
loadError instanceof Error
|
|
|
|
|
|
? loadError.message
|
|
|
|
|
|
: "دریافت لیست برنامههای کوددهی انجام نشد.",
|
|
|
|
|
|
);
|
|
|
|
|
|
setPlans([]);
|
|
|
|
|
|
setSelectedPlan(null);
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
setLoading(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}, [getFarmUuid]);
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
loadPlans();
|
|
|
|
|
|
}, [loadPlans]);
|
2026-05-02 06:23:34 +03:30
|
|
|
|
|
2026-05-02 16:31:23 +03:30
|
|
|
|
const loadRelatedPlans = useCallback(async () => {
|
|
|
|
|
|
const farmUuid = getFarmUuid();
|
2026-05-02 06:23:34 +03:30
|
|
|
|
|
2026-05-02 16:31:23 +03:30
|
|
|
|
if (!farmUuid) {
|
|
|
|
|
|
setRelatedPlans([]);
|
|
|
|
|
|
setSelectedRelatedPlanId(null);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const response = await irrigationPlanService.getPlans(farmUuid, 1, PAGE_SIZE);
|
|
|
|
|
|
const items: RelatedPlanItem[] = response.data.map((plan) => ({
|
|
|
|
|
|
id: plan.plan_uuid,
|
|
|
|
|
|
title: plan.title,
|
|
|
|
|
|
finalProduct: plan.plant_name || plan.crop_id || "—",
|
|
|
|
|
|
harvestTime: formatDate(plan.created_at),
|
|
|
|
|
|
outputTon: 0,
|
|
|
|
|
|
methodLabel: `منبع: ${plan.source_label || "—"}`,
|
|
|
|
|
|
status: plan.is_active ? "active" : "draft",
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
setRelatedPlans(items);
|
|
|
|
|
|
setSelectedRelatedPlanId(items[0]?.id ?? null);
|
|
|
|
|
|
}, [getFarmUuid]);
|
|
|
|
|
|
|
|
|
|
|
|
const handleActivate = async (planId: string) => {
|
|
|
|
|
|
setActionLoadingId(planId);
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
await fertilizationPlanService.updatePlanStatus(planId, true);
|
|
|
|
|
|
setPlans((currentPlans) =>
|
|
|
|
|
|
currentPlans.map((plan) => ({
|
|
|
|
|
|
...plan,
|
|
|
|
|
|
status: plan.id === planId ? "active" : "draft",
|
|
|
|
|
|
})),
|
|
|
|
|
|
);
|
|
|
|
|
|
setSelectedPlan((currentPlan) =>
|
|
|
|
|
|
currentPlan && currentPlan.id === planId
|
|
|
|
|
|
? { ...currentPlan, status: "active" }
|
|
|
|
|
|
: currentPlan,
|
|
|
|
|
|
);
|
|
|
|
|
|
} catch (updateError) {
|
|
|
|
|
|
setError(
|
|
|
|
|
|
updateError instanceof Error
|
|
|
|
|
|
? updateError.message
|
|
|
|
|
|
: "تغییر وضعیت برنامه کوددهی انجام نشد.",
|
|
|
|
|
|
);
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
setActionLoadingId(null);
|
2026-05-02 06:23:34 +03:30
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-02 16:31:23 +03:30
|
|
|
|
const handleDelete = async (planId: string) => {
|
|
|
|
|
|
setActionLoadingId(planId);
|
2026-05-02 06:23:34 +03:30
|
|
|
|
|
2026-05-02 16:31:23 +03:30
|
|
|
|
try {
|
|
|
|
|
|
await fertilizationPlanService.deletePlan(planId);
|
|
|
|
|
|
setPlans((currentPlans) => currentPlans.filter((plan) => plan.id !== planId));
|
|
|
|
|
|
if (selectedPlan?.id === planId) {
|
|
|
|
|
|
setSelectedPlan(null);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (deleteError) {
|
|
|
|
|
|
setError(
|
|
|
|
|
|
deleteError instanceof Error
|
|
|
|
|
|
? deleteError.message
|
|
|
|
|
|
: "حذف برنامه کوددهی انجام نشد.",
|
|
|
|
|
|
);
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
setActionLoadingId(null);
|
2026-05-02 06:23:34 +03:30
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-02 16:31:23 +03:30
|
|
|
|
const handleShowDetails = async (plan: FertilizationPlanRow) => {
|
2026-05-02 06:23:34 +03:30
|
|
|
|
setSelectedPlan(plan);
|
|
|
|
|
|
setDetailsOpen(true);
|
2026-05-02 16:31:23 +03:30
|
|
|
|
setDetailsLoading(true);
|
2026-05-02 06:23:34 +03:30
|
|
|
|
|
2026-05-02 16:31:23 +03:30
|
|
|
|
try {
|
|
|
|
|
|
const detail = await fertilizationPlanService.getPlanDetail(plan.id);
|
|
|
|
|
|
setSelectedPlan(mapFertilizationPlanRow(detail, detail));
|
|
|
|
|
|
await loadRelatedPlans();
|
|
|
|
|
|
} catch (detailError) {
|
|
|
|
|
|
setError(
|
|
|
|
|
|
detailError instanceof Error
|
|
|
|
|
|
? detailError.message
|
|
|
|
|
|
: "دریافت جزئیات برنامه کوددهی انجام نشد.",
|
|
|
|
|
|
);
|
|
|
|
|
|
setDetailsOpen(false);
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
setDetailsLoading(false);
|
|
|
|
|
|
}
|
2026-05-02 06:23:34 +03:30
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<>
|
|
|
|
|
|
<Stack spacing={6}>
|
|
|
|
|
|
<FertilizationPlanParserPage />
|
|
|
|
|
|
|
|
|
|
|
|
<Card>
|
|
|
|
|
|
<CardContent>
|
|
|
|
|
|
<Stack spacing={4}>
|
2026-05-02 16:31:23 +03:30
|
|
|
|
{loading ? <LinearProgress sx={{ borderRadius: 999 }} /> : null}
|
|
|
|
|
|
{error ? <Alert severity="error">{error}</Alert> : null}
|
|
|
|
|
|
|
2026-05-02 06:23:34 +03:30
|
|
|
|
<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">
|
2026-05-02 16:31:23 +03:30
|
|
|
|
لیست برنامههای کوددهی ثبتشده برای مزرعه فعال
|
2026-05-02 06:23:34 +03:30
|
|
|
|
</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>
|
2026-05-02 16:31:23 +03:30
|
|
|
|
<TableCell>تاریخ ایجاد</TableCell>
|
|
|
|
|
|
<TableCell>مرحله رشد</TableCell>
|
|
|
|
|
|
<TableCell>نوع کود / منبع</TableCell>
|
2026-05-02 06:23:34 +03:30
|
|
|
|
<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>
|
2026-05-02 16:31:23 +03:30
|
|
|
|
<TableCell>{plan.growthStage}</TableCell>
|
2026-05-02 06:23:34 +03:30
|
|
|
|
<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)}
|
2026-05-02 16:31:23 +03:30
|
|
|
|
disabled={plan.status === "active" || actionLoadingId === plan.id}
|
2026-05-02 06:23:34 +03:30
|
|
|
|
>
|
|
|
|
|
|
<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)}
|
2026-05-02 16:31:23 +03:30
|
|
|
|
disabled={actionLoadingId === plan.id}
|
2026-05-02 06:23:34 +03:30
|
|
|
|
>
|
|
|
|
|
|
<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" />
|
2026-05-02 16:31:23 +03:30
|
|
|
|
<Chip label={`تاریخ ایجاد: ${selectedPlan.harvestTime}`} variant="tonal" />
|
|
|
|
|
|
<Chip label={`مرحله رشد: ${selectedPlan.growthStage}`} variant="tonal" />
|
2026-05-02 06:23:34 +03:30
|
|
|
|
<Chip label={`نوع کود: ${selectedPlan.fertilizerType}`} variant="tonal" />
|
|
|
|
|
|
</Stack>
|
|
|
|
|
|
) : (
|
|
|
|
|
|
<Alert severity="warning">
|
|
|
|
|
|
برای دیدن جزئیات، یکی از برنامههای کوددهی را انتخاب کنید.
|
|
|
|
|
|
</Alert>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</Stack>
|
|
|
|
|
|
</Stack>
|
|
|
|
|
|
</CardContent>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
</Stack>
|
|
|
|
|
|
|
2026-05-02 16:31:23 +03:30
|
|
|
|
{detailsLoading ? <LinearProgress sx={{ borderRadius: 999, mt: 2 }} /> : null}
|
|
|
|
|
|
|
2026-05-02 06:23:34 +03:30
|
|
|
|
{selectedPlan ? (
|
|
|
|
|
|
<RelatedPlanSelector
|
|
|
|
|
|
open={detailsOpen}
|
|
|
|
|
|
onClose={() => setDetailsOpen(false)}
|
|
|
|
|
|
title="جزییات برنامه کوددهی"
|
|
|
|
|
|
description="برای تکمیل اجرای این برنامه کوددهی، یکی از برنامههای آبیاری مرتبط را انتخاب کنید."
|
|
|
|
|
|
currentPlanName={selectedPlan.planName}
|
|
|
|
|
|
currentPlanStatus={selectedPlan.status === "active" ? "برنامه فعال" : "آماده برای فعالسازی"}
|
2026-05-02 16:31:23 +03:30
|
|
|
|
currentPlanOutput={`منبع: ${selectedPlan.sourceLabel}`}
|
2026-05-02 06:23:34 +03:30
|
|
|
|
summaryItems={[
|
|
|
|
|
|
{ label: "محصول نهایی", value: selectedPlan.finalProduct },
|
2026-05-02 16:31:23 +03:30
|
|
|
|
{ label: "تاریخ ایجاد", value: selectedPlan.harvestTime },
|
|
|
|
|
|
{ label: "جزئیات", value: selectedPlan.fertilizerType },
|
2026-05-02 06:23:34 +03:30
|
|
|
|
]}
|
|
|
|
|
|
relatedTitle="برنامههای آبیاری پیشنهادی"
|
|
|
|
|
|
relatedDescription="از بین برنامههای زیر، مناسبترین برنامه آبیاری را برای این برنامه کوددهی انتخاب کنید."
|
2026-05-02 16:31:23 +03:30
|
|
|
|
relatedPlans={relatedPlans}
|
2026-05-02 06:23:34 +03:30
|
|
|
|
selectedRelatedPlanId={selectedRelatedPlanId}
|
2026-05-02 16:31:23 +03:30
|
|
|
|
onSelectRelatedPlan={(planId) => setSelectedRelatedPlanId(planId)}
|
|
|
|
|
|
onConfirm={() => setDetailsOpen(false)}
|
2026-05-02 06:23:34 +03:30
|
|
|
|
/>
|
|
|
|
|
|
) : null}
|
|
|
|
|
|
</>
|
|
|
|
|
|
);
|
2026-04-30 04:00:19 +03:30
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export default FertilizationPlanPage;
|