119 lines
3.5 KiB
TypeScript
119 lines
3.5 KiB
TypeScript
'use client';
|
|
|
|
import { useTranslations } from 'next-intl';
|
|
import { ConnectedSelectionBadge } from '@/components/ui/treatment/ConnectedSelectionBadge';
|
|
import { formatToothList } from '@/components/treatment/prosthesisTypeDisplay';
|
|
import { ProsthesisStackedTypeLabel } from '@/components/ui/lab/ProsthesisStackedTypeLabel';
|
|
import type { ProsthesisCatalogEntry } from '@/types/treatment-catalog';
|
|
|
|
export type LabCaseProsthesisGroup = {
|
|
prosthesisTypeCode: string;
|
|
teeth: string[];
|
|
connected?: boolean;
|
|
selectionGroupId?: string;
|
|
};
|
|
|
|
interface LabCaseProsthesisGroupsListProps {
|
|
groups: LabCaseProsthesisGroup[];
|
|
prosthesisCatalog: readonly ProsthesisCatalogEntry[];
|
|
fallbackTeeth?: string[];
|
|
}
|
|
|
|
export function LabCaseProsthesisGroupsList({
|
|
groups,
|
|
prosthesisCatalog,
|
|
fallbackTeeth = [],
|
|
}: LabCaseProsthesisGroupsListProps) {
|
|
const tTreatment = useTranslations('treatment');
|
|
const archLabels = {
|
|
UA: tTreatment('selectedArchUpper'),
|
|
LA: tTreatment('selectedArchLower'),
|
|
};
|
|
if (groups.length > 0) {
|
|
return (
|
|
<ul className="space-y-0.5">
|
|
{groups.map((group) => (
|
|
<li
|
|
key={`${group.selectionGroupId ?? ''}-${group.prosthesisTypeCode}-${group.teeth.join(',')}`}
|
|
className="text-[11px] leading-snug"
|
|
>
|
|
<ProsthesisStackedTypeLabel
|
|
className="font-medium"
|
|
code={group.prosthesisTypeCode}
|
|
catalog={prosthesisCatalog}
|
|
/>
|
|
{group.teeth.length > 0 ? (
|
|
<span className="text-text-muted">
|
|
{' · '}
|
|
{formatToothList(group.teeth, archLabels)}
|
|
</span>
|
|
) : null}
|
|
{group.connected ? (
|
|
<ConnectedSelectionBadge className="ms-1 align-middle text-[9px] px-1 py-px" />
|
|
) : null}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
);
|
|
}
|
|
|
|
if (fallbackTeeth.length > 0) {
|
|
return <p className="text-[11px] text-text-muted">{formatToothList(fallbackTeeth, archLabels)}</p>;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
export type LabCaseToothJobRow = {
|
|
teeth: string[];
|
|
codes: string[];
|
|
connected?: boolean;
|
|
};
|
|
|
|
interface LabCaseToothJobsListProps {
|
|
rows: LabCaseToothJobRow[];
|
|
prosthesisCatalog: readonly ProsthesisCatalogEntry[];
|
|
}
|
|
|
|
export function LabCaseToothJobsList({
|
|
rows,
|
|
prosthesisCatalog,
|
|
}: LabCaseToothJobsListProps) {
|
|
const tTreatment = useTranslations('treatment');
|
|
const archLabels = {
|
|
UA: tTreatment('selectedArchUpper'),
|
|
LA: tTreatment('selectedArchLower'),
|
|
};
|
|
if (rows.length === 0) return null;
|
|
|
|
return (
|
|
<ul className="space-y-1">
|
|
{rows.map((row) => (
|
|
<li
|
|
key={`${row.teeth.join(',')}-${row.codes.join('+')}`}
|
|
className="flex flex-wrap items-baseline gap-x-1.5 gap-y-0.5 text-[11px] leading-snug"
|
|
>
|
|
<span className="font-semibold text-text-primary">
|
|
{formatToothList(row.teeth, archLabels)}
|
|
</span>
|
|
{row.codes.map((code) => (
|
|
<span key={code} className="inline-flex items-baseline gap-x-1.5">
|
|
<span className="text-text-muted" aria-hidden>
|
|
·
|
|
</span>
|
|
<ProsthesisStackedTypeLabel
|
|
className="font-medium"
|
|
code={code}
|
|
catalog={prosthesisCatalog}
|
|
/>
|
|
</span>
|
|
))}
|
|
{row.connected ? (
|
|
<ConnectedSelectionBadge className="align-middle text-[9px] px-1 py-px" />
|
|
) : null}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
);
|
|
}
|