/** * @ai-summary Mobile screen for viewing centralized audit logs * @ai-context Touch-friendly card layout with collapsible filters */ import React, { useState, useCallback } from 'react'; import dayjs from 'dayjs'; import { GlassCard } from '../../../shared-minimal/components/mobile/GlassCard'; import { useUnifiedAuditLogs, useExportAuditLogs } from '../hooks/useAuditLogs'; import { AuditLogCategory, AuditLogSeverity, AuditLogFilters, UnifiedAuditLog, } from '../types/admin.types'; // Helper to format date const formatDate = (dateString: string): string => { return dayjs(dateString).format('MMM DD HH:mm'); }; // Severity colors for badges const severityColors: Record = { info: 'bg-blue-100 text-blue-800', warning: 'bg-yellow-100 text-yellow-800', error: 'bg-red-100 text-red-800', }; // Category colors for badges const categoryColors: Record = { auth: 'bg-purple-100 text-purple-800', vehicle: 'bg-green-100 text-green-800', user: 'bg-indigo-100 text-indigo-800', system: 'bg-gray-100 text-gray-800', admin: 'bg-orange-100 text-orange-800', }; const categoryLabels: Record = { auth: 'Auth', vehicle: 'Vehicle', user: 'User', system: 'System', admin: 'Admin', }; const AdminLogsMobileScreen: React.FC = () => { // Filter state const [showFilters, setShowFilters] = useState(false); const [search, setSearch] = useState(''); const [category, setCategory] = useState(''); const [severity, setSeverity] = useState(''); const [page, setPage] = useState(0); const pageSize = 20; // Build filters object const filters: AuditLogFilters = { ...(search && { search }), ...(category && { category }), ...(severity && { severity }), limit: pageSize, offset: page * pageSize, }; // Query const { data, isLoading, error, refetch } = useUnifiedAuditLogs(filters); const exportMutation = useExportAuditLogs(); // Handlers const handleSearchChange = useCallback((e: React.ChangeEvent) => { setSearch(e.target.value); setPage(0); }, []); const handleCategoryChange = useCallback((e: React.ChangeEvent) => { setCategory(e.target.value as AuditLogCategory | ''); setPage(0); }, []); const handleSeverityChange = useCallback((e: React.ChangeEvent) => { setSeverity(e.target.value as AuditLogSeverity | ''); setPage(0); }, []); const handleClearFilters = useCallback(() => { setSearch(''); setCategory(''); setSeverity(''); setPage(0); }, []); const handleExport = useCallback(() => { const exportFilters: AuditLogFilters = { ...(search && { search }), ...(category && { category }), ...(severity && { severity }), }; exportMutation.mutate(exportFilters); }, [search, category, severity, exportMutation]); const handleNextPage = useCallback(() => { if (data && (page + 1) * pageSize < data.total) { setPage(p => p + 1); } }, [data, page, pageSize]); const handlePrevPage = useCallback(() => { if (page > 0) { setPage(p => p - 1); } }, [page]); const hasActiveFilters = search || category || severity; const totalPages = data ? Math.ceil(data.total / pageSize) : 0; return (
{/* Header */}

Admin Logs

View audit logs across all system activities

{/* Collapsible Filters */} {showFilters && (
Filters {hasActiveFilters && ( )}
{/* Search */} {/* Category & Severity Row */}
{/* Export Button */}
)} {/* Error State */} {error && (

Failed to load audit logs

)} {/* Loading State */} {isLoading && (
Loading logs...
)} {/* Empty State */} {!isLoading && data?.logs.length === 0 && (

No audit logs found

)} {/* Log Cards */} {!isLoading && data?.logs.map((log: UnifiedAuditLog) => (
{/* Header Row */}
{categoryLabels[log.category]} {log.severity}
{formatDate(log.createdAt)}
{/* Action */}

{log.action}

{/* Metadata */}
{log.userId && ( User: {log.userId.substring(0, 16)}... )} {log.resourceType && log.resourceId && ( {log.resourceType}: {log.resourceId.substring(0, 10)}... )}
))} {/* Pagination */} {!isLoading && data && data.total > pageSize && (
Page {page + 1} of {totalPages}
)} {/* Total Count */} {!isLoading && data && (
{data.total} total log{data.total !== 1 ? 's' : ''}
)}
); }; export default AdminLogsMobileScreen;