"use client" import { useEffect, useState } from "react" import { motion, AnimatePresence } from "framer-motion" import { RadialBarChart, RadialBar, Cell, ResponsiveContainer, Tooltip, } from "recharts" import type { AnalysisResult } from "@/app/page" const BACKEND = process.env.NEXT_PUBLIC_BACKEND_URL ?? "http://localhost:8000" // ── Types ───────────────────────────────────────────────────────────────── interface RiskScore { condition: string score: number // 0–100 level: "low" | "moderate" | "high" | "critical" confidence: number // 0–1 label_ar: string factors: string[] recommendation: string source: "rule" | "ml" } interface RiskReport { risks: RiskScore[] top_risk: RiskScore | null overall_ar: string features_used: number } // ── Level colours ───────────────────────────────────────────────────────── const LEVEL_COLOUR: Record = { low: "#22c55e", // green-500 moderate: "#f59e0b", // amber-500 high: "#ef4444", // red-500 critical: "#7c3aed", // violet-600 } const LEVEL_LABEL_AR: Record = { low: "منخفض", moderate: "متوسط", high: "مرتفع", critical: "حرج", } // ── Sub-components ──────────────────────────────────────────────────────── function RiskGauge({ score, level }: { score: number; level: string }) { const colour = LEVEL_COLOUR[level] ?? "#94a3b8" const data = [{ name: "risk", value: score }, { name: "rest", value: 100 - score }] return (
{data.map((_, i) => ( ))}
{score} {LEVEL_LABEL_AR[level]}
) } function RiskCard({ risk, delay }: { risk: RiskScore; delay: number }) { const [open, setOpen] = useState(false) const colour = LEVEL_COLOUR[risk.level] ?? "#94a3b8" return ( setOpen((v) => !v)} >

{risk.label_ar}

{LEVEL_LABEL_AR[risk.level]} ثقة {Math.round(risk.confidence * 100)}% {risk.source === "ml" && ( ML )}
{open ? "▲" : "▼"}
{open && (
{risk.factors.length > 0 && (

العوامل:

    {risk.factors.map((f, i) => (
  • {f}
  • ))}
)} {risk.recommendation && (
{risk.recommendation}
)}
)}
) } // ── Main component ──────────────────────────────────────────────────────── interface RiskDashboardProps { analysis: AnalysisResult } export function RiskDashboard({ analysis }: RiskDashboardProps) { const [report, setReport] = useState(null) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const [visible, setVisible] = useState(false) useEffect(() => { if (!analysis?.findings?.length) return setLoading(true) setError(null) fetch(`${BACKEND}/api/risk`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ findings: analysis.findings }), }) .then((r) => { if (!r.ok) throw new Error(`HTTP ${r.status}`) return r.json() }) .then((data: RiskReport) => setReport(data)) .catch(() => setError("تعذّر تحميل تقرير المخاطر")) .finally(() => setLoading(false)) }, [analysis]) // Show panel only when there's data or loading if (!analysis?.findings?.length) return null const significantRisks = (report?.risks ?? []).filter((r) => r.score >= 20) return (
{/* Toggle button */} {visible && (
{/* Overall summary */} {report?.overall_ar && ( {report.overall_ar} )} {loading && (
جاري التحليل...
)} {error && (

{error}

)} {/* Risk cards (sorted by score desc) */} {(report?.risks ?? []) .slice() .sort((a, b) => b.score - a.score) .map((risk, i) => ( ))} {report && significantRisks.length === 0 && !loading && ( ✅ لا توجد مؤشرات خطر بارزة بناءً على نتائج هذا التحليل )}
)}
) }