import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { toast } from 'sonner'; import { api, ApiError, type ApiResponse } from '../lib/api'; import type { CreditLedger, PackageDefinition, PatientPackage } from '../types'; /** * پکیج و اعتبار جلسات. * * مانده هیچ‌جا کش نمی‌شود و بعد از هر تغییر دفتر، کوئری باطل می‌شود: عددی که کاربر * می‌بیند باید همان جمع دفتر باشد، نه چیزی که فرانت حساب کرده. */ const PACKAGES_KEY = ['packages']; function fail(e: unknown, fallback: string) { toast.error(e instanceof ApiError ? e.message : fallback); } export function usePackages() { const qc = useQueryClient(); const query = useQuery({ queryKey: PACKAGES_KEY, queryFn: () => api.get>('/api/v1/packages'), }); const invalidate = () => qc.invalidateQueries({ queryKey: PACKAGES_KEY }); const create = useMutation({ mutationFn: (body: Record) => api.post>('/api/v1/packages', body), onSuccess: () => { toast.success('پکیج ساخته شد'); invalidate(); }, onError: (e) => fail(e, 'ساخت پکیج ناموفق بود'), }); const update = useMutation({ mutationFn: ({ uuid, body }: { uuid: string; body: Record }) => api.patch>(`/api/v1/package/${uuid}`, body), onSuccess: () => { toast.success('پکیج به‌روزرسانی شد'); invalidate(); }, onError: (e) => fail(e, 'به‌روزرسانی پکیج ناموفق بود'), }); /** حذف = غیرفعال کردن؛ پکیج فروخته‌شده حذف‌شدنی نیست. */ const deactivate = useMutation({ mutationFn: (uuid: string) => api.delete>(`/api/v1/package/${uuid}`), onSuccess: () => { toast.success('پکیج غیرفعال شد'); invalidate(); }, onError: (e) => fail(e, 'غیرفعال‌سازی ناموفق بود'), }); return { packages: query.data?.data ?? [], loading: query.isLoading, create, update, deactivate }; } export function usePatientPackages(patientUuid: string | undefined) { const qc = useQueryClient(); const key = ['patient-packages', patientUuid]; const query = useQuery({ queryKey: key, queryFn: () => api.get>(`/api/v1/patient/${patientUuid}/packages`), enabled: !!patientUuid, }); const sell = useMutation({ mutationFn: (body: { package_uuid: string; price_paid_rials?: number }) => api.post>(`/api/v1/patient/${patientUuid}/package`, body), onSuccess: () => { toast.success('پکیج برای بیمار ثبت شد'); qc.invalidateQueries({ queryKey: key }); }, onError: (e) => fail(e, 'ثبت پکیج ناموفق بود'), }); return { patientPackages: query.data?.data ?? [], loading: query.isLoading, sell }; } export function useCreditLedger(patientPackageUuid: string | undefined) { const qc = useQueryClient(); const key = ['credit-ledger', patientPackageUuid]; const query = useQuery({ queryKey: key, queryFn: () => api.get>(`/api/v1/patient-package/${patientPackageUuid}/ledger`), enabled: !!patientPackageUuid, }); const invalidate = () => { qc.invalidateQueries({ queryKey: key }); qc.invalidateQueries({ queryKey: ['patient-packages'] }); }; const adjust = useMutation({ mutationFn: (body: { delta: number; reason: string }) => api.post>(`/api/v1/patient-package/${patientPackageUuid}/adjust`, body), onSuccess: () => { toast.success('اصلاح اعتبار ثبت شد'); invalidate(); }, onError: (e) => fail(e, 'اصلاح اعتبار ناموفق بود'), }); const expire = useMutation({ mutationFn: (reason: string) => api.post>(`/api/v1/patient-package/${patientPackageUuid}/expire`, { reason }), onSuccess: () => { toast.success('پکیج ابطال شد'); invalidate(); }, onError: (e) => fail(e, 'ابطال پکیج ناموفق بود'), }); return { ledger: query.data?.data, loading: query.isLoading, adjust, expire }; }