diff --git a/src/components/PMRInterface.tsx b/src/components/PMRInterface.tsx index 0dac10f..8073e05 100644 --- a/src/components/PMRInterface.tsx +++ b/src/components/PMRInterface.tsx @@ -6,6 +6,7 @@ import { SummaryView } from './views/SummaryView' import { ConsultationsView } from './views/ConsultationsView' import { MedicationsView } from './views/MedicationsView' import { ProblemsView } from './views/ProblemsView' +import { InvestigationsView } from './views/InvestigationsView' interface PMRInterfaceProps { children?: React.ReactNode @@ -46,6 +47,8 @@ export function PMRInterface({ children }: PMRInterfaceProps) { return case 'problems': return + case 'investigations': + return default: return (
diff --git a/src/components/views/InvestigationsView.tsx b/src/components/views/InvestigationsView.tsx new file mode 100644 index 0000000..122a249 --- /dev/null +++ b/src/components/views/InvestigationsView.tsx @@ -0,0 +1,239 @@ +import { useState, useEffect, useRef } from 'react' +import { ChevronDown, ChevronUp, ExternalLink, Circle } from 'lucide-react' +import { investigations } from '@/data/investigations' +import type { Investigation } from '@/types/pmr' + +type InvestigationStatus = 'Complete' | 'Ongoing' | 'Live' + +function StatusBadge({ status }: { status: InvestigationStatus }) { + if (status === 'Live') { + return ( +
+ + + + + Live +
+ ) + } + + const colorMap: Record, { bg: string; label: string }> = { + Complete: { bg: 'bg-green-500', label: 'Complete' }, + Ongoing: { bg: 'bg-amber-500', label: 'Ongoing' }, + } + + const { bg, label } = colorMap[status as Exclude] + + return ( +
+ + {label} +
+ ) +} + +function InvestigationRow({ + investigation, + isExpanded, + onToggle, +}: { + investigation: Investigation + isExpanded: boolean + onToggle: () => void +}) { + const contentRef = useRef(null) + const [contentHeight, setContentHeight] = useState(undefined) + const prefersReducedMotion = useRef( + window.matchMedia('(prefers-reduced-motion: reduce)').matches + ).current + + useEffect(() => { + if (contentRef.current) { + setContentHeight(contentRef.current.scrollHeight) + } + }, [isExpanded]) + + return ( + <> + + + {investigation.name} + + + {investigation.requestedYear} + + + + + + {investigation.resultSummary} + + + + + + + +
+
+
+
+ Date Requested: + {investigation.requestedYear} +
+
+ Date Reported: + {investigation.reportedYear ?? 'Pending'} +
+
+ Status: + + {investigation.status} + {investigation.status === 'Live' && investigation.externalUrl && ( + <> — Live at {investigation.externalUrl.replace('https://', '')} + )} + +
+
+ Requesting Clinician: + {investigation.requestingClinician} +
+
+ Methodology: + {investigation.methodology} +
+
+ Results: +
    + {investigation.results.map((result, idx) => ( +
  • + - + {result} +
  • + ))} +
+
+
+ Tech Stack: + {investigation.techStack.join(', ')} +
+
+ {investigation.externalUrl && ( + + )} +
+
+ + + + ) +} + +export function InvestigationsView() { + const [expandedId, setExpandedId] = useState(null) + + const handleToggle = (id: string) => { + setExpandedId(expandedId === id ? null : id) + } + + return ( +
+
+

+ Investigation Results +

+

+ Projects presented as diagnostic investigations — tests that were ordered, performed, and returned results. +

+
+
+ + + + + + + + + + + + {investigations.map((investigation) => ( + handleToggle(investigation.id)} + /> + ))} + +
+ Test Name + + Requested + + Status + + Result + + Expand +
+
+ {investigations.length === 0 && ( +
No investigation results
+ )} +
+ ) +}