Day 2 โ€“ Building a Dashboard to View Audit Trails in Laravel#LaravelGPTAudit #LaravelAdmin #AuditTrailDashboard #SpatieActivityLog


Now that we’re logging activity, let’s create a user-friendly dashboard to view and filter logs using Laravel Blade, Bootstrap, and optional JS enhancements.


๐Ÿ›  Step 1: Create a route and controller

In routes/web.php:

Route::middleware(['auth', 'can:view-audit-logs'])->group(function () {
    Route::get('/audit-logs', [\App\Http\Controllers\AuditLogController::class, 'index'])->name('audit.logs');
});

Generate the controller:

php artisan make:controller AuditLogController

๐Ÿ“„ Step 2: Query logs in controller

In AuditLogController.php:

use Spatie\Activitylog\Models\Activity;
use Illuminate\Http\Request;

public function index(Request $request)
{
    $logs = Activity::with('causer')
        ->when($request->filled('search'), function ($q) use ($request) {
            $q->where('description', 'like', '%' . $request->search . '%');
        })
        ->latest()
        ->paginate(20);

    return view('audit_logs.index', compact('logs'));
}

๐Ÿงพ Step 3: Create Blade view

In resources/views/audit_logs/index.blade.php:

<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl">Audit Trail Logs</h2>
    </x-slot>

    <form method="GET" class="mb-4">
        <input name="search" class="border px-2 py-1" placeholder="Search description..." value="{{ request('search') }}">
        <button class="bg-blue-500 text-white px-3 py-1 rounded">Search</button>
    </form>

    <table class="w-full table-auto border-collapse">
        <thead>
            <tr>
                <th class="border px-2 py-1">Date</th>
                <th class="border px-2 py-1">User</th>
                <th class="border px-2 py-1">Description</th>
                <th class="border px-2 py-1">Changes</th>
            </tr>
        </thead>
        <tbody>
            @foreach ($logs as $log)
                <tr>
                    <td class="border px-2 py-1">{{ $log->created_at->format('d M Y, H:i') }}</td>
                    <td class="border px-2 py-1">{{ optional($log->causer)->name ?? 'System' }}</td>
                    <td class="border px-2 py-1">{{ $log->description }}</td>
                    <td class="border px-2 py-1 text-sm">
                        @if ($log->properties)
                            <strong>Old:</strong> {{ json_encode($log->properties['old'] ?? []) }}<br>
                            <strong>New:</strong> {{ json_encode($log->properties['attributes'] ?? []) }}
                        @endif
                    </td>
                </tr>
            @endforeach
        </tbody>
    </table>

    <div class="mt-4">
        {{ $logs->links() }}
    </div>
</x-app-layout>

๐Ÿ” Step 4: Add permission check (optional)

Add a Gate in AuthServiceProvider:

Gate::define('view-audit-logs', function ($user) {
    return $user->hasRole('admin') || $user->hasPermission('view-audit');
});

โœ… Tomorrow (Day 3), weโ€™ll integrate GPT to summarize these logs into human-friendly sentences.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.