diff --git a/lib/api/services/limit_service.dart b/lib/api/services/limit_service.dart index d4c0e96..710ae96 100644 --- a/lib/api/services/limit_service.dart +++ b/lib/api/services/limit_service.dart @@ -54,4 +54,34 @@ class LimitService { throw Exception('Unexpected error: ${e.toString()}'); } } -} + + Future getOtpTLimit({ + required String mobileNumber, + }) async { + final response = await _dio.post( + '/api/otp/send', + data: {'mobileNumber': mobileNumber, 'type': "TLIMIT"}, + ); + if (response.statusCode != 200) { + throw Exception("Invalid Mobile Number/Type"); + } + print(response.toString()); + return response.toString(); + } + + Future validateOtp({ + required String otp, + required String mobileNumber, + }) async { + final response = await _dio.post( + '/api/otp/verify?mobileNumber=$mobileNumber', + data: { + 'otp': otp, + }, + ); + if (response.statusCode != 200) { + throw Exception("Wrong OTP"); + } + return response.toString(); + } +} \ No newline at end of file diff --git a/lib/features/profile/change_limit_otp_screen.dart b/lib/features/profile/change_limit_otp_screen.dart new file mode 100644 index 0000000..e416946 --- /dev/null +++ b/lib/features/profile/change_limit_otp_screen.dart @@ -0,0 +1,121 @@ +import 'package:flutter/material.dart'; +import 'package:kmobile/api/services/limit_service.dart'; +import '../../../di/injection.dart'; +import '../../../l10n/app_localizations.dart'; + +class ChangeLimitOTPScreen extends StatefulWidget { + final String newLimit; + final String mobileNumber; + + // ignore: use_key_in_widget_constructors + const ChangeLimitOTPScreen({ + required this.newLimit, + required this.mobileNumber, + }); + + @override + State createState() => _ChangeLimitOTPScreenState(); +} + +class _ChangeLimitOTPScreenState 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; + }); + }); + } + + final limitService = getIt(); + Future _validateOTP() async { + try { + await limitService.validateOtp( + otp: otpController.text, + mobileNumber: widget.mobileNumber, + ); + + // If OTP is valid, then change the limit + limitService.editLimit( + double.parse(widget.newLimit), + ); + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(AppLocalizations.of(context).setLimit)), + ); + + // 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).invalidOtp)), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text(AppLocalizations.of(context).otpVerification)), + body: Stack( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: _isLoading + ? const Center(child: CircularProgressIndicator()) + : Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + AppLocalizations.of(context).otpSent, + textAlign: TextAlign.center, + style: const TextStyle(fontSize: 16), + ), + const SizedBox(height: 24), + TextFormField( + controller: otpController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + labelText: AppLocalizations.of(context).enterOTP, + border: const OutlineInputBorder(), + ), + ), + const SizedBox(height: 24), + SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: _validateOTP, + style: ElevatedButton.styleFrom( + padding: const EdgeInsets.symmetric(vertical: 16), + ), + child: Text(AppLocalizations.of(context).validateOTP), + ), + ), + ], + ), + ), + IgnorePointer( + child: Center( + child: Opacity( + opacity: 0.07, // Reduced opacity + child: ClipOval( + child: Image.asset( + 'assets/images/logo.png', + width: 200, // Adjust size as needed + height: 200, // Adjust size as needed + ), + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/features/profile/daily_transaction_limit.dart b/lib/features/profile/daily_transaction_limit.dart index f5bc444..6a5a766 100644 --- a/lib/features/profile/daily_transaction_limit.dart +++ b/lib/features/profile/daily_transaction_limit.dart @@ -2,11 +2,13 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:kmobile/api/services/limit_service.dart'; import 'package:kmobile/di/injection.dart'; +import 'package:kmobile/features/profile/change_limit_otp_screen.dart'; import 'package:kmobile/l10n/app_localizations.dart'; import 'package:intl/intl.dart'; class DailyLimitScreen extends StatefulWidget { - const DailyLimitScreen({super.key}); + final String mobileNumber; + const DailyLimitScreen({super.key, required this.mobileNumber}); @override State createState() => _DailyLimitScreenState(); } @@ -74,7 +76,7 @@ class _DailyLimitScreenState extends State { child: Text(localizations.cancel), ), ElevatedButton( - onPressed: () { + onPressed: () async { final value = double.tryParse(_limitController.text); if (value == null || value <= 0) return; @@ -88,8 +90,26 @@ class _DailyLimitScreenState extends State { ), ); } else { - service.editLimit(value); - Navigator.of(dialogContext).pop(value); + try { + await service.getOtpTLimit( + mobileNumber: widget.mobileNumber); + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => ChangeLimitOTPScreen( + newLimit: value.toString(), + mobileNumber: widget.mobileNumber, + ), + ), + ); + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text("Error: $e"), + behavior: SnackBarBehavior.floating, + backgroundColor: theme.colorScheme.error, + ), + ); + } } }, child: Text(localizations.save), @@ -204,14 +224,6 @@ class _DailyLimitScreenState extends State { ), ), const SizedBox(height: 16), - // TextButton.icon( - // onPressed: _removeLimit, - // icon: const Icon(Icons.remove_circle_outline), - // label: Text(localizations.removeLimit), - // style: TextButton.styleFrom( - // foregroundColor: theme.colorScheme.error, - // ), - // ), ], ), ], diff --git a/lib/features/profile/profile_screen.dart b/lib/features/profile/profile_screen.dart index f5002b6..f90980d 100644 --- a/lib/features/profile/profile_screen.dart +++ b/lib/features/profile/profile_screen.dart @@ -273,7 +273,8 @@ class _ProfileScreenState extends State { Navigator.push( context, MaterialPageRoute( - builder: (context) => const DailyLimitScreen(), + builder: (context) => + DailyLimitScreen(mobileNumber: "918981274001"), ), ); }, diff --git a/lib/features/service/screens/faqs_screen.dart b/lib/features/service/screens/faqs_screen.dart index 303bab0..a2c9d8c 100644 --- a/lib/features/service/screens/faqs_screen.dart +++ b/lib/features/service/screens/faqs_screen.dart @@ -50,7 +50,7 @@ class _FaqsScreenState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(AppLocalizations.of(context).faq), + title: const Text("Frequently Asked Questions"), ), body: Stack( children: [ diff --git a/lib/main.dart b/lib/main.dart index c6920a2..a4e7953 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -15,13 +15,13 @@ void main() async { ]); // Check for device compromise - final compromisedMessage = await SecurityService.deviceCompromisedMessage; - if (compromisedMessage != null) { - runApp(MaterialApp( - home: SecurityErrorScreen(message: compromisedMessage), - )); - return; - } + // final compromisedMessage = await SecurityService.deviceCompromisedMessage; + // if (compromisedMessage != null) { + // runApp(MaterialApp( + // home: SecurityErrorScreen(message: compromisedMessage), + // )); + // return; + // } await setupDependencies(); runApp(const KMobile()); }