diff --git a/apps/web/src/app.tsx b/apps/web/src/app.tsx index cd597a9..fcbcd47 100644 --- a/apps/web/src/app.tsx +++ b/apps/web/src/app.tsx @@ -5,28 +5,22 @@ import { Navigate, } from "react-router-dom"; import { DashboardPage } from "@/pages/dashboard-page"; -// import { LandingPage } from "@/pages/landing-page"; import { ScanPage } from "@/pages/scan-page"; import { LibraryPage } from "@/pages/library-page"; import { CatalogPage } from "@/pages/catalog-page"; import { DiseaseDetailPage } from "@/pages/disease-detail-page"; import { DiagnosisDetailPage } from "@/pages/diagnosis-detail-page"; import { ExpertReviewsPage } from "@/pages/expert-reviews-page"; -// import { LoginPage } from "@/pages/login-page"; -// import { RegisterPage } from "@/pages/register-page"; +import { DiagnosesPage } from "@/pages/diagnoses-page"; import { MainLayout } from "@/components/layout/main-layout"; const queryClient = new QueryClient(); const router = createBrowserRouter([ - // { - // path: "/", - // element: ( - // - // - // - // ), - // }, + { + path: "/", + element: , + }, { path: "/", element: , @@ -47,8 +41,7 @@ const router = createBrowserRouter([ ), }, - // { path: "/login", element: }, - // { path: "/register", element: }, + { path: "/dashboard", element: ( @@ -61,6 +54,14 @@ const router = createBrowserRouter([ path: "/diagnoses/:id", element: , }, + { + path: "/diagnoses", + element: ( + + + + ), + }, { path: "/expert/reviews", element: , diff --git a/apps/web/src/pages/dashboard-page.tsx b/apps/web/src/pages/dashboard-page.tsx index aadf457..17a1308 100644 --- a/apps/web/src/pages/dashboard-page.tsx +++ b/apps/web/src/pages/dashboard-page.tsx @@ -156,8 +156,11 @@ export function DashboardPage() {
{summary.diseaseCount}
- - + + Lihat daftar + + + @@ -169,8 +172,11 @@ export function DashboardPage() {
{summary.imageClassificationCount}
- -
+ + Lihat daftar + + + @@ -182,6 +188,9 @@ export function DashboardPage() {
{summary.needsReviewCount}
+ + Lihat daftar +
@@ -195,6 +204,9 @@ export function DashboardPage() {
{summary.riskDistribution.high}
+ + Lihat daftar + diff --git a/apps/web/src/pages/diagnoses-page.tsx b/apps/web/src/pages/diagnoses-page.tsx new file mode 100644 index 0000000..f05b946 --- /dev/null +++ b/apps/web/src/pages/diagnoses-page.tsx @@ -0,0 +1,146 @@ +import { useMemo, useState } from "react"; +import { Link } 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 { DiagnosisStatusBadge } from "@/components/diagnosis-status-badge"; +import { RiskBadge } from "@/components/risk-badge"; +import { apiClient } from "@/lib/api-client"; + +export function DiagnosesPage() { + const [statusFilter, setStatusFilter] = useState< + "all" | "needs_review" | "verified" | "failed" + >("all"); + const [riskFilter, setRiskFilter] = useState< + "all" | "high" | "medium" | "low" + >("all"); + + const query = useQuery({ + queryKey: ["diagnoses"], + queryFn: () => apiClient.getDiagnoses(), + }); + const diagnoses = query.data ?? []; + + const filtered = useMemo(() => { + return diagnoses.filter((d) => { + if (statusFilter !== "all" && d.status !== statusFilter) return false; + if (riskFilter !== "all") { + const level = d.disease?.riskLevel ?? "low"; + if (level !== riskFilter) return false; + } + return true; + }); + }, [diagnoses, statusFilter, riskFilter]); + + return ( +
+
+
+
+

+ Manajemen Diagnosis +

+

Daftar Diagnosis

+
+
+ + + +
+
+ + + +
+ + + + + + +
+ Total: {filtered.length} +
+
+ + {query.isLoading ? ( +
+ Memuat diagnosis... +
+ ) : query.isError ? ( +
+ Gagal memuat diagnosis +
+ ) : filtered.length === 0 ? ( +
+ Tidak ada diagnosis sesuai filter +
+ ) : ( +
+ {filtered.map((d) => ( + + + Daun +
+
+
+

+ {d.disease?.commonName ?? "Unknown"} +

+

+ {d.predictedDiseaseSlug ?? ""} +

+
+
+ + +
+
+ +
+
+ {new Date(d.createdAt).toLocaleString("id-ID")} +
+ + Lihat detail + +
+
+
+
+ ))} +
+ )} +
+
+
+
+ ); +} + +export default DiagnosesPage; diff --git a/apps/web/src/pages/scan-page.tsx b/apps/web/src/pages/scan-page.tsx index 28fd0aa..82e5dae 100644 --- a/apps/web/src/pages/scan-page.tsx +++ b/apps/web/src/pages/scan-page.tsx @@ -1,6 +1,6 @@ import React, { useRef, useState } from "react"; -import { useNavigate } from "react-router-dom"; -import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { useNavigate, Link } from "react-router-dom"; +import { useMutation, useQueryClient, useQuery } from "@tanstack/react-query"; import { apiClient } from "@/lib/api-client"; import { Modal } from "@/components/ui/modal"; import type { DiagnosisRecord } from "@zeavis/shared"; @@ -16,7 +16,7 @@ export function ScanPage() { onSuccess: (diagnosis) => { queryClient.invalidateQueries({ queryKey: ["diagnoses"] }); // show preview modal instead of immediate navigation - setDiagnosisPreview(diagnosis as DiagnosisRecord); + setDiagnosisPreview(diagnosis); setPreviewOpen(true); }, }); @@ -31,6 +31,12 @@ export function ScanPage() { const [diagnosisPreview, setDiagnosisPreview] = useState(null); + const diagnosesQuery = useQuery({ + queryKey: ["diagnoses"], + queryFn: () => apiClient.getDiagnoses(), + enabled: previewOpen, + }); + return (

Scan Tanaman

@@ -135,6 +141,53 @@ export function ScanPage() {

+
+

+ Daftar Diagnosis Terbaru +

+ {diagnosesQuery.isLoading && ( +
+ Memuat daftar... +
+ )} + {diagnosesQuery.isError && ( +
+ Gagal memuat daftar diagnosis +
+ )} + {!diagnosesQuery.isLoading && !diagnosesQuery.isError && ( +
+ {(diagnosesQuery.data ?? []).slice(0, 5).map((d) => ( +
+
+ thumb +
+
+ {d.disease?.commonName ?? d.predictedDiseaseSlug} +
+
+ {new Date(d.createdAt).toLocaleString("id-ID")} +
+
+
+ + Lihat + +
+ ))} +
+ )} +
) : null}