import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../bloc/onboarding_bloc.dart'; import '../../data/models/formule_model.dart'; /// Étape 1 — Choix de la formule (BASIC / STANDARD / PREMIUM) et de la plage de membres class PlanSelectionPage extends StatefulWidget { final List formules; const PlanSelectionPage({super.key, required this.formules}); @override State createState() => _PlanSelectionPageState(); } class _PlanSelectionPageState extends State { String? _selectedPlage; String? _selectedFormule; static const _plages = [ ('PETITE', 'Petite', '1–100 membres'), ('MOYENNE', 'Moyenne', '101–500 membres'), ('GRANDE', 'Grande', '501–2 000 membres'), ('TRES_GRANDE', 'Très grande', '2 000+ membres'), ]; static const _formules = [ ('BASIC', 'Basic', Icons.star_outline, Color(0xFF1976D2)), ('STANDARD', 'Standard', Icons.star_half, Color(0xFF388E3C)), ('PREMIUM', 'Premium', Icons.star, Color(0xFFF57C00)), ]; List get _filteredFormules => widget.formules .where((f) => _selectedPlage == null || f.plage == _selectedPlage) .toList() ..sort((a, b) => a.ordreAffichage.compareTo(b.ordreAffichage)); FormuleModel? get _selectedFormuleModel => _filteredFormules .where((f) => f.code == _selectedFormule && f.plage == _selectedPlage) .firstOrNull; @override Widget build(BuildContext context) { final theme = Theme.of(context); return Scaffold( appBar: AppBar( title: const Text('Choisir votre formule'), automaticallyImplyLeading: false, ), body: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Indicateur d'étapes _StepIndicator(current: 1, total: 3), const SizedBox(height: 24), Text('Taille de votre organisation', style: theme.textTheme.titleMedium), const SizedBox(height: 8), // Sélecteur de plage Wrap( spacing: 8, runSpacing: 8, children: _plages.map((p) { final (code, label, sublabel) = p; final selected = _selectedPlage == code; return ChoiceChip( label: Column( children: [ Text(label, style: TextStyle( fontWeight: FontWeight.bold, color: selected ? Colors.white : null)), Text(sublabel, style: TextStyle( fontSize: 11, color: selected ? Colors.white70 : Colors.grey[600])), ], ), selected: selected, onSelected: (_) => setState(() { _selectedPlage = code; _selectedFormule = null; }), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), ); }).toList(), ), if (_selectedPlage != null) ...[ const SizedBox(height: 24), Text('Niveau de formule', style: theme.textTheme.titleMedium), const SizedBox(height: 8), // Cartes de formules ..._formules.map((f) { final (code, label, icon, color) = f; final formule = _filteredFormules .where((fm) => fm.code == code) .firstOrNull; if (formule == null) return const SizedBox.shrink(); final selected = _selectedFormule == code; return _FormuleCard( formule: formule, label: label, icon: icon, color: color, selected: selected, onTap: () => setState(() => _selectedFormule = code), ); }), ], const SizedBox(height: 32), ], ), ), bottomNavigationBar: Padding( padding: const EdgeInsets.all(16), child: ElevatedButton( onPressed: _selectedPlage != null && _selectedFormule != null ? () => context.read().add( OnboardingFormuleSelected( codeFormule: _selectedFormule!, plage: _selectedPlage!, ), ) : null, style: ElevatedButton.styleFrom( minimumSize: const Size.fromHeight(48), ), child: const Text('Continuer'), ), ), ); } } class _FormuleCard extends StatelessWidget { final FormuleModel formule; final String label; final IconData icon; final Color color; final bool selected; final VoidCallback onTap; const _FormuleCard({ required this.formule, required this.label, required this.icon, required this.color, required this.selected, required this.onTap, }); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: AnimatedContainer( duration: const Duration(milliseconds: 200), margin: const EdgeInsets.only(bottom: 8), decoration: BoxDecoration( color: selected ? color.withOpacity(0.1) : Colors.white, border: Border.all( color: selected ? color : Colors.grey[300]!, width: selected ? 2 : 1, ), borderRadius: BorderRadius.circular(12), ), child: Padding( padding: const EdgeInsets.all(16), child: Row( children: [ Icon(icon, color: color, size: 28), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(label, style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, color: selected ? color : null)), if (formule.description != null) Text(formule.description!, style: const TextStyle(fontSize: 12, color: Colors.grey)), ], ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( '${_formatPrix(formule.prixMensuel)} FCFA', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 15, color: color), ), const Text('/mois', style: TextStyle(fontSize: 11, color: Colors.grey)), ], ), const SizedBox(width: 8), Icon( selected ? Icons.check_circle : Icons.radio_button_unchecked, color: selected ? color : Colors.grey, ), ], ), ), ), ); } String _formatPrix(double prix) { if (prix >= 1000) { return '${(prix / 1000).toStringAsFixed(0)} 000'; } return prix.toStringAsFixed(0); } } 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), ), ), ); }), ); } }