ui(precedents): collapsible groups by precedent + Hebrew labels + RTL fixes
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 33s
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 33s
After running the dual-mode halacha extractor on a real appeals committee decision (403-17), the pending-review tab surfaced 351 halachot in a single flat list — the chair correctly pointed out that this is unusable without grouping. Three fixes: 1. Group pending halachot by precedent (case_law_id). Each group shows the citation, court, date, level and item count; default state is collapsed so the chair picks one ruling at a time. Within a group, items still sort by confidence ascending so the doubtful ones surface first. J/K/A/R/E now scope to currently-expanded groups; toggling open auto-focuses the first item. 2. Translate the badges that were leaking English: rule_type values (`persuasive`, `interpretive`, `binding`, `application`, `procedural`, `obiter`) now render as Hebrew labels, and `confidence X.XX` becomes `ביטחון X.XX`. The card header no longer repeats the citation since it's already in the group header. 3. Strip Unicode bidi marks (U+200E/F/202A-E/2066-9) from displayed citations. Nevo PDFs and the upload form embed these in the case_number; they render as zero-width but visually push the text away from the right edge of the table cell. Also: hide the empty court line under the case name in the list (was rendering as a stray em-dash), and use a muted em-dash for empty date/level rather than blank/dash inconsistency across columns. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,15 @@ function formatDate(iso: string | null) {
|
||||
}
|
||||
}
|
||||
|
||||
/* The upload form (and Nevo PDFs) embed Unicode bidi marks (RTL/LTR/embedding/
|
||||
* isolate) inside the citation. They render as zero-width but visually push
|
||||
* the text away from the cell edge. Strip them for display only — DB still
|
||||
* has the original. */
|
||||
function cleanCitation(s: string | null | undefined): string {
|
||||
if (!s) return "—";
|
||||
return s.replace(/[--]/g, "").trim();
|
||||
}
|
||||
|
||||
function StatusPill({ p }: { p: Precedent }) {
|
||||
if (p.extraction_status === "failed") {
|
||||
return <Badge variant="outline" className="bg-danger-bg text-danger border-danger/40">נכשל</Badge>;
|
||||
@@ -75,14 +84,18 @@ function PrecedentRow({
|
||||
|
||||
return (
|
||||
<TableRow className="border-rule hover:bg-gold-wash/30">
|
||||
<TableCell className="font-semibold text-navy" dir="ltr">
|
||||
{p.case_number}
|
||||
<TableCell className="font-semibold text-navy text-right" dir="rtl">
|
||||
<span dir="auto">{cleanCitation(p.case_number)}</span>
|
||||
</TableCell>
|
||||
<TableCell className="text-ink">
|
||||
<div className="font-medium">{p.case_name || "—"}</div>
|
||||
<div className="text-[0.72rem] text-ink-muted">{p.court || "—"}</div>
|
||||
<div className="font-medium">{cleanCitation(p.case_name)}</div>
|
||||
{p.court ? (
|
||||
<div className="text-[0.72rem] text-ink-muted">{p.court}</div>
|
||||
) : null}
|
||||
</TableCell>
|
||||
<TableCell className="text-ink-muted">
|
||||
{p.date ? formatDate(p.date) : <span className="text-ink-light">—</span>}
|
||||
</TableCell>
|
||||
<TableCell className="text-ink-muted">{formatDate(p.date)}</TableCell>
|
||||
<TableCell>
|
||||
{p.practice_area ? (
|
||||
<Badge variant="outline" className="bg-navy-soft/40 text-navy border-navy/30">
|
||||
@@ -93,7 +106,11 @@ function PrecedentRow({
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell className="text-ink-muted text-[0.78rem]">
|
||||
{p.precedent_level || "—"}
|
||||
{p.precedent_level ? (
|
||||
p.precedent_level
|
||||
) : (
|
||||
<span className="text-ink-light">—</span>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<StatusPill p={p} />
|
||||
|
||||
Reference in New Issue
Block a user