import React, { useState, useCallback } from 'react'; import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'; import { Head, router } from '@inertiajs/react'; import { PageProps } from '@/types'; import { DataTable } from '@/Components/DataTable'; import { Portal } from '@/Components/Portal'; import _ from 'lodash'; interface Activity { id: number; log_name: string; description: string; subject_type: string; subject_id: number; causer_id: number; causer?: { first_name: string; last_name: string; email: string }; properties: any; created_at: string; } interface ActivityLogsPageProps extends PageProps { activities: { data: Activity[]; meta: any; links: any[]; }; filters: any; availableLogNames: string[]; availableEvents: string[]; } /* ─── Log Detail Modal (Modern & Clean) ───────────────────────────── */ /* ─── Log Detail Modal (Modern & Clean) ───────────────────────────── */ function LogModal({ activity, onClose }: { activity: Activity; onClose: () => void }) { const [copied, setCopied] = useState(false); const jsonString = JSON.stringify(activity.properties, null, 4); const handleCopy = () => { navigator.clipboard.writeText(jsonString); setCopied(true); setTimeout(() => setCopied(false), 2000); }; return (

Activity Details

{activity.description}

{/* Meta Info */}

{activity.causer ? `${activity.causer.first_name} ${activity.causer.last_name}` : 'System'}

{new Date(activity.created_at).toLocaleString()}

{activity.log_name}

{activity.subject_type.split('\\').pop()} #{activity.subject_id}

{/* Payload */}
JSON Format
                                    {jsonString}
                                
); } export default function ActivityLogsIndex({ activities, filters, availableLogNames, availableEvents }: ActivityLogsPageProps) { const [isLoading, setIsLoading] = useState(false); const [selectedLog, setSelectedLog] = useState(null); const [selectedIds, setSelectedIds] = useState<(number | string)[]>([]); const [localFilters, setLocalFilters] = useState({ search: filters.search || '', log_name: filters.log_name || '', event: filters.event || '', per_page: filters.per_page || 15, }); const debouncedFilter = useCallback(_.debounce((params) => { setIsLoading(true); router.get(route('activity-logs.index'), params, { preserveState: true, preserveScroll: true, replace: true, only: ['activities', 'filters'], onFinish: () => setIsLoading(false) }); }, 400), []); const updateFilter = (key: string, value: any) => { const newFilters = { ...localFilters, [key]: value }; setLocalFilters(newFilters); const params = { ...newFilters, page: 1 }; setSelectedIds([]); // Clear selection on filter change debouncedFilter(params); }; const handleBulkDelete = () => { const count = selectedIds.length; swal.confirm('Purge Logs?', `Are you sure you want to permanently delete ${count} activity logs?`, 'Purge') .then(result => { if (result.isConfirmed) { router.post(route('activity-logs.bulk-delete'), { ids: selectedIds }, { preserveScroll: true, onSuccess: () => { setSelectedIds([]); swal.success('Purged', `${count} logs deleted successfully.`); } }); } }); }; const columns = [ { header: 'Activity', accessorKey: 'description', cell: (a: Activity) => (
{a.description} {a.log_name}
) }, { header: 'Causer', accessorKey: 'causer', cell: (a: Activity) => (
{a.causer ? `${a.causer.first_name[0]}${a.causer.last_name[0]}` : 'SYS'}
{a.causer ? `${a.causer.first_name} ${a.causer.last_name}` : 'System'} {a.causer?.email || 'automated@system'}
) }, { header: 'Properties', accessorKey: 'properties', cell: (a: Activity) => (
{JSON.stringify(a.properties)}
) }, { header: 'Date & Time', accessorKey: 'created_at', cell: (a: Activity) => ( {new Date(a.created_at).toLocaleString('en-US', { day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit' })} ) }, { header: 'Action', accessorKey: 'actions', cell: (a: Activity) => (
) } ]; return (

Activity Logs

Audit trail of system events and user actions

updateFilter('search', e.target.value)} className="w-full h-11 pl-10 pr-4 rounded-2xl border border-gray-100 bg-white text-sm font-semibold text-gray-700 placeholder-gray-400 focus:outline-none focus:border-[#D4A017] focus:ring-4 focus:ring-[#D4A017]/5 transition-all shadow-sm" />
{selectedLog && setSelectedLog(null)} />} {/* Floating Bulk Actions Bar */}
0 ? 'translate-y-0 opacity-100' : 'translate-y-20 opacity-0 pointer-events-none'}`}>
{selectedIds.length} Logs selected
); }