import 'package:app/core/i18n/translations.g.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; class AppShell extends StatefulWidget { final Widget child; const AppShell({super.key, required this.child}); @override State createState() => _AppShellState(); } class _AppShellState extends State { static const double _breakpoint = 800; // Tablet/Desktop threshold final FocusNode _contentFocus = FocusNode(debugLabel: 'contentFocus'); @override void dispose() { _contentFocus.dispose(); super.dispose(); } // --- NAV ITEMS ------------------------------------------------------------- // Desktop/Tablet drawer items (you can keep them rich/longer here) List<({IconData icon, IconData? selectedIcon, String label, String route})> _getDesktopItems(BuildContext context) { final t = Translations.of(context); return [ ( icon: Icons.dashboard_outlined, selectedIcon: Icons.dashboard, label: t.app.navigationDashboard, route: '/', ), ( icon: Icons.account_balance_wallet_outlined, selectedIcon: Icons.account_balance_wallet, label: t.app.navigationBudgets, route: '/budget', ), ( icon: Icons.inventory_2_outlined, selectedIcon: Icons.inventory_2, label: t.app.navigationInventory, route: '/inventory', ), ( icon: Icons.bar_chart_outlined, selectedIcon: Icons.bar_chart, label: t.app.navigationReports, route: '/reports', ), ( icon: Icons.settings_outlined, selectedIcon: Icons.settings, label: t.app.navigationSettings, route: '/settings', ), ]; } // Mobile bottom bar items (exactly the four you asked for) List<({IconData icon, String label, String route})> _getMobileTabs( BuildContext context, ) { final t = Translations.of(context); return [ (icon: Icons.dashboard, label: t.app.navigationDashboard, route: '/home'), // “Haushalt (inkl. Budget)” → map to /budget for now (icon: Icons.home, label: 'Haushalt', route: '/budget'), (icon: Icons.inventory_2, label: 'Inventar', route: '/inventory'), (icon: Icons.directions_car, label: 'Auto', route: '/car'), ]; } int _indexForPath(String path, List items, String Function(T) routeOf) { for (var i = 0; i < items.length; i++) { if (path.startsWith(routeOf(items[i]))) return i; } return 0; } void _goForIndex( BuildContext ctx, int i, List items, String Function(T) routeOf, ) { ctx.go(routeOf(items[i])); } @override Widget build(BuildContext context) { final t = Translations.of(context); final width = MediaQuery.of(context).size.width; final isDesktop = width >= _breakpoint; final currentPath = GoRouterState.of(context).matchedLocation; // keep focus on right/content pane on wide layouts if (isDesktop) { WidgetsBinding.instance.addPostFrameCallback((_) { if (mounted && !_contentFocus.hasFocus) _contentFocus.requestFocus(); }); } final appBar = AppBar( title: const _LogoHeader(), // On desktop we use a persistent drawer, so no burger button. leading: isDesktop ? null : Builder( builder: (ctx) => IconButton( icon: const Icon(Icons.menu), onPressed: () => Scaffold.of(ctx).openDrawer(), tooltip: t.app.tooltipMenu, ), ), actions: [ IconButton( tooltip: t.app.tooltipNotifications, onPressed: () {}, icon: const Icon(Icons.notifications_none), ), IconButton( tooltip: t.app.tooltipUserSettings, onPressed: () => context.push('/settings'), icon: const Icon(Icons.account_circle_outlined), ), ], ); if (!isDesktop) { // ------------------- MOBILE: Bottom Navigation ------------------- final tabs = _getMobileTabs(context); final selected = _indexForPath(currentPath, tabs, (it) => it.route); return Scaffold( appBar: appBar, // Keep drawer for mobile? You asked for bottom bar instead — remove drawer. body: SafeArea(child: widget.child), bottomNavigationBar: NavigationBar( selectedIndex: selected, onDestinationSelected: (i) => _goForIndex(context, i, tabs, (it) => it.route), destinations: [ for (final it in tabs) NavigationDestination(icon: Icon(it.icon), label: it.label), ], ), ); } // ------------------- TABLET/DESKTOP: Persistent Drawer ------------------- final items = _getDesktopItems(context); final selected = _indexForPath(currentPath, items, (it) => it.route); return Scaffold( appBar: appBar, body: Row( children: [ // Persistent drawer area SizedBox( width: 300, child: _DesktopDrawer(items: items, selectedIndex: selected), ), const VerticalDivider(width: 1), // Content Expanded( child: SafeArea( child: Focus( focusNode: _contentFocus, autofocus: true, child: widget.child, ), ), ), ], ), ); } } class _DesktopDrawer extends StatelessWidget { final List< ({IconData icon, IconData? selectedIcon, String label, String route}) > items; final int selectedIndex; const _DesktopDrawer({required this.items, required this.selectedIndex}); @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; return Material( elevation: 0, child: SafeArea( child: ListTileTheme( selectedColor: scheme.onSecondaryContainer, selectedTileColor: scheme.secondaryContainer, child: ListView( padding: const EdgeInsets.symmetric(vertical: 8), children: [ const _LogoHeader(), const Divider(), for (var i = 0; i < items.length; i++) ListTile( selected: i == selectedIndex, leading: Icon( i == selectedIndex ? (items[i].selectedIcon ?? items[i].icon) : items[i].icon, ), title: Text(items[i].label), onTap: () => context.go(items[i].route), ), ], ), ), ), ); } } class _AppDrawer extends StatelessWidget { final List< ({IconData icon, IconData? selectedIcon, String label, String route}) > items; final int selectedIndex; const _AppDrawer({required this.items, required this.selectedIndex}); @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; return Drawer( child: SafeArea( child: ListTileTheme( selectedColor: scheme.onSecondaryContainer, selectedTileColor: scheme.secondaryContainer, child: ListView( padding: const EdgeInsets.symmetric(vertical: 8), children: [ const _LogoHeader(), const Divider(), for (var i = 0; i < items.length; i++) ListTile( selected: i == selectedIndex, leading: Icon( i == selectedIndex ? (items[i].selectedIcon ?? items[i].icon) : items[i].icon, ), title: Text(items[i].label), onTap: () { Navigator.of(context).maybePop(); context.go(items[i].route); }, ), const Divider(), ListTile( leading: const Icon(Icons.settings_outlined), title: Text(Translations.of(context).app.drawerSettings), onTap: () { Navigator.of(context).maybePop(); context.go('/settings'); }, ), ], ), ), ), ); } } class _LogoHeader extends StatelessWidget { const _LogoHeader(); @override Widget build(BuildContext context) { return const Padding( padding: EdgeInsets.all(16), child: Row( children: [ Icon(Icons.account_balance_wallet, size: 28), SizedBox(width: 8), ], ), ); } }