Download PDF #2
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ChangePasswordOTPScreen extends StatefulWidget {
|
||||
final String currentPassword;
|
||||
final String newPassword;
|
||||
final String confirmPassword;
|
||||
|
||||
// ignore: use_key_in_widget_constructors
|
||||
const ChangePasswordOTPScreen({
|
||||
required this.currentPassword,
|
||||
required this.newPassword,
|
||||
required this.confirmPassword,
|
||||
});
|
||||
|
||||
@override
|
||||
State<ChangePasswordOTPScreen> createState() => _ChangePasswordOTPScreenState();
|
||||
}
|
||||
|
||||
class _ChangePasswordOTPScreenState extends State<ChangePasswordOTPScreen> {
|
||||
bool _isLoading = true;
|
||||
final TextEditingController otpController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// Simulate OTP sending delay
|
||||
Future.delayed(const Duration(seconds: 2), () {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void _validateOTP() {
|
||||
// TODO: Add validation logic later
|
||||
print("Validating OTP...");
|
||||
print('Current Password: ${widget.currentPassword}');
|
||||
print('New Password: ${widget.newPassword}');
|
||||
print('Confirm Password: ${widget.confirmPassword}');
|
||||
print('Entered OTP: ${otpController.text}');
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('OTP Verification')),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: _isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Text(
|
||||
'An OTP has been sent to your registered mobile number.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 16),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
TextFormField(
|
||||
controller: otpController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Enter OTP',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: _validateOTP,
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
),
|
||||
child: const Text('Validate OTP'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
140
lib/features/profile/change_password/change_password_screen.dart
Normal file
140
lib/features/profile/change_password/change_password_screen.dart
Normal file
@@ -0,0 +1,140 @@
|
||||
// ignore_for_file: use_key_in_widget_constructors
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import 'change_password_otp_screen.dart';
|
||||
|
||||
class ChangePasswordScreen extends StatefulWidget {
|
||||
const ChangePasswordScreen();
|
||||
|
||||
@override
|
||||
State<ChangePasswordScreen> createState() => _ChangePasswordScreenState();
|
||||
}
|
||||
|
||||
class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final currentPasswordController = TextEditingController();
|
||||
final newPasswordController = TextEditingController();
|
||||
final confirmPasswordController = TextEditingController();
|
||||
|
||||
bool _showCurrentPassword = false;
|
||||
bool _showNewPassword = false;
|
||||
bool _showConfirmPassword = false;
|
||||
|
||||
final passwordRegex =
|
||||
RegExp(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{8,}$');
|
||||
|
||||
String? validateCurrentPassword(String? value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Current password is required';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String? validateNewPassword(String? value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'New password is required';
|
||||
}
|
||||
if (!passwordRegex.hasMatch(value)) {
|
||||
return 'At least 8 chars, upper & lower case, digit, special char';
|
||||
}
|
||||
if (value == currentPasswordController.text) {
|
||||
return 'New password must differ from current';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String? validateConfirmPassword(String? value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Confirm new password is required';
|
||||
}
|
||||
if (value != newPasswordController.text) {
|
||||
return 'Passwords do not match';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void _proceed() {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ChangePasswordOTPScreen(
|
||||
currentPassword: currentPasswordController.text,
|
||||
newPassword: newPasswordController.text,
|
||||
confirmPassword: confirmPasswordController.text,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(AppLocalizations.of(context).changePassword)),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: currentPasswordController,
|
||||
obscureText: !_showCurrentPassword,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Current Password',
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(_showCurrentPassword
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off),
|
||||
onPressed: () =>
|
||||
setState(() => _showCurrentPassword = !_showCurrentPassword),
|
||||
),
|
||||
),
|
||||
validator: validateCurrentPassword,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
controller: newPasswordController,
|
||||
obscureText: !_showNewPassword,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'New Password',
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(_showNewPassword
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off),
|
||||
onPressed: () =>
|
||||
setState(() => _showNewPassword = !_showNewPassword),
|
||||
),
|
||||
),
|
||||
validator: validateNewPassword,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
controller: confirmPasswordController,
|
||||
obscureText: !_showConfirmPassword,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Confirm New Password',
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(_showConfirmPassword
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off),
|
||||
onPressed: () =>
|
||||
setState(() => _showConfirmPassword = !_showConfirmPassword),
|
||||
),
|
||||
),
|
||||
validator: validateConfirmPassword,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
ElevatedButton(
|
||||
onPressed: _proceed,
|
||||
child: Text(AppLocalizations.of(context).proceed),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:kmobile/data/repositories/auth_repository.dart';
|
||||
import 'package:kmobile/features/profile/change_password/change_password_screen.dart';
|
||||
import 'package:kmobile/features/profile/logout_dialog.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../../di/injection.dart';
|
||||
@@ -44,7 +45,10 @@ class ProfileScreen extends StatelessWidget {
|
||||
leading: const Icon(Icons.password),
|
||||
title: Text(loc.changePassword),
|
||||
onTap: () {
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const ChangePasswordScreen()),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
|
Reference in New Issue
Block a user