mad-lawsuit/app/Http/Controllers/Admin/DashboardController.php
friday-bot 04bd71aaaa Add document access statistics to admin dashboard
Records every successful document download and surfaces the counts in the
admin area, so the docket owner can see which filings are being pulled and
how often.

- document_accesses table + DocumentAccess model
- DocumentController@download records each successful download with IP and
  user agent
- documents:import-access-log backfills history from an archived nginx log
- Dashboard gains a 60-day downloads card and a most-requested list
- New Document Access page with a date-range filter and per-day trend

Client IPs were only captured from 2026-07-30, when the reverse proxy chain
started forwarding X-Forwarded-For correctly. Rows imported from the old
nginx log therefore have no IP, and the UI labels those periods as download
counts rather than unique visitors instead of showing a misleading number.
2026-07-30 13:14:01 -06:00

78 lines
2.5 KiB
PHP

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\DocketEntry;
use App\Models\Document;
use App\Models\DocumentAccess;
use App\Models\Subscription;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
use Inertia\Response;
class DashboardController extends Controller
{
/**
* Display the admin dashboard with statistics and recent entries.
*/
public function index(): Response
{
$stats = [
'total_entries' => DocketEntry::count(),
'total_documents' => Document::count(),
'total_subscribers' => Subscription::where('is_active', true)->count(),
'recent_entries' => DocketEntry::with('documents')
->latest('date')
->take(5)
->get()
->map(function ($entry) {
return [
'id' => $entry->id,
'date' => $entry->date->format('m/d/Y'),
'title' => $entry->title,
'summary' => $entry->summary,
'documents_count' => $entry->documents->count(),
];
}),
];
$stats += $this->documentAccessSummary();
return Inertia::render('Admin/Dashboard', $stats);
}
/**
* Headline document-access numbers for the last 60 days, plus the most
* requested documents. Crawlers are excluded so the figures reflect people.
*/
private function documentAccessSummary(): array
{
$since = Carbon::now()->subDays(60)->startOfDay();
return [
'downloads_60d' => DocumentAccess::excludingBots()
->where('accessed_at', '>=', $since)
->count(),
'top_documents_60d' => DocumentAccess::query()
->excludingBots()
->join('documents', 'documents.id', '=', 'document_accesses.document_id')
->where('document_accesses.accessed_at', '>=', $since)
->groupBy('documents.id', 'documents.title')
->orderByDesc('downloads')
->take(5)
->get([
'documents.id',
'documents.title',
DB::raw('count(*) as downloads'),
])
->map(fn ($row) => [
'id' => $row->id,
'title' => $row->title,
'downloads' => (int) $row->downloads,
]),
];
}
}