Files
dyolink/frontend/src/components/ui/lab/LabCaseProsthesisGroupsList.tsx
Admin 5d3597f973
Some checks failed
Production — tag build, push, deploy / build-and-push (push) Failing after 23s
Production — tag build, push, deploy / deploy (push) Has been skipped
improvement: icons added to prosthesis types catalog.
2026-09-05 01:29:53 +03:30

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>
);
}