## Tests BLoC (Task P2.4 Mobile) - 25 nouveaux fichiers *_bloc_test.dart + mocks générés (build_runner) - Features couvertes : authentication, admin_users, adhesions, backup, communication/messaging, contributions, dashboard, finance (approval/budget), events, explore/network, feed, logs_monitoring, notifications, onboarding, organizations (switcher/types/CRUD), profile, reports, settings, solidarity - ~380 tests, > 80% coverage BLoCs ## Sécurité Production (Task P2.2) - lib/core/security/app_integrity_service.dart (freerasp 7.5.1) - Migration API breaking changes freerasp 7.5.1 : - onRootDetected → onPrivilegedAccess - onDebuggerDetected → onDebug - onSignatureDetected → onAppIntegrity - onHookDetected → onHooks - onEmulatorDetected → onSimulator - onUntrustedInstallationSourceDetected → onUnofficialStore - onDeviceBindingDetected → onDeviceBinding - onObfuscationIssuesDetected → onObfuscationIssues - Talsec.start() split → start() + attachListener() - const AndroidConfig/IOSConfig → final (constructors call ConfigVerifier) - supportedAlternativeStores → supportedStores ## Pubspec - bloc_test: ^9.1.7 → ^10.0.0 (compat flutter_bloc ^9.0.0) - freerasp 7.5.1 ## Config - android/app/build.gradle : ajustements release - lib/core/config/environment.dart : URLs API actualisées - lib/main.dart + app_router : intégrations sécurité/BLoC ## Cleanup - Suppression docs intermédiaires (TACHES_*.md, TASK_*_COMPLETION_REPORT.md, TESTS_UNITAIRES_PROGRESS.md) - .g.dart régénérés (json_serializable) - .mocks.dart régénérés (mockito) ## Résultat - 142 fichiers, +27 596 insertions - Toutes les tâches P2 mobile complétées Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
112 lines
4.9 KiB
Dart
112 lines
4.9 KiB
Dart
/// Configuration centralisée des routes de l'application
|
|
///
|
|
/// Gère toutes les routes et la navigation de l'application UnionFlow
|
|
library app_router;
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import '../../features/authentication/presentation/bloc/auth_bloc.dart';
|
|
import '../../features/authentication/presentation/pages/login_page.dart';
|
|
import '../../features/about/presentation/pages/about_page.dart';
|
|
import '../../features/help/presentation/pages/help_support_page.dart';
|
|
import '../../features/profile/presentation/pages/profile_page_wrapper.dart';
|
|
import '../../features/organizations/presentation/pages/organizations_page_wrapper.dart';
|
|
import '../../features/members/presentation/pages/members_page_wrapper.dart';
|
|
import '../../features/events/presentation/pages/events_page_wrapper.dart';
|
|
import '../../features/solidarity/presentation/pages/demandes_aide_page_wrapper.dart';
|
|
import '../../features/contributions/presentation/pages/contributions_page_wrapper.dart';
|
|
import '../../features/reports/presentation/pages/reports_page_wrapper.dart';
|
|
import '../../features/adhesions/presentation/pages/adhesions_page_wrapper.dart';
|
|
import '../../features/settings/presentation/pages/system_settings_page.dart';
|
|
import '../../features/dashboard/presentation/pages/advanced_dashboard_page.dart';
|
|
import '../../features/admin/presentation/pages/user_management_page.dart';
|
|
import '../../features/communication/presentation/pages/conversations_page_wrapper.dart';
|
|
import '../../features/finance_workflow/presentation/pages/pending_approvals_page.dart';
|
|
import '../../features/finance_workflow/presentation/pages/budgets_list_page.dart';
|
|
import '../../core/navigation/main_navigation_layout.dart';
|
|
import '../../features/onboarding/presentation/pages/onboarding_flow_page.dart';
|
|
|
|
/// Configuration des routes de l'application
|
|
class AppRouter {
|
|
/// Routes principales de l'application
|
|
static Map<String, WidgetBuilder> get routes => {
|
|
'/': (context) => BlocConsumer<AuthBloc, AuthState>(
|
|
listener: (context, state) {
|
|
// Compte bloqué (SUSPENDU / DESACTIVE) → dialog informatif
|
|
if (state is AuthAccountNotActive) {
|
|
showDialog<void>(
|
|
context: context,
|
|
barrierDismissible: false,
|
|
builder: (dialogContext) => AlertDialog(
|
|
icon: const Icon(
|
|
Icons.lock_person_outlined,
|
|
color: Color(0xFFB71C1C),
|
|
size: 48,
|
|
),
|
|
title: const Text('Accès refusé'),
|
|
content: Text(state.message),
|
|
actions: [
|
|
ElevatedButton(
|
|
onPressed: () => Navigator.of(dialogContext).pop(),
|
|
child: const Text('OK'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
},
|
|
builder: (context, state) {
|
|
if (state is AuthLoading) {
|
|
return const Scaffold(
|
|
body: Center(child: CircularProgressIndicator()),
|
|
);
|
|
} else if (state is AuthAuthenticated) {
|
|
return const MainNavigationLayout();
|
|
} else if (state is AuthPendingOnboarding) {
|
|
// OrgAdmin EN_ATTENTE_VALIDATION → workflow d'onboarding
|
|
return OnboardingFlowPage(
|
|
onboardingState: state.onboardingState,
|
|
organisationId: state.organisationId ?? '',
|
|
souscriptionId: state.souscriptionId,
|
|
typeOrganisation: state.typeOrganisation,
|
|
);
|
|
} else {
|
|
return const LoginPage();
|
|
}
|
|
},
|
|
),
|
|
'/login': (context) => const LoginPage(),
|
|
'/about': (context) => const AboutPage(),
|
|
'/help': (context) => const HelpSupportPage(),
|
|
'/profile': (context) => const ProfilePageWrapper(),
|
|
'/organizations': (context) => const OrganizationsPageWrapper(),
|
|
'/members': (context) => const MembersPageWrapper(),
|
|
'/events': (context) => const EventsPageWrapper(),
|
|
'/solidarity': (context) => const DemandesAidePageWrapper(),
|
|
'/reports': (context) => const ReportsPageWrapper(),
|
|
'/finances': (context) => const CotisationsPageWrapper(),
|
|
'/adhesions': (context) => const AdhesionsPageWrapper(),
|
|
'/messages': (context) => const ConversationsPageWrapper(),
|
|
'/settings': (context) => const SystemSettingsPage(),
|
|
'/analytics': (context) {
|
|
final authState = context.read<AuthBloc>().state;
|
|
if (authState is AuthAuthenticated) {
|
|
final orgId = authState.user.organizationContexts.isNotEmpty
|
|
? authState.user.organizationContexts.first.organizationId
|
|
: '';
|
|
return AdvancedDashboardPage(
|
|
organizationId: orgId,
|
|
userId: authState.user.id,
|
|
);
|
|
}
|
|
return const LoginPage();
|
|
},
|
|
'/global-users': (context) => const UserManagementPage(),
|
|
'/approvals': (context) => const PendingApprovalsPage(),
|
|
'/budgets': (context) => const BudgetsListPage(),
|
|
};
|
|
|
|
/// Route initiale de l'application
|
|
static const String initialRoute = '/';
|
|
}
|