import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class CustomTextField extends StatelessWidget { final TextEditingController controller; final String label; final String? hintText; final IconData? prefixIcon; final Widget? suffixIcon; final bool obscureText; final TextInputType keyboardType; final String? Function(String?)? validator; final List? inputFormatters; final int? maxLines; final int? minLines; final bool readOnly; final VoidCallback? onTap; final Function(String)? onChanged; final bool autofocus; final FocusNode? focusNode; final String? errorText; final Color? fillColor; final String? helperText; final Function(String)? onFieldSubmitted; final bool isRequired; const CustomTextField({ super.key, required this.controller, required this.label, this.hintText, this.prefixIcon, this.suffixIcon, this.obscureText = false, this.keyboardType = TextInputType.text, this.validator, this.inputFormatters, this.maxLines = 1, this.minLines, this.readOnly = false, this.onTap, this.onChanged, this.autofocus = false, this.focusNode, this.errorText, this.fillColor, this.helperText, this.onFieldSubmitted, this.isRequired = false, }); @override Widget build(BuildContext context) { final theme = Theme.of(context); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (label.isNotEmpty) ...[ Text( label, style: theme.textTheme.titleSmall?.copyWith( fontWeight: FontWeight.w500, color: theme.colorScheme.onBackground, ), ), const SizedBox(height: 8), ], // Ajouter un Container avec une ombre pour créer un effet d'élévation Stack( children: [ Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 4, offset: const Offset(0, 2), ), ], ), child: TextFormField( controller: controller, obscureText: obscureText, keyboardType: keyboardType, validator: validator, inputFormatters: inputFormatters, maxLines: maxLines, minLines: minLines, readOnly: readOnly, onTap: onTap, onChanged: onChanged, onFieldSubmitted: onFieldSubmitted, autofocus: autofocus, focusNode: focusNode, style: theme.textTheme.bodyLarge?.copyWith( color: theme.colorScheme.onBackground, ), decoration: InputDecoration( hintText: hintText, hintStyle: theme.textTheme.bodyLarge?.copyWith( color: theme.colorScheme.onBackground.withOpacity(0.5), ), errorText: errorText, helperText: helperText, helperStyle: theme.textTheme.bodySmall?.copyWith( color: theme.colorScheme.onBackground.withOpacity(0.6), ), prefixIcon: prefixIcon != null ? Icon(prefixIcon, color: theme.colorScheme.primary) : null, suffixIcon: suffixIcon, // Couleur de fond différente selon l'état (lecture seule ou éditable) fillColor: fillColor ?? (readOnly ? const Color( 0xFFF8F9FA) // Gris plus clair pour readOnly : const Color( 0xFFECEFF1)), // Gris plus foncé pour éditable filled: true, // Ajouter une élévation avec une petite ombre border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none, ), // Ajouter une ombre pour créer un effet d'élévation enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none, gapPadding: 0, ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( color: theme.colorScheme.primary, width: 2, ), ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( color: theme.colorScheme.error, width: 2, ), ), focusedErrorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide( color: theme.colorScheme.error, width: 2, ), ), contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 16, ), ), ), ), // Point rouge en haut à droite pour indiquer que le champ est obligatoire if (isRequired) Positioned( top: 0, right: 0, child: Container( width: 10, height: 10, margin: const EdgeInsets.only(top: 8, right: 8), decoration: const BoxDecoration( color: Colors.red, shape: BoxShape.circle, ), ), ), ], ), ], ); } }