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:
hamed
2026-07-30 14:57:21 +03:30
co-authored by Claude Opus 5
parent 0051205bf2
commit 50759bf663
6 changed files with 402 additions and 59 deletions
+4
View File
@@ -467,6 +467,10 @@ class Appointment
],
'address' => $firstAddress?->toArray(),
'address_id' => $this->addressId,
// محلِ نوبت‌دهی این نوبت. null = مطب شخصی. کلاینت بدون این نمی‌داند روش
// نوبت‌دهی را از کدام برنامه بپرسد: یک پزشک می‌تواند در مطب اسلاتی و در
// کلینیک سرویسی باشد و محیط جاریِ پنل لزوماً محیط این نوبت نیست.
'clinic_uuid' => $this->clinic?->getUuid(),
'user' => [
'uuid' => $this->user->getUuid(),
'mobile' => $this->user->getMobileNumber(),