Files
geo/app/lib/presentation/user/user_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

183 lines
5.0 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/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 UserCommunicationPage extends StatefulWidget {
const UserCommunicationPage({super.key});
@override
State<UserCommunicationPage> createState() => _UserCommunicationPageState();
}
class _UserCommunicationPageState extends State<UserCommunicationPage> {
bool _isChatInitialized = false;
bool _isInitializing = false;
String? _initError;
@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('Utilisateur non connecté');
}
// Initialiser le module chat avec les informations de l'utilisateur
await ChatModule.init(
apiUrl: apiService.baseUrl,
userId: currentUser.currentUser!.id,
userName: currentUser.userName ?? currentUser.userEmail ?? 'Utilisateur',
userRole: currentUser.currentUser!.role,
userEntite: currentUser.fkEntite ?? currentAmicale?.id,
authToken: currentUser.sessionId,
);
setState(() {
_isChatInitialized = true;
_isInitializing = false;
});
} catch (e) {
setState(() {
_initError = e.toString();
_isInitializing = false;
});
debugPrint('Erreur initialisation chat: $e');
}
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Scaffold(
backgroundColor: Colors.transparent,
body: 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...',
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',
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'),
),
],
),
);
}
if (_isChatInitialized) {
// Afficher directement le module chat
return ChatModule.getRoomsPage();
}
// É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 non initialisé',
style: theme.textTheme.titleLarge?.copyWith(
color: theme.colorScheme.onSurface.withOpacity(0.5),
),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _initializeChat,
child: const Text('Initialiser le chat'),
),
],
),
);
}
@override
void dispose() {
// Ne pas disposer le chat ici car il est partagé
super.dispose();
}
}