production

This commit is contained in:
2026-08-28 11:13:15 +05:30
parent d7348e253f
commit 5723d373b2
162 changed files with 17924 additions and 7026 deletions

View File

@@ -816,12 +816,23 @@ class _CallButton extends StatelessWidget {
/// the kitchen's. See [StopContact].
final String? semanticLabel;
const _CallButton({required this.phone, this.size, this.semanticLabel});
/// A disc rather than a rounded square. The sheets draw it beside a round
/// avatar, where a square tile reads as a control belonging to something
/// else; the cards keep the square, which matches the tiles around it.
final bool round;
const _CallButton({
required this.phone,
this.size,
this.semanticLabel,
this.round = false,
});
@override
Widget build(BuildContext context) {
return _SquareIconButton(
icon: LucideIcons.phone,
round: round,
size: size ?? math.max(52.0, 52.w),
// ── Green, and the same green everywhere a phone appears ──
//
@@ -833,9 +844,9 @@ class _CallButton extends StatelessWidget {
// app he already uses — it is what the glyph means before the palette
// gets a say — and "done" is carried by a tick and a word, not by a hue
// on a handset.
background: ColorConstants.acceptGreen.withValues(alpha: 0.12),
background: Narrative.emeraldWash,
border: Colors.transparent,
iconColor: ColorConstants.acceptGreen,
iconColor: Narrative.emerald,
semanticLabel: semanticLabel ?? 'Call this stop',
onTap: () async {
// A dialer that fails to open is silent by default: the rider is at
@@ -859,6 +870,7 @@ class _SquareIconButton extends StatelessWidget {
final Color iconColor;
final String semanticLabel;
final VoidCallback onTap;
final bool round;
const _SquareIconButton({
required this.icon,
@@ -868,25 +880,29 @@ class _SquareIconButton extends StatelessWidget {
required this.iconColor,
required this.semanticLabel,
required this.onTap,
this.round = false,
});
@override
Widget build(BuildContext context) {
final radius = BorderRadius.circular(
round ? DesignConstants.radiusFull : DesignConstants.radiusXl,
);
return Semantics(
button: true,
label: semanticLabel,
child: Material(
color: background,
borderRadius: BorderRadius.circular(DesignConstants.radiusXl),
borderRadius: radius,
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(DesignConstants.radiusXl),
borderRadius: radius,
child: Container(
width: size,
height: size,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(DesignConstants.radiusXl),
borderRadius: radius,
border: Border.all(color: border, width: 1.5),
),
child: Icon(icon, color: iconColor, size: 22.sp),
@@ -1044,71 +1060,21 @@ class _QueueHeading extends StatelessWidget {
),
),
],
if (order != null) ...[
const Spacer(),
Flexible(child: _OrderProvenance(source: order!)),
],
// ── The provenance chip is gone ──
//
// `As assigned` / `Nearest first` sat at the head of the queue, in a
// tinted pill with a glyph, telling the rider where the *ordering* of
// his list came from. It is a fact about this app's sorting, not
// about his work: he cannot act on it, he cannot change it, and on
// the common day it said the same three words every time he opened
// the tab. What he needs from that row is which trip and how far
// through it he is, and both are already on it.
],
),
);
}
}
/// `Hub route` / `Nearest first` — where the queue's order came from.
///
/// Deliberately quiet. It is a provenance mark, not a warning: nearest-first
/// is a reasonable order when nobody has assigned one, and the rider does not
/// need alarming about it. What he needs is to not be told it is his route.
class _OrderProvenance extends StatelessWidget {
final RouteOrderSource source;
const _OrderProvenance({required this.source});
@override
Widget build(BuildContext context) {
final assigned = source.isAdmin;
final tint = assigned
? ColorConstants.acceptGreen
: ColorConstants.secondaryText;
return Tooltip(
message: source.explanation,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 3.h),
decoration: BoxDecoration(
color: tint.withValues(alpha: assigned ? 0.10 : 0.07),
borderRadius: BorderRadius.circular(DesignConstants.radiusFull),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
assigned ? LucideIcons.route : LucideIcons.navigation,
size: 11.sp,
color: tint,
),
SizedBox(width: 4.w),
Flexible(
child: Text(
source.label,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 10.5.sp,
fontWeight: FontWeight.w700,
letterSpacing: 0.2,
color: tint,
fontFamily: FontConstants.fontFamily,
),
),
),
],
),
),
);
}
}
/// `Bag 1 · Joe` — the pairing, as one object.
///
/// ── Why they are one line and not two facts ──