import React, { useState } from "react"; import axios from "axios"; function Predict() { const [file, setFile] = useState(null); const [prediction, setPrediction] = useState(null); // Changed from string to object to store full prediction data const [loading, setLoading] = useState(false); // Added loading state for better UX const [error, setError] = useState(""); // Added error state for better error handling const handleUpload = async () => { // Clear previous results and errors setError(""); setPrediction(null); // FIX 1: Check if file is selected before proceeding if (!file) { setError("Please select an image file."); return; } // FIX 2: Check if user is authenticated const token = localStorage.getItem("token"); if (!token) { setError("Please log in to make predictions."); return; } const formData = new FormData(); formData.append("file", file); // FIX 3: Use 'file' instead of undefined 'selectedFile' setLoading(true); // Set loading state try { const res = await axios.post("/predict", formData, { // ✅ CHANGED: Removed 'http://localhost:5000' headers: { Authorization: `Bearer ${token}`, // FIX 4: Added backticks for template literal syntax "Content-Type": "multipart/form-data", }, }); console.log("Prediction result:", res.data); // FIX 5: Actually update state with prediction results instead of just commenting setPrediction({ anomalyDetected: res.data.anomaly_detected, type: res.data.type, confidence: res.data.confidence, severity: res.data.severity, imageId: res.data.image_id, predictionId: res.data.prediction_id }); } catch (err) { console.error("Prediction failed:", err); // FIX 6: Enhanced error handling with specific error messages if (err.response) { // Server responded with an error status const status = err.response.status; const message = err.response.data?.error || "Unknown server error"; switch (status) { case 400: setError(`Invalid request: ${message}`); break; case 401: setError("Session expired. Please log in again."); localStorage.removeItem("token"); // Clear invalid token break; case 413: setError("File too large. Please select a smaller image (max 16MB)."); break; case 503: setError("Service temporarily unavailable. Please try again later."); break; default: setError(`Server error (${status}): ${message}`); } } else if (err.request) { // Network error - no response received setError("Unable to connect to server. Please check your internet connection."); } else { // Other error (request setup, etc.) setError("An unexpected error occurred. Please try again."); } } finally { setLoading(false); // Always clear loading state } }; // Helper function to format confidence as percentage const formatConfidence = (confidence) => { return (confidence * 100).toFixed(2); }; // Helper function to handle file selection const handleFileChange = (e) => { const selectedFile = e.target.files[0]; setFile(selectedFile); // Clear previous results when new file is selected setPrediction(null); setError(""); }; return (

Screw Anomaly Detection

{/* File input section */}
{/* Show selected file info */} {file && (

Selected: {file.name} ({(file.size / 1024 / 1024).toFixed(2)} MB)

)}
{/* Upload button */} {/* Error display */} {error && (
Error: {error}
)} {/* Loading indicator */} {loading && (

🔍 Analyzing image... Please wait.

)} {/* FIX 9: Enhanced prediction results display */} {prediction && (

Prediction Results:

Status: {prediction.type}

Anomaly Detected: {prediction.anomalyDetected ? "Yes" : "No"}

Confidence: {formatConfidence(prediction.confidence)}%

Severity: {prediction.severity}

{/* Warning for detected anomalies */} {prediction.anomalyDetected && (
⚠️ Defect Detected! Please inspect the screw carefully and consider replacement.
)}
)}
); } export default Predict;