This commit is contained in:
2026-04-28 19:00:11 +03:30
parent ffac636648
commit fa832e14b5
9 changed files with 1899 additions and 755 deletions
@@ -0,0 +1,216 @@
# Backend data needed only for irrigation recommendation
این فایل فقط اطلاعاتی را لیست می کند که فرانت برای بخش `recommendation` در صفحه
`src/views/dashboards/farm/smartIrrigation/SmartIrrigationRecommendation.tsx`
از بک اند نیاز دارد.
این سند شامل داده های `config`، `history`، یا اکشن های جانبی نیست؛ فقط داده های لازم برای
ساخت نتیجه توصیه آبیاری را پوشش می دهد.
## Request payload
فرانت برای گرفتن توصیه فقط به این فیلدها نیاز دارد:
```json
{
"farm_uuid": "string",
"plant_name": "string",
"growth_stage": "string"
}
```
## Response fields used by UI
فرانت در وضعیت فعلی فقط از این فیلدها در پاسخ recommendation استفاده می کند:
```json
{
"plan": {
"frequencyPerWeek": 4,
"durationMinutes": 38,
"bestTimeOfDay": "05:30 تا 08:00 صبح",
"moistureLevel": 72,
"warning": "string"
},
"water_balance": {
"active_kc": 0.93,
"crop_profile": {
"kc_initial": 0.55,
"kc_mid": 1.05,
"kc_end": 0.78
},
"daily": [
{
"forecast_date": "2025-02-12",
"et0_mm": 5.4,
"etc_mm": 4.9,
"effective_rainfall_mm": 0,
"gross_irrigation_mm": 17,
"irrigation_timing": "05:30 - 07:00"
}
]
},
"timeline": [
{
"step_number": 1,
"title": "string",
"description": "string"
}
],
"sections": [
{
"title": "string",
"icon": "string",
"type": "warning | tip",
"content": "string"
}
]
}
```
## Field-by-field usage
### 1) `plan`
برای نمایش خلاصه نسخه و هشدارها:
- `plan.frequencyPerWeek`
- نمایش تعداد نوبت آبیاری
- `plan.durationMinutes`
- نمایش مدت هر نوبت
- `plan.bestTimeOfDay`
- نمایش بهترین بازه زمانی آبیاری
- `plan.moistureLevel`
- نمایش مقدار رطوبت فعلی در gauge
- `plan.warning`
- نمایش هشدار اصلی در بخش warnings
### 2) `water_balance`
برای نمایش تراز آب و داده های روزانه:
- `water_balance.daily[]`
- `forecast_date`
- `gross_irrigation_mm`
- `irrigation_timing`
- `et0_mm`
- `etc_mm`
- `effective_rainfall_mm`
- `water_balance.crop_profile`
- `kc_initial`
- `kc_mid`
- `kc_end`
- `water_balance.active_kc`
- فعلا در UI فعلی استفاده مستقیم ندارد، اما بهتر است بماند اگر قرار است بعدا نمایش داده شود
### 3) `timeline`
برای نمایش Stepper مراحل اجرا:
- `timeline[].step_number`
- `timeline[].title`
- `timeline[].description`
نکته:
- در UI فعلی فقط همین سه فیلد لازم است.
- `time_label` و `state` قبلا در ماک استفاده شده بودند ولی در نسخه فعلی UI دیگر مصرف نمی شوند.
### 4) `sections`
برای هشدارها و نکات تکمیلی:
- `sections[].type`
- فقط این مقادیر فعلا مصرف می شوند:
- `warning`
- `tip`
- `sections[].title`
- برای کارت tip
- `sections[].icon`
- برای کارت tip
- `sections[].content`
- برای متن warning و tip
## Minimum response required
اگر بخواهیم حداقل پاسخ قابل استفاده برای UI فعلی را تعریف کنیم، این ساختار کافی است:
```json
{
"plan": {
"frequencyPerWeek": 4,
"durationMinutes": 38,
"bestTimeOfDay": "05:30 تا 08:00 صبح",
"moistureLevel": 72,
"warning": "در ساعات گرم روز آبیاری انجام نشود"
},
"water_balance": {
"crop_profile": {
"kc_initial": 0.55,
"kc_mid": 1.05,
"kc_end": 0.78
},
"daily": [
{
"forecast_date": "2025-02-12",
"et0_mm": 5.4,
"etc_mm": 4.9,
"effective_rainfall_mm": 0,
"gross_irrigation_mm": 17,
"irrigation_timing": "05:30 - 07:00"
}
]
},
"timeline": [
{
"step_number": 1,
"title": "بررسی فشار",
"description": "فشار ابتدا و انتهای لاین کنترل شود"
}
],
"sections": [
{
"title": "هشدار تبخیر بالا",
"icon": "tabler-alert-triangle",
"type": "warning",
"content": "در ساعات گرم روز آبیاری انجام نشود"
},
{
"title": "نکته بهره وری",
"icon": "tabler-bulb",
"type": "tip",
"content": "شست وشوی فیلترها به یکنواختی آبیاری کمک می کند"
}
]
}
```
## Fields currently not required by this UI
فیلدهای زیر در نسخه فعلی صفحه برای نمایش recommendation لازم نیستند:
- `raw_response`
- `status`
- `generated_at`
- `recommendation_title`
- `recommendation_subtitle`
- `final_verdict`
- `primary_method`
- `usage_summary`
- `alternative_plans`
- `sections[].type = schedule`
- `sections[].type = method`
## Practical backend recommendation
اگر هدف فقط راه اندازی همین UI فعلی است، بهتر است endpoint recommendation حداقل این 4 بخش را برگرداند:
- `plan`
- `water_balance`
- `timeline`
- `sections`
و در `sections` فعلا حداقل این دو نوع را پشتیبانی کند:
- `warning`
- `tip`
+534
View File
@@ -0,0 +1,534 @@
# Smart Irrigation Backend Integration
این فایل مشخص می کند صفحه
`src/views/dashboards/farm/smartIrrigation/SmartIrrigationRecommendation.tsx`
برای کار کامل با بک‌اند دقیقا چه داده هایی لازم دارد و از کدام endpointها باید استفاده کند.
هدف این سند:
- حذف داده های ماک
- مشخص شدن contract حداقلی بین فرانت و بک‌اند
- معلوم شدن این که هر بخش UI از کدام فیلد تغذیه می شود
---
## 1) دریافت محصولات انتخاب شده مزرعه
### Endpoint
`GET /api/plants/selected/?farm_uuid=<uuid>`
### کاربرد در UI
برای این بخش ها استفاده می شود:
- نمایش لیست محصول ها برای انتخاب
- گرفتن stageهای هر محصول
- انتخاب مقدار اولیه `selectedCrop`
- انتخاب مقدار اولیه `growthStage`
### فیلدهای لازم از response
```json
{
"data": [
{
"name": "گوجه فرنگی",
"icon": "tabler-carrot",
"growth_stages": ["رویشی", "گلدهی", "میوه دهی"]
}
]
}
```
### فیلدهای مصرفی
- `data[].name`
- برای `crop.id`
- برای `crop.name`
- `data[].icon`
- برای آیکن کارت محصول
- `data[].growth_stages[]`
- برای لیست stageها
---
## 2) تولید recommendation آبیاری
### Endpoint
`POST /api/irrigation/recommend/`
### Request payload مورد نیاز فرانت
```json
{
"farm_uuid": "11111111-1111-1111-1111-111111111111",
"plant_name": "گوجه فرنگی",
"growth_stage": "گلدهی"
}
```
### نکته مهم
در UI فعلی برای recommendation فقط این سه فیلد برای request لازم هستند:
- `farm_uuid`
- `plant_name`
- `growth_stage`
---
## 3) فیلدهای لازم از response recommendation
فرانت در وضعیت فعلی فقط این بخش ها را برای نمایش نتیجه لازم دارد.
### ساختار کلی مورد نیاز
```json
{
"code": 200,
"msg": "success",
"data": {
"recommendation_uuid": "uuid",
"crop_id": "گوجه فرنگی",
"plant_name": "گوجه فرنگی",
"growth_stage": "گلدهی",
"irrigation_method_name": "آبیاری قطره ای",
"status": "pending_confirmation",
"status_label": "منتظر تایید",
"plan": {},
"water_balance": {},
"timeline": [],
"sections": []
}
}
```
---
## 4) مصرف دقیق هر فیلد در UI recommendation
## 4.1) هدر صفحه نتیجه
برای نوار بالای صفحه نتیجه:
- `data.plant_name`
- `data.growth_stage`
کاربرد:
- ساخت `resultContext`
- نمایش عنوان بالای صفحه بعد از تولید recommendation
---
## 4.2) کارت Instruction Details
این کارت از این فیلدها تغذیه می شود:
### از `plan`
- `plan.frequencyPerWeek`
- `plan.durationMinutes`
- `plan.bestTimeOfDay`
- `plan.moistureLevel`
### از `water_balance`
- `water_balance.daily[].gross_irrigation_mm`
### نمونه حداقلی
```json
{
"plan": {
"frequencyPerWeek": 4,
"durationMinutes": 38,
"bestTimeOfDay": "05:30 تا 08:00 صبح",
"moistureLevel": 72,
"warning": "در ساعات گرم روز آبیاری انجام نشود"
},
"water_balance": {
"daily": [
{
"gross_irrigation_mm": 17
}
]
}
}
```
### نکته
در UI فعلی مقدار `Water Amount` با تکیه بر:
- `water_balance.daily[0].gross_irrigation_mm`
- و مساحت انتخابی در فرانت
محاسبه می شود.
اگر بخواهید محاسبه دقیق تر و backend-driven شود، بهتر است بک‌اند یکی از این دو را هم بدهد:
- `recommended_liters_per_hectare`
- یا `recommended_total_liters`
اما فعلا UI بدون اینها هم کار می کند.
---
## 4.3) Gauge / Circular Indicator
برای gauge فقط این دو مقدار لازم است:
- `plan.moistureLevel`
- `water_balance.daily` لازم نیست
و اگر بخواهید target هم از بک‌اند بیاید، بهتر است این فیلد اضافه شود:
- `target_moisture`
### وضعیت فعلی
در نسخه فعلی فرانت هنوز یک target mock-style استفاده می کند.
برای اتصال کامل بهتر است بک‌اند این فیلد را هم داخل `plan` برگرداند:
```json
{
"plan": {
"moistureLevel": 72,
"targetMoisture": 78
}
}
```
### پیشنهاد
اگر ممکن است این فیلد به response اضافه شود:
- `plan.targetMoisture`
---
## 4.4) تراز آب و نیاز روزانه
این بخش مستقیما از `water_balance` استفاده می کند.
### فیلدهای لازم
```json
{
"water_balance": {
"active_kc": 0.93,
"crop_profile": {
"kc_initial": 0.55,
"kc_mid": 1.05,
"kc_end": 0.78
},
"daily": [
{
"forecast_date": "2025-02-12",
"et0_mm": 5.4,
"etc_mm": 4.9,
"effective_rainfall_mm": 0,
"gross_irrigation_mm": 17,
"irrigation_timing": "05:30 - 07:00"
}
]
}
}
```
### فیلدهای مصرفی
#### از `water_balance.daily[]`
- `forecast_date`
- `gross_irrigation_mm`
- `irrigation_timing`
- `et0_mm`
- `etc_mm`
- `effective_rainfall_mm`
#### از `water_balance.crop_profile`
- `kc_initial`
- `kc_mid`
- `kc_end`
#### از `water_balance`
- `active_kc`
- فعلا در UI اصلی مستقیم رندر نمی شود، ولی برای آینده مفید است
---
## 4.5) Stepper مراحل و دستورالعمل اجرا
برای این بخش فقط `timeline` لازم است.
### ساختار لازم
```json
{
"timeline": [
{
"step_number": 1,
"title": "بررسی فشار",
"description": "فشار ابتدا و انتهای لاین کنترل شود"
}
]
}
```
### فیلدهای مصرفی
- `timeline[].step_number`
- `timeline[].title`
- `timeline[].description`
### نکته
در UI فعلی این فیلدها کافی هستند.
فیلدهایی مثل `time_label` یا `state` فعلا لازم نیستند.
---
## 4.6) هشدارها و نکات
این بخش از `plan.warning` و `sections` استفاده می کند.
### فیلدهای لازم
```json
{
"plan": {
"warning": "در ساعات گرم روز آبیاری انجام نشود"
},
"sections": [
{
"title": "هشدار تبخیر بالا",
"icon": "tabler-alert-triangle",
"type": "warning",
"content": "در ساعات گرم روز آبیاری انجام نشود"
},
{
"title": "نکته بهره وری",
"icon": "tabler-bulb",
"type": "tip",
"content": "شست وشوی فیلترها به یکنواختی آبیاری کمک می کند"
}
]
}
```
### مصرف در UI
#### هشدارها
- `plan.warning`
- `sections[].type === "warning"`
- `sections[].content`
#### نکات پایین صفحه
- `sections[].type === "tip"`
- `sections[].title`
- `sections[].icon`
- `sections[].content`
---
## 5) حداقل response پیشنهادی برای recommendation
اگر هدف فقط راه افتادن UI فعلی recommendation باشد، این حداقل پاسخ کافی است:
```json
{
"code": 200,
"msg": "success",
"data": {
"recommendation_uuid": "8a4c22d8-3f75-4aef-8e04-b40f6b4a2d11",
"crop_id": "گوجه فرنگی",
"plant_name": "گوجه فرنگی",
"growth_stage": "گلدهی",
"irrigation_method_name": "آبیاری قطره ای",
"status": "pending_confirmation",
"status_label": "منتظر تایید",
"plan": {
"frequencyPerWeek": 4,
"durationMinutes": 38,
"bestTimeOfDay": "05:30 تا 08:00 صبح",
"moistureLevel": 72,
"targetMoisture": 78,
"warning": "در ساعات گرم روز آبیاری انجام نشود"
},
"water_balance": {
"active_kc": 0.93,
"crop_profile": {
"kc_initial": 0.55,
"kc_mid": 1.05,
"kc_end": 0.78
},
"daily": [
{
"forecast_date": "2025-02-12",
"et0_mm": 5.4,
"etc_mm": 4.9,
"effective_rainfall_mm": 0,
"gross_irrigation_mm": 17,
"irrigation_timing": "05:30 - 07:00"
}
]
},
"timeline": [
{
"step_number": 1,
"title": "بررسی فشار",
"description": "فشار ابتدا و انتهای لاین کنترل شود"
}
],
"sections": [
{
"title": "هشدار تبخیر بالا",
"icon": "tabler-alert-triangle",
"type": "warning",
"content": "در ساعات گرم روز آبیاری انجام نشود"
},
{
"title": "نکته بهره وری",
"icon": "tabler-bulb",
"type": "tip",
"content": "شست وشوی فیلترها به یکنواختی آبیاری کمک می کند"
}
]
}
}
```
---
## 6) history recommendationهای آبیاری
### Endpoint
`GET /api/irrigation/recommendations/?farm_uuid=<uuid>&page=1&page_size=10`
### کاربرد در UI
برای جدول history پایین فرم استفاده می شود.
### فیلدهای لازم هر آیتم
```json
{
"recommendation_uuid": "uuid",
"plant_name": "گوجه فرنگی",
"growth_stage": "گلدهی",
"irrigation_method_name": "آبیاری قطره ای",
"status": "pending_confirmation",
"status_label": "منتظر تایید",
"requested_at": "2025-02-12T09:30:00Z"
}
```
### نکته مهم برای فرانت فعلی
در کد فعلی جدول history این فیلد را به عنوان ستون روش آبیاری می خواهد:
- `irrigation_method`
اما طبق contract بک‌اند، فیلد موجود این است:
- `irrigation_method_name`
### نتیجه
برای اتصال کامل یکی از این دو کار باید انجام شود:
1. یا فرانت `irrigation_method_name` را بخواند
2. یا بک‌اند علاوه بر آن، فیلد `irrigation_method` هم برگرداند
پیشنهاد بهتر:
- فرانت را با `irrigation_method_name` align کنید
### pagination لازم
```json
{
"pagination": {
"page": 1,
"page_size": 10,
"total_pages": 1,
"total_items": 1,
"has_next": false,
"has_previous": false,
"next": null,
"previous": null
}
}
```
---
## 7) جزئیات یک recommendation
### Endpoint
`GET /api/irrigation/recommendations/{recommendation_uuid}/`
### کاربرد در UI
وقتی کاربر از جدول history روی آیکن گزارش کلیک می کند، این endpoint باید صدا زده شود.
### ساختار لازم
خروجی این endpoint باید همان shape endpoint recommendation اصلی را برگرداند؛ یعنی:
- `recommendation_uuid`
- `plant_name`
- `growth_stage`
- `irrigation_method_name`
- `status`
- `status_label`
- `plan`
- `water_balance`
- `timeline`
- `sections`
---
## 8) فیلدهایی که فعلا در UI لازم نیستند
این فیلدها در نسخه فعلی صفحه ضروری نیستند:
- `raw_response`
- `crop_id` (اگر `plant_name` وجود داشته باشد)
- `sensor_uuid`
- `status` در خود recommendation result page
- `generated_at`
- `final_verdict`
- `recommendation_title`
- `recommendation_subtitle`
- `primary_method`
- `usage_summary`
- `alternative_plans`
- `sections[].type = schedule`
- `sections[].type = method`
---
## 9) جمع بندی نهایی
برای این صفحه اگر بخواهیم فقط داده های ضروری از بک‌اند بگیریم، این endpointها کافی هستند:
1. `GET /api/plants/selected/`
2. `POST /api/irrigation/recommend/`
3. `GET /api/irrigation/recommendations/`
4. `GET /api/irrigation/recommendations/{recommendation_uuid}/`
و برای recommendation page حداقل این بخش های response باید حتما وجود داشته باشند:
- `plant_name`
- `growth_stage`
- `plan`
- `water_balance`
- `timeline`
- `sections`
و برای history:
- `recommendation_uuid`
- `plant_name`
- `growth_stage`
- `irrigation_method_name`
- `status`
- `status_label`
- `requested_at`
- `pagination`
+100 -30
View File
@@ -627,21 +627,21 @@
"description": "این شبیه‌ساز رشد گیاه را بر اساس سرعت پایه، میزان نور خورشید و آب دریافتی محاسبه می‌کند. هر برگ به صورت تدریجی روی ساقه ظاهر شده و با حرکت طبیعی در باد نمایش داده می‌شود. محصول‌دهی (g) پس از ۲۰٪ رشد شروع شده و با تعداد برگ، نور و آب شتاب می‌گیرد. سرعت محصول (g/s) نشان‌دهنده نرخ لحظه‌ای تولید است. نمودار تغییرات همه شاخص‌ها را در طول زمان ثبت می‌کند."
},
"irrigation": {
"title": "توصیه هوشمند آبیاری",
"subtitle": "بر اساس دادههای ثبت شده مزرعه شما",
"farmInfo": {
"title": "اطلاعات مزرعه",
"soilType": "نوع خاک",
"waterQuality": "کیفیت آب",
"climateZone": "منطقه اقلیمی"
},
"verifiedBadge": "داده تأیید شده",
"editFarmInfo": "ویرایش اطلاعات مزرعه",
"title": "توصیه آبیاری هوشمند",
"subtitle": "محصول و مرحله رشد را انتخاب کنید تا نسخه آبیاری این مزرعه از روی داده های بک اند تولید شود.",
"farmIrrigationMethod": "روش آبیاری ثبت شده روی مزرعه: {method}",
"plantSelection": {
"title": "انتخاب محصول"
},
"growthStage": {
"title": "مرحله رشد"
"title": "مرحله رشد",
"options": {
"initial": "شروع رشد",
"vegetative": "رشد رویشی",
"flowering": "گلدهی",
"fruiting": "باردهی",
"maturity": "رسیدگی"
}
},
"crops": {
"wheat": "گندم",
@@ -649,28 +649,98 @@
"cotton": "پنبه",
"saffron": "زعفران",
"canola": "کلزا",
"vegetables": "سبزیجات"
"vegetables": "سبزیجات",
"cucumber": "خیار"
},
"generateCta": "تولید برنامه آبیاری",
"generating": "در حال تحلیل و تولید برنامه آبیاری...",
"units": {
"mm": "میلی متر",
"literShort": "لیتر"
},
"status": {
"fetchingReport": "در حال دریافت گزارش توصیه"
},
"actions": {
"saveVersion": "ذخیره این نسخه",
"setReminder": "تنظیم یادآور"
},
"gauge": {
"currentSoilMoisture": "رطوبت فعلی خاک",
"target": "هدف"
},
"instructionStats": {
"waterAmount": {
"label": "مقدار آب",
"hint": "برای سطح انتخاب شده"
},
"duration": {
"label": "مدت زمان",
"hint": "زمان تقریبی هر نوبت آبیاری"
},
"frequency": {
"label": "تناوب",
"hint": "تعداد دفعات پیشنهادی بر اساس تراز آب و مرحله رشد"
},
"bestWindow": {
"label": "بهترین بازه",
"hint": "بهترین زمان اجرا برای کاهش تلفات تبخیر"
}
},
"recommendation": {
"instructionDetailsTitle": "جزئیات دستور آبیاری",
"instructionDetailsSubtitle": "خلاصه ای سریع از دستور اجرایی آبیاری و شاخص اصلی موثر بر این توصیه.",
"soilMoistureDriverTitle": "محرک رطوبت خاک",
"soilMoistureDriverSubtitle": "رطوبت فعلی خاک با مقدار هدف مقایسه می شود تا منطق توصیه مشخص باشد.",
"waterBalanceTitle": "تراز آب و نیاز روزانه",
"executionWindow": "بازه اجرا",
"cropProfileTitle": "پروفایل گیاه",
"kcInitial": "Kc شروع",
"kcMid": "Kc میانی",
"kcEnd": "Kc پایانی",
"executionStepsTitle": "مراحل و دستورالعمل اجرا",
"warningsTitle": "هشدارها و نکات مهم",
"generatedTitle": "نسخه آبیاری هوشمند {plant}",
"generatedSubtitle": "پیشنهاد ویژه برای مرحله {stage}",
"durationPerTurn": "{value} دقیقه در هر نوبت",
"frequencyPerWeek": "{value} نوبت در هفته",
"weatherBasedWindow": "طبق وضعیت آب و هوا"
},
"history": {
"title": "تاریخچه توصیه های آبیاری",
"subtitle": "همه توصیه های قبلی مزرعه را اینجا ببینید و گزارش کامل هرکدام را باز کنید.",
"viewReport": "مشاهده گزارش",
"empty": "هنوز توصیه ای برای این مزرعه ثبت نشده است.",
"rowsPerPage": "تعداد در صفحه:",
"displayedRows": "{from}{to} از {count}",
"statuses": {
"pending": "در انتظار",
"in_progress": "در حال پردازش",
"completed": "تکمیل شده"
},
"columns": {
"requestedAt": "تاریخ ثبت",
"cropStage": "محصول / مرحله رشد",
"method": "روش آبیاری",
"status": "وضعیت",
"report": "گزارش"
}
},
"details": {
"waterBalanceTitle": "جزئیات تراز آب {date}",
"waterBalanceContent": "ET0: {et0} {mm}\nETc: {etc} {mm}\nبارش موثر: {rainfall} {mm}\nآبیاری ناخالص: {gross} {mm}\nبازه اجرا: {timing}",
"addReminder": "افزودن به یادآور",
"understood": "متوجه شدم"
},
"generateCta": "تولید توصیه آبیاری",
"generating": "در حال تولید توصیه آبیاری...",
"loadingCard": "در حال تحلیل و تولید نسخه آبیاری...",
"errors": {
"noFarm": "ابتدا یک مزرعه انتخاب کنید.",
"generateFailed": "دریافت برنامه آبیاری با خطا مواجه شد.",
"timeout": "دریافت نتیجه بیش از حد طول کشید. دوباره تلاش کنید."
},
"result": {
"moistureLevel": "سطح رطوبت هدف",
"frequency": "تناوب آبیاری",
"timesPerWeek": "بار در هفته",
"duration": "مدت هر نوبت",
"minutes": "دقیقه",
"bestTime": "بهترین زمان آبیاری",
"smartWarning": "هشدار هوشمند",
"waterBalance": "جزئیات تراز آب",
"forecastDate": "تاریخ پیش‌بینی",
"grossIrrigation": "نیاز آبیاری ناخالص",
"irrigationTiming": "زمان آبیاری",
"activeKc": "ضریب رشد فعال"
"noSelectedPlants": "برای این مزرعه هنوز محصولی انتخاب نشده است.",
"selectedPlantsFailed": "خطا در دریافت محصولات انتخاب شده مزرعه",
"generateFailed": "خطا در تولید توصیه آبیاری",
"historyFailed": "خطا در دریافت تاریخچه توصیه های آبیاری",
"reportFailed": "خطا در دریافت گزارش توصیه آبیاری",
"pendingResponse": "درخواست ثبت شد اما پاسخ نهایی هنوز آماده نیست."
}
},
"fertilization": {
+94
View File
@@ -112,5 +112,99 @@
"economicOverview": "النظرة الاقتصادية",
"sensorSection": "المستشعرات",
"sensor7In1": "مستشعر التربة 7 في 1"
},
"irrigation": {
"title": "توصية الري الذكية",
"subtitle": "اختر المحصول ومرحلة النمو لتوليد توصية الري لهذه المزرعة اعتمادا على بيانات الخلفية.",
"generateCta": "إنشاء توصية الري",
"generating": "جار إنشاء توصية الري...",
"loadingCard": "جار تحليل البيانات وإنشاء خطة الري...",
"farmIrrigationMethod": "طريقة الري المسجلة في المزرعة: {method}",
"growthStage": {
"title": "مرحلة النمو"
},
"plantSelection": {
"title": "اختيار المحصول"
},
"units": {
"mm": "مم",
"literShort": "لتر"
},
"status": {
"fetchingReport": "جار تحميل تقرير التوصية"
},
"actions": {
"saveVersion": "حفظ هذه النسخة",
"setReminder": "تعيين تذكير"
},
"gauge": {
"currentSoilMoisture": "رطوبة التربة الحالية",
"target": "الهدف"
},
"instructionStats": {
"waterAmount": {
"label": "كمية المياه",
"hint": "للمساحة المحددة"
},
"duration": {
"label": "المدة",
"hint": "المدة التقديرية لكل دورة ري"
},
"frequency": {
"label": "التكرار",
"hint": "الوتيرة المقترحة حسب توازن المياه ومرحلة النمو"
},
"bestWindow": {
"label": "أفضل وقت",
"hint": "الوقت المفضل للتنفيذ لتقليل فقدان التبخر"
}
},
"recommendation": {
"instructionDetailsTitle": "تفاصيل تعليمات الري",
"instructionDetailsSubtitle": "ملخص سريع لتعليمات الري الدقيقة والمؤشر الأساسي الذي يقود هذه التوصية.",
"soilMoistureDriverTitle": "مؤشر رطوبة التربة",
"soilMoistureDriverSubtitle": "تتم مقارنة رطوبة التربة الحالية بالحد المستهدف لتوضيح منطق التوصية.",
"waterBalanceTitle": "توازن المياه والاحتياج اليومي",
"executionWindow": "نافذة التنفيذ",
"cropProfileTitle": "ملف المحصول",
"kcInitial": "Kc البداية",
"kcMid": "Kc الوسط",
"kcEnd": "Kc النهاية",
"executionStepsTitle": "خطوات التنفيذ والتعليمات",
"warningsTitle": "تحذيرات وملاحظات مهمة",
"generatedTitle": "خطة الري الذكية لـ {plant}",
"generatedSubtitle": "توصية خاصة لمرحلة {stage}",
"durationPerTurn": "{value} دقيقة لكل دورة",
"frequencyPerWeek": "{value} مرات في الأسبوع",
"weatherBasedWindow": "بحسب حالة الطقس"
},
"history": {
"title": "سجل توصيات الري",
"subtitle": "اعرض جميع التوصيات السابقة لهذه المزرعة وافتح التقرير الكامل لكل واحدة.",
"viewReport": "عرض التقرير",
"empty": "لم يتم تسجيل أي توصية لهذه المزرعة بعد.",
"columns": {
"requestedAt": "تاريخ الطلب",
"cropStage": "المحصول / مرحلة النمو",
"method": "طريقة الري",
"status": "الحالة",
"report": "التقرير"
}
},
"details": {
"waterBalanceTitle": "تفاصيل توازن المياه {date}",
"waterBalanceContent": "ET0: {et0} {mm}\nETc: {etc} {mm}\nالأمطار الفعالة: {rainfall} {mm}\nالري الإجمالي: {gross} {mm}\nنافذة التنفيذ: {timing}",
"addReminder": "إضافة إلى التذكير",
"understood": "فهمت"
},
"errors": {
"noFarm": "يرجى اختيار مزرعة أولا.",
"noSelectedPlants": "لم يتم اختيار أي محصول لهذه المزرعة بعد.",
"selectedPlantsFailed": "فشل تحميل المحاصيل المختارة للمزرعة",
"generateFailed": "فشل إنشاء توصية الري",
"historyFailed": "فشل تحميل سجل توصيات الري",
"reportFailed": "فشل تحميل تقرير توصية الري",
"pendingResponse": "تم تسجيل الطلب ولكن الاستجابة النهائية ليست جاهزة بعد."
}
}
}
+94
View File
@@ -112,5 +112,99 @@
"economicOverview": "Economic Overview",
"sensorSection": "Sensors",
"sensor7In1": "Soil Sensor 7-in-1"
},
"irrigation": {
"title": "Smart Irrigation Recommendation",
"subtitle": "Select the crop and growth stage to generate the irrigation recommendation for this farm from backend data.",
"generateCta": "Generate Irrigation Recommendation",
"generating": "Generating irrigation recommendation...",
"loadingCard": "Analyzing data and generating the irrigation plan...",
"farmIrrigationMethod": "Irrigation method saved on the farm: {method}",
"growthStage": {
"title": "Growth Stage"
},
"plantSelection": {
"title": "Plant Selection"
},
"units": {
"mm": "mm",
"literShort": "L"
},
"status": {
"fetchingReport": "Fetching recommendation report"
},
"actions": {
"saveVersion": "Save This Version",
"setReminder": "Set Reminder"
},
"gauge": {
"currentSoilMoisture": "CURRENT SOIL MOISTURE",
"target": "Target"
},
"instructionStats": {
"waterAmount": {
"label": "Water Amount",
"hint": "across the selected field area"
},
"duration": {
"label": "Duration",
"hint": "Estimated runtime for each irrigation cycle"
},
"frequency": {
"label": "Frequency",
"hint": "Recommended cadence based on water balance and growth stage"
},
"bestWindow": {
"label": "Best Window",
"hint": "Preferred execution time to reduce evaporation losses"
}
},
"recommendation": {
"instructionDetailsTitle": "Instruction Details",
"instructionDetailsSubtitle": "A quick operational snapshot of the exact irrigation instructions and the metric driving this recommendation.",
"soilMoistureDriverTitle": "Soil Moisture Driver",
"soilMoistureDriverSubtitle": "Current soil moisture is compared against the target threshold to justify the final recommendation.",
"waterBalanceTitle": "Water Balance and Daily Need",
"executionWindow": "Execution Window",
"cropProfileTitle": "Crop Profile",
"kcInitial": "Kc Initial",
"kcMid": "Kc Mid",
"kcEnd": "Kc End",
"executionStepsTitle": "Execution Steps and Instructions",
"warningsTitle": "Warnings and Important Notes",
"generatedTitle": "Smart irrigation plan for {plant}",
"generatedSubtitle": "Special recommendation for the {stage} stage",
"durationPerTurn": "{value} minutes per cycle",
"frequencyPerWeek": "{value} times per week",
"weatherBasedWindow": "Based on weather conditions"
},
"history": {
"title": "Irrigation Recommendation History",
"subtitle": "Review all previous recommendations for this farm and open the full report for each one.",
"viewReport": "View Report",
"empty": "No recommendations have been recorded for this farm yet.",
"columns": {
"requestedAt": "Requested At",
"cropStage": "Crop / Growth Stage",
"method": "Irrigation Method",
"status": "Status",
"report": "Report"
}
},
"details": {
"waterBalanceTitle": "Water Balance Details {date}",
"waterBalanceContent": "ET0: {et0} {mm}\nETc: {etc} {mm}\nEffective rainfall: {rainfall} {mm}\nGross irrigation: {gross} {mm}\nExecution window: {timing}",
"addReminder": "Add to Reminder",
"understood": "Understood"
},
"errors": {
"noFarm": "Please select a farm first.",
"noSelectedPlants": "No plants have been selected for this farm yet.",
"selectedPlantsFailed": "Failed to load selected plants for the farm",
"generateFailed": "Failed to generate irrigation recommendation",
"historyFailed": "Failed to load irrigation recommendation history",
"reportFailed": "Failed to load irrigation recommendation report",
"pendingResponse": "The request was submitted, but the final response is not ready yet."
}
}
}
+97
View File
@@ -112,5 +112,102 @@
"economicOverview": "نمای اقتصادی",
"sensorSection": "سنسورها",
"sensor7In1": "سنسور خاک 7 در 1"
},
"irrigation": {
"title": "توصیه آبیاری هوشمند",
"subtitle": "محصول و مرحله رشد را انتخاب کنید تا نسخه آبیاری این مزرعه از روی داده های بک اند تولید شود.",
"generateCta": "تولید توصیه آبیاری",
"generating": "در حال تولید توصیه آبیاری...",
"loadingCard": "در حال تحلیل و تولید نسخه آبیاری...",
"farmIrrigationMethod": "روش آبیاری ثبت شده روی مزرعه: {method}",
"growthStage": {
"title": "مرحله رشد"
},
"plantSelection": {
"title": "انتخاب محصول"
},
"units": {
"mm": "میلی متر",
"literShort": "لیتر"
},
"status": {
"fetchingReport": "در حال دریافت گزارش توصیه"
},
"actions": {
"saveVersion": "ذخیره این نسخه",
"setReminder": "تنظیم یادآور"
},
"gauge": {
"currentSoilMoisture": "رطوبت فعلی خاک",
"target": "هدف",
"currentValueExample": "۴۲٪",
"targetValueExample": "۴۲٪"
},
"instructionStats": {
"waterAmount": {
"label": "مقدار آب",
"hint": "برای سطح انتخاب شده"
},
"duration": {
"label": "مدت زمان",
"hint": "زمان تقریبی هر نوبت آبیاری"
},
"frequency": {
"label": "تناوب",
"hint": "تعداد دفعات پیشنهادی بر اساس تراز آب و مرحله رشد"
},
"bestWindow": {
"label": "بهترین بازه",
"hint": "بهترین زمان اجرا برای کاهش تلفات تبخیر",
"example": "اوایل صبح یا نزدیک غروب"
}
},
"recommendation": {
"instructionDetailsTitle": "جزئیات دستور آبیاری",
"instructionDetailsSubtitle": "خلاصه ای سریع از دستور اجرایی آبیاری و شاخص اصلی موثر بر این توصیه.",
"soilMoistureDriverTitle": "محرک رطوبت خاک",
"soilMoistureDriverSubtitle": "رطوبت فعلی خاک با مقدار هدف مقایسه می شود تا منطق توصیه مشخص باشد.",
"waterBalanceTitle": "تراز آب و نیاز روزانه",
"executionWindow": "بازه اجرا",
"cropProfileTitle": "پروفایل گیاه",
"kcInitial": "Kc شروع",
"kcMid": "Kc میانی",
"kcEnd": "Kc پایانی",
"executionStepsTitle": "مراحل و دستورالعمل اجرا",
"warningsTitle": "هشدارها و نکات مهم",
"generatedTitle": "نسخه آبیاری هوشمند {plant}",
"generatedSubtitle": "پیشنهاد ویژه برای مرحله {stage}",
"durationPerTurn": "{value} دقیقه در هر نوبت",
"frequencyPerWeek": "{value} نوبت در هفته",
"weatherBasedWindow": "طبق وضعیت آب و هوا"
},
"history": {
"title": "تاریخچه توصیه های آبیاری",
"subtitle": "همه توصیه های قبلی مزرعه را اینجا ببینید و گزارش کامل هرکدام را باز کنید.",
"viewReport": "مشاهده گزارش",
"empty": "هنوز توصیه ای برای این مزرعه ثبت نشده است.",
"columns": {
"requestedAt": "تاریخ ثبت",
"cropStage": "محصول / مرحله رشد",
"method": "روش آبیاری",
"status": "وضعیت",
"report": "گزارش"
}
},
"details": {
"waterBalanceTitle": "جزئیات تراز آب {date}",
"waterBalanceContent": "ET0: {et0} {mm}\nETc: {etc} {mm}\nبارش موثر: {rainfall} {mm}\nآبیاری ناخالص: {gross} {mm}\nبازه اجرا: {timing}",
"addReminder": "افزودن به یادآور",
"understood": "متوجه شدم"
},
"errors": {
"noFarm": "ابتدا یک مزرعه انتخاب کنید.",
"noSelectedPlants": "برای این مزرعه هنوز محصولی انتخاب نشده است.",
"selectedPlantsFailed": "خطا در دریافت محصولات انتخاب شده مزرعه",
"generateFailed": "خطا در تولید توصیه آبیاری",
"historyFailed": "خطا در دریافت تاریخچه توصیه های آبیاری",
"reportFailed": "خطا در دریافت گزارش توصیه آبیاری",
"pendingResponse": "درخواست ثبت شد اما پاسخ نهایی هنوز آماده نیست."
}
}
}
+94
View File
@@ -112,5 +112,99 @@
"economicOverview": "Aperçu économique",
"sensorSection": "Capteurs",
"sensor7In1": "Capteur de sol 7-en-1"
},
"irrigation": {
"title": "Recommandation intelligente d'irrigation",
"subtitle": "Selectionnez la culture et le stade de croissance pour generer la recommandation d'irrigation de cette ferme a partir des donnees du backend.",
"generateCta": "Generer la recommandation",
"generating": "Generation de la recommandation d'irrigation...",
"loadingCard": "Analyse des donnees et generation du plan d'irrigation...",
"farmIrrigationMethod": "Methode d'irrigation enregistree sur la ferme : {method}",
"growthStage": {
"title": "Stade de croissance"
},
"plantSelection": {
"title": "Selection de la culture"
},
"units": {
"mm": "mm",
"literShort": "L"
},
"status": {
"fetchingReport": "Recuperation du rapport de recommandation"
},
"actions": {
"saveVersion": "Enregistrer cette version",
"setReminder": "Definir un rappel"
},
"gauge": {
"currentSoilMoisture": "HUMIDITE ACTUELLE DU SOL",
"target": "Objectif"
},
"instructionStats": {
"waterAmount": {
"label": "Quantite d'eau",
"hint": "sur la surface selectionnee"
},
"duration": {
"label": "Duree",
"hint": "Duree estimee pour chaque cycle d'irrigation"
},
"frequency": {
"label": "Frequence",
"hint": "Rythme recommande selon le bilan hydrique et le stade de croissance"
},
"bestWindow": {
"label": "Meilleure plage",
"hint": "Horaire prefere pour reduire les pertes par evaporation"
}
},
"recommendation": {
"instructionDetailsTitle": "Details des instructions",
"instructionDetailsSubtitle": "Un apercu rapide des instructions d'irrigation et de l'indicateur qui pilote cette recommandation.",
"soilMoistureDriverTitle": "Indicateur d'humidite du sol",
"soilMoistureDriverSubtitle": "L'humidite actuelle du sol est comparee au seuil cible pour justifier la recommandation finale.",
"waterBalanceTitle": "Bilan hydrique et besoin quotidien",
"executionWindow": "Fenetre d'execution",
"cropProfileTitle": "Profil de la culture",
"kcInitial": "Kc initial",
"kcMid": "Kc milieu",
"kcEnd": "Kc final",
"executionStepsTitle": "Etapes et instructions d'execution",
"warningsTitle": "Avertissements et notes importantes",
"generatedTitle": "Plan d'irrigation intelligent pour {plant}",
"generatedSubtitle": "Recommandation speciale pour le stade {stage}",
"durationPerTurn": "{value} minutes par cycle",
"frequencyPerWeek": "{value} fois par semaine",
"weatherBasedWindow": "Selon les conditions meteo"
},
"history": {
"title": "Historique des recommandations d'irrigation",
"subtitle": "Consultez toutes les recommandations precedentes de cette ferme et ouvrez le rapport complet de chacune.",
"viewReport": "Voir le rapport",
"empty": "Aucune recommandation n'a encore ete enregistree pour cette ferme.",
"columns": {
"requestedAt": "Date",
"cropStage": "Culture / Stade",
"method": "Methode d'irrigation",
"status": "Statut",
"report": "Rapport"
}
},
"details": {
"waterBalanceTitle": "Details du bilan hydrique {date}",
"waterBalanceContent": "ET0 : {et0} {mm}\nETc : {etc} {mm}\nPluie efficace : {rainfall} {mm}\nIrrigation brute : {gross} {mm}\nFenetre d'execution : {timing}",
"addReminder": "Ajouter au rappel",
"understood": "Compris"
},
"errors": {
"noFarm": "Veuillez d'abord selectionner une ferme.",
"noSelectedPlants": "Aucune culture n'a encore ete selectionnee pour cette ferme.",
"selectedPlantsFailed": "Echec du chargement des cultures selectionnees de la ferme",
"generateFailed": "Echec de la generation de la recommandation d'irrigation",
"historyFailed": "Echec du chargement de l'historique des recommandations d'irrigation",
"reportFailed": "Echec du chargement du rapport de recommandation d'irrigation",
"pendingResponse": "La requete a ete enregistree, mais la reponse finale n'est pas encore prete."
}
}
}
@@ -41,16 +41,19 @@ export interface IrrigationConfigResponse {
}
export interface IrrigationPlan {
frequencyPerWeek: number | string;
durationMinutes: number | string;
bestTimeOfDay: string;
moistureLevel: number | string;
frequencyPerWeek?: number | string;
durationMinutes?: number | string;
bestTimeOfDay?: string;
moistureLevel?: number | string;
warning?: string;
[key: string]: unknown;
}
export interface IrrigationRecommendPayload {
farm_uuid: string;
farm_uuid?: string;
sensor_uuid?: string;
crop_id?: string;
plant_name?: string;
growth_stage?: string;
irrigation_method_id?: string;
farm_data?: Partial<FarmInfo>;
@@ -78,13 +81,57 @@ export interface WaterBalance {
daily: WaterBalanceDailyEntry[];
crop_profile?: WaterBalanceCropProfile;
active_kc?: number;
[key: string]: unknown;
}
export interface IrrigationRecommendationTimelineItem {
step_number: number;
title: string;
description: string;
}
export interface IrrigationRecommendationSection {
title: string;
icon?: string;
type: "schedule" | "warning" | "tip" | "method" | string;
content: string;
}
export interface IrrigationRecommendationResult {
recommendation_uuid?: string;
crop_id?: string;
plant_name?: string;
growth_stage?: string;
irrigation_method_name?: string;
status?: string;
status_label?: string;
plan: IrrigationPlan;
raw_response?: string;
water_balance?: WaterBalance;
status?: string;
timeline?: IrrigationRecommendationTimelineItem[];
sections?: IrrigationRecommendationSection[];
}
export interface IrrigationRecommendationHistoryItem {
recommendation_uuid: string;
crop_id?: string;
plant_name?: string;
growth_stage?: string;
irrigation_method_name?: string;
status: "pending_confirmation" | "in_progress" | "completed" | "error" | string;
status_label: string;
requested_at: string;
}
export interface IrrigationRecommendationHistoryPagination {
page: number;
page_size: number;
total_pages: number;
total_items: number;
has_next: boolean;
has_previous: boolean;
next: string | null;
previous: string | null;
}
export interface WaterStressPayload {
@@ -120,10 +167,16 @@ export type IrrigationRecommendResponse =
| RecommendationTaskInitResponse;
interface ApiResponse<T> {
status: string;
code?: number;
msg?: string;
status?: string;
data: T;
}
interface PaginatedApiResponse<T> extends ApiResponse<T> {
pagination: IrrigationRecommendationHistoryPagination;
}
async function unwrap<T>(promise: Promise<ApiResponse<T>>): Promise<T> {
const res = await promise;
return res.data;
@@ -142,9 +195,7 @@ function normalizeRecommendationResult(
export const irrigationRecommendationService = {
listMethods(): Promise<IrrigationMethod[]> {
return unwrap(
apiClient.get<ApiResponse<IrrigationMethod[]>>(`${PREFIX}/`),
);
return unwrap(apiClient.get<ApiResponse<IrrigationMethod[]>>(`${PREFIX}/`));
},
getConfig(farmUuid: string): Promise<IrrigationConfigResponse> {
@@ -173,6 +224,36 @@ export const irrigationRecommendationService = {
);
},
async getRecommendationsHistory(
farmUuid: string,
page = 1,
pageSize = 10,
): Promise<{
data: IrrigationRecommendationHistoryItem[];
pagination: IrrigationRecommendationHistoryPagination;
}> {
const response = await apiClient.get<
PaginatedApiResponse<IrrigationRecommendationHistoryItem[]>
>(
`${RECOMMEND_PREFIX}/recommendations/?farm_uuid=${encodeURIComponent(farmUuid)}&page=${page}&page_size=${pageSize}`,
);
return {
data: response.data,
pagination: response.pagination,
};
},
getRecommendationDetail(
recommendationUuid: string,
): Promise<IrrigationRecommendationResult> {
return unwrap(
apiClient.get<ApiResponse<IrrigationRecommendationResult>>(
`${RECOMMEND_PREFIX}/recommendations/${encodeURIComponent(recommendationUuid)}/`,
),
).then(normalizeRecommendationResult);
},
getWaterStress(payload?: WaterStressPayload): Promise<WaterStressResponse> {
return unwrap(
apiClient.post<ApiResponse<WaterStressResponse>>(
File diff suppressed because it is too large Load Diff