Files
dyolink/frontend/src/components/ui/treatment/LabDispatchAttentionPanel.tsx

117 lines
4.4 KiB
TypeScript

'use client';
import { useTranslations } from 'next-intl';
import { AlertTriangle } from 'lucide-react';
import { Button } from '@/components/ui/shared/Button';
import { DetailLabSendBadge } from '@/components/ui/treatment/DetailLabSendBadge';
import { TreatmentTypeBadge } from '@/components/ui/treatment/TreatmentTypeBadge';
import { treatmentTypeLabelFromCatalog } from '@/components/shared/treatmentTypeDisplay';
import type { LabDispatchAttentionItem } from '@/components/treatment/labDispatchAttention';
import type { LinkedOrganizationOption } from '@/types/treatment';
import type { TreatmentCatalogEntry } from '@/types/treatment-catalog';
interface LabDispatchAttentionPanelProps {
items: LabDispatchAttentionItem[];
treatmentCatalog: TreatmentCatalogEntry[];
labDependentCodes: Set<string>;
orgs?: LinkedOrganizationOption[];
onGoToDispatch: (item: LabDispatchAttentionItem) => void;
compact?: boolean;
}
export function LabDispatchAttentionPanel({
items,
treatmentCatalog,
labDependentCodes,
orgs,
onGoToDispatch,
compact = false,
}: LabDispatchAttentionPanelProps) {
const t = useTranslations('treatment');
if (items.length === 0) {
return null;
}
return (
<div className={compact ? 'space-y-2 pt-2' : 'surface-card p-4 space-y-3 border border-amber-500/35 bg-amber-500/5'}>
{!compact ? (
<div className="flex items-start gap-2">
<AlertTriangle className="h-4 w-4 text-amber-600 dark:text-amber-400 shrink-0 mt-0.5 icon-flat" />
<div className="min-w-0">
<h3 className="text-sm font-semibold text-text-primary">{t('labAttentionTitle')}</h3>
<p className="text-[11px] text-text-muted mt-0.5">{t('labAttentionSubtitle')}</p>
</div>
</div>
) : null}
<ul
className={`space-y-1.5 overflow-y-auto overscroll-y-contain pr-1 ${
compact ? 'max-h-[min(200px,30vh)]' : 'max-h-[min(240px,35vh)]'
}`}
>
{items.map((item) => {
const teeth = item.detail.teeth.length
? [...item.detail.teeth].sort().join(', ')
: t('teethNone');
const dateLabel = new Date(item.treatmentAt).toLocaleDateString(undefined, {
month: 'short',
day: 'numeric',
year: 'numeric',
});
return (
<li
key={item.key}
className={`flex flex-col gap-1.5 rounded-[var(--radius-sm)] border border-border/60 bg-background-secondary/40 px-2 py-1.5 sm:flex-row sm:items-center sm:justify-between ${
compact ? '' : ''
}`}
>
<div className="min-w-0 space-y-1">
<div className="flex flex-wrap items-center gap-1.5">
<time className="text-[11px] font-medium text-text-primary tabular-nums">
{dateLabel}
</time>
{item.isCurrentDraft ? (
<span className="text-[10px] uppercase tracking-wide text-primary font-medium">
{t('labAttentionCurrentDraft')}
</span>
) : null}
</div>
<div className="flex flex-wrap items-center gap-1.5 min-w-0">
<span className="text-[11px] text-text-muted tabular-nums">
{t('detailLabel', { n: item.detailNumber })}
</span>
<TreatmentTypeBadge
type={item.detail.treatmentType}
label={treatmentTypeLabelFromCatalog(
item.detail.treatmentType,
treatmentCatalog,
)}
/>
<DetailLabSendBadge
detail={item.detail}
labDependentCodes={labDependentCodes}
orgs={orgs}
/>
</div>
<p className="text-[11px] text-text-secondary truncate">
{t('teethLabel')} {teeth}
</p>
</div>
<Button
type="button"
variant="primary"
className={`shrink-0 w-full sm:w-auto text-xs ${compact ? 'py-1' : 'py-1.5'}`}
onClick={() => onGoToDispatch(item)}
>
{item.isCurrentDraft ? t('labAttentionGoDispatch') : t('labAttentionLoadDispatch')}
</Button>
</li>
);
})}
</ul>
</div>
);
}