Files
legal-ai/web-ui/src/components/cases/agent-activity-preview.tsx
Chaim 32db9621b6
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 4s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
feat(ui): עיצוב מחדש של טאב הסקירה בדף תיק
- הסרת כרטיס "סקירת התיק" הדל (3 אלמנטים בלבד)
- כפתור "התחל תהליך" עלה לפס-הפעולות בראש הדף (ליד "העלאת מסמכים")
- כרטיס חדש AgentActivityPreview: 4 הissues האחרונים + קישור לטאב מלא
- "תוצאה צפויה" ירדה לשורת מטא-דאטה בראיל הסטטוס (מוצגת רק אם נקבעה)
- תיקון באג: expected_outcome לא נשמר — guard if expected_outcome: הוחלף ב-is not None

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 11:06:10 +00:00

111 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import Link from "next/link";
import { Loader2, CheckCircle2, Clock } from "lucide-react";
import { useAgentActivity } from "@/lib/api/agents";
import type { PaperclipIssue } from "@/lib/api/agents";
const STATUS_DOT: Record<string, string> = {
in_progress: "bg-gold",
todo: "bg-rule",
backlog: "bg-rule",
done: "bg-success",
cancelled: "bg-ink-muted/40",
};
const STATUS_LABEL: Record<string, string> = {
in_progress: "בביצוע",
todo: "לביצוע",
backlog: "ממתין",
done: "הושלם",
cancelled: "בוטל",
};
function timeAgo(iso: string | null): string {
if (!iso) return "—";
const diffMs = Date.now() - new Date(iso).getTime();
const m = Math.floor(diffMs / 60_000);
if (m < 60) return `לפני ${m}ד'`;
const h = Math.floor(m / 60);
if (h < 24) return `לפני ${h}ש'`;
return `לפני ${Math.floor(h / 24)} ימים`;
}
function IssueRow({ issue }: { issue: PaperclipIssue }) {
const dot = STATUS_DOT[issue.status] ?? "bg-rule";
const lbl = STATUS_LABEL[issue.status] ?? issue.status;
const isDone = issue.status === "done";
return (
<div className="flex items-start gap-3 py-3 border-b border-rule-soft last:border-0">
<span
className={`mt-1.5 w-2 h-2 rounded-full flex-none ${dot} ${issue.status === "in_progress" ? "animate-pulse" : ""}`}
/>
<div className="flex-1 min-w-0">
<p className={`text-[0.88rem] font-medium leading-snug ${isDone ? "text-ink-muted line-through" : "text-navy"}`}>
{issue.title}
</p>
<p className="text-[0.75rem] text-ink-muted mt-0.5">
{issue.assignee_name ?? lbl}
</p>
</div>
<div className="flex-none flex flex-col items-end gap-1">
{isDone ? (
<CheckCircle2 className="w-3.5 h-3.5 text-success mt-0.5" />
) : issue.status === "in_progress" ? (
<Loader2 className="w-3.5 h-3.5 text-gold animate-spin mt-0.5" />
) : (
<Clock className="w-3.5 h-3.5 text-ink-muted mt-0.5" />
)}
<span className="text-[0.72rem] text-ink-muted tabular-nums">
{timeAgo(issue.completed_at ?? issue.started_at ?? issue.created_at)}
</span>
</div>
</div>
);
}
export function AgentActivityPreview({
caseNumber,
}: {
caseNumber: string;
}) {
const { data, isLoading } = useAgentActivity(caseNumber);
const issues = [...(data?.issues ?? [])]
.sort((a, b) => {
const ta = a.started_at ?? a.created_at ?? "";
const tb = b.started_at ?? b.created_at ?? "";
return tb.localeCompare(ta);
})
.slice(0, 4);
return (
<div className="rounded-lg border border-rule bg-surface shadow-sm overflow-hidden">
<div className="px-5 py-3.5 border-b border-rule-soft bg-parchment flex items-center justify-between">
<span className="text-[0.92rem] font-semibold text-navy">פעילות סוכנים</span>
<Link
href={`/cases/${caseNumber}#agents`}
className="text-[0.78rem] font-semibold text-gold-deep hover:underline"
>
כל הפעילות
</Link>
</div>
<div className="px-5">
{isLoading ? (
<div className="flex items-center justify-center py-8 text-ink-muted gap-2">
<Loader2 className="w-4 h-4 animate-spin" />
<span className="text-sm">טוען...</span>
</div>
) : issues.length === 0 ? (
<p className="py-8 text-center text-sm text-ink-muted">
אין פעילות סוכנים עדיין
</p>
) : (
issues.map((issue) => <IssueRow key={issue.id} issue={issue} />)
)}
</div>
</div>
);
}