Replace the customer app with Doormile CX

Book a pickup, track it to delivery — the rebuilt customer app.

- Design language from doormile-screens.html: brand #8F0F06, Manrope +
  Geist Mono (variable fonts), bordered cards instead of shadows, crimson
  brand headers, sliding tab indicator, mono for anything read digit by digit.
- lib/data (one live API implementation, plus a debug-only offline fake),
  lib/state, lib/ui (tokens, widgets, screens).
- 84 tests, plus a design snapshot harness that renders every screen with the
  real fonts: flutter test test/design_snapshot_test.dart --run-skipped
  --update-goldens

This replaces the previous app (pubspec 'doormile', app id
com.doormile.customer). That tree remains in history at 6c7d656; note its
android/app/google-services.json is not carried over, and the application id
here is in.doormile.customer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-15 16:07:33 +05:30
parent 6c7d656de5
commit 0d66627c3c
305 changed files with 21930 additions and 11056 deletions

24
lib/state/app_scope.dart Normal file
View File

@@ -0,0 +1,24 @@
import 'package:flutter/widgets.dart';
import 'app_state.dart';
/// Makes [AppState] available to the widget tree and rebuilds dependents when
/// it changes. Deliberately dependency-free — no external state package.
class AppScope extends InheritedNotifier<AppState> {
const AppScope({super.key, required AppState state, required super.child})
: super(notifier: state);
/// Subscribes the calling widget to changes.
static AppState of(BuildContext context) {
final scope = context.dependOnInheritedWidgetOfExactType<AppScope>();
assert(scope != null, 'AppScope.of() called outside an AppScope');
return scope!.notifier!;
}
/// Reads without subscribing — for callbacks and one-shot lookups.
static AppState read(BuildContext context) {
final scope = context.getInheritedWidgetOfExactType<AppScope>();
assert(scope != null, 'AppScope.read() called outside an AppScope');
return scope!.notifier!;
}
}