'use client'; /** * IntakeStatusBlock * * Shows intake completion status: percentage, section checklist. * Uses Cortex shared components and hooks. * * Epic: E2.S1 - Intake Blocks */ import { useCortexStore } from '@/stores/cortex-store'; import { BlockContainer } from './block-container'; import type { BlockPrefillData } from '@/stores/cortex-store'; import { BLOCK_CONFIGS } from '@/lib/cortex/types'; import { ClipboardList, CheckCircle2, Circle, User, ExternalLink, } from 'lucide-react'; // Use extracted hooks and components import { useBlockData, useIntakeContext, type IntakePrefillData } from '@/lib/cortex/hooks'; import { BlockLoading, BlockError, BlockEmpty, BlockSection, BlockFooter, } from '@/components/cortex/shared'; // Import response type from API import type { IntakeStatusResponse } from '@/app/api/cortex/intake/status/route'; // ============================================================================ // Types // ============================================================================ interface IntakeStatusBlockProps { prefill?: IntakePrefillData; } // ============================================================================ // Sub-components // ============================================================================ function CompletionRing({ percentage }: { percentage: number }) { // SVG circle progress ring const radius = 40; const circumference = 2 * Math.PI * radius; const offset = circumference - (percentage / 100) * circumference; // Color based on percentage const getColor = () => { if (percentage >= 80) return 'text-green-500'; if (percentage >= 50) return 'text-amber-500'; return 'text-red-500'; }; return (
{/* Background circle */} {/* Progress circle */}
{percentage}%
); } interface SectionItemProps { label: string; completed: boolean; required: boolean; count: number; } function SectionItem({ label, completed, required, count }: SectionItemProps) { return (
{completed ? ( ) : ( )} {label} {required && !completed && ( * )}
{count > 0 && ( {count} item{count !== 1 ? 's' : ''} )}
); } // ============================================================================ // Main Component // ============================================================================ export function IntakeStatusBlock({ prefill }: IntakeStatusBlockProps) { const config = BLOCK_CONFIGS.intake_status; const { closeBlock } = useCortexStore(); // Get patient context (from prefill or activePatient) const { patientId, patientName, hasPatientContext } = useIntakeContext(prefill); // Fetch intake status data const { data, isLoading, error, refetch } = useBlockData({ endpoint: '/api/cortex/intake/status', params: { patientId: patientId || undefined, intakeId: prefill?.intakeId, }, enabled: hasPatientContext, operationName: 'Intake status laden', }); // No patient context if (!hasPatientContext) { return ( { closeBlock(); // TODO: Open zoeken block }, }} /> ); } // Loading state if (isLoading) { return ( ); } // Error state if (error) { return ( ); } // No data if (!data) { return ( ); } // Separate required and optional sections const requiredSections = data.sections.filter((s) => s.required); const optionalSections = data.sections.filter((s) => !s.required); return (
{/* Patient name header */} {patientName && (
Patiënt: {patientName}
)} {/* Completion overview */}

{data.completionPercentage === 100 ? 'Intake compleet!' : data.completionPercentage >= 80 ? 'Bijna klaar' : 'Intake in uitvoering'}

{data.completedCount} van {data.totalRequired} verplichte secties ingevuld

{data.status === 'afgerond' && ( Afgerond )}
{/* Required sections */} s.completed).length} >
{requiredSections.map((section) => ( ))}
{/* Optional sections */} s.completed).length} >
{optionalSections.map((section) => ( ))}
{/* Footer with actions */} { // Navigate to intake page const url = `/epd/patients/${data.patientId}/intakes/${data.intakeId}`; window.location.href = url; }, }} />
); }