import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../widgets/shared/mini_header_bar.dart'; import '../../shared/widgets/core_card.dart'; import '../../shared/widgets/mini_avatar.dart'; import '../../shared/widgets/core_shimmer.dart'; import '../../shared/widgets/info_badge.dart'; import '../../shared/design_system/tokens/app_typography.dart'; import '../../shared/design_system/tokens/app_colors.dart'; import '../../core/di/injection.dart'; import '../../features/explore/presentation/bloc/network_bloc.dart'; import '../../features/explore/presentation/bloc/network_event.dart'; import '../../features/explore/presentation/bloc/network_state.dart'; /// UnionFlow Mobile - Onglet Réseau/Découverte (Mode DRY) /// Affiche les membres et organisations. Strict minimalisme. class NetworkPage extends StatelessWidget { const NetworkPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return BlocProvider( create: (_) => getIt()..add(LoadNetworkRequested()), child: const _NetworkView(), ); } } class _NetworkView extends StatefulWidget { const _NetworkView(); @override State<_NetworkView> createState() => _NetworkViewState(); } class _NetworkViewState extends State<_NetworkView> { final TextEditingController _searchController = TextEditingController(); @override void dispose() { _searchController.dispose(); super.dispose(); } void _onSearchChanged(String query) { context.read().add(SearchNetworkRequested(query)); } @override Widget build(BuildContext context) { final isDark = Theme.of(context).brightness == Brightness.dark; return Scaffold( appBar: const MiniHeaderBar(title: 'Réseau'), body: Column( children: [ // Barre de recherche collante (Twitter Style) Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( color: Theme.of(context).scaffoldBackgroundColor, border: Border( bottom: BorderSide( color: isDark ? AppColors.darkBorder : AppColors.lightBorder, width: 1, ), ), ), child: TextField( controller: _searchController, onChanged: _onSearchChanged, style: AppTypography.actionText, decoration: InputDecoration( hintText: 'Rechercher des membres, organisations...', hintStyle: AppTypography.subtitleSmall, prefixIcon: const Icon(Icons.search, size: 20, color: AppColors.textSecondaryLight), filled: true, fillColor: isDark ? AppColors.darkSurface : AppColors.lightSurface, contentPadding: const EdgeInsets.symmetric(vertical: 0), // Garder petit border: OutlineInputBorder( borderRadius: BorderRadius.circular(20), borderSide: BorderSide.none, ), ), ), ), Expanded( child: BlocBuilder( builder: (context, state) { if (state is NetworkInitial || state is NetworkLoading) { return const Padding( padding: EdgeInsets.all(8.0), child: CoreShimmer(itemCount: 6), ); } if (state is NetworkError) { return Center( child: Text( state.message, style: AppTypography.bodyTextSmall.copyWith(color: AppColors.error), ), ); } if (state is NetworkLoaded) { if (state.items.isEmpty) { return const Center( child: Text('Aucun résultat trouvé.', style: AppTypography.subtitleSmall), ); } return ListView.builder( padding: const EdgeInsets.all(8), itemCount: state.items.length, itemBuilder: (context, index) { final item = state.items[index]; return CoreCard( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: Row( children: [ MiniAvatar( imageUrl: item.avatarUrl, fallbackText: item.name.isNotEmpty ? item.name[0] : 'U', size: 40, isOnline: item.isConnected, // Pastille verte simulée ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item.name, style: AppTypography.actionText, maxLines: 1, overflow: TextOverflow.ellipsis, ), if (item.subtitle != null) Text( item.subtitle!, style: AppTypography.subtitleSmall, maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ), ), const SizedBox(width: 8), // Badge dynamique fonction du type ; tap pour Suivre / Ne plus suivre if (item.type == 'Organization') InfoBadge.neutral('Organisation') else GestureDetector( onTap: () { context.read().add(ToggleFollowRequested(item.id)); }, child: InfoBadge( text: item.isConnected ? 'Connecté' : 'Suivre', backgroundColor: item.isConnected ? AppColors.lightSurface : AppColors.primaryGreen, textColor: item.isConnected ? AppColors.textPrimaryLight : Colors.white, ), ), ], ), ); }, ); } return const SizedBox.shrink(); }, ), ), ], ), ); } }