UPDATE
This commit is contained in:
@@ -0,0 +1,381 @@
|
||||
# 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
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user