import 'package:flutter/material.dart'; import 'package:flux/core/routes/routes.dart'; import 'package:flux/core/utils/extensions.dart'; import 'package:go_router/go_router.dart'; // ========================================== // 1. IL GUSCIO (QUELLO CHE PASSI AL ROUTER) // ========================================== class AppShell extends StatelessWidget { final Widget child; const AppShell({super.key, required this.child}); @override Widget build(BuildContext context) { // Breakpoint a 900px: sotto è Mobile/Tablet (Drawer), sopra è Desktop (Sidebar) final isDesktop = MediaQuery.sizeOf(context).width >= 900; final currentPath = GoRouterState.of(context).uri.path; return Scaffold( // Su mobile usiamo un'AppBar minimale per avere il bottone "Hamburger" nativo appBar: isDesktop ? null : AppBar( title: const Text( "FLUX", style: TextStyle(fontWeight: FontWeight.bold), ), centerTitle: true, elevation: 0, backgroundColor: Theme.of(context).colorScheme.surface, surfaceTintColor: Colors.transparent, ), drawer: isDesktop ? null : Drawer( // Su mobile inietta il menu qui! child: AppMenu(currentPath: currentPath, isDrawer: true), ), body: isDesktop ? Row( children: [ // Su desktop inietta il menu a sinistra! AppMenu(currentPath: currentPath, isDrawer: false), const VerticalDivider(thickness: 1, width: 1), Expanded(child: child), ], ) : child, // Su mobile il child prende tutto lo schermo sotto l'AppBar ); } } class AppMenu extends StatefulWidget { final String currentPath; // Lo usiamo ancora per capire cosa accendere final bool isDrawer; const AppMenu({super.key, required this.currentPath, required this.isDrawer}); @override State createState() => _AppMenuState(); } class _AppMenuState extends State { bool _isCollapsed = false; @override Widget build(BuildContext context) { final theme = Theme.of(context); final bool effectivelyCollapsed = _isCollapsed && !widget.isDrawer; return AnimatedContainer( duration: const Duration(milliseconds: 200), curve: Curves.easeInOut, width: effectivelyCollapsed ? 72 : 260, child: SafeArea( child: Column( children: [ // --- HEADER --- Container( height: 80, padding: const EdgeInsets.symmetric(horizontal: 20.0), alignment: effectivelyCollapsed ? Alignment.center : Alignment.centerLeft, child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.bolt, color: theme.colorScheme.primary, size: 32), if (!effectivelyCollapsed) ...[ const SizedBox(width: 12), Text( "FLUX", style: theme.textTheme.titleLarge?.copyWith( fontWeight: FontWeight.bold, ), ), ], ], ), ), // --- VOCI DI MENU --- Expanded( child: SingleChildScrollView( scrollDirection: Axis.horizontal, physics: const NeverScrollableScrollPhysics(), child: SizedBox( width: effectivelyCollapsed ? 72 : 260, child: ListView( padding: const EdgeInsets.symmetric(horizontal: 8.0), children: [ _buildRouteItem( title: context.l10n.commonDashboard, icon: Icons.dashboard_outlined, routeName: Routes.home, // <--- Usiamo la tua costante! pathToCheck: '/', // Il path da controllare per colorarlo isCollapsed: effectivelyCollapsed, ), const SizedBox(height: 8), // --- IL MENU GERARCHICO (ANAGRAFICHE) --- _buildHierarchicalItem( title: context.l10n.commonMasterData, icon: Icons.folder_special_outlined, basePathToCheck: '/master-data', // Se il path inizia così, espandi isCollapsed: effectivelyCollapsed, subItems: [ _SubMenuItem( "Clienti", Routes.customers, '/master-data/customers', ), _SubMenuItem( "Fornitori", Routes.providers, '/master-data/providers', ), _SubMenuItem( "Prodotti", Routes.products, '/master-data/products', ), _SubMenuItem( "Staff", Routes.staff, '/master-data/staff', ), ], ), const SizedBox(height: 8), _buildRouteItem( title: context.l10n.commonSettings, icon: Icons.settings_outlined, routeName: Routes.settings, pathToCheck: '/settings', isCollapsed: effectivelyCollapsed, ), ], ), ), ), ), // --- PULSANTE TOGGLE (Solo Desktop) --- if (!widget.isDrawer) Padding( padding: const EdgeInsets.all(8.0), child: IconButton( tooltip: _isCollapsed ? 'Espandi Menu' : 'Riduci Menu', icon: Icon( _isCollapsed ? Icons.keyboard_double_arrow_right : Icons.keyboard_double_arrow_left, color: theme.iconTheme.color?.withValues(alpha: 0.5), ), onPressed: () { setState(() { _isCollapsed = !_isCollapsed; }); }, ), ), ], ), ), ); } // ========================================== // WIDGET HELPER AGGIORNATI // ========================================== Widget _buildRouteItem({ required String title, required IconData icon, required String routeName, required String pathToCheck, required bool isCollapsed, }) { final isSelected = widget.currentPath == pathToCheck; final theme = Theme.of(context); if (isCollapsed) { return Tooltip( message: title, preferBelow: false, child: InkWell( onTap: () { if (widget.isDrawer) Navigator.pop(context); context.goNamed(routeName); // <--- goNamed! }, borderRadius: BorderRadius.circular(8), child: Container( height: 48, alignment: Alignment.center, decoration: BoxDecoration( color: isSelected ? theme.colorScheme.primaryContainer.withValues(alpha: 0.4) : Colors.transparent, borderRadius: BorderRadius.circular(8), ), child: Icon( icon, color: isSelected ? theme.colorScheme.primary : null, ), ), ), ); } return ListTile( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), selectedTileColor: theme.colorScheme.primaryContainer.withValues( alpha: 0.4, ), selected: isSelected, leading: Icon(icon, color: isSelected ? theme.colorScheme.primary : null), title: Text( title, style: TextStyle( fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, ), maxLines: 1, overflow: TextOverflow.clip, ), onTap: () { if (widget.isDrawer) Navigator.pop(context); context.goNamed(routeName); // <--- goNamed! }, ); } Widget _buildHierarchicalItem({ required String title, required IconData icon, required String basePathToCheck, required bool isCollapsed, required List<_SubMenuItem> subItems, }) { final isSelected = widget.currentPath.startsWith(basePathToCheck); final theme = Theme.of(context); if (isCollapsed) { return PopupMenuButton( tooltip: title, offset: const Offset(60, 0), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), onSelected: (routeName) { // Il routeName arriva dal value del menu if (widget.isDrawer) Navigator.pop(context); context.goNamed(routeName); // <--- goNamed! }, itemBuilder: (context) => subItems .map( (item) => PopupMenuItem( value: item .routeName, // Passiamo il nome della rotta (Routes.customers) child: Text( item.title, style: TextStyle( fontWeight: widget.currentPath == item.pathToCheck ? FontWeight.bold : FontWeight.normal, color: widget.currentPath == item.pathToCheck ? theme.colorScheme.primary : null, ), ), ), ) .toList(), child: Container( height: 48, alignment: Alignment.center, decoration: BoxDecoration( color: isSelected ? theme.colorScheme.primaryContainer.withValues(alpha: 0.4) : Colors.transparent, borderRadius: BorderRadius.circular(8), ), child: Icon( icon, color: isSelected ? theme.colorScheme.primary : null, ), ), ); } return Theme( data: theme.copyWith(dividerColor: Colors.transparent), child: ExpansionTile( initiallyExpanded: isSelected, maintainState: true, tilePadding: const EdgeInsets.symmetric(horizontal: 16), leading: Icon( icon, color: isSelected ? theme.colorScheme.primary : null, ), title: Text( title, style: TextStyle( fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, ), maxLines: 1, overflow: TextOverflow.clip, ), children: subItems.map((item) { final isSubSelected = widget.currentPath == item.pathToCheck; return Padding( padding: const EdgeInsets.only(left: 32.0, bottom: 4.0), child: ListTile( dense: true, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), selectedTileColor: theme.colorScheme.primaryContainer.withValues( alpha: 0.2, ), selected: isSubSelected, title: Text( item.title, style: TextStyle( fontWeight: isSubSelected ? FontWeight.bold : FontWeight.normal, color: isSubSelected ? theme.colorScheme.primary : theme.textTheme.bodyMedium?.color, ), maxLines: 1, overflow: TextOverflow.clip, ), onTap: () { if (widget.isDrawer) Navigator.pop(context); context.goNamed(item.routeName); // <--- goNamed! }, ), ); }).toList(), ), ); } } // Struttura dati per le voci dei sottomenu aggiornata class _SubMenuItem { final String title; final String routeName; // Es: Routes.customers final String pathToCheck; // Es: '/master-data/customers' _SubMenuItem(this.title, this.routeName, this.pathToCheck); }