diff --git a/lib/core/routes/app_router.dart b/lib/core/routes/app_router.dart index f07a855..de19dd0 100644 --- a/lib/core/routes/app_router.dart +++ b/lib/core/routes/app_router.dart @@ -2,8 +2,9 @@ import 'package:flutter/material.dart'; import 'package:flux/core/blocs/session/session_bloc.dart'; import 'package:flux/features/auth/ui/auth_screen.dart'; import 'package:flux/features/company/ui/create_company_screen.dart'; -import 'package:flux/features/dashboard/ui/dashboard_screen.dart'; +import 'package:flux/features/home/ui/dashboard_content.dart'; import 'package:flux/features/store/ui/create_store_screen.dart'; +import 'package:flux/ui/home_screen.dart'; import 'package:go_router/go_router.dart'; import 'dart:async'; @@ -33,8 +34,9 @@ class AppRouter { if (isUnauthenticated && location != '/login') return '/login'; - if (isNoCompany && location != '/create-company') + if (isNoCompany && location != '/create-company') { return '/create-company'; + } if (isNoStore && location != '/create-store') return '/create-store'; @@ -44,10 +46,7 @@ class AppRouter { return null; }, routes: [ - GoRoute( - path: '/', - builder: (context, state) => const DashboardScreen(), - ), + GoRoute(path: '/', builder: (context, state) => const HomeScreen()), GoRoute( path: '/login', builder: (context, state) => const AuthScreen(), diff --git a/lib/features/dashboard/ui/dashboard_screen.dart b/lib/features/home/ui/dashboard_content.dart similarity index 53% rename from lib/features/dashboard/ui/dashboard_screen.dart rename to lib/features/home/ui/dashboard_content.dart index 0c488a6..ce5af56 100644 --- a/lib/features/dashboard/ui/dashboard_screen.dart +++ b/lib/features/home/ui/dashboard_content.dart @@ -3,8 +3,10 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flux/core/blocs/session/session_bloc.dart'; import 'package:flux/core/theme/theme.dart'; -class DashboardScreen extends StatelessWidget { - const DashboardScreen({super.key}); +class DashboardContent extends StatelessWidget { + final bool? isLargeScreen; + + const DashboardContent({super.key, this.isLargeScreen}); @override Widget build(BuildContext context) { @@ -38,21 +40,29 @@ class DashboardScreen extends StatelessWidget { ), SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildWelcomeHeader(context, company?.ragioneSociale), - const SizedBox(height: 30), - _SectionTitle(title: 'AZIONI RAPIDE'), - const SizedBox(height: 16), - _buildGridActions(context), - const SizedBox(height: 32), - _SectionTitle(title: 'STATO NEGOZIO'), - const SizedBox(height: 16), - _buildInfoCard(context, store), - ], + child: Center( + child: Container( + constraints: const BoxConstraints( + maxWidth: 1200, + ), // Larghezza massima "confortevole" + padding: const EdgeInsets.all(24.0), + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildWelcomeHeader(context, company?.ragioneSociale), + const SizedBox(height: 30), + _SectionTitle(title: 'AZIONI RAPIDE'), + const SizedBox(height: 16), + _buildGridActions(context), + const SizedBox(height: 32), + _SectionTitle(title: 'STATO NEGOZIO'), + const SizedBox(height: 16), + _buildInfoCard(context, store), + ], + ), + ), ), ), ), @@ -84,39 +94,71 @@ class DashboardScreen extends StatelessWidget { } Widget _buildGridActions(BuildContext context) { - return GridView.count( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - crossAxisCount: 2, - mainAxisSpacing: 16, - crossAxisSpacing: 16, - childAspectRatio: 1.5, - children: [ - _ActionCard( - label: 'Nuova Op', - icon: Icons.add_task_rounded, - color: context.accent, - onTap: () {}, - ), - _ActionCard( - label: 'Clienti', - icon: Icons.people_alt_rounded, - color: Colors.orange, - onTap: () {}, - ), - _ActionCard( - label: 'Campagne', - icon: Icons.campaign_rounded, - color: Colors.purple, - onTap: () {}, - ), - _ActionCard( - label: 'Report', - icon: Icons.analytics_rounded, - color: Colors.teal, - onTap: () {}, - ), - ], + return LayoutBuilder( + builder: (context, constraints) { + // Calcoliamo il numero di colonne in base alla larghezza + // Sotto i 600px (mobile): 2 colonne + // Tra 600 e 1000px (tablet): 3 o 4 colonne + // Sopra i 1000px (desktop): 6 colonne + int crossAxisCount = 2; + if (constraints.maxWidth > 1000) { + crossAxisCount = 6; + } else if (constraints.maxWidth > 600) { + crossAxisCount = 4; + } + + return GridView.count( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + crossAxisCount: crossAxisCount, + mainAxisSpacing: 16, + crossAxisSpacing: 16, + // Su desktop rendiamo i tasti un po' più squadrati (1.0) + // Su mobile manteniamo il rettangolo (1.5) + childAspectRatio: constraints.maxWidth > 600 ? 1.2 : 1.5, + children: [ + _ActionCard( + label: 'Nuova Op', + icon: Icons.add_task_rounded, + color: context.accent, + onTap: () {}, + ), + _ActionCard( + label: 'Clienti', + icon: Icons.people_alt_rounded, + color: Colors.orange, + onTap: () {}, + ), + _ActionCard( + label: 'Campagne', + icon: Icons.campaign_rounded, + color: Colors.purple, + onTap: () {}, + ), + _ActionCard( + label: 'Report', + icon: Icons.analytics_rounded, + color: Colors.teal, + onTap: () {}, + ), + // Se siamo su desktop, possiamo aggiungere altri slot senza affollare + if (constraints.maxWidth > 600) ...[ + _ActionCard( + label: 'Impostazioni', + icon: Icons.settings, + color: Colors.grey, + onTap: () {}, + ), + _ActionCard( + label: 'Supporto', + icon: Icons.help_outline, + color: Colors.blueGrey, + onTap: () {}, + ), + ], + ], + ); + }, ); } diff --git a/lib/features/home/ui/home_screen.dart b/lib/features/home/ui/home_screen.dart new file mode 100644 index 0000000..e24d4f4 --- /dev/null +++ b/lib/features/home/ui/home_screen.dart @@ -0,0 +1,128 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flux/core/blocs/session/session_bloc.dart'; +import 'package:flux/core/theme/theme.dart'; +import 'package:flux/features/home/ui/dashboard_content.dart'; + +class HomeScreen extends StatefulWidget { + const HomeScreen({super.key}); + + @override + State createState() => _HomeScreenState(); +} + +class _HomeScreenState extends State { + int _selectedIndex = 0; + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return LayoutBuilder( + builder: (context, constraints) { + // Definiamo se siamo su uno schermo "Large" (es. sopra i 900px) + final bool isLargeScreen = constraints.maxWidth > 900; + + return Scaffold( + body: Row( + children: [ + // --- SIDEBAR (Solo per schermi grandi) --- + if (isLargeScreen) + NavigationRail( + selectedIndex: _selectedIndex, + onDestinationSelected: (int index) { + setState(() => _selectedIndex = index); + }, + extended: + constraints.maxWidth > + 1200, // Si allarga se c'è molto spazio + labelType: constraints.maxWidth > 1200 + ? NavigationRailLabelType.none + : NavigationRailLabelType.all, + leading: _buildRailHeader(constraints.maxWidth > 1200), + destinations: const [ + NavigationRailDestination( + icon: Icon(Icons.dashboard_outlined), + selectedIcon: Icon(Icons.dashboard), + label: Text('Dashboard'), + ), + NavigationRailDestination( + icon: Icon(Icons.people_outlined), + selectedIcon: Icon(Icons.people), + label: Text('Clienti'), + ), + NavigationRailDestination( + icon: Icon(Icons.receipt_long_outlined), + selectedIcon: Icon(Icons.receipt_long), + label: Text('Operazioni'), + ), + ], + ), + + // --- CONTENUTO PRINCIPALE --- + Expanded( + child: _buildMainContent(context, state, isLargeScreen), + ), + ], + ), + // --- BOTTOM NAVIGATION (Solo per Mobile) --- + bottomNavigationBar: isLargeScreen + ? null + : BottomNavigationBar( + currentIndex: _selectedIndex, + onTap: (index) => setState(() => _selectedIndex = index), + items: const [ + BottomNavigationBarItem( + icon: Icon(Icons.dashboard), + label: 'Home', + ), + BottomNavigationBarItem( + icon: Icon(Icons.people), + label: 'Clienti', + ), + BottomNavigationBarItem( + icon: Icon(Icons.receipt_long), + label: 'Ops', + ), + ], + ), + ); + }, + ); + }, + ); + } + + // Header per la Sidebar (Logo o Icona) + Widget _buildRailHeader(bool isExtended) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 24), + child: isExtended + ? Text( + 'FLUX', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 24, + color: context.accent, + ), + ) + : Icon(Icons.bolt, color: context.accent, size: 32), + ); + } + + Widget _buildMainContent( + BuildContext context, + SessionState state, + bool isLargeScreen, + ) { + // Qui gestiamo lo switch tra le pagine + switch (_selectedIndex) { + case 0: + return DashboardContent(isLargeScreen: isLargeScreen); + case 1: + return const Center(child: Text('Pagina Clienti')); // La faremo! + default: + return const DashboardContent(); + } + } +}