'use client'; /** * Patient Context Card Component * * Displays medical context (conditions, risks, vitals) for a patient * in the appointment modal. Collapsible by default. */ import React, { useEffect, useState } from 'react'; import { AlertTriangle, Activity, Stethoscope, Loader2, ChevronDown, ChevronRight } from 'lucide-react'; import type { PatientDetail, Condition, RiskAssessment, VitalSign } from '@/lib/types/overdracht'; interface PatientContextCardProps { patientId: string; } // Risk type labels in Dutch const RISK_TYPE_LABELS: Record = { suiciderisico: 'Suicide', agressie: 'Agressie', terugval: 'Terugval', automutilatie: 'Automutilatie', verwaarlozing: 'Verwaarlozing', weglopen: 'Weglopen', }; // Risk level colors const RISK_LEVEL_STYLES: Record = { zeer_hoog: { bg: 'bg-red-100', text: 'text-red-800', dot: 'bg-red-500' }, hoog: { bg: 'bg-red-100', text: 'text-red-700', dot: 'bg-red-500' }, gemiddeld: { bg: 'bg-amber-100', text: 'text-amber-800', dot: 'bg-amber-500' }, laag: { bg: 'bg-green-100', text: 'text-green-800', dot: 'bg-green-500' }, }; export function PatientContextCard({ patientId }: PatientContextCardProps) { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const [isExpanded, setIsExpanded] = useState(false); useEffect(() => { const fetchContext = async () => { setIsLoading(true); setError(null); try { const response = await fetch(`/api/overdracht/${patientId}`); if (!response.ok) { throw new Error('Kon patient context niet laden'); } const result = await response.json(); setData(result); } catch (err) { setError(err instanceof Error ? err.message : 'Onbekende fout'); } finally { setIsLoading(false); } }; fetchContext(); }, [patientId]); // Loading state if (isLoading) { return (
Medische context laden...
); } // Error state if (error) { return null; // Silently fail - don't block the modal } // No data or all arrays empty if (!data) { return null; } const hasConditions = data.conditions.length > 0; const hasRisks = data.risks.length > 0; const hasVitals = data.vitals.length > 0; // Nothing to show if (!hasConditions && !hasRisks && !hasVitals) { return null; } // Sort risks by level (highest first) const sortedRisks = [...data.risks].sort((a, b) => { const order = ['zeer_hoog', 'hoog', 'gemiddeld', 'laag']; return order.indexOf(a.risk_level) - order.indexOf(b.risk_level); }); // Filter to significant risks only (gemiddeld and up) const significantRisks = sortedRisks.filter( (r) => r.risk_level === 'zeer_hoog' || r.risk_level === 'hoog' || r.risk_level === 'gemiddeld' ); // Build summary for collapsed state const summaryParts: string[] = []; if (hasConditions) summaryParts.push(`${data.conditions.length} diagnose${data.conditions.length > 1 ? 's' : ''}`); if (significantRisks.length > 0) summaryParts.push(`${significantRisks.length} risico${significantRisks.length > 1 ? "'s" : ''}`); if (hasVitals) summaryParts.push(`${data.vitals.length} vital${data.vitals.length > 1 ? 's' : ''}`); return (
{/* Collapsible header */} {/* Expanded content */} {isExpanded && (
{/* Risks - Always show first if present (most important) */} {significantRisks.length > 0 && (
Risico's
{significantRisks.map((risk) => ( ))}
)} {/* Conditions */} {hasConditions && (
Diagnoses
{data.conditions.slice(0, 3).map((condition) => ( ))} {data.conditions.length > 3 && (
+ {data.conditions.length - 3} meer
)}
)} {/* Vitals (today only) */} {hasVitals && (
Vitals vandaag
{data.vitals.slice(0, 4).map((vital) => ( ))}
)}
)}
); } function RiskBadge({ risk }: { risk: RiskAssessment }) { const styles = RISK_LEVEL_STYLES[risk.risk_level] || RISK_LEVEL_STYLES.laag; const label = RISK_TYPE_LABELS[risk.risk_type] || risk.risk_type; const levelLabel = risk.risk_level === 'zeer_hoog' ? 'Zeer hoog' : risk.risk_level.charAt(0).toUpperCase() + risk.risk_level.slice(1); return ( {label}: {levelLabel} ); } function ConditionItem({ condition }: { condition: Condition }) { return (
{condition.code_display}
); } function VitalItem({ vital }: { vital: VitalSign }) { const isAbnormal = vital.interpretation_code === 'H' || vital.interpretation_code === 'L'; return (
{vital.code_display}:{' '} {vital.value_quantity_value} {vital.value_quantity_unit && ` ${vital.value_quantity_unit}`}
); }