211 lines
5.5 KiB
Dart
211 lines
5.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
|
|
/// Custom app bar implementing clean, minimal header design
|
|
/// with contextual actions for the transit app
|
|
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|
final String title;
|
|
final List<Widget>? actions;
|
|
final Widget? leading;
|
|
final bool showBackButton;
|
|
final VoidCallback? onBackPressed;
|
|
final Color? backgroundColor;
|
|
final Color? foregroundColor;
|
|
final double elevation;
|
|
final bool centerTitle;
|
|
|
|
const CustomAppBar({
|
|
super.key,
|
|
required this.title,
|
|
this.actions,
|
|
this.leading,
|
|
this.showBackButton = true,
|
|
this.onBackPressed,
|
|
this.backgroundColor,
|
|
this.foregroundColor,
|
|
this.elevation = 0,
|
|
this.centerTitle = true,
|
|
});
|
|
|
|
@override
|
|
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
|
|
|
|
void _handleBackPress(BuildContext context) {
|
|
// Haptic feedback for back navigation
|
|
HapticFeedback.lightImpact();
|
|
|
|
if (onBackPressed != null) {
|
|
onBackPressed!();
|
|
} else {
|
|
Navigator.of(context).pop();
|
|
}
|
|
}
|
|
|
|
Widget _buildLeading(BuildContext context) {
|
|
if (leading != null) {
|
|
return leading!;
|
|
}
|
|
|
|
if (showBackButton && Navigator.of(context).canPop()) {
|
|
return IconButton(
|
|
icon: const Icon(Icons.arrow_back_ios_new),
|
|
onPressed: () => _handleBackPress(context),
|
|
tooltip: 'Atrás',
|
|
);
|
|
}
|
|
|
|
return const SizedBox.shrink();
|
|
}
|
|
|
|
List<Widget> _buildActions(BuildContext context) {
|
|
final List<Widget> actionWidgets = [];
|
|
|
|
// Add custom actions if provided
|
|
if (actions != null) {
|
|
actionWidgets.addAll(actions!);
|
|
}
|
|
|
|
// Add contextual actions based on current route
|
|
final currentRoute = ModalRoute.of(context)?.settings.name;
|
|
|
|
switch (currentRoute) {
|
|
case '/map-screen':
|
|
actionWidgets.add(
|
|
IconButton(
|
|
icon: const Icon(Icons.my_location),
|
|
onPressed: () {
|
|
HapticFeedback.lightImpact();
|
|
// Handle location centering
|
|
},
|
|
tooltip: 'Mi ubicación',
|
|
),
|
|
);
|
|
actionWidgets.add(
|
|
IconButton(
|
|
icon: const Icon(Icons.filter_list),
|
|
onPressed: () {
|
|
HapticFeedback.lightImpact();
|
|
// Handle filter options
|
|
},
|
|
tooltip: 'Filtros',
|
|
),
|
|
);
|
|
break;
|
|
case '/schedules-screen':
|
|
actionWidgets.add(
|
|
IconButton(
|
|
icon: const Icon(Icons.refresh),
|
|
onPressed: () {
|
|
HapticFeedback.lightImpact();
|
|
// Handle schedule refresh
|
|
},
|
|
tooltip: 'Actualizar',
|
|
),
|
|
);
|
|
break;
|
|
case '/coupons-screen':
|
|
actionWidgets.add(
|
|
IconButton(
|
|
icon: const Icon(Icons.qr_code_scanner),
|
|
onPressed: () {
|
|
HapticFeedback.lightImpact();
|
|
// Handle QR code scanning
|
|
},
|
|
tooltip: 'Escanear',
|
|
),
|
|
);
|
|
break;
|
|
}
|
|
|
|
return actionWidgets;
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final theme = Theme.of(context);
|
|
|
|
return AppBar(
|
|
title: Text(
|
|
title,
|
|
style: theme.textTheme.titleLarge?.copyWith(
|
|
fontWeight: FontWeight.w500,
|
|
color: foregroundColor ?? theme.colorScheme.onSurface,
|
|
),
|
|
),
|
|
leading: _buildLeading(context),
|
|
actions: _buildActions(context),
|
|
backgroundColor: backgroundColor ?? theme.colorScheme.surface,
|
|
foregroundColor: foregroundColor ?? theme.colorScheme.onSurface,
|
|
elevation: elevation,
|
|
shadowColor: theme.shadowColor.withValues(alpha: 0.1),
|
|
surfaceTintColor: Colors.transparent,
|
|
centerTitle: centerTitle,
|
|
systemOverlayStyle: SystemUiOverlayStyle(
|
|
statusBarColor: Colors.transparent,
|
|
statusBarIconBrightness: theme.brightness == Brightness.light
|
|
? Brightness.dark
|
|
: Brightness.light,
|
|
statusBarBrightness: theme.brightness,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Specialized app bar for map screen with location and filter controls
|
|
class CustomMapAppBar extends CustomAppBar {
|
|
const CustomMapAppBar({
|
|
super.key,
|
|
super.title = 'Mapa de Rutas',
|
|
super.showBackButton = false,
|
|
});
|
|
}
|
|
|
|
/// Specialized app bar for schedules screen with refresh functionality
|
|
class CustomSchedulesAppBar extends CustomAppBar {
|
|
const CustomSchedulesAppBar({
|
|
super.key,
|
|
super.title = 'Horarios',
|
|
});
|
|
}
|
|
|
|
/// Specialized app bar for coupons screen with QR scanner
|
|
class CustomCouponsAppBar extends CustomAppBar {
|
|
const CustomCouponsAppBar({
|
|
super.key,
|
|
super.title = 'Cupones',
|
|
});
|
|
}
|
|
|
|
/// Specialized app bar for bus stop details with contextual actions
|
|
class CustomBusStopAppBar extends CustomAppBar {
|
|
final String stopName;
|
|
|
|
const CustomBusStopAppBar({
|
|
super.key,
|
|
required this.stopName,
|
|
}) : super(title: stopName);
|
|
|
|
@override
|
|
List<Widget> _buildActions(BuildContext context) {
|
|
return [
|
|
IconButton(
|
|
icon: const Icon(Icons.favorite_border),
|
|
onPressed: () {
|
|
HapticFeedback.lightImpact();
|
|
// Handle adding to favorites
|
|
},
|
|
tooltip: 'Agregar a favoritos',
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.share),
|
|
onPressed: () {
|
|
HapticFeedback.lightImpact();
|
|
// Handle sharing bus stop
|
|
},
|
|
tooltip: 'Compartir',
|
|
),
|
|
...super._buildActions(context),
|
|
];
|
|
}
|
|
}
|