/// Page contacter le bureau — Communication UnionFlow v4 /// /// Remplace l'ancien broadcast par un canal vers le rôle PRESIDENT. library broadcast_page; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../shared/design_system/unionflow_design_system.dart'; import '../../../../shared/widgets/core_card.dart'; import '../bloc/messaging_bloc.dart'; import '../bloc/messaging_event.dart'; import '../bloc/messaging_state.dart'; import 'conversation_detail_page.dart'; /// Page pour contacter le bureau (canal rôle PRESIDENT) class BroadcastPage extends StatefulWidget { final String organizationId; const BroadcastPage({ super.key, required this.organizationId, }); @override State createState() => _BroadcastPageState(); } class _BroadcastPageState extends State { final _messageController = TextEditingController(); String _selectedRole = 'PRESIDENT'; bool _isSending = false; static const _roles = [ ('PRESIDENT', 'Président'), ('TRESORIER', 'Trésorier'), ('SECRETAIRE', 'Secrétaire'), ('VICE_PRESIDENT', 'Vice-Président'), ('CONSEILLER', 'Conseiller'), ]; @override void dispose() { _messageController.dispose(); super.dispose(); } void _submit() { final message = _messageController.text.trim(); if (message.isEmpty || _isSending) return; setState(() => _isSending = true); context.read().add( DemarrerConversationRole( roleCible: _selectedRole, organisationId: widget.organizationId, premierMessage: message, ), ); } @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; return BlocListener( listener: (context, state) { if (state is ConversationCreee) { setState(() => _isSending = false); // Naviguer vers la conversation créée Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (_) => BlocProvider.value( value: context.read(), child: ConversationDetailPage(conversationId: state.conversation.id), ), ), ); } if (state is MessagingError) { setState(() => _isSending = false); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(state.message), backgroundColor: ColorTokens.error, ), ); } }, child: Scaffold( backgroundColor: scheme.surface, appBar: UFAppBar( title: 'Contacter le bureau', moduleGradient: ModuleColors.communicationGradient, automaticallyImplyLeading: true, ), body: SafeArea( top: false, child: SingleChildScrollView( padding: const EdgeInsets.all(SpacingTokens.md), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Info CoreCard( child: Row( children: [ Container( width: 44, height: 44, decoration: BoxDecoration( color: ModuleColors.communication.withOpacity(0.15), borderRadius: BorderRadius.circular(SpacingTokens.radiusSm), ), child: const Icon( Icons.account_circle_outlined, color: ModuleColors.communication, size: 24, ), ), const SizedBox(width: SpacingTokens.md), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Contacter un responsable', style: AppTypography.actionText), const SizedBox(height: 2), Text( 'Votre message sera transmis au titulaire du rôle choisi', style: AppTypography.subtitleSmall, ), ], ), ), ], ), ), const SizedBox(height: SpacingTokens.lg), // Sélection du rôle Text('Destinataire', style: AppTypography.actionText), const SizedBox(height: SpacingTokens.sm), Wrap( spacing: SpacingTokens.sm, runSpacing: SpacingTokens.sm, children: _roles.map((role) { final isSelected = _selectedRole == role.$1; return ChoiceChip( label: Text(role.$2), selected: isSelected, selectedColor: ModuleColors.communication.withOpacity(0.2), labelStyle: AppTypography.bodyTextSmall.copyWith( color: isSelected ? ModuleColors.communication : null, fontWeight: isSelected ? FontWeight.w600 : null, ), onSelected: (_) => setState(() => _selectedRole = role.$1), ); }).toList(), ), const SizedBox(height: SpacingTokens.lg), // Message Text('Message', style: AppTypography.actionText), const SizedBox(height: SpacingTokens.sm), TextField( controller: _messageController, maxLines: 6, minLines: 3, decoration: InputDecoration( hintText: 'Écrivez votre message...', hintStyle: AppTypography.bodyTextSmall.copyWith( color: scheme.onSurfaceVariant, ), filled: true, fillColor: scheme.surfaceContainerHighest.withOpacity(0.3), border: OutlineInputBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), borderSide: BorderSide(color: scheme.outlineVariant), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), borderSide: BorderSide(color: scheme.outlineVariant), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(SpacingTokens.radiusMd), borderSide: const BorderSide(color: ModuleColors.communication, width: 2), ), ), style: AppTypography.bodyMedium, ), const SizedBox(height: SpacingTokens.xl), SizedBox( width: double.infinity, child: UFPrimaryButton( label: _isSending ? 'Envoi en cours...' : 'Envoyer le message', onPressed: _isSending ? null : _submit, icon: _isSending ? null : Icons.send_rounded, ), ), ], ), ), ), ), ); } }