import { useEffect, useMemo, useState } from 'react'; import { Download, Search, Trash2, } from 'lucide-react'; import { Button } from '@/components/ui/Button'; import { Card } from '@/components/ui/Card'; import { Badge } from '@/components/ui/Badge'; import { Select } from '@/components/ui/Select'; import { clearActivityLogs, exportActivityLogs, getActivityLogs, } from '@/services/activityLogService'; import type { ActivityLogEntry, ActivityLogLevel, ActivityLogSource, } from '@/types/activity'; const levels: Array<'all' | ActivityLogLevel> = [ 'all', 'info', 'success', 'warning', 'error', ]; const sources: Array<'all' | ActivityLogSource> = [ 'all', 'desktop', 'router', 'backend', 'vps', ]; const levelLabels: Record<'all' | ActivityLogLevel, string> = { all: 'Todos', info: 'Info', success: 'Sucesso', warning: 'Aviso', error: 'Erro', }; const sourceLabels: Record<'all' | ActivityLogSource, string> = { all: 'Todas', desktop: 'Desktop', router: 'Router', backend: 'Backend', vps: 'VPS', }; function levelTone(level: ActivityLogLevel) { if (level === 'success') return 'green'; if (level === 'warning') return 'purple'; if (level === 'error') return 'red'; return 'blue'; } export function ActivityLogs() { const [logs, setLogs] = useState< ActivityLogEntry[] >([]); const [levelFilter, setLevelFilter] = useState<'all' | ActivityLogLevel>('all'); const [sourceFilter, setSourceFilter] = useState<'all' | ActivityLogSource>('all'); const [query, setQuery] = useState(''); function refreshLogs() { setLogs(getActivityLogs()); } useEffect(() => { refreshLogs(); window.addEventListener( 'activity-log-added', refreshLogs, ); return () => { window.removeEventListener( 'activity-log-added', refreshLogs, ); }; }, []); const filteredLogs = useMemo(() => { const normalizedQuery = query.trim().toLowerCase(); return logs.filter((log) => { const matchesLevel = levelFilter === 'all' || log.level === levelFilter; const matchesSource = sourceFilter === 'all' || log.source === sourceFilter; const matchesQuery = !normalizedQuery || [ log.action, log.message, log.routerIp, log.vpnIp, log.source, log.level, ] .filter(Boolean) .join(' ') .toLowerCase() .includes(normalizedQuery); return ( matchesLevel && matchesSource && matchesQuery ); }); }, [logs, levelFilter, sourceFilter, query]); return (

Registos de Atividade

Histórico local de auditoria de provisionamento para técnicos.

setQuery(event.target.value) } placeholder="Pesquisar ação, IP VPN, IP router, mensagem..." className="w-full bg-transparent py-3 text-sm text-white outline-none placeholder:text-slate-600" />
({ value: source, label: sourceLabels[source], }))} />

Eventos de Auditoria

{filteredLogs.length} apresentados /{' '} {logs.length} total
{filteredLogs.map((log) => ( ))} {filteredLogs.length === 0 && ( )}
Hora Nível Origem Ação Mensagem IP VPN
{new Date( log.timestamp, ).toLocaleString()} {levelLabels[log.level]} {sourceLabels[log.source]} {log.action} {log.message} {log.vpnIp ?? '—'}
Nenhum registo de atividade encontrado.
); }