"use client"; import { useState, useEffect, useCallback, useRef } from "react"; import { useTranslations } from "next-intl"; import type { AuditLogEntry } from "@/lib/compliance/index"; import ActivityFeed from "./components/ActivityFeed"; import EventTypeFilter, { type EventCategory, matchesCategory, } from "./components/EventTypeFilter"; const FEED_LIMIT = 200; export default function ActivityFeedClient() { const t = useTranslations("activity"); const [allEntries, setAllEntries] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [category, setCategory] = useState("all"); const referenceNowMs = useRef(Date.now()); const fetchEntries = useCallback(async () => { setLoading(true); setError(null); try { const params = new URLSearchParams({ level: "high", limit: String(FEED_LIMIT), }); const res = await fetch(`/api/compliance/audit-log?${params.toString()}`); if (!res.ok) { throw new Error(t("description")); } const data = (await res.json()) as AuditLogEntry[]; // Reset reference time on fresh load so relative timestamps are stable referenceNowMs.current = Date.now(); setAllEntries(Array.isArray(data) ? data : []); } catch (err: unknown) { const msg = err instanceof Error ? err.message : "Failed to fetch activity"; setError(msg); } finally { setLoading(false); } }, [t]); useEffect(() => { fetchEntries(); }, [fetchEntries]); const filtered = category === "all" ? allEntries : allEntries.filter((e) => { const action = typeof e.action === "string" ? e.action : ""; return matchesCategory(action, category); }); return (
{/* Header */}

{t("title")}

{t("description")}

{/* Filter */} {/* Error */} {error && (
{error}
)} {/* Feed */}
{loading ? (
Loading activity…
) : ( )}
); }