A whole bunch of changes
This commit is contained in:
parent
901ec678a3
commit
956231048e
122 changed files with 5442 additions and 914 deletions
108
lib/widgets/hero_banner.dart
Normal file
108
lib/widgets/hero_banner.dart
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
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)),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue