feat(ui): IA redesign → production · יישום נאמן של 16 הדפים הנותרים למוקאפים
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 6s
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 6s
תיקון הגישה: יישום מלא ונאמן של עיצוב-המוקאפים המאושרים (Claude Design) על כל הדפים — שינוי-הרכב אמיתי פר-מוקאפ, לא ליטוש-טוקנים. כל hook/query/mutation/טאב/ טופס/נתון נשמר (אומת: tsc נקי + בדיקת-נוכחות hooks קריטיים; 0 פונקציונליות נמחקה). דפים (← מוקאפ): - בית — לוח: KPI + "תיקים לפי סטטוס" (bars) + כרטיס-אישורים + CTA כפול. - ארכיון — filter-bar שטוח + טבלה נקייה + צ'יפי-סוג/תוצאה. - הערות יו״ר — פריסה דו-טורית + טופס-הוספה חי + כרטיסי-הערה. - ספריית-פסיקה — tabs קו-תחתון + כרטיסי-תוצאה halacha/קטע + AuthorityBadge. - דף-תקדים — באנר-meta parchment + דו-טורי + provenance pills. - פסיקה-חסרה — pill פתוחים + צ'יפי-סטטוס + CTA העלאה. - יומונים — אזור-העלאה מקווקו + כרטיסי-digest + "ממתין" כתווית פסיבית. - גרף — פאנל-צד שכבות/אנליטיקה + canvas parchment. - אימון-סגנון — פורטרט: banner + KPI + אנטומיה + ביטויי-חתימה. - מתודולוגיה — עורך-צ'קליסט + "חל על:" + canon chip. - מיומנויות/סקריפטים — טבלאות אמיתיות + צ'יפי-סטטוס. - הגדרות — sidenav דו-טורי + env-rows עם "ממתין ל-redeploy". - דף-תיק — באנר-תיק parchment + tabs + timeline + "פתח עורך החלטה". - תפעול — SectionHeaders + טבלת-שירותים + כרטיסי-שער gold-wash. - compose — באנר-תיק + SOT pill + פריסה דו-טורית + "השלמה והעברה". תיקונים שלי אחרי הסוכנים: documents-panel (הוצאת רכיב Shell מ-render — React Compiler), scripts useMemo deps. /approvals כבר נבנה מחדש נאמנה (commit קודם). בדיקות: npx tsc --noEmit ✓ · eslint ✓ (לבד מ-learning-panel:109 קיים-מראש). שימור-פונקציונליות אומת. CI Docker build = שער סופי לפני deploy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -33,26 +33,24 @@ export function DigestCard({
|
||||
actions?: ReactNode;
|
||||
}) {
|
||||
const linked = Boolean(digest.linked_case_law_id);
|
||||
const pending = digest.extraction_status !== "completed";
|
||||
return (
|
||||
<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">
|
||||
{digest.concept_tag && (
|
||||
<Badge className="bg-gold text-navy border-0">{digest.concept_tag}</Badge>
|
||||
)}
|
||||
<div className="flex flex-col rounded-lg border border-rule bg-surface shadow-sm p-4">
|
||||
{/* top row — yomon-number + date at start, concept tag pushed to end */}
|
||||
<div className="flex items-center gap-2.5 mb-2.5 flex-wrap">
|
||||
{digest.yomon_number && (
|
||||
<span className="font-mono" dir="ltr">
|
||||
<span className="text-navy font-bold text-[0.95rem]">
|
||||
יומון {digest.yomon_number}
|
||||
</span>
|
||||
)}
|
||||
{digest.digest_date && (
|
||||
<span className="text-ink-muted text-[0.78rem]">· {formatDate(digest.digest_date)}</span>
|
||||
)}
|
||||
{digest.publication && digest.publication !== "כל יום" && (
|
||||
<Badge variant="outline" className="bg-rule-soft text-ink-muted text-[0.65rem]">
|
||||
{digest.publication}
|
||||
</Badge>
|
||||
)}
|
||||
{digest.digest_date && <span>· {formatDate(digest.digest_date)}</span>}
|
||||
{digest.practice_area && (
|
||||
<span>· {practiceAreaLabel(digest.practice_area)}</span>
|
||||
)}
|
||||
{digest.digest_kind === "announcement" && (
|
||||
<Badge variant="outline" className="bg-sky-50 text-sky-700 border-sky-300 text-[0.65rem]">
|
||||
עדכון
|
||||
@@ -63,47 +61,45 @@ export function DigestCard({
|
||||
מאמר
|
||||
</Badge>
|
||||
)}
|
||||
{digest.extraction_status !== "completed" && (
|
||||
<Badge variant="outline" className="bg-rule-soft text-ink-muted text-[0.65rem]">
|
||||
{digest.extraction_status === "pending" ? "ממתין לעיבוד" : digest.extraction_status}
|
||||
</Badge>
|
||||
{digest.concept_tag && (
|
||||
<span className="ms-auto rounded-full bg-info-bg text-info text-[0.72rem] font-semibold px-2.5 py-0.5">
|
||||
{digest.concept_tag}
|
||||
</span>
|
||||
)}
|
||||
{typeof score === "number" && (
|
||||
<span className="ms-auto tabular-nums">דירוג {score.toFixed(2)}</span>
|
||||
<span className="ms-1 tabular-nums text-ink-muted text-[0.78rem]">
|
||||
דירוג {score.toFixed(2)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* holding — the digest headline */}
|
||||
{digest.headline_holding && (
|
||||
<p className="text-navy font-medium text-[0.95rem]" dir="rtl">
|
||||
<p className="text-ink font-medium text-[0.92rem] leading-6 mb-2.5" dir="rtl">
|
||||
{digest.headline_holding}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* source ruling — "מקור:" + citation, start-bordered (mockup `.ruling`) */}
|
||||
<div className="border-s-2 border-rule ps-3 text-[0.8rem] text-ink-muted leading-6" dir="rtl">
|
||||
<b className="text-ink-soft font-semibold">מקור:</b>{" "}
|
||||
{digest.underlying_citation || "—"}
|
||||
</div>
|
||||
|
||||
{digest.summary && (
|
||||
<p className="text-ink-soft text-sm leading-relaxed" dir="rtl">
|
||||
<p className="text-ink-soft text-[0.82rem] leading-relaxed mt-2" dir="rtl">
|
||||
{digest.summary}
|
||||
</p>
|
||||
)}
|
||||
|
||||
<div className="flex items-start gap-2 flex-wrap pt-1 border-t border-rule-soft mt-1">
|
||||
<span className="text-[0.72rem] text-ink-muted mt-1">פסק מקורי:</span>
|
||||
<span className="text-[0.82rem] text-ink font-mono flex-1 min-w-[200px]" dir="rtl">
|
||||
{digest.underlying_citation || "—"}
|
||||
{digest.practice_area && (
|
||||
<span className="text-ink-muted text-[0.72rem] mt-2">
|
||||
{practiceAreaLabel(digest.practice_area)}
|
||||
</span>
|
||||
{linked ? (
|
||||
<Link href={`/precedents/${digest.linked_case_law_id}`}>
|
||||
<Badge className="bg-emerald-100 text-emerald-800 border-emerald-300 hover:bg-emerald-200">
|
||||
מקושר לפסק ↗
|
||||
</Badge>
|
||||
</Link>
|
||||
) : (
|
||||
<Badge variant="outline" className="bg-amber-50 text-amber-700 border-amber-300">
|
||||
הפסק טרם בקורפוס
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{digest.subject_tags?.length > 0 && (
|
||||
<div className="flex flex-wrap gap-1">
|
||||
<div className="flex flex-wrap gap-1 mt-2">
|
||||
{digest.subject_tags.map((t) => (
|
||||
<Badge key={t} variant="outline" className="text-[0.65rem] bg-surface">
|
||||
{t}
|
||||
@@ -112,7 +108,31 @@ export function DigestCard({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{actions && <div className="flex items-center gap-2 pt-1">{actions}</div>}
|
||||
{/* foot — link-status chip + passive "ממתין לעיבוד" label (mockup `.foot`) */}
|
||||
<div className="mt-3 pt-3 border-t border-rule-soft flex items-center gap-2 flex-wrap">
|
||||
{linked ? (
|
||||
<Link href={`/precedents/${digest.linked_case_law_id}`}>
|
||||
<span className="rounded-full bg-success-bg text-success text-[0.72rem] font-semibold px-3 py-0.5 hover:opacity-90">
|
||||
מקושר לפסיקה ↗
|
||||
</span>
|
||||
</Link>
|
||||
) : (
|
||||
<span className="rounded-full bg-rule-soft text-ink-muted text-[0.72rem] font-semibold px-3 py-0.5">
|
||||
לא מקושר
|
||||
</span>
|
||||
)}
|
||||
{pending && (
|
||||
/* passive status label — a dot + text, deliberately NOT a button */
|
||||
<span className="ms-auto inline-flex items-center gap-1.5 text-[0.72rem] font-medium text-ink-muted">
|
||||
<span className="h-[7px] w-[7px] rounded-full bg-warn/60" aria-hidden />
|
||||
{digest.extraction_status === "pending" ? "ממתין לעיבוד" : digest.extraction_status}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{actions && (
|
||||
<div className="flex items-center gap-2 pt-3">{actions}</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
import type { PracticeArea } from "@/lib/api/precedent-library";
|
||||
import { PRACTICE_AREAS } from "@/components/precedents/practice-area";
|
||||
import { DigestCard } from "./digest-card";
|
||||
import { DigestUploadDialog } from "./digest-upload-dialog";
|
||||
|
||||
type LinkedFilter = "all" | "linked" | "unlinked";
|
||||
|
||||
@@ -96,9 +95,6 @@ export function DigestListPanel() {
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="ms-auto">
|
||||
<DigestUploadDialog />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{error ? (
|
||||
@@ -117,6 +113,8 @@ export function DigestListPanel() {
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
<p className="text-[0.78rem] text-ink-muted">{data.count} יומונים</p>
|
||||
{/* two-column card grid (mockup 10 `.grid`) */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
{data.items.map((d) => (
|
||||
<DigestCard
|
||||
key={d.id}
|
||||
@@ -148,6 +146,7 @@ export function DigestListPanel() {
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -24,7 +24,7 @@ import { PRACTICE_AREAS } from "@/components/precedents/practice-area";
|
||||
* via the MCP drainer ``digest_process_pending`` — so the toast tells the
|
||||
* user the digest is queued, not yet searchable.
|
||||
*/
|
||||
export function DigestUploadDialog() {
|
||||
export function DigestUploadDialog({ trigger }: { trigger?: React.ReactNode } = {}) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [yomonNumber, setYomonNumber] = useState("");
|
||||
@@ -71,10 +71,12 @@ export function DigestUploadDialog() {
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button className="bg-navy text-parchment hover:bg-navy-soft">
|
||||
<Upload className="w-4 h-4 me-1" />
|
||||
העלאת יומון
|
||||
</Button>
|
||||
{trigger ?? (
|
||||
<Button className="bg-gold text-white hover:bg-gold-deep border-transparent">
|
||||
<Upload className="w-4 h-4 me-1" />
|
||||
העלאת יומון
|
||||
</Button>
|
||||
)}
|
||||
</DialogTrigger>
|
||||
<DialogContent dir="rtl">
|
||||
<DialogHeader>
|
||||
@@ -140,7 +142,7 @@ export function DigestUploadDialog() {
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={upload.isPending}
|
||||
className="bg-navy text-parchment hover:bg-navy-soft"
|
||||
className="bg-gold text-white hover:bg-gold-deep border-transparent"
|
||||
>
|
||||
{upload.isPending ? "מעלה…" : "העלה"}
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user