"use client"; /* * System-health monitoring section (INV-IA4): DB health, table counts, the * halacha review backlog (read-only pointer to /approvals), active background * tasks, and failed/stuck documents. Extracted from the former /diagnostics * page so /operations is the single monitoring surface — /diagnostics now * redirects here (one intent = one surface). */ import Link from "next/link"; import { AlertTriangle, CheckCircle2, Clock, Database } from "lucide-react"; import { Card, CardContent } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Skeleton } from "@/components/ui/skeleton"; import { useDiagnostics, type DiagDoc } from "@/lib/api/system"; const TABLE_LABELS: Record = { cases: "תיקים", documents: "מסמכים", document_chunks: "chunks", style_corpus: "קורפוס סגנון", style_patterns: "דפוסי סגנון", }; function formatRelativeTime(iso: string | null) { if (!iso) return "—"; const then = new Date(iso); const diffMs = Date.now() - then.getTime(); const min = Math.floor(diffMs / 60000); if (min < 1) return "עכשיו"; if (min < 60) return `לפני ${min} דקות`; const hr = Math.floor(min / 60); if (hr < 24) return `לפני ${hr} שעות`; const days = Math.floor(hr / 24); if (days < 30) return `לפני ${days} ימים`; return then.toLocaleDateString("he-IL"); } function DocRow({ doc, tone }: { doc: DiagDoc; tone: "danger" | "warn" }) { const cls = tone === "danger" ? "bg-danger-bg/60 border-danger/30" : "bg-warn-bg/60 border-warn/30"; return (
  • {doc.title || "(ללא כותרת)"}
    {doc.case_number && ( ערר {doc.case_number} )} {formatRelativeTime(doc.created_at)}
    {doc.status}
  • ); } export function SystemHealthSection() { const { data, isPending, error } = useDiagnostics(); if (error) { return ( {error.message} ); } return (
    {/* DB status + table counts */}
    מצב DB
    {isPending ? ( ) : data?.db_ok ? (
    מחובר
    ) : (
    מנותק
    )}
    ספירת טבלאות
    {Object.keys(TABLE_LABELS).map((key) => (
    {TABLE_LABELS[key]}
    {isPending ? "—" : (data?.tables[key] ?? "—")}
    ))}
    {/* Halacha review backlog (ADM-1, INV-IA5): render the human-gate counter the backend returns; the action lives at /approvals (INV-IA1). */}

    תור אישור הלכות {isPending ? "—" : (data?.halacha_backlog?.pending_review ?? 0)} לאישור ←

    {isPending ? ( ) : (
    ממתינים (נקי)
    {data?.halacha_backlog?.pending_clean ?? 0}
    דורש תיקון
    {data?.halacha_backlog?.pending_flagged ?? 0}
    אושרו
    {data?.halacha_backlog?.approved ?? 0}
    הוותיק ביותר
    {formatRelativeTime(data?.halacha_backlog?.oldest_pending_at ?? null)}
    )}
    {/* Active tasks */}

    משימות רקע פעילות {data?.active_tasks.length ?? 0}

    {isPending ? ( ) : data?.active_tasks.length === 0 ? (

    אין משימות פעילות

    ) : (
      {data?.active_tasks.map((t) => (
    • {t.filename || t.task_id} {t.step || t.status}
    • ))}
    )}
    {/* Failed + stuck docs */}

    מסמכים שנכשלו {data?.failed_documents.length ?? 0}

    {isPending ? ( ) : data?.failed_documents.length === 0 ? (

    אין כשלונות

    ) : (
      {data?.failed_documents.map((d) => ( ))}
    )}

    תקועים (> 10 דק׳) {data?.stuck_documents.length ?? 0}

    {isPending ? ( ) : data?.stuck_documents.length === 0 ? (

    אין מסמכים תקועים

    ) : (
      {data?.stuck_documents.map((d) => ( ))}
    )}
    ); }