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 (
{/* Header */}

Engineering Mode

Manually test the OmniDiag inference pipeline for {diseaseLabel}. Adjust patient parameters and run inference to see predictions and SHAP explanations.

{/* ── Dynamic Input Form ── */}

Patient Parameters

{selectedDisease ? ( ) : (
No disease selected. Please select a disease from the sidebar.
)}
{coldStart && (

This might take a few moments if it's the first scan of the day.

)}
{/* ── Results Panel ── */}
{/* Prediction Result */}

Prediction Result

{result && ( )}
{loading && !result && (

{coldStart ? 'Waking up the diagnostic engine...' : 'Running AI inference...'}

)} {error && (

Error

{error}

)} {!result && !error && !loading && (
Adjust patient parameters and click "Run Inference" to see results.
)} {result && (
Diagnosis {result.diagnosis === 'Positive' ? ( <> Positive ) : ( <> Negative )}
Confidence {(result.confidence * 100).toFixed(2)}%
Prediction {result.prediction === 1 ? 'Positive' : 'Negative'}
{/* Generate AI Report */} {shapData && ( )} {/* Raw JSON */}
Raw JSON Response
                      {JSON.stringify(result, null, 2)}
                    
)}
{/* SHAP Explanation */} {shapData && (

SHAP Explanation

{/* DiCE Counterfactuals — What-If Scenarios */}
{/* Textual Explanation */} {shapData.text_explanation && (

Feature Impact Summary

{shapData.text_explanation}

Raw SHAP JSON
                        {JSON.stringify(shapData, null, 2)}
                      
)}
)}
{/* AI Report Modal */} {showReportModal && result && shapData && ( = 0.7 ? 'HIGH' : result.confidence >= 0.4 ? 'MODERATE' : 'LOW'} shapValues={shapData.chart_data} features={lastFormData} onClose={() => setShowReportModal(false)} /> )}
); }