Remove unused pages: PolicySimulationPage, ResourceUtilizationPage, TreatmentCoursePage, WaitlistPage, and their associated tests
This commit is contained in:
@@ -1,138 +0,0 @@
|
||||
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<ApiResponse<CourseProtocol[]>>('/api/v1/course-protocols'),
|
||||
});
|
||||
|
||||
const invalidate = () => qc.invalidateQueries({ queryKey: PROTOCOLS_KEY });
|
||||
|
||||
const create = useMutation({
|
||||
mutationFn: (body: Record<string, unknown>) =>
|
||||
api.post<ApiResponse<CourseProtocol>>('/api/v1/course-protocols', body),
|
||||
onSuccess: () => {
|
||||
toast.success('پروتکل ساخته شد');
|
||||
invalidate();
|
||||
},
|
||||
onError: (e) => fail(e, 'ساخت پروتکل ناموفق بود'),
|
||||
});
|
||||
|
||||
const update = useMutation({
|
||||
mutationFn: ({ uuid, body }: { uuid: string; body: Record<string, unknown> }) =>
|
||||
api.patch<ApiResponse<CourseProtocol>>(`/api/v1/course-protocol/${uuid}`, body),
|
||||
onSuccess: () => {
|
||||
toast.success('پروتکل بهروزرسانی شد');
|
||||
invalidate();
|
||||
},
|
||||
onError: (e) => fail(e, 'بهروزرسانی پروتکل ناموفق بود'),
|
||||
});
|
||||
|
||||
const deactivate = useMutation({
|
||||
mutationFn: (uuid: string) => api.delete<ApiResponse<CourseProtocol>>(`/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<ApiResponse<TreatmentCourse[]>>(`/api/v1/patient/${patientUuid}/courses`),
|
||||
enabled: !!patientUuid,
|
||||
});
|
||||
|
||||
const start = useMutation({
|
||||
mutationFn: (body: { protocol_uuid: string; patient_package_uuid?: string }) =>
|
||||
api.post<ApiResponse<TreatmentCourse>>('/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<ApiResponse<TreatmentCourse>>(`/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<ApiResponse<TreatmentCourse>>(`/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<ApiResponse<{ booked: number; remaining: number; message: string | null }>>(
|
||||
`/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<ApiResponse<NextSlotSuggestion>>(
|
||||
`/api/v1/treatment-course/${courseUuid}/next-slot-suggestion?branch_uuid=${branchUuid}`,
|
||||
),
|
||||
enabled: !!courseUuid && !!branchUuid,
|
||||
});
|
||||
|
||||
return { suggestion: query.data?.data, loading: query.isLoading };
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
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<ApiResponse<PackageDefinition[]>>('/api/v1/packages'),
|
||||
});
|
||||
|
||||
const invalidate = () => qc.invalidateQueries({ queryKey: PACKAGES_KEY });
|
||||
|
||||
const create = useMutation({
|
||||
mutationFn: (body: Record<string, unknown>) =>
|
||||
api.post<ApiResponse<PackageDefinition>>('/api/v1/packages', body),
|
||||
onSuccess: () => {
|
||||
toast.success('پکیج ساخته شد');
|
||||
invalidate();
|
||||
},
|
||||
onError: (e) => fail(e, 'ساخت پکیج ناموفق بود'),
|
||||
});
|
||||
|
||||
const update = useMutation({
|
||||
mutationFn: ({ uuid, body }: { uuid: string; body: Record<string, unknown> }) =>
|
||||
api.patch<ApiResponse<PackageDefinition>>(`/api/v1/package/${uuid}`, body),
|
||||
onSuccess: () => {
|
||||
toast.success('پکیج بهروزرسانی شد');
|
||||
invalidate();
|
||||
},
|
||||
onError: (e) => fail(e, 'بهروزرسانی پکیج ناموفق بود'),
|
||||
});
|
||||
|
||||
/** حذف = غیرفعال کردن؛ پکیج فروختهشده حذفشدنی نیست. */
|
||||
const deactivate = useMutation({
|
||||
mutationFn: (uuid: string) => api.delete<ApiResponse<PackageDefinition>>(`/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<ApiResponse<PatientPackage[]>>(`/api/v1/patient/${patientUuid}/packages`),
|
||||
enabled: !!patientUuid,
|
||||
});
|
||||
|
||||
const sell = useMutation({
|
||||
mutationFn: (body: { package_uuid: string; price_paid_rials?: number }) =>
|
||||
api.post<ApiResponse<PatientPackage>>(`/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<ApiResponse<CreditLedger>>(`/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<ApiResponse<PatientPackage>>(`/api/v1/patient-package/${patientPackageUuid}/adjust`, body),
|
||||
onSuccess: () => {
|
||||
toast.success('اصلاح اعتبار ثبت شد');
|
||||
invalidate();
|
||||
},
|
||||
onError: (e) => fail(e, 'اصلاح اعتبار ناموفق بود'),
|
||||
});
|
||||
|
||||
const expire = useMutation({
|
||||
mutationFn: (reason: string) =>
|
||||
api.post<ApiResponse<PatientPackage>>(`/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 };
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { api, type ApiResponse } from '../lib/api';
|
||||
import type { AccuracyRow, ReportEnvelope, UtilizationRow } from '../types';
|
||||
|
||||
/**
|
||||
* گزارشهای بهرهوری و دقت برنامه.
|
||||
*
|
||||
* بازه همیشه صریح فرستاده میشود تا نمودار با پیشفرض سرور جابهجا نشود.
|
||||
*/
|
||||
export function useResourceUtilization(branchUuid: string | undefined, from: number, to: number) {
|
||||
const query = useQuery({
|
||||
queryKey: ['resource-utilization', branchUuid, from, to],
|
||||
queryFn: () =>
|
||||
api.get<ApiResponse<ReportEnvelope<UtilizationRow>>>(
|
||||
`/api/v1/reports/resource-utilization?branch_uuid=${branchUuid}&from=${from}&to=${to}`,
|
||||
),
|
||||
enabled: !!branchUuid,
|
||||
});
|
||||
|
||||
return { rows: query.data?.data?.rows ?? [], loading: query.isLoading };
|
||||
}
|
||||
|
||||
export function usePlanAccuracy(from: number, to: number) {
|
||||
const query = useQuery({
|
||||
queryKey: ['plan-accuracy', from, to],
|
||||
queryFn: () =>
|
||||
api.get<ApiResponse<ReportEnvelope<AccuracyRow>>>(
|
||||
`/api/v1/reports/plan-accuracy?from=${from}&to=${to}`,
|
||||
),
|
||||
});
|
||||
|
||||
return { rows: query.data?.data?.rows ?? [], loading: query.isLoading };
|
||||
}
|
||||
Reference in New Issue
Block a user