108 lines
3.2 KiB
Dart
108 lines
3.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import '../theme/app_theme.dart';
|
|
|
|
/// Green gradient hero banner background shared by every screen that shows
|
|
/// a totals summary (Receipts, Vehicle Detail) — callers supply their own
|
|
/// stat row / controls as [child], keeping the container/gradient styling
|
|
/// itself in one place.
|
|
class HeroBanner extends StatelessWidget {
|
|
final Widget child;
|
|
|
|
const HeroBanner({super.key, required this.child});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container(
|
|
padding: const EdgeInsets.fromLTRB(20, 16, 20, 10),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(15),
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
colors: AppTheme.heroGradient(context),
|
|
),
|
|
),
|
|
child: child,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// A single label/value pair inside a [HeroBanner], e.g. "Total Gallons".
|
|
class HeroStat extends StatelessWidget {
|
|
final String label;
|
|
final String value;
|
|
final bool alignEnd;
|
|
|
|
const HeroStat({super.key, required this.label, required this.value, required this.alignEnd});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final textAlign = alignEnd ? TextAlign.end : TextAlign.start;
|
|
return Column(
|
|
crossAxisAlignment: alignEnd ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
label,
|
|
textAlign: textAlign,
|
|
style: TextStyle(
|
|
color: AppTheme.heroTextSecondary(context),
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(
|
|
value,
|
|
textAlign: textAlign,
|
|
style: const TextStyle(
|
|
color: AppTheme.heroText,
|
|
fontSize: 28,
|
|
fontWeight: FontWeight.w800,
|
|
letterSpacing: -0.5,
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
/// The icon + two-stat row shared by every hero banner: gallons on the
|
|
/// left, the hero icon in the middle, cost on the right.
|
|
class HeroStatsRow extends StatelessWidget {
|
|
final String gallonsValue;
|
|
final String costValue;
|
|
final String gallonsLabel;
|
|
final String costLabel;
|
|
|
|
const HeroStatsRow({
|
|
super.key,
|
|
required this.gallonsValue,
|
|
required this.costValue,
|
|
this.gallonsLabel = 'Total Gallons',
|
|
this.costLabel = 'Total Fuel Cost',
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
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,
|
|
),
|
|
),
|
|
Expanded(child: HeroStat(label: costLabel, value: costValue, alignEnd: true)),
|
|
],
|
|
);
|
|
}
|
|
}
|