import 'package:flutter/material.dart'; import 'package:fancy_password_field/fancy_password_field.dart'; import 'package:pweb/config/constants.dart'; import 'package:pweb/generated/i18n/app_localizations.dart'; class PasswordField extends StatefulWidget { final TextEditingController controller; final ValueChanged? onValid; final bool hasStrengthIndicator; final String? labelText; final Set rules; final AutovalidateMode? autovalidateMode; final Widget Function(Set, String)? validationRuleBuilder; const PasswordField({ super.key, required this.controller, this.onValid, this.validationRuleBuilder, this.labelText, this.hasStrengthIndicator = false, this.autovalidateMode, this.rules = const {}, }); @override State createState() => _PasswordFieldState(); } class _PasswordFieldState extends State { bool _lastValidationResult = false; void _onChanged(String value) { bool isValid = widget.rules.every((rule) => rule.validate(value)); // Only trigger onValid if validation result has changed if (isValid != _lastValidationResult) { _lastValidationResult = isValid; widget.onValid?.call(isValid); } } @override Widget build(BuildContext context) { return FancyPasswordField( key: widget.key, controller: widget.controller, decoration: InputDecoration( labelText: widget.labelText ?? AppLocalizations.of(context)!.password, ), validationRules: widget.rules, hasStrengthIndicator: widget.hasStrengthIndicator, validationRuleBuilder: widget.validationRuleBuilder, autovalidateMode: widget.autovalidateMode, onChanged: _onChanged, ); } } Widget defaulRulesPasswordField( BuildContext context, { required TextEditingController controller, Key? key, ValueChanged? onValid, Widget Function(Set, String)? validationRuleBuilder, String? labelText, FocusNode? focusNode, AutovalidateMode? autovalidateMode, bool hasStrengthIndicator = false, Set additionalRules = const {}, }) { Set rules = { DigitValidationRule( customText: AppLocalizations.of(context)!.passwordValidationRuleDigit, ), UppercaseValidationRule( customText: AppLocalizations.of(context)!.passwordValidationRuleUpperCase, ), LowercaseValidationRule( customText: AppLocalizations.of(context)!.passwordValidationRuleLowerCase, ), MinCharactersValidationRule( Constants.minPasswordCharacters, customText: AppLocalizations.of(context)! .passwordValidationRuleMinCharacters(Constants.minPasswordCharacters), ), ...additionalRules, }; return PasswordField( key: key, controller: controller, onValid: onValid, validationRuleBuilder: validationRuleBuilder, hasStrengthIndicator: hasStrengthIndicator, labelText: labelText, autovalidateMode: autovalidateMode, rules: rules, ); }