"use client"; import { useSafeIntl } from "@kopexa/i18n"; import { CheckCirleIcon, EditIcon } from "@kopexa/icons"; import { Button, Card, Chip, Heading, Separator, Textarea, } from "@kopexa/sight"; import { useState } from "react"; import { messages } from "./messages"; import type { RiskTreatment, RiskTreatmentValue } from "./types"; // ============================================ // Types // ============================================ export interface RiskTreatmentCardProps { /** The current treatment value */ value?: RiskTreatmentValue; /** Callback when the treatment changes */ onChange?: (value: RiskTreatmentValue) => void; /** Make the component read-only */ readOnly?: boolean; /** Custom title for the card */ title?: string; /** Recommended treatment based on risk level */ recommended?: RiskTreatment; } // ============================================ // Treatment Option Component // ============================================ interface TreatmentOptionProps { id: RiskTreatment; label: string; description: string; hint?: string; isSelected: boolean; isRecommended: boolean; recommendedLabel: string; onSelect: (id: RiskTreatment) => void; } function TreatmentOption({ id, label, description, hint, isSelected, isRecommended, recommendedLabel, onSelect, }: TreatmentOptionProps) { return ( onSelect(id)} className={` w-full text-left p-4 rounded-lg border-2 transition-all ${ isSelected ? "border-primary bg-primary/5" : "border-border hover:border-primary/50 hover:bg-muted/50" } `} > {/* Radio indicator */} {isSelected && ( )} {/* Content */} {label} {isRecommended && ( {recommendedLabel} )} {description} {hint && ( → {hint} )} ); } // ============================================ // Main Component // ============================================ const defaultValue: RiskTreatmentValue = { treatment: "not_defined", rationale: undefined, }; export function RiskTreatmentCard({ value, onChange, readOnly = false, title, recommended, }: RiskTreatmentCardProps) { const intl = useSafeIntl(); const [isEditing, setIsEditing] = useState(false); const [editValues, setEditValues] = useState( value || defaultValue, ); // i18n labels const t = { title: intl.formatMessage(messages.title), strategyLabel: intl.formatMessage(messages.strategy_label), strategyPrompt: intl.formatMessage(messages.strategy_prompt), rationaleLabel: intl.formatMessage(messages.rationale_label), rationalePlaceholder: intl.formatMessage(messages.rationale_placeholder), noRationale: intl.formatMessage(messages.no_rationale), edit: intl.formatMessage(messages.edit), cancel: intl.formatMessage(messages.cancel), save: intl.formatMessage(messages.save), recommended: intl.formatMessage(messages.recommended), // Treatment labels acceptLabel: intl.formatMessage(messages.accept_label), mitigateLabel: intl.formatMessage(messages.mitigate_label), transferLabel: intl.formatMessage(messages.transfer_label), avoidLabel: intl.formatMessage(messages.avoid_label), notDefinedLabel: intl.formatMessage(messages.not_defined_label), // Treatment descriptions acceptDescription: intl.formatMessage(messages.accept_description), mitigateDescription: intl.formatMessage(messages.mitigate_description), transferDescription: intl.formatMessage(messages.transfer_description), avoidDescription: intl.formatMessage(messages.avoid_description), // Treatment hints acceptHint: intl.formatMessage(messages.accept_hint), mitigateHint: intl.formatMessage(messages.mitigate_hint), transferHint: intl.formatMessage(messages.transfer_hint), avoidHint: intl.formatMessage(messages.avoid_hint), }; const treatmentLabels: Record = { accept: t.acceptLabel, mitigate: t.mitigateLabel, transfer: t.transferLabel, avoid: t.avoidLabel, not_defined: t.notDefinedLabel, }; const treatmentOptions: Array<{ id: RiskTreatment; label: string; description: string; hint: string; }> = [ { id: "accept", label: t.acceptLabel, description: t.acceptDescription, hint: t.acceptHint, }, { id: "mitigate", label: t.mitigateLabel, description: t.mitigateDescription, hint: t.mitigateHint, }, { id: "transfer", label: t.transferLabel, description: t.transferDescription, hint: t.transferHint, }, { id: "avoid", label: t.avoidLabel, description: t.avoidDescription, hint: t.avoidHint, }, ]; const cardTitle = title ?? t.title; const currentValue = isEditing ? editValues : value || defaultValue; const isNotDefined = currentValue.treatment === "not_defined"; const handleSave = () => { onChange?.(editValues); setIsEditing(false); }; const handleCancel = () => { setEditValues(value || defaultValue); setIsEditing(false); }; const handleStartEdit = () => { setEditValues(value || defaultValue); setIsEditing(true); }; const handleTreatmentSelect = (treatment: RiskTreatment) => { setEditValues((prev) => ({ ...prev, treatment })); }; const handleRationaleChange = (rationale: string) => { setEditValues((prev) => ({ ...prev, rationale: rationale || undefined })); }; return ( {cardTitle} {isEditing && ( {t.edit} )} {!readOnly && (!isEditing ? ( ) : ( {t.cancel} {t.save} ))} {isEditing ? ( <> {/* Edit Mode: Treatment Selection */} {t.strategyPrompt} {treatmentOptions.map((option) => ( ))} {/* Edit Mode: Rationale */} {t.rationaleLabel} handleRationaleChange(e.target.value)} placeholder={t.rationalePlaceholder} rows={3} className="text-sm" /> > ) : ( <> {/* View Mode: Selected Strategy */} {t.strategyLabel} {!isNotDefined && ( )} {treatmentLabels[currentValue.treatment]} {/* View Mode: Rationale */} {t.rationaleLabel} {currentValue.rationale || t.noRationale} > )} ); }
{description}
→ {hint}
{t.strategyPrompt}
{t.strategyLabel}
{treatmentLabels[currentValue.treatment]}
{t.rationaleLabel}
{currentValue.rationale || t.noRationale}