feat(admin): service-aware time picking on the appointment edit page
In service mode the page now mounts the existing ServiceSlotPicker and hides the three free-form time inputs plus the single-service select: a 45-minute service could previously be shortened to 20 and the next patient would sit on top of it. Hidden rather than disabled — a disabled field reads as "you must do something here". Saving splits in two: the service-aware endpoint takes the time and services (the client sends no duration), then the usual PATCH carries deposit, insurance, status and note without slot_start/slot_end/version, since the reschedule already advanced the optimistic-lock version. Booking mode is read from the appointment's own schedule via an explicit clinic_uuid, not from the panel's current environment: a doctor can be slot-based in their office and service-based in a clinic. That required exposing clinic_uuid in Appointment::toArray(), which was missing. appointment-service-slots accepts exclude_appointment_uuid, gated on canManage of that appointment — an ungated parameter would let anyone fabricate availability. ServiceSlotPicker gained two optional props; its existing callers pass neither and are unaffected. Its reset-on-doctor-change effect now skips the first run, which would otherwise wipe the initial selection. Task: docs/new_feture/taskes/task-00-service-mode-completion/ Slot-mode contract: unchanged (--group=slot-mode-frozen green) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# چکلیست — تسک ۰۰ (تکمیل نوبتدهی سرویسی در clinicpro)
|
||||
|
||||
**وضعیت کلی:** 🔄 در حال انجام — قابلیت ۶ از ۱۰ تمام شد (بکاند کامل؛ مانده: UI، backfill، مستندات)
|
||||
**وضعیت کلی:** 🔄 در حال انجام — قابلیت ۷ از ۱۰ تمام شد (مانده: ReserveAppointmentsPage، backfill، مستندات)
|
||||
**آخرین بازبینی:** ۱۴۰۵/۰۵/۰۸
|
||||
|
||||
قواعد: [_shared/definition-of-done.md](../_shared/definition-of-done.md) ·
|
||||
@@ -60,24 +60,24 @@ UI: [_shared/ui-conventions.md](../_shared/ui-conventions.md)
|
||||
|
||||
| # | مورد | وضعیت | یادداشت |
|
||||
|---|---|---|---|
|
||||
| ۳.۱ | `AppointmentEditPage`: حالت سرویسی `ServiceSlotPicker` نشان میدهد | ⏳ | |
|
||||
| ۳.۲ | `AppointmentEditPage`: حالت اسلاتی **دقیقاً** رفتار امروز | ⏳ | سه فیلد ساعت |
|
||||
| ۳.۳ | ورودی دستی ساعت در حالت سرویسی **پنهان**، نه disabled | ⏳ | |
|
||||
| ۳.۴ | `ServiceSlotPicker` موجود بازاستفاده شد؛ نسخهٔ موازی ساخته نشد | ⏳ | فقط prop `excludeAppointmentUuid` |
|
||||
| ۳.۱ | `AppointmentEditPage`: حالت سرویسی `ServiceSlotPicker` نشان میدهد | ✅ | روش نوبتدهی از برنامهٔ **همین نوبت** پرسیده میشود (`clinic_uuid` صریح)، نه از محیط جاری پنل — پزشک میتواند در مطب اسلاتی و در کلینیک سرویسی باشد. لازمهٔ این کار: افزودن `clinic_uuid` به `toArray()` که نبود |
|
||||
| ۳.۲ | `AppointmentEditPage`: حالت اسلاتی **دقیقاً** رفتار امروز | ✅ | ۵ تست موجود صفحه سبز ماند + دو تست خط سرخ تازه: سه فیلد ساعت با مقدار هیدریتشده، و همان `PATCH` با `version` بدون هیچ `POST` |
|
||||
| ۳.۳ | ورودی دستی ساعت در حالت سرویسی **پنهان**، نه disabled | ✅ | `queryByLabelText('ساعت شروع')` در حالت سرویسی `null` است. `SearchableSelect` سرویس تکی هم پنهان میشود — نگهداشتنش دو منبع برای یک چیز بود |
|
||||
| ۳.۴ | `ServiceSlotPicker` موجود بازاستفاده شد؛ نسخهٔ موازی ساخته نشد | ✅ | دو prop اختیاری: `excludeAppointmentUuid` و `initialSelection`. رفتار فعلیاش در `AppointmentCreatePage` و `AppointmentsPage` دستنخورده (هر دو prop `undefined`). یک اصلاح لازم شد: effect ریست روی تعویض پزشک، اجرای نخست را معاف کند وگرنه `initialSelection` همان لحظه پاک میشد |
|
||||
| ۳.۵ | `ReserveAppointmentsPage`: سرویسها + دکمهٔ تبدیل | ⏳ | |
|
||||
| ۳.۶ | `ReserveAppointmentsPage` از جدول خام به `DataTable` مهاجرت کرد | ⏳ | `<td style={td}>` حذف شد |
|
||||
| ۳.۷ | مدت و بافر فارسی با واحد: «۳۵ دقیقه (+۱۰ دقیقه فاصله)» | ⏳ | |
|
||||
| ۳.۷ | مدت و بافر فارسی با واحد: «۳۵ دقیقه (+۱۰ دقیقه فاصله)» | 🔄 | در `AppointmentEditPage` هست («زمان انتخابی: ۱۶:۰۰ (+۱۰ دقیقه فاصله)») و `ServiceSlotPicker` خودش «مدت کل: N دقیقه» را نشان میدهد. `ReserveAppointmentsPage` مانده — قابلیت ۸ |
|
||||
| ۳.۸ | هیچ رنگ/شعاع/سایهٔ hard-code — همه از توکنهای `styles.css` | ⏳ | |
|
||||
| ۳.۹ | دارکمود (`data-theme="dark"`) بررسی شد | ⏳ | |
|
||||
| ۳.۱۰ | حالت فشرده (`data-density="compact"`) بررسی شد | ⏳ | |
|
||||
| ۳.۱۱ | انتخاب چند سرویس با `SearchableSelect`؛ هیچ `<select>` بومی | ⏳ | |
|
||||
| ۳.۱۱ | انتخاب چند سرویس با `SearchableSelect`؛ هیچ `<select>` بومی | ✅ | `ServiceSlotPicker` از `SearchableSelect` برای بخش و دکمههای toggle برای سرویسها استفاده میکند (کد موجود). هیچ `<select>` بومی اضافه نشد |
|
||||
| ۳.۱۲ | `backTo`/`BackButton` روی هر دو صفحه | ⏳ | |
|
||||
| ۳.۱۳ | وضعیت لیست رزروها در URL با `useUrlState` | ⏳ | |
|
||||
| ۳.۱۴ | تاریخ با `PersianDateInput` · مبلغ با `formatRial` | ⏳ | |
|
||||
| ۳.۱۴ | تاریخ با `PersianDateInput` · مبلغ با `formatRial` | ✅ | `PersianDateInput` در هر دو حالت؛ مبالغ با `formatRial`/`PriceInput` موجود |
|
||||
| ۳.۱۵ | RTL بررسی شد (`ms/me` نه `ml/mr`) | ⏳ | |
|
||||
| ۳.۱۶ | موبایل بررسی شد — بدون اسکرول افقی | ⏳ | |
|
||||
| ۳.۱۷ | همهٔ رشتهها فارسی و از i18n | ⏳ | |
|
||||
| ۳.۱۸ | داده با TanStack Query و استخراج envelope درست | ⏳ | |
|
||||
| ۳.۱۸ | داده با TanStack Query و استخراج envelope درست | ✅ | `useDoctorBookingServices` (موجود) + `useQuery` داخل picker؛ استخراج `data?.data` |
|
||||
|
||||
## ۴. تست
|
||||
|
||||
@@ -92,7 +92,8 @@ UI: [_shared/ui-conventions.md](../_shared/ui-conventions.md)
|
||||
| ۴.۷ | `BookingTenantTest` موجود سبز ماند | ✅ | داخل `tests/Appointment` — کل ۳۰۹ تست `tests/Appointment` + `tests/Shared` سبز |
|
||||
| ۴.۱۰ | `ServiceSlotExcludeSelfTest` — رفتار exclude | ✅ | ۶ تست / ۱۱ assertion. شامل: بازهٔ خودِ نوبت با exclude برمیگردد · مدت بلندتر روی همان ساعت · نوبتِ دیگری همچنان اشغال میماند · `null` صریح و ضمنی خروجی یکسان · فیلتر repository فقط همان ردیف · exclude کردن نوبت رزرو بیاثر |
|
||||
| ۴.۹ | `AppointmentServiceFieldsTest` — متدها و ستونهای جدید | ✅ | ۹ تست / ۲۴ assertion. شامل: همگامی ستون تکی · حفظ ترتیب · فهرست خالی → `null` · حالت اسلاتی هر دو ستون `null` · مدتِ `null` بافر را هم `null` میکند · تکراریها dedup · نوبت قدیمیِ فقط-تکی · بقای مقادیر پس از flush/clear |
|
||||
| ۴.۸ | `AppointmentEditPage.test.tsx` — دو حالت | ⏳ | |
|
||||
| ۴.۸ | `AppointmentEditPage` — دو حالت | ✅ | فایل جدید `AppointmentEditPage.serviceMode.test.tsx`: ۹ تست. شامل: پنهانبودن ورودی ساعت · دکمهٔ غیرفعال + راهنما · `exclude_appointment_uuid` در query · `service-reschedule` **بدون هیچ مدتی** · `PATCH` بعدی بی`version` · هشدار سرویس غیرفعال · و سه تست خط سرخ (اسلاتی و رزرو). فایل موجود `AppointmentEditPage.test.tsx` هم سبز ماند |
|
||||
| ۴.۱۱ | کل vitest سبز | ✅ | `86 files / 604 tests passed` روی host (داخل ddev باینری esbuild پلتفرم اشتباه دارد — مسئلهٔ محیطی از قبل) |
|
||||
|
||||
## ۵. مستندات
|
||||
|
||||
|
||||
Reference in New Issue
Block a user