The appointments page only ever showed one doctor's row, but in the resource-first model a single appointment can hold a room and a device at the same time, and that — not the doctor's schedule — is what runs the capacity out. An hour could look free on the doctor's lane while the only alexandrite laser was already taken. A third view, "منابع", draws one lane per resource for the selected day. Blocks come from resource_occupancy rather than the appointment: that range includes the device's setup and cleanup minutes and is the same range the availability engine treats as busy. A multi-segment appointment therefore shows up on every resource it holds, and each block links to the appointment it belongs to. GET /api/v1/resources/timeline keeps a fixed query count — one for occupancy, one for shifts, one for the patient names — instead of one per resource. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
54 lines
1.7 KiB
TypeScript
54 lines
1.7 KiB
TypeScript
import { useQuery } from '@tanstack/react-query';
|
|
import { api, type ApiResponse } from '../lib/api';
|
|
|
|
export type ResourceTimelineItem = {
|
|
uuid: string;
|
|
starts_at: number;
|
|
ends_at: number;
|
|
status: 'booked' | 'hold';
|
|
segment_name: string | null;
|
|
appointment_id: number | null;
|
|
patient_name: string | null;
|
|
appointment_uuid: string | null;
|
|
appointment_status: string | null;
|
|
};
|
|
|
|
export type ResourceTimelineLane = {
|
|
uuid: string;
|
|
name: string;
|
|
type_name: string;
|
|
address_name: string | null;
|
|
capacity: number;
|
|
shifts: { start_minute: number; end_minute: number }[];
|
|
items: ResourceTimelineItem[];
|
|
};
|
|
|
|
export type ResourceTimelineDay = {
|
|
date: number;
|
|
day_of_week: number;
|
|
resources: ResourceTimelineLane[];
|
|
};
|
|
|
|
/**
|
|
* «کدام منبع در این روز کِی گرفته است» — ورودی نمای منبعمحورِ صفحهٔ نوبتها.
|
|
*
|
|
* بازهها از جدول اشغال میآیند نه از خودِ نوبت: آمادهسازی و تمیزکاری دستگاه هم
|
|
* درونشان است و همان بازهای است که موتور جستجو اشغال میبیند.
|
|
*/
|
|
export function useResourceTimeline(date: string, addressUuid?: string) {
|
|
const params = new URLSearchParams({ date });
|
|
if (addressUuid) params.set('address_uuid', addressUuid);
|
|
|
|
const query = useQuery({
|
|
queryKey: ['resource-timeline', date, addressUuid ?? null],
|
|
queryFn: () => api.get<ApiResponse<ResourceTimelineDay>>(`/api/v1/resources/timeline?${params}`),
|
|
enabled: !!date,
|
|
});
|
|
|
|
return {
|
|
day: query.data?.data,
|
|
loading: query.isLoading,
|
|
error: query.isError ? ((query.error as Error)?.message || 'خطای نامشخص') : null,
|
|
};
|
|
}
|