diff --git a/frontend/lib/config/app_router.dart b/frontend/lib/config/app_router.dart index 8408cf4..074262f 100644 --- a/frontend/lib/config/app_router.dart +++ b/frontend/lib/config/app_router.dart @@ -22,6 +22,9 @@ import '../screens/home/home_screen.dart'; import '../screens/administrateurs/admin_dashboardScreen.dart'; import '../screens/gestionnaire/gestionnaire_dashboard_screen.dart'; import '../screens/home/parent_screen/ParentDashboardScreen.dart'; +import '../screens/am/am_dashboard_screen.dart'; +import '../screens/legal/privacy_page.dart'; +import '../screens/legal/legal_page.dart'; import '../screens/unknown_screen.dart'; // --- Provider Instances --- @@ -64,7 +67,16 @@ class AppRouter { ), GoRoute( path: '/am-dashboard', - builder: (BuildContext context, GoRouterState state) => const HomeScreen(), + builder: (BuildContext context, GoRouterState state) => + const AmDashboardScreen(), + ), + GoRoute( + path: '/privacy', + builder: (BuildContext context, GoRouterState state) => const PrivacyPage(), + ), + GoRoute( + path: '/legal', + builder: (BuildContext context, GoRouterState state) => const LegalPage(), ), // --- Parent Registration Flow --- diff --git a/frontend/lib/models/user.dart b/frontend/lib/models/user.dart index a07a176..01b89ce 100644 --- a/frontend/lib/models/user.dart +++ b/frontend/lib/models/user.dart @@ -41,9 +41,9 @@ class AppUser { relaisJson is Map ? relaisJson : {}; return AppUser( - id: json['id'] as String, - email: json['email'] as String, - role: json['role'] as String, + id: (json['id'] as String?) ?? '', + email: (json['email'] as String?) ?? '', + role: (json['role'] as String?) ?? '', createdAt: json['cree_le'] != null ? DateTime.parse(json['cree_le'] as String) : (json['createdAt'] != null diff --git a/frontend/lib/screens/administrateurs/admin_dashboardScreen.dart b/frontend/lib/screens/administrateurs/admin_dashboardScreen.dart index 43d3ca6..20a9678 100644 --- a/frontend/lib/screens/administrateurs/admin_dashboardScreen.dart +++ b/frontend/lib/screens/administrateurs/admin_dashboardScreen.dart @@ -1,9 +1,12 @@ import 'package:flutter/material.dart'; +import 'package:p_tits_pas/models/user.dart'; +import 'package:p_tits_pas/services/auth_service.dart'; import 'package:p_tits_pas/services/configuration_service.dart'; +import 'package:p_tits_pas/widgets/admin/dashboard_admin.dart'; import 'package:p_tits_pas/widgets/admin/parametres_panel.dart'; import 'package:p_tits_pas/widgets/admin/user_management_panel.dart'; import 'package:p_tits_pas/widgets/app_footer.dart'; -import 'package:p_tits_pas/widgets/admin/dashboard_admin.dart'; +import 'package:p_tits_pas/widgets/dashboard/dashboard_bandeau.dart'; class AdminDashboardScreen extends StatefulWidget { const AdminDashboardScreen({super.key}); @@ -14,6 +17,7 @@ class AdminDashboardScreen extends StatefulWidget { class _AdminDashboardScreenState extends State { bool? _setupCompleted; + AppUser? _user; int mainTabIndex = 0; int settingsSubIndex = 0; @@ -31,9 +35,11 @@ class _AdminDashboardScreenState extends State { Future _loadSetupStatus() async { try { final completed = await ConfigurationService.getSetupStatus(); + final user = await AuthService.getCurrentUser(); if (!mounted) return; setState(() { _setupCompleted = completed; + _user = user; if (!completed) mainTabIndex = 1; }); } catch (e) { @@ -68,17 +74,29 @@ class _AdminDashboardScreenState extends State { return Scaffold( appBar: PreferredSize( preferredSize: const Size.fromHeight(60.0), - child: Container( - decoration: BoxDecoration( - border: Border( - bottom: BorderSide(color: Colors.grey.shade300), + child: DashboardBandeau( + tabItems: [ + DashboardTabItem( + label: 'Gestion des utilisateurs', + enabled: _setupCompleted!, ), - ), - child: DashboardAppBarAdmin( - selectedIndex: mainTabIndex, - onTabChange: onMainTabChange, - setupCompleted: _setupCompleted!, - ), + const DashboardTabItem(label: 'Paramètres'), + ], + selectedTabIndex: mainTabIndex, + onTabSelected: onMainTabChange, + userDisplayName: _user?.fullName.isNotEmpty == true + ? _user!.fullName + : 'Admin', + userEmail: _user?.email, + userRole: _user?.role, + onProfileTap: () { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Modification du profil – à venir')), + ); + }, + onSettingsTap: () => onMainTabChange(1), + onLogout: () {}, + showLogoutConfirmation: true, ), ), body: Column( diff --git a/frontend/lib/screens/am/am_dashboard_screen.dart b/frontend/lib/screens/am/am_dashboard_screen.dart new file mode 100644 index 0000000..fea0afe --- /dev/null +++ b/frontend/lib/screens/am/am_dashboard_screen.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:p_tits_pas/models/user.dart'; +import 'package:p_tits_pas/services/auth_service.dart'; +import 'package:p_tits_pas/widgets/app_footer.dart'; +import 'package:p_tits_pas/widgets/dashboard/dashboard_bandeau.dart'; + +/// Dashboard assistante maternelle – page blanche avec bandeau générique. +/// Contenu détaillé à venir. +class AmDashboardScreen extends StatefulWidget { + const AmDashboardScreen({super.key}); + + @override + State createState() => _AmDashboardScreenState(); +} + +class _AmDashboardScreenState extends State { + int selectedTabIndex = 0; + AppUser? _user; + + @override + void initState() { + super.initState(); + _loadUser(); + } + + Future _loadUser() async { + final user = await AuthService.getCurrentUser(); + if (mounted) setState(() => _user = user); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: PreferredSize( + preferredSize: const Size.fromHeight(60.0), + child: DashboardBandeau( + tabItems: const [ + DashboardTabItem(label: 'Mon tableau de bord'), + DashboardTabItem(label: 'Paramètres'), + ], + selectedTabIndex: selectedTabIndex, + onTabSelected: (index) => setState(() => selectedTabIndex = index), + userDisplayName: _user?.fullName.isNotEmpty == true + ? _user!.fullName + : 'Assistante maternelle', + userEmail: _user?.email, + userRole: _user?.role, + onProfileTap: () { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Modification du profil – à venir')), + ); + }, + onSettingsTap: () { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Paramètres – à venir')), + ); + }, + onLogout: () {}, + showLogoutConfirmation: true, + ), + ), + body: Column( + children: [ + Expanded( + child: Center( + child: Text( + 'Dashboard AM – à venir', + style: Theme.of(context).textTheme.titleLarge, + ), + ), + ), + const AppFooter(), + ], + ), + ); + } +} diff --git a/frontend/lib/screens/gestionnaire/gestionnaire_dashboard_screen.dart b/frontend/lib/screens/gestionnaire/gestionnaire_dashboard_screen.dart index f712dca..921ad0f 100644 --- a/frontend/lib/screens/gestionnaire/gestionnaire_dashboard_screen.dart +++ b/frontend/lib/screens/gestionnaire/gestionnaire_dashboard_screen.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:p_tits_pas/widgets/admin/dashboard_admin.dart'; +import 'package:p_tits_pas/models/user.dart'; +import 'package:p_tits_pas/services/auth_service.dart'; import 'package:p_tits_pas/widgets/admin/user_management_panel.dart'; import 'package:p_tits_pas/widgets/app_footer.dart'; +import 'package:p_tits_pas/widgets/dashboard/dashboard_bandeau.dart'; /// Dashboard gestionnaire – même shell que l'admin, sans onglet Paramètres. /// Réutilise [UserManagementPanel]. @@ -14,24 +16,47 @@ class GestionnaireDashboardScreen extends StatefulWidget { } class _GestionnaireDashboardScreenState extends State { + AppUser? _user; + + @override + void initState() { + super.initState(); + _loadUser(); + } + + Future _loadUser() async { + final user = await AuthService.getCurrentUser(); + if (mounted) setState(() => _user = user); + } + @override Widget build(BuildContext context) { return Scaffold( appBar: PreferredSize( preferredSize: const Size.fromHeight(60.0), - child: Container( - decoration: BoxDecoration( - border: Border( - bottom: BorderSide(color: Colors.grey.shade300), - ), - ), - child: DashboardAppBarAdmin( - selectedIndex: 0, - onTabChange: (_) {}, - showSettingsTab: false, - roleLabel: 'Gestionnaire', - setupCompleted: true, - ), + child: DashboardBandeau( + tabItems: const [ + DashboardTabItem(label: 'Gestion des utilisateurs'), + ], + selectedTabIndex: 0, + onTabSelected: (_) {}, + userDisplayName: _user?.fullName.isNotEmpty == true + ? _user!.fullName + : 'Gestionnaire', + userEmail: _user?.email, + userRole: _user?.role, + onProfileTap: () { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Modification du profil – à venir')), + ); + }, + onSettingsTap: () { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Paramètres – à venir')), + ); + }, + onLogout: () {}, + showLogoutConfirmation: true, ), ), body: Column( diff --git a/frontend/lib/screens/home/parent_screen/ParentDashboardScreen.dart b/frontend/lib/screens/home/parent_screen/ParentDashboardScreen.dart index 81deb26..c71e4dc 100644 --- a/frontend/lib/screens/home/parent_screen/ParentDashboardScreen.dart +++ b/frontend/lib/screens/home/parent_screen/ParentDashboardScreen.dart @@ -1,11 +1,12 @@ import 'package:flutter/material.dart'; import 'package:p_tits_pas/controllers/parent_dashboard_controller.dart'; +import 'package:p_tits_pas/models/user.dart'; +import 'package:p_tits_pas/services/auth_service.dart'; import 'package:p_tits_pas/services/dashboardService.dart'; import 'package:p_tits_pas/widgets/app_footer.dart'; -import 'package:p_tits_pas/widgets/dashbord_parent/app_layout.dart'; import 'package:p_tits_pas/widgets/dashbord_parent/children_sidebar.dart'; -import 'package:p_tits_pas/widgets/dashbord_parent/dashboard_app_bar.dart'; import 'package:p_tits_pas/widgets/dashbord_parent/wid_dashbord.dart'; +import 'package:p_tits_pas/widgets/dashboard/dashboard_bandeau.dart'; import 'package:p_tits_pas/widgets/main_content_area.dart'; import 'package:p_tits_pas/widgets/messaging_sidebar.dart'; import 'package:provider/provider.dart'; @@ -19,6 +20,7 @@ class ParentDashboardScreen extends StatefulWidget { class _ParentDashboardScreenState extends State { int selectedIndex = 0; + AppUser? _user; void onTabChange(int index) { setState(() { @@ -29,12 +31,18 @@ class _ParentDashboardScreenState extends State { @override void initState() { super.initState(); + _loadUser(); // Initialiser les données du dashboard WidgetsBinding.instance.addPostFrameCallback((_) { context.read().initDashboard(); }); } + Future _loadUser() async { + final user = await AuthService.getCurrentUser(); + if (mounted) setState(() => _user = user); + } + Widget _getBody() { switch (selectedIndex) { case 0: @@ -53,29 +61,43 @@ class _ParentDashboardScreenState extends State { return ChangeNotifierProvider( create: (context) => ParentDashboardController(DashboardService())..initDashboard(), child: Scaffold( - appBar: PreferredSize(preferredSize: const Size.fromHeight(60.0), - child: Container( - decoration: BoxDecoration( - border: Border( - bottom: BorderSide(color: Colors.grey.shade300), - ), - ), - child: DashboardAppBar( - selectedIndex: selectedIndex, - onTabChange: onTabChange, + appBar: PreferredSize( + preferredSize: const Size.fromHeight(60.0), + child: DashboardBandeau( + tabItems: const [ + DashboardTabItem(label: 'Mon tableau de bord'), + DashboardTabItem(label: 'Trouver une nounou'), + DashboardTabItem(label: 'Paramètres'), + ], + selectedTabIndex: selectedIndex, + onTabSelected: onTabChange, + userDisplayName: _user?.fullName.isNotEmpty == true + ? _user!.fullName + : 'Parent', + userEmail: _user?.email, + userRole: _user?.role, + onProfileTap: () { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Modification du profil – à venir')), + ); + }, + onSettingsTap: () { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Paramètres – à venir')), + ); + }, + onLogout: () {}, + showLogoutConfirmation: true, ), ), - ), body: Column( children: [ - Expanded (child: _getBody(), - ), + Expanded(child: _getBody()), const AppFooter(), ], ), - ) - // body: _buildResponsiveBody(context, controller), - // footer: const AppFooter(), + ), ); } diff --git a/frontend/lib/widgets/admin/dashboard_admin.dart b/frontend/lib/widgets/admin/dashboard_admin.dart index 13bbb43..55c99be 100644 --- a/frontend/lib/widgets/admin/dashboard_admin.dart +++ b/frontend/lib/widgets/admin/dashboard_admin.dart @@ -1,143 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:p_tits_pas/services/auth_service.dart'; - -/// Barre du dashboard admin : onglets Gestion des utilisateurs | Paramètres + déconnexion. -/// Pour le dashboard gestionnaire : [showSettingsTab] = false, [roleLabel] = 'Gestionnaire'. -class DashboardAppBarAdmin extends StatelessWidget - implements PreferredSizeWidget { - final int selectedIndex; - final ValueChanged onTabChange; - final bool setupCompleted; - final bool showSettingsTab; - final String roleLabel; - - const DashboardAppBarAdmin({ - Key? key, - required this.selectedIndex, - required this.onTabChange, - this.setupCompleted = true, - this.showSettingsTab = true, - this.roleLabel = 'Admin', - }) : super(key: key); - - @override - Size get preferredSize => const Size.fromHeight(kToolbarHeight + 10); - - @override - Widget build(BuildContext context) { - return AppBar( - elevation: 0, - automaticallyImplyLeading: false, - title: Row( - children: [ - const SizedBox(width: 24), - Image.asset( - 'assets/images/logo.png', - height: 40, - fit: BoxFit.contain, - ), - Expanded( - child: Center( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - _buildNavItem(context, 'Gestion des utilisateurs', 0, - enabled: setupCompleted), - if (showSettingsTab) ...[ - const SizedBox(width: 24), - _buildNavItem(context, 'Paramètres', 1, enabled: true), - ], - ], - ), - ), - ), - ], - ), - actions: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Center( - child: Text( - roleLabel, - style: const TextStyle( - color: Colors.black, - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - ), - ), - Padding( - padding: const EdgeInsets.only(right: 16), - child: TextButton( - onPressed: () => _handleLogout(context), - style: TextButton.styleFrom( - backgroundColor: const Color(0xFF9CC5C0), - foregroundColor: Colors.white, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5), - ), - ), - child: const Text('Se déconnecter'), - ), - ), - ], - ); - } - - Widget _buildNavItem(BuildContext context, String title, int index, - {bool enabled = true}) { - final bool isActive = index == selectedIndex; - return InkWell( - onTap: enabled ? () => onTabChange(index) : null, - child: Opacity( - opacity: enabled ? 1.0 : 0.5, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - decoration: BoxDecoration( - color: isActive ? const Color(0xFF9CC5C0) : Colors.transparent, - borderRadius: BorderRadius.circular(20), - border: isActive ? null : Border.all(color: Colors.black26), - ), - child: Text( - title, - style: TextStyle( - color: isActive ? Colors.white : Colors.black, - fontWeight: isActive ? FontWeight.w600 : FontWeight.normal, - fontSize: 14, - ), - ), - ), - ), - ); - } - - void _handleLogout(BuildContext context) { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text('Déconnexion'), - content: const Text('Êtes-vous sûr de vouloir vous déconnecter ?'), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text('Annuler'), - ), - ElevatedButton( - onPressed: () async { - Navigator.pop(context); - await AuthService.logout(); - if (context.mounted) context.go('/login'); - }, - child: const Text('Déconnecter'), - ), - ], - ), - ); - } -} /// Sous-barre : Gestionnaires | Parents | Assistantes maternelles | [Administrateurs]. /// [subTabCount] = 3 pour masquer l'onglet Administrateurs (dashboard gestionnaire). diff --git a/frontend/lib/widgets/app_footer.dart b/frontend/lib/widgets/app_footer.dart index a4559d2..b87f82b 100644 --- a/frontend/lib/widgets/app_footer.dart +++ b/frontend/lib/widgets/app_footer.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:p_tits_pas/models/m_dashbord/child_model.dart'; import 'package:p_tits_pas/services/bug_report_service.dart'; @@ -185,13 +186,11 @@ class AppFooter extends StatelessWidget { } void _handleLegalNotices(BuildContext context) { - // Handle legal notices action - Navigator.pushNamed(context, '/legal'); + context.push('/legal'); } void _handlePrivacyPolicy(BuildContext context) { - // Handle privacy policy action - Navigator.pushNamed(context, '/privacy'); + context.push('/privacy'); } void _handleContactSupport(BuildContext context) { diff --git a/frontend/lib/widgets/dashboard/dashboard_bandeau.dart b/frontend/lib/widgets/dashboard/dashboard_bandeau.dart new file mode 100644 index 0000000..6ac6560 --- /dev/null +++ b/frontend/lib/widgets/dashboard/dashboard_bandeau.dart @@ -0,0 +1,299 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:p_tits_pas/services/auth_service.dart'; + +/// Item d'onglet pour le bandeau (label + enabled). +class DashboardTabItem { + final String label; + final bool enabled; + + const DashboardTabItem({ + required this.label, + this.enabled = true, + }); +} + +/// Icône associée au rôle utilisateur (alignée sur le panneau admin). +IconData _iconForRole(String? role) { + if (role == null || role.isEmpty) return Icons.person_outline; + final r = role.toLowerCase(); + if (r == 'super_admin') return Icons.verified_user_outlined; + if (r == 'admin' || r == 'administrateur') return Icons.manage_accounts_outlined; + if (r == 'gestionnaire') return Icons.assignment_ind_outlined; + if (r == 'parent') return Icons.supervisor_account_outlined; + if (r == 'assistante_maternelle') return Icons.face; + return Icons.person_outline; +} + +/// Bandeau générique type Gitea : icône | onglets | capsule (Prénom Nom ▼) → menu (email, Profil, Paramètres, Déconnexion). +class DashboardBandeau extends StatelessWidget implements PreferredSizeWidget { + final Widget? leading; + final List tabItems; + final int selectedTabIndex; + final ValueChanged onTabSelected; + final String userDisplayName; + final String? userEmail; + /// Rôle de l'utilisateur pour afficher l'icône correspondante (même que panneau admin). + final String? userRole; + final VoidCallback? onProfileTap; + final VoidCallback? onSettingsTap; + final VoidCallback? onLogout; + final bool showLogoutConfirmation; + final bool bottomBorder; + final double? preferredHeight; + + const DashboardBandeau({ + super.key, + this.leading, + required this.tabItems, + required this.selectedTabIndex, + required this.onTabSelected, + required this.userDisplayName, + this.userEmail, + this.userRole, + this.onProfileTap, + this.onSettingsTap, + this.onLogout, + this.showLogoutConfirmation = true, + this.bottomBorder = true, + this.preferredHeight, + }); + + @override + Size get preferredSize => + Size.fromHeight(preferredHeight ?? (kToolbarHeight + 10)); + + Widget _defaultLeading() { + return Image.asset( + 'assets/images/logo.png', + height: 40, + fit: BoxFit.contain, + ); + } + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: Theme.of(context).appBarTheme.backgroundColor ?? Colors.white, + border: bottomBorder + ? Border(bottom: BorderSide(color: Colors.grey.shade300)) + : null, + ), + child: AppBar( + elevation: 0, + automaticallyImplyLeading: false, + title: Row( + children: [ + const SizedBox(width: 24), + leading ?? _defaultLeading(), + Expanded( + child: Center( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + for (int i = 0; i < tabItems.length; i++) ...[ + if (i > 0) const SizedBox(width: 24), + _buildNavItem( + context, + title: tabItems[i].label, + index: i, + enabled: tabItems[i].enabled, + ), + ], + ], + ), + ), + ), + ], + ), + actions: [ + _buildUserCapsule(context), + ], + ), + ); + } + + Widget _buildNavItem( + BuildContext context, { + required String title, + required int index, + bool enabled = true, + }) { + final isActive = index == selectedTabIndex; + return InkWell( + onTap: enabled ? () => onTabSelected(index) : null, + child: Opacity( + opacity: enabled ? 1.0 : 0.5, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + decoration: BoxDecoration( + color: isActive ? const Color(0xFF9CC5C0) : Colors.transparent, + borderRadius: BorderRadius.circular(20), + border: isActive ? null : Border.all(color: Colors.black26), + ), + child: Text( + title, + style: TextStyle( + color: isActive ? Colors.white : Colors.black, + fontWeight: isActive ? FontWeight.w600 : FontWeight.normal, + fontSize: 14, + ), + ), + ), + ), + ); + } + + Widget _buildUserCapsule(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(right: 16), + child: PopupMenuButton( + offset: const Offset(0, 45), + position: PopupMenuPosition.under, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + onSelected: (value) { + switch (value) { + case 'profile': + onProfileTap?.call(); + break; + case 'settings': + onSettingsTap?.call(); + break; + case 'logout': + _handleLogout(context); + break; + } + }, + itemBuilder: (context) { + final entries = >[]; + if (userEmail != null && userEmail!.isNotEmpty) { + entries.add( + PopupMenuItem( + enabled: false, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.email_outlined, size: 16, color: Colors.grey.shade700), + const SizedBox(width: 8), + Flexible( + child: Text( + userEmail!, + style: TextStyle( + fontSize: 12, + color: Colors.grey.shade700, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + ); + entries.add(const PopupMenuDivider()); + } + if (onProfileTap != null) { + entries.add( + const PopupMenuItem( + value: 'profile', + child: ListTile( + leading: Icon(Icons.person_outline, size: 20), + title: Text('Modification du profil'), + contentPadding: EdgeInsets.zero, + visualDensity: VisualDensity.compact, + ), + ), + ); + } + if (onSettingsTap != null) { + entries.add( + const PopupMenuItem( + value: 'settings', + child: ListTile( + leading: Icon(Icons.settings_outlined, size: 20), + title: Text('Paramètres'), + contentPadding: EdgeInsets.zero, + visualDensity: VisualDensity.compact, + ), + ), + ); + } + if (onLogout != null) { + if (entries.isNotEmpty) entries.add(const PopupMenuDivider()); + entries.add( + const PopupMenuItem( + value: 'logout', + child: ListTile( + leading: Icon(Icons.logout, size: 20), + title: Text('Déconnexion'), + contentPadding: EdgeInsets.zero, + visualDensity: VisualDensity.compact, + ), + ), + ); + } + return entries; + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + decoration: BoxDecoration( + color: Colors.grey.shade100, + borderRadius: BorderRadius.circular(20), + border: Border.all(color: Colors.grey.shade300), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(_iconForRole(userRole), size: 18, color: Colors.grey.shade700), + const SizedBox(width: 6), + Text( + userDisplayName, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Colors.black87, + ), + ), + const SizedBox(width: 4), + Icon(Icons.keyboard_arrow_down, size: 20, color: Colors.grey.shade700), + ], + ), + ), + ), + ); + } + + void _handleLogout(BuildContext context) { + if (showLogoutConfirmation) { + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: const Text('Déconnexion'), + content: const Text( + 'Êtes-vous sûr de vouloir vous déconnecter ?'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(ctx), + child: const Text('Annuler'), + ), + ElevatedButton( + onPressed: () async { + Navigator.pop(ctx); + onLogout?.call(); + await AuthService.logout(); + if (context.mounted) context.go('/login'); + }, + child: const Text('Déconnecter'), + ), + ], + ), + ); + } else { + onLogout?.call(); + AuthService.logout().then((_) { + if (context.mounted) context.go('/login'); + }); + } + } +} + diff --git a/frontend/lib/widgets/dashbord_parent/dashboard_app_bar.dart b/frontend/lib/widgets/dashbord_parent/dashboard_app_bar.dart deleted file mode 100644 index c89fd6e..0000000 --- a/frontend/lib/widgets/dashbord_parent/dashboard_app_bar.dart +++ /dev/null @@ -1,156 +0,0 @@ -import 'package:flutter/material.dart'; - -class DashboardAppBar extends StatelessWidget implements PreferredSizeWidget { - final int selectedIndex; - final ValueChanged onTabChange; - - const DashboardAppBar({Key? key, required this.selectedIndex, required this.onTabChange}) : super(key: key); - - @override - Size get preferredSize => const Size.fromHeight(kToolbarHeight + 10); - - @override - Widget build(BuildContext context) { - final isMobile = MediaQuery.of(context).size.width < 768; - return AppBar( - // backgroundColor: Colors.white, - elevation: 0, - title: Row( - children: [ - // Logo de la ville - // Container( - // height: 32, - // width: 32, - // decoration: BoxDecoration( - // color: Colors.white, - // borderRadius: BorderRadius.circular(8), - // ), - // child: const Icon( - // Icons.location_city, - // color: Color(0xFF9CC5C0), - // size: 20, - // ), - // ), - SizedBox(width: MediaQuery.of(context).size.width * 0.19), - const Text( - "P'tit Pas", - style: TextStyle( - color: Color(0xFF9CC5C0), - fontWeight: FontWeight.bold, - fontSize: 18, - ), - ), - SizedBox(width: MediaQuery.of(context).size.width * 0.1), - - // Navigation principale - _buildNavItem(context, 'Mon tableau de bord', 0), - const SizedBox(width: 24), - _buildNavItem(context, 'Trouver une nounou', 1), - const SizedBox(width: 24), - _buildNavItem(context, 'Paramètres', 2), - ], - ), - actions: isMobile - ? [_buildMobileMenu(context)] - : [ - // Nom de l'utilisateur - const Padding( - padding: EdgeInsets.symmetric(horizontal: 16), - child: Center( - child: Text( - 'Jean Dupont', - style: TextStyle( - color: Colors.black, - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - ), - ), - - // Bouton déconnexion - Padding( - padding: const EdgeInsets.only(right: 16), - child: TextButton( - onPressed: () => _handleLogout(context), - style: TextButton.styleFrom( - backgroundColor: const Color(0xFF9CC5C0), - foregroundColor: Colors.white, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5), - ), - ), - child: const Text('Se déconnecter'), - ), - ), - SizedBox(width: MediaQuery.of(context).size.width * 0.1), - ], - ); - } - - Widget _buildNavItem(BuildContext context, String title, int index) { - final bool isActive = index == selectedIndex; - return InkWell( - onTap: () => onTabChange(index), - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - decoration: BoxDecoration( - color: isActive ? const Color(0xFF9CC5C0) : Colors.transparent, - borderRadius: BorderRadius.circular(20), - border: isActive ? null : Border.all(color: Colors.black26), - ), - child: Text( - title, - style: TextStyle( - color: isActive ? Colors.white : Colors.black, - fontWeight: isActive ? FontWeight.w600 : FontWeight.normal, - fontSize: 14, - ), - ), - ), - ); -} - - - Widget _buildMobileMenu(BuildContext context) { - return PopupMenuButton( - icon: const Icon(Icons.menu, color: Colors.white), - onSelected: (value) { - if (value == 3) { - _handleLogout(context); - } - }, - itemBuilder: (context) => [ - const PopupMenuItem(value: 0, child: Text("Mon tableau de bord")), - const PopupMenuItem(value: 1, child: Text("Trouver une nounou")), - const PopupMenuItem(value: 2, child: Text("Paramètres")), - const PopupMenuDivider(), - const PopupMenuItem(value: 3, child: Text("Se déconnecter")), - ], - ); - } - - void _handleLogout(BuildContext context) { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text('Déconnexion'), - content: const Text('Êtes-vous sûr de vouloir vous déconnecter ?'), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text('Annuler'), - ), - ElevatedButton( - onPressed: () { - Navigator.pop(context); - // TODO: Implémenter la logique de déconnexion - }, - child: const Text('Déconnecter'), - ), - ], - ), - ); - } -} \ No newline at end of file