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'); }); } } }