import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../bloc/onboarding_bloc.dart'; import '../../../../core/di/injection.dart'; import '../../../../features/authentication/presentation/bloc/auth_bloc.dart'; import '../../../../shared/design_system/tokens/unionflow_colors.dart'; import 'plan_selection_page.dart'; import 'period_selection_page.dart'; import 'subscription_summary_page.dart'; import 'payment_method_page.dart'; import 'wave_payment_page.dart'; import 'awaiting_validation_page.dart'; /// Page conteneur du workflow d'onboarding. /// Reçoit l'état initial du backend (onboardingState) et dispatch au bon écran. class OnboardingFlowPage extends StatelessWidget { final String onboardingState; final String? souscriptionId; final String organisationId; final String? typeOrganisation; const OnboardingFlowPage({ super.key, required this.onboardingState, required this.organisationId, this.typeOrganisation, this.souscriptionId, }); @override Widget build(BuildContext context) { return BlocProvider( create: (_) => getIt() ..add(OnboardingStarted( initialState: onboardingState, existingSouscriptionId: souscriptionId, typeOrganisation: typeOrganisation, organisationId: organisationId.isNotEmpty ? organisationId : null, )), child: const _OnboardingFlowView(), ); } } class _OnboardingFlowView extends StatelessWidget { const _OnboardingFlowView(); @override Widget build(BuildContext context) { return BlocConsumer( listener: (context, state) { // Paiement confirmé → re-check du statut (auto-activation backend) if (state is OnboardingPaiementConfirme) { context.read().add(const AuthStatusChecked()); } }, builder: (context, state) { if (state is OnboardingLoading || state is OnboardingInitial || state is OnboardingPaiementConfirme) { return Scaffold( backgroundColor: UnionFlowColors.background, body: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const CircularProgressIndicator( color: UnionFlowColors.unionGreen, ), const SizedBox(height: 16), Text( state is OnboardingPaiementConfirme ? 'Activation de votre compte…' : 'Chargement…', style: const TextStyle( color: UnionFlowColors.textSecondary, fontSize: 15, ), ), ], ), ), ); } if (state is OnboardingError) { return Scaffold( backgroundColor: UnionFlowColors.background, body: Center( child: Padding( padding: const EdgeInsets.all(32), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: 80, height: 80, decoration: BoxDecoration( color: UnionFlowColors.errorPale, shape: BoxShape.circle, ), child: const Icon(Icons.error_outline, size: 40, color: UnionFlowColors.error), ), const SizedBox(height: 20), Text( state.message, textAlign: TextAlign.center, style: const TextStyle( color: UnionFlowColors.textPrimary, fontSize: 15), ), const SizedBox(height: 24), ElevatedButton( onPressed: () => context.read().add( const OnboardingStarted( initialState: 'NO_SUBSCRIPTION'), ), style: ElevatedButton.styleFrom( backgroundColor: UnionFlowColors.unionGreen, foregroundColor: Colors.white, ), child: const Text('Réessayer'), ), ], ), ), ), ); } if (state is OnboardingStepFormule) { return PlanSelectionPage(formules: state.formules); } if (state is OnboardingStepPeriode) { return PeriodSelectionPage( codeFormule: state.codeFormule, plage: state.plage, formules: state.formules, ); } if (state is OnboardingStepSummary) { return SubscriptionSummaryPage(souscription: state.souscription); } if (state is OnboardingStepChoixPaiement) { return PaymentMethodPage(souscription: state.souscription); } if (state is OnboardingStepPaiement) { return WavePaymentPage( souscription: state.souscription, waveLaunchUrl: state.waveLaunchUrl, ); } if (state is OnboardingStepAttente) { return AwaitingValidationPage(souscription: state.souscription); } if (state is OnboardingRejected) { return _RejectedPage(commentaire: state.commentaire); } return const Scaffold( body: Center(child: CircularProgressIndicator()), ); }, ); } } class _RejectedPage extends StatelessWidget { final String? commentaire; const _RejectedPage({this.commentaire}); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: UnionFlowColors.background, body: SafeArea( child: Padding( padding: const EdgeInsets.all(32), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: 100, height: 100, decoration: BoxDecoration( color: UnionFlowColors.errorPale, shape: BoxShape.circle, ), child: const Icon(Icons.cancel_outlined, size: 52, color: UnionFlowColors.error), ), const SizedBox(height: 28), const Text( 'Demande rejetée', style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: UnionFlowColors.textPrimary, ), ), const SizedBox(height: 12), const Text( 'Votre demande de souscription a été refusée.', textAlign: TextAlign.center, style: TextStyle(color: UnionFlowColors.textSecondary), ), if (commentaire != null && commentaire!.isNotEmpty) ...[ const SizedBox(height: 20), Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: UnionFlowColors.errorPale, borderRadius: BorderRadius.circular(12), border: Border.all( color: UnionFlowColors.error.withOpacity(0.3)), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Icon(Icons.comment_outlined, color: UnionFlowColors.error, size: 18), const SizedBox(width: 10), Expanded( child: Text( commentaire!, style: const TextStyle( color: UnionFlowColors.textPrimary, fontSize: 14, height: 1.5), ), ), ], ), ), ], const SizedBox(height: 36), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () => context.read().add( const OnboardingStarted( initialState: 'NO_SUBSCRIPTION'), ), style: ElevatedButton.styleFrom( backgroundColor: UnionFlowColors.unionGreen, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), ), child: const Text('Soumettre une nouvelle demande', style: TextStyle(fontSize: 15)), ), ), const SizedBox(height: 12), TextButton( onPressed: () => context.read().add(const AuthLogoutRequested()), child: const Text('Se déconnecter', style: TextStyle(color: UnionFlowColors.textSecondary)), ), ], ), ), ), ); } }