A whole lot of stuff

This commit is contained in:
Courtney Arnold 2026-08-18 11:04:58 -05:00
parent faf319322a
commit ad850d2be6
50 changed files with 3013 additions and 213 deletions

View file

@ -68,12 +68,15 @@ class HeroStat extends StatelessWidget {
}
/// The icon + two-stat row shared by every hero banner: gallons on the
/// left, the hero icon in the middle, cost on the right.
/// left, the hero icon (or, if [estimatedRefundValue] is given, the
/// estimated fuel refund in its place — see the Receipts tab, the only
/// caller that ever passes it) in the middle, cost on the right.
class HeroStatsRow extends StatelessWidget {
final String gallonsValue;
final String costValue;
final String gallonsLabel;
final String costLabel;
final String? estimatedRefundValue;
const HeroStatsRow({
super.key,
@ -81,6 +84,7 @@ class HeroStatsRow extends StatelessWidget {
required this.costValue,
this.gallonsLabel = 'Total Gallons',
this.costLabel = 'Total Fuel Cost',
this.estimatedRefundValue,
});
@override
@ -91,18 +95,58 @@ class HeroStatsRow extends StatelessWidget {
Expanded(child: HeroStat(label: gallonsLabel, value: gallonsValue, alignEnd: false)),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
// Tall enough to extend past the bottom of the label+value text
// next to it, not just match the label's height — width scales
// automatically from the source's own aspect ratio since only
// height is given.
child: Image.asset(
'assets/icon/hero_icon.png',
height: 58,
fit: BoxFit.contain,
),
child: estimatedRefundValue == null
// Tall enough to extend past the bottom of the label+value
// text next to it, not just match the label's height — width
// scales automatically from the source's own aspect ratio
// since only height is given.
? Image.asset(
'assets/icon/hero_icon.png',
height: 58,
fit: BoxFit.contain,
)
: _EstimatedRefundStat(value: estimatedRefundValue!),
),
Expanded(child: HeroStat(label: costLabel, value: costValue, alignEnd: true)),
],
);
}
}
/// The estimated-fuel-refund stat that takes the hero icon's place in the
/// middle of [HeroStatsRow] when that's turned on — smaller/more compact
/// than [HeroStat] since it sits in the narrower middle slot rather than
/// an [Expanded] one.
class _EstimatedRefundStat extends StatelessWidget {
final String value;
const _EstimatedRefundStat({required this.value});
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Est. Refund',
textAlign: TextAlign.center,
style: TextStyle(
color: AppTheme.heroTextSecondary(context),
fontSize: 10,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 4),
Text(
value,
textAlign: TextAlign.center,
style: const TextStyle(
color: AppTheme.heroText,
fontSize: 30,
fontWeight: FontWeight.w800,
),
),
],
);
}
}