This commit is contained in:
2026-04-01 17:58:42 +03:30
parent bde110868a
commit e76dd01c4d
2 changed files with 241 additions and 17 deletions
@@ -33,8 +33,14 @@ const MapComponent = dynamic(() => Promise.resolve(CropZoningMap), {
const POLL_INTERVAL = 2000;
const MAX_POLLS = 100;
const ZONES_PAGE_SIZE = 100;
const getNormalizedTaskStatus = (status?: string) => status?.toLowerCase();
const mergeZones = (pages: ZoneInitialData[][]) =>
pages
.flat()
.sort((left, right) => (left.sequence ?? 0) - (right.sequence ?? 0));
export default function CropZoningWrapper() {
const t = useTranslations("cropZoning");
const { sensorHub } = useSensorHub();
@@ -77,36 +83,95 @@ export default function CropZoningWrapper() {
try {
let polls = 0;
const loadAllZonePages = async (
firstResponse: Extract<
Awaited<ReturnType<typeof cropZoningService.getArea>>,
{ area: unknown }
>,
completedTaskMessage?: string,
) => {
setAreaGeoJson(firstResponse.area as unknown as MapDrawGeoJSON);
const firstPageZones = firstResponse.zones ?? [];
const totalPages = Math.max(firstResponse.pagination?.total_pages ?? 1, 1);
const pageSize = firstResponse.pagination?.page_size ?? ZONES_PAGE_SIZE;
const zonePages: ZoneInitialData[][] = [firstPageZones];
setZonesData(firstPageZones as ZoneInitialData[]);
setProgress({
message: totalPages > 1 ? `${t("loadingArea")} (1/${totalPages})` : completedTaskMessage || t("loadingArea"),
percent: totalPages > 1 ? 80 : 100,
});
for (let page = 2; page <= totalPages; page++) {
if (cancelled) break;
const pageRes = await cropZoningService.getArea(sensorHub.id, {
page,
pageSize,
});
if (!("area" in pageRes)) {
throw new Error(t("errors.areaLoadFailed"));
}
zonePages.push(pageRes.zones ?? []);
const mergedZones = mergeZones(zonePages);
const pagesLoaded = zonePages.length;
const pagesProgress =
totalPages > 0 ? Math.round((pagesLoaded / totalPages) * 20) : 20;
setZonesData(mergedZones);
setProgress({
message: `${t("loadingArea")} (${pagesLoaded}/${totalPages})`,
percent: Math.min(80 + pagesProgress, 100),
});
}
if (!cancelled) {
setZonesData(mergeZones(zonePages));
setProgress({
message: completedTaskMessage || t("loadingArea"),
percent: 100,
});
}
};
while (!cancelled && polls < MAX_POLLS) {
const res = await cropZoningService.getArea(sensorHub.id);
const res = await cropZoningService.getArea(sensorHub.id, {
page: 1,
pageSize: ZONES_PAGE_SIZE,
});
if (!("area" in res)) break;
const task = res.task;
const taskStatus = getNormalizedTaskStatus(task?.status);
if (task) {
setProgress({
message: task.message || task.stage_label || t("loadingArea"),
percent: task.progress_percent || 0,
percent: Math.min(Math.round((task.progress_percent || 0) * 0.8), 80),
});
}
if (taskStatus === "completed" || taskStatus === "success") {
setAreaGeoJson(res.area as unknown as MapDrawGeoJSON);
if (res.zones) setZonesData(res.zones as ZoneInitialData[]);
await loadAllZonePages(
res,
task?.message || task?.stage_label || t("loadingArea"),
);
break;
}
if ((!task && res.area) || (res.area && taskStatus !== "pending" && taskStatus !== "processing")) {
setAreaGeoJson(res.area as unknown as MapDrawGeoJSON);
if (res.zones) setZonesData(res.zones as ZoneInitialData[]);
await loadAllZonePages(res, task?.message || task?.stage_label || t("loadingArea"));
break;
}
if (taskStatus === "failed" || taskStatus === "failure") {
throw new Error(task.message || t("errors.areaLoadFailed"));
throw new Error(task?.message || t("errors.areaLoadFailed"));
}
if (taskStatus === "pending" || taskStatus === "processing") {
@@ -116,7 +181,7 @@ export default function CropZoningWrapper() {
break;
}
}
if (polls >= MAX_POLLS) {
throw new Error(t("errors.timeout"));
}