Files
hackathon-innovaflow5.0-cdf…/views_v2/app.dart
2026-05-22 23:50:10 -06:00

144 lines
4.5 KiB
Dart

// lib/app.dart
// Root de la app: go_router + bottom navigation de 4 tabs (P3).
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'features/eta/eta_screen.dart';
import 'features/notifications/notifications_screen.dart';
import 'features/feedback/feedback_screen.dart';
import 'features/quiz/quiz_screen.dart';
// ──────────────────────────────────────────
// Router
// ──────────────────────────────────────────
final _router = GoRouter(
initialLocation: '/eta',
routes: [
ShellRoute(
builder: (context, state, child) => _ScaffoldWithNav(child: child),
routes: [
GoRoute(
path: '/eta',
pageBuilder: (context, state) => const NoTransitionPage(
child: EtaScreen(),
),
),
GoRoute(
path: '/notifications',
pageBuilder: (context, state) => const NoTransitionPage(
child: NotificationsScreen(),
),
),
GoRoute(
path: '/feedback',
pageBuilder: (context, state) => const NoTransitionPage(
child: FeedbackScreen(),
),
),
GoRoute(
path: '/quiz',
pageBuilder: (context, state) => const NoTransitionPage(
child: QuizScreen(),
),
),
],
),
],
);
// ──────────────────────────────────────────
// App widget
// ──────────────────────────────────────────
class RecolectaApp extends StatelessWidget {
const RecolectaApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Recolecta',
debugShowCheckedModeBanner: false,
theme: _buildTheme(Brightness.light),
darkTheme: _buildTheme(Brightness.dark),
themeMode: ThemeMode.system,
routerConfig: _router,
);
}
ThemeData _buildTheme(Brightness brightness) {
final isDark = brightness == Brightness.dark;
return ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF1D9E75), // teal-400
brightness: brightness,
),
useMaterial3: true,
appBarTheme: AppBarTheme(
backgroundColor:
isDark ? const Color(0xFF1A1A1A) : Colors.white,
foregroundColor: isDark ? Colors.white : Colors.black87,
elevation: 0,
scrolledUnderElevation: 1,
titleTextStyle: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: isDark ? Colors.white : Colors.black87,
),
),
);
}
}
// ──────────────────────────────────────────
// Bottom navigation shell
// ──────────────────────────────────────────
class _ScaffoldWithNav extends StatelessWidget {
final Widget child;
const _ScaffoldWithNav({required this.child});
static const _tabs = [
_TabItem(path: '/eta', icon: Icons.schedule_rounded, label: 'ETA'),
_TabItem(
path: '/notifications',
icon: Icons.notifications_outlined,
label: 'Avisos'),
_TabItem(
path: '/feedback',
icon: Icons.feedback_outlined,
label: 'Buzón'),
_TabItem(
path: '/quiz', icon: Icons.quiz_outlined, label: 'Quiz'),
];
@override
Widget build(BuildContext context) {
final location = GoRouterState.of(context).uri.path;
final currentIndex =
_tabs.indexWhere((t) => location.startsWith(t.path));
return Scaffold(
body: child,
bottomNavigationBar: NavigationBar(
selectedIndex: currentIndex < 0 ? 0 : currentIndex,
onDestinationSelected: (i) => context.go(_tabs[i].path),
destinations: _tabs
.map(
(t) => NavigationDestination(
icon: Icon(t.icon),
label: t.label,
),
)
.toList(),
height: 64,
labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
),
);
}
}
class _TabItem {
final String path;
final IconData icon;
final String label;
const _TabItem(
{required this.path, required this.icon, required this.label});
}