"use client"; /** * Side panel shown when a node is selected. For precedent/halacha nodes it * deep-links into the existing precedent library (/precedents/[id]) so the * graph is a navigation surface, not a dead-end visualization. */ import Link from "next/link"; import { ExternalLink, X } from "lucide-react"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { Skeleton } from "@/components/ui/skeleton"; import type { GraphNode } from "@/lib/api/graph"; import { usePrecedent } from "@/lib/api/precedent-library"; const TYPE_LABELS: Record = { precedent: "פסיקה", halacha: "הלכה", topic: "נושא", practice_area: "תחום", gap: "פסיקה חסרה", digest: "יומון", }; const RULE_TYPE_LABELS: Record = { binding: "מחייב", interpretive: "פרשני", procedural: "דיוני", obiter: "אמרת אגב", application: "יישום", }; const GAP_STATUS_LABELS: Record = { open: "ממתינה לקליטה", uploaded: "הועלתה", closed: "טופלה", irrelevant: "לא רלוונטית", }; const PA_LABELS: Record = { rishuy_uvniya: "רישוי ובנייה", betterment_levy: "היטל השבחה", compensation_197: "פיצויים (ס׳ 197)", appeals_committee: "ועדת ערר", }; const SOURCE_LABELS: Record = { external_upload: "פסיקה חיצונית", internal_committee: "החלטת ועדה", cited_only: "מוזכר בלבד", nevo_seed: "נבו", }; export function GraphNodePanel({ node, onClose, }: { node: GraphNode; onClose: () => void; }) { const isPrecedentLike = node.type === "precedent" || node.type === "halacha"; const isPrecedent = node.type === "precedent"; const isHalacha = node.type === "halacha"; const isGap = node.type === "gap"; const isDigest = node.type === "digest"; // Rich detail (summary/headnote) for precedents — reuses the library hook. const detailId = isPrecedent ? node.case_law_id : null; const detail = usePrecedent(detailId); return (
{TYPE_LABELS[node.type] ?? node.type}

{node.label}

{isPrecedent && } {isHalacha && ( <> {node.source_kind && ( )} {node.note && (

{node.note}

)} )} {node.practice_area && ( )} {isPrecedent && node.source_kind && ( )} {node.precedent_level && } {isGap && ( <> {node.gap_status && ( )}

פסיקה זו מצוטטת בקורפוס אך אינה קיימת בו — מועמדת לקליטה.

)} {isDigest && ( <> {node.note && (

{node.note}

)} {node.court && } {node.date && }

סיכום יומי מ״כל יום״ — מצביע על הפסיקה שהוא מנתח.

)} {!isPrecedentLike && !isGap && !isDigest && (

לחיצה על נקודה זו מתמקדת בשכניה — כל הפסיקות המשויכות אליה.

)}
{detailId && (
{detail.isPending ? ( <> ) : detail.error ? (

לא ניתן לטעון תקציר.

) : detail.data?.headnote || detail.data?.summary ? (

{detail.data.headnote || detail.data.summary}

) : (

אין תקציר.

)}
)} {isPrecedentLike && node.case_law_id && ( )} {isGap && ( )} {isDigest && ( )}
); } function Row({ label, value }: { label: string; value: string }) { return (
{label}
{value}
); }