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:
@@ -45,10 +45,10 @@ export default function CaseDetailPage({
|
||||
? EXPECTED_OUTCOME_LABELS[data.expected_outcome] ?? data.expected_outcome
|
||||
: null;
|
||||
|
||||
return (
|
||||
<AppShell>
|
||||
<section className="space-y-6">
|
||||
{error ? (
|
||||
if (error) {
|
||||
return (
|
||||
<AppShell>
|
||||
<section className="space-y-6">
|
||||
<Card className="bg-danger-bg border-danger/40">
|
||||
<CardContent className="px-6 py-6 text-center space-y-3">
|
||||
<p className="text-danger font-semibold">שגיאה בטעינת התיק</p>
|
||||
@@ -58,130 +58,168 @@ export default function CaseDetailPage({
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</section>
|
||||
</AppShell>
|
||||
);
|
||||
}
|
||||
|
||||
const tabsList = (
|
||||
<TabsList
|
||||
variant="line"
|
||||
className="gap-6 h-auto p-0 rounded-none -mb-px"
|
||||
>
|
||||
{[
|
||||
["overview", "סקירה"],
|
||||
["arguments", "טיעונים"],
|
||||
["decision", "ההחלטה"],
|
||||
["drafts", "טיוטות והערות"],
|
||||
["agents", "סוכנים"],
|
||||
].map(([value, label]) => (
|
||||
<TabsTrigger
|
||||
key={value}
|
||||
value={value}
|
||||
className="flex-none rounded-none px-0 pb-3.5 pt-0 text-[0.92rem] font-medium text-ink-muted data-active:text-navy data-active:font-semibold data-active:after:bg-gold data-active:after:bottom-0"
|
||||
>
|
||||
{label}
|
||||
</TabsTrigger>
|
||||
))}
|
||||
</TabsList>
|
||||
);
|
||||
|
||||
const bandActions = (
|
||||
<>
|
||||
{data && <CaseEditDialog data={data} />}
|
||||
<UploadSheet caseNumber={caseNumber} />
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<AppShell>
|
||||
<Tabs defaultValue="overview" dir="rtl">
|
||||
{/* parchment band — header (title/chips/parties/actions) + tab strip */}
|
||||
{isPending ? (
|
||||
<div className="-mx-10 -mt-10 mb-2 bg-parchment border-b border-rule px-10 pt-6 pb-4 space-y-3">
|
||||
<Skeleton className="h-4 w-40" />
|
||||
<Skeleton className="h-8 w-64" />
|
||||
<Skeleton className="h-6 w-96" />
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{isPending ? (
|
||||
<Card className="bg-surface border-rule shadow-sm">
|
||||
<CardContent className="px-6 py-5 space-y-3">
|
||||
<Skeleton className="h-4 w-40" />
|
||||
<Skeleton className="h-8 w-64" />
|
||||
<Skeleton className="h-6 w-96" />
|
||||
<CaseHeader data={data} actions={bandActions} tabs={tabsList} />
|
||||
)}
|
||||
|
||||
{/* two-column wrap — main tab content (1fr) + rail (340px) */}
|
||||
<div className="grid gap-6 lg:grid-cols-[1fr_340px] items-start mt-6">
|
||||
<div className="min-w-0">
|
||||
<TabsContent value="overview" className="mt-0 space-y-5">
|
||||
<Card className="bg-surface border-rule shadow-sm overflow-hidden p-0">
|
||||
<div className="px-5 py-3.5 border-b border-rule-soft bg-parchment text-[0.92rem] font-semibold text-navy">
|
||||
סקירת התיק
|
||||
</div>
|
||||
<CardContent className="px-5 py-4 space-y-4">
|
||||
<div>
|
||||
<h3 className="text-navy text-[0.95rem] font-semibold mb-1.5">תוצאה צפויה</h3>
|
||||
<p className="text-ink-soft text-sm leading-relaxed">
|
||||
{expectedOutcomeLabel ?? "לא נקבעה תוצאה צפויה."}
|
||||
</p>
|
||||
</div>
|
||||
<div className="pt-2 border-t border-rule-soft">
|
||||
<dl className="grid grid-cols-2 gap-y-2 gap-x-6 text-sm">
|
||||
<dt className="text-ink-muted">בעיבוד</dt>
|
||||
<dd className="text-ink tabular-nums">
|
||||
{data?.processing_count ?? 0}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
{canStartWorkflow && (
|
||||
<div className="pt-2 border-t border-rule-soft">
|
||||
<Button
|
||||
className="bg-gold-deep hover:bg-gold-deep/90 text-parchment"
|
||||
disabled={startWorkflow.isPending}
|
||||
onClick={() =>
|
||||
startWorkflow.mutate(undefined, {
|
||||
onSuccess: (res) =>
|
||||
toast.success(
|
||||
`תהליך הופעל — ${res.issue_identifier}`,
|
||||
),
|
||||
onError: (err) =>
|
||||
toast.error(`שגיאה: ${err.message}`),
|
||||
})
|
||||
}
|
||||
>
|
||||
{startWorkflow.isPending ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin me-1.5" />
|
||||
) : (
|
||||
<Play className="w-4 h-4 me-1.5" />
|
||||
)}
|
||||
התחל תהליך
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : (
|
||||
<CaseHeader data={data} />
|
||||
)}
|
||||
|
||||
<div className="grid gap-6 lg:grid-cols-[1fr_280px]">
|
||||
<DocumentsPanel data={data} />
|
||||
|
||||
{/* gold CTA — open the decision editor (mockup .cta) */}
|
||||
<Button
|
||||
asChild
|
||||
className="w-full bg-gold text-white hover:bg-gold-deep border-transparent py-6 text-base font-semibold"
|
||||
>
|
||||
<Link href={`/cases/${caseNumber}/compose`}>
|
||||
פתח עורך החלטה →
|
||||
</Link>
|
||||
</Button>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="arguments" className="mt-0">
|
||||
<Card className="bg-surface border-rule shadow-sm">
|
||||
<CardContent className="px-6 py-5">
|
||||
<Tabs defaultValue="overview" dir="rtl">
|
||||
<div className="flex items-center justify-between gap-3 mb-1 flex-wrap">
|
||||
<TabsList className="bg-rule-soft/60">
|
||||
<TabsTrigger value="overview">סקירה</TabsTrigger>
|
||||
<TabsTrigger value="arguments">
|
||||
טיעונים
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="decision">
|
||||
ההחלטה
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="drafts">
|
||||
טיוטות והערות
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="agents">
|
||||
סוכנים
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<Button asChild className="bg-navy hover:bg-navy-soft text-parchment">
|
||||
<Link href={`/cases/${caseNumber}/compose`}>
|
||||
פתח בעורך ההחלטה
|
||||
</Link>
|
||||
</Button>
|
||||
{data && <CaseEditDialog data={data} />}
|
||||
<UploadSheet caseNumber={caseNumber} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<TabsContent value="overview" className="mt-5 space-y-4">
|
||||
<div>
|
||||
<h3 className="text-navy text-base mb-2">תוצאה צפויה</h3>
|
||||
<p className="text-ink-soft text-sm leading-relaxed">
|
||||
{expectedOutcomeLabel ?? "לא נקבעה תוצאה צפויה."}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-navy text-base mb-2">סיכום מהיר</h3>
|
||||
<dl className="grid grid-cols-2 gap-y-2 gap-x-6 text-sm">
|
||||
<dt className="text-ink-muted">בעיבוד</dt>
|
||||
<dd className="text-ink tabular-nums">
|
||||
{data?.processing_count ?? 0}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
{canStartWorkflow && (
|
||||
<div className="pt-2 border-t border-rule">
|
||||
<Button
|
||||
className="bg-gold-deep hover:bg-gold-deep/90 text-parchment"
|
||||
disabled={startWorkflow.isPending}
|
||||
onClick={() =>
|
||||
startWorkflow.mutate(undefined, {
|
||||
onSuccess: (res) =>
|
||||
toast.success(
|
||||
`תהליך הופעל — ${res.issue_identifier}`,
|
||||
),
|
||||
onError: (err) =>
|
||||
toast.error(`שגיאה: ${err.message}`),
|
||||
})
|
||||
}
|
||||
>
|
||||
{startWorkflow.isPending ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin me-1.5" />
|
||||
) : (
|
||||
<Play className="w-4 h-4 me-1.5" />
|
||||
)}
|
||||
התחל תהליך
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<DocumentsPanel data={data} />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="arguments" className="mt-5">
|
||||
<LegalArgumentsPanel caseNumber={caseNumber} />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="decision" className="mt-5">
|
||||
<DecisionBlocksPanel caseNumber={caseNumber} />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="drafts" className="mt-5">
|
||||
<DraftsPanel
|
||||
caseNumber={caseNumber}
|
||||
status={data?.status}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="agents" className="mt-5">
|
||||
<AgentActivityFeed caseNumber={caseNumber} />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
<LegalArgumentsPanel caseNumber={caseNumber} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
|
||||
<Card className="bg-surface border-rule shadow-sm h-fit">
|
||||
<CardContent className="px-6 py-5 space-y-5">
|
||||
<AgentStatusWidget caseNumber={caseNumber} />
|
||||
<h2 className="text-navy text-base mb-4">שלב בתהליך</h2>
|
||||
<WorkflowTimeline status={data?.status} />
|
||||
<StatusChanger caseNumber={caseNumber} currentStatus={data?.status} />
|
||||
<StatusGuide />
|
||||
<TabsContent value="decision" className="mt-0">
|
||||
<Card className="bg-surface border-rule shadow-sm">
|
||||
<CardContent className="px-6 py-5">
|
||||
<DecisionBlocksPanel caseNumber={caseNumber} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</section>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="drafts" className="mt-0">
|
||||
<Card className="bg-surface border-rule shadow-sm">
|
||||
<CardContent className="px-6 py-5">
|
||||
<DraftsPanel caseNumber={caseNumber} status={data?.status} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="agents" className="mt-0">
|
||||
<Card className="bg-surface border-rule shadow-sm">
|
||||
<CardContent className="px-6 py-5">
|
||||
<AgentActivityFeed caseNumber={caseNumber} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
</div>
|
||||
|
||||
{/* rail — status timeline + status controls (mockup .rail) */}
|
||||
<div className="space-y-5">
|
||||
<Card className="bg-surface border-rule shadow-sm overflow-hidden p-0 h-fit">
|
||||
<div className="px-5 py-3.5 border-b border-rule-soft bg-parchment text-[0.92rem] font-semibold text-navy">
|
||||
סטטוס התיק
|
||||
</div>
|
||||
<CardContent className="px-5 py-4 space-y-4">
|
||||
<AgentStatusWidget caseNumber={caseNumber} />
|
||||
<WorkflowTimeline status={data?.status} />
|
||||
<StatusChanger caseNumber={caseNumber} currentStatus={data?.status} />
|
||||
<StatusGuide />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</Tabs>
|
||||
</AppShell>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user