miler map
This commit is contained in:
@@ -59,6 +59,19 @@ class PickupCard extends StatelessWidget {
|
||||
/// off the row's raw status.
|
||||
final Set<String> outForDeliveryIds;
|
||||
|
||||
/// `next_action` per order, as the pivot returned it.
|
||||
///
|
||||
/// Only needed to tell a **hub-routed** parcel from one whose routing has not
|
||||
/// been reported yet: both sit on `Created`, and only the recorded pivot
|
||||
/// instruction separates them. Everything else the card asks resolves from
|
||||
/// the row's own `consignmentstatus`.
|
||||
///
|
||||
/// Defaulting to empty is safe by construction — without it a hub parcel
|
||||
/// reads as [NextLeg.unknown], which withholds the customer destination and
|
||||
/// the Start-delivery control exactly as the hub leg does. It loses the
|
||||
/// precise wording, never the guard.
|
||||
final Map<String, String> pivotActions;
|
||||
|
||||
const PickupCard({
|
||||
super.key,
|
||||
required this.item,
|
||||
@@ -70,6 +83,7 @@ class PickupCard extends StatelessWidget {
|
||||
this.label = '',
|
||||
this.collectedIds = const {},
|
||||
this.outForDeliveryIds = const {},
|
||||
this.pivotActions = const {},
|
||||
});
|
||||
|
||||
String _val(List<String> keys, [String fallback = '']) {
|
||||
@@ -101,6 +115,17 @@ class PickupCard extends StatelessWidget {
|
||||
// his box. See [MilkRun.workingKind].
|
||||
final StopKind kind = MilkRun.workingKind(item, collectedIds: collectedIds);
|
||||
|
||||
// ── Where this parcel goes next, per order ──
|
||||
//
|
||||
// The card used to answer this from [ServiceProfile.deliversToCustomer] — a
|
||||
// line-level constant — which is false on logistics. So a hyperlocal parcel
|
||||
// already released into the rider's hands drew its *sender* as the
|
||||
// destination, and a Chennai-bound one drew a receiver he is never going to.
|
||||
final NextLegDecision leg = NextLegResolver.resolve(
|
||||
item,
|
||||
pivotAction: pivotActions[MilkRun.idOf(item)] ?? '',
|
||||
);
|
||||
|
||||
final String customer = _val([
|
||||
'pickupcustomer',
|
||||
'tenantname',
|
||||
@@ -129,8 +154,12 @@ class PickupCard extends StatelessWidget {
|
||||
// customer names the pickup, and the drop end appears only if the
|
||||
// payload actually carries one.
|
||||
final String source = stopSourceName(item);
|
||||
final bool pickupIsSource =
|
||||
ServiceProfile.active.deliversToCustomer && source.isNotEmpty;
|
||||
// The receiver names the far end whenever the rider is carrying it there —
|
||||
// whether that is a milk round (line-level) or a hyperlocal parcel the
|
||||
// backend routed direct (per-order).
|
||||
final bool carryingToCustomer =
|
||||
ServiceProfile.active.deliversToCustomer || leg.isCustomer;
|
||||
final bool pickupIsSource = carryingToCustomer && source.isNotEmpty;
|
||||
final String pickupName = pickupIsSource ? source : customer;
|
||||
final String dropAddress = _val(['dropaddress', 'DropAddress']);
|
||||
final String dropName = pickupIsSource
|
||||
@@ -139,8 +168,16 @@ class PickupCard extends StatelessWidget {
|
||||
|
||||
/// True once the rider is carrying it: the drop becomes the destination and
|
||||
/// takes the top of the card.
|
||||
// ── The immediate destination leads; never a hub leg's receiver ──
|
||||
//
|
||||
// On [NextLeg.hub] the receiver is in another district and the rider is
|
||||
// going to a hub. Letting that address take the headline is the navigation
|
||||
// mistake this whole change exists to prevent, so a hub leg never leads
|
||||
// with a drop — the final destination is demoted to context below.
|
||||
final bool dropLeads =
|
||||
pickupIsSource && (dropName.isNotEmpty || dropAddress.isNotEmpty);
|
||||
!leg.isHub &&
|
||||
(pickupIsSource || leg.isCustomer) &&
|
||||
(dropName.isNotEmpty || dropAddress.isNotEmpty);
|
||||
|
||||
// ── No accent stripe any more ──
|
||||
//
|
||||
@@ -217,6 +254,30 @@ class PickupCard extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// ── What kind of journey this is, above the name ──
|
||||
//
|
||||
// HUB HANDOVER and CUSTOMER DELIVERY are different
|
||||
// physical acts with different endings, and the row
|
||||
// has to say which before the rider reads the place.
|
||||
// Drawn only once the parcel is actually his; an
|
||||
// uncollected stop has no leg yet.
|
||||
if (leg.leg.eyebrow.isNotEmpty) ...[
|
||||
Text(
|
||||
leg.leg.eyebrow,
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
fontWeight: FontWeight.w800,
|
||||
letterSpacing: 0.8,
|
||||
color: leg.isHub
|
||||
? ColorConstants.deliveryAccent
|
||||
: leg.isUnknown
|
||||
? ColorConstants.warning
|
||||
: ColorConstants.secondaryText,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 3.h),
|
||||
],
|
||||
Text(
|
||||
(dropLeads ? dropName : pickupName).isEmpty
|
||||
? 'Not named'
|
||||
@@ -225,7 +286,7 @@ class PickupCard extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 22.sp,
|
||||
fontWeight: FontWeight.w800,
|
||||
fontWeight: FontWeight.w900,
|
||||
height: 1.1,
|
||||
letterSpacing: -0.6,
|
||||
color: ColorConstants.slateText,
|
||||
@@ -264,7 +325,7 @@ class PickupCard extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
fontSize: 15.sp,
|
||||
height: 1.35,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: ColorConstants.secondaryText,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
),
|
||||
@@ -357,7 +418,7 @@ class PickupCard extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
fontSize: 14.5.sp,
|
||||
height: 1.35,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: ColorConstants.warning,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
),
|
||||
@@ -390,7 +451,7 @@ class PickupCard extends StatelessWidget {
|
||||
'PICKED UP FROM',
|
||||
style: TextStyle(
|
||||
fontSize: 11.5.sp,
|
||||
fontWeight: FontWeight.w800,
|
||||
fontWeight: FontWeight.w900,
|
||||
letterSpacing: 0.8,
|
||||
color: ColorConstants.secondaryText,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
@@ -409,7 +470,7 @@ class PickupCard extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 14.5.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontWeight: FontWeight.w800,
|
||||
letterSpacing: -0.2,
|
||||
height: 1.2,
|
||||
color: ColorConstants.slateText,
|
||||
@@ -462,7 +523,7 @@ class PickupCard extends StatelessWidget {
|
||||
child: Text(
|
||||
'Finish the current stop first',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 14.sp,
|
||||
color: ColorConstants.secondaryText,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
@@ -627,7 +688,7 @@ class _JourneyBlock extends StatelessWidget {
|
||||
distance,
|
||||
style: TextStyle(
|
||||
fontSize: 15.5.sp,
|
||||
fontWeight: FontWeight.w800,
|
||||
fontWeight: FontWeight.w900,
|
||||
letterSpacing: -0.3,
|
||||
color: fg,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
@@ -641,7 +702,7 @@ class _JourneyBlock extends StatelessWidget {
|
||||
'~$travel',
|
||||
style: TextStyle(
|
||||
fontSize: 12.5.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: ColorConstants.secondaryText,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
),
|
||||
@@ -687,7 +748,7 @@ class _DistanceEta extends StatelessWidget {
|
||||
travel == '—' ? distance : '$distance · ~$travel',
|
||||
style: TextStyle(
|
||||
fontSize: 15.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontWeight: FontWeight.w800,
|
||||
letterSpacing: -0.2,
|
||||
color: fg,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
@@ -737,7 +798,7 @@ class _ActionLine extends StatelessWidget {
|
||||
|
||||
TextStyle style(Color c) => TextStyle(
|
||||
fontSize: 14.5.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontWeight: FontWeight.w800,
|
||||
color: c,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
);
|
||||
@@ -1040,7 +1101,7 @@ class _QueueHeading extends StatelessWidget {
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 12.5.sp,
|
||||
fontWeight: FontWeight.w800,
|
||||
fontWeight: FontWeight.w900,
|
||||
letterSpacing: 1.2,
|
||||
color: live
|
||||
? ColorConstants.primary
|
||||
@@ -1054,7 +1115,7 @@ class _QueueHeading extends StatelessWidget {
|
||||
'$count',
|
||||
style: TextStyle(
|
||||
fontSize: 12.5.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontWeight: FontWeight.w800,
|
||||
color: ColorConstants.secondaryText,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
),
|
||||
@@ -1129,7 +1190,7 @@ class _LabelPair extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: size.sp,
|
||||
fontWeight: FontWeight.w800,
|
||||
fontWeight: FontWeight.w900,
|
||||
letterSpacing: -0.2,
|
||||
color: muted
|
||||
? ColorConstants.secondaryText
|
||||
@@ -1147,7 +1208,7 @@ class _LabelPair extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: size.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontWeight: FontWeight.w800,
|
||||
letterSpacing: -0.2,
|
||||
color: ColorConstants.secondaryText,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
@@ -1212,7 +1273,7 @@ class _TaskChip extends StatelessWidget {
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w800,
|
||||
fontWeight: FontWeight.w900,
|
||||
letterSpacing: 1.0,
|
||||
color: look.color,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
@@ -1268,7 +1329,7 @@ class _NextCard extends StatelessWidget {
|
||||
// in position, which is what makes their labels a
|
||||
// convenience rather than the only thing ranking them.
|
||||
fontSize: 17.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontWeight: FontWeight.w700,
|
||||
height: 1.15,
|
||||
letterSpacing: -0.4,
|
||||
color: ColorConstants.slateText,
|
||||
@@ -1292,7 +1353,7 @@ class _NextCard extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 14.5.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: ColorConstants.secondaryText,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
),
|
||||
@@ -1349,7 +1410,7 @@ class _LaterRow extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 16.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: -0.3,
|
||||
color: ColorConstants.slateText,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
@@ -1361,7 +1422,7 @@ class _LaterRow extends StatelessWidget {
|
||||
RouteMetricsHelper.formatDistance(distanceMeters),
|
||||
style: TextStyle(
|
||||
fontSize: 14.5.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: ColorConstants.secondaryText,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
),
|
||||
@@ -1417,7 +1478,7 @@ class _SkippedRow extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 18.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontWeight: FontWeight.w800,
|
||||
letterSpacing: -0.4,
|
||||
color: ColorConstants.slateText,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
@@ -1436,7 +1497,7 @@ class _SkippedRow extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 14.5.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontWeight: FontWeight.w700,
|
||||
height: 1.3,
|
||||
color: ColorConstants.warning,
|
||||
fontFamily: FontConstants.fontFamily,
|
||||
@@ -1447,7 +1508,12 @@ class _SkippedRow extends StatelessWidget {
|
||||
Row(
|
||||
children: [
|
||||
if (label.isNotEmpty) ...[
|
||||
_LabelPair(label: label, customer: '', muted: true, size: 13.5),
|
||||
_LabelPair(
|
||||
label: label,
|
||||
customer: '',
|
||||
muted: true,
|
||||
size: 13.5,
|
||||
),
|
||||
SizedBox(width: 12.w),
|
||||
],
|
||||
Expanded(
|
||||
|
||||
Reference in New Issue
Block a user