import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { toast } from 'sonner'; import { api, ApiError, type ApiResponse } from '../lib/api'; import type { Policy, PolicyCategory, PolicySchema, PolicySimulationRun, PolicyTemplate, } from '../types'; /** * قوانین کلینیک. * * دو نکتهٔ قراردادی که فرم به آن‌ها وابسته است: * ۱. schema و الگوها از سرور می‌آیند، نه از فهرستی در فرانت — یک حقیقت، نه دو تا. * ۲. فعال‌سازی بدون آزمایشِ همان نسخه ۴۲۲ می‌گیرد؛ UI باید کاربر را اول به آزمایش ببرد. */ const POLICIES_KEY = ['policies']; function fail(e: unknown, fallback: string) { toast.error(e instanceof ApiError ? e.message : fallback); } /** schema تقریباً هرگز عوض نمی‌شود؛ نگه‌داشتن طولانی‌اش هزینه‌ای ندارد. */ export function usePolicySchema() { const query = useQuery({ queryKey: ['policy-schema'], queryFn: () => api.get>('/api/v1/policy-schema'), staleTime: 300_000, }); return { schema: query.data?.data, loading: query.isLoading }; } export function usePolicyTemplates() { const query = useQuery({ queryKey: ['policy-templates'], queryFn: () => api.get>('/api/v1/policy-templates'), staleTime: 300_000, }); return { templates: query.data?.data ?? [], loading: query.isLoading }; } export function usePolicies(category?: PolicyCategory | '') { const qc = useQueryClient(); const key = [...POLICIES_KEY, category ?? '']; const query = useQuery({ queryKey: key, queryFn: () => api.get>( `/api/v1/policies${category ? `?category=${category}` : ''}`, ), }); const invalidate = () => qc.invalidateQueries({ queryKey: POLICIES_KEY }); const activate = useMutation({ mutationFn: (uuid: string) => api.post>(`/api/v1/policy/${uuid}/activate`, {}), onSuccess: () => { toast.success('قانون فعال شد'); invalidate(); }, onError: (e) => fail(e, 'فعال‌سازی ناموفق بود'), }); const deactivate = useMutation({ mutationFn: (uuid: string) => api.post>(`/api/v1/policy/${uuid}/deactivate`, {}), onSuccess: () => { toast.success('قانون غیرفعال شد'); invalidate(); }, onError: (e) => fail(e, 'غیرفعال‌سازی ناموفق بود'), }); return { policies: query.data?.data ?? [], loading: query.isLoading, activate, deactivate, }; } export function usePolicy(uuid: string | undefined) { const query = useQuery({ queryKey: ['policy', uuid], queryFn: () => api.get>(`/api/v1/policy/${uuid}`), enabled: !!uuid, }); return { policy: query.data?.data, loading: query.isLoading }; } export function usePolicyMutations() { const qc = useQueryClient(); const create = useMutation({ mutationFn: (body: Record) => api.post>('/api/v1/policy', body), onSuccess: () => { toast.success('قانون ساخته شد — حالا آزمایشش کنید'); qc.invalidateQueries({ queryKey: POLICIES_KEY }); }, onError: (e) => fail(e, 'ساخت قانون ناموفق بود'), }); const newVersion = useMutation({ mutationFn: ({ uuid, body }: { uuid: string; body: Record }) => api.post>(`/api/v1/policy/${uuid}/version`, body), onSuccess: (_d, v) => { toast.success('نسخهٔ تازه ثبت شد'); qc.invalidateQueries({ queryKey: POLICIES_KEY }); qc.invalidateQueries({ queryKey: ['policy', v.uuid] }); }, onError: (e) => fail(e, 'ثبت نسخه ناموفق بود'), }); return { create, newVersion }; } export function usePolicySimulation(uuid: string | undefined) { const qc = useQueryClient(); const key = ['policy-simulations', uuid]; const history = useQuery({ queryKey: key, queryFn: () => api.get>(`/api/v1/policy/${uuid}/simulations`), enabled: !!uuid, }); const run = useMutation({ mutationFn: (sampleSize?: number) => api.post>(`/api/v1/policy/${uuid}/simulate`, { sample_size: sampleSize ?? 50, }), onSuccess: () => { qc.invalidateQueries({ queryKey: key }); qc.invalidateQueries({ queryKey: POLICIES_KEY }); }, onError: (e) => fail(e, 'اجرای آزمایشی ناموفق بود'), }); return { runs: history.data?.data ?? [], loading: history.isLoading, run }; }