import { useState, useEffect, useRef } from 'react'; import { Activity, Zap, Loader2, AlertCircle, CheckCircle2, RefreshCw, FileText, } from 'lucide-react'; import { api } from '../api'; import { useDisease } from '../context/DiseaseContext'; import DynamicClinicalForm from './DynamicClinicalForm'; import ShapBarChart from './ShapBarChart'; import WhatIfScenarioCard from './WhatIfScenarioCard'; import ClinicalReportModal from './ClinicalReportModal'; export default function EngineeringMode() { const { selectedDisease, currentDiseaseInfo } = useDisease(); const [loading, setLoading] = useState(false); const [coldStart, setColdStart] = useState(false); const [error, setError] = useState(null); const [result, setResult] = useState(null); const [shapData, setShapData] = useState(null); const [counterfactualsData, setCounterfactualsData] = useState(null); const [counterfactualsLoading, setCounterfactualsLoading] = useState(false); const [lastFormData, setLastFormData] = useState(null); const [showReportModal, setShowReportModal] = useState(false); const coldStartTimer = useRef(null); // Show "Waking up..." message if request takes > 8s (HF Spaces cold start) useEffect(() => { if (loading) { coldStartTimer.current = setTimeout(() => setColdStart(true), 8_000); } else { setColdStart(false); } return () => { if (coldStartTimer.current) clearTimeout(coldStartTimer.current); }; }, [loading]); const runInference = async (formData) => { if (!selectedDisease) return; setLoading(true); setCounterfactualsLoading(true); setColdStart(false); setError(null); setResult(null); setShapData(null); setCounterfactualsData(null); setLastFormData(formData); try { const [pred, expl] = await Promise.all([ api.predict(selectedDisease, formData), api.explain(selectedDisease, formData), ]); setResult(pred); setShapData(expl); } catch (err) { setError(err.message || 'Inference failed. Is the backend running?'); } // Counterfactuals: only supported by ensemble diseases (e.g. diabetes). // Skip entirely for single-model diseases (e.g. heart_disease) to avoid a // noisy 501 error in the browser console. if (currentDiseaseInfo?.supports_counterfactuals) { try { const cfResponse = await api.counterfactuals(selectedDisease, formData); setCounterfactualsData(cfResponse?.counterfactuals ?? null); } catch { setCounterfactualsData(null); } } else { setCounterfactualsData(null); } setLoading(false); setCounterfactualsLoading(false); }; const handleRefresh = () => { if (lastFormData && selectedDisease) { runInference(lastFormData); } }; const diseaseLabel = currentDiseaseInfo?.display_name || selectedDisease || 'Heart Disease'; return (
Manually test the OmniDiag inference pipeline for {diseaseLabel}. Adjust patient parameters and run inference to see predictions and SHAP explanations.
This might take a few moments if it's the first scan of the day.
)}{coldStart ? 'Waking up the diagnostic engine...' : 'Running AI inference...'}
Error
{error}
{JSON.stringify(result, null, 2)}
Feature Impact Summary
{shapData.text_explanation}
{JSON.stringify(shapData, null, 2)}