import React, { useState, useRef } from "react"; /** * CropGuard.jsx — React frontend for the crop disease detection system. * Implements the four-step farmer flow from §3.10.4: * home -> preview -> loading -> result * Talks to the FastAPI backend's POST /predict endpoint. * * Set the API base URL via Vite env: VITE_API_URL=http://localhost:8000 */ const API = import.meta.env.VITE_API_URL || "http://localhost:8000"; const SEVERITY = { early: { label: "Early stage", urgency: "Routine", color: "#3fa34d", desc: "Symptoms are small and localised. You have time, but act soon." }, moderate: { label: "Moderate stage", urgency: "Urgent", color: "#e9a625", desc: "The disease covers a good part of the leaf and may spread fast. Treat this week." }, severe: { label: "Severe stage", urgency: "Emergency", color: "#cf3b2f", desc: "Most of the leaf or plant is affected. Act today to save the rest of your crop." }, }; export default function CropGuard() { const [screen, setScreen] = useState("home"); // home | preview | loading | result const [imgUrl, setImgUrl] = useState(null); const [file, setFile] = useState(null); const [result, setResult] = useState(null); const [error, setError] = useState(null); const camRef = useRef(null); const galRef = useRef(null); function pick(e) { const f = e.target.files?.[0]; if (!f) return; setFile(f); setImgUrl(URL.createObjectURL(f)); setScreen("preview"); e.target.value = ""; } async function analyse() { setScreen("loading"); setError(null); try { const fd = new FormData(); fd.append("file", file); const res = await fetch(`${API}/predict`, { method: "POST", body: fd }); if (!res.ok) throw new Error("Server error"); setResult(await res.json()); setScreen("result"); } catch (err) { setError("Could not reach the analysis server. Check your connection and try again."); setScreen("preview"); } } function reset() { setScreen("home"); setResult(null); setImgUrl(null); setFile(null); } return (
🌿

CropGuard GH

Snap a leaf. Know the disease.
{screen === "home" && (

Diagnose crop disease in seconds

Photograph a sick leaf and get the disease, its severity, and what to do — free.

{error &&

{error}

}

Detects: Maize · Tomato · Cassava

)} {screen === "preview" && (
leaf

Is this the right photo?

Make sure the diseased leaf fills the frame and is in focus.

{error &&

{error}

}
)} {screen === "loading" && (

Analysing the leaf…

Checking colour, spots and damage

)} {screen === "result" && result && ( )}
); } function Result({ result, onReset }) { const d = result.disease || {}; const healthy = !!d.healthy; const sev = !healthy && result.severity ? SEVERITY[result.severity] : null; return (
Detected disease
{d.name}
🌿 {d.crop}
Confidence{Math.round(result.confidence * 100)}%
{!healthy && sev && (
Severity ● {sev.label}
Urgency {sev.urgency}
)} {sev &&

{sev.desc}

} {!healthy && (

✅ What to do now

    {(d.treatment || []).map((t, i) =>
  1. {t}
  2. )}
{(d.products || []).map((p, i) => 🧪 {p})}
)} {!healthy && (

ℹ️ About this disease

{d.cause}

)} {healthy && (

✅ No disease detected

This leaf looks healthy. Keep monitoring your field weekly.

)}

⚠️ This is a diagnostic aid, not a replacement for an extension officer. For unusual or severe cases, consult MoFA.

); }