import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { toast } from 'sonner'; import { api, ApiError, type ApiResponse } from '../lib/api'; import type { CourseProtocol, NextSlotSuggestion, TreatmentCourse } from '../types'; /** * پروتکل دوره و دورهٔ بیمار. * * `progress` هرگز در فرانت حساب نمی‌شود — سرور می‌دهدش، چون همان‌جاست که وضعیت جلسات * منبع حقیقت است. */ const PROTOCOLS_KEY = ['course-protocols']; function fail(e: unknown, fallback: string) { toast.error(e instanceof ApiError ? e.message : fallback); } export function useCourseProtocols() { const qc = useQueryClient(); const query = useQuery({ queryKey: PROTOCOLS_KEY, queryFn: () => api.get>('/api/v1/course-protocols'), }); const invalidate = () => qc.invalidateQueries({ queryKey: PROTOCOLS_KEY }); const create = useMutation({ mutationFn: (body: Record) => api.post>('/api/v1/course-protocols', body), onSuccess: () => { toast.success('پروتکل ساخته شد'); invalidate(); }, onError: (e) => fail(e, 'ساخت پروتکل ناموفق بود'), }); const update = useMutation({ mutationFn: ({ uuid, body }: { uuid: string; body: Record }) => api.patch>(`/api/v1/course-protocol/${uuid}`, body), onSuccess: () => { toast.success('پروتکل به‌روزرسانی شد'); invalidate(); }, onError: (e) => fail(e, 'به‌روزرسانی پروتکل ناموفق بود'), }); const deactivate = useMutation({ mutationFn: (uuid: string) => api.delete>(`/api/v1/course-protocol/${uuid}`), onSuccess: () => { toast.success('پروتکل غیرفعال شد'); invalidate(); }, onError: (e) => fail(e, 'غیرفعال‌سازی ناموفق بود'), }); return { protocols: query.data?.data ?? [], loading: query.isLoading, create, update, deactivate }; } export function usePatientCourses(patientUuid: string | undefined) { const qc = useQueryClient(); const key = ['patient-courses', patientUuid]; const query = useQuery({ queryKey: key, queryFn: () => api.get>(`/api/v1/patient/${patientUuid}/courses`), enabled: !!patientUuid, }); const start = useMutation({ mutationFn: (body: { protocol_uuid: string; patient_package_uuid?: string }) => api.post>('/api/v1/treatment-course', { patient_uuid: patientUuid, ...body, }), onSuccess: () => { toast.success('دوره شروع شد'); qc.invalidateQueries({ queryKey: key }); }, onError: (e) => fail(e, 'شروع دوره ناموفق بود'), }); return { courses: query.data?.data ?? [], loading: query.isLoading, start }; } export function useTreatmentCourse(courseUuid: string | undefined) { const qc = useQueryClient(); const key = ['treatment-course', courseUuid]; const query = useQuery({ queryKey: key, queryFn: () => api.get>(`/api/v1/treatment-course/${courseUuid}`), enabled: !!courseUuid, }); const invalidate = () => { qc.invalidateQueries({ queryKey: key }); qc.invalidateQueries({ queryKey: ['patient-courses'] }); }; const abandon = useMutation({ mutationFn: (reason: string) => api.post>(`/api/v1/treatment-course/${courseUuid}/abandon`, { reason }), onSuccess: () => { toast.success('دوره رها شد'); invalidate(); }, onError: (e) => fail(e, 'رهاکردن دوره ناموفق بود'), }); const bookAll = useMutation({ mutationFn: (body: { branch_uuid: string; doctor_uuid: string }) => api.post>( `/api/v1/treatment-course/${courseUuid}/book-all`, body, ), onSuccess: (res) => { toast.success(res.data.message ?? `${res.data.booked} جلسه رزرو شد`); invalidate(); }, onError: (e) => fail(e, 'رزرو جلسات ناموفق بود'), }); return { course: query.data?.data, loading: query.isLoading, abandon, bookAll }; } export function useNextSlotSuggestion(courseUuid: string | undefined, branchUuid: string | undefined) { const query = useQuery({ queryKey: ['course-next-slot', courseUuid, branchUuid], queryFn: () => api.get>( `/api/v1/treatment-course/${courseUuid}/next-slot-suggestion?branch_uuid=${branchUuid}`, ), enabled: !!courseUuid && !!branchUuid, }); return { suggestion: query.data?.data, loading: query.isLoading }; }