diff --git a/android/.kotlin/sessions/kotlin-compiler-4046697654005308772.salive b/android/.kotlin/sessions/kotlin-compiler-4046697654005308772.salive new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/assets/navigation/backButton.png b/assets/navigation/backButton.png new file mode 100644 index 0000000000000000000000000000000000000000..2bebceb2505856a134af5fad315a9a1c532a0908 Binary files /dev/null and b/assets/navigation/backButton.png differ diff --git a/assets/successImages/verificationSuccess.png b/assets/successImages/verificationSuccess.png new file mode 100644 index 0000000000000000000000000000000000000000..83097d6b6d1c6920a0c40306c360cd8307b6fb08 Binary files /dev/null and b/assets/successImages/verificationSuccess.png differ diff --git a/lib/appLocalization/language_key.dart b/lib/appLocalization/language_key.dart index 76a296233337afffdb66ce6199b8c6d9f6cedf27..307a03de8dd4319c8c2271a0fcf21263277a06f2 100644 --- a/lib/appLocalization/language_key.dart +++ b/lib/appLocalization/language_key.dart @@ -1,3 +1,17 @@ const String message = "message"; -const String name = "name"; \ No newline at end of file +const String name = "name"; + +///Verify otp texts +const String otpTitle = "otpTitle"; +const String otpSubTitle = "otpSubTitle"; +const String enterOTP = "enterOTP"; +const String resendOTPIn = "resendOTPIn"; +const String resendOTP = "resendOTP"; +const String verify = "verify"; +const String back = "back"; +const String verifySuccessTitle = "verifySuccessTitle"; +const String verifySuccessSubTitle = "verifySuccessSubTitle"; +const String seconds = "seconds"; +const String incorrectOTPError = "incorrectOTPError"; +const String apiError = "apiError"; \ No newline at end of file diff --git a/lib/appLocalization/languages.dart b/lib/appLocalization/languages.dart index 4da92007863555fcc304dc1e064185a3fa12dff3..0856a691b491957e3536b6072c6a2e67d1ae3114 100644 --- a/lib/appLocalization/languages.dart +++ b/lib/appLocalization/languages.dart @@ -12,12 +12,40 @@ class Languages extends Translations { /// English language constants Map<String, String> englishConstants = { message: "What is the project name?", - name: "Exide CRR" + name: "Exide CRR", + + ///Verify otp screen + otpTitle:"Verify OTP", + otpSubTitle:"Please verify the OTP which have been sent your registered mobile number.", + enterOTP:"Enter OTP", + resendOTPIn: " in ", + resendOTP: "Resend OTP", + seconds: "seconds.", + verify: "Verify", + back: "Back", + verifySuccessTitle:"Verification Successful", + verifySuccessSubTitle:"You have verified your OTP successfully.", + incorrectOTPError:"Incorrect OTP.Please try again!", + apiError:"Something went wrong.Please try again!" }; /// Hindi language constants Map<String, String> hindiConstants = { message: "प्रोजेक्ट का नाम क्या है?", - name: "एक्साइड सीआरआर" + name: "एक्साइड सीआरआर", + + ///Verify otp screen + otpTitle:"ओटीपी सत्यापित करें", + otpSubTitle:"कृपया उस ओटीपी को सत्यापित करें जो आपके पंजीकृत मोबाइल नंबर पर भेजा गया है।", + enterOTP:"ओटीपी दर्ज करें", + resendOTPIn:" ", + resendOTP: "ओटीपी दोबारा भेजें", + seconds:"सेकंड में ", + verify: "सत्यापित करें", + back: "पीछे", + verifySuccessTitle:"सत्यापन सफल", + verifySuccessSubTitle:"आपने अपना ओटीपी सफलतापूर्वक सत्यापित कर लिया है।", + incorrectOTPError:"ग़लत ओटीपी.कृपया पुनः प्रयास करें!", + apiError:"कुछ गड़बड़ हुई है। कृपया दोबारा प्रयास करें!" }; } \ No newline at end of file diff --git a/lib/constants/app_config_constants.dart b/lib/constants/app_config_constants.dart index fba1c45a7b53c7b1d4701f30e0445e7789b0c6c2..eeb8f09008c33058b11f3541a7db70a31bdaa12e 100644 --- a/lib/constants/app_config_constants.dart +++ b/lib/constants/app_config_constants.dart @@ -16,9 +16,9 @@ class AppConfigCons { static const devServer = "https://kong-proxy-dev.34.144.253.77.nip.io/b2b"; static const testServer = "https://34.36.169.7.nip.io"; - static const appDevName = "Radha-Exports-Admin-dev"; - static const appUATName = "Radha-Exports-Admin-UAT"; - static const appProdName = "Radha-Exports-Admin"; + static const appDevName = "Exide-dev"; + static const appUATName = "Exide-UAT"; + static const appProdName = "Exide"; static const adminProd = "https://1upnow-api.hdfcergo.com/"; static const adminUat = "https://advisor-uat-api.test-uat.com/"; diff --git a/lib/constants/app_constants.dart b/lib/constants/app_constants.dart index c79b464243c12c1fd9b8793ec59d46f0e102ba3b..953a1bc1f02cff09cfb92d22c366e0df6c0e42c7 100644 --- a/lib/constants/app_constants.dart +++ b/lib/constants/app_constants.dart @@ -1,46 +1,10 @@ class AppConstants { - static const String login = "Login"; - static const String forgotPassword = "Forgot Password"; - static const String loginEmailInfo = "Enter your email address and"; - static const String loginPasswordInfo = "password to access your account"; + static String username = 'Exidehtptrans1'; + static String password = '_<P)>lnL0{'; - static const String sendEmail = "Send E-mail"; - static const String sendOtp = "Send OTP"; - static const String checkEmail = "Check your E-mail"; - static const String changePassword = "Change Password"; - static const String confirmOtp = "Confirm OTP"; - static const String otpMatched = "OTP matched successfully"; - static const String otpInfo = "We have sent a password recover instruction"; - static const String otpOtherInfo = "Didn't receive the OTP? Please wait for 5 min before resending the OTP"; - static const String otpSentInfo = "OTP sent successfully"; - static const String remainingTime = "Remaining time"; - static const String userName = "User_name"; - static const String userId = "user_id"; - static const String firstName = "First_name"; - static const String lastName = "Last_name"; - static const String avatarUrl = "avatar_url"; - static const String emailId = "Email_ID"; - static const String sessionToken = "Session_token"; - static const String joinSession = 'Join Session'; - static const String userRoles = "Role"; - static const String home = 'home'; - static const String na = "NA"; - static const String search = 'Search'; - - static const String nameError = "Please enter name"; - static const String emailIdError = "Please enter valid email id"; - static const String errorOccurred = "An error occurred. Please retry"; - static const String invalidEmailError = - "The email address you provided is not associated with any account"; - static const String passwordNotMatchError = "The new password and confirm password do not match"; - static const String passwordError = "Password is not valid"; - static const String mandatoryField = "*Mandatory Field"; - static const String internetError = "No Internet Connection"; - static const String noDataFoundError = "No data available"; - static const String noUserFoundError = "No user found"; +} - static const String uploadImageFailedError = "Image upload failed. Please retry"; - static const String communicationError = "Error occurred while Communication with Server with StatusCode"; - static const String validationError = "Incorrect email or password, please retry."; - static const String personaError = "Unauthorised user for mobile app, please login on web app"; +///Controller tags +class Tag { + static String verifyOtpControllerTag="verify_otp_controller"; } diff --git a/lib/constants/image_constants.dart b/lib/constants/image_constants.dart index 3bfd3acd76c6d4b10c10a5963b69fe37357b8128..268608d834815703c726daf5778467032a20aafc 100644 --- a/lib/constants/image_constants.dart +++ b/lib/constants/image_constants.dart @@ -9,7 +9,6 @@ class ImageConstants { static const String profileIcon = "assets/profile_pic.png"; static const String icProfileIcon = "assets/ic_profile_place_holder.png"; static const String logoutIcon = "assets/ic_logout_icon.png"; - static const String backButton = "assets/ic_back_button.png"; static const String bottomMapNav = "assets/bottomNavigation/ic_bottom_map.png"; static const String bottomVehicleNav = "assets/bottomNavigation/ic_bottom_vehicle.png"; @@ -43,4 +42,8 @@ class ImageConstants { static const String passwordHideEye = "assets/images/passwordHideEye.png"; static const String passwordUnhideEye = "assets/images/passwordUnhideEye.png"; + + ///Verify otp assets +static const String backButton="assets/navigation/backButton.png"; +static const String verificationSuccess="assets/successImages/verificationSuccess.png"; } \ No newline at end of file diff --git a/lib/controller/base_controller.dart b/lib/controller/base_controller.dart index 0a654da7aced59ffd6b6f3295f7f1f9d0155e2b1..24630fd1516639ef761d6a0403337d874991f9c7 100644 --- a/lib/controller/base_controller.dart +++ b/lib/controller/base_controller.dart @@ -1,7 +1,6 @@ /* Created by Nitesh Kumar on 05/28/24 */ import 'dart:async'; -import 'dart:developer'; import 'dart:io' show Platform; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:dio/dio.dart'; @@ -26,12 +25,18 @@ class BaseController extends GetxController with WidgetsBindingObserver { RxBool isGeneralConfigLoading = false.obs; Completer<void> generalConfigFetchCompleter = Completer<void>(); + ///verifyOtp + RxString generatedOtp="".obs; + //todo-Fetch the phone number from welcome screen + RxString userPhoneNumber="919945215727".obs; + + + String encryptedSseId = ""; String userName = ""; String fullName = ""; String userDesignation = ""; String userEmail = ""; - String userPhoneNumber = ""; String empMobileNo = ""; String empWorkLocation = ""; String assetUrl = ""; diff --git a/lib/customWidget/app_text.dart b/lib/customWidget/app_text.dart index 21db7353cb22203798b19bdef9ff0fcbdcca8028..8e35f0dbf623281760ea52018fddb7085d006050 100644 --- a/lib/customWidget/app_text.dart +++ b/lib/customWidget/app_text.dart @@ -1,10 +1,11 @@ +import 'package:exide_crr/res/app_color_text_size.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import '../constants/font_constants.dart'; class AppText extends StatelessWidget { String text; - Color textColor; + Color textColor,underlineColor; double fontSize; FontWeight fontWeight; FontStyle fontStyle; @@ -24,7 +25,7 @@ class AppText extends StatelessWidget { // required this.lineHeight, this.maxLine=1, this.fontStyle = FontStyle.normal, - this.underLine = false, + this.underLine = false,this.underlineColor=AppColor.blackColor, this.isCurrency = false}) : super(key: key); @@ -40,7 +41,7 @@ class AppText extends StatelessWidget { fontWeight: fontWeight, fontStyle: fontStyle, // height: lineHeight, - color: textColor, + color: textColor,decorationColor:underlineColor, decoration: underLine ? TextDecoration.underline : TextDecoration.none), softWrap: softWrap, diff --git a/lib/customWidget/dialogues/success_dialogue.dart b/lib/customWidget/dialogues/success_dialogue.dart new file mode 100644 index 0000000000000000000000000000000000000000..5fd057f4093aa7a60441918926545072a6196f68 --- /dev/null +++ b/lib/customWidget/dialogues/success_dialogue.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import '../app_text.dart'; +import '../../res/app_color_text_size.dart'; + +Future<dynamic> verificationSuccess( + {required BuildContext context, + required String assetName, + required String title, + required String subtitle}) { + return Get.dialog( + barrierColor: AppColor.black.withOpacity(0.5), + Center( + child: SingleChildScrollView( + child: PopScope(canPop: false, + child: AlertDialog( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(12.0))), + backgroundColor: AppColor.white, + contentPadding: EdgeInsets.zero, + content: Padding( + padding: EdgeInsets.all(24.0.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Image.asset( + assetName, + width: 64, + height: 64, + ), + AppText( + text: title, + fontSize: TextSize.textSubHeadingSize, + fontWeight: FontWeight.w500, + textColor: AppColor.slateGray, + ).paddingOnly(top: 16.0), + AppText( + text: subtitle, + fontSize: TextSize.textSmallSize, + fontWeight: FontWeight.w400, + textColor: AppColor.lightGrey, + maxLine: 2, + textAlign: TextAlign.center, + ).paddingOnly(top: 8.0), + ], + ), + ), + ), + ), + ), + )); +} diff --git a/lib/customWidget/otp_text_field/otp_text_field.dart b/lib/customWidget/otp_text_field/otp_text_field.dart index 7a13e370d8e336c3618310c88fbef3c079971911..12b457f0b5a0704003fc8ebc434437adb57e2005 100644 --- a/lib/customWidget/otp_text_field/otp_text_field.dart +++ b/lib/customWidget/otp_text_field/otp_text_field.dart @@ -57,7 +57,7 @@ class OTPTextField extends StatefulWidget { /// default FieldStyle.underline [FieldStyle] /// Callback function, called when a change is detected to the pin. - final ValueChanged<String>? onChanged; + final ValueChanged<String> onChanged; /// Callback function, called when pin is completed. final ValueChanged<String>? onCompleted; @@ -80,7 +80,7 @@ class OTPTextField extends StatefulWidget { this.outlineBorderRadius = 10, this.textFieldAlignment = MainAxisAlignment.spaceBetween, this.obscureText = false, - this.onChanged, + required this.onChanged, this.inputFormatter, this.contentPadding = const EdgeInsets.symmetric(vertical: 8), @@ -160,15 +160,10 @@ class _OTPTextFieldState extends State<OTPTextField> { InputBorder getBorder(Color color) { return !widget.hasError - ? GradientOutlineInputBorder(borderRadius: BorderRadius.circular(widget.outlineBorderRadius), - gradient: const LinearGradient( - colors: [ - Color(0xFFFF5050), - Color(0xFF1071FF), - ], - ), - width: 1.0, - ) + ? OutlineInputBorder( + borderSide: BorderSide(color: _otpFieldStyle.borderColor), + borderRadius: BorderRadius.circular(widget.outlineBorderRadius), + ) : OutlineInputBorder( borderSide: BorderSide(color: _otpFieldStyle.errorBorderColor), borderRadius: BorderRadius.circular(widget.outlineBorderRadius), diff --git a/lib/customWidget/otp_text_field/otp_text_field_style.dart b/lib/customWidget/otp_text_field/otp_text_field_style.dart index 093452f5c4b169c513c2e4b493b190a254e89010..7af03b5eb7291fede55b12e21e74d276e6e6b486 100644 --- a/lib/customWidget/otp_text_field/otp_text_field_style.dart +++ b/lib/customWidget/otp_text_field/otp_text_field_style.dart @@ -21,9 +21,9 @@ class OtpFieldStyle { OtpFieldStyle( {this.backgroundColor = Colors.transparent, - this.borderColor = Colors.black26, - this.focusBorderColor = Colors.blue, - this.disabledBorderColor = Colors.grey, - this.enabledBorderColor = Colors.black26, + this.borderColor = Colors.white, + this.focusBorderColor = Colors.white, + this.disabledBorderColor = Colors.white, + this.enabledBorderColor = Colors.white, this.errorBorderColor = Colors.red}); } diff --git a/lib/model/verifyOtp.dart b/lib/model/verifyOtp.dart new file mode 100644 index 0000000000000000000000000000000000000000..e1ca0c3dd21e5110ea0a14f6f431747462ace6f7 --- /dev/null +++ b/lib/model/verifyOtp.dart @@ -0,0 +1,29 @@ +// To parse this JSON data, do +// +// final getToken = getTokenFromJson(jsonString); + +import 'dart:convert'; + +GetToken getTokenFromJson(String str) => GetToken.fromJson(json.decode(str)); + +String getTokenToJson(GetToken data) => json.encode(data.toJson()); + +class GetToken { + String? token; + DateTime? expiryDate; + + GetToken({ + this.token, + this.expiryDate, + }); + + factory GetToken.fromJson(Map<String, dynamic> json) => GetToken( + token: json["token"], + expiryDate:json["expiryDate"]!=null? DateTime.parse(json["expiryDate"]):null, + ); + + Map<String, dynamic> toJson() => { + "token": token, + "expiryDate": expiryDate?.toIso8601String(), + }; +} diff --git a/lib/my_app.dart b/lib/my_app.dart index f638ca06c3361abb9e1e8cd87b87a91b649fa42f..77fbaec1ff3b7441b4e8769373af8a246b6d29c8 100644 --- a/lib/my_app.dart +++ b/lib/my_app.dart @@ -22,7 +22,7 @@ class MyApp extends StatelessWidget { minTextAdapt: true, useInheritedMediaQuery: true, designSize: const Size(360, 800), - builder: (context, widget) => GetMaterialApp.router( + builder: (context, widget) => GetMaterialApp( title: AppEnvironment.appName, key: const GlobalObjectKey(AppConfigCons.appName), defaultTransition: Transition.fade, diff --git a/lib/preferences/app_shared_preferences.dart b/lib/preferences/app_shared_preferences.dart index ba18b0d1de2189c13ebf6d9c0697a3459c8d2d55..e16a4b366b91808ef0a5a802a6f4a29105bbb01d 100644 --- a/lib/preferences/app_shared_preferences.dart +++ b/lib/preferences/app_shared_preferences.dart @@ -1,11 +1,12 @@ import 'dart:async'; import 'dart:convert'; import 'dart:developer'; -import 'package:exide_crr/ServerRequest/all_request.dart'; import 'package:exide_crr/utils/custom_toast.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:http/http.dart' as http; +import '../serverRequest/all_request.dart'; + class PreferenceHelper { static const String accessToken = 'access_token'; static const String refreshToken = 'refresh_token'; diff --git a/lib/res/app_color_text_size.dart b/lib/res/app_color_text_size.dart index 20f6dd92fefcedf36da10fcac6cbae69ef488bfc..5476924b4c7c3ef71979390d8d115eef09938c12 100644 --- a/lib/res/app_color_text_size.dart +++ b/lib/res/app_color_text_size.dart @@ -33,7 +33,8 @@ class AppColor { static const textFieldHintColor = Color(0xff9B9B9B); static const primarySecColor = Color(0xFF3A88F4); static Color redLight = const Color(0xffFF1717); - static const inActiveButtonColor = Color(0xff808080); + static const inActiveButtonColor = Color(0xffF9BBBF); + static const slateGray = Color(0xff454A4F); static const MaterialColor primaryColorSwatch = MaterialColor(primaryColorHexValue, <int, Color>{ diff --git a/lib/routes/routes.dart b/lib/routes/routes.dart index 9e2d697e90dac1fa3aab1c66234056f09fd802b6..217307c37410ec973f2ec66c66b51c0fc6a58f69 100644 --- a/lib/routes/routes.dart +++ b/lib/routes/routes.dart @@ -4,6 +4,9 @@ import 'package:exide_crr/routes/routes_name.dart'; import 'package:exide_crr/views/splash/splash_screen.dart'; import 'package:get/get.dart'; +import '../views/verifyOTP/view/verify_otp_screen.dart'; + + class Routes { static String tag = "APP Routing"; @@ -15,12 +18,12 @@ class Routes { transitionDuration: const Duration(milliseconds: 800), transition: Transition.cupertinoDialog, ), - // GetPage( - // name: RoutesName.loginScreen, - // page: () => const LoginScreen(), - // transitionDuration: const Duration(milliseconds: 800), - // transition: Transition.cupertinoDialog, - // ), + GetPage( + name: RoutesName.verifyOtp, + page: () => const VerifyOtp(), + transitionDuration: const Duration(milliseconds: 800), + transition: Transition.cupertinoDialog, + ), // GetPage( // name: RoutesName.homeScreen, // page: () => const HomeScreen(), diff --git a/lib/routes/routes_name.dart b/lib/routes/routes_name.dart index 4072a396a3550ce7644dc5dbbbd7e433ad2d9949..0ab593b9ea1108ce1695e2481ac4a80fa2915d91 100644 --- a/lib/routes/routes_name.dart +++ b/lib/routes/routes_name.dart @@ -4,5 +4,6 @@ class RoutesName { static const String splashScreen = "/"; static const String loginScreen = "/login"; static const String homeScreen = "/home"; + static const String verifyOtp = "/verifyOtp"; } \ No newline at end of file diff --git a/lib/serverRequest/all_request.dart b/lib/serverRequest/all_request.dart index 2dfffd8c1b669319f6d087ec79d718e8e2a9ca37..437072ac47091cf0c61e2905d76762e319690e5a 100644 --- a/lib/serverRequest/all_request.dart +++ b/lib/serverRequest/all_request.dart @@ -1,24 +1,34 @@ import 'dart:async'; import 'dart:convert'; import 'dart:developer'; -import 'dart:io'; - -import 'package:dio/dio.dart'; +import 'package:exide_crr/utils/miscellaneous.dart'; import 'package:exide_crr/constants/app_constants.dart'; +import 'package:exide_crr/controller/base_controller.dart'; import 'package:exide_crr/data/app_env.dart'; import 'package:exide_crr/preferences/app_shared_preferences.dart'; import 'package:exide_crr/serverRequest/app_exception.dart'; import 'package:exide_crr/utils/custom_toast.dart'; -import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.dart'; +import 'package:get/get_core/src/get_main.dart'; import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; +import '../appLocalization/language_key.dart'; +import '../model/verifyOtp.dart'; + final httpClient = http.Client(); class AllHttpRequest { static String? apiUrl = AppEnvironment.baseApiUrl; - Map<String, String> formDataHeader = {"Content-type": "application/x-www-form-urlencoded"}; + static String? baseUrlForSendOtp = "https://http.myvfirst.com/smpp"; + static String? smsData = + "The OTP to get your Free Exide Sunday Ro of Top Solar Solution Proposal is"; + + Map<String, String> formDataHeader = { + "Content-type": "application/x-www-form-urlencoded" + }; Map<String, String> jsonHeader = {"Content-type": "application/json"}; Future login({body, funcName}) async { @@ -30,7 +40,8 @@ class AllHttpRequest { log("Request : $body"); // make POST request Uri uri = Uri.parse(url); - var response = await http.post(uri, headers: headers, body: json.encode(body)); + var response = + await http.post(uri, headers: headers, body: json.encode(body)); log("Response : ${response.body}"); return json.decode(response.body); @@ -54,7 +65,8 @@ class AllHttpRequest { log("Request : $body"); // make POST request Uri uri = Uri.parse(url); - var response = await http.post(uri, headers: headers, body: json.encode(body)); + var response = + await http.post(uri, headers: headers, body: json.encode(body)); log("Response : ${response.body}"); return json.decode(response.body); @@ -96,26 +108,80 @@ class AllHttpRequest { } } - Future forgotPassword(paramBody) async { - // set up POST request arguments - String url = '${AllHttpRequest.apiUrl!}reset_password'; - Map<String, String>? headers = {"Content-type": "application/json"}; - Uri uri = Uri.parse(url); - // make POST request - var response = await http.post(uri, headers: headers, body: paramBody); + /// Send otp api calls + late GetToken generatedAuth; - if (response.statusCode == 200) { - // If the call to the server was successful, parse the JSON. + Future generateAuth() async { + try { + ///Generate authorization token for send otp + String url = '$baseUrlForSendOtp/api/sendsms/token?action=generate'; + + String basicAuth = + 'Basic ${base64.encode(utf8.encode('${AppConstants.username}:${AppConstants.password}'))}'; + Map<String, String>? headers = { + "Content-type": "application/json", + "Authorization": basicAuth + }; + Uri uri = Uri.parse(url); + // make POST request + var response = await http.post(uri, headers: headers); + if (response.statusCode == 200) { + /// If the call to the server was successful, parse the JSON. + generatedAuth = GetToken.fromJson(jsonDecode(response.body)); + + ///Use generatedAuth to send SMS + sendOtp(); + } else { + Fluttertoast.showToast(msg: apiError.tr); + log("Error generate auth--${response.statusCode}"); + throw Error(); + } + } catch (e) { + Fluttertoast.showToast(msg: apiError.tr); + log("Error generate auth--$e"); + throw Error(); + } + } - return true; - } else { - return false; + Future sendOtp() async { + try { + final baseController = Get.find<BaseController>(); + + ///Locally generated 4 digit otp + baseController.generatedOtp.value = Miscellaneous.generateOTP(); + + ///Static smsData along with generated otp + var smsContent='$smsData ${baseController.generatedOtp.value} -EXIDE'; + + ///Set up POST request arguments + String url = '$baseUrlForSendOtp/sendsms?to=${baseController.userPhoneNumber}&from=ExideB&text=$smsContent'; + Map<String, String>? headers = { + "Content-type": "application/json", + "Authorization": "Bearer ${generatedAuth.token}", + }; + Uri uri = Uri.parse(url); + var response = await http.post(uri, headers: headers); + + if (response.statusCode == 200) { + ///If success do nothing + } else { + Fluttertoast.showToast(msg: apiError.tr); + log("Error generate auth--${response.statusCode}"); + throw Error(); + } + } catch (e) { + Fluttertoast.showToast(msg: apiError.tr); + log("Error generate auth--$e"); + throw Error(); } } + /// + Future postSubmit({funName, body}) async { // String? accessToken = await PreferenceHelper.getToken(); - String? accessToken = await PreferenceHelper.getPreferenceData(PreferenceHelper.accessToken); + String? accessToken = + await PreferenceHelper.getPreferenceData(PreferenceHelper.accessToken); log("accessToken-==$accessToken"); @@ -129,7 +195,8 @@ class AllHttpRequest { // make POST request log("Url : $url"); log("Body : $body"); - var response = await http.post(Uri.parse(url), headers: headers, body: json.encode(body)); + var response = await http.post(Uri.parse(url), + headers: headers, body: json.encode(body)); log("Response $funName: ${response.body}}"); log("Status Code===${response.statusCode}}"); if (response.statusCode == 200) { @@ -140,7 +207,7 @@ class AllHttpRequest { // If the call to the server request parameter missing, parse the JSON. var jsonResponse = json.decode(response.body); return jsonResponse; - } else if(response.statusCode == 401){ + } else if (response.statusCode == 401) { var refreshResponse = await getNewToken(); return refreshResponse; } else { @@ -223,7 +290,6 @@ class AllHttpRequest { log("headers-==$headers"); - log("Url : $url"); Uri uri = Uri.parse(url); // make GET request @@ -235,7 +301,7 @@ class AllHttpRequest { // If the call to the server was successful, parse the JSON. var jsonResponse = json.decode(response.body); return jsonResponse; - } else if(response.statusCode == 500){ + } else if (response.statusCode == 500) { return null; } else { // navigatorKey.currentState!.pushAndRemoveUntil( @@ -257,7 +323,8 @@ class AllHttpRequest { Future getRequest({funName}) async { // String? accessToken = await PreferenceHelper.getToken(); - String? accessToken = await PreferenceHelper.getPreferenceData(PreferenceHelper.accessToken); + String? accessToken = + await PreferenceHelper.getPreferenceData(PreferenceHelper.accessToken); // log("accessToken-==$accessToken"); @@ -268,7 +335,6 @@ class AllHttpRequest { log("headers-==$headers"); - log("Url : $url"); Uri uri = Uri.parse(url); // make GET request @@ -287,10 +353,10 @@ class AllHttpRequest { // If the call to the server was successful, parse the JSON. var jsonResponse = json.decode(response.body); return jsonResponse; - } else if(response.statusCode == 401){ + } else if (response.statusCode == 401) { var refreshResponse = await getNewToken(); return refreshResponse; - } else if(response.statusCode == 500){ + } else if (response.statusCode == 500) { return null; } else { return {}; @@ -326,11 +392,13 @@ class AllHttpRequest { } } - Future uploadFiles(String apiEndpoint, String filePath, String screenName) async { + Future uploadFiles( + String apiEndpoint, String filePath, String screenName) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); final String? sessionToken = prefs.getString('Session_token'); log("URL : $apiEndpoint"); - var request = http.MultipartRequest('POST', Uri.parse(AllHttpRequest.apiUrl! + apiEndpoint)); + var request = http.MultipartRequest( + 'POST', Uri.parse(AllHttpRequest.apiUrl! + apiEndpoint)); request.headers.addAll({ 'session-token': sessionToken!, 'Content-Type': 'multipart/form-data', @@ -384,7 +452,8 @@ class AllHttpRequest { final SharedPreferences prefs = await SharedPreferences.getInstance(); final String? sessionToken = prefs.getString('Session_token'); - var request = http.MultipartRequest('POST', Uri.parse(AllHttpRequest.apiUrl! + funName)); + var request = http.MultipartRequest( + 'POST', Uri.parse(AllHttpRequest.apiUrl! + funName)); request.headers.addAll({ 'session-token': sessionToken!, 'Content-Type': 'multipart/form-data', @@ -404,38 +473,39 @@ class AllHttpRequest { } } - Future<dynamic> uploadResourceWithProgress( - {required url, - required String screenName, - required String resourcePath, - required Function(int bytesCount, int totalLength) onUploadProgress}) async { - dynamic responseJson; - try { - final SharedPreferences prefs = await SharedPreferences.getInstance(); - final String? userId = prefs.getString('user_id'); - final String? sessionToken = prefs.getString('Session_token'); - Map<String, MultipartFile> requestBody = {}; - MultipartFile multiPartFile = await MultipartFile.fromFile(resourcePath); - requestBody.putIfAbsent('resource', () => multiPartFile); - log("URL : ${apiUrl! + url}"); - log("Multipart Request : $requestBody"); - Dio dio = Dio(); - FormData formData = FormData.fromMap(requestBody); - var response = await dio.post(apiUrl! + url, - data: formData, - options: Options(headers: { - 'user-id': userId!, - 'session-token': sessionToken!, - 'Content-Type': 'multipart/form-data', - }), - onSendProgress: onUploadProgress); - - responseJson = returnDioResponse(response); - } on SocketException { - throw FetchDataException(AppConstants.internetError); - } - return responseJson; - } + // Future<dynamic> uploadResourceWithProgress( + // {required url, + // required String screenName, + // required String resourcePath, + // required Function(int bytesCount, int totalLength) + // onUploadProgress}) async { + // dynamic responseJson; + // try { + // final SharedPreferences prefs = await SharedPreferences.getInstance(); + // final String? userId = prefs.getString('user_id'); + // final String? sessionToken = prefs.getString('Session_token'); + // Map<String, MultipartFile> requestBody = {}; + // MultipartFile multiPartFile = await MultipartFile.fromFile(resourcePath); + // requestBody.putIfAbsent('resource', () => multiPartFile); + // log("URL : ${apiUrl! + url}"); + // log("Multipart Request : $requestBody"); + // Dio dio = Dio(); + // FormData formData = FormData.fromMap(requestBody); + // var response = await dio.post(apiUrl! + url, + // data: formData, + // options: Options(headers: { + // 'user-id': userId!, + // 'session-token': sessionToken!, + // 'Content-Type': 'multipart/form-data', + // }), + // onSendProgress: onUploadProgress); + // + // responseJson = returnDioResponse(response); + // } on SocketException { + // throw FetchDataException(AppConstants.internetError); + // } + // return responseJson; + // } Future postDataSubmit(funName, body, String screenName) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); @@ -478,31 +548,30 @@ class AllHttpRequest { // } } - dynamic returnDioResponse(Response<dynamic> response) { - log("Response ${response.statusCode} : ${response.data}"); - switch (response.statusCode) { - case 200: - return response.data; - case 201: - return response.data; - case 400: - throw BadRequestException(response.data['message']); - case 401: - { - // if (responseJson["message"] == "Session Expired") { - // setLocalStorageValues(); - // } - throw UnauthorisedException(response.data['message']); - } - case 403: - throw UnauthorisedException(response.data['message']); - case 500: - default: - throw FetchDataException( - response.data['message'] ?? '${AppConstants.communicationError} : ${response.statusCode}'); - } - } - + // dynamic returnDioResponse(Response<dynamic> response) { + // log("Response ${response.statusCode} : ${response.data}"); + // switch (response.statusCode) { + // case 200: + // return response.data; + // case 201: + // return response.data; + // case 400: + // throw BadRequestException(response.data['message']); + // case 401: + // { + // // if (responseJson["message"] == "Session Expired") { + // // setLocalStorageValues(); + // // } + // throw UnauthorisedException(response.data['message']); + // } + // case 403: + // throw UnauthorisedException(response.data['message']); + // case 500: + // default: + // throw FetchDataException(response.data['message'] ?? + // '${AppConstants.communicationError} : ${response.statusCode}'); + // } + // } dynamic returnResponse(http.Response response) { logRequest(response); @@ -525,8 +594,8 @@ class AllHttpRequest { throw UnauthorisedException(responseJson['message']); case 500: default: - throw FetchDataException( - responseJson['message'] ?? '${AppConstants.communicationError} : ${response.statusCode}'); + throw FetchDataException(responseJson['message'] ?? + ' Error occurred while Communication with Server with StatusCode : ${response.statusCode}'); } } @@ -548,24 +617,24 @@ class AllHttpRequest { } Future getNewToken() async { - final String? refreshTok = await PreferenceHelper.getPreferenceData(PreferenceHelper.refreshToken); - final String? emailAddress = await PreferenceHelper.getPreferenceData(PreferenceHelper.email); + final String? refreshTok = + await PreferenceHelper.getPreferenceData(PreferenceHelper.refreshToken); + final String? emailAddress = + await PreferenceHelper.getPreferenceData(PreferenceHelper.email); log("GetNewToken====>>>>${AllHttpRequest.apiUrl}token/refresh"); log("RefreshToken====>>>>$refreshTok"); // set up POST request arguments - String url = "${AllHttpRequest.apiUrl??""}token/refresh"; + String url = "${AllHttpRequest.apiUrl ?? ""}token/refresh"; Map<String, String> headers = { - "Accept":"application/json", - "Content-Type":"application/json" + "Accept": "application/json", + "Content-Type": "application/json" }; - var body = { - "refresh_token": "$refreshTok", - "email": "$emailAddress" - }; + var body = {"refresh_token": "$refreshTok", "email": "$emailAddress"}; - var responseData = await http.post(Uri.parse(url), headers: headers, body: json.encode(body)); + var responseData = await http.post(Uri.parse(url), + headers: headers, body: json.encode(body)); log("${responseData.request!.headers}"); log("${responseData.request}"); log("${responseData.statusCode}"); @@ -576,17 +645,19 @@ class AllHttpRequest { // If the call to the server was successful, parse the JSON. var response = json.decode(responseData.body); - PreferenceHelper.setPreferenceData(PreferenceHelper.accessToken, response["access_token"]); - PreferenceHelper.setPreferenceData(PreferenceHelper.refreshToken, response["refresh_token"]); + PreferenceHelper.setPreferenceData( + PreferenceHelper.accessToken, response["access_token"]); + PreferenceHelper.setPreferenceData( + PreferenceHelper.refreshToken, response["refresh_token"]); // AllHttpRequest allHttpRequest = AllHttpRequest(); // allHttpRequest.getRequest(funName: funcName); return response; + } else if (responseData.statusCode == 401) { + CustomToast.showToastMessage( + 'Your session has been expired. Please login again.'); - } else if(responseData.statusCode == 401){ - CustomToast.showToastMessage('Your session has been expired. Please login again.'); - - /// clear the preference data + /// clear the preference data PreferenceHelper.clearUserPreferenceData(); // navigatorKey.currentState?.push(); diff --git a/lib/serverRequest/sendOtp/send_otp_request.dart b/lib/serverRequest/sendOtp/send_otp_request.dart new file mode 100644 index 0000000000000000000000000000000000000000..cc6fb5e908c066c39d0ec4912139a4207880deaf --- /dev/null +++ b/lib/serverRequest/sendOtp/send_otp_request.dart @@ -0,0 +1,13 @@ +// class LapsedPolicyRequest extends RemoteRequest { +// LapsedPolicyRequest( +// {required var filter}) { +// initialize(filter); +// } +// +// void initialize(filter) { +// filter = Uri.encodeComponent(filter); +// url = "${renewalsBaseUrl}lapsed-policies/$filter"; +// type = APIRequestType.get; +// } +// } + diff --git a/lib/utils/miscellaneous.dart b/lib/utils/miscellaneous.dart index bafa8040e8f2bb999b6affa80cda12e33a307315..76b24cc9bed751a296815328295544fc5e3ebae2 100644 --- a/lib/utils/miscellaneous.dart +++ b/lib/utils/miscellaneous.dart @@ -399,4 +399,10 @@ class Miscellaneous { } return double.tryParse(str) != null; } + + static String generateOTP() { + final math.Random random = math.Random(); + final int otp = 1000 + random.nextInt(9000); // Ensures a 4-digit number + return otp.toString(); + } } diff --git a/lib/utils/res/styles.dart b/lib/utils/res/styles.dart index d2990f4422ef9c69af4ecb0db343c43362b2e11e..3ffdc4ec07977a49d96897006a9d1e3046dd5235 100644 --- a/lib/utils/res/styles.dart +++ b/lib/utils/res/styles.dart @@ -200,4 +200,23 @@ class Styles { height: 1.0, color: AppColor.redLight, ); + +///Verify OTP + static TextStyle resendTextUnderline = GoogleFonts.getFont( + FontConstants.fontFamilyName, + fontSize: TextSize.textSmallSize, + fontWeight: FontWeight.w400, + color: AppColor.redLight.withOpacity(0.3),decoration: TextDecoration.underline,decorationColor: AppColor.redLight.withOpacity(0.3), + ); + + static TextStyle resendText = GoogleFonts.getFont( + FontConstants.fontFamilyName, + fontSize: TextSize.textSmallSize, + 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/splash/splash_screen.dart b/lib/views/splash/splash_screen.dart index 16ea397b71e68c92af17892867dafe6385cd2785..697a77fd175e98f16e6869db968daea3039e2ce4 100644 --- a/lib/views/splash/splash_screen.dart +++ b/lib/views/splash/splash_screen.dart @@ -6,6 +6,9 @@ import 'package:exide_crr/utils/res/styles.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import '../../appLocalization/language_key.dart'; +import '../../routes/routes_name.dart'; + class SplashScreen extends StatelessWidget { const SplashScreen({super.key}); @@ -20,8 +23,8 @@ class SplashScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ ListTile( - title: Text("message".tr, style: Styles.fontStyle,), - subtitle: Text("name".tr, style: Styles.subFontStyle,), + title: Text(message.tr, style: Styles.fontStyle,), + subtitle: Text(name.tr, style: Styles.subFontStyle,), ), const SizedBox(height: 50,), @@ -64,7 +67,7 @@ class SplashScreen extends StatelessWidget { GestureDetector( onTap: () { - Get.updateLocale(const Locale("hi", "IN")); + Get.updateLocale(const Locale("hi", "IN")); }, child: Container( width: 120, diff --git a/lib/views/verifyOTP/controller/verify_otp_controller.dart b/lib/views/verifyOTP/controller/verify_otp_controller.dart new file mode 100644 index 0000000000000000000000000000000000000000..4e5803796bc472c199e33db184a2ab27b04afc63 --- /dev/null +++ b/lib/views/verifyOTP/controller/verify_otp_controller.dart @@ -0,0 +1,90 @@ +import 'dart:async'; +import 'package:flutter/cupertino.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:get/get.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 '../../../customWidget/dialogues/success_dialogue.dart'; + +class VerifyOtpController extends GetxController { + final baseController = Get.find<BaseController>(); + RxInt counter = 90.obs; + Timer? timer; + StreamController<ErrorAnimationType> errorController = + StreamController<ErrorAnimationType>(); + TextEditingController otpTextController = TextEditingController(); + RxBool verifyLoader = false.obs; + + @override + void onInit() { + startTimer(); + AllHttpRequest().generateAuth(); + super.onInit(); + } + + @override + void onClose() { + timer?.cancel(); + super.onClose(); + } + + onClickVerifyHandler(BuildContext context) { + verifyLoader(true); + Future.delayed( + const Duration(seconds: 2), + () => { + if (baseController.generatedOtp.value == + otpTextController.value.text) + { + verificationSuccess( + context: context, + assetName: ImageConstants.verificationSuccess, + title: verifySuccessTitle.tr, + subtitle: verifySuccessSubTitle.tr) + } + else + { + resetLoading(), + Fluttertoast.showToast(msg: incorrectOTPError.tr) + }, + }); + + update(); + } + + onClickResendOTP() { + resetTimer(); + startTimer(); + resetLoading(); + + ///During resend otp auth is fetched from state variable and is not regenerated + AllHttpRequest().sendOtp(); + update(); + } + + startTimer() { + ///Decrease the counter value up to 0 + timer = Timer.periodic(const Duration(seconds: 1), (timer) { + if (counter > 0) { + counter--; + } else { + timer.cancel(); + } + update(); + }); + } + + resetTimer() { + ///Set counter to 90s + counter = 90.obs; + } + + resetLoading() { + ///Reset Loading and clear otp in pintextfield + otpTextController.clear(); + verifyLoader(false); + } +} diff --git a/lib/views/verifyOTP/view/verify_otp_screen.dart b/lib/views/verifyOTP/view/verify_otp_screen.dart new file mode 100644 index 0000000000000000000000000000000000000000..7a0104f406f0101f9b2fc7b6de3a4b6b026c24a0 --- /dev/null +++ b/lib/views/verifyOTP/view/verify_otp_screen.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import '../../../constants/app_constants.dart'; +import '../../../customWidget/otp_text_field/otp_text_field.dart'; +import '../../../res/app_color_text_size.dart'; +import '../controller/verify_otp_controller.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}); + + @override + State<VerifyOtp> createState() => _VerifyOtpState(); +} + +class _VerifyOtpState extends State<VerifyOtp> { + OtpFieldController otpFieldController = OtpFieldController(); + + @override + Widget build(BuildContext context) { + return GetBuilder( + tag: Tag.verifyOtpControllerTag, + init: VerifyOtpController(), + builder: (controller) => Scaffold( + backgroundColor: AppColor.white, + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + screenHeader(), + ///PinCode field + pinCodeField(controller,context), + ///Resend text + resendOTPText(controller) + ], + ).paddingOnly(right: 16.0.h, left: 16.0.h, top: 104.h), + 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..01c249c173323e06997ca866195d7b1e214016d1 --- /dev/null +++ b/lib/views/verifyOTP/widgets/pincode_text_field.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:pin_code_fields/pin_code_fields.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, + appContext: context, + ).paddingOnly(top: 8.0.h, bottom: 16, 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), + ], + ); +} diff --git a/pubspec.lock b/pubspec.lock index acdb0ea291e3ed09f8b199c29ff1cb6377ba6c04..c336c79fa42635989a5445aa8ec559dd1d3b1a24 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" + sha256: "37a42d06068e2fe3deddb2da079a8c4d105f241225ba27b7122b37e9865fd8f7" url: "https://pub.dev" source: hosted - version: "1.3.25" + version: "1.3.35" adaptive_number: dependency: transitive description: @@ -93,26 +93,26 @@ packages: dependency: "direct main" description: name: cloud_firestore - sha256: "31cfa4d65d6e9ea837234fffe121304034c30c9214c06207b4a35867e3757900" + sha256: a0f161b92610e078b4962d7e6ebeb66dc9cce0ada3514aeee442f68165d78185 url: "https://pub.dev" source: hosted - version: "4.15.8" + version: "4.17.5" cloud_firestore_platform_interface: dependency: transitive description: name: cloud_firestore_platform_interface - sha256: a0097a26569b015faf8142e159e855241609ea9a1738b5fd1c40bfe8411b41a0 + sha256: "6a55b319f8d33c307396b9104512e8130a61904528ab7bd8b5402678fca54b81" url: "https://pub.dev" source: hosted - version: "6.1.9" + version: "6.2.5" cloud_firestore_web: dependency: transitive description: name: cloud_firestore_web - sha256: ed680ece29a5750985119c09cdc276b460c3a2fa80e8c12f9b7241f6b4a7ca16 + sha256: "89dfa1304d3da48b3039abbb2865e3d30896ef858e569a16804a99f4362283a9" url: "https://pub.dev" source: hosted - version: "3.10.8" + version: "3.12.5" collection: dependency: transitive description: @@ -229,10 +229,10 @@ packages: dependency: transitive description: name: ffi - sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" file: dependency: transitive description: @@ -245,58 +245,58 @@ packages: dependency: "direct main" description: name: firebase_analytics - sha256: b13cbf1ee78744ca5e6b762e9218db3bd3967a0edfed75f58339907892a2ccb9 + sha256: dbf1e7ab22cfb1f4a4adb103b46a26276b4edc593d4a78ef6fb942bafc92e035 url: "https://pub.dev" source: hosted - version: "10.8.9" + version: "10.10.7" firebase_analytics_platform_interface: dependency: transitive description: name: firebase_analytics_platform_interface - sha256: "416b33d62033db5ecd2df719fcb657ad04e9995fa0fc392ffdab4ca0e76cb679" + sha256: "3729b74f8cf1d974a27ba70332ecb55ff5ff560edc8164a6469f4a055b429c37" url: "https://pub.dev" source: hosted - version: "3.9.9" + version: "3.10.8" firebase_analytics_web: dependency: transitive description: name: firebase_analytics_web - sha256: "9dca9d8d468172444ef18cabb73fe99f7aae24733bfad67115bd36bffd2d65c1" + sha256: "019cd7eee74254d33fbd2e29229367ce33063516bf6b3258a341d89e3b0f1655" url: "https://pub.dev" source: hosted - version: "0.5.5+21" + version: "0.5.7+7" firebase_auth: dependency: "direct main" description: name: firebase_auth - sha256: "17b841e1b000c3441b8ffceca88f468e078d0443db9643e77541bdfb7a3fd16b" + sha256: cfc2d970829202eca09e2896f0a5aa7c87302817ecc0bdfa954f026046bf10ba url: "https://pub.dev" source: hosted - version: "4.17.8" + version: "4.20.0" firebase_auth_platform_interface: dependency: transitive description: name: firebase_auth_platform_interface - sha256: f294ceef40409a36c819a14280ca864fe487b44033e5276443377c66cb448310 + sha256: a0270e1db3b2098a14cb2a2342b3cd2e7e458e0c391b1f64f6f78b14296ec093 url: "https://pub.dev" source: hosted - version: "7.1.8" + version: "7.3.0" firebase_auth_web: dependency: transitive description: name: firebase_auth_web - sha256: "1f231da900fe7ff9f2974f8adcbdb3363c410c24725978afa5dc33e1e7e62e06" + sha256: "64e067e763c6378b7e774e872f0f59f6812885e43020e25cde08f42e9459837b" url: "https://pub.dev" source: hosted - version: "5.9.8" + version: "5.12.0" firebase_core: dependency: "direct main" description: name: firebase_core - sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" + sha256: "26de145bb9688a90962faec6f838247377b0b0d32cc0abecd9a4e43525fc856c" url: "https://pub.dev" source: hosted - version: "2.27.0" + version: "2.32.0" firebase_core_platform_interface: dependency: transitive description: @@ -309,74 +309,74 @@ packages: dependency: transitive description: name: firebase_core_web - sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 + sha256: "43d9e951ac52b87ae9cc38ecdcca1e8fa7b52a1dd26a96085ba41ce5108db8e9" url: "https://pub.dev" source: hosted - version: "2.11.5" + version: "2.17.0" firebase_crashlytics: dependency: "direct main" description: name: firebase_crashlytics - sha256: c4f1b723d417bc9c4774810e774ff91df8fb0032d33fb2888b2c887e865581b8 + sha256: "9897c01efaa950d2f6da8317d12452749a74dc45f33b46390a14cfe28067f271" url: "https://pub.dev" source: hosted - version: "3.4.18" + version: "3.5.7" firebase_crashlytics_platform_interface: dependency: transitive description: name: firebase_crashlytics_platform_interface - sha256: c5a11fca3df76a98e3fa68fde8b10a08aacb9a7639f619fbfd4dad6c67a08643 + sha256: "16a71e08fbf6e00382816e1b13397898c29a54fa0ad969c2c2a3b82a704877f0" url: "https://pub.dev" source: hosted - version: "3.6.25" + version: "3.6.35" firebase_messaging: dependency: "direct main" description: name: firebase_messaging - sha256: e41586e0fd04fe9a40424f8b0053d0832e6d04f49e020cdaf9919209a28497e9 + sha256: a1662cc95d9750a324ad9df349b873360af6f11414902021f130c68ec02267c4 url: "https://pub.dev" source: hosted - version: "14.7.19" + version: "14.9.4" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface - sha256: f7a9d74ff7fc588a924f6b2eaeaa148b0db521b13a9db55f6ad45864fa98c06e + sha256: "87c4a922cb6f811cfb7a889bdbb3622702443c52a0271636cbc90d813ceac147" url: "https://pub.dev" source: hosted - version: "4.5.27" + version: "4.5.37" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web - sha256: fc21e771166860c55b103701c5ac7cdb2eec28897b97c42e6e5703cbedf9e02e + sha256: "0d34dca01a7b103ed7f20138bffbb28eb0e61a677bf9e78a028a932e2c7322d5" url: "https://pub.dev" source: hosted - version: "3.6.8" + version: "3.8.7" firebase_remote_config: dependency: "direct main" description: name: firebase_remote_config - sha256: b085a72c007bd8f177a7ab98b8292d764659b07fb6b0561b84125239ee656efc + sha256: "653bd94b68e2c4e89eca10db90576101f1024151f39f2d4e7c64ae6a90a5f9c5" url: "https://pub.dev" source: hosted - version: "4.3.17" + version: "4.4.7" firebase_remote_config_platform_interface: dependency: transitive description: name: firebase_remote_config_platform_interface - sha256: c589e007156b2c9f903253764c108abb96c1b56dd17cf0b91afc4b72ccab7bb6 + sha256: "24a2c445b15de3af7e4582ebceb2aa9a1e3731d0202cb3e7a1e03012440fa07d" url: "https://pub.dev" source: hosted - version: "1.4.25" + version: "1.4.35" firebase_remote_config_web: dependency: transitive description: name: firebase_remote_config_web - sha256: "92443c70e2721ab9d4beb23eb1d9f971da7381332451daee04f619b0f9204569" + sha256: "525aa3000fd27cd023841c802010a06515e564aab2f147aa964b35f54abbf449" url: "https://pub.dev" source: hosted - version: "1.4.25" + version: "1.6.7" fixnum: dependency: transitive description: @@ -394,10 +394,10 @@ packages: dependency: transitive description: name: flutter_cache_manager - sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" + sha256: "395d6b7831f21f3b989ebedbb785545932adb9afe2622c1ffacf7f4b53a7e544" url: "https://pub.dev" source: hosted - version: "3.3.1" + version: "3.3.2" flutter_lints: dependency: "direct dev" description: @@ -500,10 +500,10 @@ packages: dependency: "direct main" description: name: get_it - sha256: e6017ce7fdeaf218dc51a100344d8cb70134b80e28b760f8bb23c242437bafd7 + sha256: d85128a5dae4ea777324730dc65edd9c9f43155c109d5cc0a69cab74139fbac1 url: "https://pub.dev" source: hosted - version: "7.6.7" + version: "7.7.0" get_storage: dependency: "direct main" description: @@ -524,10 +524,10 @@ packages: dependency: transitive description: name: google_identity_services_web - sha256: "0c56c2c5d60d6dfaf9725f5ad4699f04749fb196ee5a70487a46ef184837ccf6" + sha256: "9482364c9f8b7bd36902572ebc3a7c2b5c8ee57a9c93e6eb5099c1a9ec5265d8" url: "https://pub.dev" source: hosted - version: "0.3.0+2" + version: "0.3.1+1" google_sign_in: dependency: "direct main" description: @@ -540,10 +540,10 @@ packages: dependency: transitive description: name: google_sign_in_android - sha256: "7647893c65e6720973f0e579051c8f84b877b486614d9f70a404259c41a4632e" + sha256: "8f2606fffd912ff8c23e8d94da106764c116112ce65fb18c78123331ae628eb3" url: "https://pub.dev" source: hosted - version: "6.1.23" + version: "6.1.24" google_sign_in_ios: dependency: transitive description: @@ -564,10 +564,10 @@ packages: dependency: transitive description: name: google_sign_in_web - sha256: a278ea2d01013faf341cbb093da880d0f2a552bbd1cb6ee90b5bebac9ba69d77 + sha256: fc0f14ed45ea616a6cfb4d1c7534c2221b7092cc4f29a709f0c3053cc3e821bd url: "https://pub.dev" source: hosted - version: "0.12.3+2" + version: "0.12.4" gradient_borders: dependency: "direct main" description: @@ -580,10 +580,10 @@ packages: dependency: "direct main" description: name: http - sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" http_parser: dependency: transitive description: @@ -608,6 +608,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.7" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + url: "https://pub.dev" + source: hosted + version: "10.0.4" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" lints: dependency: transitive description: @@ -620,26 +644,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.12.0" nm: dependency: transitive description: @@ -684,10 +708,10 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" path_parsing: dependency: transitive description: @@ -708,10 +732,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d + sha256: "9c96da072b421e98183f9ea7464898428e764bc0ce5567f27ec8693442e72514" url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.2.5" path_provider_foundation: dependency: transitive description: @@ -800,6 +824,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.2" + pin_code_fields: + dependency: "direct main" + description: + name: pin_code_fields + sha256: "4c0db7fbc889e622e7c71ea54b9ee624bb70c7365b532abea0271b17ea75b729" + url: "https://pub.dev" + source: hosted + version: "8.0.1" platform: dependency: transitive description: @@ -860,10 +892,10 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" + sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" shared_preferences_foundation: dependency: transitive description: @@ -892,10 +924,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" + sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.3.0" shared_preferences_windows: dependency: transitive description: @@ -937,18 +969,18 @@ packages: dependency: transitive description: name: sqflite - sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6 + sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.3+1" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5" + sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4" url: "https://pub.dev" source: hosted - version: "2.5.3" + version: "2.5.4" stack_trace: dependency: transitive description: @@ -993,10 +1025,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.0" typed_data: dependency: transitive description: @@ -1017,10 +1049,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "17cd5e205ea615e2c6ea7a77323a11712dffa0720a8a90540db57a01347f9ad9" + sha256: ceb2625f0c24ade6ef6778d1de0b2e44f2db71fded235eb52295247feba8c5cf url: "https://pub.dev" source: hosted - version: "6.3.2" + version: "6.3.3" url_launcher_ios: dependency: transitive description: @@ -1057,10 +1089,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b + sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.1" url_launcher_windows: dependency: transitive description: @@ -1109,30 +1141,38 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + url: "https://pub.dev" + source: hosted + version: "14.2.1" web: dependency: transitive description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.5.1" win32: dependency: transitive description: name: win32 - sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" + sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4 url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.5.1" win32_registry: dependency: transitive description: name: win32_registry - sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a" + sha256: "10589e0d7f4e053f2c61023a31c9ce01146656a70b7b7f0828c0b46d7da2a9bb" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.3" xdg_directories: dependency: transitive description: @@ -1150,5 +1190,5 @@ packages: source: hosted version: "6.5.0" sdks: - dart: ">=3.2.4 <4.0.0" - flutter: ">=3.16.6" + dart: ">=3.4.0 <4.0.0" + flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index c2dca227621ebb159c763007a759adcd58ecc54c..b112ac1ee70dcd4cc03a6e061c46f1caeae0f28d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -76,9 +76,9 @@ dependencies: gradient_borders: ^1.0.0 cached_network_image: ^3.3.1 firebase_messaging: ^14.7.13 - geocoding: ^2.0.2 dart_jsonwebtoken: ^2.12.2 + pin_code_fields: ^8.0.1 dev_dependencies: @@ -103,6 +103,10 @@ flutter: # the material Icons class. uses-material-design: true + assets: + - assets/navigation/ + - assets/successImages/ + # To add assets to your application, add an assets section, like this: # assets: # - images/a_dot_burr.jpeg