'use client';
import { memo, type ReactNode } from 'react';
import type { FdiToothId } from '@/types/treatment';
import type { ToothShapeKind } from '@/components/treatment/fdiToothMeta';
import { getToothPathModel, type ToothPathModel } from '@/components/ui/treatment/toothPathModel';
interface ToothGlyphProps {
fdi: FdiToothId;
kind: ToothShapeKind;
gradientId: string;
selected: boolean;
upper?: boolean;
mirrored?: boolean;
upsideDown?: boolean;
className?: string;
}
function filledSilhouette(
model: ToothPathModel,
crownFill: string,
rootFill: string,
stroke: string,
strokeW: number,
): ReactNode {
return (
<>
{model.roots.map((d, i) => (
))}
>
);
}
function detailOnly(model: ToothPathModel, stroke: string, strokeW: number): ReactNode {
if (!model.detailStroke) return null;
const { d, widthScale } = model.detailStroke;
return ;
}
function renderClinicalFill(model: ToothPathModel, selected: boolean, gradientId: string): ReactNode {
const stroke = selected ? 'var(--color-primary)' : '#1e293b';
const strokeW = selected ? 2.4 : 1.35;
const fill = `url(#${gradientId})`;
return (
<>
{filledSilhouette(model, fill, fill, stroke, strokeW)}
{detailOnly(model, stroke, strokeW)}
>
);
}
/** FDI chart tooth: clinical gradient + roots only. */
export const ToothGlyph = memo(function ToothGlyph({
fdi,
kind,
gradientId,
selected,
upper,
mirrored,
upsideDown,
className = 'w-8 h-[4.85rem]',
}: ToothGlyphProps) {
const model: ToothPathModel | null = getToothPathModel(fdi, kind, upper);
const filter = selected ? 'drop-shadow(0 0 6px rgba(9, 169, 188, 0.65))' : undefined;
if (!model) {
return (
);
}
const body = renderClinicalFill(model, selected, gradientId);
return (
);
});