ordering-ui-react-native 0.14.52 → 0.14.55

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.14.52",
3
+ "version": "0.14.55",
4
4
  "description": "Reusable components made in react native",
5
5
  "main": "src/index.tsx",
6
6
  "author": "ordering.inc",
@@ -32,6 +32,7 @@ import { Wallets } from './src/components/Wallets';
32
32
  import { PaymentOptionWallet } from './src/components/PaymentOptionWallet';
33
33
  import { ProductForm } from './src/components/ProductForm';
34
34
  import { UpsellingProducts } from './src/components/UpsellingProducts';
35
+ import { VerifyEmail } from './src/components/VerifyEmail';
35
36
 
36
37
  import { Toast } from './src/components/shared/OToast';
37
38
  import {
@@ -94,6 +95,7 @@ export {
94
95
  PaymentOptionWallet,
95
96
  ProductForm,
96
97
  UpsellingProducts,
98
+ VerifyEmail,
97
99
 
98
100
  // OComponents
99
101
  Toast,
@@ -127,6 +127,8 @@ const CheckoutUI = (props: any) => {
127
127
  const [openChangeStore, setOpenChangeStore] = useState(false)
128
128
  const [isDeliveryOptionModalVisible, setIsDeliveryOptionModalVisible] = useState(false)
129
129
 
130
+ const isWalletEnabled = configs?.wallet_enabled?.value === '1'
131
+
130
132
  const driverTipsOptions = typeof configs?.driver_tip_options?.value === 'string'
131
133
  ? JSON.parse(configs?.driver_tip_options?.value) || []
132
134
  : configs?.driver_tip_options?.value || []
@@ -506,7 +508,7 @@ const CheckoutUI = (props: any) => {
506
508
  </ChSection>
507
509
  )}
508
510
 
509
- {!cartState.loading && cart && (
511
+ {!cartState.loading && cart && isWalletEnabled && (
510
512
  <WalletPaymentOptionContainer>
511
513
  <PaymentOptionWallet
512
514
  cart={cart}
@@ -5,7 +5,7 @@ import { useTheme } from 'styled-components/native';
5
5
  import { OIcon, OText } from '../shared';
6
6
 
7
7
  const LogoutButtonUI = (props: any) => {
8
- const { handleLogoutClick, text, color } = props
8
+ const { handleLogoutClick, text, color, iconSize } = props
9
9
  const theme = useTheme();
10
10
 
11
11
  return (
@@ -15,7 +15,7 @@ const LogoutButtonUI = (props: any) => {
15
15
  >
16
16
  <OIcon
17
17
  src={theme.images.general.logout}
18
- width={17}
18
+ width={iconSize ?? 17}
19
19
  color={color ? color : theme.colors.textNormal}
20
20
  style={{ marginEnd: 14 }}
21
21
  />
@@ -55,7 +55,7 @@ const PaymentOptionWalletUI = (props: any) => {
55
55
  }
56
56
 
57
57
  const handleOnChange = (position: any, wallet: any) => {
58
- const updatedCheckedState = checkedState.map((item, index) =>
58
+ const updatedCheckedState = checkedState.map((item: any, index: any) =>
59
59
  index === position ? !item : item
60
60
  );
61
61
 
@@ -85,7 +85,7 @@ const PaymentOptionWalletUI = (props: any) => {
85
85
  walletsState.result?.length > 0 &&
86
86
  (
87
87
  <>
88
- {walletsState.result?.map((wallet: any, idx: any) => wallet.valid && (
88
+ {walletsState.result?.map((wallet: any, idx: any) => wallet.valid && wallet.balance >= 0 && (
89
89
  <Container
90
90
  key={wallet.id}
91
91
  isBottomBorder={idx === walletsState.result?.filter((wallet: any) => wallet.valid)?.length - 1}
@@ -212,7 +212,9 @@ export const ProductOptionsUI = (props: any) => {
212
212
  }
213
213
 
214
214
  const handleRedirectLogin = () => {
215
- navigation.navigate('Login');
215
+ navigation.navigate('Login', {
216
+ store_slug: props.businessSlug
217
+ });
216
218
  };
217
219
 
218
220
  const handleSwitchQtyUnit = (val: string) => {
@@ -5,6 +5,7 @@ import {
5
5
  useLanguage,
6
6
  ToastType,
7
7
  useToast,
8
+ useConfig
8
9
  } from 'ordering-components/native';
9
10
  import { useTheme } from 'styled-components/native';
10
11
  import { useForm } from 'react-hook-form';
@@ -91,12 +92,15 @@ const ProfileListUI = (props: ProfileParams) => {
91
92
 
92
93
  const [{ user }] = useSession();
93
94
  const [, t] = useLanguage();
95
+ const [{ configs }] = useConfig();
94
96
  const [, { showToast }] = useToast();
95
97
  const { errors } = useForm();
96
98
 
97
99
  const { height } = useWindowDimensions();
98
100
  const { top, bottom } = useSafeAreaInsets();
99
101
 
102
+ const isWalletEnabled = configs?.wallet_enabled?.value === '1'
103
+
100
104
  const onRedirect = (route: string, params?: any) => {
101
105
  navigation.navigate(route, params)
102
106
  }
@@ -161,10 +165,12 @@ const ProfileListUI = (props: ProfileParams) => {
161
165
  <MessageCircle name='message1' style={styles.messageIconStyle} color={theme.colors.textNormal} />
162
166
  <OText size={14} lineHeight={24} weight={'400'} color={theme.colors.textNormal}>{t('MESSAGES', 'Messages')}</OText>
163
167
  </ListItem>
164
- <ListItem onPress={() => onRedirect('Wallets', { isFromProfile: true, isGoBack: true })} activeOpacity={0.7}>
165
- <Ionicons name='wallet-outline' style={styles.messageIconStyle} color={theme.colors.textNormal} />
166
- <OText size={14} lineHeight={24} weight={'400'} color={theme.colors.textNormal}>{t('WALLETS', 'Wallets')}</OText>
167
- </ListItem>
168
+ {!isWalletEnabled && (
169
+ <ListItem onPress={() => onRedirect('Wallets', { isFromProfile: true, isGoBack: true })} activeOpacity={0.7}>
170
+ <Ionicons name='wallet-outline' style={styles.messageIconStyle} color={theme.colors.textNormal} />
171
+ <OText size={14} lineHeight={24} weight={'400'} color={theme.colors.textNormal}>{t('WALLETS', 'Wallets')}</OText>
172
+ </ListItem>
173
+ )}
168
174
  <ListItem onPress={() => navigation.navigate('Help', {})} activeOpacity={0.7}>
169
175
  <OIcon src={theme.images.general.ic_help} width={16} color={theme.colors.textNormal} style={{ marginEnd: 14 }} />
170
176
  <OText size={14} lineHeight={24} weight={'400'} color={theme.colors.textNormal}>{t('HELP', 'Help')}</OText>
@@ -0,0 +1,303 @@
1
+ import React, { useEffect, useState, useRef } from 'react';
2
+ import { useTheme } from 'styled-components/native';
3
+ import {
4
+ StyleSheet,
5
+ Text,
6
+ View,
7
+ TextInput,
8
+ SafeAreaView,
9
+ TouchableOpacity,
10
+ } from 'react-native';
11
+ import {
12
+ VerifyEmail as VerifyEmailController,
13
+ useToast,
14
+ useSession,
15
+ useLanguage,
16
+ ToastType
17
+ } from 'ordering-components/native';
18
+
19
+ import { OText, OInput, OButton } from '../shared';
20
+ import { LogoutButton } from '../LogoutButton'
21
+
22
+ import {
23
+ Container,
24
+ InputsSection,
25
+ WrapperText,
26
+ InputWrapper,
27
+ WrappCountdown,
28
+ CountDownContainer,
29
+ OtpSection,
30
+ DigitInput,
31
+ ButtonsActions,
32
+ WrapperActions
33
+ } from './styles'
34
+
35
+ const TIME_COUNTDOWN = 60 * 10 // 10 minutes
36
+ const CODE_LENGTH = 6;
37
+
38
+ const VerifyEmailUI = (props: any) => {
39
+ const {
40
+ verifyEmailState,
41
+ cleanErrorsState,
42
+ sendVerifyEmailCode,
43
+ checkVerifyEmailCode,
44
+ } = props
45
+
46
+ const theme = useTheme();
47
+ const [, t] = useLanguage()
48
+ const [{ user }] = useSession()
49
+ const [, { showToast }] = useToast();
50
+
51
+ const ref = useRef<TextInput>(null);
52
+
53
+ const [otpState, setOtpState] = useState('')
54
+ const [emailVerification, setEmailVerification] = useState(false)
55
+
56
+ const [timer, setTimer] = useState(`${TIME_COUNTDOWN / 60}:00`)
57
+ const [isSendCodeAgain, setIsSendCodeAgain] = useState(false)
58
+ const [containerIsFocused, setContainerIsFocused] = useState(false);
59
+
60
+ const codeDigitsArray = new Array(CODE_LENGTH).fill(0);
61
+
62
+ const style = StyleSheet.create({
63
+ inputContainer: {
64
+ borderWidth: 1,
65
+ borderRadius: 7.6,
66
+ padding: 12,
67
+ borderColor: theme.colors.disabled,
68
+ },
69
+ inputContainerFocused: {
70
+ borderColor: theme.colors.primary,
71
+ },
72
+ hiddenCodeInput: {
73
+ position: 'absolute',
74
+ height: 0,
75
+ width: 0,
76
+ opacity: 0,
77
+ },
78
+ inputStyle: {
79
+ marginBottom: 28,
80
+ borderWidth: 1,
81
+ borderColor: theme.colors.border,
82
+ borderRadius: 7.6,
83
+ },
84
+ btnStyle: {
85
+ borderRadius: 7.6,
86
+ marginTop: 5,
87
+ marginBottom: 2
88
+ }
89
+ });
90
+
91
+ const handleOnPress = () => {
92
+ setContainerIsFocused(true);
93
+ ref?.current?.focus();
94
+ };
95
+
96
+ const handleOnBlur = () => {
97
+ setContainerIsFocused(false);
98
+ };
99
+
100
+ const toDigitInput = (_value: number, idx: number) => {
101
+ const emptyInputChar = '0';
102
+ const digit = otpState[idx] || emptyInputChar;
103
+
104
+ const isCurrentDigit = idx === otpState.length;
105
+ const isLastDigit = idx === CODE_LENGTH - 1;
106
+ const isCodeFull = otpState.length === CODE_LENGTH;
107
+
108
+ const isFocused = isCurrentDigit || (isLastDigit && isCodeFull);
109
+
110
+ const containerStyle =
111
+ containerIsFocused && isFocused
112
+ ? {...style.inputContainer, ...style.inputContainerFocused}
113
+ : style.inputContainer;
114
+
115
+ return (
116
+ <View key={idx} style={containerStyle}>
117
+ <Text
118
+ style={{
119
+ fontSize: 20,
120
+ color: otpState[idx] ? theme.colors.black : theme.colors.disabled
121
+ }}
122
+ >
123
+ {digit}
124
+ </Text>
125
+ </View>
126
+ );
127
+ };
128
+
129
+ const handleSendOtp = () => {
130
+ setTimer(`${TIME_COUNTDOWN / 60}:00`)
131
+ setIsSendCodeAgain(true)
132
+ sendVerifyEmailCode({ email: user?.email })
133
+ }
134
+
135
+ useEffect(() => {
136
+ let _timer = TIME_COUNTDOWN - 1;
137
+ let minutes = 0;
138
+ let seconds = 0;
139
+ const interval = setInterval(() => {
140
+ minutes = _timer / 60;
141
+ seconds = _timer % 60;
142
+
143
+ minutes = minutes < 10 ? 0 + minutes : minutes;
144
+ seconds = seconds < 10 ? 0 + seconds : seconds;
145
+
146
+ const formatMinutes = parseInt(minutes.toString()) < 10
147
+ ? `0${parseInt(minutes.toString())}`
148
+ : parseInt(minutes.toString());
149
+
150
+ const formatseconds = parseInt(seconds.toString()) < 10
151
+ ? `0${parseInt(seconds.toString())}`
152
+ : parseInt(seconds.toString());
153
+
154
+ setTimer(`${formatMinutes}:${formatseconds}`);
155
+
156
+ if (--_timer < 0) {
157
+ clearInterval(interval);
158
+ }
159
+
160
+ if (timer === `${TIME_COUNTDOWN / 60}:00` && isSendCodeAgain) {
161
+ setIsSendCodeAgain(false)
162
+ clearInterval(interval);
163
+ }
164
+ }, 1000);
165
+
166
+ return () => clearInterval(interval)
167
+ }, [isSendCodeAgain])
168
+
169
+ useEffect(() => {
170
+ if (otpState?.length === CODE_LENGTH) {
171
+ if (emailVerification) {
172
+ checkVerifyEmailCode({ code: otpState })
173
+ return
174
+ }
175
+ }
176
+ }, [otpState])
177
+
178
+ useEffect(() => {
179
+ if (verifyEmailState?.errorSendCode || verifyEmailState?.errorCheckCode) {
180
+ showToast(
181
+ ToastType.Error,
182
+ verifyEmailState?.errorSendCode?.[0]
183
+ ?? verifyEmailState?.errorCheckCode?.[0]
184
+ ?? t('ERROR', 'Error'),
185
+ );
186
+ setTimeout(() => {
187
+ cleanErrorsState();
188
+ setOtpState('');
189
+ }, 2000);
190
+ }
191
+ }, [verifyEmailState])
192
+
193
+ useEffect(() => {
194
+ if (!verifyEmailState?.loadingSendCode) {
195
+ setEmailVerification(!!verifyEmailState?.resultSendCode)
196
+ }
197
+ }, [verifyEmailState])
198
+
199
+ return (
200
+ <SafeAreaView style={{ flex: 1 }}>
201
+ <Container>
202
+ <WrapperActions>
203
+ <WrapperText>
204
+ <OText size={22} weight='bold' style={{ marginBottom: 10 }}>
205
+ {t('VERIFICATION_CODE', 'Verification Code')}
206
+ </OText>
207
+ <OText size={14} color={theme.colors.disabled} style={{ textAlign: 'center', paddingVertical: 20 }}>
208
+ {!emailVerification ? (
209
+ t('VERIFICATION_CODE_MESSAGE', 'In order to continue using our platform please verify your email')
210
+ ) : (
211
+ t('VERIFICATION_CODE_SENT_MESSAGE', 'Please type the verification code sent to your email')
212
+ )}
213
+ </OText>
214
+ </WrapperText>
215
+ <View style={{ position: 'absolute', top: 0, right: 0 }}>
216
+ <LogoutButton iconSize={20} />
217
+ </View>
218
+ </WrapperActions>
219
+
220
+ {!emailVerification ? (
221
+ <InputWrapper>
222
+ <OInput
223
+ placeholder={user?.email}
224
+ style={style.inputStyle}
225
+ icon={theme.images.general.email}
226
+ isDisabled
227
+ />
228
+ </InputWrapper>
229
+ ) : (
230
+ <>
231
+ <WrappCountdown>
232
+ <CountDownContainer color={timer === '00:00' ? theme.colors.error: theme.colors.success}>
233
+ <OText
234
+ size={26}
235
+ color={timer === '00:00' ? theme.colors.error: theme.colors.success}
236
+ >
237
+ {timer}
238
+ </OText>
239
+ </CountDownContainer>
240
+ </WrappCountdown>
241
+
242
+ <InputsSection>
243
+ <OtpSection>
244
+ <DigitInput
245
+ disabled={otpState.length === CODE_LENGTH}
246
+ onPress={handleOnPress}
247
+ >
248
+ {codeDigitsArray.map(toDigitInput)}
249
+ </DigitInput>
250
+ <TextInput
251
+ ref={ref}
252
+ value={otpState}
253
+ placeholder='0'
254
+ onChangeText={setOtpState}
255
+ onSubmitEditing={handleOnBlur}
256
+ keyboardType="number-pad"
257
+ returnKeyType="done"
258
+ textContentType="oneTimeCode"
259
+ maxLength={CODE_LENGTH}
260
+ style={style.hiddenCodeInput}
261
+ />
262
+ </OtpSection>
263
+ </InputsSection>
264
+
265
+ <WrapperText>
266
+ <TouchableOpacity
267
+ onPress={handleSendOtp}
268
+ >
269
+ <OText color={theme.colors.primary}>
270
+ {t('RESEND_AGAIN', 'Resend again?')}
271
+ </OText>
272
+ </TouchableOpacity>
273
+ </WrapperText>
274
+ </>
275
+ )}
276
+ </Container>
277
+ <ButtonsActions>
278
+ <View style={{ width: '100%' }}>
279
+ <OButton
280
+ onClick={emailVerification ? () => setEmailVerification(false) : handleSendOtp}
281
+ text={emailVerification ? t('CANCEL', 'Cancel') : t('SEND_CODE', 'Send code')}
282
+ bgColor={emailVerification ? theme.colors.secundary : theme.colors.primary}
283
+ borderColor={emailVerification ? theme.colors.secundary : theme.colors.primary}
284
+ textStyle={{ color: emailVerification ? 'black' : 'white' }}
285
+ imgRightSrc={null}
286
+ isLoading={verifyEmailState?.loadingSendCode || verifyEmailState?.loadingCheckCode}
287
+ style={emailVerification ? style.btnStyle : { borderRadius: 7.6 }}
288
+ />
289
+ </View>
290
+ </ButtonsActions>
291
+ </SafeAreaView>
292
+ )
293
+ }
294
+
295
+ export const VerifyEmail = (props: any) => {
296
+ const verifyProps = {
297
+ ...props,
298
+ UIComponent: VerifyEmailUI
299
+ }
300
+ return (
301
+ <VerifyEmailController {...verifyProps} />
302
+ )
303
+ }
@@ -0,0 +1,77 @@
1
+ import styled from 'styled-components/native';
2
+
3
+ export const Container = styled.View`
4
+ padding: 20px;
5
+ `
6
+
7
+ export const WrapperText = styled.View`
8
+ display: flex;
9
+ flex-direction: column;
10
+ margin: 0 auto 0px;
11
+ align-items: center;
12
+ `
13
+
14
+ export const InputWrapper = styled.View``
15
+
16
+ export const WrapperActions = styled.View`
17
+ position: relative;
18
+ `
19
+
20
+ export const ButtonsActions = styled.View`
21
+ position: absolute;
22
+ bottom: 0px;
23
+ left: 0;
24
+ right: 0;
25
+ padding: 12px 40px;
26
+ flex-direction: row;
27
+ border-top-width: 1px;
28
+ border-color: ${(props: any) => props.theme.colors.border};
29
+ width: 100%;
30
+ justify-content: space-between;
31
+ background-color: #FFF;
32
+ z-index: 1000;
33
+ justify-content: space-between;
34
+ `
35
+
36
+ export const OtpSection = styled.SafeAreaView`
37
+ flex: 1;
38
+ align-items: center;
39
+ justify-content: center;
40
+ `
41
+
42
+ export const DigitInput = styled.Pressable`
43
+ width: 80%;
44
+ flex-direction: row;
45
+ justify-content: space-between;
46
+ `
47
+
48
+ export const CountDownContainer = styled.View`
49
+ background-color: ${(props: any) => `${props.color}4D`};
50
+ border-radius: 7.6px;
51
+ padding: 5px 0px 0px;
52
+ margin: 0 auto;
53
+ display: flex;
54
+ justify-content: center;
55
+ align-items: center;
56
+ width: 80%;
57
+ `
58
+
59
+ export const WrappCountdown = styled.View`
60
+ padding-bottom: 20px;
61
+ padding-top: 20px;
62
+ `
63
+
64
+ export const InputsSection = styled.View`
65
+ display: flex;
66
+ flex-direction: row;
67
+ justify-content: space-between;
68
+ padding-bottom: 20px;
69
+ `
70
+
71
+ export const ErrorSection = styled.View`
72
+ margin-bottom: 20px;
73
+ width: 100%;
74
+ display: flex;
75
+ justify-content: center;
76
+ flex-direction: column;
77
+ `
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react'
1
+ import React, { useState, useEffect } from 'react'
2
2
  import { Pressable, View } from 'react-native';
3
3
  import { useTheme } from 'styled-components/native'
4
4
  import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
@@ -60,6 +60,14 @@ const WalletsUI = (props: any) => {
60
60
  navigation?.canGoBack() && navigation.goBack()
61
61
  }
62
62
 
63
+ useEffect(() => {
64
+ if (configs?.wallet_enabled?.value === '0') {
65
+ navigation.navigate('BottomTab', {
66
+ screen: 'Profile'
67
+ })
68
+ }
69
+ }, [configs])
70
+
63
71
  return (
64
72
  <Container>
65
73
  <NavBar