import React, { useMemo, useState, useCallback } from 'react' import { motion, AnimatePresence } from 'framer-motion' import { ChevronRight } from 'lucide-react' import { useDetailPanel } from '@/contexts/DetailPanelContext' import { timelineEntities, timelineConsultations } from '@/data/timeline' import type { TimelineEntity } from '@/types/pmr' const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches function hexToRgba(hex: string, opacity: number): string { const r = parseInt(hex.slice(1, 3), 16) const g = parseInt(hex.slice(3, 5), 16) const b = parseInt(hex.slice(5, 7), 16) return `rgba(${r},${g},${b},${opacity})` } interface TimelineInterventionItemProps { entity: TimelineEntity isExpanded: boolean isHighlightedFromGraph: boolean isEducationAnchor: boolean onToggle: () => void onViewFull: () => void onHighlight?: (id: string | null) => void } function TimelineInterventionItem({ entity, isExpanded, isHighlightedFromGraph, isEducationAnchor, onToggle, onViewFull, onHighlight, }: TimelineInterventionItemProps) { const isEducation = entity.kind === 'education' const interventionLabel = isEducation ? 'Education Intervention' : 'Career Intervention' const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault() onToggle() } if (e.key === 'Escape' && isExpanded) { e.preventDefault() onToggle() } }, [isExpanded, onToggle], ) return (
onHighlight?.(entity.id)} onMouseLeave={() => onHighlight?.(null)} >
{ if (!isExpanded) { e.currentTarget.parentElement!.style.borderColor = hexToRgba(entity.orgColor, 0.2) e.currentTarget.parentElement!.style.boxShadow = 'var(--shadow-md)' } }} onMouseLeave={(e) => { if (!isExpanded) { e.currentTarget.parentElement!.style.borderColor = 'var(--border-light)' e.currentTarget.parentElement!.style.boxShadow = 'none' } }} > {isExpanded && (
    {entity.details.map((detail, i) => (
  • ))}
{!!entity.codedEntries?.length && (
{entity.codedEntries.map((entry) => ( {entry.code}: {entry.description} ))}
)}
)}
) } interface TimelineInterventionsSubsectionProps { onNodeHighlight?: (id: string | null) => void highlightedRoleId?: string | null } export function TimelineInterventionsSubsection({ onNodeHighlight, highlightedRoleId }: TimelineInterventionsSubsectionProps) { const [expandedId, setExpandedId] = useState(null) const { openPanel } = useDetailPanel() const consultationsById = useMemo( () => new Map(timelineConsultations.map((consultation) => [consultation.id, consultation])), [], ) const firstEducationId = useMemo( () => timelineEntities.find((entity) => entity.kind === 'education')?.id ?? null, [], ) const handleToggle = useCallback((id: string) => { setExpandedId((prev) => (prev === id ? null : id)) }, []) const handleViewFull = useCallback((entity: TimelineEntity) => { const consultation = consultationsById.get(entity.id) if (!consultation) return openPanel({ type: 'career-role', consultation }) }, [consultationsById, openPanel]) return (
{timelineEntities.map((entity) => ( handleToggle(entity.id)} onViewFull={() => handleViewFull(entity)} onHighlight={onNodeHighlight} /> ))}
) }