import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import '../../../core/constants/design_system.dart'; import '../../../core/constants/env_config.dart'; import '../../../core/utils/page_transitions.dart'; import '../../../data/datasources/event_remote_data_source.dart'; import '../../../data/datasources/social_remote_data_source.dart'; import '../../../data/datasources/user_remote_data_source.dart'; import '../../../data/services/secure_storage.dart'; import '../../widgets/custom_snackbar.dart'; import '../../widgets/social/create_post_dialog.dart'; import '../event/event_screen.dart'; import 'social_content.dart'; /// Écran social avec design moderne et contenu enrichi. /// /// Cet écran affiche les posts sociaux, les stories, et les interactions /// avec une interface utilisateur optimisée et compacte. /// /// **Fonctionnalités:** /// - Affichage des posts sociaux /// - Stories /// - Interactions (like, comment, share) /// - Création de posts class SocialScreen extends StatefulWidget { const SocialScreen({super.key}); @override State createState() => _SocialScreenState(); } class _SocialScreenState extends State { late final SocialRemoteDataSource _socialDataSource; late final EventRemoteDataSource _eventDataSource; late final SecureStorage _secureStorage; late final UserRemoteDataSource _userDataSource; final ValueNotifier _refreshTrigger = ValueNotifier(0); String? _userId; @override void initState() { super.initState(); _socialDataSource = SocialRemoteDataSource(http.Client()); _eventDataSource = EventRemoteDataSource(http.Client()); _userDataSource = UserRemoteDataSource(http.Client()); _secureStorage = SecureStorage(); _loadUserId(); } @override void dispose() { _refreshTrigger.dispose(); super.dispose(); } /// Charge l'ID utilisateur depuis le stockage sécurisé Future _loadUserId() async { final userId = await _secureStorage.getUserId(); if (mounted) { setState(() { _userId = userId; }); } } @override Widget build(BuildContext context) { final theme = Theme.of(context); return Scaffold( appBar: _buildAppBar(theme), body: SocialContent( userId: _userId, refreshTrigger: _refreshTrigger, ), floatingActionButton: _buildFloatingActionButton(context, theme), ); } /// Construit la barre d'application. PreferredSizeWidget _buildAppBar(ThemeData theme) { return AppBar( elevation: 0, scrolledUnderElevation: 2, title: Text( 'Social', style: theme.textTheme.titleLarge?.copyWith( fontWeight: FontWeight.bold, letterSpacing: -0.5, ), ), actions: [ IconButton( icon: const Icon(Icons.search_rounded, size: 22), tooltip: 'Rechercher', onPressed: _handleSearch, ), IconButton( icon: const Icon(Icons.add_circle_outline_rounded, size: 22), tooltip: 'Créer un post', onPressed: _handleCreatePost, ), ], ); } /// Construit le bouton flottant (compact). Widget _buildFloatingActionButton(BuildContext context, ThemeData theme) { return FloatingActionButton( onPressed: _handleCreatePost, tooltip: 'Nouveau post', elevation: 2, child: const Icon(Icons.add_rounded, size: 26), ); } /// Gère la recherche. void _handleSearch() { final theme = Theme.of(context); showDialog( context: context, builder: (context) { final searchController = TextEditingController(); return AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(DesignSystem.radiusMd), ), title: Row( children: [ Icon( Icons.search_rounded, color: theme.colorScheme.primary, size: 24, ), const SizedBox(width: DesignSystem.spacingMd), const Text('Rechercher'), ], ), titleTextStyle: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, fontSize: 17, ), content: TextField( controller: searchController, decoration: InputDecoration( hintText: 'Posts, utilisateurs...', hintStyle: theme.textTheme.bodyMedium?.copyWith( color: theme.colorScheme.onSurface.withOpacity(0.4), fontSize: 14, ), prefixIcon: Icon( Icons.search_rounded, size: 20, color: theme.colorScheme.onSurface.withOpacity(0.5), ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(DesignSystem.radiusMd), ), contentPadding: const EdgeInsets.symmetric( horizontal: DesignSystem.spacingMd, vertical: DesignSystem.spacingSm, ), ), style: theme.textTheme.bodyMedium?.copyWith(fontSize: 14), autofocus: true, onSubmitted: (value) { Navigator.pop(context); _performSearch(value); }, ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Annuler'), ), FilledButton( onPressed: () { Navigator.pop(context); _performSearch(searchController.text); }, child: const Text('Rechercher'), ), ], ); }, ); } /// Effectue la recherche. Future _performSearch(String query) async { if (query.trim().isEmpty) { context.showWarning('Veuillez entrer un terme de recherche'); return; } if (EnvConfig.enableDetailedLogs) { debugPrint('[SocialScreen] Recherche: $query'); } try { // Rechercher dans les événements (endpoint disponible) final events = await _eventDataSource.searchEvents(query); // Rechercher dans les posts sociaux (quand l'endpoint sera disponible) // final posts = await _socialDataSource.searchPosts(query); if (mounted) { final totalResults = events.length; // + posts.length; if (totalResults > 0) { // Naviguer vers l'écran des événements avec les résultats final userId = await _secureStorage.getUserId(); if (userId != null && mounted) { await context.pushSlideRight( EventScreen( userId: userId, userFirstName: '', userLastName: '', profileImageUrl: '', ), ); } if (mounted) { context.showSuccess( '$totalResults résultat(s) trouvé(s) pour "$query"', ); } } else { context.showInfo('Aucun résultat trouvé pour "$query"'); } } } catch (e) { if (mounted) { context.showError('Erreur lors de la recherche: ${e.toString()}'); } } } /// Gère la création d'un post avec support d'images/vidéos. Future _handleCreatePost() async { // Récupérer les informations utilisateur pour l'affichage final userId = await _secureStorage.getUserId(); if (userId == null || userId.isEmpty) { if (mounted) { context.showWarning('Vous devez être connecté pour créer un post'); } return; } try { // Récupérer les vraies informations utilisateur depuis le backend final userModel = await _userDataSource.getUser(userId); final userName = '${userModel.userFirstName} ${userModel.userLastName}'; final userAvatarUrl = userModel.profileImageUrl; if (!mounted) return; await CreatePostDialog.show( context: context, onPostCreated: (content, medias) => _createPost(content, medias), userName: userName, userAvatarUrl: userAvatarUrl, ); } catch (e) { if (mounted) { context.showError( 'Erreur lors de la récupération des informations utilisateur: ${e.toString()}', ); } } } /// Crée un nouveau post avec contenu et médias. Future _createPost(String content, List medias) async { try { final userId = await _secureStorage.getUserId(); if (userId == null || userId.isEmpty) { if (mounted) { context.showWarning('Vous devez être connecté pour créer un post'); } return; } if (EnvConfig.enableDetailedLogs) { debugPrint('[SocialScreen] Création de post: $content'); debugPrint('[SocialScreen] Nombre de médias: ${medias.length}'); } // TODO: Uploader les médias et récupérer les URLs // Pour l'instant, on crée juste le post avec le contenu await _socialDataSource.createPost( content: content, userId: userId, ); if (mounted) { context.showSuccess('Post créé avec succès'); // Actualiser automatiquement la liste des posts _refreshTrigger.value++; } } catch (e) { if (mounted) { context.showError('Erreur lors de la création: ${e.toString()}'); } } } }