feat(appointments): a resource-first view on the timeline
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>
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
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,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user