"use client"; import { useEffect, useState } from "react"; import Link from "next/link"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { AppShell } from "@/components/app-shell"; import { LibraryListPanel } from "@/components/precedents/library-list-panel"; import { LibrarySearchPanel } from "@/components/precedents/library-search-panel"; import { HalachaReviewPanel } from "@/components/precedents/halacha-review-panel"; import { LibraryStatsPanel } from "@/components/precedents/library-stats-panel"; import { useHalachotPending } from "@/lib/api/precedent-library"; import { useMissingPrecedents } from "@/lib/api/missing-precedents"; /** * Precedent Library admin page. * * Four tabs: * - ספרייה — browse all uploaded precedents (filters + upload + delete) * - חיפוש סמנטי — semantic search across halachot + chunks * - ממתין לאישור — chair review queue (PRIMARY tab; halachot from * auto-extraction must be approved before agents can use them) * - סטטיסטיקה — counts and coverage * * Distinct from /training (style corpus = Daphna's voice) and the * per-case precedent attacher (chair-attached quotes scoped to a case). */ /** Colored count pill riding on a tab trigger (mockup 07: warn for review * queue, info for incoming). Returns null when the queue is empty. */ function CountPill({ n, tone }: { n: number; tone: "warn" | "info" }) { if (!n) return null; const cls = tone === "warn" ? "bg-warn text-white" : "bg-info text-white"; return ( {n} ); } function PendingPill() { const { data } = useHalachotPending(); return ; } function IncomingPill() { // "פסיקה נכנסת" = open missing-precedents waiting for the chair to upload. const { data } = useMissingPrecedents({ status: "open", limit: 1 }); return ; } const PRECEDENT_TABS = new Set(["library", "search", "review", "incoming", "stats"]); export default function PrecedentsPage() { // Controlled so a deep link like /precedents?tab=review (e.g. from a pending // halacha on a precedent-detail page, #133) lands on the right tab. Read after // mount to avoid an SSR/CSR mismatch and the useSearchParams Suspense rule. const [tab, setTab] = useState("library"); useEffect(() => { // read post-mount (not lazy init) to avoid an SSR/CSR hydration mismatch const t = new URLSearchParams(window.location.search).get("tab"); // eslint-disable-next-line react-hooks/set-state-in-effect if (t && PRECEDENT_TABS.has(t)) setTab(t); }, []); return (

ספריית הפסיקה הסמכותית

קורפוס הפסיקה והלכות המערכת — חיפוש סמנטי, תור-אישור והשלמת פסיקה חסרה. כל קובץ עובר חילוץ הלכות אוטומטי, וההלכות ממתינות לאישור היו"ר לפני שהן זמינות לסוכני הכתיבה.

{/* tabs as a dedicated row under the header — underline-style triggers with colored count pills (mockup 07). */} {[ { value: "library", label: "ספרייה", pill: null }, { value: "search", label: "חיפוש בקורפוס", pill: null }, { value: "review", label: "תור הלכות", pill: }, { value: "incoming", label: "פסיקה נכנסת", pill: , }, { value: "stats", label: "סטטיסטיקה", pill: null }, ].map((t) => ( {t.label} {t.pill} ))}
{/* "פסיקה נכנסת" — the incoming/missing-precedent queue. Kept as a tab per the mockup; full management lives on /missing-precedents. */}
); } /** Lightweight in-tab pointer to the dedicated missing-precedents page, * preserving the mockup's "פסיקה נכנסת" tab without duplicating the table. */ function IncomingTab() { const { data } = useMissingPrecedents({ status: "open", limit: 1 }); const open = data?.by_status?.open ?? 0; return (

פסיקה נכנסת

{open ? ( {open} פתוחים ) : null}

פסיקה שצוטטה בכתבי-הטענות אך אינה קיימת בקורפוס. השלמתה מאפשרת אימות-הלכה ועיגון-מקור (INV-AH).

לניהול פסיקה חסרה ←
); }