Change Password Implemented

This commit is contained in:
2025-09-09 16:03:34 +05:30
parent b3fb387bdd
commit c322d1d2fd
7 changed files with 110 additions and 35 deletions

View File

@@ -71,7 +71,7 @@ class BeneficiaryService {
return response.data['name']; return response.data['name'];
} }
// Send Data for Validation // Beneficiary Validate And ADD
Future<bool> sendForValidation(Beneficiary beneficiary) async { Future<bool> sendForValidation(Beneficiary beneficiary) async {
try { try {
final response = await _dio.post( final response = await _dio.post(

View File

@@ -10,7 +10,7 @@ class ChangePasswordService {
}) async { }) async {
final response = await _dio.post( final response = await _dio.post(
'/api/otp/send', '/api/otp/send',
queryParameters: { data: {
'mobileNumber': mobileNumber, 'mobileNumber': mobileNumber,
'type': "CHANGE_LPWORD" 'type': "CHANGE_LPWORD"
}, },
@@ -18,6 +18,7 @@ class ChangePasswordService {
if (response.statusCode != 200) { if (response.statusCode != 200) {
throw Exception("Invalid Mobile Number/Type"); throw Exception("Invalid Mobile Number/Type");
} }
print(response.toString());
return response.toString(); return response.toString();
} }
@@ -28,7 +29,7 @@ class ChangePasswordService {
}) async { }) async {
final response = await _dio.post( final response = await _dio.post(
'/api/otp/verify?mobileNumber=$mobileNumber', '/api/otp/verify?mobileNumber=$mobileNumber',
queryParameters: { data: {
'otp' : otp, 'otp' : otp,
}, },
); );
@@ -45,7 +46,7 @@ class ChangePasswordService {
}) async { }) async {
final response = await _dio.post( final response = await _dio.post(
'/api/auth/change/login_password', '/api/auth/change/login_password',
queryParameters: { data: {
'OldLPsw': OldLPsw, 'OldLPsw': OldLPsw,
'newLPsw': newLPsw, 'newLPsw': newLPsw,
'confirmLPsw': confirmLPsw, 'confirmLPsw': confirmLPsw,

View File

@@ -11,6 +11,7 @@ import 'package:kmobile/features/auth/controllers/theme_cubit.dart';
import 'package:kmobile/features/auth/controllers/theme_mode_cubit.dart'; import 'package:kmobile/features/auth/controllers/theme_mode_cubit.dart';
import '../api/services/auth_service.dart'; import '../api/services/auth_service.dart';
import '../api/interceptors/auth_interceptor.dart'; import '../api/interceptors/auth_interceptor.dart';
import '../api/services/change_password_service.dart';
import '../data/repositories/auth_repository.dart'; import '../data/repositories/auth_repository.dart';
import '../features/auth/controllers/auth_cubit.dart'; import '../features/auth/controllers/auth_cubit.dart';
import '../security/secure_storage.dart'; import '../security/secure_storage.dart';
@@ -48,6 +49,7 @@ Future<void> setupDependencies() async {
getIt.registerSingleton<NeftService>(NeftService(getIt<Dio>())); getIt.registerSingleton<NeftService>(NeftService(getIt<Dio>()));
getIt.registerSingleton<RtgsService>(RtgsService(getIt<Dio>())); getIt.registerSingleton<RtgsService>(RtgsService(getIt<Dio>()));
getIt.registerSingleton<ImpsService>(ImpsService(getIt<Dio>())); getIt.registerSingleton<ImpsService>(ImpsService(getIt<Dio>()));
getIt.registerLazySingleton<ChangePasswordService>(() => ChangePasswordService(getIt<Dio>()),);
// Add auth interceptor after repository is available // Add auth interceptor after repository is available
getIt<Dio>().interceptors.add( getIt<Dio>().interceptors.add(
@@ -63,8 +65,8 @@ Dio _createDioClient() {
final dio = Dio( final dio = Dio(
BaseOptions( BaseOptions(
baseUrl: baseUrl:
'http://lb-test-mobile-banking-app-192209417.ap-south-1.elb.amazonaws.com:8080', //'http://lb-test-mobile-banking-app-192209417.ap-south-1.elb.amazonaws.com:8080',
//'http://localhost:8081', 'http://localhost:8081',
// 'http://localhost:8082', // 'http://localhost:8082',
connectTimeout: const Duration(seconds: 5), connectTimeout: const Duration(seconds: 5),
receiveTimeout: const Duration(seconds: 10), receiveTimeout: const Duration(seconds: 10),

View File

@@ -1,15 +1,21 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../../api/services/change_password_service.dart';
import '../../../di/injection.dart';
import '../../../l10n/app_localizations.dart';
class ChangePasswordOTPScreen extends StatefulWidget { class ChangePasswordOTPScreen extends StatefulWidget {
final String currentPassword; final String currentPassword;
final String newPassword; final String newPassword;
final String confirmPassword; final String confirmPassword;
final String mobileNumber;
// ignore: use_key_in_widget_constructors // ignore: use_key_in_widget_constructors
const ChangePasswordOTPScreen({ const ChangePasswordOTPScreen({
required this.currentPassword, required this.currentPassword,
required this.newPassword, required this.newPassword,
required this.confirmPassword, required this.confirmPassword,
required this.mobileNumber,
}); });
@override @override
@@ -30,20 +36,39 @@ class _ChangePasswordOTPScreenState extends State<ChangePasswordOTPScreen> {
}); });
}); });
} }
final changePasswordService = getIt<ChangePasswordService>();
Future<void> _validateOTP() async {
try {
await changePasswordService.validateOtp(
otp: otpController.text,
mobileNumber: widget.mobileNumber,
);
void _validateOTP() { // If OTP is valid, then change the password
// TODO: Add validation logic later await changePasswordService.validateChangePwd(
print("Validating OTP..."); OldLPsw: widget.currentPassword,
print('Current Password: ${widget.currentPassword}'); newLPsw: widget.newPassword,
print('New Password: ${widget.newPassword}'); confirmLPsw: widget.confirmPassword,
print('Confirm Password: ${widget.confirmPassword}'); );
print('Entered OTP: ${otpController.text}');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(AppLocalizations.of(context).pwdchangeSuccess)),
);
// Navigate back to profile or login
Navigator.of(context).popUntil((route) => route.isFirst);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('${AppLocalizations.of(context).failedToValidate}: $e')),
);
}
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('OTP Verification')), appBar: AppBar(title: Text(AppLocalizations.of(context).otpVerification)),
body: Padding( body: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: _isLoading child: _isLoading
@@ -51,18 +76,18 @@ class _ChangePasswordOTPScreenState extends State<ChangePasswordOTPScreen> {
: Column( : Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
const Text( Text(
'An OTP has been sent to your registered mobile number.', AppLocalizations.of(context).otpSent,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(fontSize: 16), style: const TextStyle(fontSize: 16),
), ),
const SizedBox(height: 24), const SizedBox(height: 24),
TextFormField( TextFormField(
controller: otpController, controller: otpController,
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
decoration: const InputDecoration( decoration: InputDecoration(
labelText: 'Enter OTP', labelText: AppLocalizations.of(context).enterOTP,
border: OutlineInputBorder(), border: const OutlineInputBorder(),
), ),
), ),
const SizedBox(height: 24), const SizedBox(height: 24),
@@ -73,7 +98,7 @@ class _ChangePasswordOTPScreenState extends State<ChangePasswordOTPScreen> {
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16), padding: const EdgeInsets.symmetric(vertical: 16),
), ),
child: const Text('Validate OTP'), child: Text(AppLocalizations.of(context).validateOTP),
), ),
), ),
], ],

