feat(ui): /approvals — יישום נאמן של עיצוב-המוקאפ (תיקון)
יישום מלא של פריסת-הכרטיס מהמוקאפ המאושר 01-approvals (במקום ליטוש שטחי קודם): מספר-גדול (text-3xl navy) במקום badge קטן · נקודת-חומרה + כותרת + שורת-ותק · שורות-מדגם עם המקור מיושר לקצה והפרדה עדינה · CTA gold. כל הנתונים/לוגיקה נשמרו. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,13 +17,6 @@ import {
|
||||
* פסיקה חסרה, הערות שטרם יושמו, ותיקים שנכשלו ב-QA. המטרה:
|
||||
* שאף פריט הדורש את אישורך לא יישכח. הנתונים נשלפים חי מ-/api/chair/pending.
|
||||
*/
|
||||
const SEVERITY_BADGE: Record<ApprovalSeverity, string> = {
|
||||
high: "bg-gold text-navy border-transparent",
|
||||
medium: "bg-gold-wash text-gold-deep border-gold/40",
|
||||
low: "bg-rule-soft text-ink-muted border-rule",
|
||||
ok: "bg-emerald-50 text-emerald-800 border-emerald-300/60",
|
||||
};
|
||||
|
||||
// Severity expressed as a colored dot next to the title (matches the approved
|
||||
// IA-redesign mockup): high=danger, medium=warn, low=info, ok=success.
|
||||
const SEVERITY_DOT: Record<ApprovalSeverity, string> = {
|
||||
@@ -49,67 +42,84 @@ function formatDate(iso?: string | null): string {
|
||||
function ApprovalCard({ cat }: { cat: ApprovalCategory }) {
|
||||
const cleared = cat.count === 0;
|
||||
return (
|
||||
<Card className="bg-surface border-rule shadow-sm flex flex-col">
|
||||
<CardContent className="px-6 py-5 flex flex-col gap-3 grow">
|
||||
<div className="flex items-start gap-3">
|
||||
<Card className="bg-surface border-rule shadow-sm flex flex-col overflow-hidden">
|
||||
<CardContent className="p-0 flex flex-col grow">
|
||||
{/* top row — severity dot · title+age · big count number (mockup 01) */}
|
||||
<div className="flex items-start gap-3 px-5 pt-5 pb-2">
|
||||
<span
|
||||
className={`mt-2 h-2.5 w-2.5 shrink-0 rounded-full ${SEVERITY_DOT[cat.severity]}`}
|
||||
aria-hidden
|
||||
/>
|
||||
<h2 className="text-navy text-lg mb-0 leading-snug grow">{cat.label}</h2>
|
||||
<div className="grow min-w-0">
|
||||
<h2 className="text-navy text-base font-semibold mb-0 leading-snug">{cat.label}</h2>
|
||||
<div className="text-[0.78rem] text-ink-muted mt-0.5">
|
||||
{cleared ? (
|
||||
<span className="inline-block rounded-full bg-success-bg text-success text-[0.72rem] px-2.5 py-0.5 font-medium">
|
||||
תור נקי
|
||||
</span>
|
||||
) : cat.oldest_at ? (
|
||||
<>הוותיק ביותר — {formatDate(cat.oldest_at)}</>
|
||||
) : (
|
||||
cat.description
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
className={`inline-flex items-center justify-center min-w-[2.25rem] h-7 px-2 rounded-full border text-sm font-semibold tabular-nums ${SEVERITY_BADGE[cat.severity]}`}
|
||||
className="text-3xl font-bold text-navy leading-none tabular-nums shrink-0"
|
||||
aria-label={`${cat.count} פריטים ממתינים`}
|
||||
>
|
||||
{cat.count}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<p className="text-ink-muted text-[0.85rem] leading-relaxed mb-0">
|
||||
{cat.description}
|
||||
</p>
|
||||
|
||||
{cat.oldest_at && cat.count > 0 ? (
|
||||
<p className="text-[0.78rem] text-gold-deep mb-0">
|
||||
הישן ביותר ממתין מ־{formatDate(cat.oldest_at)}
|
||||
</p>
|
||||
{/* description kept (subtle) when the age line took the title slot */}
|
||||
{!cleared && cat.oldest_at ? (
|
||||
<p className="px-5 text-[0.8rem] text-ink-muted leading-relaxed mb-0">{cat.description}</p>
|
||||
) : null}
|
||||
|
||||
{cat.extra ? (
|
||||
<p className="text-[0.78rem] text-ink-muted mb-0">
|
||||
<p className="px-5 mt-1 text-[0.78rem] text-ink-muted mb-0">
|
||||
סך {cat.extra.total} שאילתות · {cat.extra.reviewed} אושרו על־ידך
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
{cleared ? (
|
||||
<p className="text-[0.85rem] text-emerald-700 mb-0">אין פריטים ממתינים ✓</p>
|
||||
) : cat.sample && cat.sample.length > 0 ? (
|
||||
<ul className="space-y-1.5 mt-1">
|
||||
{!cleared && cat.sample && cat.sample.length > 0 ? (
|
||||
<ul className="mt-3 px-5 border-t border-rule-soft">
|
||||
{cat.sample.map((s, i) => {
|
||||
const body = (
|
||||
<>
|
||||
<span className="line-clamp-2">{s.text || "—"}</span>
|
||||
const row = (
|
||||
<div className="flex items-start gap-2">
|
||||
<span className="line-clamp-2 text-ink-soft">{s.text || "—"}</span>
|
||||
{s.source ? (
|
||||
<span className="text-ink-muted text-[0.72rem]"> · {s.source}</span>
|
||||
<span className="text-ink-muted text-[0.72rem] ms-auto shrink-0 whitespace-nowrap">
|
||||
{s.source}
|
||||
</span>
|
||||
) : null}
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<li key={i} className="text-[0.82rem] text-ink leading-snug border-s-2 border-rule ps-2.5">
|
||||
<li
|
||||
key={i}
|
||||
className="text-[0.82rem] py-2.5 border-b border-rule-soft last:border-b-0"
|
||||
>
|
||||
{s.href ? (
|
||||
<Link href={s.href} className="hover:text-gold-deep hover:underline block">
|
||||
{body}
|
||||
<Link href={s.href} className="block hover:text-gold-deep">
|
||||
{row}
|
||||
</Link>
|
||||
) : (
|
||||
body
|
||||
row
|
||||
)}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
) : cleared ? (
|
||||
<p className="px-5 mt-2 text-[0.85rem] text-ink-muted mb-0">
|
||||
אין פריטים הממתינים להתייחסות. כל התיקים עברו בדיקת-איכות.
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
<div className="mt-auto pt-2">
|
||||
{/* foot — gold CTA when actionable, quiet outline when cleared */}
|
||||
<div className="mt-auto px-5 pt-4 pb-5">
|
||||
{cat.href ? (
|
||||
cleared ? (
|
||||
<Button asChild variant="outline" size="sm" className="border-rule text-ink-muted">
|
||||
|
||||
Reference in New Issue
Block a user