diff --git a/lib/components/signup/password_requirements.dart b/lib/components/signup/password_requirements.dart new file mode 100644 index 0000000..6128cf5 --- /dev/null +++ b/lib/components/signup/password_requirements.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; + +class PasswordRequirements extends StatelessWidget { + final String password; + + const PasswordRequirements({super.key, required this.password}); + + bool get _hasMinLength => password.length >= 8; + bool get _hasUppercase => password.contains(RegExp(r'[A-Z]')); + bool get _hasLowercase => password.contains(RegExp(r'[a-z]')); + bool get _hasDigit => password.contains(RegExp(r'[0-9]')); + bool get _hasSpecialChar => + password.contains(RegExp(r'[!@#\$%^&*(),.?":{}|<>]')); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 10), + const Text( + 'Votre mot de passe doit contenir :', + style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 8), + _buildRequirement(_hasMinLength, 'Au moins 8 caractères'), + _buildRequirement(_hasUppercase, 'Une majuscule'), + _buildRequirement(_hasLowercase, 'Une minuscule'), + _buildRequirement(_hasDigit, 'Un chiffre'), + _buildRequirement(_hasSpecialChar, 'Un caractère spécial'), + ], + ); + } + + Widget _buildRequirement(bool isMet, String text) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 2.0), + child: Row( + children: [ + Icon( + isMet ? Icons.check_circle : Icons.circle_outlined, + color: isMet ? Colors.green : Colors.grey, + size: 16, + ), + const SizedBox(width: 8), + Text( + text, + style: TextStyle( + color: isMet ? Colors.green : Colors.grey, + fontSize: 12, + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages/signup.dart b/lib/pages/signup.dart index 7cea84b..45f0b3b 100644 --- a/lib/pages/signup.dart +++ b/lib/pages/signup.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:sign_in_button/sign_in_button.dart'; import 'package:travel_mate/components/loading/laoding_content.dart'; +import 'package:travel_mate/components/signup/password_requirements.dart'; import 'package:travel_mate/components/signup/sign_up_platform_content.dart'; import 'package:travel_mate/services/auth_service.dart'; import '../blocs/auth/auth_bloc.dart'; @@ -66,6 +67,18 @@ class _SignUpPageState extends State { if (value.length < 8) { return 'Le mot de passe doit contenir au moins 8 caractères'; } + if (!value.contains(RegExp(r'[A-Z]'))) { + return 'Le mot de passe doit contenir une majuscule'; + } + if (!value.contains(RegExp(r'[a-z]'))) { + return 'Le mot de passe doit contenir une minuscule'; + } + if (!value.contains(RegExp(r'[0-9]'))) { + return 'Le mot de passe doit contenir un chiffre'; + } + if (!value.contains(RegExp(r'[!@#\$%^&*(),.?":{}|<>]'))) { + return 'Le mot de passe doit contenir un caractère spécial'; + } return null; } @@ -209,6 +222,7 @@ class _SignUpPageState extends State { controller: _passwordController, validator: _validatePassword, obscureText: _obscurePassword, + onChanged: (value) => setState(() {}), decoration: InputDecoration( labelText: 'Mot de passe', border: const OutlineInputBorder( @@ -229,6 +243,7 @@ class _SignUpPageState extends State { ), ), ), + PasswordRequirements(password: _passwordController.text), const SizedBox(height: 20), // Champ Confirmation mot de passe diff --git a/pubspec.yaml b/pubspec.yaml index 86ff701..fe63bdd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.2+3 +version: 1.0.3+1 environment: sdk: ^3.9.2