Owner-facing SPA dashboard for tracking trucker trips, costs, weights, and shipment contracts. Built with SvelteKit 2 + Svelte 5, deployed as a static SPA on Azure Static Web Apps.
graph TB
subgraph "Mobile"
A[TruckerMobile<br/>React Native / Expo]
end
subgraph "Azure Cloud"
B[Azure Function App<br/>Python 3.11]
C[(PostgreSQL<br/>Flexible Server)]
D[Azure Static Web Apps]
end
subgraph "Dashboard"
E[TruckerDashboard<br/>SvelteKit SPA]
end
A -- "POST/PUT/DELETE /api/trips" --> B
B -- "SQL" --> C
E -- "GET /api/dashboard/*" --> B
E -- "GET/POST/PUT/DELETE /api/contracts" --> B
D -- "Hosts" --> E
/dashboard/locations so new shipping sites show up automatically.Từ DD/MM/YYYY đến DD/MM/YYYY window; same label travels into every export.flowchart LR
subgraph "Contract Matching"
A[Contract<br/>subject = 'YP'] --> B{Trip stops}
B -->|pickup: YP| C[Match ✓]
B -->|delivery: LHH| D[No match]
C --> E[Sum delivery<br/>weights only]
E --> F[60.350 / 100.000 kg<br/>60.4%]
end
src/
├── routes/+page.svelte # Main page with tab navigation (Tổng quan / Hợp đồng)
├── lib/
│ ├── api/
│ │ ├── client.ts # API client (dashboard + contract endpoints)
│ │ └── types.ts # TypeScript interfaces (Trip, Contract, etc.)
│ ├── contracts/
│ │ └── ContractTab.svelte # Contract management UI (cards, form, progress bars)
│ ├── charts/ # Chart.js components (CostBreakdown, WeightChart, Timeline, CostCategories)
│ ├── exports/exporter.ts # Multi-format export (CSV, Excel, PDF, JSON)
│ └── format.ts # VND currency formatting, date helpers
├── app.css # Global design system (Inter font, CSS variables)
└── +layout.ts # prerender=true, ssr=false (static SPA)
| Decision | Rationale |
|---|---|
| Single-page with tabs | Contracts and trips share context (same API base, same drivers). Tabs keep navigation simple. |
| Contract matching at query time | No FK links to trips — matching by location + date range is computed server-side via PostgreSQL lateral join. Simple, no sync issues. |
| Delivery weights only | Contract fulfillment counts only delivery stop weights, not pickup. Pickup weight ≠ delivered goods. |
| Extracted ContractTab component | Keeps +page.svelte manageable ( |
npm install
npm run dev # localhost:5173
npm run build # Production build → /build
npm run check # Type check + Svelte validation
./scripts/deploy.sh # Build + deploy to Azure Static Web Apps
Requires Azure CLI login (az login). Deploys to: https://thankful-water-0807a7b00.1.azurestaticapps.net