- Updated FuelAttentionItem type to include qrCodeId for better tracking. - Enhanced loadOverview function to fetch and include qrCodeId in vehicle data. - Modified UI components in dashboard and fuel-view to display QR code information when available, improving visibility for users. |
||
|---|---|---|
| .opencode/openwork/inbox/chat-attachments | ||
| docs | ||
| public | ||
| scripts | ||
| src | ||
| .dockerignore | ||
| .env.local.example | ||
| .gitignore | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| cooler.env | ||
| COOLIFY.md | ||
| deployment-vptid1uo0jnz2q4t1mcbqjj9-all-logs-2026-08-19-00-23-06.txt | ||
| docker-compose.yml | ||
| Dockerfile | ||
| next.config.js | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.mjs | ||
| README.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
MEGA INFRASTRUCTURE — Operations Dashboard
A Next.js 16 + TypeScript + Tailwind v4 dashboard for a construction company. Tracks fuel consumption per hour/day/week, delivery notes & outstanding items per purchase order, and weekly workforce hours with attendance flags.
The project is frontend-first with mock data, ready to be wired up to PocketBase (or any backend) for live data.
Modules
| Path | What it does |
|---|---|
/login |
Numeric PIN gate. PIN lives in NEXT_PUBLIC_APP_PIN. Append ?demo=1 to any URL to skip the PIN during development. |
/dashboard |
Operations overview — KPI cards, fuel chart, order status donut, "needs attention" rail, top suppliers. |
/dashboard/fuel |
Per-vehicle consumption, theft detection, CSV ingest (papaparse), anomaly log. |
/dashboard/orders |
Purchase-order table with filters, pagination, sort. Click any PO to see line items, delivery notes, outstanding items. |
/dashboard/employees |
Weekly hours per employee with progress bar, overtime flag, role/site/attendance filters, mini daily-hours chart. |
APIs
GET /api/health— counts and site list.GET /api/mcp?module=all|fuel|orders|employees— compact JSON for an AI agent / MCP server / n8n workflow.POST /api/upload— multipart upload of PDF / image / CSV (delivery notes, fuel attachments). 20 MB limit per file.
PWA
The app is installable on phone and desktop. Service worker is generated by
@ducanh2912/next-pwa at build time (public/sw.js), manifest at
public/manifest.json, icons at public/icons/.
Note:
@ducanh2912/next-pwauses the Webpack plugin, sonext devandnext buildmust run with--webpack. Next 16 ships Turbopack by default; thepackage.jsonscripts already pass--webpack.
Run
cp .env.local.example .env.local # change NEXT_PUBLIC_APP_PIN
npm install
npm run dev # http://localhost:3000
Default PIN is 2468.
Production
npm run build
npm run start
How the theft detection works
src/lib/fuel.ts defines EXPECTED_LITRES_TOLERANCE_PCT = 12. For every
reading we compute:
expectedLitres = hoursWorked * expectedConsumptionPerHour
deltaPct = (litresFilled - expectedLitres) / expectedLitres * 100
Severity buckets:
| Over expected | Severity |
|---|---|
| ≤ 12 % | ok |
| 12 – 24 % | watch |
| 24 – 48 % | alert |
| > 48 % | critical |
Adjust EXPECTED_LITRES_TOLERANCE_PCT to suit on-site practice.
CSV format for fuel upload
Required columns:
vehicleRegistration,date,hoursWorked,odometer,litresFilled,unitPrice,expectedConsumptionPerHour
MI-EX-01,2026-08-01,9.5,12480,90,24.50,9
The "Template" button on the Fuel page downloads a populated example.
Wiring a backend
Replace the imports in src/app/dashboard/*/page.tsx and
src/app/api/mcp/route.ts with calls into PocketBase / your API. The shape
of every type is in src/lib/types.ts.
Recommended PocketBase collections:
vehicles(registration, type, model, tankCapacityL, assignedSite)fuel_readings(vehicleId, date, hoursWorked, odometer, litresFilled, unitPrice, expectedConsumptionPerHour, attachment?)orders(reference, supplier, site, status, priority, placedAt, expectedAt, totalValue, notes)order_lines(orderId, description, quantityOrdered, quantityDelivered, unit, unitPrice)delivery_notes(orderId, scannedBy, file, mimeType, receivedAt)employees(fullName, role, site, status, phone, hourlyRate, weeklyTargetHours)daily_hours(employeeId, date, hours)