View File

@@ -1,6 +1,8 @@
// ignore_for_file: use_key_in_widget_constructors // ignore_for_file: use_key_in_widget_constructors
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../../api/services/change_password_service.dart';
import '../../../di/injection.dart';
import '../../../l10n/app_localizations.dart'; import '../../../l10n/app_localizations.dart';
import 'change_password_otp_screen.dart'; import 'change_password_otp_screen.dart';
@@ -26,36 +28,43 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
String? validateCurrentPassword(String? value) { String? validateCurrentPassword(String? value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
return 'Current password is required'; return AppLocalizations.of(context).currentpwdrqd;
} }
return null; return null;
} }
String? validateNewPassword(String? value) { String? validateNewPassword(String? value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
return 'New password is required'; return AppLocalizations.of(context).newpwdrqd;
} }
if (!passwordRegex.hasMatch(value)) { if (!passwordRegex.hasMatch(value)) {
return 'At least 8 chars, upper & lower case, digit, special char'; return AppLocalizations.of(context).pwdFormat;
} }
if (value == currentPasswordController.text) { if (value == currentPasswordController.text) {
return 'New password must differ from current'; return AppLocalizations.of(context).newoldpwddiff;
} }
return null; return null;
} }
String? validateConfirmPassword(String? value) { String? validateConfirmPassword(String? value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
return 'Confirm new password is required'; return AppLocalizations.of(context).confirmpwdrqd;
} }
if (value != newPasswordController.text) { if (value != newPasswordController.text) {
return 'Passwords do not match'; return AppLocalizations.of(context).pwdmismatch;
} }
return null; return null;
} }
final ChangePasswordService _changePasswordService = getIt<ChangePasswordService>();
void _proceed() async {
if (_formKey.currentState!.validate()) {
try {
const mobileNumber = "8981274001"; // Replace with actual mobile number
await _changePasswordService.getOtp(mobileNumber: mobileNumber);
void _proceed() {
if (_formKey.currentState!.validate()) {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
@@ -63,11 +72,17 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
currentPassword: currentPasswordController.text, currentPassword: currentPasswordController.text,
newPassword: newPasswordController.text, newPassword: newPasswordController.text,
confirmPassword: confirmPasswordController.text, confirmPassword: confirmPasswordController.text,
mobileNumber: mobileNumber,
), ),
), ),
); );
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('${AppLocalizations.of(context).failedtosentOTP}: $e')),
);
} }
} }
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -83,7 +98,7 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
controller: currentPasswordController, controller: currentPasswordController,
obscureText: !_showCurrentPassword, obscureText: !_showCurrentPassword,
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Current Password', labelText: AppLocalizations.of(context).currentpwd,
suffixIcon: IconButton( suffixIcon: IconButton(
icon: Icon(_showCurrentPassword icon: Icon(_showCurrentPassword
? Icons.visibility ? Icons.visibility
@@ -99,7 +114,7 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
controller: newPasswordController, controller: newPasswordController,
obscureText: !_showNewPassword, obscureText: !_showNewPassword,
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'New Password', labelText: AppLocalizations.of(context).newpwd,
suffixIcon: IconButton( suffixIcon: IconButton(
icon: Icon(_showNewPassword icon: Icon(_showNewPassword
? Icons.visibility ? Icons.visibility
@@ -115,7 +130,7 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
controller: confirmPasswordController, controller: confirmPasswordController,
obscureText: !_showConfirmPassword, obscureText: !_showConfirmPassword,
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Confirm New Password', labelText: AppLocalizations.of(context).confirmpwd,
suffixIcon: IconButton( suffixIcon: IconButton(
icon: Icon(_showConfirmPassword icon: Icon(_showConfirmPassword
? Icons.visibility ? Icons.visibility

View File

@@ -292,5 +292,21 @@
"viewCardDeatils": "View Card Details", "viewCardDeatils": "View Card Details",
"logout": "Logout", "logout": "Logout",
"logoutCheck": "Are you sure you want to logout?", "logoutCheck": "Are you sure you want to logout?",
"changeLoginPassword": "Change Login Password" "changeLoginPassword": "Change Login Password",
"currentpwdrqd": "Current password is required",
"newpwdrqd": "New password is required",
"pwdFormat": "At least 8 characters(upper & lower case), digit, special char",
"newoldpwddiff": "New password must differ from current",
"confirmpwdrqd": "Confirm password is required",
"pwdmismatch": "Passwords do not match",
"failedtosentOTP": "Failed to send OTP",
"currentpwd": "Current Password",
"newpwd": "New Password",
"confirmpwd": "Confirm New Password",
"pwdchangeSuccess": "Password changed successfully!",
"failedToValidate": "Failed to Validate",
"otpVerification": "OTP Verification",
"otpSent": "An OTP has been sent to your registered mobile number.",
"enterOTP": "Enter OTP",
"validateOTP": "Validate OTP"
} }

View File

@@ -293,5 +293,21 @@
"viewCardDeatils": "कार्ड विवरण देखें", "viewCardDeatils": "कार्ड विवरण देखें",
"logout": "लॉग आउट", "logout": "लॉग आउट",
"logoutCheck": "क्या आप लॉग आउट करना चाहते हैं?", "logoutCheck": "क्या आप लॉग आउट करना चाहते हैं?",
"changeLoginPassword": "लॉगिन पासवर्ड बदलें" "changeLoginPassword": "लॉगिन पासवर्ड बदलें",
"currentpwdrqd": "वर्तमान पासवर्ड आवश्यक है",
"newpwdrqd": "नया पासवर्ड आवश्यक है",
"pwdFormat": "कम से कम 8 अक्षर (बड़े और छोटे अक्षर), अंक, विशेष अक्षर",
"newoldpwddiff": "नया पासवर्ड वर्तमान पासवर्ड से भिन्न होना चाहिए",
"confirmpwdrqd": "पुष्टि पासवर्ड आवश्यक है",
"pwdmismatch": "सांकेतिक शब्द मेल नहीं खाते",
"failedtosentOTP": "ओटीपी भेजने में विफल",
"currentpwd": "वर्तमान पासवर्ड",
"newpwd": "नया पासवर्ड",
"confirmpwd": "नए पासवर्ड की पुष्टि करें",
"pwdchangeSuccess": "पासवर्ड सफलतापूर्वक बदला गया!",
"failedToValidate": "सत्यापित करने में विफल",
"otpVerification": "ओटीपी सत्यापन",
"otpSent": "आपके पंजीकृत मोबाइल नंबर पर एक ओटीपी भेजा गया है।",
"enterOTP": "ओटीपी दर्ज करें",
"validateOTP": "ओटीपी सत्यापित करें"
} }