diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index b196665..1038617 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -42,5 +42,9 @@ "whatsapp": "واتس اب", "reject": "يرفض", "approve": "يوافق", - "cancel": "إلغاء" + "cancel": "إلغاء", + "otp": "OTP", + "verification": "تَحَقّق", + "resend": "إعادة إرسال", + "codeExpire": "انتهت صلاحية رمز التحقق" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index c570230..27757e5 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -42,5 +42,9 @@ "whatsapp": "Whatsapp", "reject": "Reject", "approve": "Approve", - "cancel": "Cancel" + "cancel": "Cancel", + "otp": "OTP", + "verification": "Verification", + "resend": "Resend", + "codeExpire": "The verification code has been expired" } \ No newline at end of file diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 92e4416..48c23d2 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ @@ -13,6 +13,7 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 9D12EA470E69A39F3F4EEEAC /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBDA1EC0585A028F26394B8F /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -31,6 +32,7 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 27FAD59055A271CDB6345D20 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -42,6 +44,9 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + CBDA1EC0585A028F26394B8F /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E8F2C56CA7A126F5FC598365 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + FF2E7CCDDEE1BDF1A3E7D477 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -49,12 +54,21 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9D12EA470E69A39F3F4EEEAC /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 5070F4CF6F638C91B59F4B67 /* Frameworks */ = { + isa = PBXGroup; + children = ( + CBDA1EC0585A028F26394B8F /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -72,6 +86,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, + CACFC9B4D329C2F774D03EE9 /* Pods */, + 5070F4CF6F638C91B59F4B67 /* Frameworks */, ); sourceTree = ""; }; @@ -98,6 +114,16 @@ path = Runner; sourceTree = ""; }; + CACFC9B4D329C2F774D03EE9 /* Pods */ = { + isa = PBXGroup; + children = ( + FF2E7CCDDEE1BDF1A3E7D477 /* Pods-Runner.debug.xcconfig */, + 27FAD59055A271CDB6345D20 /* Pods-Runner.release.xcconfig */, + E8F2C56CA7A126F5FC598365 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -105,12 +131,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + CDED494F0D32669A035C1EA5 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 2CEBFA1962BF46DCB0A31085 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -169,6 +197,23 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 2CEBFA1962BF46DCB0A31085 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -197,6 +242,28 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + CDED494F0D32669A035C1EA5 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -288,6 +355,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = KT58FV5WJU; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -416,6 +484,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = KT58FV5WJU; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -438,6 +507,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = KT58FV5WJU; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/lib/dialogs/otp_dialog.dart b/lib/dialogs/otp_dialog.dart index 28b1fc0..4355884 100644 --- a/lib/dialogs/otp_dialog.dart +++ b/lib/dialogs/otp_dialog.dart @@ -1,15 +1,15 @@ import 'dart:async'; -import 'package:easy_localization/src/public_ext.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:hmg_nurses/classes/colors.dart'; import 'package:hmg_nurses/extensions/int_extensions.dart'; import 'package:hmg_nurses/extensions/string_extensions.dart'; +import 'package:hmg_nurses/generated/locale_keys.g.dart'; import 'package:hmg_nurses/widgets/button/default_button.dart'; import 'package:hmg_nurses/widgets/otp_widget.dart'; - final ValueNotifier otpFieldClear = ValueNotifier(""); class OtpDialog { @@ -17,18 +17,13 @@ class OtpDialog { final int? mobileNo; final Function(String, TextEditingController _pinPutController) onSuccess; final Function onFailure; - final BuildContext context; final Function onResendCode; int remainingTime = 120; Future? timer; - static BuildContext? _context; - - static bool? _loading; - - OtpDialog(this.context, this.type, this.mobileNo, this.onSuccess, this.onFailure, {required this.onResendCode}); + OtpDialog({required this.type, required this.mobileNo, required this.onSuccess, required this.onFailure, required this.onResendCode}); GlobalKey? verifyAccountForm = GlobalKey(); @@ -53,7 +48,6 @@ class OtpDialog { // ProjectViewModel projectProvider; String displayTime = ''; - String? _code; dynamic setState; bool stopTimer = false; @@ -75,7 +69,7 @@ class OtpDialog { } return Container( - padding: EdgeInsets.all(21), + padding: const EdgeInsets.all(21), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -92,38 +86,33 @@ class OtpDialog { width: 50, ), 12.height, - "LocaleKeys.otp.tr()".toText14(), - "LocaleKeys.verification.tr()".toText24(isBold: true), + LocaleKeys.otp.tr().toText14(), + LocaleKeys.verification.tr().toText24(isBold: true), 6.height, - ("LocaleKeys.pleaseEnterTheVerificationCodeSentTo.tr()" + ' xxxxxxxx' + mobileNo.toString().substring(mobileNo.toString().length - 3)).toText16(), + ('${LocaleKeys.pleaseEnterTheVerificationCodeSentTo.tr()} xxxxxxxx${mobileNo.toString().substring(mobileNo.toString().length - 3)}').toText16(), 18.height, ValueListenableBuilder( builder: (BuildContext context, String value, Widget? child) { - // This builder will only get called when the _counter - // is updated. return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Directionality( - textDirection: TextDirection.ltr, - child: Center( - child: OTPWidget( - autoFocus: true, - controller: _pinPutController, - defaultBorderColor: const Color(0xffD8D8D8), - maxLength: 4, - onTextChanged: (text) {}, - pinBoxColor: Colors.white, - onDone: (code) => _onOtpCallBack(code, null), - textBorderColor: const Color(0xffD8D8D8), - pinBoxWidth: 60, - pinBoxHeight: 60, - pinTextStyle: const TextStyle(fontSize: 24.0, color: MyColors.darkTextColor), - pinTextAnimatedSwitcherTransition: ProvidedPinBoxTextAnimation.scalingTransition, - pinTextAnimatedSwitcherDuration: const Duration(milliseconds: 300), - pinBoxRadius: 10, - keyboardType: TextInputType.number, - ), + Center( + child: OTPWidget( + autoFocus: true, + controller: _pinPutController, + defaultBorderColor: const Color(0xffD8D8D8), + maxLength: 4, + onTextChanged: (text) {}, + pinBoxColor: Colors.white, + onDone: (code) => _onOtpCallBack(code, null), + textBorderColor: const Color(0xffD8D8D8), + pinBoxWidth: 60, + pinBoxHeight: 60, + pinTextStyle: const TextStyle(fontSize: 24.0, color: MyColors.darkTextColor), + pinTextAnimatedSwitcherTransition: ProvidedPinBoxTextAnimation.scalingTransition, + pinTextAnimatedSwitcherDuration: const Duration(milliseconds: 300), + pinBoxRadius: 10, + keyboardType: TextInputType.number, ), ), 10.height, @@ -131,7 +120,7 @@ class OtpDialog { ? Row( children: [ Expanded( - child: "LocaleKeys.codeExpire.tr()".toText16( + child: LocaleKeys.codeExpire.tr().toText16( color: MyColors.redColor, ), ), @@ -146,7 +135,7 @@ class OtpDialog { ) : RichText( text: TextSpan( - text: "LocaleKeys.theVerificationCodeWillExpireIn.tr()" + '\n', + text: '${LocaleKeys.theVerificationCodeWillExpireIn.tr()}\n', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.darkTextColor, letterSpacing: -0.48), children: [ TextSpan( @@ -163,7 +152,7 @@ class OtpDialog { ), 18.height, DefaultButton( - stopTimer ? "LocaleKeys.resend.tr()" : "LocaleKeys.cancel.tr()", + stopTimer ? LocaleKeys.resend.tr() : LocaleKeys.cancel.tr(), () async { if (stopTimer) { hideSMSBox(context); @@ -177,8 +166,8 @@ class OtpDialog { colors: stopTimer ? null : [ - MyColors.pinkDarkColor, - MyColors.pinkDarkColor, + MyColors.redColor, + MyColors.redColor, ], ), ], @@ -211,16 +200,6 @@ class OtpDialog { ); } - // String validateCodeDigit(value) { - // if (value.isEmpty) { - // return ' '; - // } else if (value.length == 3) { - // print(value); - // } else { - // return null; - // } - // } - String getSecondsAsDigitalClock(int inputSeconds) { int secNum = int.parse(inputSeconds.toString()); // don't forget the second param int hours = (secNum / 3600).floor(); @@ -228,9 +207,9 @@ class OtpDialog { double seconds = secNum - hours * 3600 - minutes * 60; String minutesString = ""; String secondsString = ""; - minutesString = minutes < 10 ? "0" + minutes.toString() : minutes.toString(); - secondsString = seconds < 10 ? "0" + seconds.toStringAsFixed(0) : seconds.toStringAsFixed(0); - return minutesString + ":" + secondsString; + minutesString = minutes < 10 ? "0$minutes" : minutes.toString(); + secondsString = seconds < 10 ? "0${seconds.toStringAsFixed(0)}" : seconds.toStringAsFixed(0); + return "$minutesString:$secondsString"; } void startTimer(setState) { diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 8520064..73e4320 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -58,7 +58,11 @@ class CodegenLoader extends AssetLoader{ "whatsapp": "واتس اب", "reject": "يرفض", "approve": "يوافق", - "cancel": "إلغاء" + "cancel": "إلغاء", + "otp": "OTP", + "verification": "تَحَقّق", + "resend": "إعادة إرسال", + "codeExpire": "انتهت صلاحية رمز التحقق" }; static const Map en_US = { "mohemm": "Mohemm", @@ -104,7 +108,11 @@ static const Map en_US = { "whatsapp": "Whatsapp", "reject": "Reject", "approve": "Approve", - "cancel": "Cancel" + "cancel": "Cancel", + "otp": "OTP", + "verification": "Verification", + "resend": "Resend", + "codeExpire": "The verification code has been expired" }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; } diff --git a/lib/main.dart b/lib/main.dart index a563baa..3bff34a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,6 +12,9 @@ import 'package:sizer/sizer.dart'; import 'generated/codegen_loader.g.dart'; + +GlobalKey navigatorKey = GlobalKey(); + Logger logger = Logger( // filter: null, // Use the default LogFilter (-> only log in debug mode) printer: PrettyPrinter( @@ -71,6 +74,7 @@ class MyApp extends StatelessWidget { ) { List> delegates = context.localizationDelegates; return MaterialApp( + key: navigatorKey, theme: AppTheme.getTheme( EasyLocalization.of(context)?.locale.languageCode == "ar", ), diff --git a/lib/ui/login/login_method_page.dart b/lib/ui/login/login_method_page.dart index 34fa32a..0ac6632 100644 --- a/lib/ui/login/login_method_page.dart +++ b/lib/ui/login/login_method_page.dart @@ -5,6 +5,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_svg/svg.dart'; import 'package:hmg_nurses/classes/colors.dart'; import 'package:hmg_nurses/classes/utils.dart'; +import 'package:hmg_nurses/dialogs/otp_dialog.dart'; import 'package:hmg_nurses/extensions/int_extensions.dart'; import 'package:hmg_nurses/extensions/string_extensions.dart'; import 'package:hmg_nurses/generated/locale_keys.g.dart'; @@ -105,10 +106,26 @@ class LoginMethodsPageState extends State { } else { if (isNeedVerifyWithFaceIDAndBiometrics) { // performApiCall(_title, _icon, selectedFlag, _flag); + // TODO: CALL API AND THEN SHOW DIALOG + OtpDialog( + type: 1, + mobileNo: 0504278212, + onSuccess: (string, TextEditingController pinPutController) {}, + onFailure: () {}, + onResendCode: () {}, + ).displayDialog(context); } else { // performApiCall(_title, _icon, _flag, _flag); + // TODO: CALL API AND THEN SHOW DIALOG + OtpDialog( + type: 1, + mobileNo: 0504278212, + onSuccess: (string, TextEditingController pinPutController) {}, + onFailure: () {}, + onResendCode: () {}, + ).displayDialog(context); } } } diff --git a/lib/ui/login/login_vm.dart b/lib/ui/login/login_vm.dart new file mode 100644 index 0000000..1b5f238 --- /dev/null +++ b/lib/ui/login/login_vm.dart @@ -0,0 +1,7 @@ + +import 'package:flutter/cupertino.dart'; + +class LoginVM extends ChangeNotifier { + + +} \ No newline at end of file