"use client"; import { useMemo } from "react"; import Create from "../../modals/Create"; import Chip from "../../controls/Chip"; import InputLabel from "../../utility/InputLabel"; import ContentLockup from "../../type/ContentLockup"; import ModalTextAreaField from "../../../(app)/create/components/ModalTextAreaField"; import { useMessages, useTranslation } from "../../../contexts/MessagesContext"; import type { TemplateChipDetail } from "../../../../lib/create/templateReviewMapping"; export interface TemplateChipDetailModalProps { isOpen: boolean; onClose: () => void; detail: TemplateChipDetail | null; } /** * Read-only mirror of the custom-rule per-chip modals. Shows the exact text * from `messages/en/create/customRule/*.json` for the matched preset — never * the template `body` placeholder. When no preset is found for the chip label, * the modal surfaces a clear "details not available" note rather than falling * back to seed copy. */ export function TemplateChipDetailModal({ isOpen, onClose, detail, }: TemplateChipDetailModalProps) { const m = useMessages(); const t = useTranslation("create.templateReview.chipDetailModal"); const resolved = useMemo(() => resolveChipContent(detail, m), [detail, m]); return ( } showBackButton={false} showNextButton onNext={onClose} nextButtonText={t("closeButton")} ariaLabel={resolved?.title || "Template entry details"} >
{resolved?.body ?? (

{t("fallback.bodyLabel")}

)}
); } type ResolvedChipContent = { title: string; subtitle: string; body: React.ReactNode; }; function resolveChipContent( detail: TemplateChipDetail | null, m: ReturnType, ): ResolvedChipContent | null { if (!detail) return null; const title = detail.chipLabel; switch (detail.groupKey) { case "coreValues": { const cv = m.create.customRule.coreValues; const preset = findCoreValuePreset(cv.values, detail.chipLabel); if (!preset) return noPresetFallback(title); return { title, subtitle: cv.detailModal.subtitle, body: ( <> ), }; } case "communication": { const comm = m.create.customRule.communication; const preset = findMethodByLabel(comm.methods, detail.chipLabel); if (!preset) return noPresetFallback(title); return { title, subtitle: preset.supportText, body: ( <> ), }; } case "membership": { const mem = m.create.customRule.membership; const preset = findMethodByLabel(mem.methods, detail.chipLabel); if (!preset) return noPresetFallback(title); return { title, subtitle: preset.supportText, body: ( <> ), }; } case "decisionApproaches": { const da = m.create.customRule.decisionApproaches; const preset = findMethodByLabel(da.methods, detail.chipLabel); if (!preset) return noPresetFallback(title); return { title, subtitle: preset.supportText, body: ( <> ), }; } case "conflictManagement": { const cm = m.create.customRule.conflictManagement; const preset = findMethodByLabel(cm.methods, detail.chipLabel); if (!preset) return noPresetFallback(title); return { title, subtitle: preset.supportText, body: ( <> ), }; } default: return noPresetFallback(title); } } function noPresetFallback(title: string): ResolvedChipContent { return { title, subtitle: "", body: null }; } function noop() { /* read-only */ } /** * Minimal read-only Applicable Scope row — locked chips shown as "selected" * without the "+ Add" affordance. */ function ReadOnlyScopeField({ label, scopes, }: { label: string; scopes: readonly string[]; }) { return (
{scopes.map((scope) => ( ))}
); } function ReadOnlyValueField({ label, value, }: { label: string; value: string; }) { return (
{value}
); } /** Case-insensitive, trim-tolerant method lookup by `label`. */ function findMethodByLabel( methods: readonly T[], label: string, ): T | undefined { const normalized = label.trim().toLowerCase(); return methods.find((m) => m.label.trim().toLowerCase() === normalized); } type CoreValuePreset = { label: string; meaning: string; signals: string }; function findCoreValuePreset( values: readonly unknown[], label: string, ): CoreValuePreset | undefined { const normalized = label.trim().toLowerCase(); for (const v of values) { if ( v && typeof v === "object" && "label" in v && typeof (v as CoreValuePreset).label === "string" && (v as CoreValuePreset).label.trim().toLowerCase() === normalized ) { const preset = v as Partial; return { label: preset.label ?? label, meaning: preset.meaning ?? "", signals: preset.signals ?? "", }; } } return undefined; }