feat: Implement resource-based appointment booking flow

- Updated DoctorPage component to accept bookingResources prop for appointment list.
- Added serviceQuery function to serialize service item UUIDs for API requests.
- Introduced new API endpoints for fetching booking resources and resource slots.
- Enhanced tests for new resource-based booking functionality, including resource selection and service availability.
- Created ResourceSelect component for selecting appointment types, including doctor and resource options.
- Updated appointment submission logic to include resource_uuid in payload when applicable.
- Ensured UI reflects changes in booking flow without disrupting existing doctor-centric experience.
This commit is contained in:
hamed
2026-08-09 10:45:52 +03:30
parent 1668ef8890
commit 54bebbd41a
23 changed files with 1094 additions and 32 deletions
+29 -3
View File
@@ -9,6 +9,15 @@ import api from "./api";
const clinicQuery = (clinicUuid, prefix = "&") =>
clinicUuid ? `${prefix}clinic_uuid=${encodeURIComponent(clinicUuid)}` : "";
/**
* آرایه را با `[]` سریالایز می‌کند؛ `params` اکسیوس این کار را نمی‌کند و backend
* فهرست سرویس‌ها را خالی می‌بیند.
*/
const serviceQuery = (serviceItemUuids = []) =>
serviceItemUuids
.map((u) => `&service_item_uuids[]=${encodeURIComponent(u)}`)
.join("");
export const request = {
sendCode: (mobile, altcha, domain) =>
api.post(
@@ -81,12 +90,29 @@ export const request = {
getServiceSlots: (doctor_uuid, date, serviceItemUuids = [], clinic_uuid = null) =>
api.get(
`api/v1/appointment-service-slots?doctor_uuid=${doctor_uuid}&date=${date}` +
serviceItemUuids
.map((u) => `&service_item_uuids[]=${encodeURIComponent(u)}`)
.join("") +
serviceQuery(serviceItemUuids) +
clinicQuery(clinic_uuid),
removeTokenHead
),
// نوبت‌دهی منبع‌محور: منبع تقویم خودش را دارد، پس اسلات و تقویمِ ماهش هم از
// اندپوینت‌های خودش می‌آید نه از برنامهٔ هفتگی پزشک.
getBookingResources: (doctor_uuid, clinic_uuid = null) =>
api.get(
`api/v1/appointment-booking-resources/${doctor_uuid}${clinicQuery(clinic_uuid, "?")}`,
removeTokenHead
),
getResourceSlots: (resource_uuid, date, serviceItemUuids = []) =>
api.get(
`api/v1/appointment-resource-slots?resource_uuid=${encodeURIComponent(resource_uuid)}&date=${date}` +
serviceQuery(serviceItemUuids),
removeTokenHead
),
getResourceMonthAvailability: (resource_uuid, year, month, serviceItemUuids = []) =>
api.get(
`api/v1/appointment-resource-month-availability/${resource_uuid}?year=${year}&month=${month}` +
serviceQuery(serviceItemUuids),
removeTokenHead
),
postAppointment: (data) => api.post(`api/v1/appointment`, data, { requireAuth: true }),
getMyAppointments: (params) => api.get(`api/v1/appointments/user`, { params, requireAuth: true }),
getPaymentConfig: () => api.get(`api/v1/payment/config`, { requireAuth: true }),