feat(mobile): amélioration gestion erreurs LCB-FT (T021)

Phase 4 Mobile - Section 4.1 Épargne

Nouveau fichier :
- ErrorFormatter : utilitaire central pour formater les erreurs backend
  - Détecte et formate spécialement les erreurs LCB-FT (origine fonds manquante)
  - Détecte erreurs KYC, réseau, 400/401/403/404/500
  - Messages conviviaux avec emojis
  - Durée d'affichage adaptée (6s pour LCB-FT, 3s sinon)

Modifications 3 dialogs (dépôt, retrait, transfert) :
- Remplacement affichage erreur brut par ErrorFormatter.format()
- Messages explicites : "L'origine des fonds est obligatoire (conformité LCB-FT)"
- Durée snackbar conditionnelle selon type erreur

Impact UX :
- Messages d'erreur clairs et professionnels
- Utilisateur comprend POURQUOI l'origine fonds est requise (anti-blanchiment)
- Temps de lecture suffisant pour messages importants

Spec : specs/001-mutuelles-anti-blanchiment/spec.md
Progression : 18/27 tâches (67%)

Signed-off-by: lions dev Team
This commit is contained in:
dahoud
2026-03-15 02:46:41 +00:00
parent 5ef8ae1140
commit 62318476f8
4 changed files with 114 additions and 5 deletions

View File

@@ -0,0 +1,95 @@
/// Utilitaire pour formater les messages d'erreur venant du backend.
/// Gère notamment les erreurs LCB-FT (anti-blanchiment).
class ErrorFormatter {
/// Formate une erreur en message utilisateur convivial.
///
/// Détecte et formate spécialement les erreurs LCB-FT (origine des fonds manquante).
/// Supprime les préfixes techniques comme "Exception: " ou "DioException: ".
static String format(dynamic error) {
if (error == null) return 'Une erreur inconnue est survenue';
final errorString = error.toString();
// Erreur LCB-FT : origine des fonds manquante
if (errorString.contains('origine des fonds') ||
errorString.contains('LCB-FT') ||
errorString.contains('au-dessus du seuil')) {
return '🛡️ L\'origine des fonds est obligatoire pour cette opération (conformité LCB-FT anti-blanchiment).\n\nVeuillez préciser d\'où proviennent les fonds.';
}
// Erreur KYC
if (errorString.contains('KYC') || errorString.contains('vérification identité')) {
return '🛡️ Votre identité doit être vérifiée pour cette opération (conformité KYC).\n\nContactez votre administrateur.';
}
// Erreur solde insuffisant
if (errorString.contains('solde') && errorString.contains('insuffisant')) {
return '💳 Solde insuffisant pour effectuer cette opération.';
}
// Erreur réseau / timeout
if (errorString.contains('SocketException') ||
errorString.contains('timeout') ||
errorString.contains('network')) {
return '📡 Erreur de connexion. Vérifiez votre connexion internet et réessayez.';
}
// Erreur 400 générique (validation backend)
if (errorString.contains('400') || errorString.contains('Bad Request')) {
// Essayer d'extraire le message du backend
final match = RegExp(r'message["\s:]+([^"}\n]+)', caseSensitive: false)
.firstMatch(errorString);
if (match != null && match.group(1) != null) {
return match.group(1)!.trim();
}
return 'Données invalides. Vérifiez les informations saisies.';
}
// Erreur 401 / 403 (authentification / autorisation)
if (errorString.contains('401') || errorString.contains('403')) {
return '🔒 Vous n\'avez pas les autorisations nécessaires pour cette opération.';
}
// Erreur 404 (ressource non trouvée)
if (errorString.contains('404')) {
return 'Ressource non trouvée. Elle a peut-être été supprimée.';
}
// Erreur 500 (erreur serveur)
if (errorString.contains('500') || errorString.contains('Internal Server')) {
return '🔧 Erreur serveur. Nos équipes ont été notifiées. Réessayez plus tard.';
}
// Nettoyer les préfixes techniques
String cleaned = errorString
.replaceFirst('Exception: ', '')
.replaceFirst('DioException: ', '')
.replaceFirst('DioError: ', '')
.replaceFirst('Error: ', '')
.trim();
// Si le message est trop long, le tronquer
if (cleaned.length > 200) {
cleaned = '${cleaned.substring(0, 197)}...';
}
return cleaned.isNotEmpty ? cleaned : 'Une erreur est survenue';
}
/// Détermine si une erreur est critique (nécessite intervention admin).
static bool isCritical(dynamic error) {
final errorString = error.toString().toLowerCase();
return errorString.contains('kyc') ||
errorString.contains('vérification identité') ||
errorString.contains('401') ||
errorString.contains('403');
}
/// Détermine si une erreur est liée au LCB-FT.
static bool isLcbFtError(dynamic error) {
final errorString = error.toString().toLowerCase();
return errorString.contains('origine des fonds') ||
errorString.contains('lcb-ft') ||
errorString.contains('anti-blanchiment');
}
}