diff --git a/lib/appLocalization/languages.dart b/lib/appLocalization/languages.dart index 3c4fc5f59e5343e4d6122983be62f67331522063..0856a691b491957e3536b6072c6a2e67d1ae3114 100644 --- a/lib/appLocalization/languages.dart +++ b/lib/appLocalization/languages.dart @@ -18,7 +18,7 @@ class Languages extends Translations { otpTitle:"Verify OTP", otpSubTitle:"Please verify the OTP which have been sent your registered mobile number.", enterOTP:"Enter OTP", - resendOTPIn: "Resend OTP in ", + resendOTPIn: " in ", resendOTP: "Resend OTP", seconds: "seconds.", verify: "Verify", @@ -38,7 +38,7 @@ class Languages extends Translations { otpTitle:"ओटीपी सत्यापित करें", otpSubTitle:"कृपया उस ओटीपी को सत्यापित करें जो आपके पंजीकृत मोबाइल नंबर पर भेजा गया है।", enterOTP:"ओटीपी दर्ज करें", - resendOTPIn:"ओटीपी दोबारा भेजें", + resendOTPIn:" ", resendOTP: "ओटीपी दोबारा भेजें", seconds:"सेकंड में ", verify: "सत्यापित करें", diff --git a/lib/utils/res/styles.dart b/lib/utils/res/styles.dart index f612e43de81f09a33c3f7d70347b7222848a4c05..3ffdc4ec07977a49d96897006a9d1e3046dd5235 100644 --- a/lib/utils/res/styles.dart +++ b/lib/utils/res/styles.dart @@ -206,7 +206,7 @@ class Styles { FontConstants.fontFamilyName, fontSize: TextSize.textSmallSize, fontWeight: FontWeight.w400, - color: AppColor.lightGrey,decoration: TextDecoration.underline,decorationColor:AppColor.redLight, + color: AppColor.redLight.withOpacity(0.3),decoration: TextDecoration.underline,decorationColor: AppColor.redLight.withOpacity(0.3), ); static TextStyle resendText = GoogleFonts.getFont( @@ -215,4 +215,8 @@ class Styles { fontWeight: FontWeight.w400, color: AppColor.lightGrey, ); + static TextStyle pinCodeText = GoogleFonts.getFont(FontConstants.fontFamilyName, + fontSize: TextSize.textSmallSize, + fontWeight: FontWeight.w500, + color: AppColor.black); } diff --git a/lib/views/verifyOTP/controller/verify_otp_controller.dart b/lib/views/verifyOTP/controller/verify_otp_controller.dart index e37d9aa3ae70bb61e79590383ce9d9684919ac9b..04324bb6c31879da5dd2a4f0f85ac4a97efbef4a 100644 --- a/lib/views/verifyOTP/controller/verify_otp_controller.dart +++ b/lib/views/verifyOTP/controller/verify_otp_controller.dart @@ -1,51 +1,67 @@ import 'dart:async'; -import 'dart:math'; - import 'package:flutter/cupertino.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:get/get.dart'; -import 'package:get/get_state_manager/src/simple/get_controllers.dart'; import 'package:pin_code_fields/pin_code_fields.dart'; - import '../../../appLocalization/language_key.dart'; import '../../../constants/image_constants.dart'; import '../../../controller/base_controller.dart'; import '../../../serverRequest/all_request.dart'; -import '../widgets/verification_success_dialogue.dart'; +import '../../../customWidget/dialogues/success_dialogue.dart'; class VerifyOtpController extends GetxController { final baseController = Get.find<BaseController>(); - RxInt counter = 90.obs; + RxInt counter = 20.obs; Timer? timer; - RxString enteredOtp="".obs; + RxString enteredOtp = "".obs; StreamController<ErrorAnimationType> errorController = - StreamController<ErrorAnimationType>(); + StreamController<ErrorAnimationType>(); + TextEditingController otpTextController = TextEditingController(); + RxBool verifyLoader = false.obs; @override void onInit() { startTimer(); - print("otp"); - // generatedOtp=generateOTP().obs; AllHttpRequest().generateAuth(); super.onInit(); } - onClickVerifyHandler(BuildContext context){ - if (baseController.generatedOtp.value == - enteredOtp.value) { - verificationSuccess( - context: context, - assetName: ImageConstants.verificationSuccess, - title: verifySuccessTitle.tr, - subtitle: verifySuccessSubTitle.tr); - }else{ - Fluttertoast.showToast(msg: incorrectOTPError.tr); - } + onClickVerifyHandler(BuildContext context) { + verifyLoader(true); + Future.delayed( + const Duration(seconds: 30), + () => { + if (baseController.generatedOtp.value == + otpTextController.value.text) + { + verificationSuccess( + context: context, + assetName: ImageConstants.verificationSuccess, + title: verifySuccessTitle.tr, + subtitle: verifySuccessSubTitle.tr) + } + else + { + otpTextController.clear(), + verifyLoader(false), + Fluttertoast.showToast(msg: incorrectOTPError.tr) + } + }); + + update(); } + onClickResendOTP() { + resetTimer(); + startTimer(); + otpTextController.clear(); + update(); + AllHttpRequest().generateAuth(); + } startTimer() { + ///Decrease the counter value up to 0 timer = Timer.periodic(const Duration(seconds: 1), (timer) { if (counter > 0) { counter--; @@ -55,4 +71,9 @@ class VerifyOtpController extends GetxController { update(); }); } + + resetTimer() { + ///Set counter to 90s + counter = 90.obs; + } } diff --git a/lib/views/verifyOTP/view/verify_otp_screen.dart b/lib/views/verifyOTP/view/verify_otp_screen.dart index 762b0980e6cc4ab8f873640e2e1d5f4023ddd7f0..1b9d85cd81cdae9aff6391a6d0a42961c64d8308 100644 --- a/lib/views/verifyOTP/view/verify_otp_screen.dart +++ b/lib/views/verifyOTP/view/verify_otp_screen.dart @@ -6,6 +6,7 @@ import 'package:get_storage/get_storage.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:pin_code_fields/pin_code_fields.dart'; import '../../../appLocalization/language_key.dart'; +import '../../../constants/app_constants.dart'; import '../../../constants/font_constants.dart'; import '../../../customWidget/app_text.dart'; import '../../../customWidget/button_widget.dart'; @@ -13,8 +14,13 @@ import '../../../customWidget/otp_text_field/otp_text_field.dart'; import '../../../customWidget/otp_text_field/otp_text_field_style.dart'; import '../../../res/app_color_text_size.dart'; import '../../../serverRequest/all_request.dart'; +import '../../../utils/res/styles.dart'; import '../controller/verify_otp_controller.dart'; -import '../widgets/verification_success_dialogue.dart'; +import '../../../customWidget/dialogues/success_dialogue.dart'; +import '../widgets/floating_button.dart'; +import '../widgets/pincode_text_field.dart'; +import '../widgets/resend_otp_text.dart'; +import '../widgets/screen_header.dart'; class VerifyOtp extends StatefulWidget { const VerifyOtp({super.key}); @@ -29,101 +35,21 @@ class _VerifyOtpState extends State<VerifyOtp> { @override Widget build(BuildContext context) { return GetBuilder( - tag: 'onboarding_mobile_otp_controller_tag', + tag: Tag.verifyOtpControllerTag, init: VerifyOtpController(), builder: (controller) => Scaffold( backgroundColor: AppColor.white, body: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - Image.asset( - ImageConstants.backButton, - width: 32, - height: 32, - ), - AppText( - text: back.tr, - fontSize: 14, - fontWeight: FontWeight.w500, - textColor: AppColor.black, - ).paddingOnly(left: 12.0.h), - ], - ).paddingOnly(bottom: 24.0), - AppText( - text: otpTitle.tr, - fontSize: 24, - fontWeight: FontWeight.w500, - textColor: AppColor.lightBlack, - ).paddingOnly(bottom: 8.0.h), - AppText( - text: otpSubTitle.tr, - fontSize: 14, - fontWeight: FontWeight.w400, - textColor: AppColor.lightGrey, - maxLine: 3, - textAlign: TextAlign.start, - ), - AppText( - text: enterOtp.tr, - fontSize: 14, - fontWeight: FontWeight.w500, - textColor: AppColor.lightGrey, - ).paddingOnly(top: 24.0.h), - PinCodeTextField( - keyboardType: TextInputType.number, - length: 4, - enablePinAutofill: true, - enableActiveFill: true, - cursorColor: Colors.black,textStyle: GoogleFonts.getFont(FontConstants.fontFamilyName, - fontSize: 14, - fontWeight: FontWeight.w500, - color: Colors.black), - pinTheme: PinTheme( - shape: PinCodeFieldShape.box, - selectedFillColor:AppColor.lightWhite, - inactiveFillColor:AppColor.lightWhite, - activeColor: AppColor.lightWhite, - borderRadius: BorderRadius.circular(10), - fieldHeight: 50, - fieldWidth: 50, - selectedColor: AppColor.lightWhite, - activeFillColor: AppColor.lightWhite, - inactiveColor:AppColor.lightWhite, - ), - animationType: AnimationType.fade, - animationDuration: const Duration(milliseconds: 300), - errorAnimationController: controller.errorController, - // Pass it here - onChanged: (text) { - controller.enteredOtp(text); - }, - appContext: context, - ).paddingOnly(top: 8.0.h, bottom: 16.0.h, right: 92.w), - AppText( - text: '${resendOtp.tr} ${controller.counter} ${seconds.tr}', - fontSize: 14, - fontWeight: FontWeight.w400, - textColor: AppColor.lightGrey, - maxLine: 3, - textAlign: TextAlign.start, - ), + screenHeader(), + ///PinCode field + pinCodeField(controller,context), + ///Resend text + resendOTPText(controller) ], ).paddingOnly(right: 16.0.h, left: 16.0.h, top: 104.h), - floatingActionButton: Container( - padding: const EdgeInsets.symmetric(horizontal: 14.0), - width: MediaQuery.of(context).size.width, - height: 50, - child: CustomButton( - width: MediaQuery.of(context).size.width, - height: 50, - buttonName: verify.tr, - activeBackgroundColor: AppColor.darkRed, - isActive: controller.enteredOtp.value.length == 4, - onTap: () => controller.onClickVerifyHandler(context), - ), - ), + floatingActionButton: floatingBottomButton(controller,context), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, ), ); diff --git a/lib/views/verifyOTP/widgets/floating_button.dart b/lib/views/verifyOTP/widgets/floating_button.dart new file mode 100644 index 0000000000000000000000000000000000000000..fa75aa3ffc073c1b9cb5c3c7fadd8fe14ed72aac --- /dev/null +++ b/lib/views/verifyOTP/widgets/floating_button.dart @@ -0,0 +1,26 @@ +import 'package:flutter/cupertino.dart'; +import 'package:get/get.dart'; + +import '../../../appLocalization/language_key.dart'; +import '../../../customWidget/button_widget.dart'; +import '../../../res/app_color_text_size.dart'; +import '../controller/verify_otp_controller.dart'; + +Widget floatingBottomButton(VerifyOtpController controller,BuildContext context){ + return Container( + padding: const EdgeInsets.symmetric(horizontal: 14.0), + width: MediaQuery.of(context).size.width, + height: 50, + child: CustomButton( + isLoading: controller.verifyLoader.value, + width: MediaQuery.of(context).size.width, + height: 50, + buttonName: verify.tr, + activeBackgroundColor: controller.verifyLoader.value + ? AppColor.inActiveButtonColor + : AppColor.darkRed, + isActive: controller.otpTextController.value.text.length == 4, + onTap: () => controller.onClickVerifyHandler(context), + ), + ); +} \ No newline at end of file diff --git a/lib/views/verifyOTP/widgets/pincode_text_field.dart b/lib/views/verifyOTP/widgets/pincode_text_field.dart new file mode 100644 index 0000000000000000000000000000000000000000..7edec68f1f858b55f7b202f22dbab3e34ab48228 --- /dev/null +++ b/lib/views/verifyOTP/widgets/pincode_text_field.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:pin_code_fields/pin_code_fields.dart'; + +import '../../../constants/font_constants.dart'; +import '../../../res/app_color_text_size.dart'; +import '../../../utils/res/styles.dart'; +import '../controller/verify_otp_controller.dart'; + +Widget pinCodeField(VerifyOtpController controller,BuildContext context) { + return PinCodeTextField( + keyboardType: TextInputType.number, + length: 4, + enablePinAutofill: true, + enableActiveFill: true, + cursorColor: Colors.black, + textStyle: Styles.pinCodeText, + pinTheme: PinTheme( + shape: PinCodeFieldShape.box, + selectedFillColor: AppColor.lightWhite, + inactiveFillColor: AppColor.lightWhite, + activeColor: AppColor.lightWhite, + borderRadius: BorderRadius.circular(10), + fieldHeight: 50, + fieldWidth: 50, + selectedColor: AppColor.lightWhite, + activeFillColor: AppColor.lightWhite, + inactiveColor: AppColor.lightWhite, + ), + animationType: AnimationType.fade, + animationDuration: const Duration(milliseconds: 300), + errorAnimationController: controller.errorController, + controller: controller.otpTextController, + // Pass it here + onChanged: (text) { + controller.enteredOtp(text); + }, + appContext: context, + ).paddingOnly(top: 8.0.h, bottom: 16.0.h, right: 92.w); +} diff --git a/lib/views/verifyOTP/widgets/resend_otp_text.dart b/lib/views/verifyOTP/widgets/resend_otp_text.dart new file mode 100644 index 0000000000000000000000000000000000000000..82e07e59ec57c0c821097c62221ac7739f8d99ff --- /dev/null +++ b/lib/views/verifyOTP/widgets/resend_otp_text.dart @@ -0,0 +1,40 @@ +import 'dart:ui'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../appLocalization/language_key.dart'; +import '../../../customWidget/app_text.dart'; +import '../../../res/app_color_text_size.dart'; +import '../../../utils/res/styles.dart'; +import '../controller/verify_otp_controller.dart'; + +Widget resendOTPText(VerifyOtpController controller){ + return controller.counter.value == 0 + ? InkWell( + onTap: controller.onClickResendOTP, + child: AppText( + text: resendOTP.tr, + fontSize: TextSize.textSmallSize, + underLine: true, + fontWeight: FontWeight.w400, + textColor: AppColor.redLight, + maxLine: 3, + textAlign: TextAlign.start, + underlineColor: AppColor.redLight, + ), + ) + : RichText( + text: TextSpan( + children: <TextSpan>[ + TextSpan( + text: resendOTP.tr, + style: Styles.resendTextUnderline), + TextSpan( + text: "${resendOTPIn.tr}${controller.counter} ${seconds.tr}", + style: Styles.resendText), + ], + ), + ); +} \ No newline at end of file diff --git a/lib/views/verifyOTP/widgets/screen_header.dart b/lib/views/verifyOTP/widgets/screen_header.dart new file mode 100644 index 0000000000000000000000000000000000000000..38b3d2b269eacd34335ae6e226e4f4d4614922b4 --- /dev/null +++ b/lib/views/verifyOTP/widgets/screen_header.dart @@ -0,0 +1,53 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import '../../../appLocalization/language_key.dart'; +import '../../../constants/image_constants.dart'; +import '../../../customWidget/app_text.dart'; +import '../../../res/app_color_text_size.dart'; + +Widget screenHeader() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + InkWell( onTap: () => Get.back(), + child: Row( + children: [ + Image.asset( + ImageConstants.backButton, + width: 32, + height: 32, + ), + AppText( + text: back.tr, + fontSize: TextSize.textSmallSize, + fontWeight: FontWeight.w500, + textColor: AppColor.black, + ).paddingOnly(left: 12.0.h), + ], + ).paddingOnly(bottom: 24.0), + ), + AppText( + text: otpTitle.tr, + fontSize: TextSize.textXXLargeSize, + fontWeight: FontWeight.w500, + textColor: AppColor.lightBlack, + ).paddingOnly(bottom: 8.0.h), + AppText( + text: otpSubTitle.tr, + fontSize: TextSize.textSmallSize, + fontWeight: FontWeight.w400, + textColor: AppColor.lightGrey, + maxLine: 3, + textAlign: TextAlign.start, + ), + AppText( + text: enterOTP.tr, + fontSize: TextSize.textSmallSize, + fontWeight: FontWeight.w500, + textColor: AppColor.lightGrey, + ).paddingOnly(top: 24.0.h), + ], + ); +}