feat(ui): IA redesign → production · צרור-2 (13 הדפים הנותרים, ליטוש-ויזואלי) #212

Merged
chaim merged 1 commits from worktree-ia-redesign-prod2 into main 2026-06-11 22:19:43 +00:00
9 changed files with 96 additions and 37 deletions

View File

@@ -156,14 +156,29 @@ export default function ArchivePage() {
<AppShell> <AppShell>
<section className="space-y-8"> <section className="space-y-8">
<header className="space-y-1.5"> <header className="space-y-1.5">
<div className="text-[0.75rem] uppercase tracking-[0.12em] text-gold-deep"> <nav className="text-[0.78rem] text-ink-muted mb-1">
ארכיון תיקי ערר <Link href="/" className="hover:text-gold-deep">בית</Link>
<span aria-hidden> · </span>
<span className="text-navy">ארכיון</span>
</nav>
<div className="flex items-end justify-between gap-4 flex-wrap">
<div className="space-y-1">
<div className="text-[0.75rem] uppercase tracking-[0.12em] text-gold-deep">
ארכיון תיקי ערר
</div>
<h1 className="text-navy mb-0">תיקים סגורים</h1>
<p className="text-ink-muted text-base max-w-2xl leading-relaxed">
תיקים שסגרו את הטיפול בהם. שחזור מחזיר את התיק לרשימה הראשית
ופותח מחדש את הפרויקט המקביל ב-Paperclip.
</p>
</div>
<div className="inline-flex items-baseline gap-2 rounded-lg border border-rule bg-gold-wash px-4 py-2.5">
<span className="text-2xl font-semibold text-gold-deep leading-none tabular-nums">
{table.getFilteredRowModel().rows.length}
</span>
<span className="text-[0.85rem] text-ink-soft">תיקים בארכיון</span>
</div>
</div> </div>
<h1 className="text-navy">תיקים סגורים</h1>
<p className="text-ink-muted text-base max-w-2xl leading-relaxed">
תיקים שסגרו את הטיפול בהם. שחזור מחזיר את התיק לרשימה הראשית
ופותח מחדש את הפרויקט המקביל ב-Paperclip.
</p>
</header> </header>
<div className="h-[2px] bg-gradient-to-l from-transparent via-gold to-transparent" /> <div className="h-[2px] bg-gradient-to-l from-transparent via-gold to-transparent" />
@@ -178,9 +193,6 @@ export default function ArchivePage() {
className="max-w-sm bg-surface" className="max-w-sm bg-surface"
dir="rtl" dir="rtl"
/> />
<span className="text-sm text-ink-muted me-auto">
{table.getFilteredRowModel().rows.length} תיקים בארכיון
</span>
</div> </div>
<div className="rounded-lg border border-rule bg-surface shadow-sm overflow-hidden"> <div className="rounded-lg border border-rule bg-surface shadow-sm overflow-hidden">

View File

@@ -86,9 +86,9 @@ function FeedbackCard({ fb }: { fb: ChairFeedback }) {
</p> </p>
{fb.lesson_extracted ? ( {fb.lesson_extracted ? (
<div className="rounded-md bg-gold-wash/40 border border-gold/30 px-3 py-2"> <div className="rounded-md bg-gold-wash/40 border-s-[3px] border-gold ps-3 pe-3 py-2">
<div className="text-[0.68rem] text-gold-deep mb-0.5">לקח שהופק</div> <div className="text-[0.68rem] text-gold-deep mb-0.5">לקח שהופק</div>
<p className="text-ink-soft text-[0.82rem] leading-relaxed m-0 whitespace-pre-wrap" dir="rtl"> <p className="text-ink-soft text-[0.82rem] leading-relaxed m-0 whitespace-pre-wrap italic" dir="rtl">
{fb.lesson_extracted} {fb.lesson_extracted}
</p> </p>
</div> </div>
@@ -104,7 +104,7 @@ function FeedbackCard({ fb }: { fb: ChairFeedback }) {
size="sm" size="sm"
onClick={onResolve} onClick={onResolve}
disabled={resolve.isPending} disabled={resolve.isPending}
className="bg-gold text-navy hover:bg-gold-deep" className="bg-gold text-white hover:bg-gold-deep border-transparent"
> >
<Check className="w-3.5 h-3.5 me-1" /> <Check className="w-3.5 h-3.5 me-1" />
סמן כיושם סמן כיושם

View File

@@ -1,5 +1,6 @@
"use client"; "use client";
import Link from "next/link";
import { AppShell } from "@/components/app-shell"; import { AppShell } from "@/components/app-shell";
import { Card, CardContent } from "@/components/ui/card"; import { Card, CardContent } from "@/components/ui/card";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
@@ -12,12 +13,19 @@ export default function MethodologyPage() {
return ( return (
<AppShell> <AppShell>
<section className="space-y-6"> <section className="space-y-6">
<div> <header>
<h1 className="text-xl font-bold text-navy">מתודולוגיה</h1> <nav className="text-[0.78rem] text-ink-muted mb-1">
<p className="text-sm text-ink-muted mt-1"> <Link href="/" className="hover:text-gold-deep">בית</Link>
<span aria-hidden> · </span>
<span className="text-navy">מתודולוגיה</span>
</nav>
<h1 className="text-navy mb-0">מתודולוגיה</h1>
<p className="text-ink-muted text-sm mt-1 max-w-2xl">
הגדרות ניסוח יחסי אורך, כללי דיון, וצ׳קליסטים לפי סוג ערר הגדרות ניסוח יחסי אורך, כללי דיון, וצ׳קליסטים לפי סוג ערר
</p> </p>
</div> </header>
<div className="h-[2px] bg-gradient-to-l from-transparent via-gold to-transparent" />
<Card className="bg-surface border-rule shadow-sm"> <Card className="bg-surface border-rule shadow-sm">
<CardContent className="px-6 py-5"> <CardContent className="px-6 py-5">

View File

@@ -56,12 +56,24 @@ export default function MissingPrecedentsPage() {
<span aria-hidden> · </span> <span aria-hidden> · </span>
<span className="text-navy">פסיקה חסרה בקורפוס</span> <span className="text-navy">פסיקה חסרה בקורפוס</span>
</nav> </nav>
<h1 className="text-navy mb-0">פסיקה חסרה בקורפוס</h1> <div className="flex items-end justify-between gap-4 flex-wrap">
<p className="text-ink-muted text-sm mt-1 max-w-3xl"> <div>
פסיקות שצוטטו בכתבי הטענות אך אינן עדיין בקורפוס. סוכן המחקר רושם <h1 className="text-navy mb-0">פסיקה חסרה בקורפוס</h1>
פערים אוטומטית; היו&quot;ר סוגר אותם על־ידי העלאת המסמך ניתוב <p className="text-ink-muted text-sm mt-1 max-w-3xl">
אוטומטי בין הקורפוס הסמכותי (פסקי דין) להחלטות ועדות ערר. פסיקות שצוטטו בכתבי הטענות אך אינן עדיין בקורפוס. סוכן המחקר רושם
</p> פערים אוטומטית; היו&quot;ר סוגר אותם על־ידי העלאת המסמך ניתוב
אוטומטי בין הקורפוס הסמכותי (פסקי דין) להחלטות ועדות ערר.
</p>
</div>
{byStatus.open ? (
<div className="inline-flex items-baseline gap-2 rounded-lg border border-rule bg-warn-bg px-4 py-2.5">
<span className="text-2xl font-semibold text-warn leading-none tabular-nums">
{byStatus.open}
</span>
<span className="text-[0.85rem] text-ink-soft">פתוחים</span>
</div>
) : null}
</div>
</header> </header>
<div className="h-[2px] bg-gradient-to-l from-transparent via-gold to-transparent" /> <div className="h-[2px] bg-gradient-to-l from-transparent via-gold to-transparent" />

View File

@@ -132,7 +132,7 @@ export default function PrecedentDetailPage({
<div className="flex items-center gap-2 flex-wrap"> <div className="flex items-center gap-2 flex-wrap">
{data.practice_area ? ( {data.practice_area ? (
<Badge variant="outline" className="text-[0.7rem]"> <Badge variant="outline" className="text-[0.7rem] bg-info-bg text-info border-transparent">
{PRACTICE_AREA_LABELS[data.practice_area] ?? data.practice_area} {PRACTICE_AREA_LABELS[data.practice_area] ?? data.practice_area}
</Badge> </Badge>
) : null} ) : null}
@@ -142,14 +142,14 @@ export default function PrecedentDetailPage({
</Badge> </Badge>
) : null} ) : null}
{data.precedent_level ? ( {data.precedent_level ? (
<Badge variant="outline" className="text-[0.7rem]"> <Badge variant="outline" className="text-[0.7rem] bg-gold-wash text-gold-deep border-rule">
{data.precedent_level} {data.precedent_level}
</Badge> </Badge>
) : null} ) : null}
{data.is_binding ? ( {data.is_binding ? (
<Badge <Badge
variant="outline" variant="outline"
className="text-[0.7rem] bg-gold-wash text-gold-deep border-gold/40" className="text-[0.7rem] bg-success-bg text-success border-transparent"
> >
הלכה מחייבת הלכה מחייבת
</Badge> </Badge>
@@ -185,7 +185,7 @@ export default function PrecedentDetailPage({
{(data as { key_quote?: string }).key_quote ? ( {(data as { key_quote?: string }).key_quote ? (
<div> <div>
<h3 className="text-navy text-sm font-semibold m-0 mb-1">ציטוט מרכזי</h3> <h3 className="text-navy text-sm font-semibold m-0 mb-1">ציטוט מרכזי</h3>
<blockquote className="text-ink-soft text-sm leading-relaxed border-r-2 border-gold pr-3 m-0"> <blockquote className="text-ink-soft text-sm leading-relaxed border-s-[3px] border-gold bg-gold-wash ps-3 pe-4 py-3 rounded-e m-0">
{(data as { key_quote?: string }).key_quote} {(data as { key_quote?: string }).key_quote}
</blockquote> </blockquote>
</div> </div>

View File

@@ -1,5 +1,6 @@
"use client"; "use client";
import Link from "next/link";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { AppShell } from "@/components/app-shell"; import { AppShell } from "@/components/app-shell";
@@ -35,7 +36,12 @@ export default function ScriptsPage() {
<section className="space-y-6"> <section className="space-y-6">
<div className="flex items-end justify-between gap-4"> <div className="flex items-end justify-between gap-4">
<div> <div>
<h1 className="text-xl font-bold text-navy">סקריפטים</h1> <nav className="text-[0.78rem] text-ink-muted mb-1">
<Link href="/" className="hover:text-gold-deep">בית</Link>
<span aria-hidden> · </span>
<span className="text-navy">סקריפטים</span>
</nav>
<h1 className="text-navy mb-0">סקריפטים</h1>
<p className="text-sm text-ink-muted mt-1"> <p className="text-sm text-ink-muted mt-1">
קטלוג כל הסקריפטים בתיקיית{" "} קטלוג כל הסקריפטים בתיקיית{" "}
<code className="rounded bg-rule-soft px-1 py-0.5 font-mono text-[0.78rem]"> <code className="rounded bg-rule-soft px-1 py-0.5 font-mono text-[0.78rem]">
@@ -60,6 +66,8 @@ export default function ScriptsPage() {
) : null} ) : null}
</div> </div>
<div className="h-[2px] bg-gradient-to-l from-transparent via-gold to-transparent" />
<Card className="bg-surface border-rule shadow-sm"> <Card className="bg-surface border-rule shadow-sm">
<CardContent className="px-6 py-5"> <CardContent className="px-6 py-5">
{isLoading ? ( {isLoading ? (

View File

@@ -15,15 +15,31 @@ function formatSize(bytes: number | null) {
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
} }
function StatusDot({ tone }: { tone: string }) {
return <span className={`h-1.5 w-1.5 rounded-full ${tone}`} aria-hidden />;
}
function statusBadge(s: Skill) { function statusBadge(s: Skill) {
if (s.not_in_db) { if (s.not_in_db) {
return <Badge variant="outline" className="bg-warn-bg text-warn border-warn/40">לא סונכרן</Badge>; return (
<Badge variant="outline" className="gap-1.5 bg-warn-bg text-warn border-warn/40">
<StatusDot tone="bg-warn" />לא סונכרן
</Badge>
);
} }
if (s.db_markdown_chars > 0 && s.disk_exists) { if (s.db_markdown_chars > 0 && s.disk_exists) {
return <Badge variant="outline" className="bg-success-bg text-success border-success/40">מסונכרן</Badge>; return (
<Badge variant="outline" className="gap-1.5 bg-success-bg text-success border-success/40">
<StatusDot tone="bg-success" />מסונכרן
</Badge>
);
} }
if (s.db_markdown_chars > 0) { if (s.db_markdown_chars > 0) {
return <Badge variant="outline" className="bg-info-bg text-info border-info/40">DB בלבד</Badge>; return (
<Badge variant="outline" className="gap-1.5 bg-info-bg text-info border-info/40">
<StatusDot tone="bg-info" />DB בלבד
</Badge>
);
} }
return <Badge variant="outline">לא ידוע</Badge>; return <Badge variant="outline">לא ידוע</Badge>;
} }

View File

@@ -44,8 +44,8 @@ export function AuthorityBadge({
title="דרגת-המחייבות נגזרת אוטומטית מזהות הערכאה" title="דרגת-המחייבות נגזרת אוטומטית מזהות הערכאה"
className={ className={
isBinding isBinding
? "text-[0.65rem] bg-gold/15 text-navy border-gold/50" ? "text-[0.65rem] bg-success-bg text-success border-transparent"
: "text-[0.65rem] bg-muted text-ink-muted border-border" : "text-[0.65rem] bg-gold-wash text-gold-deep border-rule"
} }
> >
{AUTHORITY_LABELS[authority]} {AUTHORITY_LABELS[authority]}

View File

@@ -42,7 +42,7 @@ function HalachaCard({ hit }: { hit: Extract<SearchHit, { type: "halacha" }> })
<p className="text-navy font-medium text-[0.95rem]" dir="rtl"> <p className="text-navy font-medium text-[0.95rem]" dir="rtl">
{hit.rule_statement} {hit.rule_statement}
</p> </p>
<blockquote className="text-ink-soft text-sm border-r-2 border-gold pr-3" dir="rtl"> <blockquote className="text-ink-soft text-sm border-s-2 border-gold ps-3" dir="rtl">
&ldquo;{hit.supporting_quote}&rdquo; &ldquo;{hit.supporting_quote}&rdquo;
{hit.page_reference && <span className="text-ink-muted text-[0.72rem] ms-2">({hit.page_reference})</span>} {hit.page_reference && <span className="text-ink-muted text-[0.72rem] ms-2">({hit.page_reference})</span>}
</blockquote> </blockquote>
@@ -63,7 +63,7 @@ function PassageCard({ hit }: { hit: Extract<SearchHit, { type: "passage" }> })
return ( return (
<div className="rounded-lg border border-rule bg-surface p-4 space-y-2"> <div className="rounded-lg border border-rule bg-surface p-4 space-y-2">
<div className="flex items-center gap-2 text-[0.78rem] text-ink-muted flex-wrap"> <div className="flex items-center gap-2 text-[0.78rem] text-ink-muted flex-wrap">
<Badge variant="outline" className="bg-rule-soft text-ink-muted">קטע</Badge> <Badge variant="outline" className="bg-info-bg text-info border-transparent">קטע</Badge>
<span className="font-mono" dir="ltr">{hit.case_number}</span> <span className="font-mono" dir="ltr">{hit.case_number}</span>
{hit.court && <span>· {hit.court}</span>} {hit.court && <span>· {hit.court}</span>}
{hit.decision_date && <span>· {formatDate(hit.decision_date)}</span>} {hit.decision_date && <span>· {formatDate(hit.decision_date)}</span>}
@@ -161,8 +161,11 @@ export function LibrarySearchPanel() {
</div> </div>
) : ( ) : (
<div className="space-y-3"> <div className="space-y-3">
<p className="text-[0.78rem] text-ink-muted"> <p className="text-[0.78rem] text-ink-muted flex items-center gap-2">
{data.count} תוצאות (הלכות מאושרות בלבד) <span className="inline-flex items-center rounded-full bg-success-bg text-success text-[0.7rem] font-semibold px-2.5 py-0.5">
הלכות מאושרות בלבד
</span>
<span className="tabular-nums">{data.count} תוצאות</span>
</p> </p>
{data.items.map((hit, i) => {data.items.map((hit, i) =>
hit.type === "halacha" ? ( hit.type === "halacha" ? (