116 lines
3.6 KiB
Markdown
116 lines
3.6 KiB
Markdown
|
|
# 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-pwa` uses the **Webpack** plugin, so `next dev`
|
|||
|
|
> and `next build` must run with `--webpack`. Next 16 ships Turbopack by
|
|||
|
|
> default; the `package.json` scripts already pass `--webpack`.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Run
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cp .env.local.example .env.local # change NEXT_PUBLIC_APP_PIN
|
|||
|
|
npm install
|
|||
|
|
npm run dev # http://localhost:3000
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Default PIN is **`2468`**.
|
|||
|
|
|
|||
|
|
### Production
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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)
|