improvement: attachment selection for lab dispatch added. attachment preview added to cases feature.
This commit is contained in:
@@ -14,11 +14,14 @@ import { Button } from '@/components/ui/shared/Button';
|
||||
import { SearchBar } from '@/components/ui/shared/SearchBar';
|
||||
import { ToastStack } from '@/components/ui/shared/Toast';
|
||||
import { LabCaseCommentsPanel } from '@/components/ui/lab/LabCaseCommentsPanel';
|
||||
import { CaseToothChartPanel } from '@/components/ui/lab/CaseToothChartPanel';
|
||||
import { LabCaseAttachmentPreview } from '@/components/ui/lab/LabCaseAttachmentPreview';
|
||||
import { labTaskStatusVariant } from '@/components/ui/lab/labTaskStatusDisplay';
|
||||
import {
|
||||
formatToothList,
|
||||
prosthesisTypeBadgeStyle,
|
||||
} from '@/components/ui/treatment/prosthesisTypeDisplay';
|
||||
import { treatmentsApi } from '@/lib/api/treatments';
|
||||
import type { CounterpartItemDto } from '@/lib/api/organization';
|
||||
import type { LabCaseDetail, LabCaseListItem, LabTaskStatus } from '@/types/cases';
|
||||
import type { TreatmentCatalogEntry } from '@/types/treatment-catalog';
|
||||
@@ -186,6 +189,39 @@ export function ConnectionCaseHistoryContent({
|
||||
document.getElementById('case-comments')?.scrollIntoView({ behavior: 'smooth' });
|
||||
}
|
||||
|
||||
const loadClinicAttachmentBlob = useCallback(
|
||||
(_caseId: string, attachmentId: string) => treatmentsApi.getAttachmentFileBlob(attachmentId),
|
||||
[],
|
||||
);
|
||||
|
||||
const latestCaseAttachment = useMemo(() => {
|
||||
if (!selectedCase?.attachments.length) return null;
|
||||
return [...selectedCase.attachments].sort(
|
||||
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
|
||||
)[0];
|
||||
}, [selectedCase?.attachments]);
|
||||
|
||||
const caseProsthesisRows = useMemo(() => {
|
||||
if (!selectedCase) return [];
|
||||
if (selectedCase.toothProsthesis.length > 0) {
|
||||
const byCode = new Map<string, string[]>();
|
||||
for (const row of selectedCase.toothProsthesis) {
|
||||
const key = row.prosthesisTypeCode;
|
||||
const teeth = byCode.get(key) ?? [];
|
||||
if (!teeth.includes(row.tooth)) teeth.push(row.tooth);
|
||||
byCode.set(key, teeth);
|
||||
}
|
||||
return [...byCode.entries()].map(([prosthesisTypeCode, teeth]) => ({
|
||||
prosthesisTypeCode,
|
||||
teeth,
|
||||
}));
|
||||
}
|
||||
return selectedCase.tasksByTooth.map((g) => ({
|
||||
prosthesisTypeCode: g.prosthesisTypeCode,
|
||||
teeth: g.teeth,
|
||||
}));
|
||||
}, [selectedCase]);
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
@@ -348,6 +384,27 @@ export function ConnectionCaseHistoryContent({
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="flex flex-wrap items-start gap-4">
|
||||
<CaseToothChartPanel
|
||||
details={selectedCase.details}
|
||||
prosthesisRows={caseProsthesisRows}
|
||||
scale={0.5}
|
||||
className="min-w-0 flex-1"
|
||||
/>
|
||||
{latestCaseAttachment && selectedCaseId ? (
|
||||
<div className="shrink-0 space-y-1">
|
||||
<p className="text-xs font-medium text-text-secondary">
|
||||
{tCases('latestAttachment')}
|
||||
</p>
|
||||
<LabCaseAttachmentPreview
|
||||
caseId={selectedCaseId}
|
||||
attachment={latestCaseAttachment}
|
||||
loadBlob={loadClinicAttachmentBlob}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{selectedCase.details.length > 0 && (
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-sm font-medium text-text-primary">
|
||||
@@ -383,12 +440,13 @@ export function ConnectionCaseHistoryContent({
|
||||
className="rounded-md border border-border p-3 space-y-2"
|
||||
>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<span
|
||||
className="inline-flex items-center rounded px-2 py-0.5 text-xs font-medium border"
|
||||
<Badge
|
||||
truncate
|
||||
title={group.prosthesisTypeLabel}
|
||||
style={prosthesisTypeBadgeStyle(group.prosthesisTypeCode, groupIndex)}
|
||||
>
|
||||
{group.prosthesisTypeLabel}
|
||||
</span>
|
||||
</Badge>
|
||||
<span className="text-sm font-medium text-text-primary">
|
||||
{tCases('toothGroupTitle', {
|
||||
teeth: formatToothList(group.teeth),
|
||||
|
||||
Reference in New Issue
Block a user