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/app_colors.dart'; import '../../../../shared/design_system/tokens/unionflow_colors.dart'; import 'onboarding_shared_widgets.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 _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 isDark = Theme.of(context).brightness == Brightness.dark; final montant = souscription.montantTotal ?? 0; final remise = _periodeRemises[souscription.typePeriode]; return Scaffold( backgroundColor: Theme.of(context).scaffoldBackgroundColor, body: Column( children: [ // ── Header hero gradient ─────────────────────────── Container( decoration: const BoxDecoration(gradient: UnionFlowColors.primaryGradient), child: SafeArea( bottom: false, child: Padding( padding: const EdgeInsets.fromLTRB(20, 12, 20, 32), child: Column( children: [ // Barre de progression — toutes complètes à l'étape 3 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), // Icône principale Container( width: 80, height: 80, 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: 40), ), const SizedBox(height: 14), // Montant Text( _formatPrix(montant), style: const TextStyle( color: Colors.white, fontSize: 42, fontWeight: FontWeight.w900, letterSpacing: -1, ), ), const Text( 'FCFA à régler', style: TextStyle(color: Colors.white70, fontSize: 14, fontWeight: FontWeight.w500), ), // Badge remise if (remise != null) ...[ const SizedBox(height: 10), Container( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 5), decoration: BoxDecoration( color: UnionFlowColors.gold.withOpacity(0.3), borderRadius: BorderRadius.circular(20), border: Border.all(color: UnionFlowColors.goldLight.withOpacity(0.5)), ), child: Text( '🎉 $remise appliquée', style: const TextStyle( color: UnionFlowColors.goldLight, fontSize: 13, fontWeight: FontWeight.w700, ), ), ), ], ], ), ), ), ), // ── Contenu scrollable ────────────────────────────── Expanded( child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), 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, isDark: isDark, items: [ _DetailItem(label: 'Nom', value: souscription.organisationNom!, bold: true), if (souscription.typeOrganisation != null) _DetailItem(label: 'Type', value: souscription.typeOrganisation!), ], ), const SizedBox(height: 14), ], // Formule _DetailCard( title: 'Formule souscrite', icon: Icons.workspace_premium_rounded, iconColor: UnionFlowColors.gold, isDark: isDark, items: [ _DetailItem(label: 'Niveau', value: souscription.typeFormule, bold: true), _DetailItem( label: 'Capacité', 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, isDark: isDark, 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) _DetailItem(label: 'Début', value: _formatDate(souscription.dateDebut!)), if (souscription.dateFin != null) _DetailItem(label: 'Fin', value: _formatDate(souscription.dateFin!)), ], ), const SizedBox(height: 20), // Bloc montant total — proéminent Container( padding: const EdgeInsets.all(18), decoration: BoxDecoration( gradient: LinearGradient( colors: isDark ? [UnionFlowColors.gold.withOpacity(0.18), UnionFlowColors.amber.withOpacity(0.12)] : [UnionFlowColors.goldPale, const Color(0xFFFFF3C8)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(16), border: Border.all(color: UnionFlowColors.gold.withOpacity(0.4)), boxShadow: isDark ? null : UnionFlowColors.goldGlowShadow, ), child: Row( children: [ Container( width: 52, height: 52, decoration: BoxDecoration( gradient: UnionFlowColors.goldGradient, borderRadius: BorderRadius.circular(14), ), child: const Icon(Icons.monetization_on_rounded, color: Colors.white, size: 28), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'TOTAL À PAYER', style: TextStyle( color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondary, fontSize: 11, fontWeight: FontWeight.w600, letterSpacing: 0.5, ), ), Text( '${_formatPrix(montant)} FCFA', style: TextStyle( color: isDark ? AppColors.textPrimaryDark : AppColors.textPrimary, fontSize: 24, fontWeight: FontWeight.w900, letterSpacing: -0.5, ), ), if (remise != null) Text( remise, style: const TextStyle( color: UnionFlowColors.gold, fontSize: 12, fontWeight: FontWeight.w600, ), ), ], ), ), ], ), ), const SizedBox(height: 20), // Notes _NoteBox( icon: Icons.security_rounded, iconColor: UnionFlowColors.unionGreen, accentColor: UnionFlowColors.unionGreen, isDark: isDark, title: 'Paiement sécurisé', message: 'Votre paiement est traité de manière sécurisée via Wave Mobile Money. Une fois confirmé, votre compte sera activé automatiquement.', ), const SizedBox(height: 10), _NoteBox( icon: Icons.bolt_rounded, iconColor: UnionFlowColors.amber, accentColor: UnionFlowColors.amber, isDark: isDark, title: 'Activation immédiate', message: 'Dès que Wave confirme le paiement, votre espace administrateur est activé avec toutes les fonctionnalités de votre formule.', ), const SizedBox(height: 10), _NoteBox( icon: Icons.support_agent_rounded, iconColor: UnionFlowColors.info, accentColor: UnionFlowColors.info, isDark: isDark, title: 'Besoin d\'aide ?', message: 'En cas de problème, contactez support@unionflow.app — réponse sous 24h.', ), ], ), ), ), ], ), bottomNavigationBar: OnboardingBottomBar( enabled: true, label: 'Choisir le moyen de paiement', onPressed: () => context.read().add(const OnboardingChoixPaiementOuvert()), ), ); } 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) => '${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; final bool isDark; const _DetailCard({ required this.title, required this.icon, required this.iconColor, required this.items, required this.isDark, }); @override Widget build(BuildContext context) { final bgColor = isDark ? AppColors.surfaceDark : AppColors.surface; final borderColor = isDark ? AppColors.borderDark : AppColors.border; final textPrimary = isDark ? AppColors.textPrimaryDark : AppColors.textPrimary; final textSecondary= isDark ? AppColors.textSecondaryDark : AppColors.textSecondary; return Container( decoration: BoxDecoration( color: bgColor, borderRadius: BorderRadius.circular(16), border: Border.all(color: borderColor), boxShadow: isDark ? null : UnionFlowColors.softShadow, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // En-tête section Padding( padding: const EdgeInsets.fromLTRB(16, 14, 16, 10), child: Row( children: [ Container( width: 34, height: 34, decoration: BoxDecoration( color: iconColor.withOpacity(isDark ? 0.2 : 0.1), borderRadius: BorderRadius.circular(8), ), child: Icon(icon, color: iconColor, size: 18), ), const SizedBox(width: 10), Text( title, style: TextStyle( fontWeight: FontWeight.w700, fontSize: 14, color: textPrimary, ), ), ], ), ), Divider(height: 1, color: borderColor), 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: 110, child: Text(item.label, style: TextStyle(color: textSecondary, fontSize: 13)), ), Expanded( child: Text( item.value, style: TextStyle( color: textPrimary, fontSize: 13, fontWeight: item.bold ? FontWeight.w700 : FontWeight.w500, ), ), ), ], ), )).toList(), ), ), ], ), ); } } class _NoteBox extends StatelessWidget { final IconData icon; final Color iconColor; final Color accentColor; final bool isDark; final String title; final String message; const _NoteBox({ required this.icon, required this.iconColor, required this.accentColor, required this.isDark, required this.title, required this.message, }); @override Widget build(BuildContext context) { final bgColor = accentColor.withOpacity(isDark ? 0.12 : 0.06); final borderColor = accentColor.withOpacity(isDark ? 0.3 : 0.2); final textSecondary= isDark ? AppColors.textSecondaryDark : AppColors.textSecondary; return Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: bgColor, 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: TextStyle(color: textSecondary, fontSize: 12, height: 1.5), ), ], ), ), ], ), ); } }