feat: implement service mode completion for nobat724_front
- Add task for completing service mode in clinicpro with detailed objectives and acceptance criteria. - Create architecture documentation for task 00b, outlining involved components and necessary changes. - Develop checklist for task 00b to ensure all requirements are met. - Document implementation notes for task 00b, emphasizing API contract checks and design system adherence. - Update task documentation for task 00b, specifying goals and current issues with service mode.
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
# نکات پیادهسازی — تسک ۰۰ب
|
||||
|
||||
## ۱. اول قرارداد پاسخ را بررسی کن، بعد کد بزن
|
||||
|
||||
سه چیز را پیش از شروع تأیید کن:
|
||||
|
||||
```bash
|
||||
# ۱. پاسخ appointments/user چه فیلدهایی دارد؟
|
||||
curl -s -H "Authorization: Bearer $TOKEN" \
|
||||
https://clinic-pro.ddev.site/api/v1/appointments/user | jq '.data[0] | keys'
|
||||
|
||||
# ۲. start_times هر آیتم end_time دارد؟
|
||||
curl -s "https://clinic-pro.ddev.site/api/v1/appointment-service-slots?doctor_uuid=…&date=…&service_item_uuids[]=…" \
|
||||
| jq '.data.start_times[0]'
|
||||
|
||||
# ۳. total_duration_minutes و buffer_minutes در پاسخ هستند؟
|
||||
```
|
||||
|
||||
اگر `service_items` یا `service_total_minutes` در پاسخ `appointments/user` نیست،
|
||||
**به تسک ۰۰ برگردان** — سریالایزر آنجا اصلاح میشود، نه اینکه اینجا از endpoint دیگری
|
||||
دور بزنیم.
|
||||
|
||||
## ۲. رنگها را از همسایه کپی کن، نه از حافظه
|
||||
|
||||
```bash
|
||||
# ببین مرحلهٔ قبلی رزرو چه کلاسی میزند
|
||||
grep -n "className" components/appointment/location/index.js | head -30
|
||||
grep -n "className" components/appointment/date/index.js | head -30
|
||||
```
|
||||
|
||||
هدف: کامپوننت انتخاب سرویس **از بقیهٔ مراحل قابل تشخیص نباشد**. اگر بقیه `bg-white`
|
||||
میزنند و توکن ندارند، تو هم توکن جدید نساز — همان کاری را بکن که آنها میکنند،
|
||||
و اگر دارکمود در آنها هم شکسته است، این یک مسئلهٔ جدا است که در چکلیست ⚠️ ثبت
|
||||
میشود، نه اینکه در این تسک کل صفحهٔ رزرو بازطراحی شود.
|
||||
|
||||
**دامنه را گسترش نده.** فقط `service/index.js` که خودمان اضافه کردیم و از بقیه منحرف است.
|
||||
|
||||
## ۳. `fallbackSum` موقت است و باید هشدار بدهد
|
||||
|
||||
```js
|
||||
const minutes = data?.total_duration_minutes ?? (() => {
|
||||
console.warn('[booking] total_duration_minutes missing — falling back to client sum');
|
||||
return fallbackSum(draft, services);
|
||||
})();
|
||||
```
|
||||
|
||||
بدون `console.warn`، بکاندی که فیلد را نمیدهد بیصدا کار میکند و شش ماه بعد کسی
|
||||
نمیفهمد چرا مدت با نوبت نمیخواند. حذف `fallbackSum` پس از deploy تسک ۰۰ یک ردیف
|
||||
⏳ در چکلیست است با تسک مقصد مشخص.
|
||||
|
||||
## ۴. آستانهٔ شکاف: ۶۰ دقیقه، با دلیل
|
||||
|
||||
```js
|
||||
const GAP_THRESHOLD_MIN = 60;
|
||||
```
|
||||
|
||||
شیفت صبح/عصر معمولاً ۲-۳ ساعت فاصله دارد. یک نوبت ۹۰ دقیقهای هم میتواند شکاف ۹۰
|
||||
دقیقهای بسازد بدون اینکه شیفت جدا باشد — پس آستانه نباید کمتر از مدت نوبت باشد:
|
||||
|
||||
```js
|
||||
const threshold = Math.max(GAP_THRESHOLD_MIN, durationMin);
|
||||
```
|
||||
|
||||
این خط را فراموش نکن، وگرنه نوبتهای بلند به تبهای تکعضوی تقسیم میشوند.
|
||||
|
||||
هیوریستیک است و در کامنت باید بنویسی: راه دقیق، گروهبندی از سمت بکاند است که تسک ۰۶
|
||||
در endpoint جدید میدهد.
|
||||
|
||||
## ۵. شرط `&&` روی فیلدهای سرویسی در پنل
|
||||
|
||||
```jsx
|
||||
{turn.service_items?.length > 0 && ( … )}
|
||||
```
|
||||
|
||||
نه `turn.service_items.map(...)` خالی. نوبت اسلاتی این فیلد را ندارد و بدون شرط، کارت
|
||||
همهٔ نوبتهای اسلاتی کرش میکند — یعنی کل پنل کاربر میشکند، نه فقط یک خط.
|
||||
|
||||
تست: پنل کاربری که **فقط** نوبت اسلاتی دارد باید بدون هیچ تغییری رندر شود.
|
||||
|
||||
## ۶. جابهجایی: مودال موجود، انتخابگر موجود
|
||||
|
||||
```
|
||||
ButtonData.js → دکمهٔ «جابهجایی» → isTurnsDetails/modal/index.js
|
||||
└─ components/appointment/date/ بازاستفاده
|
||||
```
|
||||
|
||||
انتخابگر تاریخ/ساعت جدید نساز. کامپوننت `date/` از قبل هر دو حالت را میشناسد
|
||||
(`adaptSlots` و `adaptServiceSlots`) و همان را با props متفاوت صدا بزن.
|
||||
|
||||
## ۷. خطای بکاند را نمایش بده، نه پیام عمومی
|
||||
|
||||
```js
|
||||
// ❌
|
||||
catch { toast.error('خطایی رخ داد'); }
|
||||
|
||||
// ✅
|
||||
catch (err) {
|
||||
const msg = err?.response?.data?.errors?.[0]?.message ?? 'خطایی رخ داد';
|
||||
toast.error(msg);
|
||||
refetchSlots(); // ← فهرست زمانها بهروز شود
|
||||
}
|
||||
```
|
||||
|
||||
`ERR_SLOT_TAKEN` پیام فارسی دقیق دارد («این بازه زمانی قبلاً رزرو شده است»). نشان دادن
|
||||
«خطای نامشخص» یعنی بیمار همان دکمه را ده بار میزند. `refetchSlots()` بعد از خطای تداخل
|
||||
اجباری است.
|
||||
|
||||
## ۸. edge case ها
|
||||
|
||||
| حالت | رفتار درست |
|
||||
|---|---|
|
||||
| محل سرویسی بدون سرویس `bookable` | پیام روشن + پیشنهاد محل دیگر اگر باشد |
|
||||
| پزشک اسلاتی در مطب، سرویسی در کلینیک | تعویض محل، مرحلهٔ سرویس را ظاهر/پنهان میکند و انتخابها باطل میشوند (رفتار موجود `changeLocation`) |
|
||||
| `start_times` خالی | پیام دلیلدار، نه فهرست خالی |
|
||||
| `total_duration_minutes` غایب | `fallbackSum` + `console.warn` |
|
||||
| نوبت سرویسی قدیمی بدون `service_items` | نام «—»، مدت اگر هست نمایش، بدون کرش |
|
||||
| پنل کاربری فقط با نوبت اسلاتی | بیتبهبیت مثل امروز |
|
||||
| نوبت رزرو (`is_reserve`) در پنل | مدت نمایش داده نشود (زمان ندارد)، فقط سرویسها |
|
||||
| جابهجایی به زمان اشغالشده | پیام فارسی بکاند + `refetch` |
|
||||
| دارکمود در پنل (`class`) و صفحات عمومی (`data-theme`) | هر دو بررسی شوند — دو مکانیزم متفاوتاند |
|
||||
| یک سرویس با `duration_minutes = null` | بکاند `422` میدهد؛ UI پیامش را نشان دهد و آن سرویس را برجسته کند |
|
||||
|
||||
## ۹. تست
|
||||
|
||||
پروژه تست خودکار محدودی دارد. سناریوهای دستی اجباری (در چکلیست ثبت شوند):
|
||||
|
||||
```
|
||||
۱. رزرو سرویسی کامل: انتخاب محل سرویسی → سرویس → روز → ساعت → ثبت → پیامک
|
||||
۲. همان مسیر در دارکمود (صفحات عمومی، data-theme)
|
||||
۳. رزرو اسلاتی کامل — باید بیتبهبیت مثل قبل باشد
|
||||
۴. پزشک با دو شیفت در حالت سرویسی → دو تب زمانی با برچسب واقعی
|
||||
۵. پنل کاربر با نوبت اسلاتی تنها → بدون تغییر
|
||||
۶. پنل کاربر با نوبت سرویسی → سرویسها و مدت دیده میشود
|
||||
۷. پنل کاربر در دارکمود (class)
|
||||
۸. جابهجایی نوبت سرویسی → مدت حفظ میشود
|
||||
۹. جابهجایی به زمان اشغالشده → پیام فارسی + refetch
|
||||
۱۰. موبایل: هر ده مورد بالا، بدون اسکرول افقی
|
||||
```
|
||||
|
||||
اگر تست خودکار اضافه میکنی، `adaptServiceSlots` تابع خالص است و بهترین کاندید:
|
||||
|
||||
```
|
||||
tests/appointmentSlots.test.js
|
||||
- یک شیفت → یک گروه
|
||||
- دو شیفت با شکاف ۳ ساعت → دو گروه با برچسب درست
|
||||
- نوبت ۹۰ دقیقهای با شکاف ۹۰ دقیقه → یک گروه (آستانه = max(60, duration))
|
||||
- start_times خالی → []
|
||||
- end_time از پاسخ میآید، نه محاسبه
|
||||
```
|
||||
|
||||
## ۱۰. مستندات
|
||||
|
||||
`nobat724_front/CLAUDE.md` یک بخش کوتاه «حالتهای نوبتدهی» بگیرد: `slot` و `service`،
|
||||
اینکه per محل تعیین میشوند، و اینکه `adaptSlots`/`adaptServiceSlots` نقطهٔ تفکیکاند.
|
||||
|
||||
در `clinicpro/docs/api/appointment.md` یادداشت کن که گروهبندی شیفت در حالت سرویسی
|
||||
هیوریستیک سمت فرانت است و راه دقیقش endpoint تسک ۰۶ است.
|
||||
Reference in New Issue
Block a user