ordering-ui-react-native 0.15.50 → 0.15.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ordering-ui-react-native",
3
- "version": "0.15.50",
3
+ "version": "0.15.53",
4
4
  "description": "Reusable components made in react native",
5
5
  "main": "src/index.tsx",
6
6
  "author": "ordering.inc",
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect } from 'react';
2
2
  import { Platform, Text, StyleSheet } from 'react-native';
3
- import { useApi, useSession, useLanguage } from 'ordering-components/native';
3
+ import { useApi, useSession, useLanguage, useConfig } from 'ordering-components/native';
4
4
  import { appleAuthAndroid, appleAuth } from '@invertase/react-native-apple-authentication';
5
5
  import uuid from 'react-native-uuid';
6
6
  import Icon from 'react-native-vector-icons/FontAwesome5';
@@ -16,12 +16,12 @@ export const AppleLogin = (props: any) => {
16
16
  } = props
17
17
 
18
18
  const [ordering] = useApi();
19
- const [{ auth }] = useSession();
20
- const [, t] = useLanguage();
21
-
22
- const buttonText = auth
23
- ? t('CONTINUE_WITH_APPLE', 'Logout with Apple')
24
- : t('CONTINUE_WITH_FACEBOOK', 'Continue with Apple');
19
+ const [{ auth }] = useSession();
20
+ const [, t] = useLanguage();
21
+ const [{ configs }] = useConfig()
22
+ const buttonText = auth
23
+ ? t('CONTINUE_WITH_APPLE', 'Logout with Apple')
24
+ : t('CONTINUE_WITH_FACEBOOK', 'Continue with Apple');
25
25
 
26
26
  const performAppleLogin = async (code: string) => {
27
27
  try {
@@ -32,9 +32,10 @@ export const AppleLogin = (props: any) => {
32
32
  code: code
33
33
  })
34
34
  })
