feat: Build fleet operations dashboard for vehicles, drivers, and contracts#54
Conversation
…ontracts Adds an admin-only fleet operations view at /dashboard/admin/fleet-operations that ties vehicles, driver assignments, hire-purchase contracts and repayment performance into one operational surface: - Fleet-level metric cards: fleet size, available/assigned/maintenance counts, active contracts, average repayment %, fleet value, total collected. - Filterable + paginated vehicle table (search, status, type, contract status) with per-vehicle status, assigned driver, contract status and a repayment progress bar. Responsive: mobile cards + desktop table. - Vehicle detail page (/[id]) with specifications, contract summary, repayment progress and recent repayments history, plus empty states. - Loading skeleton and error boundary for the route. - Shared fleet helpers (status normalisation, repayment maths, contract selection) so the list and detail views don't duplicate calculation logic. - Registers the route in the admin sidebar. Access is gated by requireAdminAccess(). Aggregations run server-side over the existing Vehicle, HirePurchaseContract and DriverPayment models. npm run lint passes; new files are type-clean. (npm run build fails on a pre-existing viem/chains export error in lib/privy/react-auth.tsx that is present on main and unrelated to this change.) Closes Chainmove#46
|
@tosin-zoffun great work , this look good, can you fix the lint error before i merge |
The CI "Lint and build" job runs `tsc --noEmit`, which was failing on ~215
pre-existing type errors across the repo (CI has been red on main). This makes
`npm run lint`, `npm run typecheck` and `npm run build` all pass. All changes
are type-only with no runtime behaviour changes, except one genuine bug fix
noted below.
Root causes addressed:
- Model exports used `mongoose.models.X || mongoose.model<IX>(...)`, whose union
type made `findById/findOne().lean()` resolve to a broken `Doc[] | Doc`
overload union, breaking property access on lean docs in every consumer. Each
model export is cast to a concrete, permissive `Model<{ _id: any; [key: string]: any }>`
so lean() returns a single document.
- requireAuthenticatedUser() re-asserts its non-null user in the success branch,
so route handlers no longer see `user: T | null` (~28 errors).
- Typed untyped `useState([])`/`useState(null)` state and annotated implicit-any
callback params (admin loans page and others).
- Fixed a real arg-count bug: hrefForRange() was called with 4 args but takes 3,
so the reports range links were building malformed query strings.
- Removed a duplicate `stellarPublicKey` key in models/User.ts.
- Updated recharts tooltip/legend prop types in components/ui/chart.tsx, the
next-themes type import, lucide-react icon type, a JSX namespace, a ref
callback return, and a Buffer->BodyInit response cast for current deps.
|
Thanks @Obiajulu-gif! 🙏 I dug into the failing Lint and build check — I've pushed a commit that gets the whole pipeline green. The bulk of it was one root cause: model exports were typed One thing on your end: the new CI run is waiting on workflow approval (fork PR), so it hasn't kicked off yet — could you hit Approve and run when you get a sec? It should come back green. 🙌 |
|
@tosin-zoffun great work... |
Summary
Adds an admin-only fleet operations dashboard at
/dashboard/admin/fleet-operationsthat ties vehicles, driver assignments, hire-purchase contracts and repayment performance into a single operational surface. It complements the existing/dashboard/admin/vehiclesinventory page (which is asset-management focused) by giving operators a fleet-wide, performance-oriented view.Built to match the existing admin patterns (server components,
requireAdminAccess(),PageHeader, shadcn primitives,formatNaira/formatPercent, MongoDB aggregations) introduced by the reports dashboard (#52).What's included
/fleet-operations(page.tsx)/fleet-operations/[id](detail page)notFound().loading.tsxskeleton anderror.tsxboundary for the route.src/server/admin/fleet.ts— shared helpers (status normalisation, repayment maths, contract selection, badge tones) so the list and detail views don't duplicate calculation logic.MetricCard/RepaymentBarreusable presentational components.Acceptance criteria
requireAdminAccess()).npm run lintpasses (0 errors); new files aretsc --noEmit-clean.Out of scope / pre-existing
npm run buildcurrently fails onmainwith'tempo' / 'tempoModerato' is not exported from 'viem/chains'(inlib/privy/react-auth.tsxandapp/auth/page.tsx) — aviemversion drift unrelated to this PR. I verified the same failure reproduces on a cleanmainbuild, and that none of the files in this PR importviem. Lint passes and the new files are type-clean.Closes #46