import { useCallback, useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; import { activityApi } from "../api/activity"; import { useCompany } from "../context/CompanyContext"; import { useBreadcrumbs } from "../context/BreadcrumbContext"; import { useApi } from "../hooks/useApi"; import { EmptyState } from "../components/EmptyState"; import { timeAgo } from "../lib/timeAgo"; import { Badge } from "@/components/ui/badge"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { History, Bot, User, Settings } from "lucide-react"; function formatAction(action: string, entityType: string, entityId: string): string { const shortId = entityId.slice(0, 8); const actionMap: Record = { "company.created": "Company created", "agent.created": `Agent created`, "agent.updated": `Agent updated`, "agent.paused": `Agent paused`, "agent.resumed": `Agent resumed`, "agent.terminated": `Agent terminated`, "agent.key_created": `API key created for agent`, "issue.created": `Issue created`, "issue.updated": `Issue updated`, "issue.checked_out": `Issue checked out`, "issue.released": `Issue released`, "issue.commented": `Comment added to issue`, "heartbeat.invoked": `Heartbeat invoked`, "heartbeat.completed": `Heartbeat completed`, "heartbeat.failed": `Heartbeat failed`, "approval.created": `Approval requested`, "approval.approved": `Approval granted`, "approval.rejected": `Approval rejected`, "project.created": `Project created`, "project.updated": `Project updated`, "goal.created": `Goal created`, "goal.updated": `Goal updated`, "cost.recorded": `Cost recorded`, }; return actionMap[action] ?? `${action.replace(/[._]/g, " ")}`; } function actorIcon(entityType: string) { if (entityType === "agent") return ; if (entityType === "company" || entityType === "approval") return ; return ; } function entityLink(entityType: string, entityId: string): string | null { switch (entityType) { case "issue": return `/issues/${entityId}`; case "agent": return `/agents/${entityId}`; case "project": return `/projects/${entityId}`; case "goal": return `/goals/${entityId}`; case "approval": return `/approvals/${entityId}`; default: return null; } } export function Activity() { const { selectedCompanyId } = useCompany(); const { setBreadcrumbs } = useBreadcrumbs(); const navigate = useNavigate(); const [filter, setFilter] = useState("all"); useEffect(() => { setBreadcrumbs([{ label: "Activity" }]); }, [setBreadcrumbs]); const fetcher = useCallback(() => { if (!selectedCompanyId) return Promise.resolve([]); return activityApi.list(selectedCompanyId); }, [selectedCompanyId]); const { data, loading, error } = useApi(fetcher); if (!selectedCompanyId) { return ; } const filtered = data && filter !== "all" ? data.filter((e) => e.entityType === filter) : data; const entityTypes = data ? [...new Set(data.map((e) => e.entityType))].sort() : []; return (

Activity

{loading &&

Loading...

} {error &&

{error.message}

} {filtered && filtered.length === 0 && ( )} {filtered && filtered.length > 0 && (
{filtered.map((event) => { const link = entityLink(event.entityType, event.entityId); return (
navigate(link) : undefined} >
{actorIcon(event.entityType)} {formatAction(event.action, event.entityType, event.entityId)} {event.entityType} {event.entityId.slice(0, 8)}
{timeAgo(event.createdAt)}
); })}
)}
); }