diff --git a/lib/di/injection.dart b/lib/di/injection.dart index 4b04807..eb462e2 100644 --- a/lib/di/injection.dart +++ b/lib/di/injection.dart @@ -63,8 +63,9 @@ Dio _createDioClient() { final dio = Dio( BaseOptions( 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:8082', connectTimeout: const Duration(seconds: 5), receiveTimeout: const Duration(seconds: 10), headers: { diff --git a/lib/features/fund_transfer/screens/payment_animation.dart b/lib/features/fund_transfer/screens/payment_animation.dart index 2d9fa55..f53937a 100644 --- a/lib/features/fund_transfer/screens/payment_animation.dart +++ b/lib/features/fund_transfer/screens/payment_animation.dart @@ -209,26 +209,21 @@ class _PaymentAnimationScreenState extends State { onPressed: _shareScreenshot, icon: Icon( Icons.share_rounded, - color: Theme.of(context).primaryColor, + color: Theme.of(context).colorScheme.primary, ), label: Text( AppLocalizations.of(context).share, - style: TextStyle(color: Theme.of(context).primaryColor), + style: TextStyle(color: Theme.of(context).colorScheme.primary), ), style: ElevatedButton.styleFrom( - backgroundColor: - Theme.of(context).scaffoldBackgroundColor, padding: const EdgeInsets.symmetric( - horizontal: 32, vertical: 12), + horizontal: 45, vertical: 12), shape: RoundedRectangleBorder( - side: BorderSide( - color: Theme.of(context).primaryColor, width: 1), borderRadius: BorderRadius.circular(30), ), textStyle: const TextStyle( fontSize: 18, fontWeight: FontWeight.w600, - color: Colors.black, ), ), ), diff --git a/lib/features/profile/change_password/change_password_otp_screen.dart b/lib/features/profile/change_password/change_password_otp_screen.dart new file mode 100644 index 0000000..c87703b --- /dev/null +++ b/lib/features/profile/change_password/change_password_otp_screen.dart @@ -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 createState() => _ChangePasswordOTPScreenState(); +} + +class _ChangePasswordOTPScreenState extends State { + 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'), + ), + ), + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/features/profile/change_password/change_password_screen.dart b/lib/features/profile/change_password/change_password_screen.dart new file mode 100644 index 0000000..deb47da --- /dev/null +++ b/lib/features/profile/change_password/change_password_screen.dart @@ -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 createState() => _ChangePasswordScreenState(); +} + +class _ChangePasswordScreenState extends State { + final _formKey = GlobalKey(); + 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), + ), + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/features/profile/profile_screen.dart b/lib/features/profile/profile_screen.dart index 5f8642e..cdb6053 100644 --- a/lib/features/profile/profile_screen.dart +++ b/lib/features/profile/profile_screen.dart @@ -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(