import React, { useState, useRef } from 'react';
import axios from 'axios';
import { useAuth } from './useAuth';
import { LogOut, Activity, UploadCloud, XCircle, CheckCircle2, AlertTriangle, Loader2, ThumbsUp, ThumbsDown } from 'lucide-react';
export default function Dashboard() {
const { user, logout } = useAuth();
// UI State
const [dragActive, setDragActive] = useState(false);
const [selectedFile, setSelectedFile] = useState(null);
const [previewUrl, setPreviewUrl] = useState(null);
// API State
const [loading, setLoading] = useState(false);
const [result, setResult] = useState(null);
const [error, setError] = useState(null);
// Feedback State
const [feedbackStatus, setFeedbackStatus] = useState(null); // null, 'loading', 'success', 'error'
const inputRef = useRef(null);
// --- Drag and Drop Handlers ---
const handleDrag = (e) => {
e.preventDefault();
e.stopPropagation();
if (e.type === "dragenter" || e.type === "dragover") {
setDragActive(true);
} else if (e.type === "dragleave") {
setDragActive(false);
}
};
const handleDrop = (e) => {
e.preventDefault();
e.stopPropagation();
setDragActive(false);
if (e.dataTransfer.files && e.dataTransfer.files[0]) {
processFile(e.dataTransfer.files[0]);
}
};
const handleChange = (e) => {
e.preventDefault();
if (e.target.files && e.target.files[0]) {
processFile(e.target.files[0]);
}
};
const processFile = (file) => {
if (!file.type.startsWith("image/")) {
setError("Please upload a valid image file (JPEG/PNG).");
return;
}
setError(null);
setResult(null);
setFeedbackStatus(null);
setSelectedFile(file);
setPreviewUrl(URL.createObjectURL(file));
};
const clearSelection = () => {
setSelectedFile(null);
setPreviewUrl(null);
setResult(null);
setError(null);
setFeedbackStatus(null);
if (inputRef.current) inputRef.current.value = "";
};
// --- API Integration ---
const analyzeXRay = async () => {
if (!selectedFile) return;
setLoading(true);
setError(null);
setFeedbackStatus(null);
const formData = new FormData();
formData.append("file", selectedFile);
try {
const API_URL = import.meta.env.VITE_API_URI;
const response = await axios.post(`${API_URL}/api/v1/predict`, formData, {
headers: { "Content-Type": "multipart/form-data" }
});
setResult(response.data);
} catch (err) {
console.error("API Error:", err);
setError("Failed to connect to the diagnostic engine. Is the Hugging Face space running?");
} finally {
setLoading(false);
}
};
// --- A/B Testing Feedback Loop ---
const submitFeedback = async (isAgree) => {
if (!result?.record_id) return;
setFeedbackStatus('loading');
try {
const API_URL = import.meta.env.VITE_API_URI;
// If the doctor agrees, override is FALSE. If they disagree, override is TRUE.
const payload = {
physician_override: !isAgree,
notes: isAgree ? "Agreed with AI" : "Physician disagreed with AI diagnosis"
};
await axios.put(`${API_URL}/api/v1/override/${result.record_id}`, payload);
setFeedbackStatus('success');
} catch (err) {
console.error("Feedback Error:", err);
setFeedbackStatus('error');
}
};
return (
Diagnostic Workbench
Upload a pediatric chest X-Ray for automated pneumonia screening.
{/* Left Column: Upload & Preview */}
Patient Scan
{!previewUrl ? (
) : (
)}
{error && (
)}
{/* Right Column: AI Results */}
AI Analysis Report
{!result && !loading ? (
) : loading ? (
Running DenseNet121 Inference...
) : result && (
{/* Status Badge */}
{result.prediction === 'PNEUMONIA' ? (
) : (
)}
Detection Result
{result.prediction}
Confidence
{(result.confidence * 100).toFixed(1)}%
{/* Heatmap Image */}
Grad-CAM Explainability Heatmap
{/* The New Feedback Loop */}
Do you agree with this AI diagnosis?
{feedbackStatus === 'success' ? (
Feedback recorded. Thank you.
) : (
)}
{feedbackStatus === 'error' && (
Failed to connect to database.
)}
Record ID: {result.record_id}
)}
);
}