import { useState, useEffect } from 'react' import { getReactionLogs } from '../api' import { formatRelativeTime } from '../utils' import { Spinner, EmptyState, Pagination } from './Common' function StatusBadge({ status }: { status: string }) { const colors: Record = { success: 'bg-green-500/20 text-green-300 border-green-500/30', failed: 'bg-red-500/20 text-red-300 border-red-500/30', skipped: 'bg-gray-500/20 text-gray-400 border-gray-500/30', } return ( {status} ) } function truncate(value: any, maxLen = 60): string { if (value === null || value === undefined) return '—' const str = typeof value === 'string' ? value : JSON.stringify(value) return str.length > maxLen ? str.slice(0, maxLen) + '...' : str } export default function ReactionLogs() { const [data, setData] = useState([]) const [error, setError] = useState('') const [loading, setLoading] = useState(true) const [total, setTotal] = useState(0) const [limit, setLimit] = useState(50) const [offset, setOffset] = useState(0) const [filterReactionId, setFilterReactionId] = useState('') const [expandedRows, setExpandedRows] = useState>(new Set()) const load = () => { setLoading(true) const rid = filterReactionId.trim() ? parseInt(filterReactionId, 10) : undefined getReactionLogs(limit, offset, rid) .then((res) => { setData(res.reaction_logs) setTotal(res.total) }) .catch((e) => setError(e.message)) .finally(() => setLoading(false)) } useEffect(() => { load() }, [limit, offset]) const toggleExpand = (id: number) => { setExpandedRows((prev) => { const next = new Set(prev) if (next.has(id)) next.delete(id) else next.add(id) return next }) } if (loading) return if (error) return
Error: {error}
return (

Reaction Logs

{/* Filter */}
setFilterReactionId(e.target.value)} placeholder="Reaction ID" className="px-3 py-2 bg-gray-800 border border-gray-700 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 w-40" />
{filterReactionId && ( )}
{data.length === 0 ? ( ) : (
{data.map((log, i) => ( ))}
ID Reaction Trigger Event Projection Old Value New Value Action Status Output Duration Created
{log.id} {log.reaction_id} {log.trigger_event_id} {truncate(log.projection_def, 30)} {truncate(log.old_value)} {truncate(log.new_value)} {log.action} {log.handler_output ? (
{expandedRows.has(log.id) && (
                              {typeof log.handler_output === 'string'
                                ? log.handler_output
                                : JSON.stringify(log.handler_output, null, 2)}
                            
)}
) : ( )}
{log.duration_ms != null ? `${log.duration_ms}ms` : '—'} {formatRelativeTime(log.created_at)}
)}
) }