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'; /// Étape 3 — Récapitulatif détaillé avant paiement class SubscriptionSummaryPage extends StatelessWidget { final SouscriptionStatusModel souscription; const SubscriptionSummaryPage({super.key, required this.souscription}); static const _periodeLabels = { 'MENSUEL': 'Mensuel', 'TRIMESTRIEL': 'Trimestriel', 'SEMESTRIEL': 'Semestriel', 'ANNUEL': 'Annuel', }; static const _periodeRemises = { 'MENSUEL': null, 'TRIMESTRIEL': '–5% de remise', 'SEMESTRIEL': '–10% de remise', 'ANNUEL': '–20% de remise', }; static const _orgLabels = { 'ASSOCIATION': 'Association / ONG locale', 'MUTUELLE': 'Mutuelle (santé, fonctionnaires…)', 'COOPERATIVE': 'Coopérative / Microfinance', 'FEDERATION': 'Fédération / Grande ONG', }; static const _plageLabels = { 'PETITE': '1–100 membres', 'MOYENNE': '101–500 membres', 'GRANDE': '501–2 000 membres', 'TRES_GRANDE': '2 000+ membres', }; @override Widget build(BuildContext context) { final montant = souscription.montantTotal ?? 0; final remise = _periodeRemises[souscription.typePeriode]; return Scaffold( backgroundColor: UnionFlowColors.background, body: Column( children: [ // Header hero Container( decoration: const BoxDecoration( gradient: UnionFlowColors.primaryGradient, ), child: SafeArea( bottom: false, child: Padding( padding: const EdgeInsets.fromLTRB(20, 12, 20, 32), child: Column( children: [ // Step bar Row( children: List.generate(3, (i) => Expanded( child: Container( height: 4, margin: EdgeInsets.only(right: i < 2 ? 6 : 0), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(2), ), ), )), ), const SizedBox(height: 6), Align( alignment: Alignment.centerLeft, child: Text( 'Étape 3 sur 3', style: TextStyle( color: Colors.white.withOpacity(0.75), fontSize: 12, fontWeight: FontWeight.w500, ), ), ), const SizedBox(height: 20), // Montant principal Container( width: 90, height: 90, decoration: BoxDecoration( color: Colors.white.withOpacity(0.15), shape: BoxShape.circle, border: Border.all( color: Colors.white.withOpacity(0.4), width: 2), ), child: const Icon(Icons.receipt_long_rounded, color: Colors.white, size: 44), ), const SizedBox(height: 14), Text( _formatPrix(montant), style: const TextStyle( color: Colors.white, fontSize: 40, fontWeight: FontWeight.w900, letterSpacing: -1, ), ), const Text( 'FCFA à régler', style: TextStyle( color: Colors.white70, fontSize: 14, fontWeight: FontWeight.w500), ), if (remise != null) ...[ const SizedBox(height: 8), Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 4), decoration: BoxDecoration( color: UnionFlowColors.gold.withOpacity(0.3), borderRadius: BorderRadius.circular(20), border: Border.all( color: UnionFlowColors.goldLight.withOpacity(0.5)), ), child: Text( remise, style: const TextStyle( color: UnionFlowColors.goldLight, fontSize: 12, fontWeight: FontWeight.w700, ), ), ), ], ], ), ), ), ), // Content Expanded( child: SingleChildScrollView( padding: const EdgeInsets.fromLTRB(20, 20, 20, 100), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Organisation if (souscription.organisationNom != null) ...[ _DetailCard( title: 'Organisation', icon: Icons.business_rounded, iconColor: UnionFlowColors.indigo, items: [ _DetailItem( label: 'Nom', value: souscription.organisationNom!, bold: true), _DetailItem( label: 'Type', value: _orgLabels[souscription.typeOrganisation] ?? souscription.typeOrganisation), ], ), const SizedBox(height: 14), ], // Formule _DetailCard( title: 'Formule souscrite', icon: Icons.workspace_premium_rounded, iconColor: UnionFlowColors.gold, items: [ _DetailItem( label: 'Niveau', value: souscription.typeFormule, bold: true), _DetailItem( label: 'Taille', value: _plageLabels[souscription.plageMembres] ?? souscription.plageLibelle), if (souscription.montantMensuelBase != null) _DetailItem( label: 'Prix de base', value: '${_formatPrix(souscription.montantMensuelBase!)} FCFA/mois'), ], ), const SizedBox(height: 14), // Facturation _DetailCard( title: 'Facturation', icon: Icons.calendar_today_rounded, iconColor: UnionFlowColors.unionGreen, items: [ _DetailItem( label: 'Période', value: _periodeLabels[souscription.typePeriode] ?? souscription.typePeriode), if (souscription.coefficientApplique != null) _DetailItem( label: 'Coefficient', value: '×${souscription.coefficientApplique!.toStringAsFixed(4)}'), if (souscription.dateDebut != null && souscription.dateFin != null) ...[ _DetailItem( label: 'Début', value: _formatDate(souscription.dateDebut!)), _DetailItem( label: 'Fin', value: _formatDate(souscription.dateFin!)), ], ], ), const SizedBox(height: 14), // Montant total Container( padding: const EdgeInsets.all(18), decoration: BoxDecoration( color: UnionFlowColors.goldPale, borderRadius: BorderRadius.circular(16), border: Border.all( color: UnionFlowColors.gold.withOpacity(0.4)), boxShadow: UnionFlowColors.goldGlowShadow, ), child: Row( children: [ Container( width: 48, height: 48, decoration: BoxDecoration( gradient: UnionFlowColors.goldGradient, borderRadius: BorderRadius.circular(12), ), child: const Icon(Icons.monetization_on_rounded, color: Colors.white, size: 26), ), const SizedBox(width: 14), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Total à payer', style: TextStyle( color: UnionFlowColors.textSecondary, fontSize: 13), ), Text( '${_formatPrix(montant)} FCFA', style: const TextStyle( color: UnionFlowColors.textPrimary, fontSize: 22, fontWeight: FontWeight.w900, ), ), ], ), ), ], ), ), const SizedBox(height: 20), // Notes importantes _NoteBox( icon: Icons.security_rounded, iconColor: UnionFlowColors.unionGreen, backgroundColor: UnionFlowColors.unionGreenPale, borderColor: UnionFlowColors.unionGreen.withOpacity(0.25), title: 'Paiement sécurisé', message: 'Votre paiement est traité de manière sécurisée via Wave Mobile Money. Une fois le paiement effectué, votre compte sera activé automatiquement.', ), const SizedBox(height: 10), _NoteBox( icon: Icons.bolt_rounded, iconColor: UnionFlowColors.amber, backgroundColor: const Color(0xFFFFFBF0), borderColor: UnionFlowColors.amber.withOpacity(0.3), title: 'Activation immédiate', message: 'Dès que le paiement est confirmé par Wave, votre compte d\'administrateur est activé et vous pouvez accéder à toutes les fonctionnalités de votre formule.', ), const SizedBox(height: 10), _NoteBox( icon: Icons.support_agent_rounded, iconColor: UnionFlowColors.info, backgroundColor: UnionFlowColors.infoPale, borderColor: UnionFlowColors.info.withOpacity(0.2), title: 'Besoin d\'aide ?', message: 'En cas de problème lors du paiement, contactez notre support à support@unionflow.app — nous vous répondrons sous 24h.', ), ], ), ), ), ], ), 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: () => context .read() .add(const OnboardingChoixPaiementOuvert()), icon: const Icon(Icons.payment_rounded), label: const Text( 'Choisir le moyen de paiement', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w700), ), style: ElevatedButton.styleFrom( backgroundColor: UnionFlowColors.unionGreen, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 15), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14)), shadowColor: UnionFlowColors.unionGreen.withOpacity(0.4), elevation: 3, ), ), ), ), ); } String _formatPrix(double prix) { if (prix >= 1000000) return '${(prix / 1000000).toStringAsFixed(1)} M'; final s = prix.toStringAsFixed(0); if (s.length > 6) { return '${s.substring(0, s.length - 6)} ${s.substring(s.length - 6, s.length - 3)} ${s.substring(s.length - 3)}'; } if (s.length > 3) { return '${s.substring(0, s.length - 3)} ${s.substring(s.length - 3)}'; } return s; } String _formatDate(DateTime date) { return '${date.day.toString().padLeft(2, '0')}/${date.month.toString().padLeft(2, '0')}/${date.year}'; } } // ─── Widgets locaux ────────────────────────────────────────────────────────── class _DetailItem { final String label; final String value; final bool bold; const _DetailItem( {required this.label, required this.value, this.bold = false}); } class _DetailCard extends StatelessWidget { final String title; final IconData icon; final Color iconColor; final List<_DetailItem> items; const _DetailCard({ required this.title, required this.icon, required this.iconColor, required this.items, }); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: UnionFlowColors.surface, borderRadius: BorderRadius.circular(16), boxShadow: UnionFlowColors.softShadow, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.fromLTRB(16, 14, 16, 10), child: Row( children: [ Container( width: 34, height: 34, decoration: BoxDecoration( color: iconColor.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: Icon(icon, color: iconColor, size: 18), ), const SizedBox(width: 10), Text( title, style: const TextStyle( fontWeight: FontWeight.w700, fontSize: 14, color: UnionFlowColors.textPrimary, ), ), ], ), ), const Divider(height: 1, color: UnionFlowColors.border), Padding( padding: const EdgeInsets.fromLTRB(16, 12, 16, 14), child: Column( children: items.map((item) => Padding( padding: const EdgeInsets.only(bottom: 8), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 120, child: Text( item.label, style: const TextStyle( color: UnionFlowColors.textSecondary, fontSize: 13), ), ), Expanded( child: Text( item.value, style: TextStyle( color: UnionFlowColors.textPrimary, fontSize: 13, fontWeight: item.bold ? FontWeight.w700 : FontWeight.w500, ), ), ), ], ), )).toList(), ), ), ], ), ); } } class _NoteBox extends StatelessWidget { final IconData icon; final Color iconColor; final Color backgroundColor; final Color borderColor; final String title; final String message; const _NoteBox({ required this.icon, required this.iconColor, required this.backgroundColor, required this.borderColor, required this.title, required this.message, }); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: backgroundColor, borderRadius: BorderRadius.circular(12), border: Border.all(color: borderColor), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon(icon, color: iconColor, size: 20), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle( color: iconColor, fontWeight: FontWeight.w700, fontSize: 13, ), ), const SizedBox(height: 3), Text( message, style: const TextStyle( color: UnionFlowColors.textSecondary, fontSize: 12, height: 1.5), ), ], ), ), ], ), ); } }