Miler rider app: surface system, visible design language, backend lifecycle
Design system - MilerSurface ladder (canvas → working → raised → floating) with MilerPanel as layer 1; canvas moved to #DEE3EA so white separates at 1.290:1. - Visible vocabulary applied across Home, Deliveries, Activity, Account and the sheets: hero heads (tabular numeral + small caption, clamped at 1.3x), canvas wells for anything that opens, small filled tags for shelf labels, demoted placeholders. Recorded in DESIGN_SYSTEM.md §6. - One icon family: 222 Material glyphs migrated to Lucide; none left outside lib/xpress. - Colour semantics corrected: amber only for what is genuinely owed, brand red reserved for the live stop, disabled primaries go neutral rather than pale. Data and lifecycle - lib/data/lifecycle.dart reads mutations for what they prove; route_order.dart makes admin sequence the single ordering authority; service_day.dart, and stop_area.dart rewritten against live Coimbatore addresses (digit-token stripping, city stoplist, street suffixes, stammer collapse). - countLabel states the load once, in bags. Testing - 1440 tests passing; golden shot harnesses for Home, Deliveries, Activity, sheets and verify, with test/failures/ now gitignored (diff debris). - New pins: home_gutter_test, stop_area_test, plus updated structural bounds. Note: this commit also carries pre-existing working-tree deletions that were present before this work (API_SPEC.md, README.md, demo test fixtures). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:miler/views/helpers/widgets/page_transitions.dart';
|
||||
import 'package:miler/views/onboardscreens/otp_page.dart';
|
||||
import 'package:miler/views/onboardscreens/auth_scaffold.dart';
|
||||
import 'package:miler/widget/Bottom_page.dart';
|
||||
import 'package:miler/helpers/rider_shell.dart';
|
||||
import 'package:miler/controllers/auth.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
@@ -57,6 +58,15 @@ class _MpinViewState extends State<_MpinView> {
|
||||
|
||||
bool isVerifying = false;
|
||||
bool _rejected = false;
|
||||
|
||||
/// What actually went wrong, from [AuthController.lastPinFailure].
|
||||
///
|
||||
/// This screen used to hard-code "Incorrect MPIN. Try again." for every
|
||||
/// failure the controller reported — including the ones that never reached
|
||||
/// the server. A rider whose sign-in was dying on a device-id lookup was told
|
||||
/// his PIN was wrong, so the one thing he could report was the one thing that
|
||||
/// was not true. Whatever the controller knows, the screen now says.
|
||||
String? _failure;
|
||||
String _riderName = '';
|
||||
|
||||
@override
|
||||
@@ -101,7 +111,10 @@ class _MpinViewState extends State<_MpinView> {
|
||||
}
|
||||
|
||||
setState(() {
|
||||
if (_rejected) _rejected = false;
|
||||
if (_rejected) {
|
||||
_rejected = false;
|
||||
_failure = null;
|
||||
}
|
||||
});
|
||||
|
||||
if (_isComplete) {
|
||||
@@ -117,7 +130,12 @@ class _MpinViewState extends State<_MpinView> {
|
||||
c.clear();
|
||||
}
|
||||
_focusNodes[0].requestFocus();
|
||||
if (mounted) setState(() => _rejected = true);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_rejected = true;
|
||||
_failure = _auth.lastPinFailure;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _submitMpin() async {
|
||||
@@ -130,14 +148,27 @@ class _MpinViewState extends State<_MpinView> {
|
||||
);
|
||||
|
||||
if (!mounted) return;
|
||||
setState(() => isVerifying = false);
|
||||
setState(() {
|
||||
isVerifying = false;
|
||||
// Say it on the screen, not only inside a sheet the rider dismisses.
|
||||
if (!ok) {
|
||||
_rejected = true;
|
||||
_failure = _auth.lastPinFailure;
|
||||
}
|
||||
});
|
||||
|
||||
if (ok) {
|
||||
// Straight to the app. There used to be a "Go on duty" gate between the
|
||||
// PIN and the tabs, which made every launch a two-step sign-in for a
|
||||
// decision the rider can make — and change — from the switch in Home's
|
||||
// app bar at any moment of the shift.
|
||||
Get.offAll(() => const BottomPage());
|
||||
//
|
||||
// Which app depends on the tenant the login just resolved: `loginParsed`
|
||||
// persists `tenantid`/`tenantname` and calls `TenantController.load()`
|
||||
// before returning, so by this line the answer is settled. A delivery
|
||||
// rider lands in the ported Xpress flow, everyone else in the parcel
|
||||
// dashboard. See [riderShell].
|
||||
Get.offAll(() => riderShell());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +192,7 @@ class _MpinViewState extends State<_MpinView> {
|
||||
children: [
|
||||
AuthPrimaryButton(
|
||||
label: 'Unlock',
|
||||
icon: Icons.lock_open_rounded,
|
||||
icon: LucideIcons.lockOpen,
|
||||
loading: isVerifying,
|
||||
onPressed: isVerifying || !_isComplete ? null : _submitMpin,
|
||||
),
|
||||
@@ -190,7 +221,9 @@ class _MpinViewState extends State<_MpinView> {
|
||||
// rejected and the boxes were reset — otherwise they empty themselves
|
||||
// with no stated reason.
|
||||
AuthInlineError(
|
||||
message: _rejected ? 'Incorrect MPIN. Try again.' : null,
|
||||
message: _rejected
|
||||
? (_failure ?? 'Incorrect MPIN. Try again.')
|
||||
: null,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user