feat(ui): IA redesign → production · יישום נאמן של 16 הדפים הנותרים למוקאפים
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:
2026-06-11 23:00:25 +00:00
parent c53ef9a7c4
commit f3b075d282
32 changed files with 2925 additions and 1799 deletions

View File

@@ -1,7 +1,7 @@
"use client";
import { useState, useEffect } from "react";
import { Card, CardContent } from "@/components/ui/card";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Textarea } from "@/components/ui/textarea";
@@ -115,84 +115,124 @@ export function ContentChecklistsPanel() {
);
}
const itemCount = current
? current.draft.split("\n").filter((l) => /^\s*-\s*\[/.test(l)).length
: 0;
return (
<div className="space-y-4">
{/* Tab selector */}
<div className="flex gap-2 flex-wrap">
{items.map((item) => (
<Button
key={item.key}
size="sm"
variant={active === item.key ? "default" : "outline"}
onClick={() => { setActive(item.key); setPreview(false); }}
className="text-xs"
>
{item.label}
{item.isOverride && (
<Badge variant="secondary" className="text-[9px] mr-1.5 px-1">
מותאם
</Badge>
)}
</Button>
))}
<div className="space-y-[18px]">
{/* Type buttons — gold active (mockup 13) */}
<div className="flex gap-2.5 flex-wrap">
{items.map((item) => {
const isActive = active === item.key;
return (
<button
key={item.key}
type="button"
onClick={() => {
setActive(item.key);
setPreview(false);
}}
className={
isActive
? "rounded-lg border border-gold bg-gold px-4 py-2 text-[0.84rem] font-semibold text-white"
: "rounded-lg border border-rule bg-surface px-4 py-2 text-[0.84rem] font-medium text-ink-soft hover:border-gold/50"
}
>
{item.label}
{item.isOverride && (
<Badge
variant="secondary"
className={`text-[9px] ms-1.5 px-1 ${isActive ? "bg-white/20 text-white" : ""}`}
>
מותאם
</Badge>
)}
</button>
);
})}
</div>
{/* Editor / Preview */}
{/* "חל על:" explainer band — gold-wash (mockup 13) */}
{current && CHECKLIST_APPLIES[current.key] && (
<div className="flex items-baseline gap-2 rounded-lg border border-rule bg-gold-wash px-4 py-2.5 text-[0.84rem] text-ink-soft">
<b className="text-gold-deep font-semibold whitespace-nowrap">חל על:</b>
<span>{CHECKLIST_APPLIES[current.key]}</span>
</div>
)}
{/* Editor — framed card with header chip + parchment editor + footer */}
{current && (
<Card className="border-rule">
<CardContent className="px-5 py-4 space-y-3">
<div className="flex items-center justify-between">
<div className="min-w-0">
<h3 className="text-sm font-semibold text-navy">{current.label}</h3>
{CHECKLIST_APPLIES[current.key] && (
<p className="text-[0.72rem] text-ink-muted mt-0.5">
חל על: {CHECKLIST_APPLIES[current.key]}
</p>
)}
</div>
<Button
size="sm"
variant="ghost"
onClick={() => setPreview(!preview)}
className="text-xs shrink-0"
>
{preview ? <EyeOff className="w-3.5 h-3.5 ml-1" /> : <Eye className="w-3.5 h-3.5 ml-1" />}
{preview ? "עריכה" : "תצוגה מקדימה"}
</Button>
</div>
{preview ? (
<div className="border border-rule rounded-md p-4 bg-sand-soft/30 max-h-[500px] overflow-y-auto">
<Markdown content={current.draft} />
</div>
) : (
<Textarea
value={current.draft}
onChange={(e) => updateDraft(e.target.value)}
className="min-h-[400px] font-mono text-sm leading-relaxed"
dir="rtl"
/>
)}
<div className="flex items-center gap-2">
<Button size="sm" disabled={!current.dirty || update.isPending} onClick={handleSave}>
{update.isPending ? <Loader2 className="w-3 h-3 animate-spin ml-1" /> : <Save className="w-3 h-3 ml-1" />}
שמור
</Button>
{current.isOverride && (
<Button size="sm" variant="outline" disabled={reset.isPending} onClick={handleReset}>
<RotateCcw className="w-3 h-3 ml-1" />
איפוס לברירת מחדל
</Button>
<Card className="border-rule shadow-sm overflow-hidden p-0 gap-0">
<div className="flex items-center gap-2.5 px-[18px] py-3.5 border-b border-rule-soft">
<h2 className="text-[0.95rem] font-semibold text-navy m-0">
צ׳קליסט תוכן {current.label}
</h2>
<span
className={`ms-auto rounded-full text-xs font-semibold px-2.5 py-0.5 ${
current.isOverride
? "bg-gold-wash text-gold-deep border border-rule"
: "bg-info-bg text-info"
}`}
>
{current.isOverride ? "מותאם" : "ידני"}
</span>
<Button
size="sm"
variant="ghost"
onClick={() => setPreview(!preview)}
className="text-xs shrink-0 h-7"
>
{preview ? (
<EyeOff className="w-3.5 h-3.5 ms-1" />
) : (
<Eye className="w-3.5 h-3.5 ms-1" />
)}
<Badge
variant={current.isOverride ? "default" : "secondary"}
className="text-[10px] mr-auto"
>
{current.isOverride ? "מותאם" : "ברירת מחדל"}
</Badge>
{preview ? "עריכה" : "תצוגה מקדימה"}
</Button>
</div>
{preview ? (
<div className="p-[18px] bg-parchment max-h-[500px] overflow-y-auto border-b border-rule-soft">
<Markdown content={current.draft} />
</div>
</CardContent>
) : (
<Textarea
value={current.draft}
onChange={(e) => updateDraft(e.target.value)}
className="min-h-[340px] rounded-none border-0 border-b border-rule-soft bg-parchment font-mono text-[0.84rem] leading-[1.95] text-ink-soft focus-visible:ring-0 resize-y"
dir="rtl"
/>
)}
<div className="flex items-center gap-2.5 px-[18px] py-3.5">
<Button
disabled={!current.dirty || update.isPending}
onClick={handleSave}
className="bg-gold text-white hover:bg-gold-deep"
>
{update.isPending ? (
<Loader2 className="w-3.5 h-3.5 animate-spin ms-1" />
) : (
<Save className="w-3.5 h-3.5 ms-1" />
)}
שמור
</Button>
{current.isOverride && (
<Button
variant="outline"
disabled={reset.isPending}
onClick={handleReset}
className="border-rule text-navy"
>
<RotateCcw className="w-3.5 h-3.5 ms-1" />
אפס לברירת-מחדל
</Button>
)}
<span className="ms-auto text-[0.78rem] text-ink-muted tabular-nums">
{itemCount} פריטים
</span>
</div>
</Card>
)}
</div>