No description
Find a file
DEls 3a71e7e884 feat(schema): add timesheets, fuel_sheets, plant_hours_sheets documents
Three document collections replacing data_import_batches for the
spreadsheet importers. Each owns its source file and carries honest
outcome counters (rows_total/created/failed, row_errors) — the counts the
current importers compute and then discard.

site is required on timesheets (a wage sheet belongs to one site) and
optional on the other two, which legitimately span sites since the fuel
importer resolves a site per row. cascadeDelete is false on all three, so
deleting a site cannot destroy its source spreadsheets.

Widened source_file mimeTypes beyond the plan's three entries to match
the pool being replaced. Browsers label CSVs text/csv, application/csv or
text/plain interchangeably and the importers branch on file extension,
not MIME — so the narrower list would have parsed a CSV successfully then
rejected it on write. The 2026-08-24 migration exists because that
already happened once.

Plan corrected: its TypeScript edit added a second `expand` property to
an interface that already had one, which does not compile.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 11:09:14 +02:00
.claude feat(dashboard): enhance operations dashboard with rain outlook and coordinate support 2026-09-06 19:59:52 +02:00
.freebuff feat(ocr-result, po-items): enhance PO matching logic with fuzzy search 2026-08-26 21:39:59 +02:00
.opencode/openwork/inbox/chat-attachments Update package dependencies and remove unused API routes 2026-08-19 00:14:47 +02:00
.playwright-mcp docs(spec): fuel attention dismissal design 2026-08-28 12:19:59 +02:00
docs feat(schema): add timesheets, fuel_sheets, plant_hours_sheets documents 2026-09-11 11:09:14 +02:00
public fix(pwa): restore static manifest.json + remove dead next-pwa config 2026-08-30 22:33:35 +02:00
RAW_DOCS fix(vehicles): handle empty unit_type during updates 2026-08-29 19:17:14 +02:00
scripts feat(schema): add timesheets, fuel_sheets, plant_hours_sheets documents 2026-09-11 11:09:14 +02:00
src feat(schema): add timesheets, fuel_sheets, plant_hours_sheets documents 2026-09-11 11:09:14 +02:00
.dockerignore Fix Coolify build: include scripts/ in Docker context 2026-08-09 20:30:29 +02:00
.env.coolify feat(delivery-notes): enhance delivery note upload and processing 2026-08-26 15:33:30 +02:00
.env.local.example docs(env): default MiniMax-M3 (vision + tools verified) 2026-08-30 12:56:30 +02:00
.gitignore feat(delivery-notes): enhance delivery note upload and processing 2026-08-26 15:33:30 +02:00
AGENTS.md Enhance PO upload error handling and validation 2026-08-19 15:03:48 +02:00
CLAUDE.md Enhance PO upload error handling and validation 2026-08-19 15:03:48 +02:00
cooler.env Enhance PO upload error handling and validation 2026-08-19 15:03:48 +02:00
COOLIFY.md
Copy of THE HILLS WAGES HRS AUGUST 2026.xlsx feat(timesheets): enhance import functionality to support XLSX and CSV formats 2026-08-25 18:38:02 +02:00
deployment-vptid1uo0jnz2q4t1mcbqjj9-all-logs-2026-08-19-00-23-06.txt Refactor Purchase Order upload flow documentation 2026-08-19 02:25:11 +02:00
docker-compose.yml
Dockerfile
fuel_logs_duplicates_2026-09-10.csv refactor(schema): rename received_items and timesheets to their real names 2026-09-11 11:01:40 +02:00
next.config.js fix(pwa): restore static manifest.json + remove dead next-pwa config 2026-08-30 22:33:35 +02:00
package-lock.json feat(chat): render answers as dashboard-grade markdown 2026-08-29 21:00:35 +02:00
package.json build(pwa): wire build-icons.mjs into the build pipeline 2026-08-30 22:22:42 +02:00
postcss.config.mjs
README.md feat(dashboard): enhance operations dashboard with rain outlook and coordinate support 2026-09-06 19:59:52 +02:00
tsconfig.json
vitest.config.ts Add Vitest + n8n env var documentation 2026-08-19 02:21:36 +02:00

MEGA INFRASTRUCTURE — Operations Dashboard

A Next.js 16 + TypeScript + Tailwind v4 operations dashboard for a South African civil construction company, backed by PocketBase. Tracks, per construction site: contracts, employees & timesheets, vehicles (fuel + plant), fuel logs, plant hour meters, fixed costs, income claims, purchase orders + line items, and delivery notes with OCR-driven receipting. Includes an LLM chat ("Ask") with a read-only tool layer over the same data, and a read-only MCP server.

