Live Tracking page upgrades:
- **Heading rotation** on each truck marker via CSS transform driven by
the heading_degrees broadcast field.
- **Click-to-detail** opens a slide-over showing trip number, status,
route, started-at, current load, an ordered stop list color-coded by
status, and the last 20 timeline events.
- **Route overlay** draws planned-route polyline (stops in order →
dumpsite, dashed), stop markers (pending/arrived/completed/skipped
colors), a diamond marker for the dumpsite, and a translucent
geofence polygon when the dumpsite has one configured.
- **Breadcrumb trail** of the last 60 minutes of GPS pings rendered
as a polyline; new pings tack on incrementally while the panel is
open.
- **Real-time push via Reverb** with polling fallback. Subscribes to
private-admin.live, listens for `.truck.location`, and updates
marker position + the trucks-online list immediately. When Reverb
isn't configured or fails, falls back to 10s polling. Status pill
shows live (push) / polling / offline.
Backend additions:
- GET /admin/live/trucks/{uuid}/trail — recent location pings
- GET /admin/live/trucks/{uuid}/active-trip — full trip + stops +
dumpsite + boundary + recent timeline
- Broadcasting auth route now accepts Sanctum bearer tokens (admin
web posts them via Echo's authorizer callback)
Frontend wiring:
- npm: laravel-echo + pusher-js
- window.Verde.getEcho() lazily inits Echo with bearer-token authorizer
- Layout exposes window.VERDE_BROADCAST with reverb config
196 tests passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
29 lines
1.1 KiB
PHP
29 lines
1.1 KiB
PHP
<!DOCTYPE html>
|
|
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="csrf-token" content="{{ csrf_token() }}">
|
|
<title>{{ $title ?? 'Verde — Garbage Monitoring' }}</title>
|
|
|
|
<link rel="preconnect" href="https://fonts.bunny.net">
|
|
<link href="https://fonts.bunny.net/css?family=inter:400,500,600,700&display=swap" rel="stylesheet" />
|
|
|
|
{{-- Reverb config consumed lazily by window.Verde.getEcho() --}}
|
|
<script>
|
|
window.VERDE_BROADCAST = {
|
|
key: @json(config('reverb.apps.apps.0.key')),
|
|
host: @json(config('reverb.apps.apps.0.options.host', request()->getHost())),
|
|
port: @json(config('reverb.apps.apps.0.options.port', 8080)),
|
|
scheme: @json(config('reverb.apps.apps.0.options.scheme', 'http')),
|
|
};
|
|
</script>
|
|
|
|
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
|
</head>
|
|
<body class="font-sans">
|
|
{{ $slot ?? '' }}
|
|
@yield('content')
|
|
</body>
|
|
</html>
|