import 'package:wanisclient/utils/colors.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../config/constants/arabe.dart' as Language; import '../../config/custom_text.dart'; import '../../providers/authentification_provider.dart'; import '../../providers/language_provider.dart'; import '../../providers/utils_singleton.dart'; import '../../routes/app_routes.dart'; import '../../services/Sockets/PubNubManager.dart'; import '../../widgets/custom_button.dart'; import 'PasswordInputWidget.dart'; class CreatePasswordScreen extends StatefulWidget { final bool isForgetPassword; final String code; final String phonenumber; const CreatePasswordScreen({super.key,required this.isForgetPassword,required this.code,required this.phonenumber}); @override State createState() => _CreatePasswordScreenState(); } class _CreatePasswordScreenState extends State { final TextEditingController passwordController = TextEditingController(); final TextEditingController confirmPasswordController =TextEditingController(); final GlobalKey _formKey = GlobalKey(); late final AuthProvider authProvider; late final PubNubManager pubNubManager; bool isPasswordStrong = false; String passwordStrengthText = ''; Color passwordStrengthColor = Colors.grey; // Add validation state for confirm password String? confirmPasswordError; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { authProvider = context.read(); pubNubManager = context.read(); context.read().getLanguage(); }); } void _checkPasswordStrength(String password) { setState(() { if (password.isEmpty) { passwordStrengthText = ''; passwordStrengthColor = Colors.grey; isPasswordStrong = false; return; } // Password strength criteria bool hasMinLength = password.length >= 8; bool hasUpperCase = password.contains(RegExp(r'[A-Z]')); bool hasLowerCase = password.contains(RegExp(r'[a-z]')); bool hasNumbers = password.contains(RegExp(r'[0-9]')); bool hasSpecialCharacters = password.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]')); int strengthScore = 0; if (hasMinLength) strengthScore++; if (hasUpperCase) strengthScore++; if (hasLowerCase) strengthScore++; if (hasNumbers) strengthScore++; if (hasSpecialCharacters) strengthScore++; if (strengthScore >= 4) { passwordStrengthText = 'Choose a strong password'; passwordStrengthColor = Colors.green; isPasswordStrong = true; } else if (strengthScore >= 2) { passwordStrengthText = 'Choose a strong password'; passwordStrengthColor = Colors.orange; isPasswordStrong = false; } else { passwordStrengthText = 'Choose a strong password'; passwordStrengthColor = Colors.red; isPasswordStrong = false; } }); } void _validateConfirmPassword() { setState(() { if (confirmPasswordController.text.isEmpty) { confirmPasswordError = 'Please confirm your password'; } else if (confirmPasswordController.text != passwordController.text) { confirmPasswordError = 'must match the password above'; } else { confirmPasswordError = null; } }); } String? _validatePassword(String? value) { if (value == null || value.isEmpty) { return 'Password is required'; } if (value.length < 8) { return 'Password must be at least 8 characters'; } return null; } Future _isUserTokenValid(SharedPreferences prefs) async { var tokenData = prefs.getString("token"); bool tokenverif = tokenData != null && tokenData.isNotEmpty && tokenData != "InvalidToken"; utils.updatetoken(tokenData ?? "InvalidToken"); bool fetchprofile = await authProvider.fetchProfile(); return fetchprofile && tokenverif; } @override void dispose() { passwordController.dispose(); confirmPasswordController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final languageProvider = context.watch(); final signUpProvider = context.watch(); bool isArabic = languageProvider.currentLangCode == Language.ar; return Scaffold( backgroundColor: AppNewColors.whiteBackGround, body: SafeArea( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Form( key: _formKey, child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 20), // Back button InkWell( onTap: () { Navigator.pop(context); }, child: Container( width: 32, height: 32, margin: const EdgeInsets.symmetric(vertical: 12), decoration: BoxDecoration( color: AppNewColors.lightgray, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: AppNewColors.black.withOpacity(.1), blurRadius: 1, offset: const Offset(2, 1), //spreadRadius: -32, ) ]), child: const Icon( Icons.arrow_back, color: AppNewColors.black, size: 16, ), ), ), const SizedBox(height: 40), // Title Txt( text: 'Create your password', style: TextStyle( color: AppNewColors.titleTextColor, fontSize: 28, fontFamily: isArabic ? "Readex_Pro" : 'Inter', fontWeight: FontWeight.w700, height: 1.2, ), ), const SizedBox(height: 8), // Subtitle Txt( text: "let's secure your account", style: TextStyle( color: AppNewColors.grayTxtColor, fontSize: 16, fontFamily: isArabic ? "Readex_Pro" : 'Inter', fontWeight: FontWeight.w400, height: 1.5, ), ), const SizedBox(height: 40), // Password field PasswordWidget( label: 'Password', hintText: 'Enter your password', controller: passwordController, isArabic: isArabic, validator: _validatePassword, onChanged: (value) { _checkPasswordStrength(value); // Also validate confirm password when main password changes if (confirmPasswordController.text.isNotEmpty) { _validateConfirmPassword(); } }, ), // Password strength indicator bars if (passwordController.text.isNotEmpty) ...[ const SizedBox(height: 12), Row( children: List.generate(4, (index) { Color barColor = AppNewColors.inputTextColor.withOpacity(0.3); // Calculate strength score for coloring bars String password = passwordController.text; bool hasMinLength = password.length >= 8; bool hasUpperCase = password.contains(RegExp(r'[A-Z]')); bool hasLowerCase = password.contains(RegExp(r'[a-z]')); bool hasNumbers = password.contains(RegExp(r'[0-9]')); bool hasSpecialCharacters = password .contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]')); int strengthScore = 0; if (hasMinLength) strengthScore++; if (hasUpperCase) strengthScore++; if (hasLowerCase) strengthScore++; if (hasNumbers) strengthScore++; if (hasSpecialCharacters) strengthScore++; // Color bars based on strength if (strengthScore >= 4 && index < 4) { barColor = Colors.green; // Strong - all bars green } else if (strengthScore >= 3 && index < 3) { barColor = Colors.orange; // Medium - first 3 bars orange } else if (strengthScore >= 2 && index < 2) { barColor = Colors.orange; // Fair - first 2 bars orange } else if (strengthScore >= 1 && index < 1) { barColor = AppNewColors.redColor; // Weak - first bar red } return Expanded( child: Container( height: 4, margin: EdgeInsets.only(right: index < 3 ? 8 : 0), decoration: BoxDecoration( color: barColor, borderRadius: BorderRadius.circular(2), ), ), ); }), ), const SizedBox(height: 8), ], // Password strength text if (passwordStrengthText.isNotEmpty) ...[ Text( passwordStrengthText, style: TextStyle( color: passwordStrengthColor, fontSize: 14, fontFamily: isArabic ? "Readex_Pro" : 'Inter', fontWeight: FontWeight.w400, ), ), const SizedBox(height: 8), ], // Password strength text if (passwordController.text.isNotEmpty && !isPasswordStrong) ...[ Txt( text: 'Use uppercase letters, numbers & special characters', style: TextStyle( color: AppNewColors.inputTextColor, fontSize: 12, fontFamily: isArabic ? "Readex_Pro" : 'Inter', fontWeight: FontWeight.w400, ), ), const SizedBox(height: 8), ], const SizedBox(height: 16), // Confirm Password field - WITHOUT validator PasswordWidget( label: 'Confirm password', hintText: 'Confirm password', controller: confirmPasswordController, isArabic: isArabic, validator: null, // Remove the built-in validator onChanged: (value) { _validateConfirmPassword(); // Use our custom validation }, ), // External validation message for confirm password if (confirmPasswordError != null) ...[ const SizedBox(height: 8), Row( children: [ const Icon( Icons.error_outline, color: AppNewColors.redColor, size: 16, ), const SizedBox(width: 8), Text( confirmPasswordError!, style: TextStyle( color: AppNewColors.redColor, fontSize: 14, fontFamily: isArabic ? "Readex_Pro" : 'Inter', fontWeight: FontWeight.w400, ), ), ], ), ], const SizedBox(height: 24), // Continue button Padding( padding: const EdgeInsets.only(bottom: 40), child: CustomButton( onClick: () async { if (signUpProvider.loader) return; // Manual validation for confirm password _validateConfirmPassword(); if (_formKey.currentState!.validate() && confirmPasswordError == null) { final prefs = await SharedPreferences.getInstance(); var res =false; if(widget.isForgetPassword){ res = await signUpProvider.ResetPassword(confirmPasswordController.text,widget.phonenumber,widget.code); }else{ res = await signUpProvider.ChangePassword(confirmPasswordController.text); if (res) { if (await _isUserTokenValid(prefs)) { final userContext = UserContext(username: utils.user!.username!); pubNubManager.init(userContext); prefs.setBool("isSecondTime", true); Get.toNamed(AppRoutes.allowLocation); return; } } } } }, fontSize: 18, width: double.infinity, height: 40, borderRadius: 10, txtColor: AppNewColors.white, title: 'Continue', backgroundColor: AppNewColors.primaryBtnColor, borderColor: AppNewColors.primaryBtnColor, isloading: signUpProvider.loader, loadercolor: AppNewColors.white, ), ), ], ), ), ), ), ), ); } }