Merge pull request #39 from ATLAS-PJK-GM007/selly/frontend
Selly/frontend
This commit is contained in:
@@ -15,7 +15,7 @@ import { RiskBadge } from "@/components/risk-badge";
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
imageUrl: string;
|
imageUrl: string;
|
||||||
confidence: number; // contoh: 0.95
|
confidence: number;
|
||||||
diseaseName: string;
|
diseaseName: string;
|
||||||
scientificName: string;
|
scientificName: string;
|
||||||
riskLevel: string;
|
riskLevel: string;
|
||||||
@@ -42,8 +42,8 @@ export function DiagnosisResultView({
|
|||||||
|
|
||||||
const getRiskLevelKey = (level: string): "low" | "medium" | "high" => {
|
const getRiskLevelKey = (level: string): "low" | "medium" | "high" => {
|
||||||
const normalized = level.toLowerCase();
|
const normalized = level.toLowerCase();
|
||||||
if (normalized.includes("rendah")) return "low";
|
if (normalized.includes("rendah") || normalized === "low") return "low";
|
||||||
if (normalized.includes("tinggi")) return "high";
|
if (normalized.includes("tinggi") || normalized === "high") return "high";
|
||||||
return "medium";
|
return "medium";
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -85,18 +85,35 @@ export function DiagnosisResultView({
|
|||||||
<div className="space-y-2 mb-4">
|
<div className="space-y-2 mb-4">
|
||||||
<div className="flex justify-between text-sm font-bold text-slate-700">
|
<div className="flex justify-between text-sm font-bold text-slate-700">
|
||||||
<span>Tingkat Keyakinan AI</span>
|
<span>Tingkat Keyakinan AI</span>
|
||||||
<span className="text-emerald-600">{confidencePercent}%</span>
|
<span
|
||||||
|
className={
|
||||||
|
confidencePercent >= 75
|
||||||
|
? "text-emerald-600"
|
||||||
|
: "text-amber-500"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{confidencePercent}%
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full bg-slate-200 rounded-full h-2.5 overflow-hidden">
|
<div className="w-full bg-slate-200 rounded-full h-2.5 overflow-hidden">
|
||||||
<div
|
<div
|
||||||
className="bg-emerald-500 h-2.5 rounded-full transition-all duration-1000"
|
className={`h-2.5 rounded-full transition-all duration-1000 ${
|
||||||
|
confidencePercent >= 75 ? "bg-emerald-500" : "bg-amber-500"
|
||||||
|
}`}
|
||||||
style={{ width: `${confidencePercent}%` }}
|
style={{ width: `${confidencePercent}%` }}
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-[11px] text-emerald-600 flex items-center gap-1 font-medium">
|
{confidencePercent >= 75 ? (
|
||||||
<CheckCircle2 className="w-3 h-3" /> Di atas ambang batas minimum
|
<p className="text-[11px] text-emerald-600 flex items-center gap-1 font-medium">
|
||||||
(75%)
|
<CheckCircle2 className="w-3 h-3" /> Di atas ambang batas
|
||||||
</p>
|
minimum (75%)
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p className="text-[11px] text-amber-600 flex items-center gap-1 font-medium">
|
||||||
|
<AlertTriangle className="w-3 h-3" /> Di bawah ambang batas
|
||||||
|
minimum (75%)
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-3 pt-4 border-t border-amber-200/50">
|
<div className="flex items-center gap-3 pt-4 border-t border-amber-200/50">
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { Modal } from "@/components/ui/modal";
|
import { Modal } from "@/components/ui/modal";
|
||||||
import type { DiagnosisRecord } from "@zeavis/shared";
|
import type { DiagnosisRecord } from "@zeavis/shared";
|
||||||
|
import { diseaseCatalogSeed } from "@zeavis/shared"; // Import data seed lokal ditambahkan
|
||||||
import { apiClient } from "@/lib/api-client";
|
import { apiClient } from "@/lib/api-client";
|
||||||
import { trackScan, trackDiagnosisResult } from "@/lib/telemetry";
|
import { trackScan, trackDiagnosisResult } from "@/lib/telemetry";
|
||||||
import { DiagnosisResultView } from "../components/diagnose-result-view";
|
import { DiagnosisResultView } from "../components/diagnose-result-view";
|
||||||
@@ -95,7 +96,7 @@ export function ScanPage() {
|
|||||||
const [diagnosisPreview, setDiagnosisPreview] =
|
const [diagnosisPreview, setDiagnosisPreview] =
|
||||||
useState<DiagnosisRecord | null>(null);
|
useState<DiagnosisRecord | null>(null);
|
||||||
|
|
||||||
const diagnosesQuery = useQuery({
|
useQuery({
|
||||||
queryKey: ["diagnoses"],
|
queryKey: ["diagnoses"],
|
||||||
queryFn: () => apiClient.getDiagnoses(),
|
queryFn: () => apiClient.getDiagnoses(),
|
||||||
enabled: previewOpen,
|
enabled: previewOpen,
|
||||||
@@ -429,29 +430,46 @@ export function ScanPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<DiagnosisResultView
|
{/* Render DiagnosisResultView dengan Fallback Obat */}
|
||||||
imageUrl={
|
{(() => {
|
||||||
previewUrl ||
|
// Fallback logic for scientific name and medicine recommendations
|
||||||
diagnosisPreview.imageUrl ||
|
const seedData = diagnosisPreview.disease
|
||||||
"https://placehold.co/600x400?text=Foto+Daun"
|
? diseaseCatalogSeed.find(
|
||||||
}
|
(seed) =>
|
||||||
confidence={diagnosisPreview.confidence ?? 0}
|
seed.commonName === diagnosisPreview.disease?.commonName,
|
||||||
diseaseName={
|
)
|
||||||
diagnosisPreview.disease?.commonName ?? "Tidak Diketahui"
|
: null;
|
||||||
}
|
|
||||||
scientificName={diagnosisPreview.disease?.label ?? ""}
|
// If the API doesn't return medicine recommendations, use the seed data as a fallback
|
||||||
riskLevel={diagnosisPreview.disease?.riskLevel ?? "Sedang"}
|
const finalMedicines =
|
||||||
description={
|
(diagnosisPreview.disease as any)?.medicineRecommendations ||
|
||||||
diagnosisPreview.disease?.description ??
|
seedData?.medicineRecommendations ||
|
||||||
diagnosisPreview.disease?.summary ??
|
[];
|
||||||
"Deskripsi tidak tersedia."
|
|
||||||
}
|
return (
|
||||||
symptoms={diagnosisPreview.disease?.symptoms ?? []}
|
<DiagnosisResultView
|
||||||
preventions={diagnosisPreview.disease?.recommendations ?? []}
|
imageUrl={
|
||||||
medicines={
|
previewUrl ||
|
||||||
(diagnosisPreview.disease as any)?.medicineRecommendations ?? []
|
diagnosisPreview.imageUrl ||
|
||||||
}
|
"https://placehold.co/600x400?text=Foto+Daun"
|
||||||
/>
|
}
|
||||||
|
confidence={diagnosisPreview.confidence ?? 0}
|
||||||
|
diseaseName={
|
||||||
|
diagnosisPreview.disease?.commonName ?? "Tidak Diketahui"
|
||||||
|
}
|
||||||
|
scientificName={diagnosisPreview.disease?.label ?? ""}
|
||||||
|
riskLevel={diagnosisPreview.disease?.riskLevel ?? "Sedang"}
|
||||||
|
description={
|
||||||
|
diagnosisPreview.disease?.description ??
|
||||||
|
diagnosisPreview.disease?.summary ??
|
||||||
|
"Deskripsi tidak tersedia."
|
||||||
|
}
|
||||||
|
symptoms={diagnosisPreview.disease?.symptoms ?? []}
|
||||||
|
preventions={diagnosisPreview.disease?.recommendations ?? []}
|
||||||
|
medicines={finalMedicines} // Datanya terhubung ke sini!
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
|
|
||||||
{/* All Model Predictions */}
|
{/* All Model Predictions */}
|
||||||
{diagnosisPreview.predictions &&
|
{diagnosisPreview.predictions &&
|
||||||
|
|||||||
Reference in New Issue
Block a user