- {/* Hero header */}
-
-
-
-
-
- AI FOR SMART EDUCATION
-
-
Selamat Datang di
-
- ZeaVis Edu
-
-
- Platform edukasi berbasis AI untuk membantu petani jagung
- Indonesia mendeteksi penyakit daun secara mandiri, cepat, dan
- akurat.
-
-
-
-
-
-
-
-
-
-
- {/* Loading / Error states */}
- {isLoadingData && (
-
- Memuat data dashboard...
-
- )}
-
- {hasError && (
-
- Gagal memuat data dashboard
-
- {String(summaryQuery.error?.message)}
-
-
- )}
-
- {/* Main dashboard content */}
- {!isLoadingData && !hasError && (
- <>
- {summary && (
-
-
-
- Proyek Urgensi
-
-
- Data ringkasan terbaru dari proyek Anda untuk memantau
- perkembangan dan hasil deteksi penyakit daun jagung
-
-
-
-
-
- Total Penyakit
-
-
-
-
- {summary.diseaseCount}
-
-
- Lihat daftar
-
-
-
-
-
-
-
- Total Diagnosis
-
-
-
-
- {summary.imageClassificationCount}
-
-
- Lihat daftar
-
-
-
-
-
-
-
- Menunggu Review
-
-
-
-
- {summary.needsReviewCount}
-
-
- Lihat daftar
-
-
-
-
-
-
-
- Risiko Tinggi
-
-
-
-
- {summary.riskDistribution.high}
-
-
- Lihat daftar
-
-
-
-
- )}
-
- {/* Mission section */}
-
-
-
- Misi Platform
-
-
- Fitur inti yang kami sediakan untuk mendukung petani jagung
- Indonesia
-
-
-
-
- {missionCards.map((card) => {
- const Icon = card.icon;
-
- return (
-
-
-
-
-
-
-
- {card.title}
-
-
- {card.description}
-
-
-
-
- );
- })}
-
-
-
- {/* Diseases quick access */}
-
-
-
-
- Penyakit yang Dapat Dideteksi
-
-
- 4 kelas penyakit dan kondisi daun jagung dalam sistem kami
-
-
-
- Lihat Pustaka
-
-
-
-
- {diseasesQuick.map((d) => (
-
-
-
-
-
-
- {d.name}
-
-
- {d.sci}
-
-
-
-
-
- ))}
-
-
-
- {/* Scan quick access */}
-
-
-
Siap Mendeteksi Penyakit Daun?
-
-
- Unggah foto daun jagung Anda dan dapatkan hasil analisis AI
- dalam hitungan detik.
-
-
-
+
+ {/* Hero header */}
+
+
+
+
+
+ AI FOR SMART EDUCATION
+
+
Selamat Datang di
+
+ ZeaVis Edu
+
+
+ Platform edukasi berbasis AI untuk membantu petani jagung
+ Indonesia mendeteksi penyakit daun secara mandiri, cepat, dan
+ akurat.
+
+
+ className="px-6 py-6 text-lg font-semibold text-white hover:bg-[#1E8A2A]"
+ >
+
+ Pustaka Penyakit
+
+
+
- >
- )}
-
-
+
+
+
+
+
+ {/* Loading / Error states */}
+ {isLoadingData && (
+
+ Memuat data dashboard...
+
+ )}
+
+ {hasError && (
+
+ Gagal memuat data dashboard
+
+ {String(summaryQuery.error?.message)}
+
+
+ )}
+
+ {/* Main dashboard content */}
+ {!isLoadingData && !hasError && (
+ <>
+ {summary && (
+
+
+
+ Proyek Urgensi
+
+
+ Data ringkasan terbaru dari proyek Anda untuk memantau
+ perkembangan dan hasil deteksi penyakit daun jagung
+
+
+
+ {/* Total Diagnoses — the actual count from diagnoses table */}
+
+
+
+ Total Diagnosa
+
+
+
+
+ {summary.imageClassificationCount}
+
+
+ Lihat daftar
+
+
+
+
+ {/* Menunggu Review */}
+
+
+
+ Menunggu Review
+
+
+
+
+ {summary.needsReviewCount}
+
+
+ Lihat daftar
+
+
+
+
+ {/* Diagnosa Gagal */}
+
+
+
+ Gagal
+
+
+
+
+ —
+
+
+ Lihat daftar
+
+
+
+
+ {/* Risiko Tinggi — catalog count, link to catalog filtered */}
+
+
+
+ Kategori Risiko Tinggi
+
+
+
+
+ {summary.riskDistribution.high}
+
+
+ Lihat pustaka
+
+
+
+
+ )}
+
+ {/* Mission section */}
+
+
+
+ Misi Platform
+
+
+ Fitur inti yang kami sediakan untuk mendukung petani jagung
+ Indonesia
+
+
+
+
+ {missionCards.map((card) => {
+ const Icon = card.icon;
+
+ return (
+
+
+
+
+
+
+
+ {card.title}
+
+
+ {card.description}
+
+
+
+
+ );
+ })}
+
+
+
+ {/* Diseases quick access - now clickable, link to catalog/:slug */}
+
+
+
+
+ Penyakit yang Dapat Dideteksi
+
+
+ {diseases.length} kelas penyakit dan kondisi daun jagung dalam sistem kami
+
+
+
+ Lihat Pustaka
+
+
+
+ {diseasesQuery.isLoading ? (
+
+ Memuat data penyakit...
+
+ ) : (
+
+ {diseasesQuick.map((d) => (
+
+
+
+
+
+
+
+ {d.name}
+
+
+ {d.sci}
+
+
+
+
+
+
+ ))}
+
+ )}
+
+
+ {/* Scan quick access */}
+
+
+
Siap Mendeteksi Penyakit Daun?
+
+ Unggah foto daun jagung Anda dan dapatkan hasil analisis AI
+ dalam hitungan detik.
+
+
+
+
+ >
+ )}
+
);
}
diff --git a/apps/web/src/pages/diagnoses-page.tsx b/apps/web/src/pages/diagnoses-page.tsx
index f05b946..86f9ffc 100644
--- a/apps/web/src/pages/diagnoses-page.tsx
+++ b/apps/web/src/pages/diagnoses-page.tsx
@@ -1,19 +1,40 @@
import { useMemo, useState } from "react";
-import { Link } from "react-router-dom";
+import { Link, useSearchParams } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import { Button } from "@/components/ui/button";
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+import { Card, CardContent } from "@/components/ui/card";
import { DiagnosisStatusBadge } from "@/components/diagnosis-status-badge";
import { RiskBadge } from "@/components/risk-badge";
import { apiClient } from "@/lib/api-client";
+import type { DiagnosisStatus, RiskLevel } from "@zeavis/shared";
+
+const STATUS_OPTIONS: { value: "all" | DiagnosisStatus; label: string }[] = [
+ { value: "all", label: "Semua" },
+ { value: "ai_verified", label: "Terverifikasi AI" },
+ { value: "needs_review", label: "Menunggu Review" },
+ { value: "expert_verified", label: "Diverifikasi Pakar" },
+ { value: "expert_corrected", label: "Dikoreksi Pakar" },
+ { value: "failed", label: "Gagal" },
+];
+
+const RISK_OPTIONS: { value: "all" | RiskLevel; label: string }[] = [
+ { value: "all", label: "Semua Risiko" },
+ { value: "high", label: "Risiko Tinggi" },
+ { value: "medium", label: "Risiko Sedang" },
+ { value: "low", label: "Risiko Rendah" },
+];
export function DiagnosesPage() {
+ const [searchParams, setSearchParams] = useSearchParams();
+ const initialStatus = searchParams.get("status") as DiagnosisStatus | null;
+ const initialRisk = searchParams.get("risk") as RiskLevel | null;
+
const [statusFilter, setStatusFilter] = useState<
- "all" | "needs_review" | "verified" | "failed"
- >("all");
+ "all" | DiagnosisStatus
+ >(initialStatus ?? "all");
const [riskFilter, setRiskFilter] = useState<
- "all" | "high" | "medium" | "low"
- >("all");
+ "all" | RiskLevel
+ >(initialRisk ?? "all");
const query = useQuery({
queryKey: ["diagnoses"],
@@ -32,114 +53,148 @@ export function DiagnosesPage() {
});
}, [diagnoses, statusFilter, riskFilter]);
+ const handleStatusChange = (value: string) => {
+ const v = value as "all" | DiagnosisStatus;
+ setStatusFilter(v);
+ const next = new URLSearchParams(searchParams);
+ if (v === "all") next.delete("status");
+ else next.set("status", v);
+ setSearchParams(next);
+ };
+
+ const handleRiskChange = (value: string) => {
+ const v = value as "all" | RiskLevel;
+ setRiskFilter(v);
+ const next = new URLSearchParams(searchParams);
+ if (v === "all") next.delete("risk");
+ else next.set("risk", v);
+ setSearchParams(next);
+ };
+
return (
-
-
-
-
-
- Manajemen Diagnosis
-
-
Daftar Diagnosis
-
-
-
-
-
-
+
+
+
+
+ Manajemen Diagnosis
+
+
Daftar Diagnosis
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
+
+
-
- Total: {filtered.length}
-
+
+ Total: {filtered.length}
+
- {query.isLoading ? (
-
- Memuat diagnosis...
-
- ) : query.isError ? (
-
- Gagal memuat diagnosis
-
- ) : filtered.length === 0 ? (
-
+ {query.isLoading ? (
+
+ Memuat diagnosis...
+
+ ) : query.isError ? (
+
+ Gagal memuat diagnosis
+
+ ) : filtered.length === 0 ? (
+
+
Tidak ada diagnosis sesuai filter
-
- ) : (
-
- {filtered.map((d) => (
-
-
-
-
-
-
-
- {d.disease?.commonName ?? "Unknown"}
-
-
- {d.predictedDiseaseSlug ?? ""}
-
-
-
-
-
-
+
+ {diagnoses.length === 0 && (
+
+ Mulai dengan{" "}
+
+ melakukan scan daun
+
+ .
+
+ )}
+
+ ) : (
+
+ {filtered.map((d) => (
+
+
+
+
+
+
+
+ {d.disease?.commonName ?? "Diagnosis gagal"}
+
+
+ {d.disease?.label ?? d.predictedDiseaseSlug}
+
-
-
-
- {new Date(d.createdAt).toLocaleString("id-ID")}
-
-
- Lihat detail
-
+
+
+
-
-
- ))}
-
- )}
-
-
-
-
+
+
+
+ {new Date(d.createdAt).toLocaleString("id-ID")}
+ {d.confidence !== null && (
+
+ • {(d.confidence * 100).toFixed(0)}%
+
+ )}
+
+
+ Lihat detail
+
+
+
+
+
+ ))}
+
+ )}
+
+
+
);
}
diff --git a/apps/web/src/pages/disease-detail-page.tsx b/apps/web/src/pages/disease-detail-page.tsx
index 3bae73f..c0407eb 100644
--- a/apps/web/src/pages/disease-detail-page.tsx
+++ b/apps/web/src/pages/disease-detail-page.tsx
@@ -1,7 +1,7 @@
import { useParams, Link } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import { isDiseaseSlug } from '@zeavis/shared';
-import { ArrowLeft, BookOpen, AlertCircle } from 'lucide-react';
+import { ArrowLeft, AlertCircle, BookOpen } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { RiskBadge } from '@/components/risk-badge';
@@ -20,37 +20,37 @@ export function DiseaseDetailPage() {
if (!validatedSlug || error || (!isLoading && !disease)) {
return (
-
-
-