Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

15 - Flutter Implementation Guide (Transport Module)

Module-specific build guide on top of 00-shared/11 (Flutter architecture, get_it DI, dio, go_router, flutter_bloc) and 00-shared/06 (state patterns). Order = recommended implementation sequence; each step maps to source files.


1. Feature folder

lib/features/transport/
  data/
    dto/vehicle_dto.dart, driver_dto.dart, route_dto.dart,
        route_assignment_dto.dart   # envelope-payload mappers
    repositories/vehicle_repository.dart, driver_repository.dart,
        route_repository.dart, assignment_repository.dart
  domain/                          # thin models (Vehicle, Driver, Route,
    models.dart                    # RouteStop, RouteAssignment, Shift)
  presentation/
    cubits/vehicle_list_cubit.dart, vehicle_form_cubit.dart,
        driver_list_cubit.dart, driver_form_cubit.dart,
        route_list_cubit.dart, route_form_cubit.dart,
        assignment_cubit.dart, transport_overview_cubit.dart
    screens/overview_screen.dart, vehicles_list_screen.dart,
        vehicle_detail_screen.dart, drivers_list_screen.dart,
        driver_detail_screen.dart, routes_list_screen.dart,
        route_detail_screen.dart, route_editor_screen.dart,
        assign_student_sheet.dart, student_assignments_screen.dart
    widgets/stat_tile.dart, entity_status_badge.dart, shift_picker.dart,
        route_stop_editor.dart, resource_picker.dart,
        assignment_tile.dart, dependency_guard_dialog.dart,
        conflict_field_error.dart

Widgets per 07_Component_Library.md; screens per 05/06.

2. Models (mirror schemas exactly)

  • Vehicle - vehicle.schema.ts:19-50: plateNumber, model, capacity (int), type (bus/van/car enum), status (active/maintenance/inactive), year?, color?, insuranceExpiry? (DateTime, server sends string - parse defensively), notes?.
  • Driver - driver.schema.ts:13-47: firstName, lastName, licenseNumber, phone, email?, status (active/inactive/on_leave), licenseExpiry?, address?, emergencyContact?, joinedAt? (DateTime), notes?.
  • Route - route.schema.ts:12-40: name, startPoint, endPoint, stops List<RouteStop{name, order}> (keep sorted by order client-side), vehicleId?, driverId? (String ObjectIds), status, estimatedDuration?, notes?.
  • RouteAssignment - route-assignment.schema.ts:12-38: routeId (populated -> Route), studentId, shift (morning/evening/both), status, stopName?, assignedAt? (DateTime), notes?.

Immutable classes + fromJson/toJson (repository maps envelope data). Never send tenantId/isDeleted (server-owned, base.repository.ts:32-36).

3. Repositories (dio)

  • Endpoints per 12_API_Mapping.md; base /api/v1 + ApiBearerAuth (transport.controller.ts:23-26).
  • Paginated calls: parse data + meta {page, limit, totalItems, totalPages, hasNext, hasPrevious} (buildPaginationMeta, transport.service.ts:75).
  • Typed errors: ApiException(409, message) for conflicts (message verbatim - used directly in ConflictFieldError); ApiException(404).
  • Assignment repo: findByStudent(studentId) expects routeId populated (route-assignment.repository.ts:20-24) - map nested route.
  • Single-flight + envelope mapping per 00-shared/11 §"AppDio".

4. Cubits

Per 13_State_Management.md: implement VehicleListCubit first (pattern for the other two lists), then form cubits (with conflicts map), then AssignmentCubit (assign + student list), then TransportOverviewCubit. Use the shared LoadState sealed class and pagination mixin (00-shared/06 §3.1-3.2).

5. Screens

OrderScreenKey widgetsSource
1Vehicles list/detail/formEntityStatusBadge, ConflictFieldError, AppPagination06 §2-4
2Drivers list/detail/formsame + AppAvatar06 §5-7
3Routes list/detailResourcePicker (read), stop list06 §8-9
4Route editorRouteStopEditor (ReorderableListView + order resequence), ResourcePicker06 §10
5Assign sheet + student assignmentsShiftPicker, StudentPicker, AssignmentTile06 §11-12
6OverviewStatTile x306 §1

6. Validation (client mirror of DTOs)

  • Vehicle form: capacity >= 1 (create-vehicle.dto.ts:14-17); type from enum (:19-21).
  • Driver form: email IsEmail-style regex (:22-24); dates IsDateString -> send ISO strings (:27-29, 41-44).
  • Route form: stops {name, order} (create-route.dto.ts:11-19); optional vehicleId/driverId strings.
  • Assign: shift enum (assign-route.dto.ts:13-15).
  • Conflict messages: render server text verbatim (07 §8).

7. Navigation (go_router)

/transport                      overview (auth + any transport.* read)
/transport/vehicles             list    | children: /:id detail
/transport/drivers              list    | children: /:id detail
/transport/routes               list    | children: /:id, /:id/edit
/transport/students/:studentId/transport   assignments

Create forms = bottom sheets (phone) / dialogs (tablet), not routes (00-shared/03). Planned: /transport/live, /transport/attendance, /transport/fees placeholders (planned).

8. DI registration (get_it)

getIt.registerLazySingleton<VehicleRepository>(() => VehicleRepository(getIt()));
getIt.registerLazySingleton<DriverRepository>(() => DriverRepository(getIt()));
getIt.registerLazySingleton<RouteRepository>(() => RouteRepository(getIt()));
getIt.registerLazySingleton<AssignmentRepository>(() => AssignmentRepository(getIt()));
// cubits factory-registered per screen (pass params via constructor args)

9. Permissions & auth

  • Gate FAB/menu on RBAC (permissions.constants.ts:62-74); 403 handling per 00-shared/07; JWT via AppDio interceptor (00-shared/11).
  • Note: RBAC guards on endpoints are not yet wired in the backend (AGENTS.md "Not yet implemented") - client still gates UI.

10. Testing

  • Unit: cubit state transitions incl. 409 -> Conflict, optimistic delete rollback (13 §2-4); model fromJson for populated assignment.
  • Widget: golden per screen (00-shared/10 §6); stop editor reorder test.
  • Integration: mock dio with fixture envelopes; pagination boundary tests (meta.hasNext).
  • E2E seeds per 14 §7.

11. Forward-looking hooks

  • Live tracking/attendance/fees screens scaffolded behind feature flags, wired when backend lands (IMPLEMENTATION_PLAN.md:229).
  • QR boarding (forward-looking): mobile_scanner dependency flagged in 00-shared/11 §1.
  • Analytics events transport.* (proposed) (05 Analytics section).