382 lines
9.8 KiB
Markdown
382 lines
9.8 KiB
Markdown
|
|
# Farmer Calendar Backend Requirements
|
||
|
|
|
||
|
|
این فایل قرارداد کامل دادهای برای صفحه `farmer-calendar` را توضیح میدهد؛ یعنی هر چیزی که فرانت برای نمایش، ساخت، ویرایش و حذف رویدادهای تقویم نیاز دارد باید از بکاند دریافت یا به بکاند ارسال کند.
|
||
|
|
|
||
|
|
## Scope
|
||
|
|
|
||
|
|
این مستند بر اساس این فایلها تهیه شده است:
|
||
|
|
|
||
|
|
- `src/views/dashboards/farm/FarmerCalendarPage.tsx`
|
||
|
|
- `src/views/dashboards/farm/FarmerCalendarEventModal.tsx`
|
||
|
|
- `src/views/dashboards/farm/FarmerCalendarEventDetails.tsx`
|
||
|
|
- `src/views/apps/calendar/Calendar.tsx`
|
||
|
|
- `src/redux-store/slices/calendar.ts`
|
||
|
|
- `src/libs/api/services/eventService.ts`
|
||
|
|
|
||
|
|
## Frontend Features Covered
|
||
|
|
|
||
|
|
بکاند باید از این قابلیتهای صفحه پشتیبانی کند:
|
||
|
|
|
||
|
|
- نمایش لیست رویدادهای تقویم
|
||
|
|
- فیلتر رویدادها بر اساس بازه زمانی و نوع تقویم
|
||
|
|
- نمایش جزییات رویداد
|
||
|
|
- ساخت رویداد جدید
|
||
|
|
- ویرایش رویداد
|
||
|
|
- حذف رویداد
|
||
|
|
- دریافت جداگانهی لیست `tag`ها برای فرم ساخت/ویرایش
|
||
|
|
- پشتیبانی از drag/drop و resize رویدادها در تقویم
|
||
|
|
|
||
|
|
## Domain Model
|
||
|
|
|
||
|
|
هر رویداد تقویم باید حداقل ساختار زیر را داشته باشد:
|
||
|
|
|
||
|
|
```ts
|
||
|
|
type CalendarEvent = {
|
||
|
|
id: string;
|
||
|
|
title: string;
|
||
|
|
description: string;
|
||
|
|
deadline?: number | null;
|
||
|
|
tags: string[];
|
||
|
|
start: string;
|
||
|
|
end: string;
|
||
|
|
extendedProps?: Record<string, unknown>;
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
## Required Event Fields For Frontend
|
||
|
|
|
||
|
|
فیلدهای زیر برای عملکرد درست فرانت لازم هستند:
|
||
|
|
|
||
|
|
| Field | Type | Required | Used For |
|
||
|
|
|---|---|---:|---|
|
||
|
|
| `id` | `string` | yes | شناسایی رویداد برای edit/delete/update |
|
||
|
|
| `title` | `string` | yes | عنوان رویداد در تقویم، کارتها، مودال جزییات |
|
||
|
|
| `description` | `string` | no but recommended | نمایش توضیح در کارتها و جزییات |
|
||
|
|
| `start` | `ISO 8601 string` | yes | نمایش زمان شروع، تقویم، محاسبه امروز/این هفته |
|
||
|
|
| `end` | `ISO 8601 string` | yes | نمایش بازه زمانی، resize/drop |
|
||
|
|
| `tags` | `string[]` | yes | نمایش tag در جزییات، انتخاب مقدار در فرم |
|
||
|
|
| `deadline` | `number` | no | فعلا در state نگهداری میشود، بهتر است برگردد |
|
||
|
|
| `extendedProps` | `object` | no | برای توسعه آینده و سازگاری با FullCalendar |
|
||
|
|
|
||
|
|
## Endpoints
|
||
|
|
|
||
|
|
### 1) List Events
|
||
|
|
|
||
|
|
برای لود اولیهی صفحه و رفرش رویدادها.
|
||
|
|
|
||
|
|
`GET /api/events`
|
||
|
|
|
||
|
|
#### Query Params
|
||
|
|
|
||
|
|
| Param | Type | Required | Description |
|
||
|
|
|---|---|---:|---|
|
||
|
|
| `start` | `string` | no | شروع بازه به فرمت ISO 8601 |
|
||
|
|
| `end` | `string` | no | پایان بازه به فرمت ISO 8601 |
|
||
|
|
|
||
|
|
#### Success Response
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"events": [
|
||
|
|
{
|
||
|
|
"id": "evt_101",
|
||
|
|
"title": "آبیاری بلوک شمالی",
|
||
|
|
"description": "کنترل فشار و مدت زمان آبیاری",
|
||
|
|
"deadline": 1734942600,
|
||
|
|
"tags": ["آبیاری"],
|
||
|
|
"start": "2025-02-24T06:30:00Z",
|
||
|
|
"end": "2025-02-24T08:00:00Z",
|
||
|
|
"extendedProps": {}
|
||
|
|
}
|
||
|
|
]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Frontend Notes
|
||
|
|
|
||
|
|
- اگر `events` خالی باشد باید `[]` برگردد، نه `null`
|
||
|
|
- تاریخها باید قابل parse شدن با `new Date(...)` و `parseISO(...)` باشند
|
||
|
|
- `start` و `end` برای همه رویدادها لازماند
|
||
|
|
|
||
|
|
### 2) Get Event Details
|
||
|
|
|
||
|
|
برای سناریوهای آینده یا lazy loading جزییات.
|
||
|
|
|
||
|
|
`GET /api/events/:id`
|
||
|
|
|
||
|
|
#### Success Response
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"event": {
|
||
|
|
"id": "evt_101",
|
||
|
|
"title": "آبیاری بلوک شمالی",
|
||
|
|
"description": "کنترل فشار و مدت زمان آبیاری",
|
||
|
|
"deadline": 1734942600,
|
||
|
|
"tags": ["آبیاری"],
|
||
|
|
"start": "2025-02-24T06:30:00Z",
|
||
|
|
"end": "2025-02-24T08:00:00Z",
|
||
|
|
"extendedProps": {}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3) Create Event
|
||
|
|
|
||
|
|
برای ساخت تسک/رویداد روزانهی جدید.
|
||
|
|
|
||
|
|
`POST /api/events`
|
||
|
|
|
||
|
|
#### Request Body
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"title": "بازدید آفت در گلخانه",
|
||
|
|
"description": "بررسی وضعیت برگها و ثبت گزارش",
|
||
|
|
"deadline": 1734971400,
|
||
|
|
"tags": ["آفت"],
|
||
|
|
"start": "2025-02-24T14:00:00Z",
|
||
|
|
"end": "2025-02-24T15:00:00Z",
|
||
|
|
"extendedProps": {}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Required Create Fields
|
||
|
|
|
||
|
|
- `title`
|
||
|
|
- `start`
|
||
|
|
- `end`
|
||
|
|
|
||
|
|
#### Success Response
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"event": {
|
||
|
|
"id": "evt_102",
|
||
|
|
"title": "بازدید آفت در گلخانه",
|
||
|
|
"description": "بررسی وضعیت برگها و ثبت گزارش",
|
||
|
|
"deadline": 1734971400,
|
||
|
|
"tags": ["آفت"],
|
||
|
|
"start": "2025-02-24T14:00:00Z",
|
||
|
|
"end": "2025-02-24T15:00:00Z",
|
||
|
|
"extendedProps": {}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4) Update Event
|
||
|
|
|
||
|
|
برای ویرایش دستی، drag/drop و resize.
|
||
|
|
|
||
|
|
`PUT /api/events/:id`
|
||
|
|
|
||
|
|
#### Request Body
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"title": "بازدید آفت در گلخانه",
|
||
|
|
"description": "اولویت بالا",
|
||
|
|
"deadline": 1734971400,
|
||
|
|
"tags": ["آفت", "فوری"],
|
||
|
|
"start": "2025-02-24T15:00:00Z",
|
||
|
|
"end": "2025-02-24T16:00:00Z",
|
||
|
|
"extendedProps": {}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Success Response
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"event": {
|
||
|
|
"id": "evt_102",
|
||
|
|
"title": "بازدید آفت در گلخانه",
|
||
|
|
"description": "اولویت بالا",
|
||
|
|
"deadline": 1734971400,
|
||
|
|
"tags": ["آفت", "فوری"],
|
||
|
|
"start": "2025-02-24T15:00:00Z",
|
||
|
|
"end": "2025-02-24T16:00:00Z",
|
||
|
|
"extendedProps": {}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Important Update Notes
|
||
|
|
|
||
|
|
- این endpoint باید برای هر دو حالت `form edit` و `calendar drag/resize` جواب بدهد
|
||
|
|
- تغییر `start` و `end` باید سریع و idempotent باشد
|
||
|
|
|
||
|
|
### 5) Delete Event
|
||
|
|
|
||
|
|
`DELETE /api/events/:id`
|
||
|
|
|
||
|
|
#### Success Response
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"success": true
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Separate Tags API
|
||
|
|
|
||
|
|
طبق نیاز این صفحه، لیست `tag`ها نباید از `events` استخراج شود و باید از یک API جداگانه دریافت شود.
|
||
|
|
|
||
|
|
### 6) List Event Tags
|
||
|
|
|
||
|
|
`GET /api/events/tags`
|
||
|
|
|
||
|
|
#### Purpose
|
||
|
|
|
||
|
|
- پر کردن `select` مربوط به tag در فرم ساخت/ویرایش
|
||
|
|
- جلوگیری از وابستگی UI به استخراج `tags` از event list
|
||
|
|
- بهینهتر شدن لود مودال افزودن رویداد
|
||
|
|
|
||
|
|
#### Success Response
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"tags": [
|
||
|
|
{
|
||
|
|
"id": "tag_irrigation",
|
||
|
|
"label": "آبیاری",
|
||
|
|
"value": "آبیاری"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "tag_pest",
|
||
|
|
"label": "آفت",
|
||
|
|
"value": "آفت"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"id": "tag_harvest",
|
||
|
|
"label": "برداشت",
|
||
|
|
"value": "برداشت"
|
||
|
|
}
|
||
|
|
]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Minimum Accepted Alternative
|
||
|
|
|
||
|
|
اگر نخواهید آبجکت کامل برگردانید، این ساختار هم برای فرانت کافی است:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"tags": ["آبیاری", "آفت", "برداشت"]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Recommendation
|
||
|
|
|
||
|
|
فرمت آبجکتی بهتر است، چون بعدا این قابلیتها را سادهتر میکند:
|
||
|
|
|
||
|
|
- مرتبسازی
|
||
|
|
- disabled state
|
||
|
|
- رنگ یا آیکن برای هر tag
|
||
|
|
- localization
|
||
|
|
|
||
|
|
## Error Handling
|
||
|
|
|
||
|
|
برای همه endpointها بهتر است خطاها ساختار ثابت داشته باشند:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"code": "EVENT_VALIDATION_ERROR",
|
||
|
|
"message": "Invalid event payload",
|
||
|
|
"details": {
|
||
|
|
"start": "start is required"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
فرانت فعلی حداقل به یک `message` قابلنمایش نیاز دارد.
|
||
|
|
|
||
|
|
## Validation Rules Recommended
|
||
|
|
|
||
|
|
- `title` نباید خالی باشد
|
||
|
|
- `start` باید تاریخ معتبر باشد
|
||
|
|
- `end` باید تاریخ معتبر باشد
|
||
|
|
- `end` نباید قبل از `start` باشد
|
||
|
|
- `tags` اگر موجود است باید آرایهای از string باشد
|
||
|
|
|
||
|
|
## Date/Time Requirements
|
||
|
|
|
||
|
|
- فرمت ترجیحی: `ISO 8601 UTC`, مثال: `2025-02-24T06:30:00Z`
|
||
|
|
- timezone باید در پاسخها صریح و قابل پیشبینی باشد
|
||
|
|
- بکاند نباید تاریخ مبهم بدون timezone برگرداند
|
||
|
|
|
||
|
|
## What Frontend Actually Renders Today
|
||
|
|
|
||
|
|
این فیلدها همین الان در UI استفاده میشوند:
|
||
|
|
|
||
|
|
- `title`
|
||
|
|
- `description`
|
||
|
|
- `start`
|
||
|
|
- `end`
|
||
|
|
- `tags[0]`
|
||
|
|
|
||
|
|
این فیلدها فعلا بیشتر برای سازگاری یا توسعه بعدی نگهداری میشوند:
|
||
|
|
|
||
|
|
- `deadline`
|
||
|
|
- `extendedProps`
|
||
|
|
|
||
|
|
## Performance Recommendations
|
||
|
|
|
||
|
|
- `GET /api/events` باید pagination یا date-range filtering را پشتیبانی کند، حتی اگر فعلا فرانت از آن بهصورت کامل استفاده نکند
|
||
|
|
- `GET /api/events/tags` باید سبک و cacheable باشد
|
||
|
|
- پاسخ `GET /api/events/tags` بهتر است کوچک و بدون payload اضافی باشد
|
||
|
|
|
||
|
|
## Final Backend Checklist
|
||
|
|
|
||
|
|
- `GET /api/events`
|
||
|
|
- `GET /api/events/:id`
|
||
|
|
- `POST /api/events`
|
||
|
|
- `PUT /api/events/:id`
|
||
|
|
- `DELETE /api/events/:id`
|
||
|
|
- `GET /api/events/tags`
|
||
|
|
- پشتیبانی از `tags` به صورت آرایه
|
||
|
|
- بازگرداندن تاریخها با فرمت ISO 8601
|
||
|
|
|
||
|
|
## Suggested Stable Response Shapes
|
||
|
|
|
||
|
|
اگر بخواهید قرارداد بکاند کاملا پایدار و توسعهپذیر باشد، این دو response shape پیشنهاد میشوند:
|
||
|
|
|
||
|
|
### Events List
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"events": [
|
||
|
|
{
|
||
|
|
"id": "evt_101",
|
||
|
|
"title": "آبیاری بلوک شمالی",
|
||
|
|
"description": "کنترل فشار و مدت زمان آبیاری",
|
||
|
|
"deadline": 1734942600,
|
||
|
|
"tags": ["آبیاری"],
|
||
|
|
"start": "2025-02-24T06:30:00Z",
|
||
|
|
"end": "2025-02-24T08:00:00Z",
|
||
|
|
"extendedProps": {}
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"meta": {
|
||
|
|
"total": 1
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Tags List
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"tags": [
|
||
|
|
{
|
||
|
|
"id": "tag_irrigation",
|
||
|
|
"label": "آبیاری",
|
||
|
|
"value": "آبیاری"
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"meta": {
|
||
|
|
"total": 1
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|