Default login PIN is 2468. Change NEXT_PUBLIC_APP_PIN in production. Append ?demo=1 to any URL to bypass the PIN during development.


Quick start

cp .env.local.example .env.local
# edit NEXT_PUBLIC_POCKETBASE_URL, POCKETBASE_ADMIN_*, N8N_*
npm install
npm run dev    # next dev -H 0.0.0.0 -p 6004 --webpack

Production build / start:

npm run build   # icons + og-image + next build --webpack
npm run start   # next start -H 0.0.0.0 -p 3000

Docker / Coolify: see docs/COOLIFY.md and the Dockerfile.

MCP server (stdio, read-only):

npm run mcp     # uses the PocketBase creds in .env.local

Modules

The sidebar lists seven modules. Each is documented in docs/modules.md.

Path Module What it shows
/dashboard Overview KPI tiles, fuel-attention rail grouped by site, every site summary
/dashboard/sites and /dashboard/sites/[id] Sites Per-site profitability, burn, P&L, payroll, weekly & monthly trends
/dashboard/employees Workforce Per-employee hours, rates, weekly trend, casual-matrix import
/dashboard/plant and /dashboard/plant/[vehicleId] Plant & Equipment Hour-meter history, weekly logs, billable rate
/dashboard/fuel and /dashboard/fuel/[vehicleId] Fleet & Fuel Variance per log, over-limit flags, dismissable attention
/dashboard/purchasing and /dashboard/purchasing/[poId] Purchasing Every PO, DN fulfilment %, OCR exception inbox
/dashboard/chat Ask Read-only LLM chat with the same metrics the dashboard uses

Documentation

Document What's in it
docs/architecture.md Runtime topology, the two PB clients, rendering model, auth model, build/deploy
docs/data-model.md Every PocketBase collection, fields, relations, the project_code denormalisation, indexes, API rules
docs/modules.md One section per dashboard module — what it reads, computes, lets the user do
docs/data-flows.md End-to-end ingestion pipelines with sequence diagrams (timesheets, fuel, plant, PO, DN)
docs/api-reference.md Every API route — method, auth, request/response, error cases
docs/operations.md Env vars, scripts, tests, feature flags, deploy / smoke test
docs/multi-site-assessment.md The main deliverable — will this app hold up at 50 sites? Where does it break, and what to fix in what order?

The docs/superpowers/ directory has older design notes; treat as historical, not authoritative.


Tech stack

  • Next.js 16 (App Router, modified build — see AGENTS.md)
  • React 19 + TypeScript 5.7
  • Tailwind v4 (via @tailwindcss/postcss)
  • PocketBase 0.27 (PocketBase v0.22+ schema shape, see scripts/pb-bootstrap-schema.py)
  • SheetJS (xlsx) + PapaParse (csv) for imports
  • Recharts for charts
  • Vitest for tests
  • @ducanh2912/next-pwa (Webpack-only — next dev/build pass --webpack to support it)
  • Anthropic or MiniMax as the chat LLM provider

API surface (summary)

Route group Auth Notes
GET /api/health none Docker healthcheck
POST /api/sites, PATCH /api/sites/[id], POST /api/sites/[id]/fixed-costs server-only Sites CRUD
POST / PATCH / DELETE /api/vehicles[ /[id]] server-only Vehicles CRUD (unified fuel + plant)
POST /api/plant-hours/import, GET /api/plant-hours/template, GET /api/plant-hours/exception-report/[batchId], DELETE /api/plant-hours/[id] server-only Plant hours ingest + reporting
POST /api/timesheets/import server-only Timesheet ingest (three formats auto-detected)
POST /api/fuel-logs/import server-only Fuel log ingest
POST /api/purchase-orders/upload, POST /api/purchase-orders/process-batch (n8n), GET /api/purchase-orders/by-number/[poNumber]/items, PATCH /api/purchase-orders/[id]/supplier server-only / x-ingest-secret PO ingest pipeline
POST /api/delivery-notes/upload, GET /api/delivery-notes/[id]/slip (n8n), POST /api/delivery-notes/[id]/ocr-result (n8n), POST /api/delivery-notes/[id]/assign-po server-only / x-ingest-secret DN pipeline + manual fallback
GET / POST /api/data-import-batches/[id]/status|retry server-only Batch lifecycle
POST /api/records/[collection]/[id]/verify server-only Verify toggle for POs and DNs
POST /api/chat ENABLE_CHAT=true (no user auth) SSE chat stream

Full reference: docs/api-reference.md.


Tests

npm run typecheck   # tsc --noEmit
npm run test:run    # vitest run

The metric helpers under src/lib/metrics/*.test.ts pin every computation the dashboard exposes. Run after any change to the financial roll-up.


License

Proprietary. Internal use only.