import { useState, useEffect, useCallback } from 'react' import { auditService, AuditLog } from '../services/audit' import { logger } from '../utils/logger' interface ResourceHistoryProps { resourceType: string resourceId: string title?: string } export function ResourceHistory({ resourceType, resourceId, title = 'Change History' }: ResourceHistoryProps) { const [logs, setLogs] = useState([]) const [loading, setLoading] = useState(true) const [expanded, setExpanded] = useState(false) const loadHistory = useCallback(async () => { setLoading(true) try { const response = await auditService.getResourceHistory(resourceType, resourceId, 10) setLogs(response.logs) } catch (error) { logger.error('Failed to load resource history:', error) } finally { setLoading(false) } }, [resourceType, resourceId]) useEffect(() => { loadHistory() }, [loadHistory]) const formatChanges = (changes: AuditLog['changes']): string => { if (!changes || changes.length === 0) return '' return changes.map(c => `${c.field}: ${c.old_value ?? 'null'} → ${c.new_value ?? 'null'}`).join(', ') } if (loading) { return
Loading history...
} if (logs.length === 0) { return
No change history available
} const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault() setExpanded(!expanded) } } return (
setExpanded(!expanded)} role="button" tabIndex={0} onKeyDown={handleKeyDown} aria-expanded={expanded} aria-label={`${title}, ${logs.length} items`} > {title}
{expanded && (
{logs.map((log) => (
{log.event_type} {new Date(log.created_at).toLocaleString()}
{log.user_name || 'System'} {log.changes && log.changes.length > 0 && ( {formatChanges(log.changes)} )}
))}
)}
) } const styles: Record = { container: { backgroundColor: '#f8f9fa', borderRadius: '8px', border: '1px solid #e9ecef', marginTop: '16px', }, header: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '12px 16px', cursor: 'pointer', userSelect: 'none', }, title: { fontWeight: 600, fontSize: '14px', color: '#495057', }, toggleIcon: { fontSize: '12px', color: '#6c757d', }, content: { borderTop: '1px solid #e9ecef', padding: '8px', maxHeight: '300px', overflowY: 'auto', }, logItem: { padding: '8px 12px', borderBottom: '1px solid #e9ecef', }, logHeader: { display: 'flex', justifyContent: 'space-between', marginBottom: '4px', }, eventType: { fontSize: '12px', fontWeight: 600, color: '#007bff', }, time: { fontSize: '11px', color: '#6c757d', }, logBody: { display: 'flex', flexDirection: 'column', gap: '2px', }, userName: { fontSize: '12px', color: '#495057', }, changes: { fontSize: '11px', color: '#6c757d', fontStyle: 'italic', }, loading: { padding: '16px', textAlign: 'center', color: '#6c757d', }, empty: { padding: '16px', textAlign: 'center', color: '#6c757d', fontSize: '14px', }, } export default ResourceHistory