Files
Frontend/src/libs/api/services/cropZoningService.ts
T

253 lines
6.2 KiB
TypeScript
Raw Normal View History

/**
* Crop Zoning API
* @see CROP_ZONING_APIS.md
*/
2026-04-01 17:28:05 +03:30
import type { Feature, FeatureCollection, Polygon } from "geojson";
import { apiClient } from "../client";
import type {
RecommendationTaskInitResponse,
RecommendationTaskStatus,
RecommendationTaskStatusResponse,
} from "./recommendationTask";
import { normalizeRecommendationTaskStatus } from "./recommendationTask";
2026-04-01 17:28:05 +03:30
const PREFIX = "/api/crop-zoning";
export interface Product {
2026-04-01 17:28:05 +03:30
id: string;
label: string;
color: string;
}
export interface ZoneInitialData {
2026-04-01 17:28:05 +03:30
zoneId: string;
geometry: Polygon;
/** اگر null/خالی/uncultivable باشد، زون غیرقابل کشت و خاکستری نمایش داده می‌شود */
2026-04-01 17:28:05 +03:30
crop?: string | null;
matchPercent?: number | null;
waterNeed?: string | null;
estimatedProfit?: string | null;
}
export interface ZonesInitialResponse {
2026-04-01 17:28:05 +03:30
total_area_hectares: number;
total_area_sqm: number;
zone_count: number;
zones: ZoneInitialData[];
}
export interface AreaResponse {
2026-04-01 17:28:05 +03:30
area: Feature<Polygon> | null;
}
2026-04-01 17:28:05 +03:30
export interface CropZoningAreaTask {
status?:
| "IDLE"
| "PENDING"
| "PROCESSING"
| "SUCCESS"
| "FAILURE"
| "pending"
| "processing"
| "success"
| "completed"
| "failure"
| "failed";
stage?: string;
stage_label?: string;
area_uuid?: string;
total_zones?: number;
completed_zones?: number;
processing_zones?: number;
pending_zones?: number;
failed_zones?: number;
remaining_zones?: number;
progress_percent?: number;
message?: string;
failed_zone_errors?: string[];
cell_side_km?: number;
}
export interface CropZoningAreaResult extends AreaResponse {
status?: string;
task?: CropZoningAreaTask | null;
zones?: ZoneInitialData[];
}
export type CropZoningAreaResponse =
| CropZoningAreaResult
| RecommendationTaskInitResponse;
export interface ZoneDetailData {
2026-04-01 17:28:05 +03:30
zoneId: string;
crop: string;
matchPercent: number;
waterNeed: string;
estimatedProfit: string;
reason: string;
criteria: { name: string; value: number }[];
area_hectares?: number;
}
/** دیتای نیاز آبی هر زون — لایهٔ نیاز آبی */
export interface ZoneWaterNeedData {
2026-04-01 17:28:05 +03:30
zoneId: string;
geometry: Polygon;
level: "low" | "medium" | "high";
value?: string;
color: string;
}
/** دیتای کیفیت خاک هر زون — لایهٔ کیفیت خاک */
export interface ZoneSoilQualityData {
2026-04-01 17:28:05 +03:30
zoneId: string;
geometry: Polygon;
level: "low" | "medium" | "high";
score?: number;
color: string;
}
/** دیتای ریسک کشت هر زون — لایهٔ ریسک کشت */
export interface ZoneCultivationRiskData {
2026-04-01 17:28:05 +03:30
zoneId: string;
geometry: Polygon;
level: "low" | "medium" | "high";
color: string;
}
/** دادهٔ نمایشی هر زون روی نقشه — خروجی تبدیل از تمام لایه‌ها */
export interface ZoneMapData {
2026-04-01 17:28:05 +03:30
zoneId: string;
geometry: Polygon;
color: string;
tooltipContent: string;
cultivable: boolean;
zoneInitialData?: ZoneInitialData;
}
interface ApiResponse<T> {
2026-04-01 17:28:05 +03:30
status: string;
data: T;
}
async function unwrap<T>(promise: Promise<ApiResponse<T>>): Promise<T> {
2026-04-01 17:28:05 +03:30
const res = await promise;
return res.data;
}
function normalizeTaskInitResponse(
task: RecommendationTaskInitResponse,
): RecommendationTaskInitResponse {
return {
...task,
status: normalizeRecommendationTaskStatus(task.status),
};
}
function normalizeAreaResult(
result: CropZoningAreaResult,
): CropZoningAreaResult {
return {
...result,
task: result.task
? {
...result.task,
status: normalizeRecommendationTaskStatus(result.task.status),
}
: result.task,
};
}
export const cropZoningService = {
getProducts(): Promise<{ products: Product[] }> {
2026-04-01 17:28:05 +03:30
return unwrap(
apiClient.get<ApiResponse<{ products: Product[] }>>(
`${PREFIX}/products/`,
),
);
},
getZonesInitial(body: {
2026-04-01 17:28:05 +03:30
zones: FeatureCollection<Polygon>;
products?: string[];
}): Promise<ZonesInitialResponse> {
2026-04-01 17:28:05 +03:30
return unwrap(
apiClient.post<ApiResponse<ZonesInitialResponse>>(
`${PREFIX}/zones/initial/`,
body,
),
);
},
getZoneDetails(zoneId: string): Promise<ZoneDetailData> {
2026-04-01 17:28:05 +03:30
return unwrap(
apiClient.get<ApiResponse<ZoneDetailData>>(
`${PREFIX}/zones/${zoneId}/details/`,
),
);
},
2026-04-01 17:28:05 +03:30
getArea(sensorUuid: string): Promise<CropZoningAreaResponse> {
return unwrap(
apiClient.get<ApiResponse<CropZoningAreaResponse>>(`${PREFIX}/area/?sensor_uuid=${sensorUuid}`),
).then((response) =>
"task_id" in response
? normalizeTaskInitResponse(response)
: normalizeAreaResult(response),
);
},
getAreaStatus(
taskId: string,
): Promise<RecommendationTaskStatusResponse<CropZoningAreaResult>> {
return unwrap(
apiClient.get<
ApiResponse<RecommendationTaskStatusResponse<CropZoningAreaResult>>
>(`${PREFIX}/area/status/${taskId}/`),
).then((response) => ({
...response,
status: normalizeRecommendationTaskStatus(response.status),
result: response.result
? normalizeAreaResult(response.result)
: undefined,
}));
},
/** نیاز آبی هر منطقه — برای لایهٔ نیاز آبی */
2026-04-01 17:28:05 +03:30
getZonesWaterNeed(body: {
zones: FeatureCollection<Polygon>;
}): Promise<{ zones: ZoneWaterNeedData[] }> {
return unwrap(
2026-04-01 17:28:05 +03:30
apiClient.post<ApiResponse<{ zones: ZoneWaterNeedData[] }>>(
`${PREFIX}/zones/water-need/`,
body,
),
);
},
/** کیفیت خاک هر منطقه — برای لایهٔ کیفیت خاک */
2026-04-01 17:28:05 +03:30
getZonesSoilQuality(body: {
zones: FeatureCollection<Polygon>;
}): Promise<{ zones: ZoneSoilQualityData[] }> {
return unwrap(
2026-04-01 17:28:05 +03:30
apiClient.post<ApiResponse<{ zones: ZoneSoilQualityData[] }>>(
`${PREFIX}/zones/soil-quality/`,
body,
),
);
},
/** ریسک کشت هر منطقه — برای لایهٔ ریسک کشت */
getZonesCultivationRisk(body: {
2026-04-01 17:28:05 +03:30
zones: FeatureCollection<Polygon>;
}): Promise<{ zones: ZoneCultivationRiskData[] }> {
return unwrap(
apiClient.post<ApiResponse<{ zones: ZoneCultivationRiskData[] }>>(
`${PREFIX}/zones/cultivation-risk/`,
2026-04-01 17:28:05 +03:30
body,
),
);
},
};