| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- import 'package:flutter/material.dart';
- import 'package:flutter_riverpod/flutter_riverpod.dart';
- import 'package:go_router/go_router.dart';
- import '../../providers/auth_provider.dart';
- import '../../core/responsive.dart';
- class PersistentSidebar extends ConsumerWidget {
- final VoidCallback? onExportDatabase;
- const PersistentSidebar({super.key, this.onExportDatabase});
- @override
- Widget build(BuildContext context, WidgetRef ref) {
- final agente = ref.watch(authProvider).agente;
- final currentPath = GoRouterState.of(context).matchedLocation;
- return Container(
- width: ResponsiveBreakpoints.sidebarWidth,
- height: double.infinity,
- decoration: BoxDecoration(
- color: Theme.of(context).colorScheme.surface,
- border: Border(
- right: BorderSide(
- color: Theme.of(context).colorScheme.outlineVariant,
- ),
- ),
- ),
- child: Column(
- children: [
- // Brand
- Padding(
- padding: const EdgeInsets.fromLTRB(24, 24, 24, 32),
- child: Align(
- alignment: Alignment.centerLeft,
- child: Text(
- 'PowerAge',
- style: Theme.of(context).textTheme.headlineMedium?.copyWith(
- color: Theme.of(context).colorScheme.secondary,
- fontWeight: FontWeight.bold,
- ),
- ),
- ),
- ),
- // Agent profile
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 24),
- child: Row(
- children: [
- CircleAvatar(
- radius: 24,
- backgroundColor:
- Theme.of(context).colorScheme.secondaryContainer,
- child: Text(
- agente?.codAgente ?? '??',
- style: TextStyle(
- color:
- Theme.of(context).colorScheme.onSecondaryContainer,
- fontWeight: FontWeight.bold,
- fontSize: 16,
- ),
- ),
- ),
- const SizedBox(width: 16),
- Expanded(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- agente?.codAgente ?? '',
- style:
- Theme.of(context).textTheme.titleLarge?.copyWith(
- fontWeight: FontWeight.bold,
- ),
- overflow: TextOverflow.ellipsis,
- ),
- Text(
- agente?.ragioneSociale ?? '',
- style: Theme.of(context).textTheme.bodyMedium
- ?.copyWith(
- color: Theme.of(
- context,
- ).colorScheme.onSurfaceVariant,
- ),
- overflow: TextOverflow.ellipsis,
- ),
- ],
- ),
- ),
- ],
- ),
- ),
- const SizedBox(height: 32),
- // Nav items
- Expanded(
- child: ListView(
- padding: const EdgeInsets.symmetric(horizontal: 8),
- children: [
- _NavItem(
- icon: Icons.analytics_outlined,
- label: 'Dashboard',
- selected: currentPath == '/dashboard',
- onTap: () => context.go('/dashboard'),
- ),
- _NavItem(
- icon: Icons.shopping_cart_outlined,
- label: 'Ordini',
- selected: currentPath.startsWith('/dashboard/orders'),
- onTap: () => context.go('/dashboard/orders'),
- ),
- _NavItem(
- icon: Icons.groups_outlined,
- label: 'Clienti',
- selected: currentPath.startsWith('/dashboard/customers'),
- onTap: () => context.go('/dashboard/customers'),
- ),
- _NavItem(
- icon: Icons.menu_book_outlined,
- label: 'Catalogo',
- selected: currentPath == '/dashboard/catalog',
- onTap: () => context.go('/dashboard/catalog'),
- ),
- _NavItem(
- icon: Icons.local_offer_outlined,
- label: 'Promozioni',
- selected: currentPath == '/dashboard/promotions',
- onTap: () => context.go('/dashboard/promotions'),
- ),
- _NavItem(
- icon: Icons.event_note_outlined,
- label: 'Scadenze',
- selected: currentPath == '/dashboard/payments',
- onTap: () => context.go('/dashboard/payments'),
- ),
- _NavItem(
- icon: Icons.bar_chart_outlined,
- label: 'Statistiche',
- selected: currentPath == '/dashboard/statistics',
- onTap: () => context.go('/dashboard/statistics'),
- ),
- _NavItem(
- icon: Icons.sync_outlined,
- label: 'Sincronizzazione',
- selected: currentPath.startsWith('/dashboard/sync'),
- onTap: () => context.go('/dashboard/sync'),
- ),
- ],
- ),
- ),
- // Bottom actions
- Container(
- padding: const EdgeInsets.all(8),
- decoration: BoxDecoration(
- border: Border(
- top: BorderSide(
- color: Theme.of(
- context,
- ).colorScheme.outlineVariant.withAlpha(80),
- ),
- ),
- ),
- child: Column(
- children: [
- _NavItem(
- icon: Icons.download_outlined,
- label: 'Esporta database',
- onTap: onExportDatabase,
- ),
- _NavItem(
- icon: Icons.person_search_outlined,
- label: 'Cambia agente',
- onTap: () => context.go('/dashboard/switch-agent'),
- ),
- _NavItem(
- icon: Icons.logout,
- label: 'Logout',
- iconColor: Theme.of(context).colorScheme.error,
- textColor: Theme.of(context).colorScheme.error,
- onTap: () =>
- ref.read(authProvider.notifier).logout(),
- ),
- Padding(
- padding: const EdgeInsets.fromLTRB(16, 8, 16, 4),
- child: Align(
- alignment: Alignment.centerLeft,
- child: Text(
- 'v2.1.0',
- style: Theme.of(context).textTheme.labelSmall?.copyWith(
- color: Theme.of(context).colorScheme.outline,
- ),
- ),
- ),
- ),
- ],
- ),
- ),
- ],
- ),
- );
- }
- }
- class _NavItem extends StatelessWidget {
- final IconData icon;
- final String label;
- final bool selected;
- final VoidCallback? onTap;
- final Color? iconColor;
- final Color? textColor;
- const _NavItem({
- required this.icon,
- required this.label,
- this.selected = false,
- this.onTap,
- this.iconColor,
- this.textColor,
- });
- @override
- Widget build(BuildContext context) {
- final effectiveIconColor =
- iconColor ??
- (selected
- ? Theme.of(context).colorScheme.onSecondaryContainer
- : Theme.of(context).colorScheme.onSurfaceVariant);
- final effectiveTextColor =
- textColor ??
- (selected
- ? Theme.of(context).colorScheme.onSecondaryContainer
- : Theme.of(context).colorScheme.onSurfaceVariant);
- return Padding(
- padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
- child: Material(
- color: selected
- ? Theme.of(context).colorScheme.surfaceContainerHighest
- : Colors.transparent,
- borderRadius: BorderRadius.circular(12),
- child: InkWell(
- borderRadius: BorderRadius.circular(12),
- onTap: onTap,
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
- child: Row(
- children: [
- Icon(icon, size: 22, color: effectiveIconColor),
- const SizedBox(width: 16),
- Expanded(
- child: Text(
- label,
- style: TextStyle(
- color: effectiveTextColor,
- fontWeight: selected ? FontWeight.bold : FontWeight.w500,
- fontSize: 14,
- ),
- ),
- ),
- ],
- ),
- ),
- ),
- ),
- );
- }
- }
|