Initial commit: unionflow-mobile-apps

Application Flutter complète (sans build artifacts).

Signed-off-by: lions dev Team
This commit is contained in:
dahoud
2026-03-15 16:30:08 +00:00
commit d094d6db9c
1790 changed files with 507435 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:injectable/injectable.dart';
import '../../../../core/utils/logger.dart';
import '../../data/repositories/network_repository.dart';
import 'network_event.dart';
import 'network_state.dart';
@injectable
class NetworkBloc extends Bloc<NetworkEvent, NetworkState> {
final NetworkRepository _repository;
NetworkBloc(this._repository) : super(NetworkInitial()) {
on<LoadNetworkRequested>(_onLoadNetworkRequested);
on<SearchNetworkRequested>(_onSearchNetworkRequested);
on<ToggleFollowRequested>(_onToggleFollowRequested);
}
Future<void> _onToggleFollowRequested(ToggleFollowRequested event, Emitter<NetworkState> emit) async {
if (state is! NetworkLoaded) return;
final current = state as NetworkLoaded;
NetworkItem? item;
for (final i in current.items) {
if (i.id == event.itemId) {
item = i;
break;
}
}
if (item == null) return;
// Seuls les membres (type Member) sont persistés côté backend ; Organisation reste local.
if (item.type != 'Member') {
final items = current.items.map((i) {
if (i.id == event.itemId) return i.copyWith(isConnected: !i.isConnected);
return i;
}).toList();
emit(NetworkLoaded(items: items, currentQuery: current.currentQuery));
return;
}
try {
final bool newFollowing = item.isConnected
? await _repository.unfollow(event.itemId)
: await _repository.follow(event.itemId);
final items = current.items.map((i) {
if (i.id == event.itemId) return i.copyWith(isConnected: newFollowing);
return i;
}).toList();
emit(NetworkLoaded(items: items, currentQuery: current.currentQuery));
} catch (e, st) {
AppLogger.error('NetworkBloc: toggle follow échoué', error: e, stackTrace: st);
emit(const NetworkError('Impossible de mettre à jour le suivi. Réessayez.'));
}
}
Future<void> _onLoadNetworkRequested(LoadNetworkRequested event, Emitter<NetworkState> emit) async {
emit(NetworkLoading());
try {
final followedIds = await _repository.getFollowedIds();
final items = await _repository.search('', followedIds: followedIds.toSet());
emit(NetworkLoaded(items: items, currentQuery: ''));
} catch (e, st) {
AppLogger.error('NetworkBloc: chargement réseau échoué', error: e, stackTrace: st);
emit(NetworkError('Erreur chargement réseau : $e'));
}
}
Future<void> _onSearchNetworkRequested(SearchNetworkRequested event, Emitter<NetworkState> emit) async {
emit(NetworkLoading());
try {
if (event.query.trim().isEmpty) {
final followedIds = await _repository.getFollowedIds();
final items = await _repository.search('', followedIds: followedIds.toSet());
emit(NetworkLoaded(items: items, currentQuery: ''));
return;
}
final followedIds = await _repository.getFollowedIds();
final items = await _repository.search(event.query, followedIds: followedIds.toSet());
emit(NetworkLoaded(items: items, currentQuery: event.query));
} catch (e, st) {
AppLogger.error('NetworkBloc: recherche réseau échouée', error: e, stackTrace: st);
emit(NetworkError('Erreur de recherche : $e'));
}
}
}

View File

@@ -0,0 +1,29 @@
import 'package:equatable/equatable.dart';
abstract class NetworkEvent extends Equatable {
const NetworkEvent();
@override
List<Object> get props => [];
}
class LoadNetworkRequested extends NetworkEvent {}
class SearchNetworkRequested extends NetworkEvent {
final String query;
const SearchNetworkRequested(this.query);
@override
List<Object> get props => [query];
}
/// Bascule Suivre / Ne plus suivre pour un item (membre ou organisation).
class ToggleFollowRequested extends NetworkEvent {
final String itemId;
const ToggleFollowRequested(this.itemId);
@override
List<Object> get props => [itemId];
}

View File

@@ -0,0 +1,38 @@
import 'package:equatable/equatable.dart';
import '../../domain/entities/network_item.dart';
export '../../domain/entities/network_item.dart';
abstract class NetworkState extends Equatable {
const NetworkState();
@override
List<Object?> get props => [];
}
class NetworkInitial extends NetworkState {}
class NetworkLoading extends NetworkState {}
class NetworkLoaded extends NetworkState {
final List<NetworkItem> items;
final String currentQuery;
const NetworkLoaded({
required this.items,
this.currentQuery = '',
});
@override
List<Object?> get props => [items, currentQuery];
}
class NetworkError extends NetworkState {
final String message;
const NetworkError(this.message);
@override
List<Object?> get props => [message];
}