2026-07-13 02:09:49 +03:30
|
|
|
import type { LabTaskListItem, TaskSortField } from '@/types/cases';
|
|
|
|
|
|
|
|
|
|
export type ProsthesisTaskGroup = {
|
|
|
|
|
key: string;
|
|
|
|
|
treatmentDetailId: string;
|
|
|
|
|
prosthesisTypeCode: string;
|
|
|
|
|
prosthesisTypeLabel: string;
|
|
|
|
|
teeth: string[];
|
|
|
|
|
tasks: LabTaskListItem[];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export type CaseTaskGroup = {
|
|
|
|
|
labCaseId: string;
|
|
|
|
|
clinic: LabTaskListItem['clinic'];
|
|
|
|
|
patient: LabTaskListItem['patient'];
|
|
|
|
|
caseSentAt: string | null;
|
2026-07-13 16:30:36 +03:30
|
|
|
caseDueDate: string | null;
|
|
|
|
|
isCaseOverdue: boolean;
|
2026-07-13 02:09:49 +03:30
|
|
|
isImportant: boolean;
|
|
|
|
|
prosthesisGroups: ProsthesisTaskGroup[];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export type TaskDisplayModel =
|
|
|
|
|
| { mode: 'grouped'; cases: CaseTaskGroup[] }
|
|
|
|
|
| { mode: 'flat'; tasks: LabTaskListItem[] };
|
|
|
|
|
|
|
|
|
|
function prosthesisGroupKey(task: LabTaskListItem): string {
|
|
|
|
|
return `${task.treatmentDetailId}:${task.prosthesisTypeCode}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function groupTasksForDisplay(
|
|
|
|
|
tasks: LabTaskListItem[],
|
|
|
|
|
sortBy: TaskSortField,
|
|
|
|
|
): TaskDisplayModel {
|
|
|
|
|
if (sortBy !== 'date') {
|
|
|
|
|
return { mode: 'flat', tasks };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const cases: CaseTaskGroup[] = [];
|
|
|
|
|
const caseIndex = new Map<string, number>();
|
|
|
|
|
|
|
|
|
|
for (const task of tasks) {
|
|
|
|
|
let caseIdx = caseIndex.get(task.labCaseId);
|
|
|
|
|
if (caseIdx === undefined) {
|
|
|
|
|
caseIdx = cases.length;
|
|
|
|
|
caseIndex.set(task.labCaseId, caseIdx);
|
|
|
|
|
cases.push({
|
|
|
|
|
labCaseId: task.labCaseId,
|
|
|
|
|
clinic: task.clinic,
|
|
|
|
|
patient: task.patient,
|
|
|
|
|
caseSentAt: task.caseSentAt ?? null,
|
2026-07-13 16:30:36 +03:30
|
|
|
caseDueDate: task.caseDueDate ?? null,
|
|
|
|
|
isCaseOverdue: task.isCaseOverdue,
|
2026-07-13 02:09:49 +03:30
|
|
|
isImportant: task.isImportant,
|
|
|
|
|
prosthesisGroups: [],
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const caseGroup = cases[caseIdx];
|
|
|
|
|
const pgKey = prosthesisGroupKey(task);
|
|
|
|
|
let prosthesisGroup = caseGroup.prosthesisGroups.find((g) => g.key === pgKey);
|
|
|
|
|
if (!prosthesisGroup) {
|
|
|
|
|
prosthesisGroup = {
|
|
|
|
|
key: pgKey,
|
|
|
|
|
treatmentDetailId: task.treatmentDetailId,
|
|
|
|
|
prosthesisTypeCode: task.prosthesisTypeCode,
|
|
|
|
|
prosthesisTypeLabel: task.prosthesisTypeLabel,
|
|
|
|
|
teeth: task.teeth,
|
|
|
|
|
tasks: [],
|
|
|
|
|
};
|
|
|
|
|
caseGroup.prosthesisGroups.push(prosthesisGroup);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prosthesisGroup.tasks.push(task);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return { mode: 'grouped', cases };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function countCaseTaskProgress(caseGroup: CaseTaskGroup): {
|
|
|
|
|
completed: number;
|
|
|
|
|
total: number;
|
|
|
|
|
} {
|
|
|
|
|
let completed = 0;
|
|
|
|
|
let total = 0;
|
|
|
|
|
for (const group of caseGroup.prosthesisGroups) {
|
|
|
|
|
for (const task of group.tasks) {
|
|
|
|
|
total += 1;
|
|
|
|
|
if (task.status === 'COMPLETED') completed += 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return { completed, total };
|
|
|
|
|
}
|