diff --git a/unionflow/unionflow-mobile-apps/lib/features/epargne/presentation/widgets/transfert_epargne_dialog.dart b/unionflow/unionflow-mobile-apps/lib/features/epargne/presentation/widgets/transfert_epargne_dialog.dart index d862ee5..24e0ef3 100644 --- a/unionflow/unionflow-mobile-apps/lib/features/epargne/presentation/widgets/transfert_epargne_dialog.dart +++ b/unionflow/unionflow-mobile-apps/lib/features/epargne/presentation/widgets/transfert_epargne_dialog.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; +import '../../../../core/constants/lcb_ft_constants.dart'; +import '../../../../core/data/repositories/parametres_lcb_ft_repository.dart'; import '../../data/models/compte_epargne_model.dart'; import '../../data/models/transaction_epargne_request.dart'; import '../../data/repositories/transaction_epargne_repository.dart'; @@ -27,9 +29,15 @@ class _TransfertEpargneDialogState extends State { final _formKey = GlobalKey(); final _montantController = TextEditingController(); final _motifController = TextEditingController(); + final _origineFondsController = TextEditingController(); bool _loading = false; String? _compteDestinationId; late TransactionEpargneRepository _repository; + late ParametresLcbFtRepository _parametresRepository; + + /// Seuil LCB-FT récupéré depuis l'API (fallback à 500k XOF). + double _seuilLcbFt = kSeuilOrigineFondsObligatoireXOF; + bool _seuilLoaded = false; List get _comptesDestination { if (widget.compteSource.id == null) return []; @@ -38,17 +46,36 @@ class _TransfertEpargneDialogState extends State { .toList(); } + bool get _origineFondsRequis { + final m = double.tryParse(_montantController.text.replaceAll(',', '.')); + return m != null && m >= _seuilLcbFt; + } + @override void initState() { super.initState(); _repository = GetIt.I(); + _parametresRepository = GetIt.I(); if (_comptesDestination.isNotEmpty) _compteDestinationId = _comptesDestination.first.id; + _chargerSeuil(); + } + + /// Charge le seuil LCB-FT depuis l'API au chargement du dialog. + Future _chargerSeuil() async { + final seuil = await _parametresRepository.getSeuilJustification(); + if (mounted) { + setState(() { + _seuilLcbFt = seuil.montantSeuil; + _seuilLoaded = true; + }); + } } @override void dispose() { _montantController.dispose(); _motifController.dispose(); + _origineFondsController.dispose(); super.dispose(); } @@ -72,6 +99,16 @@ class _TransfertEpargneDialogState extends State { ); return; } + if (_origineFondsRequis && _origineFondsController.text.trim().isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'L\'origine des fonds est obligatoire pour les opérations à partir de ${_seuilLcbFt.toStringAsFixed(0)} XOF (LCB-FT).', + ), + ), + ); + return; + } setState(() => _loading = true); try { final request = TransactionEpargneRequest( @@ -80,6 +117,7 @@ class _TransfertEpargneDialogState extends State { montant: montant, compteDestinationId: _compteDestinationId, motif: _motifController.text.trim().isEmpty ? null : _motifController.text.trim(), + origineFonds: _origineFondsController.text.trim().isEmpty ? null : _origineFondsController.text.trim(), ); await _repository.transferer(request); if (!mounted) return; @@ -171,6 +209,7 @@ class _TransfertEpargneDialogState extends State { if (n > solde) return 'Solde insuffisant'; return null; }, + onChanged: (_) => setState(() {}), ), const SizedBox(height: 16), TextFormField( @@ -181,6 +220,24 @@ class _TransfertEpargneDialogState extends State { ), maxLines: 2, ), + const SizedBox(height: 16), + TextFormField( + controller: _origineFondsController, + decoration: InputDecoration( + labelText: 'Origine des fonds (LCB-FT)', + hintText: _origineFondsRequis ? 'Obligatoire au-dessus du seuil' : 'Optionnel', + border: const OutlineInputBorder(), + ), + onChanged: (_) => setState(() {}), + ), + if (_origineFondsRequis) + Padding( + padding: const EdgeInsets.only(top: 8), + child: Text( + 'Requis pour les opérations ≥ ${_seuilLcbFt.toStringAsFixed(0)} XOF', + style: TypographyTokens.bodySmall?.copyWith(color: ColorTokens.primary), + ), + ), ], ), ),