"use client"; import { useRef, useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import { Badge } from "@/components/ui/badge"; import { Markdown } from "@/components/ui/markdown"; import { useAgentActivity, useSendComment } from "@/lib/api/agents"; import type { PaperclipComment } from "@/lib/api/agents"; import { toast } from "sonner"; import { Bot, User, Send, Loader2, MessageSquare, Clock, } from "lucide-react"; /* ── Role → color mapping ────────────────────────────────────── */ const ROLE_COLORS: Record = { ceo: "bg-blue-100 text-blue-800 border-blue-200", researcher: "bg-purple-100 text-purple-800 border-purple-200", engineer: "bg-emerald-100 text-emerald-800 border-emerald-200", qa: "bg-amber-100 text-amber-800 border-amber-200", }; const ROLE_DOT: Record = { ceo: "bg-blue-500", researcher: "bg-purple-500", engineer: "bg-emerald-500", qa: "bg-amber-500", }; const ROLE_LABELS: Record = { ceo: "מנהל", researcher: "חוקר", engineer: "מהנדס", qa: "בודק איכות", general: "כללי", }; const ISSUE_STATUS_LABELS: Record = { backlog: "ממתין", todo: "לביצוע", in_progress: "בביצוע", in_review: "בבדיקה", done: "הושלם", cancelled: "בוטל", blocked: "חסום", }; function roleColor(role: string | null) { return ROLE_COLORS[role ?? ""] ?? "bg-gray-100 text-gray-700 border-gray-200"; } function roleDot(role: string | null) { return ROLE_DOT[role ?? ""] ?? "bg-gray-400"; } function roleLabel(role: string | null) { return ROLE_LABELS[role ?? ""] ?? role ?? ""; } function issueStatusLabel(status: string) { return ISSUE_STATUS_LABELS[status] ?? status; } /* ── Time formatting ─────────────────────────────────────────── */ function timeAgo(iso: string | null): string { if (!iso) return ""; const diff = Date.now() - new Date(iso).getTime(); const mins = Math.floor(diff / 60_000); if (mins < 1) return "עכשיו"; if (mins < 60) return `לפני ${mins} דק׳`; const hours = Math.floor(mins / 60); if (hours < 24) return `לפני ${hours} שע׳`; const days = Math.floor(hours / 24); return `לפני ${days} ימים`; } /* ── Issue identifier → find matching identifier ─────────────── */ function issueIdentifier( comment: PaperclipComment, issueMap: Map, ): string { return issueMap.get(comment.issue_id) ?? ""; } /* ── Comment card ────────────────────────────────────────────── */ function CommentCard({ comment, issueMap, }: { comment: PaperclipComment; issueMap: Map; }) { const isAgent = !!comment.author_agent_id; const label = isAgent ? comment.agent_name ?? "סוכן" : "חיים"; const identifier = issueIdentifier(comment, issueMap); return (
{/* Avatar */}
{isAgent ? (
) : (
)}
{/* Content */}
{/* Header */}
{label} {isAgent && comment.agent_role && ( {roleLabel(comment.agent_role)} )} {identifier && ( {identifier} )} {timeAgo(comment.created_at)}
{/* Body */}
); } /* ── Main Feed ───────────────────────────────────────────────── */ export function AgentActivityFeed({ caseNumber, }: { caseNumber: string; }) { const { data, isLoading, error } = useAgentActivity(caseNumber); const sendComment = useSendComment(caseNumber); const [body, setBody] = useState(""); const endRef = useRef(null); // Build issue_id → identifier map const issueMap = new Map(); if (data?.issues) { for (const iss of data.issues) { issueMap.set(iss.id, iss.identifier); } } // Auto-scroll on new comments const commentCount = data?.comments?.length ?? 0; useEffect(() => { endRef.current?.scrollIntoView({ behavior: "smooth" }); }, [commentCount]); const handleSend = () => { if (!body.trim()) return; sendComment.mutate( { body: body.trim() }, { onSuccess: (res) => { setBody(""); toast.success(`נשלח ל-${res.issue_identifier}`); }, onError: () => toast.error("שגיאה בשליחת ההודעה"), }, ); }; // ── Empty / loading states ── if (isLoading) { return (
טוען פעילות סוכנים...
); } if (error) { return (
שגיאה בטעינת פעילות סוכנים
); } if (!data?.issues?.length) { return (

התהליך טרם הופעל. לחץ "התחל תהליך" בלשונית סקירה.

); } const comments = data.comments ?? []; return (
{/* Issue summary bar */}
{data.issues.map((iss) => ( {iss.identifier} — {issueStatusLabel(iss.status)} ))}
{/* Comments stream */}
{comments.length === 0 ? (
הסוכנים התחילו לעבוד, ממתין לדיווח ראשון...
) : ( comments.map((c) => ( )) )}
{/* Comment input */}