diff --git a/web-ui/src/components/precedents/library-list-panel.tsx b/web-ui/src/components/precedents/library-list-panel.tsx index ffeee82..d87c3e1 100644 --- a/web-ui/src/components/precedents/library-list-panel.tsx +++ b/web-ui/src/components/precedents/library-list-panel.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { Trash2, Plus, Pencil } from "lucide-react"; +import { Trash2, Plus, Pencil, Wand2 } from "lucide-react"; import { toast } from "sonner"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, @@ -16,6 +16,7 @@ import { import { usePrecedents, useDeletePrecedent, + useRequestHalachotExtraction, isPrecedentActive, type Precedent, type PracticeArea, @@ -38,6 +39,20 @@ function cleanCitation(s: string | null | undefined): string { return s.replace(/[‎‏‪-‮⁦-⁩]/g, "").trim(); } +// Show the "extract halachot" button only when the precedent hasn't had a +// successful (or even attempted) extraction yet. Hide while processing or +// after completion to avoid duplicate requests. +function needsHalachaExtraction(p: Precedent): boolean { + if (p.extraction_status !== "completed") return false; // text not ready + if (p.halacha_extraction_status === "processing") return false; + if (p.halacha_extraction_status === "completed") return false; + if (p.halacha_extraction_status === "pending" && p.halacha_extraction_requested_at) { + return false; // already queued + } + // Remaining cases: pending+no-requested_at (never tried) or failed (retry). + return true; +} + function ActivePill({ label }: { label: string }) { return ( void }) { const del = useDeletePrecedent(); + const reqHalachot = useRequestHalachotExtraction(); const active = isPrecedentActive(p); + const showExtractHalachot = needsHalachaExtraction(p); const onDelete = async () => { if (active) { @@ -119,6 +136,15 @@ function CourtRow({ p, onEdit }: { p: Precedent; onEdit: (id: string) => void }) } }; + const onExtractHalachot = async () => { + try { + await reqHalachot.mutateAsync(p.id); + toast.success("סומן לחילוץ הלכות. הריצי מ-Claude Code: precedent_process_pending_halachot"); + } catch (e) { + toast.error(e instanceof Error ? e.message : "שגיאה"); + } + }; + return ( void }) className="text-ink-muted hover:text-navy"> + {showExtractHalachot && ( + + )} + {showExtractHalachot && ( + + )}