feat(precedents): formal citation per Israeli citation rules + copy/edit UI
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 3m25s
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 3m25s
Until now, "case_number" was the only stored identifier for a precedent.
But a *citation per the Israeli unified citation rules* is a different
beast — it has bold parties, an unbold prefix (court abbrev + panel/
district parenthetical + case number), and an unbold trailing reporter
(נבו / פ"ד...). Without storing it as a first-class field we couldn't
hand the chair a one-click "copy as citation" experience for pasting
into decisions.
Changes:
- Schema V19: case_law.citation_formatted TEXT (Markdown — parties
wrapped in **…** so the copy helper can render <strong> for Word/Docs
paste and keep plain-text fallback meaningful).
- Metadata extractor: composes citation_formatted from the document
text per the unified citation rules, with worked examples for ע"א /
עת"מ / ערר / בל"מ in the prompt. Refuses to store half-formed strings.
- PATCH /api/precedent-library/{id} accepts citation_formatted so the
chair can correct LLM mistakes.
- /precedents/[id]: dedicated "מראה מקום" block with bold rendering,
a copy-to-clipboard button (text/html + text/plain so Word keeps
the bolds), and an inline edit textarea.
- /precedents list rows: link displays the formatted citation when
available, with a small inline copy button — falls back to the bare
case_number for older rows.
Backfill of existing rows happens by re-stamping the extraction queue
once V19 has rolled out and the new field is reachable.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,10 @@ import {
|
||||
import { PRACTICE_AREAS, practiceAreaShort } from "./practice-area";
|
||||
import { PrecedentUploadSheet } from "./precedent-upload-sheet";
|
||||
import { PrecedentEditSheet } from "./precedent-edit-sheet";
|
||||
import {
|
||||
FormattedCitation,
|
||||
CitationCopyButton,
|
||||
} from "./formatted-citation";
|
||||
|
||||
function formatDate(iso: string | null) {
|
||||
if (!iso) return "—";
|
||||
@@ -152,9 +156,25 @@ function CourtRow({ p, onEdit }: { p: Precedent; onEdit: (id: string) => void })
|
||||
className="font-semibold text-navy text-right whitespace-normal break-words min-w-[280px] max-w-[420px] py-3"
|
||||
dir="rtl"
|
||||
>
|
||||
<Link href={`/precedents/${p.id}`} className="hover:underline hover:text-gold-deep" dir="auto">
|
||||
{cleanCitation(p.case_number)}
|
||||
</Link>
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<Link
|
||||
href={`/precedents/${p.id}`}
|
||||
className="hover:underline hover:text-gold-deep block min-w-0"
|
||||
dir="auto"
|
||||
>
|
||||
{p.citation_formatted ? (
|
||||
<FormattedCitation
|
||||
citation={p.citation_formatted}
|
||||
className="block leading-snug"
|
||||
/>
|
||||
) : (
|
||||
cleanCitation(p.case_number)
|
||||
)}
|
||||
</Link>
|
||||
{p.citation_formatted ? (
|
||||
<CitationCopyButton citation={p.citation_formatted} size="xs" />
|
||||
) : null}
|
||||
</div>
|
||||
</TableCell>
|
||||
{/* Column "שם / ערכאה" hidden by request (case_name often equals case_number prefix). Keep field in DB; restore by un-hiding. */}
|
||||
<TableCell className="hidden text-ink whitespace-normal break-words max-w-[260px] py-3">
|
||||
@@ -237,9 +257,25 @@ function CommitteeRow({ p, onEdit }: { p: Precedent; onEdit: (id: string) => voi
|
||||
className="font-semibold text-navy text-right whitespace-normal break-words min-w-[200px] max-w-[320px] py-3"
|
||||
dir="rtl"
|
||||
>
|
||||
<Link href={`/precedents/${p.id}`} className="hover:underline hover:text-gold-deep" dir="auto">
|
||||
{cleanCitation(p.case_number)}
|
||||
</Link>
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<Link
|
||||
href={`/precedents/${p.id}`}
|
||||
className="hover:underline hover:text-gold-deep block min-w-0"
|
||||
dir="auto"
|
||||
>
|
||||
{p.citation_formatted ? (
|
||||
<FormattedCitation
|
||||
citation={p.citation_formatted}
|
||||
className="block leading-snug"
|
||||
/>
|
||||
) : (
|
||||
cleanCitation(p.case_number)
|
||||
)}
|
||||
</Link>
|
||||
{p.citation_formatted ? (
|
||||
<CitationCopyButton citation={p.citation_formatted} size="xs" />
|
||||
) : null}
|
||||
</div>
|
||||
</TableCell>
|
||||
{/* Column "שם" hidden by request (case_name often equals case_number prefix). Keep field in DB; restore by un-hiding. */}
|
||||
<TableCell className="hidden text-ink whitespace-normal break-words max-w-[220px] py-3">
|
||||
|
||||
Reference in New Issue
Block a user