"use client"; import { useRef, useState } from "react"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Skeleton } from "@/components/ui/skeleton"; import { SubsectionCard } from "@/components/compose/subsection-card"; import { PrecedentsSection } from "@/components/compose/precedents-section"; import { Markdown } from "@/components/ui/markdown"; import { useCase } from "@/lib/api/cases"; import { useResearchAnalysis } from "@/lib/api/research"; import { useCasePrecedents } from "@/lib/api/precedents"; /* * PositionsPanel — the chair's editing surface for the analyst's threshold * claims + issues (chair positions feed block י). Extracted verbatim from the * former /compose "עמדות וטענות" tab when the decision editor was merged into * the main case page (X17 #3). Lives inside the "טיעונים ועמדות" tab above the * collapsible by-party aggregated arguments. The 12-block editor + citation * verification moved to their own top-level tabs; /compose was deleted. * * The threshold-claim / issue cards deliberately stack in a SINGLE column. * They were a two-column CSS grid, but grid rows share a height: expanding one * card grew its row and shoved every card below it down — in *both* columns. * A single column keeps the jump local to what sits underneath, and gives the * expanded body (fields + chair editor + supporting precedents) full width * instead of half. Do not reintroduce `lg:grid-cols-2` here (chair, 2026-08-04). */ function ProseSection({ title, content }: { title: string; content?: string }) { if (!content?.trim()) return null; return (

{title}

); } // ── "ייצוא ועדכון הניתוח" rail card — round-trips the analysis-and-research.md // research analysis: export DOCX, upload an updated version, download the raw MD. // (Post-final learning status lives on the drafts tab, not here — #226.) ────── function FinishRail({ caseNumber, hasAnalysis, onUploaded, }: { caseNumber: string; hasAnalysis: boolean; onUploaded: () => void; }) { const fileRef = useRef(null); const [uploading, setUploading] = useState(false); const [uploadMsg, setUploadMsg] = useState<{ ok: boolean; text: string } | null>(null); async function handleUpload(file: File) { setUploading(true); setUploadMsg(null); try { const form = new FormData(); form.append("file", file); const res = await fetch(`/api/cases/${caseNumber}/research/analysis/upload`, { method: "PUT", body: form, }); const data = await res.json(); if (!res.ok) { setUploadMsg({ ok: false, text: data.detail || "שגיאה בהעלאה" }); return; } setUploadMsg({ ok: true, text: `הקובץ הועלה — ${data.sections.threshold_claims} טענות סף, ${data.sections.issues} סוגיות`, }); onUploaded(); } catch { setUploadMsg({ ok: false, text: "שגיאת רשת" }); } finally { setUploading(false); if (fileRef.current) fileRef.current.value = ""; } } return (

ייצוא ועדכון הניתוח

פעולות על קובץ ניתוח-המחקר (analysis-and-research.md).

{ const f = e.target.files?.[0]; if (f) handleUpload(f); }} />
{hasAnalysis && ( )} {hasAnalysis && ( )}
{uploadMsg && (

{uploadMsg.text}

)}
); } export function PositionsPanel({ caseNumber }: { caseNumber: string }) { const caseQuery = useCase(caseNumber); const analysis = useResearchAnalysis(caseNumber); const precedentsQuery = useCasePrecedents(caseNumber); const allPrecedents = precedentsQuery.data ?? []; const caseLevelPrecedents = allPrecedents.filter((p) => p.section_id === null); const precedentsBySection = new Map(); for (const p of allPrecedents) { if (p.section_id) { const existing = precedentsBySection.get(p.section_id) ?? []; existing.push(p); precedentsBySection.set(p.section_id, existing); } } const practiceArea = caseQuery.data?.practice_area ?? null; const isNotFound = analysis.error instanceof Error && /404|לא נמצא|טרם בוצע/.test(analysis.error.message); return (
{analysis.isPending ? ( ) : isNotFound ? (

טרם בוצע ניתוח משפטי לתיק זה

לאחר שקובץ analysis-and-research.md ייווצר, תוכלי לערוך כאן את עמדת הוועדה לכל טענת סף וסוגיה.

) : analysis.error ? (

{analysis.error.message}

) : analysis.data ? (
{analysis.data.threshold_claims && analysis.data.threshold_claims.length > 0 && (

טענות סף

{analysis.data.threshold_claims.length}
{analysis.data.threshold_claims.map((tc) => ( ))}
)} {analysis.data.issues && analysis.data.issues.length > 0 && (

סוגיות להכרעה

{analysis.data.issues.length}
{analysis.data.issues.map((iss) => ( ))}
)} {!analysis.data.threshold_claims?.length && !analysis.data.issues?.length && ( לא נמצאו טענות סף או סוגיות בניתוח זה. )}

רקע לניתוח

{analysis.data.conclusions?.trim() && (

מסקנות

)}
) : null} {/* case-level פסיקה מצורפת + analysis export/update (INV-IA3: not removed). items-stretch keeps both cards the same height (#226). */}

פסיקה מצורפת

ציטוטים התומכים בעמדה באופן רוחבי — ישולבו בפתיחת בלוק י (דיון).

analysis.refetch()} />
); }