Skip to main content

Frontend Overview

kxinspect_frontend_flutter is a fixture-first Flutter app for the Contesting Charges assignment. It runs the full Accept/Contest journey with no backend, yet can be flipped to the FastAPI mock via a single --dart-define without changing widgets or BLoCs.

Toolchain

ToolVersion
Flutter3.41.9
Dart3.11.5
bloc / flutter_bloc9.1.x
go_router17.4.x
drift + drift_flutter2.28.x + 0.2.x
dio5.9.x
l10nflutter_localizations + ARB en/cy

pubspec.yaml resolves the manifest once (Part 1), later parts consume a frozen pubspec.lock.

Five visual states

Screenshot → RouteHub propertyWhat it proves
Hub Outstanding (/maintenance?tab=open)BookingSelector + blue deadline banner + inventory/inspection/task/charge cardsbooking switch, banner routing, task raise
Hub Accepted overlaygreen accepted outlinelifecycle in hub
Inspection (/inspections/{id})title type/code/room, notes, actions/updatescharged vs uncharged navigation
Charge (/charges/{id})intro deadline copy, fields, KxPhotoStrip, Contest/Acceptevidence viewer, thumb routing
Contest (/charges/{id}/contest)multiline Reason, 10-grapheme gate, attachmentsvalidation, optimistic submit, persistence

History is the second hub tab (?tab=history) — accepted, contested, resolved, paid with reason snapshot + statement link.

Non-negotiables

  • Fixture-only reviewflutter run --dart-define=DATA_SOURCE=fixture needs no network; assets/fixtures/app_state.json + manifest.json + vectors/ + media/ are committed byte-stable artefacts copied from the backend export.
  • Thin UI — widgets contain no transition logic; features/*/application owns it, repositories expose typed streams.
  • Central routes — every GoRoute lives in lib/router/app_router.dart with KxRouteBuilder + KxRoutes constants; no ad-hoc Navigator.push.
  • Typed models — Drift ↔ domain mappers round-trip through local_store / domain_mapper; bum swap fixture ↔ remote swaps only DI, not widgets.
  • Responsive & a11y — 360→desktop no horizontal overflow, token contrasts WCAG AA, semantics tested, keyboard operable.

Entry points

FileRole
lib/main.dartminimal main()bootstrap()
lib/bootstrap.dartAppConfig.parse, registerDependencies, runApp(KxApp); catches AppConfigException and renders diagnostic
lib/app/kx_app.dartMaterialApp.router + theme/locale/connectivity cubits
lib/router/app_router.dartcreateAppRouter(config, cubits, FeatureSlots)
lib/app/di/register_dependencies.dartGetIt + DiModule extensions compose features

What you can do right now

flutter pub get && flutter gen-l10n && dart run build_runner build --delete-conflicting-outputs
flutter run -d chrome --dart-define=DATA_SOURCE=fixture
# then:
flutter run -d chrome --dart-define=DATA_SOURCE=remote --dart-define=API_BASE_URL=http://127.0.0.1:8000

Next: Architecture for the layered view, or Routing for URL anatomy.