"use client"; import Link from "next/link"; import { useEffect, useState, useCallback, useMemo, useRef } from "react"; import { getSessionHistory, downloadSessionCSV, downloadSessionJSON, clearSessionHistory } from "@/lib/edge/history"; import { HistoryRecord } from "@/lib/edge/types"; import { FileText, Printer, X, Database, HardDrive, RefreshCw, Copy, Check, Download, PlusCircle, Activity } from "lucide-react"; interface RawCloudRecord { id: number; timestamp: string; heart_rate: number; spo2: number; sys_bp: number; dia_bp: number; temp?: number; body_temp?: number; prediction_label: string; confidence: number; } const SAMPLE_CLINICAL_RECORDS: HistoryRecord[] = [ { id: 1001, timestamp: "2026-10-18 22:45:10", heart_rate: 74, spo2: 98, sys_bp: 118, dia_bp: 78, body_temp: 37.0, prediction_label: "Normal", confidence: 0.985, is_at_risk: false, }, { id: 1002, timestamp: "2026-10-18 22:46:25", heart_rate: 76, spo2: 98, sys_bp: 120, dia_bp: 80, body_temp: 37.1, prediction_label: "Normal", confidence: 0.978, is_at_risk: false, }, { id: 1003, timestamp: "2026-10-18 22:47:40", heart_rate: 128, spo2: 91, sys_bp: 165, dia_bp: 104, body_temp: 37.3, prediction_label: "Heart Disease", confidence: 0.942, is_at_risk: true, }, { id: 1004, timestamp: "2026-10-18 22:48:55", heart_rate: 124, spo2: 92, sys_bp: 158, dia_bp: 98, body_temp: 37.2, prediction_label: "Heart Disease", confidence: 0.915, is_at_risk: true, }, { id: 1005, timestamp: "2026-10-18 22:50:10", heart_rate: 88, spo2: 96, sys_bp: 135, dia_bp: 88, body_temp: 37.0, prediction_label: "Normal", confidence: 0.962, is_at_risk: false, }, { id: 1006, timestamp: "2026-10-18 22:51:25", heart_rate: 98, spo2: 96, sys_bp: 195, dia_bp: 118, body_temp: 37.1, prediction_label: "Hypertension", confidence: 0.971, is_at_risk: true, }, { id: 1007, timestamp: "2026-10-18 22:52:40", heart_rate: 78, spo2: 97, sys_bp: 124, dia_bp: 82, body_temp: 36.9, prediction_label: "Normal", confidence: 0.981, is_at_risk: false, }, { id: 1008, timestamp: "2026-10-18 22:53:55", heart_rate: 72, spo2: 99, sys_bp: 116, dia_bp: 76, body_temp: 36.8, prediction_label: "Normal", confidence: 0.993, is_at_risk: false, }, ]; export default function PatientHistory() { const [sourceTab, setSourceTab] = useState<"session" | "cloud">("session"); const [records, setRecords] = useState([]); const [cloudRecords, setCloudRecords] = useState([]); const [loading, setLoading] = useState(true); const [cloudLoading, setCloudLoading] = useState(false); const [showReportModal, setShowReportModal] = useState(false); const [reportCopied, setReportCopied] = useState(false); const tableSectionRef = useRef(null); const refreshSessionHistory = useCallback(() => { setRecords(getSessionHistory()); setLoading(false); }, []); const fetchCloudHistory = useCallback(async () => { setCloudLoading(true); try { const apiUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000"; const res = await fetch(`${apiUrl}/history`); if (res.ok) { const raw = (await res.json()) as RawCloudRecord[]; if (Array.isArray(raw)) { const formatted: HistoryRecord[] = raw.map((r: RawCloudRecord) => ({ id: r.id, timestamp: r.timestamp, heart_rate: r.heart_rate, spo2: r.spo2, sys_bp: r.sys_bp, dia_bp: r.dia_bp, body_temp: r.temp ?? r.body_temp ?? 37.0, prediction_label: r.prediction_label, confidence: r.confidence, is_at_risk: Boolean(r.prediction_label && r.prediction_label.toLowerCase() !== "normal" && r.prediction_label.toLowerCase() !== "healthy") })); setCloudRecords(formatted); } } } catch { // cloud unavailable } finally { setCloudLoading(false); } }, []); useEffect(() => { const timer = setTimeout(() => { refreshSessionHistory(); }, 0); const interval = setInterval(() => { setRecords(getSessionHistory()); }, 1500); return () => { clearTimeout(timer); clearInterval(interval); }; }, [refreshSessionHistory]); const activeRecords = sourceTab === "session" ? records : cloudRecords; const isLoading = sourceTab === "session" ? loading : cloudLoading; const handleClear = () => { if (confirm("Are you sure you want to clear the active session telemetry log?")) { clearSessionHistory(); setRecords([]); } }; const handleLoadSampleRecords = () => { if (typeof window !== "undefined") { sessionStorage.setItem("heartflow_session_log_v2", JSON.stringify(SAMPLE_CLINICAL_RECORDS)); } setRecords(SAMPLE_CLINICAL_RECORDS); setTimeout(() => { tableSectionRef.current?.scrollIntoView({ behavior: "smooth", block: "start" }); }, 60); }; const handleOpenReport = () => { if (activeRecords.length === 0) { if (sourceTab === "session") { handleLoadSampleRecords(); } else { setCloudRecords(SAMPLE_CLINICAL_RECORDS); } } setShowReportModal(true); }; const recordsToAnalyze = activeRecords.length > 0 ? activeRecords : SAMPLE_CLINICAL_RECORDS; // Summary Metrics for Clinical Report const metrics = useMemo(() => { const list = recordsToAnalyze; if (!list || list.length === 0) return null; const hrs = list.map(r => Number(r.heart_rate) || 75); const spo2s = list.map(r => Number(r.spo2) || 98); const sbps = list.map(r => Number(r.sys_bp) || 120); const dbps = list.map(r => Number(r.dia_bp) || 80); const anomalies = list.filter(r => r.is_at_risk || (r.prediction_label && r.prediction_label.toLowerCase() !== "normal" && r.prediction_label.toLowerCase() !== "healthy")); const meanHr = Math.round(hrs.reduce((a, b) => a + b, 0) / (hrs.length || 1)); const maxHr = Math.max(...hrs); const minHr = Math.min(...hrs); const meanSpo2 = Math.round(spo2s.reduce((a, b) => a + b, 0) / (spo2s.length || 1)); const nadirSpo2 = Math.min(...spo2s); const meanSbp = Math.round(sbps.reduce((a, b) => a + b, 0) / (sbps.length || 1)); const meanDbp = Math.round(dbps.reduce((a, b) => a + b, 0) / (dbps.length || 1)); const mapValue = Math.round((2 * meanDbp + meanSbp) / 3); const shockIndex = meanSbp > 0 ? (meanHr / meanSbp).toFixed(2) : "0.62"; const riskRate = ((anomalies.length / (list.length || 1)) * 100).toFixed(1); // Find top diagnostic consensus const counts: Record = {}; list.forEach(r => { const lbl = r.prediction_label || "Normal"; counts[lbl] = (counts[lbl] || 0) + 1; }); const topDiagnosis = Object.keys(counts).reduce((a, b) => counts[a] > counts[b] ? a : b, "Normal"); const meanConfidence = list.reduce((a, b) => a + (Number(b.confidence) || 0.95), 0) / (list.length || 1); // Cryptographic-style pseudo hash for verification audit const hash = Array.from(JSON.stringify(list.slice(0, 5))) .reduce((h, c) => Math.imul(31, h) + c.charCodeAt(0) | 0, 0) .toString(16) .toUpperCase() .padStart(8, "0"); const narrative = `During this monitoring evaluation across ${list.length} recorded telemetry intervals, ${anomalies.length} observations triggered cardiovascular risk indicators (${riskRate}% risk burden). Primary consensus classification aligns with ${topDiagnosis} with ${(meanConfidence * 100).toFixed(1)}% ensemble model agreement. Mean arterial pressure is maintained at ${mapValue} mmHg with clinical shock index ${shockIndex}. Lead-II electrophysiological tracing conforms to active TinyML inference boundaries.`; return { meanHr, maxHr, minHr, meanSpo2, nadirSpo2, meanSbp, meanDbp, mapValue, shockIndex, anomalyCount: anomalies.length, total: list.length, riskRate, topDiagnosis, meanConfidence, narrative, hash }; }, [recordsToAnalyze]); const generateReportText = () => { if (!metrics) return ""; return `================================================================================ HEARTFLOW_OS CLINICAL TELEMETRY & DISCHARGE SUMMARY REPORT Document Reference: HFL-REP-${metrics.hash} Generated: ${new Date().toISOString().replace("T", " ").substring(0, 19)} UTC Patient Reference: PT-9428-A Telemetry Source: ${sourceTab === "session" ? "Active Browser Session" : "Persistent Database Archive"} Total Intervals Evaluated: ${metrics.total} ================================================================================ 1. PATIENT PHYSIOLOGICAL BIOMARKERS SUMMARY: -------------------------------------------------------------------------------- - Mean Heart Rate: ${metrics.meanHr} BPM (Observed Range: ${metrics.minHr} - ${metrics.maxHr} BPM) - Mean SpO2 Saturation: ${metrics.meanSpo2}% (Nadir SpO2: ${metrics.nadirSpo2}%) - Mean Blood Pressure: ${metrics.meanSbp}/${metrics.meanDbp} mmHg - Mean Arterial Pressure: ${metrics.mapValue} mmHg - Clinical Shock Index: ${metrics.shockIndex} (Reference Range: 0.5 - 0.7) - Anomaly Burden: ${metrics.riskRate}% (${metrics.anomalyCount} of ${metrics.total} intervals flagged) 2. ENSEMBLE DIAGNOSTIC CONSENSUS: -------------------------------------------------------------------------------- - Primary Consensus: ${metrics.topDiagnosis} - Ensemble Confidence: ${(metrics.meanConfidence * 100).toFixed(1)}% - Classifier Architecture: 5-Model Soft Voting (Random Forest, Linear SVM, KNN, Logistic Regression, MLP Neural Network) - Microcontroller Target: INT8 Fixed-Point C99 Zero-Heap Firmware 3. CLINICAL NARRATIVE: -------------------------------------------------------------------------------- ${metrics.narrative} 4. AUDIT & VERIFICATION: -------------------------------------------------------------------------------- - Verification Audit Hash: 0x${metrics.hash} - Alarm Logic Reference: IEC 60601-1-8 Alarm Priority Categories (Non-diagnostic Protocol) - Transpiler Firmware: ISO/IEC 9899:1999 (C99) - Attending Physician: ________________________________________ ================================================================================`; }; const handleDownloadReportText = () => { const text = generateReportText(); const blob = new Blob([text], { type: "text/plain;charset=utf-8;" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `Clinical_Report_PT-9428-A_${new Date().toISOString().substring(0, 10)}.txt`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }; const handleCopyReport = async () => { const text = generateReportText(); try { await navigator.clipboard.writeText(text); setReportCopied(true); setTimeout(() => setReportCopied(false), 2000); } catch { // clipboard fallback } }; return (
{/* Header */}
SESSION AUDIT TRAIL

PATIENT
SESSION LOG

{sourceTab === "session" ? "Scope: In-Memory Client Session · Sources: Live Monitor & Simulator" : "Scope: Persistent SQLite Database · Source: Backend Service"}
{/* Action Toolbar */}
{sourceTab === "session" && records.length === 0 && ( )} {sourceTab === "cloud" && ( )}
{sourceTab === "session" && (
)}
{/* Telemetry Log Table */}
{isLoading ? ( ) : activeRecords.length === 0 ? ( ) : ( activeRecords.map((record) => { const predLabel = record.prediction_label || "NORMAL"; const getStatusStyles = (label: string) => { const normalized = label.toLowerCase(); if (normalized === "normal" || normalized === "healthy") return "bg-[#d1fae5] text-[#065f46]"; if (normalized.includes("heart")) return "bg-[#fef08a] text-[#854d0e]"; if (normalized.includes("asthma")) return "bg-[#e0f2fe] text-[#075985]"; if (normalized.includes("hypertension")) return "bg-[#f3e8ff] text-[#6b21a8]"; if (normalized.includes("diabetes")) return "bg-[#ffedd5] text-[#9a3412]"; return "bg-hazard/20 text-hazard"; }; return ( ); }) )}
Timestamp HR (BPM) SpO2 (%) BP (Sys/Dia) Temp (°C) Status / Diagnosis Confidence
Loading historical records...
No Session Telemetry Recorded

{sourceTab === "session" ? "Vitals can be captured dynamically from the Live Monitor using 'Record Snapshot', or evaluated via the Simulator. You can also populate verified clinical test vectors below." : "No cloud predictions found in SQLite database. Start FastAPI backend and execute live evaluations to store persistent records."}

{sourceTab === "session" && ( )} Open Monitor →
{record.timestamp} {record.heart_rate} {record.spo2} {record.sys_bp}/{record.dia_bp} {record.body_temp} {predLabel} {(record.confidence * 100).toFixed(1)}%
{/* Clinical Discharge / Summary Report Modal (Printable) */} {showReportModal && metrics && (
{/* Modal Header */}
HEARTFLOW_OS · Clinical Telemetry Summary Report

PATIENT PHYSIOLOGICAL AUDIT

Patient ID: PT-9428-A · Date: {new Date().toISOString().replace("T", " ").substring(0, 19)} UTC · Audit Hash: 0x{metrics.hash}
{/* Vitals Summary Grid (6-Cell Clinical Grid) */}
Mean HR
{metrics.meanHr} BPM
{metrics.minHr}-{metrics.maxHr}
Nadir SpO2
{metrics.nadirSpo2} %
Mean {metrics.meanSpo2}%
Mean BP
{metrics.meanSbp}/{metrics.meanDbp}
mmHg
Mean MAP
{metrics.mapValue}
mmHg
Shock Index
{metrics.shockIndex}
HR / SBP
Risk Burden
{metrics.riskRate}%
{metrics.anomalyCount}/{metrics.total}
{/* Diagnostic Consensus Box */}
Primary Diagnostic Consensus
{metrics.topDiagnosis}
Ensemble Confidence
{(metrics.meanConfidence * 100).toFixed(1)}% (5-Model Soft Vote)
{/* Diagnostic Narrative */}
Clinical Assessment Narrative:

{metrics.narrative}

{/* Recent Telemetry Intervals Table */}
Recent Telemetry Intervals Sample ({Math.min(5, recordsToAnalyze.length)} of {metrics.total}) INT8 TinyML
{recordsToAnalyze.slice(0, 5).map((r) => (
{r.timestamp} HR: {r.heart_rate} BPM SpO2: {r.spo2}% BP: {r.sys_bp}/{r.dia_bp} {r.prediction_label} ({(r.confidence * 100).toFixed(1)}%)
))}
{/* Physician Sign-off (Clean for Print) */}
Verification Hash: 0x{metrics.hash}
Physician Signature: _______________________________
{/* Modal Actions (Hidden in Print) */}
)}
); }