import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../bloc/onboarding_bloc.dart'; import '../../data/models/formule_model.dart'; import '../../../../features/authentication/presentation/bloc/auth_bloc.dart'; /// Étape 2 — Choix de la période de facturation et du type d'organisation class PeriodSelectionPage extends StatefulWidget { final String codeFormule; final String plage; final List formules; const PeriodSelectionPage({ super.key, required this.codeFormule, required this.plage, required this.formules, }); @override State createState() => _PeriodSelectionPageState(); } class _PeriodSelectionPageState extends State { String _selectedPeriode = 'MENSUEL'; String _selectedTypeOrg = 'ASSOCIATION'; static const _periodes = [ ('MENSUEL', 'Mensuel', 'Aucune remise', 1.00), ('TRIMESTRIEL', 'Trimestriel', '5% de remise', 0.95), ('SEMESTRIEL', 'Semestriel', '10% de remise', 0.90), ('ANNUEL', 'Annuel', '20% de remise', 0.80), ]; static const _typesOrg = [ ('ASSOCIATION', 'Association / ONG locale', '×1.0'), ('MUTUELLE', 'Mutuelle (santé, fonctionnaires…)', '×1.2'), ('COOPERATIVE', 'Coopérative / Microfinance', '×1.3'), ('FEDERATION', 'Fédération / Grande ONG', '×1.0 ou ×1.5 Premium'), ]; FormuleModel? get _formule => widget.formules .where((f) => f.code == widget.codeFormule && f.plage == widget.plage) .firstOrNull; double get _prixEstime { final f = _formule; if (f == null) return 0; final coefPeriode = _periodes.firstWhere((p) => p.$1 == _selectedPeriode).$4; final coefOrg = _selectedTypeOrg == 'COOPERATIVE' ? 1.3 : _selectedTypeOrg == 'MUTUELLE' ? 1.2 : 1.0; final nbMois = {'MENSUEL': 1, 'TRIMESTRIEL': 3, 'SEMESTRIEL': 6, 'ANNUEL': 12}[_selectedPeriode]!; return f.prixMensuel * coefOrg * coefPeriode * nbMois; } String get _organisationId { final authState = context.read().state; if (authState is AuthAuthenticated) { return authState.user.organizationContexts.isNotEmpty ? authState.user.organizationContexts.first.organizationId : ''; } if (authState is AuthPendingOnboarding) { return authState.organisationId ?? ''; } return ''; } @override Widget build(BuildContext context) { final theme = Theme.of(context); return Scaffold( appBar: AppBar( title: const Text('Période & type d\'organisation'), leading: BackButton( onPressed: () => context.read().add( OnboardingStarted(initialState: 'NO_SUBSCRIPTION'), ), ), ), body: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _StepIndicator(current: 2, total: 3), const SizedBox(height: 24), // Période Text('Période de facturation', style: theme.textTheme.titleMedium), const SizedBox(height: 8), ..._periodes.map((p) { final (code, label, remise, _) = p; final selected = _selectedPeriode == code; return RadioListTile( value: code, groupValue: _selectedPeriode, onChanged: (v) => setState(() => _selectedPeriode = v!), title: Text(label, style: TextStyle( fontWeight: selected ? FontWeight.bold : FontWeight.normal)), subtitle: Text(remise, style: TextStyle( color: code != 'MENSUEL' ? Colors.green[700] : null)), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), side: BorderSide( color: selected ? theme.primaryColor : Colors.grey[300]!, ), ), tileColor: selected ? theme.primaryColor.withOpacity(0.05) : null, contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), ); }), const SizedBox(height: 24), Text('Type de votre organisation', style: theme.textTheme.titleMedium), const SizedBox(height: 4), Text( 'Détermine le coefficient tarifaire applicable.', style: theme.textTheme.bodySmall?.copyWith(color: Colors.grey[600]), ), const SizedBox(height: 8), ..._typesOrg.map((t) { final (code, label, coef) = t; final selected = _selectedTypeOrg == code; return RadioListTile( value: code, groupValue: _selectedTypeOrg, onChanged: (v) => setState(() => _selectedTypeOrg = v!), title: Text(label), subtitle: Text('Coefficient : $coef', style: const TextStyle(fontSize: 12)), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), side: BorderSide( color: selected ? theme.primaryColor : Colors.grey[300]!, ), ), tileColor: selected ? theme.primaryColor.withOpacity(0.05) : null, contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), ); }), const SizedBox(height: 24), // Estimation du prix Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: theme.primaryColor.withOpacity(0.08), borderRadius: BorderRadius.circular(12), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text('Estimation', style: TextStyle(fontWeight: FontWeight.bold)), Text( '${_prixEstime.toStringAsFixed(0)} FCFA', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: theme.primaryColor, ), ), ], ), ), const SizedBox(height: 32), ], ), ), bottomNavigationBar: Padding( padding: const EdgeInsets.all(16), child: ElevatedButton( onPressed: () { context.read() ..add(OnboardingPeriodeSelected( typePeriode: _selectedPeriode, typeOrganisation: _selectedTypeOrg, organisationId: _organisationId, )) ..add(const OnboardingDemandeConfirmee()); }, style: ElevatedButton.styleFrom(minimumSize: const Size.fromHeight(48)), child: const Text('Voir le récapitulatif'), ), ), ); } } class _StepIndicator extends StatelessWidget { final int current; final int total; const _StepIndicator({required this.current, required this.total}); @override Widget build(BuildContext context) { return Row( children: List.generate(total, (i) { final active = i + 1 <= current; return Expanded( child: Container( height: 4, margin: EdgeInsets.only(right: i < total - 1 ? 4 : 0), decoration: BoxDecoration( color: active ? Theme.of(context).primaryColor : Colors.grey[300], borderRadius: BorderRadius.circular(2), ), ), ); }), ); } }