fix(mobile): URL changement mdp corrigée + v3.0 — multi-org, AppAuth, sécurité prod
Auth: - profile_repository.dart: /api/auth/change-password → /api/membres/auth/change-password Multi-org (Phase 3): - OrgSelectorPage, OrgSwitcherBloc, OrgSwitcherEntry - org_context_service.dart: headers X-Active-Organisation-Id + X-Active-Role Navigation: - MorePage: navigation conditionnelle par typeOrganisation - Suppression adaptive_navigation (remplacé par main_navigation_layout) Auth AppAuth: - keycloak_webview_auth_service: fixes AppAuth Android - AuthBloc: gestion REAUTH_REQUIS + premierLoginComplet Onboarding: - Nouveaux états: payment_method_page, onboarding_shared_widgets - SouscriptionStatusModel mis à jour StatutValidationSouscription Android: - build.gradle: ProGuard/R8, network_security_config - Gradle wrapper mis à jour
This commit is contained in:
@@ -18,9 +18,16 @@ abstract class OnboardingEvent extends Equatable {
|
||||
class OnboardingStarted extends OnboardingEvent {
|
||||
final String? existingSouscriptionId;
|
||||
final String initialState; // NO_SUBSCRIPTION | AWAITING_PAYMENT | PAYMENT_INITIATED | AWAITING_VALIDATION
|
||||
const OnboardingStarted({required this.initialState, this.existingSouscriptionId});
|
||||
final String? typeOrganisation;
|
||||
final String? organisationId;
|
||||
const OnboardingStarted({
|
||||
required this.initialState,
|
||||
this.existingSouscriptionId,
|
||||
this.typeOrganisation,
|
||||
this.organisationId,
|
||||
});
|
||||
@override
|
||||
List<Object?> get props => [initialState, existingSouscriptionId];
|
||||
List<Object?> get props => [initialState, existingSouscriptionId, typeOrganisation, organisationId];
|
||||
}
|
||||
|
||||
/// L'utilisateur a sélectionné une formule et une plage
|
||||
@@ -51,6 +58,11 @@ class OnboardingDemandeConfirmee extends OnboardingEvent {
|
||||
const OnboardingDemandeConfirmee();
|
||||
}
|
||||
|
||||
/// Ouvre l'écran de choix du moyen de paiement (depuis le récapitulatif)
|
||||
class OnboardingChoixPaiementOuvert extends OnboardingEvent {
|
||||
const OnboardingChoixPaiementOuvert();
|
||||
}
|
||||
|
||||
/// Initie le paiement Wave
|
||||
class OnboardingPaiementInitie extends OnboardingEvent {
|
||||
const OnboardingPaiementInitie();
|
||||
@@ -109,6 +121,14 @@ class OnboardingStepSummary extends OnboardingState {
|
||||
List<Object?> get props => [souscription];
|
||||
}
|
||||
|
||||
/// Étape 3b : choix du moyen de paiement (Wave, Orange Money, etc.)
|
||||
class OnboardingStepChoixPaiement extends OnboardingState {
|
||||
final SouscriptionStatusModel souscription;
|
||||
const OnboardingStepChoixPaiement(this.souscription);
|
||||
@override
|
||||
List<Object?> get props => [souscription];
|
||||
}
|
||||
|
||||
/// Étape 4 : paiement Wave — URL à ouvrir dans le navigateur
|
||||
class OnboardingStepPaiement extends OnboardingState {
|
||||
final SouscriptionStatusModel souscription;
|
||||
@@ -118,6 +138,9 @@ class OnboardingStepPaiement extends OnboardingState {
|
||||
List<Object?> get props => [souscription, waveLaunchUrl];
|
||||
}
|
||||
|
||||
/// Paiement confirmé — déclenche un re-check du statut du compte
|
||||
class OnboardingPaiementConfirme extends OnboardingState {}
|
||||
|
||||
/// Étape 5 : en attente de validation SuperAdmin
|
||||
class OnboardingStepAttente extends OnboardingState {
|
||||
final SouscriptionStatusModel? souscription;
|
||||
@@ -145,7 +168,7 @@ class OnboardingBloc extends Bloc<OnboardingEvent, OnboardingState> {
|
||||
String? _codeFormule;
|
||||
String? _plage;
|
||||
String? _typePeriode;
|
||||
String? _typeOrganisation;
|
||||
String _typeOrganisation = '';
|
||||
String? _organisationId;
|
||||
SouscriptionStatusModel? _souscription;
|
||||
|
||||
@@ -154,12 +177,19 @@ class OnboardingBloc extends Bloc<OnboardingEvent, OnboardingState> {
|
||||
on<OnboardingFormuleSelected>(_onFormuleSelected);
|
||||
on<OnboardingPeriodeSelected>(_onPeriodeSelected);
|
||||
on<OnboardingDemandeConfirmee>(_onDemandeConfirmee);
|
||||
on<OnboardingChoixPaiementOuvert>(_onChoixPaiementOuvert);
|
||||
on<OnboardingPaiementInitie>(_onPaiementInitie);
|
||||
on<OnboardingRetourDepuisWave>(_onRetourDepuisWave);
|
||||
}
|
||||
|
||||
Future<void> _onStarted(OnboardingStarted event, Emitter<OnboardingState> emit) async {
|
||||
emit(OnboardingLoading());
|
||||
if (event.typeOrganisation != null && event.typeOrganisation!.isNotEmpty) {
|
||||
_typeOrganisation = event.typeOrganisation!;
|
||||
}
|
||||
if (event.organisationId != null && event.organisationId!.isNotEmpty) {
|
||||
_organisationId = event.organisationId;
|
||||
}
|
||||
try {
|
||||
_formules = await _datasource.getFormules();
|
||||
|
||||
@@ -189,6 +219,7 @@ class OnboardingBloc extends Bloc<OnboardingEvent, OnboardingState> {
|
||||
}
|
||||
|
||||
case 'AWAITING_VALIDATION':
|
||||
case 'VALIDATED': // Paiement confirmé mais activation compte non encore effective
|
||||
final sosc = await _datasource.getMaSouscription();
|
||||
_souscription = sosc;
|
||||
emit(OnboardingStepAttente(souscription: sosc));
|
||||
@@ -218,14 +249,23 @@ class OnboardingBloc extends Bloc<OnboardingEvent, OnboardingState> {
|
||||
|
||||
void _onPeriodeSelected(OnboardingPeriodeSelected event, Emitter<OnboardingState> emit) {
|
||||
_typePeriode = event.typePeriode;
|
||||
_typeOrganisation = event.typeOrganisation;
|
||||
// typeOrganisation already set from OnboardingStarted; override only if event provides one
|
||||
if (event.typeOrganisation.isNotEmpty) {
|
||||
_typeOrganisation = event.typeOrganisation;
|
||||
}
|
||||
_organisationId = event.organisationId;
|
||||
}
|
||||
|
||||
void _onChoixPaiementOuvert(OnboardingChoixPaiementOuvert event, Emitter<OnboardingState> emit) {
|
||||
if (_souscription != null) {
|
||||
emit(OnboardingStepChoixPaiement(_souscription!));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onDemandeConfirmee(
|
||||
OnboardingDemandeConfirmee event, Emitter<OnboardingState> emit) async {
|
||||
if (_codeFormule == null || _plage == null || _typePeriode == null ||
|
||||
_typeOrganisation == null || _organisationId == null) {
|
||||
_organisationId == null) {
|
||||
emit(const OnboardingError('Données manquantes. Recommencez depuis le début.'));
|
||||
return;
|
||||
}
|
||||
@@ -235,7 +275,7 @@ class OnboardingBloc extends Bloc<OnboardingEvent, OnboardingState> {
|
||||
typeFormule: _codeFormule!,
|
||||
plageMembres: _plage!,
|
||||
typePeriode: _typePeriode!,
|
||||
typeOrganisation: _typeOrganisation!,
|
||||
typeOrganisation: _typeOrganisation.isNotEmpty ? _typeOrganisation : null,
|
||||
organisationId: _organisationId!,
|
||||
);
|
||||
if (sosc != null) {
|
||||
@@ -281,12 +321,11 @@ class OnboardingBloc extends Bloc<OnboardingEvent, OnboardingState> {
|
||||
if (souscId != null) {
|
||||
await _datasource.confirmerPaiement(souscId);
|
||||
}
|
||||
final sosc = await _datasource.getMaSouscription();
|
||||
_souscription = sosc;
|
||||
emit(OnboardingStepAttente(souscription: sosc));
|
||||
// Émettre OnboardingPaiementConfirme pour déclencher re-check du compte
|
||||
// Si le backend auto-active le compte, AuthStatusChecked redirigera vers dashboard
|
||||
emit(OnboardingPaiementConfirme());
|
||||
} catch (e) {
|
||||
// En cas d'erreur, on affiche quand même l'écran d'attente
|
||||
emit(OnboardingStepAttente(souscription: _souscription));
|
||||
emit(OnboardingPaiementConfirme());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user