Remove unused pages: PolicySimulationPage, ResourceUtilizationPage, TreatmentCoursePage, WaitlistPage, and their associated tests

This commit is contained in:
hamed
2026-08-01 20:25:42 +03:30
parent 65d5831c64
commit 9486721fa3
21 changed files with 0 additions and 3420 deletions
-138
View File
@@ -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 };
}
-120
View File
@@ -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 };
}
-33
View File
@@ -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 };
}