import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../bloc/onboarding_bloc.dart'; import '../../data/models/souscription_status_model.dart'; import '../../../../shared/design_system/tokens/unionflow_colors.dart'; /// Écran de sélection du moyen de paiement class PaymentMethodPage extends StatefulWidget { final SouscriptionStatusModel souscription; const PaymentMethodPage({super.key, required this.souscription}); @override State createState() => _PaymentMethodPageState(); } class _PaymentMethodPageState extends State { String? _selected; static const _methods = [ _PayMethod( id: 'WAVE', name: 'Wave Mobile Money', description: 'Paiement rapide via votre compte Wave', logoAsset: 'assets/images/payment_methods/wave/logo.png', color: Color(0xFF00B9F1), available: true, badge: 'Recommandé', ), _PayMethod( id: 'ORANGE_MONEY', name: 'Orange Money', description: 'Paiement via Orange Money', logoAsset: 'assets/images/payment_methods/orange_money/logo-black.png', color: Color(0xFFFF6600), available: false, badge: 'Prochainement', ), ]; @override Widget build(BuildContext context) { final montant = widget.souscription.montantTotal ?? 0; return Scaffold( backgroundColor: UnionFlowColors.background, body: Column( children: [ // Header Container( decoration: const BoxDecoration( gradient: UnionFlowColors.primaryGradient, ), child: SafeArea( bottom: false, child: Padding( padding: const EdgeInsets.fromLTRB(20, 16, 20, 24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ IconButton( onPressed: () => Navigator.of(context).maybePop(), icon: const Icon(Icons.arrow_back_rounded, color: Colors.white), padding: EdgeInsets.zero, constraints: const BoxConstraints(), ), const SizedBox(height: 12), const Text( 'Moyen de paiement', style: TextStyle( color: Colors.white, fontSize: 24, fontWeight: FontWeight.w800, ), ), const SizedBox(height: 4), Text( 'Choisissez comment régler votre souscription', style: TextStyle( color: Colors.white.withOpacity(0.8), fontSize: 13), ), ], ), ), ), ), Expanded( child: SingleChildScrollView( padding: const EdgeInsets.fromLTRB(20, 24, 20, 100), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Montant rappel Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: UnionFlowColors.surface, borderRadius: BorderRadius.circular(14), boxShadow: UnionFlowColors.softShadow, ), child: Row( children: [ Container( width: 44, height: 44, decoration: BoxDecoration( gradient: UnionFlowColors.goldGradient, borderRadius: BorderRadius.circular(10), ), child: const Icon(Icons.receipt_rounded, color: Colors.white, size: 22), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Montant total', style: TextStyle( color: UnionFlowColors.textSecondary, fontSize: 12), ), Text( '${_formatPrix(montant)} FCFA', style: const TextStyle( color: UnionFlowColors.textPrimary, fontSize: 20, fontWeight: FontWeight.w900, ), ), ], ), ), if (widget.souscription.organisationNom != null) Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ const Text( 'Organisation', style: TextStyle( color: UnionFlowColors.textSecondary, fontSize: 11), ), Text( widget.souscription.organisationNom!, style: const TextStyle( color: UnionFlowColors.textPrimary, fontSize: 12, fontWeight: FontWeight.w600), ), ], ), ], ), ), const SizedBox(height: 24), const Text( 'Sélectionnez un moyen de paiement', style: TextStyle( color: UnionFlowColors.textPrimary, fontWeight: FontWeight.w700, fontSize: 15, ), ), const SizedBox(height: 12), ..._methods.map((m) => _MethodCard( method: m, selected: _selected == m.id, onTap: m.available ? () => setState(() => _selected = m.id) : null, )), const SizedBox(height: 20), Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: UnionFlowColors.unionGreenPale, borderRadius: BorderRadius.circular(12), border: Border.all( color: UnionFlowColors.unionGreen.withOpacity(0.25)), ), child: const Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon(Icons.lock_rounded, color: UnionFlowColors.unionGreen, size: 18), SizedBox(width: 10), Expanded( child: Text( 'Vos informations de paiement sont sécurisées et ne sont jamais stockées sur nos serveurs. La transaction est traitée directement par Wave.', style: TextStyle( fontSize: 12, color: UnionFlowColors.unionGreen, height: 1.4), ), ), ], ), ), ], ), ), ), ], ), bottomNavigationBar: Container( padding: EdgeInsets.fromLTRB( 20, 12, 20, MediaQuery.of(context).padding.bottom + 12), decoration: BoxDecoration( color: UnionFlowColors.surface, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.08), blurRadius: 12, offset: const Offset(0, -4), ), ], ), child: SizedBox( width: double.infinity, child: ElevatedButton.icon( onPressed: _selected == 'WAVE' ? () => context .read() .add(const OnboardingPaiementInitie()) : null, icon: const Icon(Icons.open_in_new_rounded), label: Text( _selected == 'WAVE' ? 'Payer avec Wave' : 'Sélectionnez un moyen de paiement', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w700), ), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF00B9F1), disabledBackgroundColor: UnionFlowColors.border, foregroundColor: Colors.white, disabledForegroundColor: UnionFlowColors.textSecondary, padding: const EdgeInsets.symmetric(vertical: 15), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14)), elevation: _selected == 'WAVE' ? 3 : 0, shadowColor: const Color(0xFF00B9F1).withOpacity(0.4), ), ), ), ), ); } String _formatPrix(double prix) { if (prix >= 1000000) return '${(prix / 1000000).toStringAsFixed(1)} M'; final s = prix.toStringAsFixed(0); if (s.length > 3) { return '${s.substring(0, s.length - 3)} ${s.substring(s.length - 3)}'; } return s; } } class _PayMethod { final String id, name, description, logoAsset; final Color color; final bool available; final String badge; const _PayMethod({ required this.id, required this.name, required this.description, required this.logoAsset, required this.color, required this.available, required this.badge, }); } class _MethodCard extends StatelessWidget { final _PayMethod method; final bool selected; final VoidCallback? onTap; const _MethodCard({ required this.method, required this.selected, this.onTap, }); @override Widget build(BuildContext context) { final disabled = onTap == null; return GestureDetector( onTap: onTap, child: AnimatedContainer( duration: const Duration(milliseconds: 200), margin: const EdgeInsets.only(bottom: 10), decoration: BoxDecoration( color: disabled ? UnionFlowColors.surfaceVariant : selected ? method.color.withOpacity(0.06) : UnionFlowColors.surface, border: Border.all( color: selected ? method.color : UnionFlowColors.border, width: selected ? 2 : 1, ), borderRadius: BorderRadius.circular(14), boxShadow: disabled ? [] : selected ? [ BoxShadow( color: method.color.withOpacity(0.15), blurRadius: 16, offset: const Offset(0, 6), ) ] : UnionFlowColors.softShadow, ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), child: Row( children: [ // Logo image Container( width: 56, height: 48, decoration: BoxDecoration( color: disabled ? UnionFlowColors.border : Colors.white, borderRadius: BorderRadius.circular(10), border: Border.all(color: UnionFlowColors.border), ), padding: const EdgeInsets.all(6), child: Image.asset( method.logoAsset, fit: BoxFit.contain, color: disabled ? UnionFlowColors.textTertiary : null, colorBlendMode: disabled ? BlendMode.srcIn : null, errorBuilder: (_, __, ___) => Icon( Icons.account_balance_wallet_rounded, color: disabled ? UnionFlowColors.textTertiary : method.color, size: 24, ), ), ), const SizedBox(width: 14), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( method.name, style: TextStyle( fontWeight: FontWeight.w700, fontSize: 14, color: disabled ? UnionFlowColors.textTertiary : UnionFlowColors.textPrimary, ), ), Text( method.description, style: TextStyle( fontSize: 12, color: disabled ? UnionFlowColors.textTertiary : UnionFlowColors.textSecondary, ), ), ], ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 3), decoration: BoxDecoration( color: disabled ? UnionFlowColors.border : method.available ? method.color.withOpacity(0.1) : UnionFlowColors.surfaceVariant, borderRadius: BorderRadius.circular(20), ), child: Text( method.badge, style: TextStyle( fontSize: 10, fontWeight: FontWeight.w700, color: disabled ? UnionFlowColors.textTertiary : method.available ? method.color : UnionFlowColors.textSecondary, ), ), ), if (!disabled) ...[ const SizedBox(height: 6), Icon( selected ? Icons.check_circle_rounded : Icons.radio_button_unchecked, color: selected ? method.color : UnionFlowColors.border, size: 20, ), ], ], ), ], ), ), ), ); } }