import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:p_tits_pas/services/auth_service.dart'; import 'package:p_tits_pas/widgets/image_button.dart'; import 'package:p_tits_pas/widgets/quotidien/quotidien_theme.dart'; /// Bandeau quotidien pastel : logo · pastilles Cahier de liaison / Agenda / /// Contrat · menu user. /// Réutilisable parent (#166) et AM (#169). class QuotidienBandeau extends StatelessWidget { final QuotidienNavSection selectedSection; final ValueChanged onSectionSelected; final String userDisplayName; final String? userEmail; final VoidCallback? onProfileTap; final VoidCallback? onSearchAmTap; final VoidCallback? onSettingsTap; final VoidCallback? onLogout; const QuotidienBandeau({ super.key, required this.selectedSection, required this.onSectionSelected, required this.userDisplayName, this.userEmail, this.onProfileTap, this.onSearchAmTap, this.onSettingsTap, this.onLogout, }); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.fromLTRB(16, 12, 16, 8), child: Row( children: [ Image.asset( QuotidienTheme.logoAsset, height: 44, fit: BoxFit.contain, ), const Spacer(), _NavPills( selected: selectedSection, onSelected: onSectionSelected, ), const Spacer(), _UserMenu( displayName: userDisplayName, email: userEmail, onProfileTap: onProfileTap, onSearchAmTap: onSearchAmTap, onSettingsTap: onSettingsTap, onLogout: onLogout, ), ], ), ); } } class _NavPills extends StatelessWidget { final QuotidienNavSection selected; final ValueChanged onSelected; const _NavPills({ required this.selected, required this.onSelected, }); @override Widget build(BuildContext context) { return Row( mainAxisSize: MainAxisSize.min, children: [ _pill( label: 'Cahier de liaison', section: QuotidienNavSection.liaison, ), const SizedBox(width: 10), _pill( label: 'Agenda', section: QuotidienNavSection.agenda, ), const SizedBox(width: 10), _pill( label: 'Contrat', section: QuotidienNavSection.contrat, ), ], ); } Widget _pill({ required String label, required QuotidienNavSection section, }) { final active = selected == section; // Même famille que l’inscription : fonds « dessinés » (pas Material). // Les deux pastilles ont la même silhouette (ratio ~4:1) : la largeur // est dérivée de la hauteur pour ne jamais déformer le PNG. // Chaque section garde sa couleur ; l'inactive est juste plus claire. return ImageButton( bg: QuotidienTheme.pillAssetFor(section), bgOpacity: active ? 1.0 : QuotidienTheme.pillInactiveOpacity, width: _pillHeight * QuotidienTheme.pillAspectRatio, height: _pillHeight, text: label, textColor: QuotidienTheme.ink, fontSize: 14, onPressed: () => onSelected(section), ); } static const double _pillHeight = 46; } class _UserMenu extends StatelessWidget { final String displayName; final String? email; final VoidCallback? onProfileTap; final VoidCallback? onSearchAmTap; final VoidCallback? onSettingsTap; final VoidCallback? onLogout; const _UserMenu({ required this.displayName, this.email, this.onProfileTap, this.onSearchAmTap, this.onSettingsTap, this.onLogout, }); @override Widget build(BuildContext context) { final shortName = displayName.trim().isEmpty ? 'Compte' : displayName.trim(); const double pillHeight = 46; const double pillWidth = pillHeight * QuotidienTheme.pillAspectRatio; return PopupMenuButton( tooltip: 'Menu utilisateur', offset: const Offset(0, pillHeight + 4), color: QuotidienTheme.ivory, elevation: 3, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), side: BorderSide(color: QuotidienTheme.lavender.withOpacity(0.6)), ), onSelected: (value) async { switch (value) { case 'profile': onProfileTap?.call(); break; case 'search_am': onSearchAmTap?.call(); break; case 'settings': onSettingsTap?.call(); break; case 'logout': await _confirmLogout(context); break; } }, itemBuilder: (context) => [ if (email != null && email!.trim().isNotEmpty) PopupMenuItem( enabled: false, child: Text( email!, style: TextStyle(color: QuotidienTheme.muted, fontSize: 12), ), ), const PopupMenuDivider(), const PopupMenuItem( value: 'profile', child: ListTile( dense: true, contentPadding: EdgeInsets.zero, leading: Icon(Icons.person_outline, size: 20), title: Text('Profil'), ), ), const PopupMenuItem( value: 'search_am', child: ListTile( dense: true, contentPadding: EdgeInsets.zero, leading: Icon(Icons.search, size: 20), title: Text('Recherche AM'), ), ), const PopupMenuItem( value: 'settings', child: ListTile( dense: true, contentPadding: EdgeInsets.zero, leading: Icon(Icons.settings_outlined, size: 20), title: Text('Paramètres'), ), ), const PopupMenuDivider(), const PopupMenuItem( value: 'logout', child: ListTile( dense: true, contentPadding: EdgeInsets.zero, leading: Icon(Icons.logout, size: 20), title: Text('Déconnexion'), ), ), ], // Même pastille « dessinée » que la nav, teinte violet pastel charte. child: Container( width: pillWidth, height: pillHeight, padding: const EdgeInsets.symmetric(horizontal: 14), decoration: const BoxDecoration( image: DecorationImage( image: AssetImage(QuotidienTheme.pillLavenderAsset), fit: BoxFit.fill, ), ), child: Row( children: [ const Icon( Icons.person_outline, size: 20, color: QuotidienTheme.ink, ), const SizedBox(width: 6), Expanded( child: Text( shortName, maxLines: 1, overflow: TextOverflow.ellipsis, style: GoogleFonts.merienda( fontSize: 13, fontWeight: FontWeight.bold, color: QuotidienTheme.ink, ), ), ), const Icon( Icons.keyboard_arrow_down, size: 18, color: QuotidienTheme.ink, ), ], ), ), ); } Future _confirmLogout(BuildContext context) async { final ok = await showDialog( context: context, builder: (ctx) => AlertDialog( title: const Text('Déconnexion'), content: const Text('Voulez-vous vraiment vous déconnecter ?'), actions: [ TextButton( onPressed: () => Navigator.of(ctx).pop(false), child: const Text('Annuler'), ), TextButton( onPressed: () => Navigator.of(ctx).pop(true), child: const Text('Déconnexion'), ), ], ), ); if (ok != true) return; onLogout?.call(); await AuthService.logout(); if (context.mounted) { context.go('/login'); } } }