miler map
This commit is contained in:
@@ -19,6 +19,7 @@ import 'package:miler/Models/stop_status.dart';
|
||||
import 'package:miler/data/order_manifest.dart';
|
||||
import 'package:miler/data/stop_area.dart';
|
||||
import 'package:miler/data/milk_run.dart';
|
||||
import 'package:miler/data/pickup_locations.dart';
|
||||
import 'package:miler/data/service_profile.dart';
|
||||
|
||||
/// ─────────────────────────────────────────────────────────────────────────
|
||||
@@ -251,7 +252,11 @@ class TripCard extends StatelessWidget {
|
||||
/// The collapsed trip brief: progress, time left, cash — and everything else
|
||||
/// one tap away. See [TripBriefStrip] for what this used to be and why the
|
||||
/// four surfaces it replaced were the wrong price for the information.
|
||||
Widget buildSummary() => TripBriefStrip(
|
||||
/// [onBrand] hands the brief over for Home's trip tab panel: no white panel
|
||||
/// of its own, and its ink inverted for the brand red it lands on. See
|
||||
/// [TripSelector].
|
||||
Widget buildSummary({bool onBrand = false}) => TripBriefStrip(
|
||||
onBrand: onBrand,
|
||||
trip: trip,
|
||||
// What the four figures describe: the collections still owed, measured
|
||||
// from where the rider is standing — the same origin the page used to
|
||||
@@ -423,11 +428,42 @@ class TripCard extends StatelessWidget {
|
||||
///
|
||||
/// A group whose orders have all left Home — collected, and now on the work
|
||||
/// tab — emits nothing at all. Its heading would be a title over a gap.
|
||||
/// Every stop is drawn as the **place** it is worked at, with its orders in a
|
||||
/// list under it.
|
||||
///
|
||||
/// ── One shape for both lines ──
|
||||
///
|
||||
/// This was a flag, then a per-stop question, and it is now neither. The
|
||||
/// history is worth keeping because each step was right about something:
|
||||
///
|
||||
/// 1. `ServiceProfile.sourceIsKitchen` — a milk round grouped its orders
|
||||
/// under the counter they are loaded at; a logistics route grouped
|
||||
/// nothing. The argument for the second half was that a parcel rider
|
||||
/// "goes to one door for one consignment", so a header above a single
|
||||
/// order would print the same name twice.
|
||||
/// 2. Then deliveries were added to it: a booking the rider *hands over* was
|
||||
/// loaded at the depot, and six drops drawing six nodes repeated one base
|
||||
/// address six times.
|
||||
///
|
||||
/// The premise under step 1 was wrong, and the milk run is the proof. A place
|
||||
/// holding one order does not print the same name twice: the header names
|
||||
/// **where** — `VBK Complex, 11C-18, Ramasamy Rd` — and the row under it
|
||||
/// names **who** — `Jai Hari Shankar P R`. Those are two different facts, and
|
||||
/// on a collection the rider needs both: the address is what he rides to, the
|
||||
/// customer is who he asks for when he gets there. Flattening them threw the
|
||||
/// address away and titled the card with the person.
|
||||
///
|
||||
/// So every stop groups by its source now, and the shape of Home is one shape
|
||||
/// on both lines. Two collections off one address gather, which they always
|
||||
/// should have; a lone one is a place holding one order. The only stop still
|
||||
/// drawn flat is one with nothing to name a place by at all — no counter and
|
||||
/// no address — where there is genuinely no header to write. See the `flat`
|
||||
/// rule below, which is unchanged.
|
||||
|
||||
@visibleForTesting
|
||||
List<RouteGroup> routeGroups() {
|
||||
final order = <String>[];
|
||||
final buckets = <String, List<int>>{};
|
||||
final grouped = ServiceProfile.active.sourceIsKitchen;
|
||||
|
||||
// Every stop is bucketed, not only the ones Home still draws: a group's bag
|
||||
// numbers are counted against the whole group the rider was handed, so the
|
||||
@@ -449,9 +485,23 @@ class TripCard extends StatelessWidget {
|
||||
// is the same two-readers-one-question failure `sourceNameOf` documents,
|
||||
// repeated on the id, and it splits a kitchen's orders across two groups
|
||||
// on the screen while the collect still treats them as one.
|
||||
final key = grouped
|
||||
// ── One key for a milk round's counter, one for the whole depot ──
|
||||
//
|
||||
// A kitchen line has several counters in a day and the rider loads at
|
||||
// each in turn, so its stops key on the counter they came off.
|
||||
//
|
||||
// A logistics day has one building. It assigns the day's bookings —
|
||||
// collections, drops and both — hands over the route, and the rider
|
||||
// accepts the lot before he leaves. So the run belongs to that building,
|
||||
// and every stop keys to it however the individual booking is addressed.
|
||||
// See [RiderHub].
|
||||
//
|
||||
// `base`, not the internal word for it: `no_hub_in_rider_copy_test`
|
||||
// forbids that string in this layer and it is right to — a bucket key is
|
||||
// one rename away from being a label.
|
||||
final key = ServiceProfile.active.sourceIsKitchen
|
||||
? MilkRun.sourceKeyOf(stop, within: trip.stops)
|
||||
: 'stop:${_idOf(stop)}';
|
||||
: 'base';
|
||||
if (!buckets.containsKey(key)) {
|
||||
buckets[key] = <int>[];
|
||||
order.add(key);
|
||||
@@ -522,22 +572,35 @@ class TripCard extends StatelessWidget {
|
||||
// to name its place with — no counter name and no address. With an
|
||||
// address it is a place holding one order, headed by where it is, with
|
||||
// the order in the list under it.
|
||||
// Every bucket is a place now, so the only stop still drawn flat is one
|
||||
// with nothing to head it with — no counter name and no address. There
|
||||
// is genuinely no header to write for that one.
|
||||
final flat =
|
||||
all.length == 1 &&
|
||||
(!grouped || (stopSourceName(first).isEmpty && place.isEmpty));
|
||||
all.length == 1 && stopSourceName(first).isEmpty && place.isEmpty;
|
||||
|
||||
// A grouped place is named by its counter, or failing that by where it
|
||||
// is. A flat one *is* the stop, so it is named by the customer —
|
||||
// `MilkRun.navigationLabel` answers "pickup" for a parcel that has not
|
||||
// been collected yet, which is a description of the leg rather than a
|
||||
// name the rider can read off a gate.
|
||||
// ── The head card is named after the place, and the depot is a place ──
|
||||
//
|
||||
// On a logistics run that place is the rider's **hub**, not any one
|
||||
// booking's address. Reading it off the stops titled the card with a
|
||||
// customer's street — right for the drops, which are loaded at the
|
||||
// depot, and wrong for the collections, which are not.
|
||||
//
|
||||
// It falls back through what the payload names and then the address, so
|
||||
// a build with no locations table still draws the card it drew before
|
||||
// rather than an untitled one.
|
||||
final hub = ServiceProfile.active.sourceIsKitchen ? '' : RiderHub.name;
|
||||
final name = flat
|
||||
? OrderManifest.customerOf(first)
|
||||
: (grouped
|
||||
? (stopSourceName(first).trim().isNotEmpty
|
||||
? stopSourceName(first)
|
||||
: place)
|
||||
: MilkRun.navigationLabel(first));
|
||||
: (hub.isNotEmpty
|
||||
? hub
|
||||
: stopSourceName(first).trim().isNotEmpty
|
||||
? stopSourceName(first)
|
||||
: place);
|
||||
return RouteGroup(
|
||||
key: key,
|
||||
// A route with no source names still groups — into one unnamed
|
||||
@@ -559,7 +622,16 @@ class TripCard extends StatelessWidget {
|
||||
// components that are identical on every stop of every route and
|
||||
// would push the part that names the street off the end of the line.
|
||||
// Not repeated when it is already the heading — see [name] above.
|
||||
location: flat || name.trim() == place ? '' : place,
|
||||
//
|
||||
// ── And never a booking's street under the hub's name ──
|
||||
//
|
||||
// `place` is the first stop's address, which is the right subtitle
|
||||
// for a counter the stops were collected from and quite wrong under
|
||||
// a depot: it printed a customer's road under `H1`, which reads as
|
||||
// the hub's address and is not. The locations table gives the hub a
|
||||
// name and no street, so when the head is the hub the line is left
|
||||
// empty rather than filled with something that looks like an answer.
|
||||
location: flat || hub.isNotEmpty || name.trim() == place ? '' : place,
|
||||
stops: stops,
|
||||
allStops: all,
|
||||
firstIndex: indices.first,
|
||||
@@ -857,7 +929,7 @@ class TripCard extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 15.5.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontWeight: FontWeight.w800,
|
||||
letterSpacing: -0.2,
|
||||
color: ColorConstants.slateText,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
@@ -879,7 +951,7 @@ class TripCard extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 13.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontWeight: FontWeight.w800,
|
||||
letterSpacing: -0.1,
|
||||
color: ColorConstants.secondaryText,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
@@ -1008,7 +1080,7 @@ class TripCard extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 11.5.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontWeight: FontWeight.w800,
|
||||
letterSpacing: 0.7,
|
||||
color: _hubColor,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
@@ -1101,7 +1173,7 @@ class TripCard extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 12.5.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontWeight: FontWeight.w800,
|
||||
letterSpacing: -0.2,
|
||||
color: picked.isEmpty
|
||||
? ColorConstants.secondaryText
|
||||
@@ -1117,7 +1189,7 @@ class TripCard extends StatelessWidget {
|
||||
all ? 'CLEAR' : 'ALL',
|
||||
style: TextStyle(
|
||||
fontSize: 11.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontWeight: FontWeight.w800,
|
||||
letterSpacing: 0.6,
|
||||
color: ColorConstants.primary,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
@@ -1379,7 +1451,7 @@ class TripCard extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontWeight: FontWeight.w800,
|
||||
color: ColorConstants.acceptGreen,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
),
|
||||
@@ -1429,7 +1501,7 @@ class TripCard extends StatelessWidget {
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 11.5.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: ColorConstants.secondaryText,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
),
|
||||
@@ -1477,7 +1549,7 @@ class _ViewRouteAction extends StatelessWidget {
|
||||
'MAP',
|
||||
style: TextStyle(
|
||||
fontSize: 11.5.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontWeight: FontWeight.w800,
|
||||
letterSpacing: 0.6,
|
||||
color: ColorConstants.primary,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
|
||||
Reference in New Issue
Block a user