Files
clinicpro/assets/admin/hooks/useDoctorBookingServices.ts
T
hamedandClaude Fable 5 7baa4df3d4 fix(booking): aggregate public booking state across all schedules
The public doctor payload built `active`/`free_turn`/`hours_of_work` from the
personal schedule alone, so a doctor bookable only at a clinic was reported as
"نوبت‌دهی غیرفعال". Aggregate over every schedule instead: any schedule with
online booking on and an active day makes the doctor bookable, and the disabled
label only appears when all of them are off.

Three admin-panel fixes for the same class of bug:

- AppointmentsPage took the selected doctor from `dbUuid`, which is the clinic's
  uuid inside a clinic context — the slots request 404'd. Use `doctorUuid`.
- TurnsTimeline rendered any error or unknown empty_reason as "این روز شیفت کاری
  ندارد". Errors now surface as errors and unknown reasons get a neutral message;
  the day-off wording is reserved for an explicit day_off from the backend.
- Admins have no clinic context, so slots fell back to the personal schedule.
  They now pick a location from `appointment-booking-locations` and that choice
  drives the slot, service and create-appointment requests.

Adds `app:schedule:normalize-format` for legacy rows stored as a bare JSON list
covering only Saturday, which read as day-off for the rest of the week.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 16:25:24 +03:30

51 lines
1.8 KiB
TypeScript

import { useQuery } from '@tanstack/react-query';
import { api } from '../lib/api';
import type { ApiResponse } from '../lib/api';
import { useClinicContext } from './useClinicContext';
export interface BookingService {
uuid: string;
name: string;
duration_minutes: number | null;
price_rials: number;
service_section: { uuid: string; name: string };
}
interface BookingServicesData {
booking_mode: 'slot' | 'service';
buffer_minutes: number;
services: BookingService[];
}
/**
* روش نوبت‌دهی و سرویس‌های قابل‌انتخابِ یک پزشک — از endpoint عمومیِ
* `appointment-booking-services`. برای سرویس‌محور کردن فرم‌های ثبت نوبت پنل.
*
* clinicUuidOverride: `undefined` یعنی context محیط جاری؛ مقدار صریح (شامل null =
* مطب شخصی) وقتی که انتخاب محل خارج از context انجام شده (مثلاً ادمین).
*/
export function useDoctorBookingServices(
doctorUuid: string | null | undefined,
clinicUuidOverride?: string | null,
) {
const contextClinicUuid = useClinicContext();
const clinicUuid = clinicUuidOverride === undefined ? contextClinicUuid : clinicUuidOverride;
const q = useQuery<ApiResponse<BookingServicesData>>({
queryKey: ['booking-services', doctorUuid, clinicUuid],
queryFn: () => api.get(
`/api/v1/appointment-booking-services/${doctorUuid}`
+ (clinicUuid ? `?clinic_uuid=${encodeURIComponent(clinicUuid)}` : '')
),
enabled: !!doctorUuid,
});
const data = q.data?.data as BookingServicesData | undefined;
return {
bookingMode: (data?.booking_mode === 'service' ? 'service' : 'slot') as 'slot' | 'service',
bufferMinutes: data?.buffer_minutes ?? 0,
services: data?.services ?? [],
isLoading: q.isLoading,
};
}