'use client'; import { useRef } from 'react'; import { useTranslations } from 'next-intl'; import { Trash2 } from 'lucide-react'; import { Button } from '@/components/ui/shared/Button'; import { Dropdown } from '@/components/ui/shared/Dropdown'; import { autosaveStatusClass, labPendingBannerClass, labSentBannerClass, labBlockedBannerClass, } from '@/components/treatment/treatmentStatusStyles'; import type { TreatmentDetailDraft } from '@/types/treatment'; import type { TreatmentCatalogEntry } from '@/types/treatment-catalog'; import { treatmentTypeColor } from '@/components/shared/treatmentTypeDisplay'; import { isDetailReadyForLabDispatch, isDetailTypeSelected, isLabDependentDetailMissingTeeth, } from '@/components/treatment/treatmentDetailRules'; interface TreatmentDetailsEditorProps { details: TreatmentDetailDraft[]; activeDetailId: string; onActiveDetailChange: (id: string) => void; onDetailsChange: (details: TreatmentDetailDraft[]) => void; isDetailLocked: (detail: TreatmentDetailDraft) => boolean; labDependentCodes: Set; treatmentCatalog: TreatmentCatalogEntry[]; disabled: boolean; canEdit: boolean; saveStatus: 'idle' | 'dirty' | 'saving' | 'saved' | 'error'; uploadBusy: boolean; onAddDetail: () => void; onRemoveDetail?: (detailClientId: string) => void; onUploadFiles: (files: FileList | null) => void; /** Detail chips + Add detail (default true). */ showChrome?: boolean; /** Type / notes / attachments fields (default true). */ showFields?: boolean; } export function TreatmentDetailsEditor({ details, activeDetailId, onActiveDetailChange, onDetailsChange, isDetailLocked, labDependentCodes, treatmentCatalog, disabled, canEdit, saveStatus, uploadBusy, onAddDetail, onRemoveDetail, onUploadFiles, showChrome = true, showFields = true, }: TreatmentDetailsEditorProps) { const t = useTranslations('treatment'); const tCommon = useTranslations('common'); const attachmentInputRef = useRef(null); const activeDetail = details.find((d) => d.clientId === activeDetailId) ?? details[0]; if (!activeDetail) return null; const locked = isDetailLocked(activeDetail); const readOnly = disabled || locked; const treatmentTypeTextColor = isDetailTypeSelected(activeDetail) ? treatmentTypeColor( activeDetail.treatmentType, treatmentCatalog.findIndex((e) => e.code === activeDetail.treatmentType), ) : undefined; const showPendingLabHint = isDetailReadyForLabDispatch(activeDetail, labDependentCodes) && !locked && !readOnly; const showMissingTeethLabBlock = isLabDependentDetailMissingTeeth( activeDetail, labDependentCodes, ); if (!showChrome && !showFields) return null; return (
{showChrome ? ( <>

{t('detailsTitle')}

{t('detailsSubtitle')}

{details.map((d, idx) => { const detailLocked = isDetailLocked(d); const isActive = d.clientId === activeDetailId; // Same rules as the former Content-step delete button: // only when more than one detail remains; disabled if no edit, day-locked, sent, or uploading. const showRemoveAction = details.length > 1; const removeDisabled = !canEdit || disabled || detailLocked || uploadBusy; return (
{showRemoveAction ? ( ) : null}
); })}
) : null} {showFields ? (
{locked &&

{t('detailLockedInShipment')}

} {showPendingLabHint && (

{t('detailPendingLabSend')}

)} {showMissingTeethLabBlock && (

{t('labShipmentBlockedBody')}

)}
{ const nextType = e.target.value as TreatmentDetailDraft['treatmentType']; onDetailsChange( details.map((d) => d.clientId === activeDetailId ? { ...d, treatmentType: nextType } : d, ), ); }} disabled={readOnly} style={{ color: treatmentTypeTextColor }} > {treatmentCatalog.map((entry, index) => ( ))}