Files
geo/app/lib/presentation/admin/admin_communication_page.dart
Pierre 5ab03751e1 feat: Release version 3.1.4 - Mode terrain et génération PDF
 Nouvelles fonctionnalités:
- Ajout du mode terrain pour utilisation mobile hors connexion
- Génération automatique de reçus PDF avec template personnalisé
- Révision complète du système de cartes avec amélioration des performances

🔧 Améliorations techniques:
- Refactoring du module chat avec architecture simplifiée
- Optimisation du système de sécurité NIST SP 800-63B
- Amélioration de la gestion des secteurs géographiques
- Support UTF-8 étendu pour les noms d'utilisateurs

📱 Application mobile:
- Nouveau mode terrain dans user_field_mode_page
- Interface utilisateur adaptative pour conditions difficiles
- Synchronisation offline améliorée

🗺️ Cartographie:
- Optimisation des performances MapBox
- Meilleure gestion des tuiles hors ligne
- Amélioration de l'affichage des secteurs

📄 Documentation:
- Ajout guide Android (ANDROID-GUIDE.md)
- Documentation sécurité API (API-SECURITY.md)
- Guide module chat (CHAT_MODULE.md)

🐛 Corrections:
- Résolution des erreurs 400 lors de la création d'utilisateurs
- Correction de la validation des noms d'utilisateurs
- Fix des problèmes de synchronisation chat

🤖 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-19 19:38:03 +02:00

251 lines
7.5 KiB
Dart
Executable File

import 'package:flutter/material.dart';
import 'package:geosector_app/core/theme/app_theme.dart';
import 'package:geosector_app/chat/chat_module.dart';
import 'package:geosector_app/chat/pages/rooms_page_embedded.dart';
import 'package:geosector_app/core/services/current_user_service.dart';
import 'package:geosector_app/core/services/api_service.dart';
import 'package:geosector_app/core/services/current_amicale_service.dart';
class AdminCommunicationPage extends StatefulWidget {
const AdminCommunicationPage({super.key});
@override
State<AdminCommunicationPage> createState() => _AdminCommunicationPageState();
}
class _AdminCommunicationPageState extends State<AdminCommunicationPage> {
bool _isChatInitialized = false;
bool _isInitializing = false;
String? _initError;
GlobalKey<RoomsPageEmbeddedState>? _roomsPageKey;
@override
void initState() {
super.initState();
_initializeChat();
}
Future<void> _initializeChat() async {
if (_isInitializing) return;
setState(() {
_isInitializing = true;
_initError = null;
});
try {
// Récupérer les informations utilisateur
final currentUser = CurrentUserService.instance;
final apiService = ApiService.instance;
final currentAmicale = CurrentAmicaleService.instance.currentAmicale;
if (currentUser.currentUser == null) {
throw Exception('Administrateur non connecté');
}
// Initialiser le module chat avec les informations de l'administrateur
await ChatModule.init(
apiUrl: apiService.baseUrl,
userId: currentUser.currentUser!.id,
userName: currentUser.userName ?? currentUser.userEmail ?? 'Administrateur',
userRole: currentUser.currentUser!.role,
userEntite: currentUser.fkEntite ?? currentAmicale?.id,
authToken: currentUser.sessionId,
);
setState(() {
_isChatInitialized = true;
_isInitializing = false;
_roomsPageKey = GlobalKey<RoomsPageEmbeddedState>();
});
} catch (e) {
setState(() {
_initError = e.toString();
_isInitializing = false;
});
debugPrint('Erreur initialisation chat admin: $e');
}
}
void _refreshRooms() {
_roomsPageKey?.currentState?.refresh();
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Container(
margin: const EdgeInsets.all(16.0),
decoration: BoxDecoration(
color: theme.colorScheme.surface,
borderRadius: BorderRadius.circular(24),
boxShadow: [
BoxShadow(
color: theme.shadowColor.withOpacity(0.1),
blurRadius: 20,
spreadRadius: 1,
offset: const Offset(0, 4),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(24),
child: _buildContent(theme),
),
);
}
Widget _buildContent(ThemeData theme) {
if (_isInitializing) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircularProgressIndicator(),
const SizedBox(height: 16),
Text(
'Initialisation du chat administrateur...',
style: theme.textTheme.bodyLarge,
),
],
),
);
}
if (_initError != null) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.error_outline,
size: 64,
color: theme.colorScheme.error,
),
const SizedBox(height: 16),
Text(
'Erreur d\'initialisation chat',
style: theme.textTheme.headlineSmall?.copyWith(
color: theme.colorScheme.error,
),
),
const SizedBox(height: 8),
Text(
_initError!,
style: theme.textTheme.bodyMedium,
textAlign: TextAlign.center,
),
const SizedBox(height: 24),
ElevatedButton.icon(
onPressed: _initializeChat,
icon: const Icon(Icons.refresh),
label: const Text('Réessayer'),
style: ElevatedButton.styleFrom(
backgroundColor: theme.colorScheme.error,
foregroundColor: Colors.white,
),
),
],
),
);
}
if (_isChatInitialized) {
// Afficher le module chat avec un header simplifié
return Column(
children: [
// En-tête simplifié avec boutons intégrés
Container(
height: 60,
padding: const EdgeInsets.symmetric(horizontal: 20),
decoration: BoxDecoration(
color: Colors.red.shade50,
border: Border(
bottom: BorderSide(
color: theme.dividerColor.withOpacity(0.1),
width: 1,
),
),
),
child: Row(
children: [
Icon(
Icons.admin_panel_settings,
color: Colors.red.shade600,
size: 24,
),
const SizedBox(width: 12),
Text(
'Messages Administration',
style: theme.textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w600,
color: Colors.red.shade600,
),
),
const Spacer(),
// Boutons d'action
IconButton(
icon: Icon(Icons.add, color: Colors.red.shade600),
onPressed: () {
// Déclencher la création d'une nouvelle conversation
// Cela sera géré par RoomsPageEmbedded
_roomsPageKey?.currentState?.createNewConversation();
},
tooltip: 'Nouvelle conversation',
),
IconButton(
icon: Icon(Icons.refresh, color: Colors.red.shade600),
onPressed: _refreshRooms,
tooltip: 'Actualiser',
),
],
),
),
// Module chat sans AppBar
Expanded(
child: RoomsPageEmbedded(
key: _roomsPageKey,
onRefreshPressed: () {
// Callback optionnel après refresh
debugPrint('Conversations actualisées');
},
),
),
],
);
}
// État initial
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.chat_bubble_outline,
size: 80,
color: theme.colorScheme.primary.withOpacity(0.3),
),
const SizedBox(height: 24),
Text(
'Chat administrateur non initialisé',
style: theme.textTheme.titleLarge?.copyWith(
color: theme.colorScheme.onSurface.withOpacity(0.5),
),
),
const SizedBox(height: 16),
ElevatedButton.icon(
onPressed: _initializeChat,
icon: const Icon(Icons.power_settings_new),
label: const Text('Initialiser le chat'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.white,
),
),
],
),
);
}
}