From 37cd28eab6160d2b7e9fc5a48fe7935effff8e40 Mon Sep 17 00:00:00 2001 From: Chaim Date: Tue, 16 Jun 2026 18:57:47 +0000 Subject: [PATCH] =?UTF-8?q?feat(precedents):=20=D7=A9=D7=99=D7=A4=D7=95?= =?UTF-8?q?=D7=A8=20=D7=98=D7=90=D7=91-=D7=94=D7=A1=D7=98=D7=98=D7=99?= =?UTF-8?q?=D7=A1=D7=98=D7=99=D7=A7=D7=94=20=E2=80=94=20=D7=9E=D7=A9=D7=A4?= =?UTF-8?q?=D7=9A-=D7=A1=D7=A7=D7=99=D7=A8=D7=94=20+=20=D7=A4=D7=A1=D7=99-?= =?UTF-8?q?=D7=A4=D7=99=D7=9C=D7=95=D7=97=20(#5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit נשאר תחת ספריית-פסיקה (לבקשת חיים) אך משופר: - שני מדדי-על: פסיקות בקורפוס · הלכות בסך-הכל. - כרטיס חדש "סטטוס סקירת הלכות" — פס-מוערם מאושרות/ממתינות/נדחו, מנצל את halachot_rejected שנחשף ב-/api/precedent-library/stats (PR #273). - "פילוח לפי תחום" ו"לפי רמת-תקדים" כפסים אופקיים במקום רשימות-טקסט. מאושר דרך שער-העיצוב (Claude Design 07b-precedents-stats). Invariant: G2 — צרכן read-only של מקור-הספירה היחיד (precedent_library_stats). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../precedents/library-stats-panel.tsx | 153 ++++++++++++------ 1 file changed, 102 insertions(+), 51 deletions(-) diff --git a/web-ui/src/components/precedents/library-stats-panel.tsx b/web-ui/src/components/precedents/library-stats-panel.tsx index 24e4829..e488d28 100644 --- a/web-ui/src/components/precedents/library-stats-panel.tsx +++ b/web-ui/src/components/precedents/library-stats-panel.tsx @@ -4,18 +4,82 @@ import { Skeleton } from "@/components/ui/skeleton"; import { useLibraryStats } from "@/lib/api/precedent-library"; import { practiceAreaLabel } from "./practice-area"; -function StatCard({ label, value, accent }: { label: string; value: number | string; accent?: boolean }) { +const fmt = (n: number) => n.toLocaleString("he-IL"); + +function StatCard({ label, value }: { label: string; value: number | string }) { return ( -
+
{label}
-
- {value} +
{value}
+
+ ); +} + +/** #5 — review-status funnel: one stacked bar (approved / pending / rejected) + * + legend with counts. Surfaces the rejected count now exposed by the stats + * endpoint, so the review pipeline is visible at a glance (mockup 07b). */ +function ReviewFunnel({ + approved, pending, rejected, +}: { approved: number; pending: number; rejected: number }) { + const total = approved + pending + rejected; + const pct = (n: number) => (total > 0 ? `${(n / total) * 100}%` : "0%"); + return ( +
+

סטטוס סקירת הלכות

+
+ + +
+
+ + + מאושרות (זמינות לסוכנים) + {fmt(approved)} + + + + ממתינות לאישור + {fmt(pending)} + + + + נדחו + {fmt(rejected)} + +
+
+ ); +} + +/** Distribution rendered as horizontal bars (was a plain count list). */ +function DistributionBars({ + title, rows, +}: { title: string; rows: { label: string; count: number }[] }) { + const max = Math.max(1, ...rows.map((r) => r.count)); + return ( +
+

{title}

+ {rows.length === 0 ? ( +

אין נתונים

+ ) : ( +
    + {rows.map((r) => ( +
  • + {r.label} + + + + + {r.count} + +
  • + ))} +
+ )}
); } @@ -33,56 +97,43 @@ export function LibraryStatsPanel() { if (isPending || !data) { return ( -
- {[...Array(4)].map((_, i) => )} +
+
+ {[...Array(2)].map((_, i) => )} +
+
); } return ( -
-
- - - 0} - /> - +
+
+ +
-
-
-

פילוח לפי תחום

- {data.by_practice_area.length === 0 ? ( -

אין נתונים

- ) : ( -
    - {data.by_practice_area.map((row) => ( -
  • - {practiceAreaLabel(row.practice_area || null)} - {row.count} -
  • - ))} -
- )} -
+ -
-

פילוח לפי רמת תקדים

- {data.by_precedent_level.length === 0 ? ( -

אין נתונים

- ) : ( -
    - {data.by_precedent_level.map((row) => ( -
  • - {row.precedent_level || "—"} - {row.count} -
  • - ))} -
- )} -
+
+ ({ + label: practiceAreaLabel(r.practice_area || null), + count: r.count, + }))} + /> + ({ + label: r.precedent_level || "לא סווג", + count: r.count, + }))} + />
); -- 2.49.1