Commit 3e056f50 by Nguyễn Thị Thúy

Merge branch 'func_smart_otp' into 'dev_phase2'

Func smart otp

See merge request !21
parents 9e9eaf65 2e941e68
...@@ -57,4 +57,5 @@ buck-out/ ...@@ -57,4 +57,5 @@ buck-out/
# CocoaPods # CocoaPods
/ios/Pods/ /ios/Pods/
/android/app/release/ /ios/Podfile.lock
/android/app/release
...@@ -132,8 +132,8 @@ android { ...@@ -132,8 +132,8 @@ android {
applicationId "com.dcv.invest" applicationId "com.dcv.invest"
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 15 versionCode 16
versionName "1.9" versionName "2.0"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
} }
splits { splits {
......
...@@ -2,24 +2,27 @@ ...@@ -2,24 +2,27 @@
package="com.dcv.invest"> package="com.dcv.invest">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" /> <uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<application <application
android:name=".MainApplication" android:name=".MainApplication"
android:label="@string/app_name" android:allowBackup="false"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true">
>
<!-- <meta-data <!-- <meta-data
android:name="com.google.firebase.messaging.default_notification_color" android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/bootsplash_background" /> --> android:resource="@color/bootsplash_background" /> -->
...@@ -27,24 +30,28 @@ ...@@ -27,24 +30,28 @@
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:exported="true" android:exported="true"
android:label="@string/app_name"
android:launchMode="singleTask" android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW"/> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/> <category android:name="android.intent.category.DEFAULT" />
<data android:scheme="appdcvinvest" android:host="screen" android:pathPrefix="/" <category android:name="android.intent.category.BROWSABLE" />
/>
<data
android:host="screen"
android:pathPrefix="/"
android:scheme="appdcvinvest" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name="com.zoontek.rnbootsplash.RNBootSplashActivity" android:name="com.zoontek.rnbootsplash.RNBootSplashActivity"
android:theme="@style/BootTheme" android:launchMode="singleTask"
android:launchMode="singleTask"> android:theme="@style/BootTheme">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
...@@ -52,8 +59,6 @@ ...@@ -52,8 +59,6 @@
</intent-filter> </intent-filter>
</activity> </activity>
......
...@@ -4,6 +4,8 @@ import android.app.Application; ...@@ -4,6 +4,8 @@ import android.app.Application;
import android.content.Context; import android.content.Context;
import com.facebook.react.PackageList; import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication; import com.facebook.react.ReactApplication;
import com.rnfingerprint.FingerprintAuthPackage;
import com.rnfingerprint.FingerprintAuthPackage;
import com.learnium.RNDeviceInfo.RNDeviceInfo; import com.learnium.RNDeviceInfo.RNDeviceInfo;
import com.reactnativecommunity.netinfo.NetInfoPackage; import com.reactnativecommunity.netinfo.NetInfoPackage;
import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactInstanceManager;
......
...@@ -4,7 +4,7 @@ buildscript { ...@@ -4,7 +4,7 @@ buildscript {
ext { ext {
buildToolsVersion = "29.0.2" buildToolsVersion = "29.0.2"
minSdkVersion = 21 minSdkVersion = 21
compileSdkVersion = 28 compileSdkVersion = 29
targetSdkVersion = 29 targetSdkVersion = 29
} }
repositories { repositories {
......
rootProject.name = 'Invest' rootProject.name = 'Invest'
include ':react-native-touch-id'
project(':react-native-touch-id').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-touch-id/android')
include ':react-native-device-info' include ':react-native-device-info'
project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android') project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android')
include ':@react-native-community_netinfo' include ':@react-native-community_netinfo'
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
2DCD954D1E0B4F2C00145EB5 /* InvestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* InvestTests.m */; }; 2DCD954D1E0B4F2C00145EB5 /* InvestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* InvestTests.m */; };
2FCC6749524E697FC9323F22 /* libPods-Invest-InvestTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ABCEBFE5646F1EF68E7C87AB /* libPods-Invest-InvestTests.a */; }; 2FCC6749524E697FC9323F22 /* libPods-Invest-InvestTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ABCEBFE5646F1EF68E7C87AB /* libPods-Invest-InvestTests.a */; };
48E6A9A75AE9C55476F21D2D /* libPods-Invest-tvOSTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4ECD31835B4784D2DC719E76 /* libPods-Invest-tvOSTests.a */; }; 48E6A9A75AE9C55476F21D2D /* libPods-Invest-tvOSTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4ECD31835B4784D2DC719E76 /* libPods-Invest-tvOSTests.a */; };
52B7A0A425F722CF00CEDA09 /* BuildFile in Resources */ = {isa = PBXBuildFile; }; 52B7A0A425F722CF00CEDA09 /* (null) in Resources */ = {isa = PBXBuildFile; };
52F3AE2D26257DEC00F77114 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 52F3AE2C26257DEB00F77114 /* GoogleService-Info.plist */; }; 52F3AE2D26257DEC00F77114 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 52F3AE2C26257DEB00F77114 /* GoogleService-Info.plist */; };
52FB2B09262400D400DD7983 /* BootSplash.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 52FB2B08262400D400DD7983 /* BootSplash.storyboard */; }; 52FB2B09262400D400DD7983 /* BootSplash.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 52FB2B08262400D400DD7983 /* BootSplash.storyboard */; };
52FB2B0A262400D400DD7983 /* BootSplash.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 52FB2B08262400D400DD7983 /* BootSplash.storyboard */; }; 52FB2B0A262400D400DD7983 /* BootSplash.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 52FB2B08262400D400DD7983 /* BootSplash.storyboard */; };
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
00E356F21AD99517003FC87E /* InvestTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InvestTests.m; sourceTree = "<group>"; }; 00E356F21AD99517003FC87E /* InvestTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InvestTests.m; sourceTree = "<group>"; };
12715EC58B6699B513B54F09 /* Pods-Invest.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Invest.debug.xcconfig"; path = "Target Support Files/Pods-Invest/Pods-Invest.debug.xcconfig"; sourceTree = "<group>"; }; 12715EC58B6699B513B54F09 /* Pods-Invest.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Invest.debug.xcconfig"; path = "Target Support Files/Pods-Invest/Pods-Invest.debug.xcconfig"; sourceTree = "<group>"; };
133EF4C3267736DE00366B03 /* InvestDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = InvestDebug.entitlements; path = Invest/InvestDebug.entitlements; sourceTree = "<group>"; };
13B07F961A680F5B00A75B9A /* Invest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Invest.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07F961A680F5B00A75B9A /* Invest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Invest.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Invest/AppDelegate.h; sourceTree = "<group>"; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Invest/AppDelegate.h; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Invest/AppDelegate.m; sourceTree = "<group>"; }; 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Invest/AppDelegate.m; sourceTree = "<group>"; };
...@@ -148,6 +149,7 @@ ...@@ -148,6 +149,7 @@
13B07FAE1A68108700A75B9A /* Invest */ = { 13B07FAE1A68108700A75B9A /* Invest */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
133EF4C3267736DE00366B03 /* InvestDebug.entitlements */,
52FB2B08262400D400DD7983 /* BootSplash.storyboard */, 52FB2B08262400D400DD7983 /* BootSplash.storyboard */,
9345F6C125FF213F006B5233 /* Fonts */, 9345F6C125FF213F006B5233 /* Fonts */,
52E1A15225F1255E00EA970D /* Invest.entitlements */, 52E1A15225F1255E00EA970D /* Invest.entitlements */,
...@@ -268,6 +270,7 @@ ...@@ -268,6 +270,7 @@
00E356EC1AD99517003FC87E /* Resources */, 00E356EC1AD99517003FC87E /* Resources */,
E44ED71C60298AC6A80FDE0F /* ShellScript */, E44ED71C60298AC6A80FDE0F /* ShellScript */,
AA0D418EA141E60BA49CB685 /* [CP] Copy Pods Resources */, AA0D418EA141E60BA49CB685 /* [CP] Copy Pods Resources */,
AF1F3EBE50A555B22ED09707 /* [CP] Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
...@@ -291,6 +294,7 @@ ...@@ -291,6 +294,7 @@
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
6CC873A1E6FA7C328D7B37A9 /* ShellScript */, 6CC873A1E6FA7C328D7B37A9 /* ShellScript */,
7407C6B05E2A16BC3AEF8BEA /* [CP] Copy Pods Resources */, 7407C6B05E2A16BC3AEF8BEA /* [CP] Copy Pods Resources */,
E734F83437ED5EC685DCCCCF /* [CP] Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
...@@ -404,7 +408,7 @@ ...@@ -404,7 +408,7 @@
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
52F3AE2D26257DEC00F77114 /* GoogleService-Info.plist in Resources */, 52F3AE2D26257DEC00F77114 /* GoogleService-Info.plist in Resources */,
52B7A0A425F722CF00CEDA09 /* BuildFile in Resources */, 52B7A0A425F722CF00CEDA09 /* (null) in Resources */,
52FB2B09262400D400DD7983 /* BootSplash.storyboard in Resources */, 52FB2B09262400D400DD7983 /* BootSplash.storyboard in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
...@@ -901,7 +905,7 @@ ...@@ -901,7 +905,7 @@
CODE_SIGN_ENTITLEMENTS = Invest/InvestDebug.entitlements; CODE_SIGN_ENTITLEMENTS = Invest/InvestDebug.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 10; CURRENT_PROJECT_VERSION = 8;
DEVELOPMENT_TEAM = MXZ24GRH48; DEVELOPMENT_TEAM = MXZ24GRH48;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
GCC_PREPROCESSOR_DEFINITIONS = ( GCC_PREPROCESSOR_DEFINITIONS = (
...@@ -935,7 +939,7 @@ ...@@ -935,7 +939,7 @@
CODE_SIGN_ENTITLEMENTS = Invest/Invest.entitlements; CODE_SIGN_ENTITLEMENTS = Invest/Invest.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 10; CURRENT_PROJECT_VERSION = 8;
DEVELOPMENT_TEAM = MXZ24GRH48; DEVELOPMENT_TEAM = MXZ24GRH48;
INFOPLIST_FILE = Invest/Info.plist; INFOPLIST_FILE = Invest/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
......
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
</Workspace>
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
<key>NSFaceIDUsageDescription</key> <key>NSFaceIDUsageDescription</key>
<string>Enabling Face ID allows you quick and secure access to your account.</string> <string>Enabling Face ID allows you quick and secure access to your account.</string>
<key>NSLocationWhenInUseUsageDescription</key> <key>NSLocationWhenInUseUsageDescription</key>
<string></string> <string/>
<key>NSPhotoLibraryUsageDescription</key> <key>NSPhotoLibraryUsageDescription</key>
<string>To upload images</string> <string>To upload images</string>
<key>UIAppFonts</key> <key>UIAppFonts</key>
...@@ -102,5 +102,9 @@ ...@@ -102,5 +102,9 @@
</array> </array>
<key>UIViewControllerBasedStatusBarAppearance</key> <key>UIViewControllerBasedStatusBarAppearance</key>
<false/> <false/>
<key>NSFaceIDUsageDescription</key>
<string>Enabling Face ID allows you quick and secure access to your account.</string>
<key>NSFaceIDUsageDescription</key>
<string>Enabling Face ID allows you quick and secure access to your account.</string>
</dict> </dict>
</plist> </plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)dcv.investcustomer.vn</string>
</array>
</dict>
</plist>
...@@ -91,6 +91,8 @@ target 'Invest' do ...@@ -91,6 +91,8 @@ target 'Invest' do
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info' pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
pod 'TouchID', :path => '../node_modules/react-native-touch-id'
target 'InvestTests' do target 'InvestTests' do
inherit! :complete inherit! :complete
# Pods for testing # Pods for testing
......
...@@ -2,6 +2,8 @@ PODS: ...@@ -2,6 +2,8 @@ PODS:
- boost-for-react-native (1.63.0) - boost-for-react-native (1.63.0)
- BVLinearGradient (2.5.6): - BVLinearGradient (2.5.6):
- React - React
- CocoaAsyncSocket (7.6.5)
- CocoaLibEvent (1.0.0)
- DoubleConversion (1.1.6) - DoubleConversion (1.1.6)
- FBLazyVector (0.62.2) - FBLazyVector (0.62.2)
- FBReactNativeSpec (0.62.2): - FBReactNativeSpec (0.62.2):
...@@ -47,6 +49,52 @@ PODS: ...@@ -47,6 +49,52 @@ PODS:
- GoogleUtilities/Reachability (~> 6.5) - GoogleUtilities/Reachability (~> 6.5)
- GoogleUtilities/UserDefaults (~> 6.5) - GoogleUtilities/UserDefaults (~> 6.5)
- Protobuf (>= 3.9.2, ~> 3.9) - Protobuf (>= 3.9.2, ~> 3.9)
- Flipper (0.33.1):
- Flipper-Folly (~> 2.1)
- Flipper-RSocket (~> 1.0)
- Flipper-DoubleConversion (1.1.7)
- Flipper-Folly (2.4.0):
- boost-for-react-native
- CocoaLibEvent (~> 1.0)
- Flipper-DoubleConversion
- Flipper-Glog
- OpenSSL-Universal (= 1.1.180)
- Flipper-Glog (0.3.6)
- Flipper-PeerTalk (0.0.4)
- Flipper-RSocket (1.2.0):
- Flipper-Folly (~> 2.4)
- FlipperKit (0.33.1):
- FlipperKit/Core (= 0.33.1)
- FlipperKit/Core (0.33.1):
- Flipper (~> 0.33.1)
- FlipperKit/CppBridge
- FlipperKit/FBCxxFollyDynamicConvert
- FlipperKit/FBDefines
- FlipperKit/FKPortForwarding
- FlipperKit/CppBridge (0.33.1):
- Flipper (~> 0.33.1)
- FlipperKit/FBCxxFollyDynamicConvert (0.33.1):
- Flipper-Folly (~> 2.1)
- FlipperKit/FBDefines (0.33.1)
- FlipperKit/FKPortForwarding (0.33.1):
- CocoaAsyncSocket (~> 7.6)
- Flipper-PeerTalk (~> 0.0.4)
- FlipperKit/FlipperKitHighlightOverlay (0.33.1)
- FlipperKit/FlipperKitLayoutPlugin (0.33.1):
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutTextSearchable
- YogaKit (~> 1.18)
- FlipperKit/FlipperKitLayoutTextSearchable (0.33.1)
- FlipperKit/FlipperKitNetworkPlugin (0.33.1):
- FlipperKit/Core
- FlipperKit/FlipperKitReactPlugin (0.33.1):
- FlipperKit/Core
- FlipperKit/FlipperKitUserDefaultsPlugin (0.33.1):
- FlipperKit/Core
- FlipperKit/SKIOSNetworkPlugin (0.33.1):
- FlipperKit/Core
- FlipperKit/FlipperKitNetworkPlugin
- Folly (2018.10.22.00): - Folly (2018.10.22.00):
- boost-for-react-native - boost-for-react-native
- DoubleConversion - DoubleConversion
...@@ -90,8 +138,9 @@ PODS: ...@@ -90,8 +138,9 @@ PODS:
- nanopb/encode (= 1.30906.0) - nanopb/encode (= 1.30906.0)
- nanopb/decode (1.30906.0) - nanopb/decode (1.30906.0)
- nanopb/encode (1.30906.0) - nanopb/encode (1.30906.0)
- OpenSSL-Universal (1.1.180)
- PromisesObjC (1.2.12) - PromisesObjC (1.2.12)
- Protobuf (3.15.8) - Protobuf (3.17.0)
- RCTRequired (0.62.2) - RCTRequired (0.62.2)
- RCTTypeSafety (0.62.2): - RCTTypeSafety (0.62.2):
- FBLazyVector (= 0.62.2) - FBLazyVector (= 0.62.2)
...@@ -323,7 +372,7 @@ PODS: ...@@ -323,7 +372,7 @@ PODS:
- React-cxxreact (= 0.62.2) - React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2) - React-jsi (= 0.62.2)
- ReactCommon/callinvoker (= 0.62.2) - ReactCommon/callinvoker (= 0.62.2)
- RNBootSplash (3.2.0): - RNBootSplash (3.2.3):
- React-Core - React-Core
- RNCAsyncStorage (1.12.1): - RNCAsyncStorage (1.12.1):
- React-Core - React-Core
...@@ -359,6 +408,8 @@ PODS: ...@@ -359,6 +408,8 @@ PODS:
- React-Core - React-Core
- React-RCTImage - React-RCTImage
- TOCropViewController - TOCropViewController
- RNKeychain (7.0.0):
- React-Core
- RNReanimated (1.13.2): - RNReanimated (1.13.2):
- React-Core - React-Core
- RNScreens (2.18.0): - RNScreens (2.18.0):
...@@ -372,7 +423,11 @@ PODS: ...@@ -372,7 +423,11 @@ PODS:
- libwebp (~> 1.0) - libwebp (~> 1.0)
- SDWebImage/Core (~> 5.7) - SDWebImage/Core (~> 5.7)
- TOCropViewController (2.6.0) - TOCropViewController (2.6.0)
- TouchID (4.4.1):
- React
- Yoga (1.14.0) - Yoga (1.14.0)
- YogaKit (1.18.1):
- Yoga (~> 1.14)
- YoutubePlayer-in-WKWebView (0.3.5) - YoutubePlayer-in-WKWebView (0.3.5)
DEPENDENCIES: DEPENDENCIES:
...@@ -380,6 +435,25 @@ DEPENDENCIES: ...@@ -380,6 +435,25 @@ DEPENDENCIES:
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec`) - FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec`)
- Flipper (~> 0.33.1)
- Flipper-DoubleConversion (= 1.1.7)
- Flipper-Folly (~> 2.1)
- Flipper-Glog (= 0.3.6)
- Flipper-PeerTalk (~> 0.0.4)
- Flipper-RSocket (~> 1.0)
- FlipperKit (~> 0.33.1)
- FlipperKit/Core (~> 0.33.1)
- FlipperKit/CppBridge (~> 0.33.1)
- FlipperKit/FBCxxFollyDynamicConvert (~> 0.33.1)
- FlipperKit/FBDefines (~> 0.33.1)
- FlipperKit/FKPortForwarding (~> 0.33.1)
- FlipperKit/FlipperKitHighlightOverlay (~> 0.33.1)
- FlipperKit/FlipperKitLayoutPlugin (~> 0.33.1)
- FlipperKit/FlipperKitLayoutTextSearchable (~> 0.33.1)
- FlipperKit/FlipperKitNetworkPlugin (~> 0.33.1)
- FlipperKit/FlipperKitReactPlugin (~> 0.33.1)
- FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.33.1)
- FlipperKit/SKIOSNetworkPlugin (~> 0.33.1)
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`) - Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
...@@ -420,14 +494,18 @@ DEPENDENCIES: ...@@ -420,14 +494,18 @@ DEPENDENCIES:
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNI18n (from `../node_modules/react-native-i18n`) - RNI18n (from `../node_modules/react-native-i18n`)
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`) - RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
- RNKeychain (from `../node_modules/react-native-keychain`)
- RNReanimated (from `../node_modules/react-native-reanimated`) - RNReanimated (from `../node_modules/react-native-reanimated`)
- RNScreens (from `../node_modules/react-native-screens`) - RNScreens (from `../node_modules/react-native-screens`)
- RNVectorIcons (from `../node_modules/react-native-vector-icons`) - RNVectorIcons (from `../node_modules/react-native-vector-icons`)
- TouchID (from `../node_modules/react-native-touch-id`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS: SPEC REPOS:
trunk: trunk:
- boost-for-react-native - boost-for-react-native
- CocoaAsyncSocket
- CocoaLibEvent
- Firebase - Firebase
- FirebaseAnalyticsInterop - FirebaseAnalyticsInterop
- FirebaseCore - FirebaseCore
...@@ -436,15 +514,24 @@ SPEC REPOS: ...@@ -436,15 +514,24 @@ SPEC REPOS:
- FirebaseInstallations - FirebaseInstallations
- FirebaseInstanceID - FirebaseInstanceID
- FirebaseMessaging - FirebaseMessaging
- Flipper
- Flipper-DoubleConversion
- Flipper-Folly
- Flipper-Glog
- Flipper-PeerTalk
- Flipper-RSocket
- FlipperKit
- GoogleDataTransport - GoogleDataTransport
- GoogleUtilities - GoogleUtilities
- libwebp - libwebp
- nanopb - nanopb
- OpenSSL-Universal
- PromisesObjC - PromisesObjC
- Protobuf - Protobuf
- SDWebImage - SDWebImage
- SDWebImageWebPCoder - SDWebImageWebPCoder
- TOCropViewController - TOCropViewController
- YogaKit
- YoutubePlayer-in-WKWebView - YoutubePlayer-in-WKWebView
EXTERNAL SOURCES: EXTERNAL SOURCES:
...@@ -530,18 +617,24 @@ EXTERNAL SOURCES: ...@@ -530,18 +617,24 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-i18n" :path: "../node_modules/react-native-i18n"
RNImageCropPicker: RNImageCropPicker:
:path: "../node_modules/react-native-image-crop-picker" :path: "../node_modules/react-native-image-crop-picker"
RNKeychain:
:path: "../node_modules/react-native-keychain"
RNReanimated: RNReanimated:
:path: "../node_modules/react-native-reanimated" :path: "../node_modules/react-native-reanimated"
RNScreens: RNScreens:
:path: "../node_modules/react-native-screens" :path: "../node_modules/react-native-screens"
RNVectorIcons: RNVectorIcons:
:path: "../node_modules/react-native-vector-icons" :path: "../node_modules/react-native-vector-icons"
TouchID:
:path: "../node_modules/react-native-touch-id"
Yoga: Yoga:
:path: "../node_modules/react-native/ReactCommon/yoga" :path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS: SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872 BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2 DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
FBLazyVector: 4aab18c93cd9546e4bfed752b4084585eca8b245 FBLazyVector: 4aab18c93cd9546e4bfed752b4084585eca8b245
FBReactNativeSpec: 5465d51ccfeecb7faa12f9ae0024f2044ce4044e FBReactNativeSpec: 5465d51ccfeecb7faa12f9ae0024f2044ce4044e
...@@ -553,14 +646,22 @@ SPEC CHECKSUMS: ...@@ -553,14 +646,22 @@ SPEC CHECKSUMS:
FirebaseInstallations: 6f5f680e65dc374397a483c32d1799ba822a395b FirebaseInstallations: 6f5f680e65dc374397a483c32d1799ba822a395b
FirebaseInstanceID: cef67c4967c7cecb56ea65d8acbb4834825c587b FirebaseInstanceID: cef67c4967c7cecb56ea65d8acbb4834825c587b
FirebaseMessaging: 29543feb343b09546ab3aa04d008ee8595b43c44 FirebaseMessaging: 29543feb343b09546ab3aa04d008ee8595b43c44
Flipper: 6c1f484f9a88d30ab3e272800d53688439e50f69
Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
Flipper-Folly: ac90e2debaad40c347b90058feb263a80a3ba657
Flipper-Glog: 1dfd6abf1e922806c52ceb8701a3599a79a200a6
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
Flipper-RSocket: a4adba0851ba12c1b011a320b2d99c93ce4e77f9
FlipperKit: 6dc9b8f4ef60d9e5ded7f0264db299c91f18832e
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51 Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
glog: 1f3da668190260b06b429bb211bfbee5cd790c28 glog: 1f3da668190260b06b429bb211bfbee5cd790c28
GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833 GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833
GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3 GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3
libwebp: e90b9c01d99205d03b6bb8f2c8c415e5a4ef66f0 libwebp: e90b9c01d99205d03b6bb8f2c8c415e5a4ef66f0
nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc
OpenSSL-Universal: 1aa4f6a6ee7256b83db99ec1ccdaa80d10f9af9b
PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97 PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97
Protobuf: adb85cd18a15bd1a777c158af9fd6e612a0e6d69 Protobuf: 7327d4444215b5f18e560a97f879ff5503c4581c
RCTRequired: cec6a34b3ac8a9915c37e7e4ad3aa74726ce4035 RCTRequired: cec6a34b3ac8a9915c37e7e4ad3aa74726ce4035
RCTTypeSafety: 93006131180074cffa227a1075802c89a49dd4ce RCTTypeSafety: 93006131180074cffa227a1075802c89a49dd4ce
RCTYouTube: 4509d59a7de050dd0c7c6cb1f427d37678d63b5c RCTYouTube: 4509d59a7de050dd0c7c6cb1f427d37678d63b5c
...@@ -584,7 +685,7 @@ SPEC CHECKSUMS: ...@@ -584,7 +685,7 @@ SPEC CHECKSUMS:
React-RCTText: fae545b10cfdb3d247c36c56f61a94cfd6dba41d React-RCTText: fae545b10cfdb3d247c36c56f61a94cfd6dba41d
React-RCTVibration: 4356114dbcba4ce66991096e51a66e61eda51256 React-RCTVibration: 4356114dbcba4ce66991096e51a66e61eda51256
ReactCommon: ed4e11d27609d571e7eee8b65548efc191116eb3 ReactCommon: ed4e11d27609d571e7eee8b65548efc191116eb3
RNBootSplash: 24175aa28fe203b10c48dc34e78d946fd33c77af RNBootSplash: 8ef5ffa03dadd35f66510b42960ce40f397c98bf
RNCAsyncStorage: b03032fdbdb725bea0bd9e5ec5a7272865ae7398 RNCAsyncStorage: b03032fdbdb725bea0bd9e5ec5a7272865ae7398
RNCCheckbox: d1749e6a92178ce5dbc31e63becd1f34f0c76bbd RNCCheckbox: d1749e6a92178ce5dbc31e63becd1f34f0c76bbd
RNCClipboard: 245417a78ab585e0d4d83926c28907e7b2bc24bd RNCClipboard: 245417a78ab585e0d4d83926c28907e7b2bc24bd
...@@ -596,15 +697,18 @@ SPEC CHECKSUMS: ...@@ -596,15 +697,18 @@ SPEC CHECKSUMS:
RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211 RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211
RNI18n: e2f7e76389fcc6e84f2c8733ea89b92502351fd8 RNI18n: e2f7e76389fcc6e84f2c8733ea89b92502351fd8
RNImageCropPicker: 35a3ceb837446fa11547704709bb22b5fac6d584 RNImageCropPicker: 35a3ceb837446fa11547704709bb22b5fac6d584
RNKeychain: f75b8c8b2f17d3b2aa1f25b4a0ac5b83d947ff8f
RNReanimated: e03f7425cb7a38dcf1b644d680d1bfc91c3337ad RNReanimated: e03f7425cb7a38dcf1b644d680d1bfc91c3337ad
RNScreens: f0d7a2a440a8ba9f4574ca1ddb3368f473891be4 RNScreens: f0d7a2a440a8ba9f4574ca1ddb3368f473891be4
RNVectorIcons: 31cebfcf94e8cf8686eb5303ae0357da64d7a5a4 RNVectorIcons: 31cebfcf94e8cf8686eb5303ae0357da64d7a5a4
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
SDWebImageWebPCoder: d0dac55073088d24b2ac1b191a71a8f8d0adac21 SDWebImageWebPCoder: d0dac55073088d24b2ac1b191a71a8f8d0adac21
TOCropViewController: 3105367e808b7d3d886a74ff59bf4804e7d3ab38 TOCropViewController: 3105367e808b7d3d886a74ff59bf4804e7d3ab38
TouchID: ba4c656d849cceabc2e4eef722dea5e55959ecf4
Yoga: 3ebccbdd559724312790e7742142d062476b698e Yoga: 3ebccbdd559724312790e7742142d062476b698e
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
YoutubePlayer-in-WKWebView: cfbf46da51d7370662a695a8f351e5fa1d3e1008 YoutubePlayer-in-WKWebView: cfbf46da51d7370662a695a8f351e5fa1d3e1008
PODFILE CHECKSUM: 621d595d82007c6dfc7414cd2f2ed0bb03a78c2b PODFILE CHECKSUM: d5f4bf13be9a761040ff8b01e612e6d56a04f1d5
COCOAPODS: 1.10.1 COCOAPODS: 1.10.1
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -24,13 +24,14 @@ ...@@ -24,13 +24,14 @@
"async": "^3.2.0", "async": "^3.2.0",
"axios": "^0.21.1", "axios": "^0.21.1",
"dateformat": "^4.5.1", "dateformat": "^4.5.1",
"jsencrypt": "^3.2.0",
"lodash": "^4.17.20", "lodash": "^4.17.20",
"moment": "^2.29.1", "moment": "^2.29.1",
"react": "16.11.0", "react": "16.11.0",
"react-hook-form": "^6.15.4", "react-hook-form": "^6.15.4",
"react-native": "0.62.2", "react-native": "0.62.2",
"react-native-autocomplete-input": "^5.0.0", "react-native-autocomplete-input": "^5.0.0",
"react-native-bootsplash": "^3.2.0", "react-native-bootsplash": "^3.2.3",
"react-native-confirmation-code-field": "^6.5.1", "react-native-confirmation-code-field": "^6.5.1",
"react-native-datepicker": "^1.7.2", "react-native-datepicker": "^1.7.2",
"react-native-device-info": "^8.1.2", "react-native-device-info": "^8.1.2",
...@@ -40,6 +41,7 @@ ...@@ -40,6 +41,7 @@
"react-native-i18n": "^2.0.15", "react-native-i18n": "^2.0.15",
"react-native-image-crop-picker": "^0.36.2", "react-native-image-crop-picker": "^0.36.2",
"react-native-indicators": "^0.17.0", "react-native-indicators": "^0.17.0",
"react-native-keychain": "^7.0.0",
"react-native-linear-gradient": "^2.5.6", "react-native-linear-gradient": "^2.5.6",
"react-native-modal": "^11.7.0", "react-native-modal": "^11.7.0",
"react-native-modal-dropdown": "^1.0.0", "react-native-modal-dropdown": "^1.0.0",
...@@ -48,9 +50,11 @@ ...@@ -48,9 +50,11 @@
"react-native-reanimated": "^1.13.2", "react-native-reanimated": "^1.13.2",
"react-native-safe-area-context": "^3.1.9", "react-native-safe-area-context": "^3.1.9",
"react-native-screens": "^2.17.1", "react-native-screens": "^2.17.1",
"react-native-segmented-control-tab": "^3.4.1",
"react-native-simple-radio-button": "^2.7.4", "react-native-simple-radio-button": "^2.7.4",
"react-native-swiper": "^1.6.0", "react-native-swiper": "^1.6.0",
"react-native-tab-view": "^2.15.2", "react-native-tab-view": "^2.15.2",
"react-native-touch-id": "^4.4.1",
"react-native-vector-icons": "^8.0.0", "react-native-vector-icons": "^8.0.0",
"react-native-webview": "^11.2.5", "react-native-webview": "^11.2.5",
"react-native-youtube": "^2.0.1", "react-native-youtube": "^2.0.1",
......
...@@ -15,9 +15,26 @@ import AsyncStorage from '@react-native-community/async-storage'; ...@@ -15,9 +15,26 @@ import AsyncStorage from '@react-native-community/async-storage';
import {DETAILNEW, TABNAVIGATOR, AUTHEN} from '../routers/ScreenNames'; import {DETAILNEW, TABNAVIGATOR, AUTHEN} from '../routers/ScreenNames';
import R from '../assets/R'; import R from '../assets/R';
import {isTablet} from 'react-native-device-info'; import {isTablet} from 'react-native-device-info';
import {RSA_KEY, MY_RSA_KEY} from './constants';
import JSEncrypt from 'jsencrypt';
import KEY from '../assets/AsynStorage';
export const encryptRSAString = (val) => {
var encrypt = new JSEncrypt();
encrypt.setPublicKey(RSA_KEY.publicKey);
var encrypted = encrypt.encrypt(val);
return encrypted;
};
export const decryptRSAString = (val) => {
var decrypt = new JSEncrypt();
decrypt.setPrivateKey(MY_RSA_KEY.privateKey);
var uncrypted = decrypt.decrypt(val);
return uncrypted;
};
export const logout = (navigation) => { export const logout = (navigation) => {
AsyncStorage.clear(); AsyncStorage.multiRemove([KEY.ACCOUNT, KEY.FIREBASE, KEY.TOKEN])
navigation.reset({ navigation.reset({
index: 1, index: 1,
routes: [{name: AUTHEN}], routes: [{name: AUTHEN}],
......
...@@ -7,3 +7,84 @@ export const RadioBuySaleEN = [ ...@@ -7,3 +7,84 @@ export const RadioBuySaleEN = [
{label: 'Buy', value: 'BUY_IN'}, {label: 'Buy', value: 'BUY_IN'},
{label: 'Sell', value: 'SELL_OUT'}, {label: 'Sell', value: 'SELL_OUT'},
]; ];
export const OTP_TYPE = {
CUSTOMER_REQUEST_DEPOSIT: 'CUSTOMER_REQUEST_DEPOSIT',
REQUEST_WITHDRAW: 'REQUEST_WITHDRAW',
};
export const RSA_KEY = {
privateKey: `-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAriPaOfp9zSDIsde2OJPU3GKlV2EXqhEGxnmO6NHnz3SCJiTA
cTMIbckGKYsmsPoZyAmdP4irA+zMUA16vixXc1+R4whR1qVcXRQ2ZL/QOAtlgBUu
9rF3/+dexv3PW/2Di1uBdGn7khj3Mrs1PKWY9FEtb+NdgTF61RKWnhE6ktoKgukI
1XN5Xvt+5QqwOpPnDcByWyrw7J5N8Jc9bsP+GC7SzURE00nuw1uazrBvVpgcgyiA
yHj3SFJIF89MZYuulJxi9GYjv6ov3kcW5o14kNPExNEgPtlTVyoe1qub/xknSm12
GOTd5V8yvjgJ8ipjHxC7CvEEhG7AT5sJ/3pOywIDAQABAoIBAQCFQT4u+7XkkF/D
Z1Qzezx54KqxcMTRCPJsUny/QFDo+TjWw2zXsruSdy/V/nt/FgNAhcrk4UosWLoH
0CjK+dd5m/phBu7JGATT3TG6auWE3YOwPYWQlUFEe+KU14gj1p0guMcZNDikFaKk
GYmlfPrMiooAgrX8tMZP4keLcZem4xvclhOF49NOaQgbeydBGf33vFUN86qMG5V8
dUy80HkZ55TNXvY6GWpfKw7nOT7LjY1dNSGykNyMVoiLIQ7rMupzXVsu40Y6jajK
7S/pWZnDLPhMMepakFVzgy/D0ixwfrfRQN1PMFAS84r1n8CpA0rjm9xLyc7sLpEp
PEGbY9GxAoGBANUlhfK2e+kpoE40q3F1o2dwAglC+ombj8+VhJc7jnf8YLYcp4mG
+8RSqLueobR4UnFInkFRuN8VklkMISMHD+YuUhamzBkGnllA6THsgafqWOi1vO1A
9sm/UhHPnONm7tp5Ogxh3LZHSLStl8CaYazHkTt6IoHIkdwCWG/BJChXAoGBANEm
sh3ZgXxe0zBB7kuPcjk5VUU3oVjpkERYjBAsOD1vtmRgD74Ev+qMCDjIosalUo8B
jxpatmup+CHB3lwbvEmTy1y1Vjm85U++9KmDvhCjgVhh97uPYAqMapmTKTkoWKYm
OzCKzoltVHGAX9AXrfwRM+Nfz7Y1pJHvAACildStAoGBAJba5+LQpQJxI7Q2MuEq
kWw0KjzD2u5p227gM+eVj0/8n7ZEsY70qlxY5HNl4q0IO9FRxDAW1vGNIvdDTnCs
HuSbBB5kDy/nL0ucVW+wJFPj2OlbN0v0HrbLYhqZBkEsKQEXq6331W5tJVg7RJxc
p6TR2khuON4CRrmgL1dpK14hAoGBAJvb4EQKQEo0R+DgYPoB7bbjGL46FIyzkQS9
j7LFoSt3Qk5On6yU0YexzrayHUs3C+zx1nhnPSXCRdyyIkg1ivyxnIx7vcPNFn10
6dIhENRJZCw+5WPqFkIGHbJQThoADP/T4avs5LjYtmLWrY/e9ZKwJyC714gLNZZi
qnfOsSUJAoGAX9CAHHCz/X3GJ+HGYm5mu3ks2hCw9umJZkabpKxnWWhpgPrqysHF
wkSh32IW6zQqgN/H7Q2sndqb5NM88rHowxPyIL1sSnmpXPNmjUhjxP74stu0EcSM
KYdYznyvql2HvuWSfOHzOdbA2umFaL09lNSDBdGiaK4ji8oleyhlWPU=
-----END RSA PRIVATE KEY-----`,
publicKey: `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAriPaOfp9zSDIsde2OJPU
3GKlV2EXqhEGxnmO6NHnz3SCJiTAcTMIbckGKYsmsPoZyAmdP4irA+zMUA16vixX
c1+R4whR1qVcXRQ2ZL/QOAtlgBUu9rF3/+dexv3PW/2Di1uBdGn7khj3Mrs1PKWY
9FEtb+NdgTF61RKWnhE6ktoKgukI1XN5Xvt+5QqwOpPnDcByWyrw7J5N8Jc9bsP+
GC7SzURE00nuw1uazrBvVpgcgyiAyHj3SFJIF89MZYuulJxi9GYjv6ov3kcW5o14
kNPExNEgPtlTVyoe1qub/xknSm12GOTd5V8yvjgJ8ipjHxC7CvEEhG7AT5sJ/3pO
ywIDAQAB
-----END PUBLIC KEY-----`,
};
export const MY_RSA_KEY = {
privateKey: `-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQBof1CpRwpsn3Nk6a831N2wc9S7Vx0hKUeiXX8yOYjBptFIEuJl
ssff7B6rRLKj/7oYKAzpXtNrNC4qqkReRLOjFQ4/gvln2h6eFRleZS0jAyYh8ukN
+yMIyT8c0YJb4jjzAjwQ7T62t8SyIVHKiMRQ0bZJAeXGvrx1t8Jwj0H+M5tu/gdt
5yvj+lMqRxxyl56WCFER3sKo/eB5dj+in31cKSdU2VW+xjXQM1jcL3k7KTfnhpq2
rIkbeYUs3qAoZ4Xn+6w1ZSf8Y2GONpnrOnQt1uF/A5ZNV3IHgwa/Y4jxF+KHcvlv
AyyOiDTVZAqn2/+JC+3z219OZCNet+VTmozzAgMBAAECggEAZmAE2DK/Jbf5R24h
uWMUZaC1U2x/H1Pf2FQdH0l6j64s7p2Bq/zBEMG1Mjm1gjIxUSU7sQ6zth2C9U2m
eWx5SVaBhPt9+J6azGkDV5Vr6RdWrn/aj1Xw9tSivksLmZVCEeGokzS68iuLyrAV
/4SKQFuUaGYxhMqsu+9x0PCoyK7nE35tLyYN9RIr9mqMBQJKeWA+4iNBZ+FPXNb4
/5p9mG7BupknXno0+3g1pf3n5hhTxCvZmIGNxkvgZP6XI8XAa6GBFSnix4q7DAEy
ODT0fq6cej7zLGjy1pjjj0681mJp+8IAOC1LrtsGCFaHqRSuYj36zsRkmz4bh5Fk
9MmNEQKBgQC73TIfG/wJKad9C+gb4Dj/FSL/5VTucGOH6/jDcVStwIrqcwq0XdwG
WplsRktPUoRt9I8xVggf3ToFL4bDutrpr5RnVAJSTX+BbnY/BWvsbcwWiDcVRL/u
78fFtjr+0Wq8vbVbvoJkT+xQ6vhNIxDklYWm+i5AaVWtap8oSwqqBwKBgQCOZa86
phESuAbF6ZZDOyESPVGDBR7nKeEjF5ingb9PqfyInesLBiUHt3LUW9LuffRHDnCG
11wI8ho/xNM/UvuzLERKcZ83cVqqsWzvR0nNfLXgpJHe/2epPmRhi91NF3lH9RbX
Q3Cmk4puUh3pK/lRlGnH4J25iNKP/bGtEW96tQKBgGKic1NkFQMWjKqZ2sbwBdzf
0x154grClW9i1JyA303OvuDzf9ZNRV1MqirwCVBfacp1Uc08d02LkI/ycRZI//Eb
z5YkxIdDy0NApPLXvN9IkpPt9sXC7+banA/Ras4pU5o/HH5L2xgh4lhl1fJiC9eI
LcEKr8f/xg0j4uZ75+B3AoGAbzGoK7wSCPP7FgDZfZZmtL99LzqIbyqcy7JZWjRP
F/49XNE0AV/C+sudt4YcqG9imToFVMZG8BVduf4Ql5pNQhSHHzqqgbjafAAgeJjK
YNPJkqnv3prCb75w1FtLbC+wXShdtarMBMehiZRGFxZnkfS6xYH4qDDXe+k3HVZI
HyECgYEAlRxGofeb/68W1XEK1rDtFtMHaQCTaKLb+vcLy/1FaHUtnFao4N393Ho8
KCJPQ/nJpO/Jz0ukvH5PKif0E3b6yaFrt94eqI7ezfxnjzJpEbh2Q8DeIRvpNWgC
lKn8Fz6kDKkofF7T5y98BqgnRSihewuhvgNM4yS6e9cU1cXesjs=
-----END RSA PRIVATE KEY-----`,
publicKey: `-----BEGIN PUBLIC KEY-----
MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBof1CpRwpsn3Nk6a831N2w
c9S7Vx0hKUeiXX8yOYjBptFIEuJlssff7B6rRLKj/7oYKAzpXtNrNC4qqkReRLOj
FQ4/gvln2h6eFRleZS0jAyYh8ukN+yMIyT8c0YJb4jjzAjwQ7T62t8SyIVHKiMRQ
0bZJAeXGvrx1t8Jwj0H+M5tu/gdt5yvj+lMqRxxyl56WCFER3sKo/eB5dj+in31c
KSdU2VW+xjXQM1jcL3k7KTfnhpq2rIkbeYUs3qAoZ4Xn+6w1ZSf8Y2GONpnrOnQt
1uF/A5ZNV3IHgwa/Y4jxF+KHcvlvAyyOiDTVZAqn2/+JC+3z219OZCNet+VTmozz
AgMBAAE=
-----END PUBLIC KEY-----`,
};
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQBof1CpRwpsn3Nk6a831N2wc9S7Vx0hKUeiXX8yOYjBptFIEuJl
ssff7B6rRLKj/7oYKAzpXtNrNC4qqkReRLOjFQ4/gvln2h6eFRleZS0jAyYh8ukN
+yMIyT8c0YJb4jjzAjwQ7T62t8SyIVHKiMRQ0bZJAeXGvrx1t8Jwj0H+M5tu/gdt
5yvj+lMqRxxyl56WCFER3sKo/eB5dj+in31cKSdU2VW+xjXQM1jcL3k7KTfnhpq2
rIkbeYUs3qAoZ4Xn+6w1ZSf8Y2GONpnrOnQt1uF/A5ZNV3IHgwa/Y4jxF+KHcvlv
AyyOiDTVZAqn2/+JC+3z219OZCNet+VTmozzAgMBAAECggEAZmAE2DK/Jbf5R24h
uWMUZaC1U2x/H1Pf2FQdH0l6j64s7p2Bq/zBEMG1Mjm1gjIxUSU7sQ6zth2C9U2m
eWx5SVaBhPt9+J6azGkDV5Vr6RdWrn/aj1Xw9tSivksLmZVCEeGokzS68iuLyrAV
/4SKQFuUaGYxhMqsu+9x0PCoyK7nE35tLyYN9RIr9mqMBQJKeWA+4iNBZ+FPXNb4
/5p9mG7BupknXno0+3g1pf3n5hhTxCvZmIGNxkvgZP6XI8XAa6GBFSnix4q7DAEy
ODT0fq6cej7zLGjy1pjjj0681mJp+8IAOC1LrtsGCFaHqRSuYj36zsRkmz4bh5Fk
9MmNEQKBgQC73TIfG/wJKad9C+gb4Dj/FSL/5VTucGOH6/jDcVStwIrqcwq0XdwG
WplsRktPUoRt9I8xVggf3ToFL4bDutrpr5RnVAJSTX+BbnY/BWvsbcwWiDcVRL/u
78fFtjr+0Wq8vbVbvoJkT+xQ6vhNIxDklYWm+i5AaVWtap8oSwqqBwKBgQCOZa86
phESuAbF6ZZDOyESPVGDBR7nKeEjF5ingb9PqfyInesLBiUHt3LUW9LuffRHDnCG
11wI8ho/xNM/UvuzLERKcZ83cVqqsWzvR0nNfLXgpJHe/2epPmRhi91NF3lH9RbX
Q3Cmk4puUh3pK/lRlGnH4J25iNKP/bGtEW96tQKBgGKic1NkFQMWjKqZ2sbwBdzf
0x154grClW9i1JyA303OvuDzf9ZNRV1MqirwCVBfacp1Uc08d02LkI/ycRZI//Eb
z5YkxIdDy0NApPLXvN9IkpPt9sXC7+banA/Ras4pU5o/HH5L2xgh4lhl1fJiC9eI
LcEKr8f/xg0j4uZ75+B3AoGAbzGoK7wSCPP7FgDZfZZmtL99LzqIbyqcy7JZWjRP
F/49XNE0AV/C+sudt4YcqG9imToFVMZG8BVduf4Ql5pNQhSHHzqqgbjafAAgeJjK
YNPJkqnv3prCb75w1FtLbC+wXShdtarMBMehiZRGFxZnkfS6xYH4qDDXe+k3HVZI
HyECgYEAlRxGofeb/68W1XEK1rDtFtMHaQCTaKLb+vcLy/1FaHUtnFao4N393Ho8
KCJPQ/nJpO/Jz0ukvH5PKif0E3b6yaFrt94eqI7ezfxnjzJpEbh2Q8DeIRvpNWgC
lKn8Fz6kDKkofF7T5y98BqgnRSihewuhvgNM4yS6e9cU1cXesjs=
-----END RSA PRIVATE KEY-----
\ No newline at end of file
-----BEGIN PUBLIC KEY-----
MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBof1CpRwpsn3Nk6a831N2w
c9S7Vx0hKUeiXX8yOYjBptFIEuJlssff7B6rRLKj/7oYKAzpXtNrNC4qqkReRLOj
FQ4/gvln2h6eFRleZS0jAyYh8ukN+yMIyT8c0YJb4jjzAjwQ7T62t8SyIVHKiMRQ
0bZJAeXGvrx1t8Jwj0H+M5tu/gdt5yvj+lMqRxxyl56WCFER3sKo/eB5dj+in31c
KSdU2VW+xjXQM1jcL3k7KTfnhpq2rIkbeYUs3qAoZ4Xn+6w1ZSf8Y2GONpnrOnQt
1uF/A5ZNV3IHgwa/Y4jxF+KHcvlvAyyOiDTVZAqn2/+JC+3z219OZCNet+VTmozz
AgMBAAE=
-----END PUBLIC KEY-----
\ No newline at end of file
import React, {useEffect, useRef} from 'react'; import React, {useEffect, useRef} from 'react';
import {View} from 'react-native'; import {Alert, View} from 'react-native';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import StackNavigation from './routers/StackNavigation'; import StackNavigation from './routers/StackNavigation';
...@@ -10,12 +10,14 @@ import NoInternetComponent from './components/NoInternet'; ...@@ -10,12 +10,14 @@ import NoInternetComponent from './components/NoInternet';
import DropdownAlert from 'react-native-dropdownalert'; import DropdownAlert from 'react-native-dropdownalert';
import DeviceInfo from 'react-native-device-info'; import DeviceInfo from 'react-native-device-info';
import R from './assets/R'; import R from './assets/R';
import {WIDTHXD, HEIGHTXD} from './Config/Functions'; import {WIDTHXD, HEIGHTXD, decryptRSAString} from './Config/Functions';
import DropdownManager from './components/DropdownAlert/DropdownManager'; import DropdownManager from './components/DropdownAlert/DropdownManager';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import KEY from './assets/AsynStorage'; import KEY from './assets/AsynStorage';
import I18n, {setLocation} from './helper/i18/i18n'; import I18n, {setLocation} from './helper/i18/i18n';
import {changeLanguage} from './actions/language'; import {changeLanguage} from './actions/language';
import {RSA_KEY, MY_RSA_KEY} from './Config/constants';
import JSEncrypt from 'jsencrypt';
enableScreens(); enableScreens();
...@@ -25,6 +27,7 @@ const RootView = (props) => { ...@@ -25,6 +27,7 @@ const RootView = (props) => {
dropDownAlertRef.current, dropDownAlertRef.current,
dropDownAlertLongTimeRef.current, dropDownAlertLongTimeRef.current,
); );
setInitLanguage(); setInitLanguage();
}, []); }, []);
...@@ -35,6 +38,7 @@ const RootView = (props) => { ...@@ -35,6 +38,7 @@ const RootView = (props) => {
if (laguage) props.changeLanguage(laguage); if (laguage) props.changeLanguage(laguage);
setLocation(I18n, laguage); setLocation(I18n, laguage);
}; };
return ( return (
<> <>
<View style={{flex: 1}}> <View style={{flex: 1}}>
......
...@@ -90,7 +90,8 @@ const FeePro = (props) => { ...@@ -90,7 +90,8 @@ const FeePro = (props) => {
return ( return (
<View> <View>
<Text style={styles.txtTitle}> {title}</Text> {title ? <Text style={styles.txtTitle}> {title}</Text> : null}
<View style={styles.wrap}> <View style={styles.wrap}>
{listItem.map((e) => ( {listItem.map((e) => (
<View key={e.id + 'a'} style={styles.item}> <View key={e.id + 'a'} style={styles.item}>
......
...@@ -129,11 +129,14 @@ const PacketCQG = (props) => { ...@@ -129,11 +129,14 @@ const PacketCQG = (props) => {
}; };
const getData = async () => { const getData = async () => {
const res = await getListPacketCQG({}); const res = await getListPacketCQG({});
console.log(res);
if ((res.data.code = 200 && res.data.data)) { if ((res.data.code = 200 && res.data.data)) {
setFee(res.data.data.fee); if (res.data.data.fee) setFee(res.data.data.fee);
setFeeConnect(res.data.data.fee_connect); if (res.data.data.fee_connect) setFeeConnect(res.data.data.fee_connect);
setFeeNonPro(res.data.data.fee_pro); if (res.data.data.fee_pro) setFeeNonPro(res.data.data.fee_pro);
setFeePro(res.data.data.fee_non_pro);
if (res.data.data.fee_non_pro) setFeePro(res.data.data.fee_non_pro);
if (res.data.data.fee_operating)
setOperrating(res.data.data.fee_operating); setOperrating(res.data.data.fee_operating);
if (res.data.package_register.length > 0) { if (res.data.package_register.length > 0) {
...@@ -159,26 +162,31 @@ const PacketCQG = (props) => { ...@@ -159,26 +162,31 @@ const PacketCQG = (props) => {
<View style={styles.container}> <View style={styles.container}>
<AppText i18nKey={'Note_cqg'} /> <AppText i18nKey={'Note_cqg'} />
<ContainerTop fee={fee} /> <ContainerTop fee={fee} />
{feeOperating.data.length > 0 ? (
<WrapNomarl <WrapNomarl
onRemovePacket={onRemovePacket} onRemovePacket={onRemovePacket}
onChoosePacket={onChoosePacket} onChoosePacket={onChoosePacket}
data={feeOperating} data={feeOperating}
listRegister={listRegister} listRegister={listRegister}
/> />
) : null}
{feeConnect.data.length > 0 ? (
<WrapNomarl <WrapNomarl
onRemovePacket={onRemovePacket} onRemovePacket={onRemovePacket}
onChoosePacket={onChoosePacket} onChoosePacket={onChoosePacket}
data={feeConnect} data={feeConnect}
listRegister={listRegister} listRegister={listRegister}
/> />
) : null}
{feeNonPro.data.length > 0 ? (
<WrapNomarl <WrapNomarl
onRemovePacket={onRemovePacket} onRemovePacket={onRemovePacket}
onChoosePacket={onChoosePacket} onChoosePacket={onChoosePacket}
data={feeNonPro} data={feeNonPro}
listRegister={listRegister} listRegister={listRegister}
/> />
) : null}
<FeePro <FeePro
onRemovePacket={onRemovePacket} onRemovePacket={onRemovePacket}
......
...@@ -44,7 +44,8 @@ const ContainerTop = (props) => { ...@@ -44,7 +44,8 @@ const ContainerTop = (props) => {
return ( return (
<View> <View>
<Text style={styles.txtTitle}> {title}</Text> {title ? <Text style={styles.txtTitle}> {title}</Text> : null}
<View style={styles.wrap}> <View style={styles.wrap}>
{listItem.map((e) => ( {listItem.map((e) => (
<View key={e.id + 'a'} style={styles.item}> <View key={e.id + 'a'} style={styles.item}>
......
...@@ -10,6 +10,8 @@ import {showAlert, TYPE} from '../../../components/DropdownAlert'; ...@@ -10,6 +10,8 @@ import {showAlert, TYPE} from '../../../components/DropdownAlert';
import {useNavigation} from '@react-navigation/native'; import {useNavigation} from '@react-navigation/native';
import {saveUserToRedux} from '../../../actions/users'; import {saveUserToRedux} from '../../../actions/users';
import {getDetailUser} from '../../../apis/Functions/users'; import {getDetailUser} from '../../../apis/Functions/users';
import AppText from '../../../components/AppText';
import {showLoading, hideLoading} from '../../../actions/loadingAction';
const MethodPayView = (props) => { const MethodPayView = (props) => {
const [data, setData] = useState([]); const [data, setData] = useState([]);
...@@ -40,9 +42,11 @@ const MethodPayView = (props) => { ...@@ -40,9 +42,11 @@ const MethodPayView = (props) => {
}; };
const getData = async () => { const getData = async () => {
props.showLoading();
const res = await getListMethod({ const res = await getListMethod({
platform: Platform.OS, platform: Platform.OS,
}); });
props.hideLoading();
if (res.data.code == 200 && res.data.data) { if (res.data.code == 200 && res.data.data) {
setData(res.data.data); setData(res.data.data);
} else { } else {
...@@ -54,6 +58,17 @@ const MethodPayView = (props) => { ...@@ -54,6 +58,17 @@ const MethodPayView = (props) => {
<View style={{flex: 1}}> <View style={{flex: 1}}>
<HeaderBack title={'SelectPaymentMethod'} /> <HeaderBack title={'SelectPaymentMethod'} />
<View style={{flex: 1}}> <View style={{flex: 1}}>
{data.length == 0 ? (
<View
style={{justifyContent: 'center', alignItems: 'center', flex: 1}}>
<AppText
i18nKey={'NoData'}
style={{
fontSize: 18,
fontWeight: 'bold',
}}></AppText>
</View>
) : (
<FlatList <FlatList
keyExtractor={(item) => item.id} keyExtractor={(item) => item.id}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
...@@ -63,8 +78,11 @@ const MethodPayView = (props) => { ...@@ -63,8 +78,11 @@ const MethodPayView = (props) => {
justifyContent: 'space-between', justifyContent: 'space-between',
}} }}
data={data} data={data}
renderItem={({item}) => <Item userId={props.user.uid} item={item} />} renderItem={({item}) => (
<Item userId={props.user.uid} item={item} />
)}
/> />
)}
</View> </View>
</View> </View>
); );
...@@ -75,4 +93,8 @@ const mapStateToProps = (state) => { ...@@ -75,4 +93,8 @@ const mapStateToProps = (state) => {
user: state.userReducer, user: state.userReducer,
}; };
}; };
export default connect(mapStateToProps, {saveUserToRedux})(MethodPayView); export default connect(mapStateToProps, {
saveUserToRedux,
showLoading,
hideLoading,
})(MethodPayView);
...@@ -16,7 +16,7 @@ const Item = (props) => { ...@@ -16,7 +16,7 @@ const Item = (props) => {
const {item} = props; const {item} = props;
const navigate = useNavigation(); const navigate = useNavigation();
return ( return (
<View style={styles.container}> <View style={[styles.container, props.isEnd ? {marginBottom: 60} : {}]}>
<Block flex={1} row> <Block flex={1} row>
{/* <View style={[styles.wrapLeft, {backgroundColor: item.color}]} /> {/* <View style={[styles.wrapLeft, {backgroundColor: item.color}]} />
<View style={styles.wrapDate}> <View style={styles.wrapDate}>
...@@ -82,9 +82,8 @@ const styles = StyleSheet.create({ ...@@ -82,9 +82,8 @@ const styles = StyleSheet.create({
elevation: 5, elevation: 5,
marginHorizontal: 10, marginHorizontal: 10,
backgroundColor: R.colors.white, backgroundColor: R.colors.white,
marginTop: 10,
borderRadius: HEIGHTXD(30), borderRadius: HEIGHTXD(30),
marginBottom: 10, marginTop: 10,
}, },
wrapRight: { wrapRight: {
borderLeftColor: R.colors.borderGray, borderLeftColor: R.colors.borderGray,
......
...@@ -80,6 +80,7 @@ const Success = (props) => { ...@@ -80,6 +80,7 @@ const Success = (props) => {
) : ( ) : (
<FlatList <FlatList
keyExtractor={(item) => item.transection_id + 'a'} keyExtractor={(item) => item.transection_id + 'a'}
showsVerticalScrollIndicator={false}
refreshing={isRefresh} refreshing={isRefresh}
onRefresh={onRefresh} onRefresh={onRefresh}
onEndReachedThreshold={0.01} onEndReachedThreshold={0.01}
...@@ -87,7 +88,9 @@ const Success = (props) => { ...@@ -87,7 +88,9 @@ const Success = (props) => {
onLoadMore(); onLoadMore();
}} }}
data={data} data={data}
renderItem={({item}) => <Item item={item} />} renderItem={({item, index}) => (
<Item item={item} isEnd={index + 1 == data.length} />
)}
/> />
)} )}
</View> </View>
......
...@@ -87,6 +87,7 @@ const Watting = (props) => { ...@@ -87,6 +87,7 @@ const Watting = (props) => {
) : ( ) : (
<FlatList <FlatList
keyExtractor={(item) => item.transection_id + 'a'} keyExtractor={(item) => item.transection_id + 'a'}
showsVerticalScrollIndicator={false}
refreshing={isRefresh} refreshing={isRefresh}
onRefresh={onRefresh} onRefresh={onRefresh}
onEndReachedThreshold={0.01} onEndReachedThreshold={0.01}
...@@ -94,7 +95,9 @@ const Watting = (props) => { ...@@ -94,7 +95,9 @@ const Watting = (props) => {
onLoadMore(); onLoadMore();
}} }}
data={data} data={data}
renderItem={({item}) => <Item item={item} />} renderItem={({item, index}) => (
<Item item={item} isEnd={index + 1 == data.length} />
)}
/> />
)} )}
</View> </View>
......
...@@ -62,13 +62,13 @@ const styles = StyleSheet.create({ ...@@ -62,13 +62,13 @@ const styles = StyleSheet.create({
}, },
btnRight: { btnRight: {
width: WIDTHXD(400), width: WIDTHXD(400),
height: HEIGHTXD(100), height: HEIGHTXD(120),
backgroundColor: R.colors.main, backgroundColor: R.colors.main,
borderRadius: 10, borderRadius: 10,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
position: 'absolute', position: 'absolute',
bottom: 10, bottom: 20,
right: 30, right: 30,
shadowColor: '#AFA9A9', shadowColor: '#AFA9A9',
shadowOffset: { shadowOffset: {
...@@ -81,13 +81,13 @@ const styles = StyleSheet.create({ ...@@ -81,13 +81,13 @@ const styles = StyleSheet.create({
}, },
btnLeft: { btnLeft: {
width: WIDTHXD(400), width: WIDTHXD(400),
height: HEIGHTXD(100), height: HEIGHTXD(120),
backgroundColor: R.colors.main, backgroundColor: R.colors.main,
borderRadius: 10, borderRadius: 10,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
position: 'absolute', position: 'absolute',
bottom: 10, bottom: 20,
left: 30, left: 30,
shadowColor: '#AFA9A9', shadowColor: '#AFA9A9',
shadowOffset: { shadowOffset: {
......
import React, {useState} from 'react'; import React, {useState} from 'react';
import { import {
View, DeviceEventEmitter,
Text,
StyleSheet,
Dimensions, Dimensions,
TouchableOpacity,
Alert,
TouchableWithoutFeedback,
Keyboard, Keyboard,
KeyboardAvoidingView, KeyboardAvoidingView,
Platform, Platform,
ScrollView, ScrollView,
StyleSheet,
Text,
TouchableOpacity,
TouchableWithoutFeedback,
View,
} from 'react-native'; } from 'react-native';
import R from '../../../assets/R'; import R from '../../../assets/R';
import HeaderBack from '../../../components/Header/HeaderBack'; import HeaderBack from '../../../components/Header/HeaderBack';
import TextField from '../../../components/Input/TextField';
import TextMulti from '../../../components/Input/TextMulti'; import TextMulti from '../../../components/Input/TextMulti';
import TextDisable from '../../../components/Input/TextDisable';
import {useNavigation} from '@react-navigation/native'; import {useNavigation} from '@react-navigation/native';
import { import {
checkFormatArray,
getFontXD, getFontXD,
HEIGHTXD,
toPriceVnd, toPriceVnd,
checkFormatArray,
WIDTHXD, WIDTHXD,
HEIGHTXD,
} from '../../../Config/Functions'; } from '../../../Config/Functions';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import {showLoading, hideLoading} from '../../../actions/loadingAction'; import {hideLoading, showLoading} from '../../../actions/loadingAction';
import {walletDeposit} from '../../../apis/Functions/Deposit';
import TextMoney from '../../../components/Input/InputMoney'; import TextMoney from '../../../components/Input/InputMoney';
import I18n from '../../../helper/i18/i18n'; import I18n from '../../../helper/i18/i18n';
import {OTPWALLET} from '../../../routers/ScreenNames'; import {
ENTER_PASSWORD_SMART_OTP,
import {getOTPApi} from '../../../apis/Functions/users'; SETTINGOTP,
SMARTOTP,
CHANGESMARTOTP,
} from '../../../routers/ScreenNames';
import {showAlert, TYPE} from '../../../components/DropdownAlert'; import {showAlert, TYPE} from '../../../components/DropdownAlert';
import {confirmAlert} from '../../../components/Aleart';
const {width} = Dimensions.get('window');
const WalletDeposit = (props) => { const WalletDeposit = (props) => {
const [amount, setAmount] = useState(); const [amount, setAmount] = useState();
...@@ -48,19 +47,35 @@ const WalletDeposit = (props) => { ...@@ -48,19 +47,35 @@ const WalletDeposit = (props) => {
I18n.t('Note').toLowerCase(), I18n.t('Note').toLowerCase(),
]; ];
const index = checkFormatArray([amount, notes]); const index = checkFormatArray([amount]);
if (index === true) { if (index === true) {
props.showLoading(); if (!props.user.smart_otp_status) {
const res = await getOTPApi({ confirmAlert(
platform: Platform.OS, `${I18n.t('YouHaveNotSettingSmartOTP')}`,
otp_by: props.user.email, () => {
type: 'CUSTOMER_REQUEST_DEPOSIT', navigate.navigate(CHANGESMARTOTP, {
TYPE: 'CREATE_SMART_OTP',
old_password: null,
isFromTransaction: true,
setupSmartOTPSuccess: () => {
navigate.goBack();
navigate.goBack();
navigate.navigate(ENTER_PASSWORD_SMART_OTP, {
type: 'DEPOSIT',
onGoToSmartOTP: (pinCode, otp) =>
onGoToSmartOTP(pinCode, otp),
});
DeviceEventEmitter.emit('reloadUserInfo');
},
}); });
props.hideLoading(); },
if (res.data.code == 200) { `${I18n.t('setting')}`,
navigate.navigate(OTPWALLET, {type: 'DEPOSIT', amount, notes}); );
} else { } else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message); navigate.navigate(ENTER_PASSWORD_SMART_OTP, {
type: 'DEPOSIT',
onGoToSmartOTP: (pinCode, otp) => onGoToSmartOTP(pinCode, otp),
});
} }
} else { } else {
showAlert( showAlert(
...@@ -70,6 +85,16 @@ const WalletDeposit = (props) => { ...@@ -70,6 +85,16 @@ const WalletDeposit = (props) => {
); );
} }
}; };
const onGoToSmartOTP = (pinCode, otp) => {
navigate.goBack();
navigate.navigate(SMARTOTP, {
type: 'DEPOSIT',
amount,
notes,
pinCode,
otp,
});
};
return ( return (
<KeyboardAvoidingView <KeyboardAvoidingView
behavior={Platform.Os === 'ios' ? 'padding' : 'height'} behavior={Platform.Os === 'ios' ? 'padding' : 'height'}
......
...@@ -6,17 +6,15 @@ import { ...@@ -6,17 +6,15 @@ import {
Dimensions, Dimensions,
TouchableOpacity, TouchableOpacity,
Platform, Platform,
Alert,
TouchableWithoutFeedback, TouchableWithoutFeedback,
Keyboard, Keyboard,
KeyboardAvoidingView, KeyboardAvoidingView,
ScrollView, ScrollView,
DeviceEventEmitter,
} from 'react-native'; } from 'react-native';
import R from '../../../assets/R'; import R from '../../../assets/R';
import HeaderBack from '../../../components/Header/HeaderBack'; import HeaderBack from '../../../components/Header/HeaderBack';
import TextField from '../../../components/Input/TextField';
import TextMulti from '../../../components/Input/TextMulti'; import TextMulti from '../../../components/Input/TextMulti';
import TextDisable from '../../../components/Input/TextDisable';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import { import {
getFontXD, getFontXD,
...@@ -27,15 +25,20 @@ import { ...@@ -27,15 +25,20 @@ import {
} from '../../../Config/Functions'; } from '../../../Config/Functions';
import PickerItem from '../../../components/Picker/PickerItem'; import PickerItem from '../../../components/Picker/PickerItem';
import RadioForm from 'react-native-simple-radio-button'; import RadioForm from 'react-native-simple-radio-button';
import {widthDraw, getListWidthDraw} from '../../../apis/Functions/Widthdraw'; import {getListWidthDraw} from '../../../apis/Functions/Widthdraw';
import {useNavigation} from '@react-navigation/native'; import {useNavigation} from '@react-navigation/native';
import {showLoading, hideLoading} from '../../../actions/loadingAction'; import {showLoading, hideLoading} from '../../../actions/loadingAction';
import {saveUserToRedux} from '../../../actions/users';
import {confirmAlert} from '../../../components/Aleart'; import {confirmAlert} from '../../../components/Aleart';
import {ADDMETHODPAY} from '../../../routers/ScreenNames'; import {
ADDMETHODPAY,
ENTER_PASSWORD_SMART_OTP,
SETTINGOTP,
CHANGESMARTOTP,
} from '../../../routers/ScreenNames';
import TextMoney from '../../../components/Input/InputMoney'; import TextMoney from '../../../components/Input/InputMoney';
import I18n from '../../../helper/i18/i18n'; import I18n from '../../../helper/i18/i18n';
import {getOTPApi} from '../../../apis/Functions/users'; import {SMARTOTP} from '../../../routers/ScreenNames';
import {OTPWALLET} from '../../../routers/ScreenNames';
import {showAlert, TYPE} from '../../../components/DropdownAlert'; import {showAlert, TYPE} from '../../../components/DropdownAlert';
var radio_props = [ var radio_props = [
{label: 'Từ ví', value: 'WALLET'}, {label: 'Từ ví', value: 'WALLET'},
...@@ -66,6 +69,7 @@ const WalletWithdraw = (props) => { ...@@ -66,6 +69,7 @@ const WalletWithdraw = (props) => {
}, [navigate]); }, [navigate]);
const getData = async () => { const getData = async () => {
props.showLoading();
const res = await getListWidthDraw({ const res = await getListWidthDraw({
platform: Platform.OS, platform: Platform.OS,
}); });
...@@ -83,9 +87,11 @@ const WalletWithdraw = (props) => { ...@@ -83,9 +87,11 @@ const WalletWithdraw = (props) => {
} else { } else {
showAlert(TYPE.ERROR, I18n.t('Notification'), I18n.t('Can_not_get_data')); showAlert(TYPE.ERROR, I18n.t('Notification'), I18n.t('Can_not_get_data'));
} }
props.hideLoading();
}; };
const onPressWithdraw = async () => { const onPressWithdraw = async () => {
console.log();
const titles = [ const titles = [
I18n.t('BeneficiaryAccount'), I18n.t('BeneficiaryAccount'),
I18n.t('AmountOfMoney').toLowerCase(), I18n.t('AmountOfMoney').toLowerCase(),
...@@ -95,25 +101,51 @@ const WalletWithdraw = (props) => { ...@@ -95,25 +101,51 @@ const WalletWithdraw = (props) => {
if (index === true) { if (index === true) {
if (amount >= props.user.configs.request_withdraw_amount_min) { if (amount >= props.user.configs.request_withdraw_amount_min) {
props.showLoading(); if (src == 'WALLET' && amount > props.user.current_money) {
const res = await getOTPApi({ showAlert(
platform: Platform.OS, TYPE.WARN,
otp_by: props.user.email, I18n.t('Notification'),
type: 'REQUEST_WITHDRAW', I18n.t('WarnMaxReqestWithdraw'),
}); );
props.hideLoading(); } else if (
if (res.data.code == 200) { src == 'INVESTMENT' &&
navigate.navigate(OTPWALLET, { amount > props.user.current_cqg_money
) {
showAlert(
TYPE.WARN,
I18n.t('Notification'),
I18n.t('WarnMaxReqestWithdraw'),
);
} else {
if (!props.user.smart_otp_status) {
confirmAlert(
`${I18n.t('YouHaveNotSettingSmartOTP')}`,
() => {
navigate.navigate(CHANGESMARTOTP, {
TYPE: 'CREATE_SMART_OTP',
old_password: null,
isFromTransaction: true,
setupSmartOTPSuccess: () => {
navigate.goBack();
navigate.goBack();
navigate.navigate(ENTER_PASSWORD_SMART_OTP, {
type: 'WITHDRAW', type: 'WITHDRAW',
src, onGoToSmartOTP: (pinCode, otp) =>
receiving_account: type.id, onGoToSmartOTP(pinCode, otp),
amount,
notes,
}); });
DeviceEventEmitter.emit('reloadUserInfo');
},
});
},
`${I18n.t('setting')}`,
);
} else { } else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message); navigate.navigate(ENTER_PASSWORD_SMART_OTP, {
type: 'WITHDRAW',
onGoToSmartOTP: (pinCode, otp) => onGoToSmartOTP(pinCode, otp),
});
}
} }
props.hideLoading();
} else { } else {
showAlert( showAlert(
TYPE.WARN, TYPE.WARN,
...@@ -130,6 +162,19 @@ const WalletWithdraw = (props) => { ...@@ -130,6 +162,19 @@ const WalletWithdraw = (props) => {
} }
}; };
const onGoToSmartOTP = (pinCode, otp) => {
navigate.goBack();
navigate.navigate(SMARTOTP, {
type: 'WITHDRAW',
src,
receiving_account: type.id,
amount,
notes,
pinCode,
otp,
});
};
return ( return (
<KeyboardAvoidingView <KeyboardAvoidingView
behavior={Platform.Os === 'ios' ? 'padding' : 'height'} behavior={Platform.Os === 'ios' ? 'padding' : 'height'}
...@@ -297,4 +342,5 @@ const mapStateToProps = (state) => { ...@@ -297,4 +342,5 @@ const mapStateToProps = (state) => {
export default connect(mapStateToProps, { export default connect(mapStateToProps, {
showLoading, showLoading,
hideLoading, hideLoading,
saveUserToRedux,
})(WalletWithdraw); })(WalletWithdraw);
...@@ -18,7 +18,7 @@ import { ...@@ -18,7 +18,7 @@ import {
FORGOTPASSWORD, FORGOTPASSWORD,
CONFIRMEMAIL, CONFIRMEMAIL,
} from '../../routers/ScreenNames'; } from '../../routers/ScreenNames';
import {checkFormatArray} from '../../Config/Functions'; import {checkFormatArray, encryptRSAString} from '../../Config/Functions';
import {loginApi} from '../../apis/Functions/users'; import {loginApi} from '../../apis/Functions/users';
import KEY from '../../assets/AsynStorage'; import KEY from '../../assets/AsynStorage';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
...@@ -29,15 +29,27 @@ import messaging from '@react-native-firebase/messaging'; ...@@ -29,15 +29,27 @@ import messaging from '@react-native-firebase/messaging';
import I18n from '../../helper/i18/i18n'; import I18n from '../../helper/i18/i18n';
import AppText from '../../components/AppText'; import AppText from '../../components/AppText';
import {showAlert, TYPE} from '../../components/DropdownAlert'; import {showAlert, TYPE} from '../../components/DropdownAlert';
import TouchID from 'react-native-touch-id';
import {call} from 'redux-saga/effects';
import KeychainService from '../../services/keychainService';
import * as Keychain from 'react-native-keychain';
import EntypoIcon from 'react-native-vector-icons/Entypo';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
const Login = (props) => { const Login = (props) => {
const {navigation} = props; const {navigation} = props;
const [email, setEmail] = useState(''); const [email, setEmail] = useState('');
const [pass, setPass] = useState(''); const [pass, setPass] = useState('');
const [biometryType, setBiometryType] = useState(null);
const [isShowBiometryLogin, setIsShowBiometryLogin] = useState(false);
const navigate = useNavigation(); const navigate = useNavigation();
const optionalConfigObject = {
title: 'Authentication Required', // Android
color: '#e00606', // Android,
fallbackLabel: '', // iOS (if empty, then label is hidden)
};
const getTokenDevice = async () => { const getTokenDevice = async () => {
let fcmToken = await AsyncStorage.getItem(KEY.FIREBASE); let fcmToken = await AsyncStorage.getItem(KEY.FIREBASE);
...@@ -48,11 +60,21 @@ const Login = (props) => { ...@@ -48,11 +60,21 @@ const Login = (props) => {
} }
} }
}; };
const getLoginByBiometry = async () => {
let loginByBiometry = await AsyncStorage.getItem(KEY.IS_LOGIN_BY_BIOMETRY);
if (loginByBiometry) {
loginByBiometry = JSON.parse(loginByBiometry)
setIsShowBiometryLogin(loginByBiometry.isLoginByBiometry);
loginByBiometry.isLoginByBiometry && Keychain.getSupportedBiometryType({}).then((biometryType) => {
setBiometryType(biometryType);
});
}
};
useEffect(() => { useEffect(() => {
props.hideLoading(); props.hideLoading();
getAccount(); getAccount();
getTokenDevice(); getTokenDevice();
getLoginByBiometry();
}, []); }, []);
const getAccount = async () => { const getAccount = async () => {
...@@ -62,7 +84,34 @@ const Login = (props) => { ...@@ -62,7 +84,34 @@ const Login = (props) => {
onSubmitLogin(account.email, account.pass); onSubmitLogin(account.email, account.pass);
} }
}; };
const getCredentialInfo = async () => {
try {
// Retrieve the credentials
const options = {
authenticationPrompt: {
title: 'Authentication needed',
cancel: 'Cancel',
},
};
const credentials = await Keychain.getGenericPassword(options);
if (credentials) {
console.log(
'Credentials successfully loaded for user ', credentials,
);
onSubmitLogin(credentials.username, credentials.password);
} else {
showAlert(
TYPE.ERROR,
I18n.t('Notification'),
I18n.t('HaveNotCredential', {type: biometryType == 'FaceID' ? I18n.t('FaceId') : I18n.t('Fingerprint')}),
);
console.log('No credentials stored');
}
} catch (error) {
console.log('Keychain couldn\'t be accessed!', error);
}
};
const onSubmitLogin = async (email, pass) => { const onSubmitLogin = async (email, pass) => {
const titles = [ const titles = [
I18n.t('Username').toLowerCase(), I18n.t('Username').toLowerCase(),
...@@ -75,12 +124,11 @@ const Login = (props) => { ...@@ -75,12 +124,11 @@ const Login = (props) => {
props.showLoading(); props.showLoading();
const res = await loginApi({ const res = await loginApi({
email, email,
password: pass, password: encryptRSAString(pass),
platform: Platform.OS, platform: Platform.OS,
device_token: firebase, device_token: firebase,
account_type: 'CUSTOMER', account_type: 'CUSTOMER',
}); });
props.hideLoading(); props.hideLoading();
if (res.data) { if (res.data) {
if (res.data.code == 200 && res.data.data) { if (res.data.code == 200 && res.data.data) {
...@@ -135,7 +183,7 @@ const Login = (props) => { ...@@ -135,7 +183,7 @@ const Login = (props) => {
<TouchableOpacity <TouchableOpacity
onPress={() => navigate.navigate(CONFIRMEMAIL)} onPress={() => navigate.navigate(CONFIRMEMAIL)}
style={styles.forgotView}> style={styles.forgotView}>
<AppText i18nKey={'ForgotPassword'} style={styles.txtTitle} /> <AppText i18nKey={'ForgotPassword'} style={styles.txtTitle}/>
</TouchableOpacity> </TouchableOpacity>
<View <View
...@@ -146,21 +194,41 @@ const Login = (props) => { ...@@ -146,21 +194,41 @@ const Login = (props) => {
<TouchableOpacity <TouchableOpacity
onPress={() => onSubmitLogin(email, pass)} onPress={() => onSubmitLogin(email, pass)}
style={styles.wrapLogin}> style={styles.wrapLogin}>
<AppText i18nKey={'Login'} style={styles.txtLogin} /> <AppText i18nKey={'Login'} style={styles.txtLogin}/>
<Image source={R.images.iconRight1} style={styles.imgIcon} /> <Image source={R.images.iconRight1} style={styles.imgIcon}/>
</TouchableOpacity>
{isShowBiometryLogin ?
<View style={{flexDirection: 'row', marginTop: WIDTHXD(70)}}>
{biometryType == 'FaceID' ?
<TouchableOpacity
onPress={() => {
getCredentialInfo();
}}>
<Image source={R.images.iconFaceId} style={[styles.imgIconBiometry, {tintColor: R.colors.main}]}/>
</TouchableOpacity>
:
<TouchableOpacity
onPress={() => {
getCredentialInfo();
}}>
<Image source={R.images.fingerprint} style={styles.imgIconBiometry}/>
</TouchableOpacity> </TouchableOpacity>
}
</View>
: null}
<View style={styles.row}> <View style={styles.row}>
<AppText i18nKey={'Have_account'} style={styles.txtTitle} /> <AppText i18nKey={'Have_account'} style={styles.txtTitle}/>
<TouchableOpacity <TouchableOpacity
onPress={() => { onPress={() => {
navigation.navigate('REGISTOR'); navigation.navigate('REGISTOR');
}}> }}>
<AppText i18nKey={'Register'} style={styles.txtRegistor} /> <AppText i18nKey={'Register'} style={styles.txtRegistor}/>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
</View> </View>
<View style={{height: 100}} /> <View style={{height: 100}}/>
</View> </View>
); );
}; };
...@@ -193,6 +261,10 @@ const styles = StyleSheet.create({ ...@@ -193,6 +261,10 @@ const styles = StyleSheet.create({
height: HEIGHTXD(72), height: HEIGHTXD(72),
marginLeft: 5, marginLeft: 5,
}, },
imgIconBiometry: {
width: WIDTHXD(120),
height: WIDTHXD(120),
},
row: { row: {
flexDirection: 'row', flexDirection: 'row',
marginTop: 30, marginTop: 30,
......
...@@ -20,6 +20,7 @@ import I18n from '../../helper/i18/i18n'; ...@@ -20,6 +20,7 @@ import I18n from '../../helper/i18/i18n';
import {showLoading, hideLoading} from '../../actions/loadingAction'; import {showLoading, hideLoading} from '../../actions/loadingAction';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import {showAlert, TYPE} from '../../components/DropdownAlert'; import {showAlert, TYPE} from '../../components/DropdownAlert';
import {encryptRSAString} from '../../Config/Functions';
const NewPassword = (props) => { const NewPassword = (props) => {
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
...@@ -36,8 +37,8 @@ const NewPassword = (props) => { ...@@ -36,8 +37,8 @@ const NewPassword = (props) => {
const res = await forgotPasswordApi({ const res = await forgotPasswordApi({
receiver_name: email, receiver_name: email,
otp, otp,
password, password: encryptRSAString(password),
password_confirmation: cfPassword, password_confirmation: encryptRSAString(cfPassword),
platform: Platform.OS, platform: Platform.OS,
}); });
props.hideLoading(); props.hideLoading();
......
...@@ -16,7 +16,13 @@ import { ...@@ -16,7 +16,13 @@ import {
useBlurOnFulfill, useBlurOnFulfill,
useClearByFocusCell, useClearByFocusCell,
} from 'react-native-confirmation-code-field'; } from 'react-native-confirmation-code-field';
import {getFontXD, HEIGHTXD, WIDTHXD} from '../../Config/Functions'; import {
getFontXD,
HEIGHTXD,
WIDTHXD,
encryptRSAString,
decryptRSAString,
} from '../../Config/Functions';
import R from '../../assets/R'; import R from '../../assets/R';
import {NEWPASSWORD} from '../../routers/ScreenNames'; import {NEWPASSWORD} from '../../routers/ScreenNames';
import {verifyOTPApi, registorApi, getOTPApi} from '../../apis/Functions/users'; import {verifyOTPApi, registorApi, getOTPApi} from '../../apis/Functions/users';
...@@ -52,7 +58,7 @@ const ConfirmOTP = (propsa) => { ...@@ -52,7 +58,7 @@ const ConfirmOTP = (propsa) => {
const res = await verifyOTPApi({ const res = await verifyOTPApi({
platform: Platform.OS, platform: Platform.OS,
receiver_name: propsa.route.params.email, receiver_name: propsa.route.params.email,
otp: value, otp: encryptRSAString(value),
type: 'CUSTOMER_VERIFY', type: 'CUSTOMER_VERIFY',
}); });
...@@ -68,18 +74,18 @@ const ConfirmOTP = (propsa) => { ...@@ -68,18 +74,18 @@ const ConfirmOTP = (propsa) => {
if (sponsor_id) { if (sponsor_id) {
res = await registorApi({ res = await registorApi({
email, email,
password, password: encryptRSAString(password),
platform: Platform.OS, platform: Platform.OS,
password_confirmation, password_confirmation: encryptRSAString(password_confirmation),
sponsor_id, sponsor_id,
phone, phone,
}); });
} else { } else {
res = await registorApi({ res = await registorApi({
email, email,
password, password: encryptRSAString(password),
platform: Platform.OS, platform: Platform.OS,
password_confirmation, password_confirmation: encryptRSAString(password_confirmation),
phone, phone,
}); });
} }
......
import React, {useEffect, useState} from 'react'; import React, {useEffect, useState} from 'react';
import {Alert, Platform, View} from 'react-native'; import {DeviceEventEmitter, Platform} from 'react-native';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import {getTransaction} from '../../apis/Functions/users'; import {getTransaction} from '../../apis/Functions/users';
import {getImagesHome} from '../../apis/Functions/General'; import {getImagesHome} from '../../apis/Functions/General';
...@@ -11,7 +11,6 @@ import {getListCategoryProduct} from '../../apis/Functions/Transaction'; ...@@ -11,7 +11,6 @@ import {getListCategoryProduct} from '../../apis/Functions/Transaction';
import {hideLoading, showLoading} from '../../actions/loadingAction'; import {hideLoading, showLoading} from '../../actions/loadingAction';
import _ from 'lodash'; import _ from 'lodash';
import {showAlert, TYPE} from '../../components/DropdownAlert/index'; import {showAlert, TYPE} from '../../components/DropdownAlert/index';
import VersionChecker from '../VersionChecker';
import {saveUserToRedux} from '../../actions/users'; import {saveUserToRedux} from '../../actions/users';
import {getDetailUser} from '../../apis/Functions/users'; import {getDetailUser} from '../../apis/Functions/users';
...@@ -52,6 +51,16 @@ const Home = (props) => { ...@@ -52,6 +51,16 @@ const Home = (props) => {
useEffect(() => { useEffect(() => {
getData(); getData();
initSocket(); initSocket();
let reloadUserInfoListener = DeviceEventEmitter.addListener(
'reloadUserInfo',
(e) => {
console.log('run in to reloadUserInfo');
onRefresh();
},
);
return () => {
reloadUserInfoListener.remove();
};
}, []); }, []);
useEffect(() => { useEffect(() => {
...@@ -218,7 +227,6 @@ const Home = (props) => { ...@@ -218,7 +227,6 @@ const Home = (props) => {
/> />
); );
}; };
<VersionChecker />;
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
return { return {
user: state.userReducer, user: state.userReducer,
......
...@@ -40,7 +40,7 @@ const PriceListView = (props) => { ...@@ -40,7 +40,7 @@ const PriceListView = (props) => {
</View> </View>
<FlatList <FlatList
style={{paddingBottom: HEIGHTXD(15), backgroundColor: R.colors.white}} style={{paddingBottom: HEIGHTXD(15), backgroundColor: R.colors.white}}
keyExtractor={(item) => item.id} keyExtractor={(item) => item.id.toString()}
data={dataPrice} data={dataPrice}
ListHeaderComponent={() => ListHeaderComponent={() =>
<View style={[styles.container]}> <View style={[styles.container]}>
......
...@@ -7,7 +7,7 @@ import {WIDTHXD} from '../../Config/Functions'; ...@@ -7,7 +7,7 @@ import {WIDTHXD} from '../../Config/Functions';
import Icon from 'react-native-vector-icons/Entypo'; import Icon from 'react-native-vector-icons/Entypo';
import {useNavigation} from '@react-navigation/native'; import {useNavigation} from '@react-navigation/native';
import {ADDMETHODPAY} from '../../routers/ScreenNames'; import {ADDMETHODPAY} from '../../routers/ScreenNames';
import AppText from '../../components/AppText';
const MethodPayView = (props) => { const MethodPayView = (props) => {
const navigate = useNavigation(); const navigate = useNavigation();
...@@ -17,7 +17,17 @@ const MethodPayView = (props) => { ...@@ -17,7 +17,17 @@ const MethodPayView = (props) => {
<View style={{flex: 1}}> <View style={{flex: 1}}>
<HeaderBack title={'PaymentSetting'} /> <HeaderBack title={'PaymentSetting'} />
<View style={{flex: 1}}> <View style={{flex: 1}}>
{listMethod.length > 0 ? ( {listMethod.length == 0 ? (
<View
style={{justifyContent: 'center', alignItems: 'center', flex: 1}}>
<AppText
i18nKey={'NoData'}
style={{
fontSize: 18,
fontWeight: 'bold',
}}></AppText>
</View>
) : (
<FlatList <FlatList
keyExtractor={(item) => item.method} keyExtractor={(item) => item.method}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
...@@ -27,7 +37,7 @@ const MethodPayView = (props) => { ...@@ -27,7 +37,7 @@ const MethodPayView = (props) => {
data={listMethod} data={listMethod}
renderItem={({item}) => <Item item={item} />} renderItem={({item}) => <Item item={item} />}
/> />
) : null} )}
<TouchableOpacity <TouchableOpacity
onPress={() => navigate.navigate(ADDMETHODPAY)} onPress={() => navigate.navigate(ADDMETHODPAY)}
......
import React, {useState, useEffect, useRef} from 'react';
import {Modal, View, TouchableWithoutFeedback, TouchableOpacity, StyleSheet, Text, TextInput} from 'react-native';
import IconClose from 'react-native-vector-icons/AntDesign';
import R from '../../assets/R';
import {WIDTHXD, getWidth, HEIGHTXD, getFontXD, getHeight} from '../../Config/Functions';
import {showAlert, TYPE} from '../../components/DropdownAlert';
import I18n from '../../helper/i18/i18n';
import DropdownAlert from 'react-native-dropdownalert';
const EnterPasswordModal = (props) => {
const [visible, setVisible] = useState(true);
const [pass, setPass] = useState('');
const dropDownAlertRef = useRef(null);
const onChangeText = (text) => {
setPass(text);
};
useEffect(() => {
setVisible(props.visible);
}, [props.visible]);
return <Modal
animationType='slide'
transparent={true}
visible={visible}
onRequestClose={() => {
props.setVisible(false);
setPass('');
}}
>
<TouchableWithoutFeedback
onPress={() => {
setPass('');
props.setVisible(false);
}}
>
<View
style={styles.opacity}
>
<View style={styles.modal}>
<View style={styles.viewTitle}>
<View style={styles.viewEmpty}></View>
<Text style={styles.titlePopup}>{I18n.t('EnterPassword')}</Text>
<TouchableOpacity onPress={() => {
setPass('');
props.setVisible(false);
}} style={styles.btClose}>
<IconClose name='close' size={WIDTHXD(48)} color={R.colors.black}/>
</TouchableOpacity>
</View>
<TextInput
autoCapitalize="none"
onChangeText={(val) => onChangeText(val)}
style={styles.txtInput}
placeholderTextColor={R.colors.placeHolder}
secureTextEntry={true}
autoFocus={true}
value={pass}
/>
<TouchableOpacity onPress={() => {
if (pass == '') {
dropDownAlertRef.current.alertWithType(TYPE.WARN, I18n.t('Notification'), `${I18n.t('Please_fill_in')}${I18n.t('Password')}`);
} else {
props.accept(pass);
setPass('')
}
}}>
<Text style={styles.txtAccept}>{I18n.t('Ok')}</Text>
</TouchableOpacity>
</View>
<DropdownAlert
inactiveStatusBarBackgroundColor={R.colors.main}
activeStatusBarBackgroundColor={R.colors.main}
warnImageSrc={R.images.iconWarn}
successImageSrc={R.images.iconSuccess}
errorImageSrc={R.images.iconError}
titleStyle={{color: '#fff'}}
messageStyle={{color: '#fff'}}
updateStatusBar={false}
closeInterval={1000}
ref={dropDownAlertRef}
warnColor={R.colors.orange400}
defaultContainer={{
borderBottomRightRadius: WIDTHXD(30),
borderBottomLeftRadius: WIDTHXD(30),
paddingTop: HEIGHTXD(30),
paddingVertical: HEIGHTXD(30),
paddingHorizontal: WIDTHXD(20),
}}
/>
</View>
</TouchableWithoutFeedback>
</Modal>;
};
const styles = StyleSheet.create({
opacity: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#rgba(0,0,0,0.7)',
},
titlePopup: {
fontSize: getFontXD(48),
color: R.colors.black,
textAlign: 'center',
flex: 10,
},
viewEmpty: {
flex: 1,
},
viewTitle: {
flexDirection: 'row',
width: WIDTHXD(960),
borderBottomWidth: 0.3,
paddingBottom: HEIGHTXD(50),
borderBottomColor: R.colors.iconGray,
borderColor: R.colors.iconGray,
},
txtAccept: {
fontSize: getFontXD(48),
color: R.colors.main,
textAlign: 'center',
marginTop: HEIGHTXD(50),
},
btClose: {
flex: 1,
justifyContent: 'center',
alignItems: 'flex-start',
},
modal: {
backgroundColor: R.colors.white,
width: WIDTHXD(960),
justifyContent: 'center',
// maxHeight: HEIGHTXD(1300),
borderRadius: WIDTHXD(20),
paddingBottom: WIDTHXD(40),
// minHeight: HEIGHTXD(369),
paddingVertical: HEIGHTXD(59),
paddingTop: HEIGHTXD(61),
paddingHorizontal: WIDTHXD(60),
alignItems: 'center',
},
txtInput: {
width: WIDTHXD(880),
height: HEIGHTXD(109),
marginTop: HEIGHTXD(50),
color: 'black',
borderRadius: 7,
borderWidth: 0.7,
borderColor: '#DBDBDB',
fontSize: getFontXD(42),
paddingVertical: 5,
paddingHorizontal: 10,
backgroundColor: 'white',
shadowColor: '#AFA9A9',
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.25,
shadowRadius: 1.84,
elevation: 1,
},
});
export default EnterPasswordModal;
import React, {useEffect, useState} from 'react'; import React, {useEffect, useState} from 'react';
import {View, Text, Switch, StyleSheet} from 'react-native'; import {View, Text, Switch, StyleSheet, Platform} from 'react-native';
import HeaderBack from '../../components/Header/HeaderBack'; import HeaderBack from '../../components/Header/HeaderBack';
import {getFontXD} from '../../Config/Functions'; import {encryptRSAString, getFontXD} from '../../Config/Functions';
import PickerItem from '../../components/Picker/PickerItem'; import PickerItem from '../../components/Picker/PickerItem';
import AppText from '../../components/AppText'; import AppText from '../../components/AppText';
import {changeLanguage} from '../../actions/language'; import {changeLanguage} from '../../actions/language';
...@@ -9,6 +9,12 @@ import {connect} from 'react-redux'; ...@@ -9,6 +9,12 @@ import {connect} from 'react-redux';
import AsyncStorage from '@react-native-community/async-storage'; import AsyncStorage from '@react-native-community/async-storage';
import KEY from '../../assets/AsynStorage'; import KEY from '../../assets/AsynStorage';
import I18n, {setLocation} from '../../helper/i18/i18n'; import I18n, {setLocation} from '../../helper/i18/i18n';
import EnterPasswordModal from './EnterPasswordModal';
import * as Keychain from 'react-native-keychain';
import {showLoading, hideLoading} from '../../actions/loadingAction';
import {verifyPassword} from '../../apis/Functions/users';
import {showAlert, TYPE} from '../../components/DropdownAlert';
const dataLanguage = [ const dataLanguage = [
{ {
value: 'vi', value: 'vi',
...@@ -21,37 +27,72 @@ const dataLanguage = [ ...@@ -21,37 +27,72 @@ const dataLanguage = [
]; ];
const SettingView = (props) => { const SettingView = (props) => {
const [isEnabled, setIsEnabled] = useState(true); const [isEnabled, setIsEnabled] = useState(false);
const toggleSwitch = () => setIsEnabled((previousState) => !previousState); const [visible, setVisible] = useState(false);
const [biometryType, setBiometryType] = useState(null);
const toggleSwitch = async () => {
if (isEnabled == true) {
await Keychain.resetGenericPassword();
AsyncStorage.setItem(KEY.IS_LOGIN_BY_BIOMETRY, JSON.stringify({isLoginByBiometry : false}));
setIsEnabled(false);
} else {
setVisible(true);
}
};
const [language, setLanguage] = useState(); const [language, setLanguage] = useState();
useEffect(() => { useEffect(() => {
convertLanguage(); convertLanguage();
getLoginByBiometry()
Keychain.getSupportedBiometryType({}).then((biometryType) => {
setBiometryType(biometryType);
});
}, []); }, []);
const getLoginByBiometry = async () => {
let loginByBiometry = await AsyncStorage.getItem(KEY.IS_LOGIN_BY_BIOMETRY);
if (loginByBiometry) {
setIsEnabled(JSON.parse(loginByBiometry).isLoginByBiometry);
}
};
const savePass = async (pass) => {
setVisible(false);
props.showLoading();
console.log(props.user);
const res = await verifyPassword({
password: encryptRSAString(pass),
platform: Platform.OS,
account_type: 'CUSTOMER',
});
if (res.status == 200 && res.data) {
if (res.data.code == 200) {
await Keychain.setGenericPassword(props.user.email, pass, {
accessControl: Keychain.ACCESS_CONTROL.BIOMETRY_CURRENT_SET,
});
AsyncStorage.setItem(KEY.IS_LOGIN_BY_BIOMETRY, JSON.stringify({isLoginByBiometry : true}));
setIsEnabled(true);
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message);
}
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), I18n.t('HaveIssue'));
}
props.hideLoading();
};
const convertLanguage = () => { const convertLanguage = () => {
const temp = dataLanguage.filter((e) => e.value == props.language.language); const temp = dataLanguage.filter((e) => e.value == props.language.language);
setLanguage(temp[0].name); setLanguage(temp[0].name);
}; };
return ( return (
<>
<View style={{flex: 1}}> <View style={{flex: 1}}>
<HeaderBack title={'Setting'} /> <HeaderBack title={'Setting'}/>
<View style={{flex: 1, padding: 10}}> <View style={{flex: 1, padding: 10}}>
{/* <View style={styles.row}>
<Text style={styles.txtTitle}>Bật thông báo</Text>
<Switch
trackColor={{false: '#DBDBDB', true: '#1C6AF6'}}
ios_backgroundColor="#767577"
thumbColor={'#f4f3f4'}
onValueChange={toggleSwitch}
value={isEnabled}
/>
</View> */}
<View style={styles.row}> <View style={styles.row}>
<AppText i18nKey={'Language'} style={styles.txtTitle} /> <AppText i18nKey={'Language'} style={styles.txtTitle}/>
<PickerItem <PickerItem
width={200} width={200}
defaultValue={language} defaultValue={language}
...@@ -66,8 +107,26 @@ const SettingView = (props) => { ...@@ -66,8 +107,26 @@ const SettingView = (props) => {
}} }}
/> />
</View> </View>
<View style={styles.row}>
<Text style={styles.txtTitle}>{I18n.t('LoginBy', {type: biometryType =='FaceID' ? I18n.t('FaceId') : I18n.t('Fingerprint')})}</Text>
<Switch
trackColor={{false: '#DBDBDB', true: '#1C6AF6'}}
ios_backgroundColor="#767577"
thumbColor={'#f4f3f4'}
onValueChange={toggleSwitch}
value={isEnabled}
/>
</View>
</View> </View>
<EnterPasswordModal
visible={visible}
accept={(pass) => savePass(pass)}
setVisible={(visible) => setVisible(visible)}
/>
</View> </View>
</>
); );
}; };
...@@ -87,8 +146,9 @@ const styles = StyleSheet.create({ ...@@ -87,8 +146,9 @@ const styles = StyleSheet.create({
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
return { return {
user: state.userReducer,
language: state.languageReducer, language: state.languageReducer,
}; };
}; };
export default connect(mapStateToProps, {changeLanguage})(SettingView); export default connect(mapStateToProps, {changeLanguage, showLoading, hideLoading})(SettingView);
import React, {useState, useEffect} from 'react';
import ChangeSmartOTPView from './ChangeSmartOTPView';
import {
getOTPApiSmartOTP,
verifyOTPApiSmart,
} from '../../../apis/Functions/users';
import {showAlert, TYPE} from '../../../components/DropdownAlert';
import {connect} from 'react-redux';
import {hideLoading, showLoading} from '../../../actions/loadingAction';
import {useNavigation} from '@react-navigation/native';
import {CONFIRMCHANGESMARTOTP} from '../../../routers/ScreenNames';
const EnterPasswordSmartOTP = (props) => {
const navigation = useNavigation();
const [firstNumber, setFirstNumber] = useState(null);
const [secondsNumber, setSecondsNumber] = useState(null);
const [thirdNumber, setThirdNumber] = useState(null);
const [fourNumber, setFourNumber] = useState(null);
useEffect(() => {
if (fourNumber) {
onCheckPINSmartOTPPin();
}
}, [fourNumber]);
const onNumberPress = (number) => {
if (!firstNumber) {
setFirstNumber(number.toString());
} else if (!secondsNumber) {
setSecondsNumber(number.toString());
} else if (!thirdNumber) {
setThirdNumber(number.toString());
} else if (!fourNumber) {
setFourNumber(number.toString());
}
};
console.log('Pros pass', props.route.params);
const onCheckPINSmartOTPPin = async () => {
let pinCode = `${firstNumber}${secondsNumber}${thirdNumber}${fourNumber}`;
setFirstNumber(null);
setSecondsNumber(null);
setThirdNumber(null);
setFourNumber(null);
if (props.route.params.isFromTransaction) {
navigation.navigate(CONFIRMCHANGESMARTOTP, {
pre_otp: pinCode,
old_password: props.route.params.old_password,
isFromTransaction: props.route.params.isFromTransaction,
TYPE: props.route.params.TYPE,
setupSmartOTPSuccess: props.route.params.setupSmartOTPSuccess,
});
} else {
navigation.navigate(CONFIRMCHANGESMARTOTP, {
pre_otp: pinCode,
old_password: props.route.params.old_password,
TYPE: props.route.params.TYPE,
});
}
};
const onDeletePress = () => {
if (fourNumber) {
setFourNumber(null);
} else if (thirdNumber) {
setThirdNumber(null);
} else if (secondsNumber) {
setSecondsNumber(null);
} else if (firstNumber) {
setFirstNumber(null);
}
};
return (
<ChangeSmartOTPView
firstNumber={firstNumber}
secondsNumber={secondsNumber}
thirdNumber={thirdNumber}
fourNumber={fourNumber}
onNumberPress={onNumberPress}
onDeletePress={onDeletePress}
/>
);
};
const mapStateToProps = (state) => {
return {
user: state.userReducer,
};
};
export default connect(mapStateToProps, {showLoading, hideLoading})(
EnterPasswordSmartOTP,
);
import React from 'react';
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import HeaderBack from '../../../components/Header/HeaderBack';
import {getFontXD, HEIGHTXD, WIDTHXD} from '../../../Config/Functions';
import I18n from '../../../helper/i18/i18n';
import R from '../../../assets/R';
import Icon from 'react-native-vector-icons/FontAwesome5';
const ChangeSmartOTPView = (props) => {
return (
<View style={{flex: 1, colorBackground: R.colors.white}}>
<HeaderBack title={'ChangeSmartOTP'} />
<Text style={[styles.textNormal, {marginTop: HEIGHTXD(40)}]}>
{I18n.t('EnterSmartOTPPINNEW')}
</Text>
<View style={[styles.rowNumber]}>
<View
style={[
styles.indicator,
{
backgroundColor: props.firstNumber
? R.colors.main
: R.colors.white,
},
]}
/>
<View
style={[
styles.indicator,
{
backgroundColor: props.secondsNumber
? R.colors.main
: R.colors.white,
},
]}
/>
<View
style={[
styles.indicator,
{
backgroundColor: props.thirdNumber
? R.colors.main
: R.colors.white,
},
]}
/>
<View
style={[
styles.indicator,
{
backgroundColor: props.fourNumber
? R.colors.main
: R.colors.white,
},
]}
/>
</View>
<View style={[styles.rowNumber, {marginTop: HEIGHTXD(80)}]}>
<TouchableOpacity
onPress={() => {
props.onNumberPress(1);
}}
style={styles.btnNumber}>
<Text style={styles.textNumber}>1</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(2);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>2</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(3);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>3</Text>
</TouchableOpacity>
</View>
<View style={styles.rowNumber}>
<TouchableOpacity
onPress={() => {
props.onNumberPress(4);
}}
style={styles.btnNumber}>
<Text style={styles.textNumber}>4</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(5);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>5</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(6);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>6</Text>
</TouchableOpacity>
</View>
<View style={styles.rowNumber}>
<TouchableOpacity
onPress={() => {
props.onNumberPress(7);
}}
style={styles.btnNumber}>
<Text style={styles.textNumber}>7</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(8);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>8</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(9);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>9</Text>
</TouchableOpacity>
</View>
<View style={styles.rowNumber}>
<TouchableOpacity
onPress={() => {
props.onNumberPress(0);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(300)}]}>
<Text style={styles.textNumber}>0</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onDeletePress();
}}
style={{
width: HEIGHTXD(260),
height: HEIGHTXD(260),
marginLeft: WIDTHXD(40),
justifyContent: 'center',
alignItems: 'center',
}}>
<Icon name={'backspace'} size={HEIGHTXD(80)} color={'#8E8C8C'} />
</TouchableOpacity>
</View>
</View>
);
};
export default ChangeSmartOTPView;
const styles = StyleSheet.create({
btnSend: {
height: HEIGHTXD(80),
justifyContent: 'center',
alignItems: 'center',
},
rowNumber: {
flexDirection: 'row',
justifyContent: 'center',
marginTop: HEIGHTXD(40),
},
btnNumber: {
height: HEIGHTXD(260),
width: HEIGHTXD(260),
justifyContent: 'center',
alignItems: 'center',
borderWidth: 0.3,
borderColor: R.colors.gray6,
borderRadius: HEIGHTXD(130),
},
indicator: {
height: HEIGHTXD(50),
width: HEIGHTXD(50),
borderWidth: 0.3,
borderColor: R.colors.gray6,
borderRadius: HEIGHTXD(35),
marginHorizontal: WIDTHXD(20),
},
textNormal: {
fontSize: getFontXD(39),
color: R.colors.black,
textAlign: 'center',
},
textNumber: {
fontSize: getFontXD(90),
color: R.colors.black,
textAlign: 'center',
},
txtSend: {
fontSize: getFontXD(42),
color: R.colors.main,
},
});
import React, {useState, useEffect} from 'react';
import ConfirmSmartOTPView from './ConfirmSmartOTPView';
import {
updateOTPApiSmart,
getOTPApiSmartOTP,
} from '../../../apis/Functions/users';
import {showAlert, TYPE} from '../../../components/DropdownAlert';
import {connect} from 'react-redux';
import {hideLoading, showLoading} from '../../../actions/loadingAction';
import I18n from '../../../helper/i18/i18n';
import {
SMARTOTPCONFIG,
TABNAVIGATOR,
CONFIRMCREATEOTP,
} from '../../../routers/ScreenNames';
import {useNavigation} from '@react-navigation/native';
import {encryptRSAString} from '../../../Config/Functions';
const ConfirmChangeSmartOTP = (props) => {
const [firstNumber, setFirstNumber] = useState(null);
const [secondsNumber, setSecondsNumber] = useState(null);
const [thirdNumber, setThirdNumber] = useState(null);
const [fourNumber, setFourNumber] = useState(null);
const navigation = useNavigation();
useEffect(() => {
if (fourNumber) {
onCheckPINSmartOTPPin();
}
}, [fourNumber]);
const onNumberPress = (number) => {
if (!firstNumber) {
setFirstNumber(number.toString());
} else if (!secondsNumber) {
setSecondsNumber(number.toString());
} else if (!thirdNumber) {
setThirdNumber(number.toString());
} else if (!fourNumber) {
setFourNumber(number.toString());
}
};
console.log('Pros pass', props.route.params);
const onCheckPINSmartOTPPin = async () => {
let pinCode = `${firstNumber}${secondsNumber}${thirdNumber}${fourNumber}`;
if (props.route.params.TYPE == 'CHANGE_SMART_OTP') {
props.showLoading();
const res = await updateOTPApiSmart({
platform: Platform.OS,
password: encryptRSAString(props.route.params.pre_otp),
password_confirmation: encryptRSAString(pinCode),
old_password: encryptRSAString(props.route.params.old_password),
});
props.hideLoading();
if (res.data.code == 200) {
showAlert(TYPE.SUCCESS, I18n.t('Notification'), res.data.message);
setFirstNumber(null);
setSecondsNumber(null);
setThirdNumber(null);
setFourNumber(null);
navigation.navigate(SMARTOTPCONFIG);
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message);
setFirstNumber(null);
setSecondsNumber(null);
setThirdNumber(null);
setFourNumber(null);
}
} else {
props.showLoading();
const res = await getOTPApiSmartOTP({
platform: Platform.OS,
otp_by: props.user.email,
otp_password: '1234',
type: 'CREATE_OTP_PASSWORD',
});
props.hideLoading();
if (res.data.code == 200) {
showAlert(TYPE.SUCCESS, I18n.t('Notification'), res.data.message);
if (props.route.params.isFromTransaction) {
navigation.navigate(CONFIRMCREATEOTP, {
password: props.route.params.pre_otp,
password_confirmation: pinCode,
isFromTransaction: props.route.params.isFromTransaction,
setupSmartOTPSuccess: props.route.params.setupSmartOTPSuccess,
});
} else {
navigation.navigate(CONFIRMCREATEOTP, {
password: props.route.params.pre_otp,
password_confirmation: pinCode,
});
}
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message);
}
}
};
const onDeletePress = () => {
if (fourNumber) {
setFourNumber(null);
} else if (thirdNumber) {
setThirdNumber(null);
} else if (secondsNumber) {
setSecondsNumber(null);
} else if (firstNumber) {
setFirstNumber(null);
}
};
return (
<ConfirmSmartOTPView
firstNumber={firstNumber}
secondsNumber={secondsNumber}
thirdNumber={thirdNumber}
fourNumber={fourNumber}
onNumberPress={onNumberPress}
onDeletePress={onDeletePress}
/>
);
};
const mapStateToProps = (state) => {
return {
user: state.userReducer,
};
};
export default connect(mapStateToProps, {showLoading, hideLoading})(
ConfirmChangeSmartOTP,
);
import React from 'react';
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import HeaderBack from '../../../components/Header/HeaderBack';
import {getFontXD, HEIGHTXD, WIDTHXD} from '../../../Config/Functions';
import I18n from '../../../helper/i18/i18n';
import R from '../../../assets/R';
import Icon from 'react-native-vector-icons/FontAwesome5';
const ChangeSmartOTPView = (props) => {
return (
<View style={{flex: 1, colorBackground: R.colors.white}}>
<HeaderBack title={'ChangeSmartOTP'} />
<Text style={[styles.textNormal, {marginTop: HEIGHTXD(40)}]}>
{I18n.t('ConfirmSmartOTP')}
</Text>
<View style={[styles.rowNumber]}>
<View
style={[
styles.indicator,
{
backgroundColor: props.firstNumber
? R.colors.main
: R.colors.white,
},
]}
/>
<View
style={[
styles.indicator,
{
backgroundColor: props.secondsNumber
? R.colors.main
: R.colors.white,
},
]}
/>
<View
style={[
styles.indicator,
{
backgroundColor: props.thirdNumber
? R.colors.main
: R.colors.white,
},
]}
/>
<View
style={[
styles.indicator,
{
backgroundColor: props.fourNumber
? R.colors.main
: R.colors.white,
},
]}
/>
</View>
<View style={[styles.rowNumber, {marginTop: HEIGHTXD(80)}]}>
<TouchableOpacity
onPress={() => {
props.onNumberPress(1);
}}
style={styles.btnNumber}>
<Text style={styles.textNumber}>1</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(2);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>2</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(3);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>3</Text>
</TouchableOpacity>
</View>
<View style={styles.rowNumber}>
<TouchableOpacity
onPress={() => {
props.onNumberPress(4);
}}
style={styles.btnNumber}>
<Text style={styles.textNumber}>4</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(5);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>5</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(6);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>6</Text>
</TouchableOpacity>
</View>
<View style={styles.rowNumber}>
<TouchableOpacity
onPress={() => {
props.onNumberPress(7);
}}
style={styles.btnNumber}>
<Text style={styles.textNumber}>7</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(8);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>8</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(9);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>9</Text>
</TouchableOpacity>
</View>
<View style={styles.rowNumber}>
<TouchableOpacity
onPress={() => {
props.onNumberPress(0);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(300)}]}>
<Text style={styles.textNumber}>0</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onDeletePress();
}}
style={{
width: HEIGHTXD(260),
height: HEIGHTXD(260),
marginLeft: WIDTHXD(40),
justifyContent: 'center',
alignItems: 'center',
}}>
<Icon name={'backspace'} size={HEIGHTXD(80)} color={'#8E8C8C'} />
</TouchableOpacity>
</View>
</View>
);
};
export default ChangeSmartOTPView;
const styles = StyleSheet.create({
btnSend: {
height: HEIGHTXD(80),
justifyContent: 'center',
alignItems: 'center',
},
rowNumber: {
flexDirection: 'row',
justifyContent: 'center',
marginTop: HEIGHTXD(40),
},
btnNumber: {
height: HEIGHTXD(260),
width: HEIGHTXD(260),
justifyContent: 'center',
alignItems: 'center',
borderWidth: 0.3,
borderColor: R.colors.gray6,
borderRadius: HEIGHTXD(130),
},
indicator: {
height: HEIGHTXD(50),
width: HEIGHTXD(50),
borderWidth: 0.3,
borderColor: R.colors.gray6,
borderRadius: HEIGHTXD(35),
marginHorizontal: WIDTHXD(20),
},
textNormal: {
fontSize: getFontXD(39),
color: R.colors.black,
textAlign: 'center',
},
textNumber: {
fontSize: getFontXD(90),
color: R.colors.black,
textAlign: 'center',
},
txtSend: {
fontSize: getFontXD(42),
color: R.colors.main,
},
});
import React, {Component, useEffect, useState} from 'react';
import {
View,
Text,
TextInput,
StyleSheet,
TouchableOpacity,
Platform,
Alert,
} from 'react-native';
import HeaderBack from '../../../components/Header/HeaderBack';
import {
CodeField,
Cursor,
useBlurOnFulfill,
useClearByFocusCell,
} from 'react-native-confirmation-code-field';
import {
getFontXD,
HEIGHTXD,
WIDTHXD,
encryptRSAString,
} from '../../../Config/Functions';
import R from '../../../assets/R';
import {NEWPASSWORD, TABNAVIGATOR} from '../../../routers/ScreenNames';
import {
verifyOTPApi,
verifyStoreOTPApiSmart,
getOTPApiSmartOTP,
} from '../../../apis/Functions/users';
import {useNavigation} from '@react-navigation/native';
import I18n from '../../../helper/i18/i18n';
import AppText from '../../../components/AppText';
import {showLoading, hideLoading} from '../../../actions/loadingAction';
import {connect} from 'react-redux';
import {showAlert, TYPE} from '../../../components/DropdownAlert';
import CountDown from '../../../components/CountDown';
import {getOTPApi} from '../../../apis/Functions/users';
const CELL_COUNT = 4;
const ConfirmOTP = (propsa) => {
const [value, setValue] = useState('');
const [isReset, setReset] = useState(false);
const navigate = useNavigation();
const ref = useBlurOnFulfill({value, cellCount: CELL_COUNT});
const [props, getCellOnLayoutHandler] = useClearByFocusCell({
value,
setValue,
});
const getOTP = async () => {
propsa.showLoading();
const res = await getOTPApiSmartOTP({
platform: Platform.OS,
otp_by: propsa.user.email,
otp_password: '1234',
type: 'CREATE_OTP_PASSWORD',
});
propsa.hideLoading();
if (res.data.code == 200) {
setReset(!isReset);
showAlert(TYPE.SUCCESS, I18n.t('Notification'), res.data.message);
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message);
}
};
const confirm = async () => {
console.log(propsa.route.params);
if (!value) {
showAlert(TYPE.WARN, I18n.t('Notification'), I18n.t('EnterOTPRequest'));
} else if (value.length != 4) {
showAlert(TYPE.WARN, I18n.t('Notification'), I18n.t('OTPInvalid'));
} else {
propsa.showLoading();
const res = await verifyStoreOTPApiSmart({
platform: Platform.OS,
password: encryptRSAString(propsa.route.params.password),
password_confirmation: encryptRSAString(
propsa.route.params.password_confirmation,
),
otp: value,
type: 'CREATE_OTP_PASSWORD',
});
propsa.hideLoading();
if (res.data.code == 200) {
showAlert(TYPE.SUCCESS, I18n.t('Notification'), res.data.message);
if (propsa.route.params.isFromTransaction) {
propsa.route.params.setupSmartOTPSuccess();
} else {
navigate.navigate(TABNAVIGATOR);
}
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message);
}
}
};
return (
<View style={{flex: 1}}>
<HeaderBack title={'VerifyOTP'} />
<View style={styles.container}>
<View style={{height: 20}} />
<View style={styles.wrap}>
<AppText i18nKey={'Verify_code'} style={styles.txtTitle} />
<View style={styles.containerCode}>
<CodeField
ref={ref}
{...props}
value={value}
onChangeText={setValue}
cellCount={CELL_COUNT}
rootStyle={styles.codeFieldRoot}
keyboardType="number-pad"
textContentType="oneTimeCode"
renderCell={({index, symbol, isFocused}) => (
<View
onLayout={getCellOnLayoutHandler(index)}
key={index}
style={[styles.cellRoot, isFocused && styles.focusCell]}>
<Text style={styles.cellText}>
{symbol || (isFocused ? <Cursor /> : null)}
</Text>
</View>
)}
/>
</View>
</View>
</View>
<View style={styles.footer}>
<TouchableOpacity onPress={confirm} style={styles.btn}>
<AppText i18nKey={'Continue'} style={styles.txtBtn} />
</TouchableOpacity>
<TouchableOpacity style={styles.wrapFooter} onPress={getOTP}>
<Text style={styles.txtNote}>{I18n.t('OTPValidFiveMinute')}</Text>
<AppText i18nKey={'Re_send'} style={styles.txtSend} />
</TouchableOpacity>
<CountDown isReset={isReset} />
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingVertical: 20,
},
footer: {
height: 200,
justifyContent: 'center',
alignItems: 'center',
},
wrap: {
flex: 1,
paddingTop: 30,
alignItems: 'center',
width: '100%',
paddingHorizontal: 50,
},
containerCode: {
height: 50,
width: '100%',
marginTop: 30,
},
codeFieldRoot: {
marginTop: 20,
},
focusCell: {
borderColor: '#000',
},
cellRoot: {
width: 40,
height: 40,
justifyContent: 'center',
alignItems: 'center',
borderBottomColor: '#ccc',
borderBottomWidth: 1,
},
cellText: {
color: '#000',
fontSize: 36,
textAlign: 'center',
},
focusCell: {
borderBottomColor: '#007AFF',
borderBottomWidth: 2,
},
txtTitle: {
fontSize: getFontXD(52),
color: '#979797',
},
btn: {
width: WIDTHXD(521),
height: HEIGHTXD(120),
borderRadius: 15,
backgroundColor: '#1C6AF6',
justifyContent: 'center',
alignItems: 'center',
},
txtBtn: {
color: R.colors.white,
fontSize: getFontXD(52),
textTransform: 'uppercase',
},
txtSend: {
fontSize: getFontXD(42),
color: '#1C6AF6',
},
wrapFooter: {
marginTop: 30,
flexDirection: 'row',
alignItems: 'center',
},
txtNote: {
color: '#A2A2A2',
fontSize: getFontXD(42),
fontStyle: 'italic',
},
});
const mapStateToProps = (state) => {
return {user: state.userReducer};
};
export default connect(mapStateToProps, {showLoading, hideLoading})(ConfirmOTP);
import React from 'react';
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import HeaderBack from '../../../components/Header/HeaderBack';
import {getFontXD, HEIGHTXD, WIDTHXD} from '../../../Config/Functions';
import I18n from '../../../helper/i18/i18n';
import R from '../../../assets/R';
import Icon from 'react-native-vector-icons/FontAwesome5';
const ChangeSmartOTPView = (props) => {
return (
<View style={{flex: 1, colorBackground: R.colors.white}}>
<HeaderBack title={'OTP'} />
<Text style={[styles.textNormal, {marginTop: HEIGHTXD(40)}]}>
{I18n.t('EnterOTPRequest')}
</Text>
<View style={[styles.rowNumber]}>
<View
style={[
styles.indicator,
{
backgroundColor: props.firstNumber
? R.colors.main
: R.colors.white,
},
]}
/>
<View
style={[
styles.indicator,
{
backgroundColor: props.secondsNumber
? R.colors.main
: R.colors.white,
},
]}
/>
<View
style={[
styles.indicator,
{
backgroundColor: props.thirdNumber
? R.colors.main
: R.colors.white,
},
]}
/>
<View
style={[
styles.indicator,
{
backgroundColor: props.fourNumber
? R.colors.main
: R.colors.white,
},
]}
/>
</View>
<View style={[styles.rowNumber, {marginTop: HEIGHTXD(80)}]}>
<TouchableOpacity
onPress={() => {
props.onNumberPress(1);
}}
style={styles.btnNumber}>
<Text style={styles.textNumber}>1</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(2);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>2</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(3);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>3</Text>
</TouchableOpacity>
</View>
<View style={styles.rowNumber}>
<TouchableOpacity
onPress={() => {
props.onNumberPress(4);
}}
style={styles.btnNumber}>
<Text style={styles.textNumber}>4</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(5);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>5</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(6);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>6</Text>
</TouchableOpacity>
</View>
<View style={styles.rowNumber}>
<TouchableOpacity
onPress={() => {
props.onNumberPress(7);
}}
style={styles.btnNumber}>
<Text style={styles.textNumber}>7</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(8);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>8</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onNumberPress(9);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>9</Text>
</TouchableOpacity>
</View>
<View style={styles.rowNumber}>
<TouchableOpacity
onPress={() => {
props.onNumberPress(0);
}}
style={[styles.btnNumber, {marginLeft: WIDTHXD(300)}]}>
<Text style={styles.textNumber}>0</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
props.onDeletePress();
}}
style={{
width: HEIGHTXD(260),
height: HEIGHTXD(260),
marginLeft: WIDTHXD(40),
justifyContent: 'center',
alignItems: 'center',
}}>
<Icon name={'backspace'} size={HEIGHTXD(80)} color={'#8E8C8C'} />
</TouchableOpacity>
</View>
</View>
);
};
export default ChangeSmartOTPView;
const styles = StyleSheet.create({
btnSend: {
height: HEIGHTXD(80),
justifyContent: 'center',
alignItems: 'center',
},
rowNumber: {
flexDirection: 'row',
justifyContent: 'center',
marginTop: HEIGHTXD(40),
},
btnNumber: {
height: HEIGHTXD(260),
width: HEIGHTXD(260),
justifyContent: 'center',
alignItems: 'center',
borderWidth: 0.3,
borderColor: R.colors.gray6,
borderRadius: HEIGHTXD(130),
},
indicator: {
height: HEIGHTXD(50),
width: HEIGHTXD(50),
borderWidth: 0.3,
borderColor: R.colors.gray6,
borderRadius: HEIGHTXD(35),
marginHorizontal: WIDTHXD(20),
},
textNormal: {
fontSize: getFontXD(39),
color: R.colors.black,
textAlign: 'center',
},
textNumber: {
fontSize: getFontXD(90),
color: R.colors.black,
textAlign: 'center',
},
txtSend: {
fontSize: getFontXD(42),
color: R.colors.main,
},
});
import React, {useState} from 'react';
import {View, Text, StyleSheet, TouchableOpacity, Platform} from 'react-native';
import HeaderBack from '../../components/Header/HeaderBack';
import {
CodeField,
Cursor,
useBlurOnFulfill,
useClearByFocusCell,
} from 'react-native-confirmation-code-field';
import {getFontXD, HEIGHTXD, WIDTHXD} from '../../Config/Functions';
import R from '../../assets/R';
import {TABNAVIGATOR} from '../../routers/ScreenNames';
import {useNavigation} from '@react-navigation/native';
import I18n from '../../helper/i18/i18n';
import AppText from '../../components/AppText';
import {showLoading, hideLoading} from '../../actions/loadingAction';
import {connect} from 'react-redux';
import {showAlert, TYPE} from '../../components/DropdownAlert';
import CountDown from '../../components/CountDown';
import {
verifyStoreOTPApiSmart,
getOTPApiSmartOTP,
} from '../../apis/Functions/users';
import {encryptRSAString} from '../../Config/Functions';
const CELL_COUNT = 4;
const ConfirmOTPSmart = (propsa) => {
const [value, setValue] = useState('');
const [isReset, setReset] = useState(false);
const navigate = useNavigation();
const ref = useBlurOnFulfill({value, cellCount: CELL_COUNT});
const [props, getCellOnLayoutHandler] = useClearByFocusCell({
value,
setValue,
});
const getOTP = async () => {
propsa.showLoading();
const res = await getOTPApiSmartOTP({
platform: Platform.OS,
otp_by: propsa.user.email,
otp_password: '1234',
type: 'CREATE_OTP_PASSWORD',
});
propsa.hideLoading();
if (res.data.code == 200) {
setReset(!isReset);
showAlert(TYPE.SUCCESS, I18n.t('Notification'), res.data.message);
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message);
}
};
const confirm = async () => {
if (!value) {
showAlert(TYPE.WARN, I18n.t('Notification'), I18n.t('EnterOTPRequest'));
} else if (value.length != 4) {
showAlert(TYPE.WARN, I18n.t('Notification'), I18n.t('OTPInvalid'));
} else {
propsa.showLoading();
const res = await verifyStoreOTPApiSmart({
platform: Platform.OS,
password: encryptRSAString(propsa.route.params.password),
password_confirmation: encryptRSAString(
propsa.route.params.password_confirmation,
),
otp: value,
type: 'CREATE_OTP_PASSWORD',
});
showAlert(TYPE.SUCCESS, I18n.t('Notification'), res.data.message);
propsa.hideLoading();
if (res.data.code == 200) {
if (propsa.route.params.isFromTransaction) {
propsa.route.params.setupSmartOTPSuccess();
} else {
navigate.navigate(TABNAVIGATOR);
}
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message);
}
}
};
return (
<View style={{flex: 1}}>
<HeaderBack title={'VerifyOTP'} />
<View style={styles.container}>
<View style={{height: 20}} />
<View style={styles.wrap}>
<AppText i18nKey={'Verify_code'} style={styles.txtTitle} />
<View style={styles.containerCode}>
<CodeField
ref={ref}
{...props}
value={value}
onChangeText={setValue}
cellCount={CELL_COUNT}
rootStyle={styles.codeFieldRoot}
keyboardType="number-pad"
textContentType="oneTimeCode"
renderCell={({index, symbol, isFocused}) => (
<View
onLayout={getCellOnLayoutHandler(index)}
key={index}
style={[styles.cellRoot, isFocused && styles.focusCell]}>
<Text style={styles.cellText}>
{symbol || (isFocused ? <Cursor /> : null)}
</Text>
</View>
)}
/>
</View>
</View>
</View>
<View style={styles.footer}>
<TouchableOpacity onPress={confirm} style={styles.btn}>
<AppText i18nKey={'Continue'} style={styles.txtBtn} />
</TouchableOpacity>
<TouchableOpacity style={styles.wrapFooter} onPress={getOTP}>
<Text style={styles.txtNote}>{I18n.t('OTPValidFiveMinute')}</Text>
<AppText i18nKey={'Re_send'} style={styles.txtSend} />
</TouchableOpacity>
<CountDown isReset={isReset} />
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingVertical: 20,
},
footer: {
height: 200,
justifyContent: 'center',
alignItems: 'center',
},
wrap: {
flex: 1,
paddingTop: 30,
alignItems: 'center',
width: '100%',
paddingHorizontal: 50,
},
containerCode: {
height: 50,
width: '100%',
marginTop: 30,
},
codeFieldRoot: {
marginTop: 20,
},
focusCell: {
borderColor: '#000',
},
cellRoot: {
width: 40,
height: 40,
justifyContent: 'center',
alignItems: 'center',
borderBottomColor: '#ccc',
borderBottomWidth: 1,
},
cellText: {
color: '#000',
fontSize: 36,
textAlign: 'center',
},
focusCell: {
borderBottomColor: '#007AFF',
borderBottomWidth: 2,
},
txtTitle: {
fontSize: getFontXD(52),
color: '#979797',
},
btn: {
width: WIDTHXD(521),
height: HEIGHTXD(120),
borderRadius: 15,
backgroundColor: '#1C6AF6',
justifyContent: 'center',
alignItems: 'center',
},
txtBtn: {
color: R.colors.white,
fontSize: getFontXD(52),
textTransform: 'uppercase',
},
txtSend: {
fontSize: getFontXD(42),
color: '#1C6AF6',
},
wrapFooter: {
marginTop: 30,
flexDirection: 'row',
alignItems: 'center',
},
txtNote: {
color: '#A2A2A2',
fontSize: getFontXD(42),
fontStyle: 'italic',
},
});
const mapStateToProps = (state) => {
return {
user: state.userReducer,
};
};
export default connect(mapStateToProps, {showLoading, hideLoading})(
ConfirmOTPSmart,
);
import React, {useState, useEffect} from 'react';
import EnterPasswordSmartOTPView from './EnterPasswordSmartOTPView';
import {getOTPApiSmartOTP, verifyOTPApiSmart} from '../../apis/Functions/users';
import {showAlert, TYPE} from '../../components/DropdownAlert';
import I18n from '../../helper/i18/i18n';
import {connect} from 'react-redux';
import {hideLoading, showLoading} from '../../actions/loadingAction';
import {OTP_TYPE} from '../../Config/constants';
import {useNavigation} from '@react-navigation/native';
import {RESET_SMART_OTP, CHANGESMARTOTP} from '../../routers/ScreenNames';
import {decryptRSAString, encryptRSAString} from '../../Config/Functions';
const EnterPasswordSmartOTP = (props) => {
const navigation = useNavigation();
const [firstNumber, setFirstNumber] = useState(null);
const [secondsNumber, setSecondsNumber] = useState(null);
const [thirdNumber, setThirdNumber] = useState(null);
const [fourNumber, setFourNumber] = useState(null);
useEffect(() => {
if (fourNumber) {
onCheckPINSmartOTPPin();
}
}, [fourNumber]);
const onNumberPress = (number) => {
if (!firstNumber) {
setFirstNumber(number.toString());
} else if (!secondsNumber) {
setSecondsNumber(number.toString());
} else if (!thirdNumber) {
setThirdNumber(number.toString());
} else if (!fourNumber) {
setFourNumber(number.toString());
}
};
const onCheckPINSmartOTPPin = async () => {
let pinCode = `${firstNumber}${secondsNumber}${thirdNumber}${fourNumber}`;
props.showLoading();
if (props.route.params.type == 'CHANGE_SMART_OTP') {
const res = await verifyOTPApiSmart({
platform: Platform.OS,
otp_password: encryptRSAString(pinCode),
type: 'VERIFY_OTP_PASSWORD',
});
if (res.data.code == 200) {
navigation.navigate(CHANGESMARTOTP, {
old_password: encryptRSAString(pinCode),
TYPE: 'CHANGE_SMART_OTP',
});
clearPIN();
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message);
clearPIN();
}
} else {
props.showLoading();
const res = await getOTPApiSmartOTP({
platform: Platform.OS,
otp_by: props.user.email,
otp_password: encryptRSAString(pinCode),
type:
props.route.params.type == 'DEPOSIT'
? OTP_TYPE.CUSTOMER_REQUEST_DEPOSIT
: OTP_TYPE.REQUEST_WITHDRAW,
});
props.hideLoading();
if (res.data.code == 200) {
props.route.params.onGoToSmartOTP(
pinCode,
decryptRSAString(res.data.data.otp),
);
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message);
clearPIN();
}
}
props.hideLoading();
};
const clearPIN = () => {
setFirstNumber(null);
setSecondsNumber(null);
setThirdNumber(null);
setFourNumber(null);
};
const onDeletePress = () => {
if (fourNumber) {
setFourNumber(null);
} else if (thirdNumber) {
setThirdNumber(null);
} else if (secondsNumber) {
setSecondsNumber(null);
} else if (firstNumber) {
setFirstNumber(null);
}
};
const onReactivationSmartOTP = () => {
navigation.navigate(RESET_SMART_OTP, {title: 'ReactivationSmartOTP'});
};
const onForgotPINCode = () => {
navigation.navigate(RESET_SMART_OTP, {title: 'ForgotSmartOTP'});
};
return (
<EnterPasswordSmartOTPView
firstNumber={firstNumber}
secondsNumber={secondsNumber}
thirdNumber={thirdNumber}
fourNumber={fourNumber}
onNumberPress={onNumberPress}
onDeletePress={onDeletePress}
onForgotPINCode={onForgotPINCode}
onReactivationSmartOTP={onReactivationSmartOTP}
/>
);
};
const mapStateToProps = (state) => {
return {
user: state.userReducer,
};
};
export default connect(mapStateToProps, {showLoading, hideLoading})(
EnterPasswordSmartOTP,
);
import React from 'react';
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import HeaderBack from '../../components/Header/HeaderBack';
import {getFontXD, HEIGHTXD, WIDTHXD} from '../../Config/Functions';
import I18n from '../../helper/i18/i18n';
import R from '../../assets/R';
import Icon from 'react-native-vector-icons/FontAwesome5';
const EnterPasswordSmartOTPView = (props) => {
return <View style={{flex: 1, colorBackground: R.colors.white}}>
<HeaderBack title={'SmartOTP'}/>
<Text style={[styles.textNormal, {marginTop: HEIGHTXD(40)}]}>
{I18n.t('EnterSmartOTPPIN')}
</Text>
<View style={[styles.rowNumber]}>
<View style={[styles.indicator, {backgroundColor: props.firstNumber? R.colors.main : R.colors.white}]}/>
<View style={[styles.indicator, {backgroundColor: props.secondsNumber? R.colors.main : R.colors.white}]}/>
<View style={[styles.indicator, {backgroundColor: props.thirdNumber? R.colors.main : R.colors.white}]}/>
<View style={[styles.indicator, {backgroundColor: props.fourNumber? R.colors.main : R.colors.white}]}/>
</View>
<View style={[styles.rowNumber, {marginTop: HEIGHTXD(80)}]}>
<TouchableOpacity onPress={() => {
props.onNumberPress(1);
}} style={styles.btnNumber}>
<Text style={styles.textNumber}>1</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
props.onNumberPress(2);
}} style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>2</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
props.onNumberPress(3);
}} style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>3</Text>
</TouchableOpacity>
</View>
<View style={styles.rowNumber}>
<TouchableOpacity onPress={() => {
props.onNumberPress(4);
}} style={styles.btnNumber}>
<Text style={styles.textNumber}>4</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
props.onNumberPress(5);
}} style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>5</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
props.onNumberPress(6);
}} style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>6</Text>
</TouchableOpacity>
</View>
<View style={styles.rowNumber}>
<TouchableOpacity onPress={() => {
props.onNumberPress(7);
}} style={styles.btnNumber}>
<Text style={styles.textNumber}>7</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
props.onNumberPress(8);
}} style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>8</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
props.onNumberPress(9);
}} style={[styles.btnNumber, {marginLeft: WIDTHXD(40)}]}>
<Text style={styles.textNumber}>9</Text>
</TouchableOpacity>
</View>
<View style={styles.rowNumber}>
<TouchableOpacity onPress={() => {
props.onNumberPress(0);
}} style={[styles.btnNumber, {marginLeft: WIDTHXD(300)}]}>
<Text style={styles.textNumber}>0</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
props.onDeletePress();
}} style={{
width: HEIGHTXD(260), height: HEIGHTXD(260), marginLeft: WIDTHXD(40), justifyContent: 'center',
alignItems: 'center',
}}>
<Icon name={'backspace'} size={HEIGHTXD(80)} color={'#8E8C8C'}/>
</TouchableOpacity>
</View>
<View style={{
width: '100%',
position: 'absolute',
bottom: HEIGHTXD(30),
justifyContent: 'center',
paddingVertical: HEIGHTXD(30),
paddingHorizontal: HEIGHTXD(30),
}}>
<TouchableOpacity onPress={() => {
props.onForgotPINCode();
}} style={styles.btnSend}>
<Text style={styles.textSmall}>{I18n.t('ForgotPINCode')}</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
props.onReactivationSmartOTP();
}} style={styles.btnSend}>
<Text style={styles.txtSend}>{I18n.t('ReactivationSmartOTP')}</Text>
</TouchableOpacity>
</View>
</View>;
};
export default EnterPasswordSmartOTPView;
const styles = StyleSheet.create({
btnSend: {
height: HEIGHTXD(80),
justifyContent: 'center',
alignItems: 'center',
},
rowNumber: {
flexDirection: 'row',
justifyContent: 'center',
marginTop: HEIGHTXD(40),
},
btnNumber: {
height: HEIGHTXD(260),
width: HEIGHTXD(260),
justifyContent: 'center',
alignItems: 'center',
borderWidth: 0.3,
borderColor: R.colors.gray6,
borderRadius: HEIGHTXD(130),
},
indicator: {
height: HEIGHTXD(50),
width: HEIGHTXD(50),
borderWidth: 0.3,
borderColor: R.colors.gray6,
borderRadius: HEIGHTXD(35),
marginHorizontal: WIDTHXD(20),
},
textNormal: {
fontSize: getFontXD(39),
color: R.colors.black,
textAlign: 'center',
},
textNumber: {
fontSize: getFontXD(90),
color: R.colors.black,
textAlign: 'center',
},
txtSend: {
fontSize: getFontXD(42),
color: R.colors.main,
},
});
import React from 'react';
import ResetSmartOTPView from './ResetSmartOTPView';
import {connect} from 'react-redux';
const ResetSmartOTP = (props) => {
return <ResetSmartOTPView
title={props.route.params.title}
companyInfo={props.user.company_info}/>;
};
const mapStateToProps = (state) => {
return {
user: state.userReducer,
};
};
export default connect(mapStateToProps, {})(
ResetSmartOTP,
);
import React, {useEffect, useState} from 'react';
import {Linking, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import HeaderBack from '../../components/Header/HeaderBack';
import AppText from '../../components/AppText';
import {getFontXD, HEIGHTXD, WIDTHXD, callNumber} from '../../Config/Functions';
import R from '../../assets/R';
import I18n from '../../helper/i18/i18n';
const ResetSmartOTPView = (props) => {
const [reRender, setReRender] = useState(false);
useEffect(() => {
setReRender(!reRender);
}, [props.companyInfo]);
return <View style={{flex: 1}}>
<HeaderBack title={props.title}/>
<View
style={{
flex: 1,
paddingHorizontal: WIDTHXD(50),
paddingTop: HEIGHTXD(40),
}}>
<Text>
<AppText i18nKey={'ResetSmartOTP'} style={styles.title}/>
<Text style={[styles.txtContent, {color: R.colors.main}]}
onPress={() => callNumber(props.companyInfo?.hotline_call)}>
{props.companyInfo?.hotline}
</Text>
<AppText i18nKey={'ResetSmartOTP2'} style={styles.title}/>
</Text>
<AppText i18nKey={'HaNoiOffice'} style={[styles.title, {color: R.colors.main, marginTop: HEIGHTXD(30)}]}/>
<Text style={styles.txtContent}>{props.companyInfo?.name}</Text>
<Text style={styles.txtContent}>{`${I18n.t('Address')} ${props.companyInfo?.address}`}</Text>
<View style={styles.row}>
<Text style={styles.title}>Email:</Text>
<TouchableOpacity
onPress={async () => {
const supported = await Linking.openURL(`mailto:${props.companyInfo?.email}`);
if (supported) {
Linking.openURL(`mailto:${props.companyInfo?.email}`);
}
}}>
<Text style={styles.txtLink}> {props.companyInfo?.email}</Text>
</TouchableOpacity>
</View>
<TouchableOpacity
onPress={async () => {
const supported = await Linking.canOpenURL(props.companyInfo?.website);
if (supported) {
Linking.openURL(props.companyInfo?.website);
}
}}>
<View style={styles.row}>
<Text style={styles.title}>Website: </Text>
<Text style={styles.txtLink}>{props.companyInfo?.website}</Text>
</View>
</TouchableOpacity>
</View>
</View>;
};
const styles = StyleSheet.create({
title: {
fontSize: getFontXD(42),
color: R.colors.black,
marginTop: 5,
},
txtContent: {
fontSize: getFontXD(42),
marginTop: 5,
},
txtLink: {
fontSize: getFontXD(42),
marginTop: 5,
textDecorationLine: 'underline',
color: R.colors.main,
},
row: {
flexDirection: 'row',
},
});
export default ResetSmartOTPView;
import React, {Component, useState} from 'react';
import {View, Text} from 'react-native';
import {CONFIRMOTPSMART} from '../../routers/ScreenNames';
import {useNavigation} from '@react-navigation/native';
import HeaderBack from '../../components/Header/HeaderBack';
import AppText from '../../components/AppText';
import TextField from '../../components/Input/TextField';
import Button from '../../components/Button';
import {connect} from 'react-redux';
import {
getFontXD,
HEIGHTXD,
WIDTHXD,
checkFormatArray,
} from '../../Config/Functions';
import R from '../../assets/R';
import {getOTPApiSmartOTP} from '../../apis/Functions/users';
import {showLoading, hideLoading} from '../../actions/loadingAction';
import I18n from '../../helper/i18/i18n';
import {TYPE, showAlert} from '../../components/DropdownAlert/index';
const SettingOTP = (props) => {
const navigatiton = useNavigation();
const [password, setPassword] = useState('');
const [password_confirmation, setPassword_confirmation] = useState('');
const getOTP = async () => {
const titles = [
I18n.t('PassGetSmartOTP'),
I18n.t('ConfirmPassGetSmartOTP'),
];
const index = checkFormatArray([password, password_confirmation]);
if (index === true) {
if (password == password_confirmation) {
props.showLoading();
const res = await getOTPApiSmartOTP({
platform: Platform.OS,
otp_by: props.user.email,
otp_password: '1234',
type: 'CREATE_OTP_PASSWORD',
});
props.hideLoading();
if (res.data.code == 200) {
showAlert(TYPE.SUCCESS, I18n.t('Notification'), res.data.message);
navigatiton.navigate(CONFIRMOTPSMART, {
password,
password_confirmation,
isFromTransaction: props.route.params.isFromTransaction,
setupSmartOTPSuccess: props.route.params.setupSmartOTPSuccess
});
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message);
}
} else {
showAlert(
TYPE.WARN,
I18n.t('Notification'),
'Mật khẩu không trùng nhau!',
);
}
} else {
showAlert(
TYPE.WARN,
I18n.t('Notification'),
I18n.t('Please_fill_in') + titles[index],
);
}
};
return (
<View style={{flex: 1}}>
<HeaderBack title={'SettingOTP'} />
<View style={{flex: 1, marginHorizontal: 10, marginTop: 20}}>
<View style={{flex: 1}}>
<TextField
onChangeText={(val) => setPassword(val)}
maxLength={4}
isNumber={true}
title={
props.language.language == 'vi'
? 'Mật khẩu lấy Smart OTP'
: I18n.t('PassGetSmartOTP')
}
isPassWord={true}
/>
<TextField
maxLength={4}
isNumber={true}
isPassWord={true}
onChangeText={(val) => setPassword_confirmation(val)}
title={
props.language.language == 'vi'
? 'Xác nhận mật khẩu lấy Smart OTP'
: I18n.t('ConfirmPassGetSmartOTP')
}
/>
</View>
<View>
<Button onClick={getOTP} title={'Xác nhận'} />
</View>
</View>
</View>
);
};
const mapStateToProps = (state) => {
return {
user: state.userReducer,
language: state.languageReducer,
};
};
export default connect(mapStateToProps, {showLoading, hideLoading})(SettingOTP);
import React, {useState, useEffect} from 'react';
import SmartOTPView from './SmartOTPView';
import {showAlert, TYPE} from '../../components/DropdownAlert';
import I18n from '../../helper/i18/i18n';
import {getOTPApiSmartOTP, verifyOTPApi} from '../../apis/Functions/users';
import {Platform} from 'react-native';
import {walletDeposit} from '../../apis/Functions/Deposit';
import {widthDraw} from '../../apis/Functions/Widthdraw';
import {TABNAVIGATOR} from '../../routers/ScreenNames';
import {connect} from 'react-redux';
import {hideLoading, showLoading} from '../../actions/loadingAction';
import {OTP_TYPE} from '../../Config/constants';
import {useNavigation} from '@react-navigation/native';
import {encryptRSAString, decryptRSAString} from '../../Config/Functions';
const SmartOTP = (props) => {
const [value, setValue] = useState(props.route.params.otp);
const [progress, setProgress] = useState(1);
const [isReset, setReset] = useState(false);
const navigate = useNavigation();
useEffect(() => {
setValue(props.route.params.otp);
}, [props.route.params.otp]);
const confirm = async () => {
if (!value) {
showAlert(TYPE.WARN, I18n.t('Notification'), I18n.t('EnterOTPRequest'));
} else if (value.length != 4) {
showAlert(TYPE.WARN, I18n.t('Notification'), I18n.t('OTPInvalid'));
} else {
props.showLoading();
let res1 = await verifyOTPApi({
platform: Platform.OS,
receiver_name: props.user.email,
otp: encryptRSAString(value),
type:
props.route.params.type == 'DEPOSIT'
? OTP_TYPE.CUSTOMER_REQUEST_DEPOSIT
: OTP_TYPE.REQUEST_WITHDRAW,
});
if (res1.data.code == 200) {
let res;
if (props.route.params.type == 'DEPOSIT') {
const {amount, notes} = props.route.params;
res = await walletDeposit({
amount,
platform: Platform.OS,
notes,
fee: 0,
otp: encryptRSAString(value),
});
} else {
const {src, receiving_account, amount, notes} = props.route.params;
res = await widthDraw({
src,
receiving_account,
amount,
platform: Platform.OS,
notes,
fee: 0,
otp: encryptRSAString(value),
});
}
props.hideLoading();
if (res.data.code == 200) {
setTimeout(() => {
showAlert(TYPE.SUCCESS, I18n.t('Notification'), res.data.message);
navigate.navigate(TABNAVIGATOR);
}, 500);
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message);
}
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res1.data.message);
}
props.hideLoading();
}
};
const getNewOTP = async () => {
props.showLoading();
const res = await getOTPApiSmartOTP({
platform: Platform.OS,
otp_by: props.user.email,
otp_password: encryptRSAString(props.route.params.pinCode),
type:
props.route.params.type == 'DEPOSIT'
? OTP_TYPE.CUSTOMER_REQUEST_DEPOSIT
: OTP_TYPE.REQUEST_WITHDRAW,
});
if (res.data.code == 200) {
setValue(decryptRSAString(res.data.data.otp));
setReset(!isReset);
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message);
}
props.hideLoading();
};
const updateProgress = (count) => {
setProgress(count > 0 ? count / 300 : 0);
};
return (
<SmartOTPView
value={value}
progress={progress}
confirm={confirm}
isReset={isReset}
getNewOTP={getNewOTP}
updateProgress={updateProgress}
setValue={setValue}
/>
);
};
const mapStateToProps = (state) => {
return {
user: state.userReducer,
};
};
export default connect(mapStateToProps, {showLoading, hideLoading})(SmartOTP);
import React, {Component} from 'react';
import {View, Text, StyleSheet, Image, TouchableOpacity} from 'react-native';
import HeaderBack from '../../components/Header/HeaderBack';
import I18n from '../../helper/i18/i18n';
import AppText from '../../components/AppText';
import {
UPDATEOTP,
ENTER_PASSWORD_SMART_OTP,
SETTINGOTP,
FAQSSMARTOTP,
RULESSMARTOTP,
} from '../../routers/ScreenNames';
import R from '../../assets/R';
import Icon from 'react-native-vector-icons/AntDesign';
import {HEIGHTXD, WIDTHXD} from '../../Config/Functions';
import {useNavigation} from '@react-navigation/native';
import {connect} from 'react-redux';
const SmartOTPConfig = (props) => {
const navigation = useNavigation();
console.log(props.user);
return (
<View style={{flex: 1}}>
<HeaderBack title={'SettingOTP'} />
<View style={{marginVertical: 20, backgroundColor: 'white'}}>
{props.user.smart_otp_status ? (
<TouchableOpacity
onPress={() =>
navigation.navigate(ENTER_PASSWORD_SMART_OTP, {
type: 'CHANGE_SMART_OTP',
})
}
style={styles.container}>
<Image style={styles.imgIcon} source={R.images.changeSmart} />
<View style={{flex: 1, justifyContent: 'center'}}>
<AppText i18nKey={'ChangeSmartOTP'} />
</View>
<Icon name={'right'} size={20} color={R.colors.color777} />
</TouchableOpacity>
) : null}
<TouchableOpacity
onPress={() => navigation.navigate(RULESSMARTOTP)}
style={styles.container}>
<Image style={styles.imgIcon} source={R.images.rules} />
<View style={{flex: 1, justifyContent: 'center'}}>
<AppText i18nKey={'Rules'} />
</View>
<Icon name={'right'} size={20} color={R.colors.color777} />
</TouchableOpacity>
<TouchableOpacity
onPress={() => navigation.navigate(FAQSSMARTOTP)}
style={styles.container}>
<Image style={styles.imgIcon} source={R.images.faq} />
<View style={{flex: 1, justifyContent: 'center'}}>
<AppText i18nKey={'FAQs'} />
</View>
<Icon name={'right'} size={20} color={R.colors.color777} />
</TouchableOpacity>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 10,
paddingVertical: 10,
borderBottomColor: R.colors.borderGray,
borderBottomWidth: 0.6,
},
imgIcon: {
width: WIDTHXD(62),
height: WIDTHXD(62),
resizeMode: 'contain',
marginRight: 10,
},
});
const mapStateToProps = (state) => {
return {
user: state.userReducer,
};
};
export default connect(mapStateToProps, {})(SmartOTPConfig);
import React from 'react';
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import HeaderBack from '../../components/Header/HeaderBack';
import I18n from '../../helper/i18/i18n';
import {getFontXD, getWidth, HEIGHTXD, WIDTHXD} from '../../Config/Functions';
import R from '../../assets/R';
import * as Progress from 'react-native-progress';
import CountDown from '../../components/CountDown';
const SmartOTPView = (props) => {
return <View style={{flex: 1}}>
<HeaderBack title={'SmartOTP'}/>
<View style={styles.viewOTP}>
<Progress.Bar progress={props.progress}
width={getWidth() - HEIGHTXD(160)}
height={HEIGHTXD(15)}
color={R.colors.main}
backgroundColor={R.colors.white}
borderWidth={0}
borderRadius={10}
/>
<Text style={{marginTop: HEIGHTXD(40)}}>
<Text style={[styles.textNormal]}>
{I18n.t('OTPWillAutoUpdate')}
</Text>
<CountDown isReset={props.isReset} isFromSmartOTP={true} autoRefress={() => props.getNewOTP() } updateProgress={(count) => {props.updateProgress(count)}}/>
</Text>
<Text style={styles.textOTP}>
{props.value}
</Text>
<Text style={[styles.textNormal, {
width: '100%',
backgroundColor: R.colors.colorOrangeLight,
paddingVertical: HEIGHTXD(30),
color: R.colors.brown,
}]}>
{I18n.t('SmartOTPWarning')}
</Text>
</View>
{/*<View style={{*/}
{/* flexDirection: 'row',*/}
{/* marginHorizontal: HEIGHTXD(40),*/}
{/*}}>*/}
{/* <Text style={[styles.textNormal, {*/}
{/* color: R.colors.main,*/}
{/* }]}>*/}
{/* Serial: 5324535436456576*/}
{/* </Text>*/}
{/* <Text style={[styles.textNormal, {*/}
{/* color: R.colors.main, position: 'absolute',*/}
{/* right: HEIGHTXD(0),*/}
{/* }]}>*/}
{/* {props.time}*/}
{/* </Text>*/}
{/*</View>*/}
<View style={{
marginHorizontal: HEIGHTXD(40),
marginVertical: HEIGHTXD(40),
}}>
<Text style={[styles.textNormal, {textAlign: 'left'}]}>{I18n.t('SmartOTPUsingFor')}</Text>
<Text style={[styles.textNormal, {
textAlign: 'left',
marginTop: HEIGHTXD(20),
}]}>{I18n.t('SmartOTPUsingForFirst')}</Text>
<Text style={[styles.textNormal, {
textAlign: 'left',
marginTop: HEIGHTXD(20),
}]}>{I18n.t('SmartOTPUsingForSecond')}</Text>
<Text style={[styles.textNormal, {
textAlign: 'left',
marginTop: HEIGHTXD(20),
}]}>{I18n.t('SmartOTPUsingForThird')}</Text>
</View>
<View style={{
width: '100%',
backgroundColor: R.colors.white,
position: 'absolute',
bottom: HEIGHTXD(0),
justifyContent: 'center',
paddingVertical: HEIGHTXD(30),
paddingHorizontal: HEIGHTXD(30),
}}>
<Text style={styles.textSmall}>
{I18n.t('OTPWillAutoFill')}
</Text>
<View
style={{
paddingVertical: 10,
justifyContent: 'center',
alignItems: 'center',
}}>
<TouchableOpacity onPress={() => {
props.confirm();
}} style={styles.btnSend}>
<Text style={styles.txtSend}>{I18n.t('ConfirmTransaction')}</Text>
</TouchableOpacity>
</View>
</View>
</View>;
};
const styles = StyleSheet.create({
viewOTP: {
width: getWidth() - HEIGHTXD(80),
backgroundColor: R.colors.white,
borderRadius: 8,
justifyContent: 'center',
alignItems: 'center',
marginVertical: HEIGHTXD(40),
marginHorizontal: HEIGHTXD(40),
padding: WIDTHXD(40),
borderColor: R.colors.gray1,
borderWidth: 0.3,
},
btnSend: {
width: '100%',
height: HEIGHTXD(120),
backgroundColor: R.colors.main,
borderRadius: 8,
justifyContent: 'center',
alignItems: 'center',
},
txtSend: {
fontSize: getFontXD(42),
color: R.colors.white,
paddingHorizontal: WIDTHXD(60),
fontWeight: 'bold',
},
textSmall: {
fontSize: getFontXD(32),
color: R.colors.color777,
marginBottom: 5,
textAlign: 'center',
},
textNormal: {
fontSize: getFontXD(39),
color: R.colors.black,
textAlign: 'center',
},
textOTP: {
fontSize: getFontXD(100),
color: R.colors.black,
textAlign: 'center',
marginVertical: HEIGHTXD(40),
},
});
export default SmartOTPView;
import React, {Component} from 'react';
import {View, Text} from 'react-native';
const UpdateOTP = (props) => {
return (
<View>
<Text>UpdateOTP OTP</Text>
</View>
);
};
export default UpdateOTP;
import React from 'react';
import {View, Text} from 'react-native';
import HeaderBack from '../../../components/Header/HeaderBack';
import {WebView} from 'react-native-webview';
const FAQs = (props) => {
return (
<View style={{flex: 1}}>
<HeaderBack isWhite={true} title={'FAQs'} />
<WebView
// androidHardwareAccelerationDisabled={true}
source={{
uri: 'http://api.dcvinvest.com/webview/smart-otp/faqs',
}}
/>
</View>
);
};
export default FAQs;
import React from 'react';
import {View, Text} from 'react-native';
import {getFontXD} from '../../../Config/Functions';
import HeaderBack from '../../../components/Header/HeaderBack';
import {WebView} from 'react-native-webview';
const RulesSmartOTP = (props) => {
return (
<View style={{flex: 1}}>
<HeaderBack isWhite={true} title={'Rules'} />
<WebView
// androidHardwareAccelerationDisabled={true}
source={{
uri: 'http://api.dcvinvest.com/webview/smart-otp/term-and-condition',
}}
/>
</View>
);
};
export default RulesSmartOTP;
...@@ -38,10 +38,9 @@ const VersionChecker = (props) => { ...@@ -38,10 +38,9 @@ const VersionChecker = (props) => {
platform: Platform.OS, platform: Platform.OS,
}); });
if ((res.data.code = 200 && res.data.data)) { if ((res.data.code = 200 && res.data.data)) {
console.log(res);
if ( if (
res.data.data[0].version_name !== verCurrent || res.data.data[0].version_name !== verCurrent ||
res.data.data[0].build.toString() !== DeviceInfo.getBuildNumber res.data.data[0].build.toString() !== DeviceInfo.getBuildNumber()
) { ) {
setVersion(res.data.data[0].version_name); setVersion(res.data.data[0].version_name);
setVisible(true); setVisible(true);
......
import React, {Component, useEffect, useState} from 'react';
import {
View,
Text,
TextInput,
StyleSheet,
TouchableOpacity,
Platform,
Alert,
} from 'react-native';
import HeaderBack from '../../components/Header/HeaderBack';
import {
CodeField,
Cursor,
useBlurOnFulfill,
useClearByFocusCell,
} from 'react-native-confirmation-code-field';
import {
getFontXD,
HEIGHTXD,
WIDTHXD,
encryptRSAString,
} from '../../Config/Functions';
import R from '../../assets/R';
import {TABNAVIGATOR} from '../../routers/ScreenNames';
import {verifyOTPApi} from '../../apis/Functions/users';
import {useNavigation} from '@react-navigation/native';
import I18n from '../../helper/i18/i18n';
import AppText from '../../components/AppText';
import {showLoading, hideLoading} from '../../actions/loadingAction';
import {connect} from 'react-redux';
import {showAlert, TYPE} from '../../components/DropdownAlert';
import CountDown from '../../components/CountDown';
import {verifyStoreOTPApiSmart} from '../../apis/Functions/users';
const CELL_COUNT = 4;
const ConfirmOTPSmart = (propsa) => {
const [value, setValue] = useState('');
const [isReset, setReset] = useState(false);
const navigate = useNavigation();
const ref = useBlurOnFulfill({value, cellCount: CELL_COUNT});
const [props, getCellOnLayoutHandler] = useClearByFocusCell({
value,
setValue,
});
const getOTP = async () => {
propsa.showLoading();
const res = await getOTPApi({
platform: Platform.OS,
otp_by: propsa.route.params.email,
type: 'FORGOT_PASSWORD',
});
propsa.hideLoading();
if (res.data.code == 200) {
setReset(!isReset);
showAlert(TYPE.SUCCESS, I18n.t('Notification'), res.data.message);
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message);
}
};
const confirm = async () => {
if (!value) {
showAlert(TYPE.WARN, I18n.t('Notification'), I18n.t('EnterOTPRequest'));
} else if (value.length != 4) {
showAlert(TYPE.WARN, I18n.t('Notification'), I18n.t('OTPInvalid'));
} else {
propsa.showLoading();
const res = await verifyStoreOTPApiSmart({
platform: Platform.OS,
password: encryptRSAString(propsa.route.params.password),
password_confirmation: encryptRSAString(
propsa.route.params.password_confirmation,
),
otp: value,
type: 'FORGOT_PASSWORD',
});
propsa.hideLoading();
if (res.data.code == 200) {
navigate.navigate(TABNAVIGATOR);
} else {
showAlert(TYPE.ERROR, I18n.t('Notification'), res.data.message);
}
}
};
return (
<View style={{flex: 1}}>
<HeaderBack title={'VerifyOTP'} />
<View style={styles.container}>
<View style={{height: 20}} />
<View style={styles.wrap}>
<AppText i18nKey={'Verify_code'} style={styles.txtTitle} />
<View style={styles.containerCode}>
<CodeField
ref={ref}
{...props}
value={value}
onChangeText={setValue}
cellCount={CELL_COUNT}
rootStyle={styles.codeFieldRoot}
keyboardType="number-pad"
textContentType="oneTimeCode"
renderCell={({index, symbol, isFocused}) => (
<View
onLayout={getCellOnLayoutHandler(index)}
key={index}
style={[styles.cellRoot, isFocused && styles.focusCell]}>
<Text style={styles.cellText}>
{symbol || (isFocused ? <Cursor /> : null)}
</Text>
</View>
)}
/>
</View>
</View>
</View>
<View style={styles.footer}>
<TouchableOpacity onPress={confirm} style={styles.btn}>
<AppText i18nKey={'Continue'} style={styles.txtBtn} />
</TouchableOpacity>
<TouchableOpacity style={styles.wrapFooter} onPress={getOTP}>
<Text style={styles.txtNote}>{I18n.t('OTPValidFiveMinute')}</Text>
<AppText i18nKey={'Re_send'} style={styles.txtSend} />
</TouchableOpacity>
<CountDown isReset={isReset} />
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingVertical: 20,
},
footer: {
height: 200,
justifyContent: 'center',
alignItems: 'center',
},
wrap: {
flex: 1,
paddingTop: 30,
alignItems: 'center',
width: '100%',
paddingHorizontal: 50,
},
containerCode: {
height: 50,
width: '100%',
marginTop: 30,
},
codeFieldRoot: {
marginTop: 20,
},
focusCell: {
borderColor: '#000',
},
cellRoot: {
width: 40,
height: 40,
justifyContent: 'center',
alignItems: 'center',
borderBottomColor: '#ccc',
borderBottomWidth: 1,
},
cellText: {
color: '#000',
fontSize: 36,
textAlign: 'center',
},
focusCell: {
borderBottomColor: '#007AFF',
borderBottomWidth: 2,
},
txtTitle: {
fontSize: getFontXD(52),
color: '#979797',
},
btn: {
width: WIDTHXD(521),
height: HEIGHTXD(120),
borderRadius: 15,
backgroundColor: '#1C6AF6',
justifyContent: 'center',
alignItems: 'center',
},
txtBtn: {
color: R.colors.white,
fontSize: getFontXD(52),
textTransform: 'uppercase',
},
txtSend: {
fontSize: getFontXD(42),
color: '#1C6AF6',
},
wrapFooter: {
marginTop: 30,
flexDirection: 'row',
alignItems: 'center',
},
txtNote: {
color: '#A2A2A2',
fontSize: getFontXD(42),
fontStyle: 'italic',
},
});
const mapStateToProps = (state) => {
return {};
};
export default connect(mapStateToProps, {showLoading, hideLoading})(
ConfirmOTPSmart,
);
...@@ -71,3 +71,28 @@ export const changeAvatart = async (body) => ...@@ -71,3 +71,28 @@ export const changeAvatart = async (body) =>
PostFormData(url.urlChangeAvatar, body) PostFormData(url.urlChangeAvatar, body)
.then((res) => res) .then((res) => res)
.catch((err) => err); .catch((err) => err);
export const getOTPApiSmartOTP = async (body) =>
PostLogin(url.urlGetSmartOTP, body)
.then((res) => res)
.catch((err) => err);
export const verifyStoreOTPApiSmart = async (body) =>
PostData(url.urlStoreOTPSmart, body)
.then((res) => res)
.catch((err) => err);
export const verifyOTPApiSmart = async (body) =>
PostData(url.urlVerufySmartOTP, body)
.then((res) => res)
.catch((err) => err);
export const updateOTPApiSmart = async (body) =>
PostData(url.urlUpdateSmartOTP, body)
.then((res) => res)
.catch((err) => err);
export const verifyPassword = async (body) =>
PostData(url.urlVerifyPassword, body)
.then((res) => res)
.catch((err) => err);
...@@ -65,20 +65,10 @@ export async function PostLogin(url, json) { ...@@ -65,20 +65,10 @@ export async function PostLogin(url, json) {
console.log('post data mobile', myRequest); console.log('post data mobile', myRequest);
return await axios(myRequest) return await axios(myRequest)
.then((response) => { .then((response) => {
if (response.data?.code === 401) {
logout();
return;
} else {
return response; return response;
}
}) })
.then((response) => { .then((response) => {
if (response.data?.code === 401) {
logout();
return;
} else {
return response; return response;
}
}) })
.catch((error) => { .catch((error) => {
console.log(error); console.log(error);
......
export const root = 'http://services.dcvinvest.com/'; export const root = 'http://services.dcvinvest.com/';
export default { export default {
urllogin: root + 'api/auth/customer-login', urllogin: root + 'api/v2/auth/customer-login',
urlRegistor: root + 'api/auth/customer-register', urlRegistor: root + 'api/auth/customer-register',
urlGetListMethod: root + 'api/v1/payments/get-list-deposit-method', urlGetListMethod: root + 'api/v1/payments/get-list-deposit-method',
urlGetOTP: root + 'api/auth/customer-get-otp', urlGetOTP: root + 'api/auth/customer-get-otp',
...@@ -27,6 +27,7 @@ export default { ...@@ -27,6 +27,7 @@ export default {
urlUpdateMethodBank: root + 'api/v1/customers/update-payment-method', urlUpdateMethodBank: root + 'api/v1/customers/update-payment-method',
urlGetDetailUser: root + 'api/v1/customers/detail', urlGetDetailUser: root + 'api/v1/customers/detail',
urlUpdateSmartOTP: root + 'api/v1/customers/update-otp-password',
//Home //Home
urlGetTransaction: root + 'api/v1/customers/statistic-transaction', urlGetTransaction: root + 'api/v1/customers/statistic-transaction',
...@@ -63,4 +64,9 @@ export default { ...@@ -63,4 +64,9 @@ export default {
urlCloseCQG: root + 'api/v1/customers/cancel-open-cqg', urlCloseCQG: root + 'api/v1/customers/cancel-open-cqg',
urlUpdateCQG: root + 'api/v1/customers/update-open-cqg', urlUpdateCQG: root + 'api/v1/customers/update-open-cqg',
urlGetUnitList: `${root}api/v1/customers/get-list-unit`, urlGetUnitList: `${root}api/v1/customers/get-list-unit`,
urlGetSmartOTP: root + 'api/v2/customer-get-otp',
urlStoreOTPSmart: root + 'api/v1/customers/store-otp-password',
urlVerufySmartOTP: root + 'api/v1/customers/verify-otp-password',
urlVerifyPassword: `${root}api/auth/customer-verify-password`,
}; };
...@@ -3,6 +3,7 @@ const KEY = { ...@@ -3,6 +3,7 @@ const KEY = {
FIREBASE: '@Firebase', FIREBASE: '@Firebase',
ACCOUNT: '@ACCOUNT', ACCOUNT: '@ACCOUNT',
LANGUAGE: '@LANGUAGE', LANGUAGE: '@LANGUAGE',
IS_LOGIN_BY_BIOMETRY: '@IS_LOGIN_BY_BIOMETRY',
}; };
export default KEY; export default KEY;
...@@ -3,6 +3,7 @@ const colors = { ...@@ -3,6 +3,7 @@ const colors = {
colorf39: '#F39C12', colorf39: '#F39C12',
gray5b71: '#5B7195', gray5b71: '#5B7195',
corlor9c: '#FF9C00', corlor9c: '#FF9C00',
colorOrangeLight: '#faf1e6',
color949: '#949494', color949: '#949494',
color504: '#A60014', color504: '#A60014',
colorRGBA040: 'rgba(255,255,255,0.4)', colorRGBA040: 'rgba(255,255,255,0.4)',
...@@ -57,6 +58,7 @@ const colors = { ...@@ -57,6 +58,7 @@ const colors = {
red: '#A60014', red: '#A60014',
red1: '#e2e8eb', red1: '#e2e8eb',
red2: '#E3434F', red2: '#E3434F',
brown: '#926e6f',
}; };
export default colors; export default colors;
...@@ -111,6 +111,15 @@ const images = { ...@@ -111,6 +111,15 @@ const images = {
toolRate: require('./images/toolRate.png'), toolRate: require('./images/toolRate.png'),
toolStopLoss: require('./images/toolStopLoss.png'), toolStopLoss: require('./images/toolStopLoss.png'),
placeholderImage: require('./images/placeholderImage.png'), placeholderImage: require('./images/placeholderImage.png'),
iconSettingGeneral: require('./images/iconSettingGeneral.png'),
iconSmartOTP: require('./images/iconSmartOTP.png'),
rules: require('./images/rules.png'),
changeSmart: require('./images/changeSmart.png'),
faq: require('./images/faq.png'),
fingerprint: require('./images/fingerprint.png'),
iconFaceId: require('./images/iconFaceID.png'),
}; };
export default images; export default images;
...@@ -5,7 +5,7 @@ export const NotificationAlert = (string) => { ...@@ -5,7 +5,7 @@ export const NotificationAlert = (string) => {
Alert.alert(I18n.t('Notification'), string); Alert.alert(I18n.t('Notification'), string);
}; };
export const confirmAlert = (content, callback) => { export const confirmAlert = (content, callback, positiveTitle) => {
Alert.alert( Alert.alert(
I18n.t('Notification'), I18n.t('Notification'),
content, content,
...@@ -15,7 +15,7 @@ export const confirmAlert = (content, callback) => { ...@@ -15,7 +15,7 @@ export const confirmAlert = (content, callback) => {
style: 'cancel', style: 'cancel',
}, },
{ {
text: I18n.t('Ok'), text: positiveTitle ? positiveTitle : I18n.t('Ok'),
onPress: () => { onPress: () => {
callback(); callback();
}, },
......
...@@ -3,6 +3,7 @@ import {View, Text} from 'react-native'; ...@@ -3,6 +3,7 @@ import {View, Text} from 'react-native';
import {showAlert, TYPE} from './DropdownAlert'; import {showAlert, TYPE} from './DropdownAlert';
import I18n from '../helper/i18/i18n'; import I18n from '../helper/i18/i18n';
import {getFontXD} from '../Config/Functions'; import {getFontXD} from '../Config/Functions';
import R from '../assets/R';
const CountDown = (props) => { const CountDown = (props) => {
const [count, setCount] = useState(300); const [count, setCount] = useState(300);
...@@ -12,14 +13,23 @@ const CountDown = (props) => { ...@@ -12,14 +13,23 @@ const CountDown = (props) => {
}, [props.isReset]); }, [props.isReset]);
useEffect(() => { useEffect(() => {
if (count == 0) if (count == 0) {
if(props.autoRefress) {
props.autoRefress()
}
if(!props.isFromSmartOTP) {
showAlert(TYPE.ERROR, I18n.t('Notification'), I18n.t('Overtime')); showAlert(TYPE.ERROR, I18n.t('Notification'), I18n.t('Overtime'));
}
}
}, [count]); }, [count]);
useEffect(() => { useEffect(() => {
if (count > 0) { if (count > 0) {
const timer = setTimeout(() => { const timer = setTimeout(() => {
setCount(count - 1); setCount(count - 1);
if(props.updateProgress) {
props.updateProgress(count)
}
}, 1000); }, 1000);
return () => clearTimeout(timer); return () => clearTimeout(timer);
} }
...@@ -31,6 +41,15 @@ const CountDown = (props) => { ...@@ -31,6 +41,15 @@ const CountDown = (props) => {
}; };
return ( return (
props.isFromSmartOTP ?
<Text
style={{
color: R.colors.red2,
fontSize: getFontXD(39),
}}>
0{parseInt(count / 60)}:{secondToString(count)}
</Text>
:
<View> <View>
<Text <Text
style={{ style={{
......
...@@ -37,6 +37,7 @@ import { ...@@ -37,6 +37,7 @@ import {
HISTORY, HISTORY,
CHOOSEMETHOD, CHOOSEMETHOD,
WALLETWITHDRAW, WALLETWITHDRAW,
SMARTOTPCONFIG,
} from '../../routers/ScreenNames'; } from '../../routers/ScreenNames';
import {useNavigation} from '@react-navigation/native'; import {useNavigation} from '@react-navigation/native';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
...@@ -200,7 +201,21 @@ const menus = [ ...@@ -200,7 +201,21 @@ const menus = [
icon: R.images.iconSetting, icon: R.images.iconSetting,
screen: SETTING, screen: SETTING,
active: false, active: false,
children: null, children: [
{
title: 'SettingOTP',
icon: R.images.iconSmartOTP,
screen: SMARTOTPCONFIG,
id: '51',
},
{
id: '52',
title: 'SettingGeneral',
icon: R.images.iconSettingGeneral,
screen: SETTING,
},
],
}, },
]; ];
...@@ -345,7 +360,7 @@ const styles = StyleSheet.create({ ...@@ -345,7 +360,7 @@ const styles = StyleSheet.create({
}, },
imgIcon: { imgIcon: {
width: WIDTHXD(62), width: WIDTHXD(62),
height: HEIGHTXD(52), height: HEIGHTXD(62),
resizeMode: 'contain', resizeMode: 'contain',
}, },
txtTitle: { txtTitle: {
...@@ -373,10 +388,9 @@ const styles = StyleSheet.create({ ...@@ -373,10 +388,9 @@ const styles = StyleSheet.create({
containerItem: { containerItem: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
marginVertical: 5, marginVertical: 10,
borderRadius: WIDTHXD(75), borderRadius: WIDTHXD(75),
paddingVertical: 10,
paddingHorizontal: 10, paddingHorizontal: 10,
}, },
row: {flexDirection: 'row', flex: 1, alignItems: 'center'}, row: {flexDirection: 'row', flex: 1, alignItems: 'center'},
......
...@@ -12,6 +12,8 @@ const TextField = (props) => { ...@@ -12,6 +12,8 @@ const TextField = (props) => {
value, value,
editable, editable,
placeholder, placeholder,
isPassWord,
} = props; } = props;
return ( return (
...@@ -30,6 +32,7 @@ const TextField = (props) => { ...@@ -30,6 +32,7 @@ const TextField = (props) => {
placeholderTextColor={R.colors.placeHolder} placeholderTextColor={R.colors.placeHolder}
editable={editable != null ? false : true} editable={editable != null ? false : true}
autoCapitalize="none" autoCapitalize="none"
secureTextEntry={isPassWord}
value={value} value={value}
keyboardType={isNumber ? 'number-pad' : 'default'} keyboardType={isNumber ? 'number-pad' : 'default'}
onChangeText={(val) => onChangeText(val)} onChangeText={(val) => onChangeText(val)}
......
...@@ -156,13 +156,13 @@ export default { ...@@ -156,13 +156,13 @@ export default {
ChangePasswordSuccess: 'Change password success', ChangePasswordSuccess: 'Change password success',
EnterAllInfo: 'Please complete all information ', EnterAllInfo: 'Please complete all information ',
Date: 'Date', Date: 'Date',
ReviewService: 'Review service of DCV Invest', ReviewService: 'Review services of DCV Invest',
VeryBad: 'Very bad', VeryBad: 'Very bad',
Bad: 'Bad', Bad: 'Bad',
Normal: 'Normal', Normal: 'Normal',
Good: 'Good', Good: 'Good',
VeryGood: 'Very good', VeryGood: 'Very good',
ShareYourFeel: 'Share your feel about service', ShareYourFeel: 'Share your feel about services',
UploadImage: 'Upload image', UploadImage: 'Upload image',
BonusMoney: 'Bonus money', BonusMoney: 'Bonus money',
Content: 'Content', Content: 'Content',
...@@ -232,7 +232,6 @@ export default { ...@@ -232,7 +232,6 @@ export default {
UploadImageFail: UploadImageFail:
'The network connection is not stable, please check the connection', 'The network connection is not stable, please check the connection',
EscrowCalculator: 'Escrow calculator', EscrowCalculator: 'Escrow calculator',
Product: 'Product',
LotTransactionNumber: 'Lot transaction number', LotTransactionNumber: 'Lot transaction number',
FirstEscrow: 'First escrow (VNĐ)', FirstEscrow: 'First escrow (VNĐ)',
FirstEscrowTotal: 'First escrow total (VNĐ)', FirstEscrowTotal: 'First escrow total (VNĐ)',
...@@ -291,4 +290,48 @@ export default { ...@@ -291,4 +290,48 @@ export default {
Overtime: 'Overtime OTP', Overtime: 'Overtime OTP',
LoginSessionEnd: 'Login session end, please login again', LoginSessionEnd: 'Login session end, please login again',
noteWithdrawMoney: 'Infor CQG account', noteWithdrawMoney: 'Infor CQG account',
SmartOTP: 'Smart OTP',
SmartOTPWarning:
'Please do not give the OTP to anyone under any circumstances.',
ConfirmTransaction: 'Confirm transaction',
OTPWillAutoUpdate: 'OTP code will be automatically update after ',
OTPWillAutoFill:
'Select "Confirm transaction" code OTP will be filled automatically',
SmartOTPUsingFor: 'OTP code using for:',
SmartOTPUsingForFirst: '• Withdrawal request',
SmartOTPUsingForSecond: '• Request an internal transfer',
SmartOTPUsingForThird: '• Request to load into CQG wallet',
EnterSmartOTPPIN: 'Please enter the Smart OTP PIN code',
ForgotPINCode: 'Forgot PIN code?',
ReactivationSmartOTP: 'Reactivation the Smart OTP',
SettingOTP: 'Setting Smart OTP',
SettingGeneral: 'Setting general',
ChangeSmartOTP: 'Smart OTP',
Rules: 'Rules',
FAQs: 'FAQs',
EnterSmartOTPPINNEW: 'Please enter the Smart new OTP PIN code',
PassGetSmartOTP: 'Password get Smart OTP',
ConfirmPassGetSmartOTP: 'Confirm password get Smart OTP',
PopupSettingSmartOTP: 'Do you want setting Smart OTP?',
ConfirmSmartOTP: 'Confirm Smart OTP',
AddSmartOTP: 'Add Smart OTP',
ResetSmartOTP:
'To ensure safety during application use, please contact the operator: ',
ResetSmartOTP2: ' press 3 to meet technical support staff.',
ForgotSmartOTP: 'Forgot Smart OTP',
WarnMaxReqestWithdraw: 'Invalid withdrawal amount',
YouHaveNotSettingSmartOTP: 'You have not installed Smart OTP',
OTP: 'Enter OTP',
HaveIssue: 'Have an issue, try again!',
HaveNotCredential: 'Can not login by %{type}, please return on login by %{type}',
LoginBy: 'Login by %{type}',
Fingerprint: 'Fingerprint',
FaceId: 'FaceId'
}; };
...@@ -288,7 +288,46 @@ export default { ...@@ -288,7 +288,46 @@ export default {
_Sell: 'Bán', _Sell: 'Bán',
FirstEscrow: 'Ký quỹ ban đầu (VNĐ) ', FirstEscrow: 'Ký quỹ ban đầu (VNĐ) ',
WarnMinReqestWithdraw: 'Số tiền rút phải lớn hơn 1 triệu đồng', WarnMinReqestWithdraw: 'Số tiền rút phải lớn hơn 1 triệu đồng',
WarnMaxReqestWithdraw: 'Số tiền rút không hợp lệ',
Overtime: 'Mã OTP hết hạn sử dụng', Overtime: 'Mã OTP hết hạn sử dụng',
LoginSessionEnd: 'Hết phiên đăng nhập, vui lòng đăng nhập lại', LoginSessionEnd: 'Hết phiên đăng nhập, vui lòng đăng nhập lại',
noteWithdrawMoney: 'Thông tin tài khoản CQG', noteWithdrawMoney: 'Thông tin tài khoản CQG',
SmartOTP: 'Smart OTP',
SmartOTPWarning:
'Vui lòng không cung cấp mã OTP cho bất cứ ai trong bất cứ trường hợp nào.',
ConfirmTransaction: 'Xác nhận giao dịch',
OTPWillAutoUpdate: 'Mã OTP sẽ tự động cập nhật sau ',
OTPWillAutoFill: 'Chọn xác nhận giao dịch mã OTP sẽ được điền tự động',
SmartOTPUsingFor: 'Mã xác thực OTP cơ bản dùng cho:',
SmartOTPUsingForFirst: '• Yêu cầu rút tiền',
SmartOTPUsingForSecond: '• Yêu cầu chuyển khoản nội bộ',
SmartOTPUsingForThird: '• Yêu cầu nạp vào ví CQG',
EnterSmartOTPPIN: 'Vui lòng nhập mã PIN Smart OTP',
ForgotPINCode: 'Quên mã PIN?',
ReactivationSmartOTP: 'Kích hoạt lại Smart OTP',
SettingOTP: 'Cài đặt Smart OTP',
SettingGeneral: 'Cài đặt chung',
EnterSmartOTPPINNEW: 'Vui lòng nhập mã PIN Smart OTP mới',
AddSmartOTP: 'Thêm Smart OTP',
ChangeSmartOTP: 'Mã PIN Smart OTP',
Rules: 'Điều khoản và điều kiện',
FAQs: 'FAQs',
PassGetSmartOTP: 'Mật khẩu lấy Smart OTP',
ConfirmPassGetSmartOTP: 'Xác nhận mật khẩu lấy Smart OTP ',
ConfirmSmartOTP: 'Xác nhận Smart OTP ',
PopupSettingSmartOTP: 'Bạn có muốn cài đặt Smart OTP?',
ResetSmartOTP:
'Để đảm bảo an toàn trong quá trình sử dụng ứng dụng, bạn vui lòng liên hệ đến tổng đài: ',
ResetSmartOTP2: ' bấm phím 3 để gặp nhân viên hỗ trợ kỹ thuật.',
ForgotSmartOTP: 'Quên Smart OTP',
YouHaveNotSettingSmartOTP: 'Bạn chưa cài đặt Smart OTP',
OTP: 'Nhập OTP',
HaveIssue: 'Có lỗi xảy ra, vui lòng thử lại',
HaveNotCredential: 'Không thể đăng nhập được bằng %{type}, vui lòng bật lại chức năng đăng nhập bằng %{type}',
LoginBy: 'Đăng nhập bằng %{type}',
Fingerprint: 'vân tay',
FaceId: 'nhận diện khuôn mặt'
}; };
...@@ -76,3 +76,22 @@ export const CACULATEDPROFITLOSS = 'CACULATEDPROFITLOSS'; ...@@ -76,3 +76,22 @@ export const CACULATEDPROFITLOSS = 'CACULATEDPROFITLOSS';
export const CACULATEDSTOPLOSS = 'CACULATEDSTOPLOSS'; export const CACULATEDSTOPLOSS = 'CACULATEDSTOPLOSS';
export const CONVERTUNIT = 'CONVERTUNIT'; export const CONVERTUNIT = 'CONVERTUNIT';
export const EXCHANGERATE = 'EXCHANGERATE'; export const EXCHANGERATE = 'EXCHANGERATE';
export const SMARTOTP = 'SMARTOTP';
export const ENTER_PASSWORD_SMART_OTP = 'ENTER_PASSWORD_SMART_OTP';
export const SETTINGOTP = 'SETTINGOTP';
export const SMARTOTPCONFIG = 'SMARTOTPCONFIG';
export const UPDATEOTP = 'UPDATEOTP';
export const CONFIRMOTPSMART = 'CONFIRMOTPSMART';
export const RESET_SMART_OTP = 'RESET_SMART_OTP';
export const CHANGESMARTOTP = 'CHANGESMARTOTP';
export const CONFIRMCHANGESMARTOTP = 'CONFIRMCHANGESMARTOTP';
export const RULESSMARTOTP = 'RULESSMARTOTP';
export const FAQSSMARTOTP = 'FAQSSMARTOTP';
export const CONFIRMCREATEOTP = 'CONFIRMCREATEOTP';
...@@ -55,12 +55,26 @@ import CaculatedProfitLoss from '../Screens/Tool/CalculatorProfitLoss/Calculator ...@@ -55,12 +55,26 @@ import CaculatedProfitLoss from '../Screens/Tool/CalculatorProfitLoss/Calculator
import CaculatedStopLoss from '../Screens/Tool/CaculatedStopLoss'; import CaculatedStopLoss from '../Screens/Tool/CaculatedStopLoss';
import ConvertUnit from '../Screens/Tool/ConvertUnit'; import ConvertUnit from '../Screens/Tool/ConvertUnit';
import ExchangeRate from '../Screens/Tool/ExchangeRate'; import ExchangeRate from '../Screens/Tool/ExchangeRate';
import SmartOTPConfig from '../Screens/SmartOTP/SmartOTPConfig';
import EnterPasswordSmartOTP from '../Screens/SmartOTP/EnterPasswordSmartOTP';
import SmartOTP from '../Screens/SmartOTP/SmartOTP';
import SettigOTP from '../Screens/SmartOTP/SettingSmartOTP';
import UpdateOTP from '../Screens/SmartOTP/UpdateSmartOTP';
import ConfirmOTPSmart from '../Screens/SmartOTP/ConfirmOTPSmart';
import ChangeSmartOTP from '../Screens/SmartOTP/ChangeSmartOTP/ChangeSmartOTP';
import ConfirmChangeSmartOTP from '../Screens/SmartOTP/ChangeSmartOTP/ConfirmChangeSmartOTP';
import FAQs from '../Screens/SmartOTP/WebView/FAQs';
import RulesSmartOTP from '../Screens/SmartOTP/WebView/RulesSmartOTP';
import ConfirmCreate from '../Screens/SmartOTP/ConfirmCreate/ConfirmCreate';
import * as ScreenName from './ScreenNames'; import * as ScreenName from './ScreenNames';
const Stack = createStackNavigator(); const Stack = createStackNavigator();
import {enableScreens} from 'react-native-screens'; import {enableScreens} from 'react-native-screens';
import ResetSmartOTP from '../Screens/SmartOTP/ResetSmartOTP';
enableScreens(); enableScreens();
...@@ -73,9 +87,26 @@ function MyStack(props) { ...@@ -73,9 +87,26 @@ function MyStack(props) {
headerMode={'none'} headerMode={'none'}
initialRouteName={ScreenName.AUTHEN}> initialRouteName={ScreenName.AUTHEN}>
<Stack.Screen <Stack.Screen
name={ScreenName.CONFIRMCREATEOTP}
component={ConfirmCreate}
/>
<Stack.Screen
name={ScreenName.CACULATEDDEPOSIT} name={ScreenName.CACULATEDDEPOSIT}
component={CaculatedDeposit} component={CaculatedDeposit}
/> />
<Stack.Screen
name={ScreenName.CONFIRMOTPSMART}
component={ConfirmOTPSmart}
/>
<Stack.Screen
name={ScreenName.SMARTOTPCONFIG}
component={SmartOTPConfig}
/>
<Stack.Screen name={ScreenName.SETTINGOTP} component={SettigOTP} />
<Stack.Screen name={ScreenName.UPDATEOTP} component={UpdateOTP} />
<Stack.Screen <Stack.Screen
name={ScreenName.CACULATEDPROFITLOSS} name={ScreenName.CACULATEDPROFITLOSS}
component={CaculatedProfitLoss} component={CaculatedProfitLoss}
...@@ -146,6 +177,18 @@ function MyStack(props) { ...@@ -146,6 +177,18 @@ function MyStack(props) {
<Stack.Screen name={ScreenName.CONFIRMEMAIL} component={ConfirmEmail} /> <Stack.Screen name={ScreenName.CONFIRMEMAIL} component={ConfirmEmail} />
<Stack.Screen name={ScreenName.NEWPASSWORD} component={NewPassWord} /> <Stack.Screen name={ScreenName.NEWPASSWORD} component={NewPassWord} />
<Stack.Screen name={ScreenName.PRODUCTDETAIL} component={ProductDetail} /> <Stack.Screen name={ScreenName.PRODUCTDETAIL} component={ProductDetail} />
<Stack.Screen name={ScreenName.SMARTOTP} component={SmartOTP} />
<Stack.Screen
name={ScreenName.ENTER_PASSWORD_SMART_OTP}
component={EnterPasswordSmartOTP}
/>
<Stack.Screen
name={ScreenName.RESET_SMART_OTP}
component={ResetSmartOTP}
/>
<Stack.Screen name={ScreenName.FAQSSMARTOTP} component={FAQs} />
<Stack.Screen name={ScreenName.RULESSMARTOTP} component={RulesSmartOTP} />
<Stack.Screen <Stack.Screen
name={ScreenName.FORGOTPASSWORD} name={ScreenName.FORGOTPASSWORD}
...@@ -155,6 +198,16 @@ function MyStack(props) { ...@@ -155,6 +198,16 @@ function MyStack(props) {
name={ScreenName.ESCROWCALCULATOR} name={ScreenName.ESCROWCALCULATOR}
component={EscrowCalculator} component={EscrowCalculator}
/> />
<Stack.Screen
name={ScreenName.CHANGESMARTOTP}
component={ChangeSmartOTP}
/>
<Stack.Screen
name={ScreenName.CONFIRMCHANGESMARTOTP}
component={ConfirmChangeSmartOTP}
/>
</Stack.Navigator> </Stack.Navigator>
); );
} }
......
...@@ -17,7 +17,12 @@ import Notification from '../Screens/Notification/Notification'; ...@@ -17,7 +17,12 @@ import Notification from '../Screens/Notification/Notification';
import Test from '../Screens/NewFeed/Test'; import Test from '../Screens/NewFeed/Test';
import {useNavigation} from '@react-navigation/native'; import {useNavigation} from '@react-navigation/native';
import Transaction from '../Screens/Transaction/Transaction'; import Transaction from '../Screens/Transaction/Transaction';
import {AccountVerification, PACKETCQG} from '../routers/ScreenNames'; import {
AccountVerification,
PACKETCQG,
SETTINGOTP,
CHANGESMARTOTP,
} from '../routers/ScreenNames';
import I18n, {setLocation} from '../helper/i18/i18n'; import I18n, {setLocation} from '../helper/i18/i18n';
import {changeLanguage} from '../actions/language'; import {changeLanguage} from '../actions/language';
import KEY from '../assets/AsynStorage'; import KEY from '../assets/AsynStorage';
...@@ -39,7 +44,7 @@ const TabNavigator = (props) => { ...@@ -39,7 +44,7 @@ const TabNavigator = (props) => {
checkDeepking(); checkDeepking();
setTimeout(() => { setTimeout(() => {
showPopUp(); showPopUp();
}, 3000); }, 4000);
let logoutListener = DeviceEventEmitter.addListener('logout', (e) => { let logoutListener = DeviceEventEmitter.addListener('logout', (e) => {
console.log('run in to logout'); console.log('run in to logout');
logout(navigate); logout(navigate);
...@@ -100,6 +105,18 @@ const TabNavigator = (props) => { ...@@ -100,6 +105,18 @@ const TabNavigator = (props) => {
return confirmAlert(I18n.t('PopupVerifyAccount'), () => { return confirmAlert(I18n.t('PopupVerifyAccount'), () => {
navigate.navigate(AccountVerification); navigate.navigate(AccountVerification);
}); });
} else if (!props.user.smart_otp_status) {
return confirmAlert(
props.language.language == 'vi'
? 'Bạn có muốn cài đặt Smart OTP?'
: 'Do you want setting Smart OTP?',
() => {
navigate.navigate(CHANGESMARTOTP, {
TYPE: 'CREATE_SMART_OTP',
old_password: null,
});
},
);
} else if (props.user.status == 3 && !props.user.contract_code) { } else if (props.user.status == 3 && !props.user.contract_code) {
return confirmAlert(I18n.t('PopupOpenCQG'), () => { return confirmAlert(I18n.t('PopupOpenCQG'), () => {
navigate.navigate(PACKETCQG); navigate.navigate(PACKETCQG);
......
import TouchID from 'react-native-touch-id';
import {Platform} from 'react-native'
export const checkBiometricSupportednEnrolled = async () => {
const optionalConfigObject = {
unifiedErrors: false, // use unified error messages (default false)
passcodeFallback: false // if true is passed, it will allow isSupported to return an error if the device is not enrolled in touch id/face id etc. Otherwise, it will just tell you what method is supported, even if the user is not enrolled. (default false)
}
return new Promise((resolve, reject) => {
//isSupported returns both cases 1. if supported 2. Is enabled/configured/enrolled
TouchID.isSupported(optionalConfigObject)
.then(biometryType => {
// Success code.
// as we are focusing on fingerprint for now
if (biometryType && biometryType != 'FaceID') {
resolve(true);
} else {
let fingerprintLableForOS = Platform.OS == "ios" ? "Touch ID" : "Fingerprint";
reject( fingerprintLableForOS + " is not available on this device");
}
})
.catch(error => {
// iOS Error Format and android error formats are different
// android use code and ios use name
// check at https://github.com/naoufal/react-native-touch-id
let errorCode = Platform.OS == "ios" ? error.name : error.code;
if (errorCode === "LAErrorTouchIDNotEnrolled" || errorCode === "NOT_AVAILABLE" || errorCode === "NOT_ENROLLED") {
let fingerprintLableForOS = Platform.OS == "ios" ? "Touch ID" : "Fingerprint";
resolve(fingerprintLableForOS + " has no enrolled fingers. Please go to settings and enable " + fingerprintLableForOS + " on this device.");
} else {
reject(Platform.OS == "ios" ? error.message : translations.t(error.code));
}
});
});
}
export const authenticateFingerPrint = () => {
return new Promise((resolve, reject) => {
// configuration object for more detailed dialog setup and style:
// const optionalConfigObject = {
// title: 'Authentication Required', // Android
// imageColor: '#e00606', // Android
// imageErrorColor: '#ff0000', // Android
// sensorDescription: 'Touch sensor', // Android
// sensorErrorDescription: 'Failed', // Android
// cancelText: 'Cancel', // Android
// fallbackLabel: 'Show Passcode', // iOS (if empty, then label is hidden)
// unifiedErrors: false, // use unified error messages (default false)
// passcodeFallback: false, // iOS - allows the device to fall back to using the passcode, if faceid/touch is not available. this does not mean that if touchid/faceid fails the first few times it will revert to passcode, rather that if the former are not enrolled, then it will use the passcode.
// };
let fingerprintLableForOS = Platform.OS == "ios" ? "Touch ID" : "Fingerprint";
TouchID.authenticate('Login to [appname] using ' + fingerprintLableForOS)
.then(success => {
// console.log('Authenticated Successfully', success)
resolve(success)
})
.catch(error => {
console.log('Authentication Failed', error.code)
reject(error)
});
});
}
import * as Keychain from 'react-native-keychain';
import { Platform } from "react-native";
export const setCredentials = async (username, password) => {
return new Promise((resolve, reject) => {
// Store the credentials
Keychain.setGenericPassword(username, password)
.then(resp => {
resolve(true)
})
.catch(err => {
console.log("err: ", err);
reject(err);
});
});
}
export const getCredentials = async () => {
return new Promise((resolve, reject) => {
Keychain.getGenericPassword()
.then((credentials) => {
if (credentials && credentials.username) {
// console.log('Credentials successfully loaded for user ' + credentials.username);
resolve(credentials);
} else {
// console.log('No credentials stored');
resolve(null);
}
})
.catch(err => {
console.log("err: ", err);
reject(err);
});
});
}
...@@ -692,9 +692,9 @@ ...@@ -692,9 +692,9 @@
regenerator-runtime "^0.13.4" regenerator-runtime "^0.13.4"
"@babel/runtime@^7.7.2": "@babel/runtime@^7.7.2":
version "7.13.10" version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.5.tgz#665450911c6031af38f81db530f387ec04cd9a98"
integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw== integrity sha512-121rumjddw9c3NCQ55KGkyE1h/nzWhU/owjhw0l4mQrkzz4x9SGS1X8gFLraHwX7td3Yo4QTL+qj0NcIzN87BA==
dependencies: dependencies:
regenerator-runtime "^0.13.4" regenerator-runtime "^0.13.4"
...@@ -2590,7 +2590,7 @@ chalk@^3.0.0: ...@@ -2590,7 +2590,7 @@ chalk@^3.0.0:
ansi-styles "^4.1.0" ansi-styles "^4.1.0"
supports-color "^7.1.0" supports-color "^7.1.0"
chalk@^4.0.0, chalk@^4.1.0: chalk@^4.0.0:
version "4.1.0" version "4.1.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz"
integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
...@@ -2598,6 +2598,14 @@ chalk@^4.0.0, chalk@^4.1.0: ...@@ -2598,6 +2598,14 @@ chalk@^4.0.0, chalk@^4.1.0:
ansi-styles "^4.1.0" ansi-styles "^4.1.0"
supports-color "^7.1.0" supports-color "^7.1.0"
chalk@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad"
integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
char-regex@^1.0.2: char-regex@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz"
...@@ -5197,6 +5205,11 @@ jsdom@^16.4.0: ...@@ -5197,6 +5205,11 @@ jsdom@^16.4.0:
ws "^7.2.3" ws "^7.2.3"
xml-name-validator "^3.0.0" xml-name-validator "^3.0.0"
jsencrypt@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/jsencrypt/-/jsencrypt-3.2.0.tgz#09242aabf1984165dcd7698fe6ed163be77c05f8"
integrity sha512-Y/WBrCYRP1A2I1OEXxqurO+W3AC5uXhiArprpYQ0Y8/1Dc3NaiINAyCLx7HzXGwN7xvW3s5xpeOTdwD7lD1SQQ==
jsesc@^2.5.1: jsesc@^2.5.1:
version "2.5.2" version "2.5.2"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz"
...@@ -6806,10 +6819,10 @@ react-native-autocomplete-input@^5.0.0: ...@@ -6806,10 +6819,10 @@ react-native-autocomplete-input@^5.0.0:
resolved "https://registry.yarnpkg.com/react-native-autocomplete-input/-/react-native-autocomplete-input-5.0.0.tgz#2bcba7be7846fe84e1e753362e3fe40c86fd7c46" resolved "https://registry.yarnpkg.com/react-native-autocomplete-input/-/react-native-autocomplete-input-5.0.0.tgz#2bcba7be7846fe84e1e753362e3fe40c86fd7c46"
integrity sha512-JsVm1rLNdyf2mLN0cw8XKTP6xwsCw+laPOxb7j81XOZhsS7nQaWytwp6+YEvSi3bnMRuUpvOUbCiS55av9/0/w== integrity sha512-JsVm1rLNdyf2mLN0cw8XKTP6xwsCw+laPOxb7j81XOZhsS7nQaWytwp6+YEvSi3bnMRuUpvOUbCiS55av9/0/w==
react-native-bootsplash@^3.2.0: react-native-bootsplash@^3.2.3:
version "3.2.0" version "3.2.3"
resolved "https://registry.yarnpkg.com/react-native-bootsplash/-/react-native-bootsplash-3.2.0.tgz#671861fdd75444f91196d3e64d3539ef50c3a30f" resolved "https://registry.yarnpkg.com/react-native-bootsplash/-/react-native-bootsplash-3.2.3.tgz#5f985a492696e14c73dc3b8475be5385b7436593"
integrity sha512-1+xMWLxqIUPbKiiwrbiekw3uKtuyNpm0R1eg5p3/ISRMXs0eZy7DHfiyCqcLq1N1a3Gv0oTZn1E7WEA2NjgdhA== integrity sha512-JNuDZ1sL9kppFrZ4OcK/ZM6gf9h5NmM6VfsLJEfa/lSPlD5wXoOyXIaeBn/6odaIPxSp31WIryeaNiZZIltu7g==
dependencies: dependencies:
chalk "^4.1.0" chalk "^4.1.0"
fs-extra "^9.1.0" fs-extra "^9.1.0"
...@@ -6879,6 +6892,11 @@ react-native-iphone-x-helper@^1.3.0: ...@@ -6879,6 +6892,11 @@ react-native-iphone-x-helper@^1.3.0:
resolved "https://registry.yarnpkg.com/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.3.1.tgz" resolved "https://registry.yarnpkg.com/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.3.1.tgz"
integrity sha512-HOf0jzRnq2/aFUcdCJ9w9JGzN3gdEg0zFE4FyYlp4jtidqU03D5X7ZegGKfT1EWteR0gPBGp9ye5T5FvSWi9Yg== integrity sha512-HOf0jzRnq2/aFUcdCJ9w9JGzN3gdEg0zFE4FyYlp4jtidqU03D5X7ZegGKfT1EWteR0gPBGp9ye5T5FvSWi9Yg==
react-native-keychain@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/react-native-keychain/-/react-native-keychain-7.0.0.tgz#11fd559fe86ae89f934b8c75ae228247deed5494"
integrity sha512-tH26sgW4OxB/llXmhO+DajFISEUoF1Ip2+WSDMIgCt8SP1xRE81m2qFzgIOc/7StYsUERxHhDPkxvq2H0/Goig==
react-native-linear-gradient@^2.5.6: react-native-linear-gradient@^2.5.6:
version "2.5.6" version "2.5.6"
resolved "https://registry.yarnpkg.com/react-native-linear-gradient/-/react-native-linear-gradient-2.5.6.tgz#96215cbc5ec7a01247a20890888aa75b834d44a0" resolved "https://registry.yarnpkg.com/react-native-linear-gradient/-/react-native-linear-gradient-2.5.6.tgz#96215cbc5ec7a01247a20890888aa75b834d44a0"
...@@ -6931,6 +6949,11 @@ react-native-screens@^2.17.1: ...@@ -6931,6 +6949,11 @@ react-native-screens@^2.17.1:
resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-2.18.0.tgz" resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-2.18.0.tgz"
integrity sha512-8+lCEsxzSu55GWRw6yZpyt3OszxN1OngfBsFXdqspaEfq6uIChanzlcD2PLVQl+iN82GAcrZM800Kd1pA477ZQ== integrity sha512-8+lCEsxzSu55GWRw6yZpyt3OszxN1OngfBsFXdqspaEfq6uIChanzlcD2PLVQl+iN82GAcrZM800Kd1pA477ZQ==
react-native-segmented-control-tab@^3.4.1:
version "3.4.1"
resolved "https://registry.yarnpkg.com/react-native-segmented-control-tab/-/react-native-segmented-control-tab-3.4.1.tgz#b6e54b8975ce8092315c9b0a1ab58b834d8ccf8e"
integrity sha512-BNPdlE9Unr0Xabewn8W+FhBMLjssXy9Ey7S7AY0hXlrKrEKFdC9z0yT+eEWd5dLam4T6T4IuGL8b7ZF4uGyWNw==
react-native-simple-radio-button@^2.7.4: react-native-simple-radio-button@^2.7.4:
version "2.7.4" version "2.7.4"
resolved "https://registry.yarnpkg.com/react-native-simple-radio-button/-/react-native-simple-radio-button-2.7.4.tgz#86e2dbe8af9e6bf60eee088f60466f7a975e7758" resolved "https://registry.yarnpkg.com/react-native-simple-radio-button/-/react-native-simple-radio-button-2.7.4.tgz#86e2dbe8af9e6bf60eee088f60466f7a975e7758"
...@@ -6948,6 +6971,11 @@ react-native-tab-view@^2.15.2: ...@@ -6948,6 +6971,11 @@ react-native-tab-view@^2.15.2:
resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-2.15.2.tgz" resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-2.15.2.tgz"
integrity sha512-2hxLkBnZtEKFDyfvNO5EUywhy3f/EiLOBO8SWqKj4BMBTO0QwnybaPE5MVF00Fhz+VA4+h/iI40Dkrrtq70dGg== integrity sha512-2hxLkBnZtEKFDyfvNO5EUywhy3f/EiLOBO8SWqKj4BMBTO0QwnybaPE5MVF00Fhz+VA4+h/iI40Dkrrtq70dGg==
react-native-touch-id@^4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/react-native-touch-id/-/react-native-touch-id-4.4.1.tgz#8b1bb2d04c30bac36bb9696d2d723e719c4a8b08"
integrity sha512-1jTl8fC+0fxvqegy/XXTyo6vMvPhjzkoDdaqoYZx0OH8AT250NuXnNPyKktvigIcys3+2acciqOeaCall7lrvg==
react-native-vector-icons@^8.0.0: react-native-vector-icons@^8.0.0:
version "8.1.0" version "8.1.0"
resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-8.1.0.tgz" resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-8.1.0.tgz"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment