app shell
This commit is contained in:
@@ -1,97 +1,375 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flux/core/routes/routes.dart';
|
||||||
import 'package:flux/core/utils/extensions.dart';
|
import 'package:flux/core/utils/extensions.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// 1. IL GUSCIO (QUELLO CHE PASSI AL ROUTER)
|
||||||
|
// ==========================================
|
||||||
class AppShell extends StatelessWidget {
|
class AppShell extends StatelessWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
const AppShell({super.key, required this.child});
|
const AppShell({super.key, required this.child});
|
||||||
|
|
||||||
// Calcoliamo l'indice attivo in base all'URL corrente!
|
|
||||||
int _calculateSelectedIndex(BuildContext context) {
|
|
||||||
final String location = GoRouterState.of(context).uri.path;
|
|
||||||
if (location.startsWith('/master-data')) return 1;
|
|
||||||
if (location.startsWith('/settings')) return 2;
|
|
||||||
return 0; // Default: Dashboard
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onItemTapped(int index, BuildContext context) {
|
|
||||||
switch (index) {
|
|
||||||
case 0:
|
|
||||||
context.go('/');
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
context.go('/master-data');
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
context.go('/settings');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final currentIndex = _calculateSelectedIndex(context);
|
// Breakpoint a 900px: sotto è Mobile/Tablet (Drawer), sopra è Desktop (Sidebar)
|
||||||
// Breakpoint: se lo schermo è più largo di 600px, usiamo la Rail laterale
|
final isDesktop = MediaQuery.sizeOf(context).width >= 900;
|
||||||
final isDesktop = MediaQuery.sizeOf(context).width >= 600;
|
final currentPath = GoRouterState.of(context).uri.path;
|
||||||
|
|
||||||
return Scaffold(
|
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
|
body: isDesktop
|
||||||
? Row(
|
? Row(
|
||||||
children: [
|
children: [
|
||||||
NavigationRail(
|
// Su desktop inietta il menu a sinistra!
|
||||||
selectedIndex: currentIndex,
|
AppMenu(currentPath: currentPath, isDrawer: false),
|
||||||
onDestinationSelected: (index) =>
|
|
||||||
_onItemTapped(index, context),
|
|
||||||
labelType: NavigationRailLabelType.all,
|
|
||||||
destinations: [
|
|
||||||
NavigationRailDestination(
|
|
||||||
icon: Icon(Icons.dashboard_outlined),
|
|
||||||
selectedIcon: Icon(Icons.dashboard),
|
|
||||||
label: Text(context.l10n.commonDashboard),
|
|
||||||
),
|
|
||||||
NavigationRailDestination(
|
|
||||||
icon: Icon(Icons.folder_special_outlined),
|
|
||||||
selectedIcon: Icon(Icons.folder_special),
|
|
||||||
label: Text(context.l10n.commonMasterData),
|
|
||||||
),
|
|
||||||
NavigationRailDestination(
|
|
||||||
icon: Icon(Icons.settings_outlined),
|
|
||||||
selectedIcon: Icon(Icons.settings),
|
|
||||||
label: Text(context.l10n.commonSettings),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const VerticalDivider(thickness: 1, width: 1),
|
const VerticalDivider(thickness: 1, width: 1),
|
||||||
// Il contenuto della pagina
|
|
||||||
Expanded(child: child),
|
Expanded(child: child),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: child, // Su mobile il contenuto prende tutto lo schermo...
|
: child, // Su mobile il child prende tutto lo schermo sotto l'AppBar
|
||||||
// ... e mettiamo la barra in basso!
|
|
||||||
bottomNavigationBar: isDesktop
|
|
||||||
? null
|
|
||||||
: NavigationBar(
|
|
||||||
selectedIndex: currentIndex,
|
|
||||||
onDestinationSelected: (index) => _onItemTapped(index, context),
|
|
||||||
destinations: [
|
|
||||||
NavigationDestination(
|
|
||||||
icon: Icon(Icons.dashboard_outlined),
|
|
||||||
selectedIcon: Icon(Icons.dashboard),
|
|
||||||
label: context.l10n.commonDashboard,
|
|
||||||
),
|
|
||||||
NavigationDestination(
|
|
||||||
icon: Icon(Icons.folder_special_outlined),
|
|
||||||
selectedIcon: Icon(Icons.folder_special),
|
|
||||||
label: context.l10n.commonMasterData,
|
|
||||||
),
|
|
||||||
NavigationDestination(
|
|
||||||
icon: Icon(Icons.settings_outlined),
|
|
||||||
selectedIcon: Icon(Icons.settings),
|
|
||||||
label: context.l10n.commonSettings,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<AppMenu> createState() => _AppMenuState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AppMenuState extends State<AppMenu> {
|
||||||
|
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<String>(
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -126,78 +126,89 @@ class AppRouter {
|
|||||||
ShellRoute(
|
ShellRoute(
|
||||||
builder: (context, state, child) => AppShell(child: child),
|
builder: (context, state, child) => AppShell(child: child),
|
||||||
routes: [
|
routes: [
|
||||||
|
// ==========================================
|
||||||
// 1. DASHBOARD
|
// 1. DASHBOARD
|
||||||
|
// ==========================================
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/',
|
path: '/',
|
||||||
name: Routes.home,
|
name: Routes.home,
|
||||||
builder: (context, state) => const HomeScreen(),
|
builder: (context, state) => const HomeScreen(),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
// 2. HUB ANAGRAFICHE E SOTTO-ROTTE
|
// 2. HUB ANAGRAFICHE E SOTTO-ROTTE
|
||||||
|
// ==========================================
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/master-data',
|
path: '/master-data',
|
||||||
name: Routes.masterData,
|
name: Routes.masterData,
|
||||||
builder: (context, state) => const MasterDataHubScreen(),
|
builder: (context, state) => const MasterDataHubScreen(),
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: 'products', // Diventa /master-data/products
|
path:
|
||||||
|
'customers', // Niente slash iniziale per le sottorotte! -> /master-data/customers
|
||||||
|
name: Routes.customers,
|
||||||
|
builder: (context, state) => const CustomersListScreen(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'providers', // -> /master-data/providers
|
||||||
|
name: Routes.providers,
|
||||||
|
builder: (context, state) => const ProviderListScreen(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'products', // -> /master-data/products
|
||||||
name: Routes.products,
|
name: Routes.products,
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
context.read<ProductsCubit>().refreshCubit();
|
context.read<ProductsCubit>().refreshCubit();
|
||||||
|
|
||||||
return const ProductsScreen();
|
return const ProductsScreen();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: 'company-settings',
|
path: 'staff', // -> /master-data/staff
|
||||||
|
name: Routes.staff,
|
||||||
|
builder: (context, state) => const StaffScreen(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path:
|
||||||
|
'stores', // Sistemata l'inversione path/name -> /master-data/stores
|
||||||
|
name: Routes.stores,
|
||||||
|
builder: (context, state) => const StoresScreen(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'company-settings', // -> /master-data/company-settings
|
||||||
name: Routes.companySettings,
|
name: Routes.companySettings,
|
||||||
builder: (context, state) => BlocProvider(
|
builder: (context, state) => BlocProvider(
|
||||||
create: (context) => CompanySettingsCubit(),
|
create: (context) => CompanySettingsCubit(),
|
||||||
child: const CompanySettingsScreen(),
|
child: const CompanySettingsScreen(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
GoRoute(
|
|
||||||
path: 'staff',
|
|
||||||
name: Routes.staff, // Diventa /master-data/staff
|
|
||||||
builder: (context, state) => const StaffScreen(),
|
|
||||||
),
|
|
||||||
GoRoute(
|
|
||||||
path: Routes.stores,
|
|
||||||
name: 'stores', // Diventa /master-data/stores
|
|
||||||
builder: (context, state) => const StoresScreen(),
|
|
||||||
),
|
|
||||||
GoRoute(
|
|
||||||
path: '/providers',
|
|
||||||
name: Routes.providers,
|
|
||||||
builder: (context, state) => const ProviderListScreen(),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
// 3. IMPOSTAZIONI
|
// 3. IMPOSTAZIONI
|
||||||
|
// ==========================================
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/settings',
|
path: '/settings',
|
||||||
name: Routes.settings,
|
name: Routes.settings,
|
||||||
builder: (context, state) => const SettingsScreen(),
|
builder: (context, state) => const SettingsScreen(),
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: 'themeSettings',
|
path: 'themeSettings', // -> /settings/themeSettings
|
||||||
name: Routes.themeSettings,
|
name: Routes.themeSettings,
|
||||||
builder: (context, state) => const ThemeSettingsView(),
|
builder: (context, state) => const ThemeSettingsView(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// 4. SCHERMATE PRINCIPALI EXTRA NELLA SHELL
|
||||||
|
// (Accessibili ad es. dalla dashboard, mantengono la sidebar)
|
||||||
|
// ==========================================
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/operations',
|
path: '/operations',
|
||||||
name: Routes.operations,
|
name: Routes.operations,
|
||||||
builder: (context, state) => const OperationListScreen(),
|
builder: (context, state) => const OperationListScreen(),
|
||||||
),
|
),
|
||||||
GoRoute(
|
|
||||||
path: '/customers',
|
|
||||||
name: Routes.customers,
|
|
||||||
builder: (context, state) =>
|
|
||||||
const CustomersListScreen(), // O come si chiama il tuo widget della lista!
|
|
||||||
),
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/tickets',
|
path: '/tickets',
|
||||||
name: Routes.tickets,
|
name: Routes.tickets,
|
||||||
|
|||||||
Reference in New Issue
Block a user