35
- if (!response.content.error) {
35
+ const { result, error } = await response.json()
36
+ if (!error) {
36
37
  if (handleSuccessAppleLogin) {
37
- handleSuccessAppleLogin(response.content.result)
38
+ handleSuccessAppleLogin(result)
38
39
  handleLoading && handleLoading(false)
39
40
  }
40
41
  } else {
@@ -52,54 +53,58 @@ export const AppleLogin = (props: any) => {
52
53
  }
53
54
 
54
55
  const onIOSButtonPress = async () => {
55
-
56
- const appleAuthRequestResponse = await appleAuth.performRequest({
57
- requestedOperation: appleAuth.Operation.LOGIN,
58
- requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
59
- });
60
-
61
- // get current authentication state for user
62
- // /!\ This method must be tested on a real device. On the iOS simulator it always throws an error.
63
- const credentialState = await appleAuth.getCredentialStateForUser(appleAuthRequestResponse.user);
64
-
65
- // use credentialState response to ensure the user is authenticated
66
- if (credentialState === appleAuth.State.AUTHORIZED) {
67
- // user is authenticated
68
- if (appleAuthRequestResponse.authorizationCode) {
69
- performAppleLogin(appleAuthRequestResponse.authorizationCode)
56
+ try {
57
+ const appleAuthRequestResponse = await appleAuth.performRequest({
58
+ requestedOperation: appleAuth.Operation.LOGIN,
59
+ requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
60
+ });
61
+
62
+ // get current authentication state for user
63
+ // /!\ This method must be tested on a real device. On the iOS simulator it always throws an error.
64
+ const credentialState = await appleAuth.getCredentialStateForUser(appleAuthRequestResponse.user);
65
+
66
+ // use credentialState response to ensure the user is authenticated
67
+ if (credentialState === appleAuth.State.AUTHORIZED) {
68
+ // user is authenticated
69
+ if (appleAuthRequestResponse.authorizationCode) {
70
+ performAppleLogin(appleAuthRequestResponse.authorizationCode)
71
+ }
70
72
  }
73
+ } catch (err: any) {
74
+ handleLoading && handleLoading(false)
75
+ handleErrors && handleErrors(err.message)
71
76
  }
72
-
73
77
  }
74
-
75
78
  const onAndroidButtonPress = async () => {
76
- // Generate secure, random values for state and nonce
77
- const rawNonce: any = uuid.v4();
78
- const state: any = uuid.v4();
79
-
80
- // Configure the request
81
- appleAuthAndroid.configure({
82
- clientId: 'com.example.client-android',
83
- // Return URL added to your Apple dev console. We intercept this redirect, but it must still match
84
- // the URL you provided to Apple. It can be an empty route on your backend as it's never called.
85
- redirectUri: 'https://example.com/auth/callback',
86
- responseType: appleAuthAndroid.ResponseType.ALL,
87
- scope: appleAuthAndroid.Scope.ALL,
88
- // Random nonce value that will be SHA256 hashed before sending to Apple.
89
- nonce: rawNonce,
90
- state,
91
- });
92
-
93
- // Open the browser window for user sign in
94
- const response = await appleAuthAndroid.signIn();
95
-
96
79
  try {
80
+ // Generate secure, random values for state and nonce
81
+ const rawNonce: any = uuid.v4();
82
+ const state: any = uuid.v4();
83
+
84
+ // Configure the request
85
+ appleAuthAndroid.configure({
86
+ // The Service ID you registered with Apple
87
+ clientId: configs?.apple_login_client_id?.value,
88
+ // Return URL added to your Apple dev console. We intercept this redirect, but it must still match
89
+ // the URL you provided to Apple. It can be an empty route on your backend as it's never called.
90
+ redirectUri: 'https://example.com/auth/callback',
91
+ responseType: appleAuthAndroid.ResponseType.ALL,
92
+ scope: appleAuthAndroid.Scope.ALL,
93
+ // Random nonce value that will be SHA256 hashed before sending to Apple.
94
+ nonce: rawNonce,
95
+ state,
96
+ });
97
+
98
+ // Open the browser window for user sign in
99
+ const response = await appleAuthAndroid.signIn();
97
100
  if (response.code) {
98
101
  performAppleLogin(response.code)
99
102
  }
100
103
  } catch (err: any) {
101
-
104
+ handleLoading && handleLoading(false)
105
+ handleErrors && handleErrors(err.message)
102
106
  }
107
+
103
108
  }
104
109
 
105
110
  useEffect(() => {
@@ -115,35 +120,36 @@ export const AppleLogin = (props: any) => {
115
120
  if (Platform.OS === 'android') return appleAuthAndroid.isSupported;
116
121
  return false;
117
122
  }
123
+
118
124
  return (
119
125
  <Container>
120
- {canShowButton() &&
121
- <AppleButton
122
- onPress={() => Platform.OS == 'android' ? onAndroidButtonPress() : onIOSButtonPress()}
123
- >
124
- <Icon
125
- name="apple"
126
- size={20}
127
- color={'black'}
128
- style={style.fbBtn}
129
- />
130
- <Text style={style.textBtn}>
131
- {buttonText}
132
- </Text>
133
- </AppleButton>
126
+ {canShowButton() &&
127
+ <AppleButton
128
+ onPress={() => Platform.OS == 'android' ? onAndroidButtonPress() : onIOSButtonPress()}
129
+ >
130
+ <Icon
131
+ name="apple"
132
+ size={20}
133
+ color={'black'}
134
+ style={style.fbBtn}
135
+ />
136
+ <Text style={style.textBtn}>
137
+ {buttonText}
138
+ </Text>
139
+ </AppleButton>
134
140
  }
135
141
  </Container>
136
142
  );
137
143
  }
138
144
 
139
145
  const style = StyleSheet.create({
140
- fbBtn: {
141
- position: 'absolute',
142
- left: 0,
143
- marginHorizontal: 16
144
- },
145
- textBtn: {
146
- fontSize: 14,
147
- color: '#000000'
148
- }
149
- })
146
+ fbBtn: {
147
+ position: 'absolute',
148
+ left: 0,
149
+ marginHorizontal: 16
150
+ },
151
+ textBtn: {
152
+ fontSize: 14,
153
+ color: '#000000'
154
+ }
155
+ })
@@ -3,14 +3,20 @@ import { TouchableOpacity } from 'react-native';
3
3
  import { LogoutAction } from 'ordering-components/native';
4
4
  import { useTheme } from 'styled-components/native';
5
5
  import { OIcon, OText } from '../shared';
6
+ import { _retrieveStoreData } from '../../providers/StoreUtil';
6
7
 
7
8
  const LogoutButtonUI = (props: any) => {
8
9
  const { handleLogoutClick, text, color, iconSize } = props
9
10
  const theme = useTheme();
10
11
 
12
+ const handleClick = async () => {
13
+ const data = await _retrieveStoreData('notification_state');
14
+ handleLogoutClick(data)
15
+ };
16
+
11
17
  return (
12
18
  <TouchableOpacity
13
- onPress={() => handleLogoutClick()}
19
+ onPress={() => handleClick()}
14
20
  style={{ flexDirection: 'row', alignItems: 'center' }}
15
21
  >
16
22
  <OIcon
@@ -1,11 +1,12 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
- import { View, Pressable, StyleSheet, Linking, Platform } from 'react-native';
2
+ import { View, Pressable, StyleSheet, Linking, Platform, TouchableOpacity } from 'react-native';
3
3
  import { useForm, Controller } from 'react-hook-form';
4
4
  import Spinner from 'react-native-loading-spinner-overlay';
5
5
  import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
6
6
  import CheckBox from '@react-native-community/checkbox';
7
7
  import { PhoneInputNumber } from '../PhoneInputNumber';
8
8
  import { FacebookLogin } from '../FacebookLogin';
9
+ import Recaptcha from 'react-native-recaptcha-that-works'
9
10
 
10
11
  import {
11
12
  SignupForm as SignUpController,
@@ -23,6 +24,7 @@ import {
23
24
  LoginWith as SignupWith,
24
25
  OTab,
25
26
  OTabs,
27
+ RecaptchaButton
26
28
  } from '../LoginForm/styles';
27
29
 
28
30
  import NavBar from '../NavBar';
@@ -63,7 +65,9 @@ const SignupFormUI = (props: SignupParams) => {
63
65
  handleSendVerifyCode,
64
66
  handleCheckPhoneCode,
65
67
  notificationState,
66
- handleChangePromotions
68
+ handleChangePromotions,
69
+ enableReCaptcha,
70
+ handleReCaptcha
67
71
  } = props;
68
72
 
69
73
  const theme = useTheme();
@@ -117,6 +121,8 @@ const SignupFormUI = (props: SignupParams) => {
117
121
  cellphone: null,
118
122
  },
119
123
  });
124
+ const [recaptchaConfig, setRecaptchaConfig] = useState<any>({})
125
+ const [recaptchaVerified, setRecaptchaVerified] = useState(false)
120
126
 
121
127
  const nameRef = useRef<any>(null);
122
128
  const lastnameRef = useRef<any>(null);
@@ -125,6 +131,7 @@ const SignupFormUI = (props: SignupParams) => {
125
131
  const emailRef = useRef<any>(null);
126
132
  const phoneRef = useRef<any>(null);
127
133
  const passwordRef = useRef<any>(null);
134
+ const recaptchaRef = useRef<any>({});
128
135
 
129
136
  const showInputPhoneNumber = (validationFields?.fields?.checkout?.cellphone?.enabled ?? false) || configs?.verification_phone_required?.value === '1'
130
137
 
@@ -286,6 +293,33 @@ const SignupFormUI = (props: SignupParams) => {
286
293
  }
287
294
  }
288
295
 
296
+ const handleOpenRecaptcha = () => {
297
+ setRecaptchaVerified(false)
298
+ if (!recaptchaConfig?.siteKey) {
299
+ showToast(ToastType.Error, t('NO_RECAPTCHA_SITE_KEY', 'The config doesn\'t have recaptcha site key'));
300
+ return
301
+ }
302
+ if (!recaptchaConfig?.baseUrl) {
303
+ showToast(ToastType.Error, t('NO_RECAPTCHA_BASE_URL', 'The config doesn\'t have recaptcha base url'));
304
+ return
305
+ }
306
+ recaptchaRef.current.open()
307
+ }
308
+
309
+ const onRecaptchaVerify = (token: any) => {
310
+ setRecaptchaVerified(true)
311
+ handleReCaptcha(token)
312
+ }
313
+
314
+ useEffect(() => {
315
+ if (configs && Object.keys(configs).length > 0 && enableReCaptcha) {
316
+ setRecaptchaConfig({
317
+ siteKey: configs?.security_recaptcha_site_key?.value || null,
318
+ baseUrl: configs?.security_recaptcha_base_url?.value || null
319
+ })
320
+ }
321
+ }, [configs, enableReCaptcha])
322
+
289
323
  useEffect(() => {
290
324
  if (!formState.loading && formState.result?.error) {
291
325
  formState.result?.result &&
@@ -467,6 +501,39 @@ const SignupFormUI = (props: SignupParams) => {
467
501
  </View>
468
502
  )}
469
503
 
504
+ {enableReCaptcha && (
505
+ <>
506
+ <TouchableOpacity
507
+ onPress={handleOpenRecaptcha}
508
+ style={{ marginHorizontal: 4, marginBottom: 10 }}
509
+ >
510
+ <RecaptchaButton>
511
+ {recaptchaVerified ? (
512
+ <MaterialCommunityIcons
513
+ name="checkbox-marked"
514
+ size={23}
515
+ color={theme.colors.primary}
516
+ />
517
+ ) : (
518
+ <MaterialCommunityIcons
519
+ name="checkbox-blank-outline"
520
+ size={23}
521
+ color={theme.colors.disabled}
522
+ />
523
+ )}
524
+ <OText size={14} mLeft={8}>{t('VERIFY_ReCAPTCHA', 'Verify reCAPTCHA')}</OText>
525
+ </RecaptchaButton>
526
+ </TouchableOpacity>
527
+ <Recaptcha
528
+ ref={recaptchaRef}
529
+ siteKey={recaptchaConfig?.siteKey}
530
+ baseUrl={recaptchaConfig?.baseUrl}
531
+ onVerify={onRecaptchaVerify}
532
+ onExpire={() => setRecaptchaVerified(false)}
533
+ />
534
+ </>
535
+ )}
536
+
470
537
  <View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}>
471
538
  <Controller
472
539
  control={control}
@@ -736,6 +803,7 @@ const SignupFormUI = (props: SignupParams) => {
736
803
  export const SignupForm = (props: any) => {
737
804
  const signupProps = {
738
805
  ...props,
806
+ isRecaptchaEnable: true,
739
807
  UIComponent: SignupFormUI,
740
808
  };
741
809
  return <SignUpController {...signupProps} />;
@@ -102,6 +102,8 @@ export interface SignupParams {
102
102
  handleCheckPhoneCode?: any;
103
103
  notificationState?: any;
104
104
  handleChangePromotions: () => void;
105
+ enableReCaptcha?: boolean;
106
+ handleReCaptcha?: () => void;
105
107
  }
106
108
 
107
109
  export interface PhoneInputParams {