'use client'; import { useEffect, useRef, useState } from 'react'; import { AdminShell } from '@/components/AdminShell'; import { getEvents, StoredEvent } from '@/lib/api'; const SUBJECTS = ['', 'signals.tip', 'signals.task', 'signals.tip.served', 'signals.tip.feedback', 'signals.task.synced']; export default function EventsPage() { const [events, setEvents] = useState([]); const [subject, setSubject] = useState(''); const [userId, setUserId] = useState(''); const [live, setLive] = useState(true); const [error, setError] = useState(''); const sinceRef = useRef(0); const timerRef = useRef | null>(null); const fetchEvents = async (reset = false) => { try { const since = reset ? 0 : sinceRef.current; const res = await getEvents({ subject: subject || undefined, userId: userId || undefined, limit: 100, since }); sinceRef.current = res.nextSince; setEvents((prev) => { const next = reset ? res.events : [...prev, ...res.events]; return next.slice(-500); // keep last 500 }); setError(''); } catch (e: any) { setError(e.message); } }; useEffect(() => { sinceRef.current = 0; fetchEvents(true); }, [subject, userId]); useEffect(() => { if (live) { timerRef.current = setInterval(() => fetchEvents(false), 2000); } else if (timerRef.current) { clearInterval(timerRef.current); } return () => { if (timerRef.current) clearInterval(timerRef.current); }; }, [live, subject, userId]); return (

Event stream

setUserId(e.target.value)} placeholder="Filter by user ID" className="bg-gray-900 border border-gray-700 rounded px-2 py-1 text-sm text-gray-300 w-64" />
{error &&

{error}

}
{events.length === 0 && (

No events yet. Waiting…

)} {[...events].reverse().map((e) => (
{e.id} {e.ts.slice(11, 19)} {e.subject} {JSON.stringify(e.payload)}
))}
); }