import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../features/auth/data/auth_providers.dart'; import '../../features/recipes/data/recipes_grid_provider.dart'; const _adminDestination = _AppDestination( path: '/admin', title: 'Admin', icon: Icons.admin_panel_settings_outlined, label: 'Admin', ); class AppShell extends ConsumerWidget { final String location; final Widget child; const AppShell({ super.key, required this.location, required this.child, }); static const _baseDestinations = [ _AppDestination( path: '/recipes', title: 'Recept', icon: Icons.restaurant_menu, label: 'Recept', ), _AppDestination( path: '/inventory', title: 'Inventarie', icon: Icons.inventory_2_outlined, label: 'Inventarie', ), _AppDestination( path: '/matsedel', title: 'Matsedel', icon: Icons.calendar_month_outlined, label: 'Matsedel', ), _AppDestination( path: '/baslager', title: 'Baslager', icon: Icons.storefront_outlined, label: 'Baslager', ), _AppDestination( path: '/import', title: 'Importera', icon: Icons.upload_file_outlined, label: 'Importera', ), _AppDestination( path: '/profile', title: 'Profil', icon: Icons.person, label: 'Profil', ), ]; List<_AppDestination> _destinations(bool isAdmin) => [ ..._baseDestinations, if (isAdmin) _adminDestination, ]; int _selectedIndex(List<_AppDestination> destinations) { final index = destinations.indexWhere( (destination) => location.startsWith(destination.path), ); return index < 0 ? 0 : index; } @override Widget build(BuildContext context, WidgetRef ref) { final isAdmin = ref.watch(isAdminProvider); final dests = _destinations(isAdmin); final selectedIndex = _selectedIndex(dests); final selectedDestination = dests[selectedIndex]; final isWide = MediaQuery.of(context).size.width >= 900; Future logout() async { await ref.read(authStateProvider.notifier).logout(); if (context.mounted) { context.go('/login'); } } void navigateTo(int index) { final target = dests[index].path; if (target != location && context.mounted) { context.go(target); } } final isRecipesRoute = location.startsWith('/recipes') && !location.startsWith('/recipes/'); return Scaffold( appBar: AppBar( title: Text(selectedDestination.title), actions: [ if (isRecipesRoute) Consumer( builder: (context, ref, child) { final view = ref.watch(recipesViewProvider).maybeWhen( data: (v) => v, orElse: () => (mode: RecipesViewMode.grid, columns: 2), ); return Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( tooltip: view.mode == RecipesViewMode.grid ? 'Visa som lista' : 'Visa som grid', icon: Icon(view.mode == RecipesViewMode.grid ? Icons.view_list : Icons.grid_view), onPressed: () => ref.read(recipesViewProvider.notifier).toggleMode(), ), if (view.mode == RecipesViewMode.grid) PopupMenuButton( icon: const Icon(Icons.grid_view), tooltip: 'Välj antal kolumner', onSelected: (columns) => ref.read(recipesViewProvider.notifier).setColumns(columns), itemBuilder: (context) => const [ PopupMenuItem(value: 2, child: Text('2 kolumner')), PopupMenuItem(value: 4, child: Text('4 kolumner')), PopupMenuItem(value: 6, child: Text('6 kolumner')), PopupMenuItem(value: 8, child: Text('8 kolumner')), ], ), ], ); }, ), IconButton( tooltip: 'Logga ut', icon: const Icon(Icons.logout), onPressed: logout, ), ], ), body: isWide ? Row( children: [ NavigationRail( selectedIndex: selectedIndex, onDestinationSelected: navigateTo, labelType: NavigationRailLabelType.all, destinations: dests .map( (destination) => NavigationRailDestination( icon: Icon(destination.icon), label: Text(destination.label), ), ) .toList(), ), const VerticalDivider(width: 1), Expanded(child: child), ], ) : child, bottomNavigationBar: isWide ? null : NavigationBar( selectedIndex: selectedIndex, onDestinationSelected: navigateTo, destinations: dests .map( (destination) => NavigationDestination( icon: Icon(destination.icon), label: destination.label, ), ) .toList(), ), ); } } class _AppDestination { final String path; final String title; final IconData icon; final String label; const _AppDestination({ required this.path, required this.title, required this.icon, required this.label, }); }