import 'package:flutter/material.dart'; /// Helpers de validation pour le formulaire de passage class PassageValidationHelpers { /// Validation pour numéro de rue static String? validateNumero(String? value) { if (value == null || value.trim().isEmpty) { return 'Le numéro est obligatoire'; } final numero = int.tryParse(value.trim()); if (numero == null || numero <= 0) { return 'Numéro invalide'; } return null; } /// Validation pour rue static String? validateRue(String? value) { if (value == null || value.trim().isEmpty) { return 'La rue est obligatoire'; } if (value.trim().length < 3) { return 'La rue doit contenir au moins 3 caractères'; } return null; } /// Validation pour ville static String? validateVille(String? value) { if (value == null || value.trim().isEmpty) { return 'La ville est obligatoire'; } return null; } /// Validation pour nom d'occupant (selon type de passage) static String? validateNomOccupant(String? value, int? passageType) { // Nom obligatoire seulement pour les passages effectués (type 1) if (passageType == 1) { if (value == null || value.trim().isEmpty) { return 'Le nom est obligatoire pour les passages effectués'; } if (value.trim().length < 2) { return 'Le nom doit contenir au moins 2 caractères'; } } return null; } /// Validation pour email static String? validateEmail(String? value) { if (value == null || value.trim().isEmpty) { return null; // Email optionnel } const emailRegex = r'^[^@]+@[^@]+\.[^@]+$'; if (!RegExp(emailRegex).hasMatch(value.trim())) { return 'Format email invalide'; } return null; } /// Validation pour téléphone static String? validatePhone(String? value) { if (value == null || value.trim().isEmpty) { return null; // Téléphone optionnel } // Enlever espaces et tirets final cleanPhone = value.replaceAll(RegExp(r'[\s\-\.]'), ''); // Vérifier format français basique if (cleanPhone.length < 10) { return 'Numéro trop court'; } return null; } /// Validation pour montant (selon type de passage) static String? validateMontant(String? value, int? passageType) { // Montant obligatoire seulement pour types 1 (Effectué) et 5 (Lot) if (passageType == 1 || passageType == 5) { if (value == null || value.trim().isEmpty) { return 'Le montant est obligatoire pour ce type'; } final montant = double.tryParse(value.replaceAll(',', '.')); if (montant == null) { return 'Montant invalide'; } if (montant <= 0) { return 'Le montant doit être supérieur à 0'; } } return null; } /// Validation pour remarque static String? validateRemarque(String? value) { if (value != null && value.length > 500) { return 'La remarque ne peut pas dépasser 500 caractères'; } return null; } /// Focus sur le premier champ en erreur avec scroll static void focusFirstError(BuildContext context, GlobalKey formKey) { // Déclencher la validation if (!formKey.currentState!.validate()) { // Flutter met automatiquement le focus sur le premier champ en erreur // Mais on peut ajouter un scroll pour s'assurer que le champ est visible // Attendre que le focus soit mis WidgetsBinding.instance.addPostFrameCallback((_) { // Trouver le champ qui a le focus final FocusNode? focusedNode = FocusScope.of(context).focusedChild; if (focusedNode != null) { // Scroll vers le champ focusé Scrollable.ensureVisible( focusedNode.context!, duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, ); } }); } } /// Validation globale du formulaire de passage static bool validatePassageForm({ required GlobalKey formKey, required BuildContext context, required int? selectedPassageType, required int fkTypeReglement, String? montant, String? nomOccupant, }) { // Validation des champs via les validators des TextFormField if (!formKey.currentState!.validate()) { // Le focus est automatiquement mis sur le premier champ en erreur return false; } // Validations spécifiques métier (comme dans l'original) if (selectedPassageType == 1) { if (nomOccupant == null || nomOccupant.trim().isEmpty) { // Ici on pourrait aussi mettre le focus sur le champ nom return false; } } if (selectedPassageType == 1 || selectedPassageType == 5) { final montantValue = double.tryParse(montant?.replaceAll(',', '.') ?? ''); if (montantValue == null || montantValue <= 0) { // Focus sur montant si erreur return false; } if (fkTypeReglement < 1 || fkTypeReglement > 3) { // Focus sur dropdown type règlement return false; } } return true; } }