import { Clock3, History, Sparkles } from "lucide-react"; import type { WorkspaceLogItem } from "../../api/logs"; import { API_BASE_URL } from "../../config/constants"; import { useTranslation } from "../../hooks/useTranslation"; import { Button } from "../ui/button"; const eventBadgeStyles: Record = { create: "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300", update: "bg-sky-100 text-sky-700 dark:bg-sky-900/30 dark:text-sky-300", delete: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300", restore: "bg-cyan-100 text-cyan-700 dark:bg-cyan-900/30 dark:text-cyan-300", archive: "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300", unarchive: "bg-lime-100 text-lime-700 dark:bg-lime-900/30 dark:text-lime-300", activate: "bg-teal-100 text-teal-700 dark:bg-teal-900/30 dark:text-teal-300", deactivate: "bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300", }; const sectionBadgeStyles: Record = { workspace: "bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300", workspace_members: "bg-violet-100 text-violet-700 dark:bg-violet-900/30 dark:text-violet-300", clients: "bg-indigo-100 text-indigo-700 dark:bg-indigo-900/30 dark:text-indigo-300", projects: "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300", project_members: "bg-cyan-100 text-cyan-700 dark:bg-cyan-900/30 dark:text-cyan-300", tags: "bg-pink-100 text-pink-700 dark:bg-pink-900/30 dark:text-pink-300", time_entries: "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300", rates: "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300", report_exports: "bg-fuchsia-100 text-fuchsia-700 dark:bg-fuchsia-900/30 dark:text-fuchsia-300", }; const resolveImageUrl = (value?: string | null) => { if (!value) return null; if (/^https?:\/\//i.test(value)) return value; return `${API_BASE_URL.replace(/\/+$/, "")}/${value.replace(/^\/+/, "")}`; }; export function LogsFeed({ items, total, hasMore, isLoading, isLoadingMore, selectedId, onOpen, onLoadMore, }: { items: WorkspaceLogItem[]; total: number; hasMore: boolean; isLoading: boolean; isLoadingMore: boolean; selectedId: number | null; onOpen: (id: number) => void; onLoadMore: () => void; }) { const { t, lang } = useTranslation(); const formatTimestamp = (value: string) => new Intl.DateTimeFormat(lang === "fa" ? "fa-IR-u-ca-persian" : "en-US", { year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", }).format(new Date(value)); const buildSummary = (item: WorkspaceLogItem) => { const actor = item.actor?.full_name || t.logs?.unknownActor || "Unknown actor"; const eventLabel = t.logs?.events?.[item.event] || item.event; const sectionLabel = t.logs?.sections?.[item.section] || item.section; const target = item.target?.name || "-"; if (typeof t.logs?.summary === "function") { return t.logs.summary(actor, eventLabel, sectionLabel, target); } return `${actor} ${eventLabel.toLowerCase()} ${target} in ${sectionLabel.toLowerCase()}`; }; const getInitials = (item: WorkspaceLogItem) => { const label = item.actor?.full_name || t.logs?.unknownActor || "?"; return label.trim().charAt(0).toUpperCase(); }; if (isLoading) { return (
{t.logs?.loading || "Loading logs..."}
); } if (!items.length) { return (

{t.logs?.empty || "No activity logs found"}

{t.logs?.emptyHint || "Adjust your filters or wait for new workspace activity."}

); } return (

{t.logs?.resultsCount?.(total) || `${total} results`}

{t.logs?.detailsHint || "Select an activity item to inspect the exact field changes."}

{items.length}/{total}
{items.map((item) => { const avatarUrl = resolveImageUrl(item.actor?.profile_picture); return ( ); })}
{hasMore ? (
) : null}
); }