ordering-ui-react-native 0.15.98 → 0.16.1
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 +3 -2
- package/src/components/StripeMethodForm/index.tsx +21 -22
- package/src/components/UpsellingProducts/index.tsx +1 -1
- package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +1 -1
- package/themes/business/src/components/LogoutButton/index.tsx +1 -1
- package/themes/kiosk/src/components/CartBottomSheet/index.tsx +9 -2
- package/themes/kiosk/src/components/CartContent/index.tsx +0 -11
- package/themes/kiosk/src/components/CategoriesMenu/index.tsx +69 -31
- package/themes/kiosk/src/components/ProductForm/index.tsx +6 -7
- package/themes/kiosk/src/components/UpsellingProducts/index.tsx +16 -5
- package/themes/kiosk/src/types/index.d.ts +1 -0
- package/themes/original/src/components/BusinessProductsListing/index.tsx +10 -1
- package/themes/original/src/components/OrderDetails/index.tsx +2 -1
- package/themes/original/src/components/UserFormDetails/index.tsx +1 -1
- package/themes/original/src/components/UserVerification/index.tsx +178 -192
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ordering-ui-react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"description": "Reusable components made in react native",
|
|
5
5
|
"main": "src/index.tsx",
|
|
6
6
|
"author": "ordering.inc",
|
|
@@ -123,7 +123,8 @@
|
|
|
123
123
|
"@babel/core": "^7.11.6",
|
|
124
124
|
"@babel/runtime": "^7.11.2",
|
|
125
125
|
"@react-native-community/eslint-config": "^2.0.0",
|
|
126
|
-
"@types/react": "^
|
|
126
|
+
"@types/react": "^18.0.14",
|
|
127
|
+
"@types/react-dom": "^18.0.5",
|
|
127
128
|
"@types/react-native": "^0.63.25",
|
|
128
129
|
"babel-jest": "^26.3.0",
|
|
129
130
|
"eslint": "^7.10.0",
|
|
@@ -131,7 +131,7 @@ export const StripeMethodForm = (props: StripeMethodFormParams) => {
|
|
|
131
131
|
|
|
132
132
|
return (
|
|
133
133
|
<>
|
|
134
|
-
{paymethod === 'google_pay'
|
|
134
|
+
{paymethod === 'google_pay' ? (
|
|
135
135
|
<View>
|
|
136
136
|
<OButton
|
|
137
137
|
textStyle={{
|
|
@@ -145,27 +145,26 @@ export const StripeMethodForm = (props: StripeMethodFormParams) => {
|
|
|
145
145
|
style={{ marginTop: 20 }}
|
|
146
146
|
/>
|
|
147
147
|
</View>
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
// )}
|
|
148
|
+
) : (
|
|
149
|
+
<View>
|
|
150
|
+
{isApplePaySupported ? (
|
|
151
|
+
<>
|
|
152
|
+
<OText>{t('APPLE_PAY_PAYMENT', 'Apple pay payment')}</OText>
|
|
153
|
+
<ApplePayButton
|
|
154
|
+
onPress={pay}
|
|
155
|
+
type="plain"
|
|
156
|
+
buttonStyle="black"
|
|
157
|
+
borderRadius={4}
|
|
158
|
+
style={{
|
|
159
|
+
width: '100%',
|
|
160
|
+
height: 50,
|
|
161
|
+
}}
|
|
162
|
+
/>
|
|
163
|
+
</>
|
|
164
|
+
) : (
|
|
165
|
+
<OText>{t('APPLE_PAY_NOT_SUPPORTED', 'Apple pay not supported')}</OText>
|
|
166
|
+
)}
|
|
167
|
+
</View>
|
|
169
168
|
)}
|
|
170
169
|
<Spinner
|
|
171
170
|
visible={loadingGooglePayment}
|
|
@@ -15,7 +15,7 @@ const LogoutButtonUI = (props: any) => {
|
|
|
15
15
|
const data = await _retrieveStoreData('notification_state');
|
|
16
16
|
const res = await handleLogoutClick(data);
|
|
17
17
|
if (res) {
|
|
18
|
-
_clearStoreData({ excludedKeys: ['
|
|
18
|
+
_clearStoreData({ excludedKeys: ['isTutorial'] });
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
21
|
|
|
@@ -62,6 +62,10 @@ const CartBottomSheetUI = (props: CartBottomSheetUIProps): React.ReactElement |
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
const handleEditProduct = (product: any) => {
|
|
65
|
+
if (props.onEditProduct) {
|
|
66
|
+
props.onEditProduct(product)
|
|
67
|
+
return
|
|
68
|
+
}
|
|
65
69
|
setCurProduct(product)
|
|
66
70
|
setModalIsOpen(true)
|
|
67
71
|
}
|
|
@@ -148,7 +152,7 @@ const CartBottomSheetUI = (props: CartBottomSheetUIProps): React.ReactElement |
|
|
|
148
152
|
<StyledBottomContent
|
|
149
153
|
style={{bottom:10}}
|
|
150
154
|
minHeight={props.height * 0.01}
|
|
151
|
-
>
|
|
155
|
+
>
|
|
152
156
|
<OButton
|
|
153
157
|
text={(cart?.subtotal >= cart?.minimum || !cart?.minimum) && cart?.valid_address ? (
|
|
154
158
|
!openUpselling !== canOpenUpselling ? `${t('CHECKOUT', 'Checkout')} ${parsePrice(cart?.total)}`: t('LOADING', 'Loading')
|
|
@@ -198,6 +202,7 @@ const CartBottomSheetUI = (props: CartBottomSheetUIProps): React.ReactElement |
|
|
|
198
202
|
canOpenUpselling={canOpenUpselling}
|
|
199
203
|
setCanOpenUpselling={setCanOpenUpselling}
|
|
200
204
|
onClose={onCloseUpselling}
|
|
205
|
+
onAddProduct={props.onAddProduct}
|
|
201
206
|
resetInactivityTimeout={resetInactivityTimeout}
|
|
202
207
|
/>
|
|
203
208
|
)}
|
|
@@ -231,7 +236,7 @@ const TopBar = (props:any) => {
|
|
|
231
236
|
<OIconButton
|
|
232
237
|
bgColor="transparent"
|
|
233
238
|
borderColor="transparent"
|
|
234
|
-
RenderIcon={() =>
|
|
239
|
+
RenderIcon={() =>
|
|
235
240
|
<EvilIcons
|
|
236
241
|
name={'close'}
|
|
237
242
|
size={40}
|
|
@@ -260,6 +265,8 @@ interface CartBottomSheetUIProps {
|
|
|
260
265
|
onNavigationRedirect: any,
|
|
261
266
|
clearInactivityTimeout: any,
|
|
262
267
|
resetInactivityTimeout: any,
|
|
268
|
+
onEditProduct: any,
|
|
269
|
+
onAddProduct: any,
|
|
263
270
|
}
|
|
264
271
|
|
|
265
272
|
export const CartBottomSheet = (props: any) => {
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
|
-
import { useLanguage } from 'ordering-components/native';
|
|
3
2
|
import { useCartBottomSheet } from '../../providers/CartBottomSheetProvider';
|
|
4
|
-
import { CCNotCarts } from './styles';
|
|
5
3
|
|
|
6
4
|
import { Cart } from '../Cart';
|
|
7
|
-
import { OText } from '../shared';
|
|
8
5
|
import Spinner from 'react-native-loading-spinner-overlay';
|
|
9
6
|
import { Cart as TypeCart } from '../../types';
|
|
10
7
|
|
|
@@ -20,7 +17,6 @@ export const CartContent = (props: any) => {
|
|
|
20
17
|
resetInactivityTimeout,
|
|
21
18
|
}: Props = props
|
|
22
19
|
|
|
23
|
-
const [, t] = useLanguage()
|
|
24
20
|
const [isCartsLoading, setIsCartsLoading] = useState(false)
|
|
25
21
|
const [, { hideCartBottomSheet }] = useCartBottomSheet();
|
|
26
22
|
|
|
@@ -56,13 +52,6 @@ export const CartContent = (props: any) => {
|
|
|
56
52
|
}
|
|
57
53
|
</>
|
|
58
54
|
)}
|
|
59
|
-
{/* {(!cart && showNotFound) && (
|
|
60
|
-
<CCNotCarts>
|
|
61
|
-
<OText size={24} style={{ textAlign: 'center' }}>
|
|
62
|
-
{t('CARTS_NOT_FOUND', 'You don\'t have carts available')}
|
|
63
|
-
</OText>
|
|
64
|
-
</CCNotCarts>
|
|
65
|
-
)} */}
|
|
66
55
|
<Spinner visible={isCartsLoading} />
|
|
67
56
|
</>
|
|
68
57
|
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
2
2
|
import { Dimensions, Platform, View } from 'react-native';
|
|
3
3
|
import { useLanguage, useOrder, useUtils } from 'ordering-components/native';
|
|
4
4
|
import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'
|
|
@@ -41,20 +41,22 @@ const CategoriesMenu = (props: any): React.ReactElement => {
|
|
|
41
41
|
|
|
42
42
|
const theme = useTheme()
|
|
43
43
|
const [, t] = useLanguage();
|
|
44
|
-
const [curIndexCateg, setIndexCateg] = useState(categories.indexOf(category));
|
|
45
44
|
const [{ parsePrice }] = useUtils();
|
|
46
45
|
const [orientationState] = useDeviceOrientation();
|
|
47
46
|
const [bottomSheetVisibility, { showCartBottomSheet, hideCartBottomSheet }] = useCartBottomSheet();
|
|
48
|
-
|
|
47
|
+
|
|
48
|
+
const [productState, setProductState] = useState<any>(null)
|
|
49
|
+
const [productSelected, setProductSelected] = useState<any>({})
|
|
50
|
+
const [curIndexCateg, setIndexCateg] = useState(categories.indexOf(category));
|
|
49
51
|
const [drawerState, setDrawerState] = useState({ isOpen: false, data: { order: null } });
|
|
50
52
|
|
|
51
53
|
const width_dimension = Dimensions.get('window').width;
|
|
52
54
|
const height_dimension = Dimensions.get('window').height;
|
|
53
|
-
|
|
55
|
+
|
|
54
56
|
const KeyboardView = styled.KeyboardAvoidingView`
|
|
55
57
|
flex: 1;
|
|
56
58
|
`;
|
|
57
|
-
|
|
59
|
+
|
|
58
60
|
const onChangeTabs = (idx: number) => {
|
|
59
61
|
resetInactivityTimeout();
|
|
60
62
|
setIndexCateg(idx);
|
|
@@ -76,6 +78,16 @@ const CategoriesMenu = (props: any): React.ReactElement => {
|
|
|
76
78
|
cart = cartsList?.find((item: any) => item.business_id == businessId);
|
|
77
79
|
}
|
|
78
80
|
|
|
81
|
+
const onEditProduct = (product: any) => {
|
|
82
|
+
setProductSelected({ ...product, _isEditProduct: true })
|
|
83
|
+
setDrawerValues({ isOpen: true, data: null })
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const onAddProduct = (product: any) => {
|
|
87
|
+
setProductSelected(product)
|
|
88
|
+
setDrawerValues({ isOpen: true, data: null })
|
|
89
|
+
}
|
|
90
|
+
|
|
79
91
|
const cartProps = {
|
|
80
92
|
...props,
|
|
81
93
|
cart,
|
|
@@ -88,16 +100,32 @@ const CategoriesMenu = (props: any): React.ReactElement => {
|
|
|
88
100
|
visible: bottomSheetVisibility,
|
|
89
101
|
clearInactivityTimeout,
|
|
90
102
|
resetInactivityTimeout,
|
|
103
|
+
onEditProduct,
|
|
104
|
+
onAddProduct
|
|
91
105
|
},
|
|
92
106
|
showNotFound: false,
|
|
93
107
|
showCartBottomSheet,
|
|
94
108
|
}
|
|
95
109
|
|
|
110
|
+
const onClickDrawer = () => {
|
|
111
|
+
setDrawerValues({ isOpen: !drawerState.isOpen, data: null })
|
|
112
|
+
setProductState(null)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const onSaveProductForm = () => {
|
|
116
|
+
showCartBottomSheet()
|
|
117
|
+
onClickDrawer()
|
|
118
|
+
}
|
|
119
|
+
|
|
96
120
|
const onToggleCart = () => {
|
|
97
121
|
if (bottomSheetVisibility) hideCartBottomSheet();
|
|
98
122
|
else showCartBottomSheet();
|
|
99
123
|
}
|
|
100
124
|
|
|
125
|
+
const onProductStateChange = useCallback((val: any) => {
|
|
126
|
+
setProductState({ ...productState, ...val })
|
|
127
|
+
}, [setProductState])
|
|
128
|
+
|
|
101
129
|
return (
|
|
102
130
|
<>
|
|
103
131
|
<View style={{
|
|
@@ -144,12 +172,14 @@ const CategoriesMenu = (props: any): React.ReactElement => {
|
|
|
144
172
|
onSelectItem={onChangeTabs}
|
|
145
173
|
/>
|
|
146
174
|
|
|
147
|
-
<GridContainer
|
|
148
|
-
style={{
|
|
149
|
-
marginTop: 20,
|
|
175
|
+
<GridContainer
|
|
176
|
+
style={{
|
|
177
|
+
marginTop: 20,
|
|
150
178
|
paddingLeft: orientationState?.orientation === LANDSCAPE
|
|
151
|
-
|
|
152
|
-
|
|
179
|
+
? bottomSheetVisibility
|
|
180
|
+
? orientationState?.dimensions?.width * 0.004
|
|
181
|
+
: orientationState?.dimensions?.width * 0.008
|
|
182
|
+
: 0
|
|
153
183
|
}}
|
|
154
184
|
>
|
|
155
185
|
{categories[curIndexCateg].products.map((product) => (
|
|
@@ -170,8 +200,7 @@ const CategoriesMenu = (props: any): React.ReactElement => {
|
|
|
170
200
|
onPress={() => {
|
|
171
201
|
resetInactivityTimeout()
|
|
172
202
|
if (isDrawer) {
|
|
173
|
-
|
|
174
|
-
setDrawerValues({ isOpen: true, data: null })
|
|
203
|
+
onAddProduct && onAddProduct(product)
|
|
175
204
|
} else {
|
|
176
205
|
navigation.navigate('ProductDetails', {
|
|
177
206
|
businessId,
|
|
@@ -191,23 +220,22 @@ const CategoriesMenu = (props: any): React.ReactElement => {
|
|
|
191
220
|
</GridContainer>
|
|
192
221
|
</Container>
|
|
193
222
|
</View>
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
</View>
|
|
223
|
+
<View
|
|
224
|
+
style={{
|
|
225
|
+
flex: bottomSheetVisibility && orientationState?.orientation === PORTRAIT ? 0 : 0.8,
|
|
226
|
+
display: bottomSheetVisibility ? 'flex' : 'none'
|
|
227
|
+
}}
|
|
228
|
+
>
|
|
229
|
+
<CartContent
|
|
230
|
+
{...cartProps}
|
|
231
|
+
/>
|
|
232
|
+
</View>
|
|
205
233
|
</View>
|
|
206
234
|
<DrawerView
|
|
207
235
|
isOpen={drawerState.isOpen}
|
|
208
236
|
width={width_dimension - (width_dimension * 0.4)}
|
|
209
237
|
height={height_dimension}
|
|
210
|
-
onClickIcon={
|
|
238
|
+
onClickIcon={onClickDrawer}
|
|
211
239
|
>
|
|
212
240
|
<KeyboardView
|
|
213
241
|
enabled
|
|
@@ -215,14 +243,24 @@ const CategoriesMenu = (props: any): React.ReactElement => {
|
|
|
215
243
|
>
|
|
216
244
|
<ProductForm
|
|
217
245
|
isDrawer
|
|
218
|
-
product={productSelected}
|
|
219
|
-
businessId={parseInt(businessId, 10)}
|
|
220
|
-
businessSlug={businessSlug}
|
|
221
|
-
onSave={() => {
|
|
222
|
-
showCartBottomSheet()
|
|
223
|
-
setDrawerValues({ isOpen: !drawerState.isOpen, data: null })
|
|
224
|
-
}}
|
|
225
246
|
navigation={navigation}
|
|
247
|
+
{...(productSelected?._isEditProduct ? {
|
|
248
|
+
isEdit: true,
|
|
249
|
+
productCart: productState?.productCart ?? productSelected,
|
|
250
|
+
product: productState?.product,
|
|
251
|
+
businessSlug: cart?.business?.slug,
|
|
252
|
+
businessId: cart?.business_id,
|
|
253
|
+
categoryId: productSelected?.category_id,
|
|
254
|
+
productId: productSelected?.id,
|
|
255
|
+
} : {
|
|
256
|
+
product: productSelected,
|
|
257
|
+
businessSlug: businessSlug,
|
|
258
|
+
businessId: parseInt(businessId, 10),
|
|
259
|
+
productState: productState,
|
|
260
|
+
productCart: productState,
|
|
261
|
+
})}
|
|
262
|
+
onSave={onSaveProductForm}
|
|
263
|
+
onProductStateChange={onProductStateChange}
|
|
226
264
|
/>
|
|
227
265
|
</KeyboardView>
|
|
228
266
|
</DrawerView>
|
|
@@ -6,8 +6,7 @@ import {
|
|
|
6
6
|
StyleSheet,
|
|
7
7
|
Animated,
|
|
8
8
|
ScrollView,
|
|
9
|
-
|
|
10
|
-
ImageBackground
|
|
9
|
+
ImageBackground,
|
|
11
10
|
} from 'react-native'
|
|
12
11
|
import {
|
|
13
12
|
ProductForm as ProductOptions,
|
|
@@ -17,7 +16,6 @@ import {
|
|
|
17
16
|
useUtils
|
|
18
17
|
} from 'ordering-components/native'
|
|
19
18
|
import MaterialCommunityIcon from 'react-native-vector-icons/MaterialCommunityIcons'
|
|
20
|
-
import Spinner from 'react-native-loading-spinner-overlay'
|
|
21
19
|
import { useTheme } from 'styled-components/native'
|
|
22
20
|
|
|
23
21
|
import { ProductIngredient } from '../ProductIngredient'
|
|
@@ -32,12 +30,11 @@ import {
|
|
|
32
30
|
ProductComment,
|
|
33
31
|
ProductActions
|
|
34
32
|
} from './styles'
|
|
35
|
-
import { OButton,
|
|
33
|
+
import { OButton, OInput, OText } from '../shared'
|
|
36
34
|
import { ProductOptionSubOption } from '../ProductOptionSubOption'
|
|
37
35
|
import { NotFoundSource } from '../NotFoundSource'
|
|
38
36
|
import NavBar from '../NavBar'
|
|
39
37
|
import { useDeviceOrientation } from '../../../../../src/hooks/DeviceOrientation'
|
|
40
|
-
import { useCartBottomSheet } from '../../providers/CartBottomSheetProvider';
|
|
41
38
|
|
|
42
39
|
export const ProductOptionsUI = (props: any) => {
|
|
43
40
|
const {
|
|
@@ -56,7 +53,6 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
56
53
|
handleChangeCommentState,
|
|
57
54
|
productObject,
|
|
58
55
|
onClose,
|
|
59
|
-
isFromCheckout,
|
|
60
56
|
isDrawer
|
|
61
57
|
} = props;
|
|
62
58
|
|
|
@@ -66,7 +62,6 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
66
62
|
const [orderState] = useOrder();
|
|
67
63
|
const [{ auth }] = useSession();
|
|
68
64
|
const [orientationState] = useDeviceOrientation();
|
|
69
|
-
const [, { showCartBottomSheet }] = useCartBottomSheet();
|
|
70
65
|
|
|
71
66
|
const { product, loading, error } = productObject;
|
|
72
67
|
|
|
@@ -87,6 +82,8 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
87
82
|
const handleSaveProduct = () => {
|
|
88
83
|
const isErrors = Object.values(errors).length > 0
|
|
89
84
|
if (!isErrors) {
|
|
85
|
+
props.onProductStateChange &&
|
|
86
|
+
props.onProductStateChange(props.isEdit ? { product, productCart }: productCart)
|
|
90
87
|
handleSave && handleSave()
|
|
91
88
|
return
|
|
92
89
|
}
|
|
@@ -503,12 +500,14 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
503
500
|
</WrapContent>
|
|
504
501
|
</View>
|
|
505
502
|
)}
|
|
503
|
+
|
|
506
504
|
{error && error.length > 0 && (
|
|
507
505
|
<NotFoundSource
|
|
508
506
|
content={error[0]?.message || error[0]}
|
|
509
507
|
/>
|
|
510
508
|
)}
|
|
511
509
|
</ScrollView>
|
|
510
|
+
|
|
512
511
|
{!loading && !error && product && (
|
|
513
512
|
<ProductActions>
|
|
514
513
|
{productCart && !isSoldOut && maxProductQuantity > 0 && (
|
|
@@ -71,6 +71,11 @@ const UpsellingProductsUI = (props: UpsellingProductsParams) => {
|
|
|
71
71
|
}, [upsellingProducts.loading, upsellingProducts?.products.length])
|
|
72
72
|
|
|
73
73
|
const handleFormProduct = (product: any) => {
|
|
74
|
+
if (props.onAddProduct) {
|
|
75
|
+
onClose && onClose()
|
|
76
|
+
props.onAddProduct(product)
|
|
77
|
+
return
|
|
78
|
+
}
|
|
74
79
|
setActualProduct(product)
|
|
75
80
|
setModalIsOpen(true)
|
|
76
81
|
}
|
|
@@ -81,9 +86,18 @@ const UpsellingProductsUI = (props: UpsellingProductsParams) => {
|
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
const UpsellingLayout = () => {
|
|
84
|
-
|
|
85
89
|
const theme = useTheme()
|
|
86
90
|
|
|
91
|
+
const onClickProduct = (product: any) => {
|
|
92
|
+
resetInactivityTimeout()
|
|
93
|
+
if (props.onAddProduct) {
|
|
94
|
+
onClose && onClose()
|
|
95
|
+
props.onAddProduct(product)
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
handleFormProduct(product)
|
|
99
|
+
}
|
|
100
|
+
|
|
87
101
|
return (
|
|
88
102
|
<Container>
|
|
89
103
|
{
|
|
@@ -167,10 +181,7 @@ const UpsellingProductsUI = (props: UpsellingProductsParams) => {
|
|
|
167
181
|
style={{ height: 40, width: '100%' }}
|
|
168
182
|
bgColor="#EAF2FE"
|
|
169
183
|
borderColor="#EAF2FE"
|
|
170
|
-
onClick={() =>
|
|
171
|
-
resetInactivityTimeout()
|
|
172
|
-
handleFormProduct(product)
|
|
173
|
-
}}
|
|
184
|
+
onClick={() => onClickProduct(product)}
|
|
174
185
|
/>
|
|
175
186
|
</Item>
|
|
176
187
|
)) : (
|
|
@@ -177,7 +177,16 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
177
177
|
const _carts = orderState?.carts?.[adjustBusinessId]
|
|
178
178
|
const products = _carts?.products
|
|
179
179
|
const unavailableProducts = products.filter((product: any) => product.valid !== true)
|
|
180
|
-
|
|
180
|
+
const alreadyRemoved = await _retrieveStoreData('already-removed')
|
|
181
|
+
_removeStoreData('already-removed')
|
|
182
|
+
if (unavailableProducts.length > 0) {
|
|
183
|
+
multiRemoveProducts && await multiRemoveProducts(unavailableProducts, _carts)
|
|
184
|
+
return
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (alreadyRemoved === 'removed') {
|
|
188
|
+
setAlertState({ open: true, content: [t('NOT_AVAILABLE_PRODUCT', 'This product is not available.')] })
|
|
189
|
+
}
|
|
181
190
|
}
|
|
182
191
|
|
|
183
192
|
const removeCartByReOrder = async () => {
|
|
@@ -398,10 +398,11 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
398
398
|
const products = carts?.[_businessId]?.products
|
|
399
399
|
const available = products.every((product: any) => product.valid === true)
|
|
400
400
|
|
|
401
|
-
if (available && reorderState?.result?.uuid) {
|
|
401
|
+
if (available && reorderState?.result?.uuid && (products?.length === order?.products.length)) {
|
|
402
402
|
onNavigationRedirect && onNavigationRedirect('CheckoutNavigator', { cartUuid: reorderState?.result.uuid })
|
|
403
403
|
} else {
|
|
404
404
|
_setStoreData('adjust-cart-products', JSON.stringify(_businessId))
|
|
405
|
+
products?.length !== order?.products.length && _setStoreData('already-removed', JSON.stringify('removed'))
|
|
405
406
|
navigation.navigate('Business', { store: businessData?.slug })
|
|
406
407
|
}
|
|
407
408
|
}
|
|
@@ -229,7 +229,7 @@ export const UserFormDetailsUI = (props: any) => {
|
|
|
229
229
|
|
|
230
230
|
useEffect(() => {
|
|
231
231
|
if (!phoneInputData.error && phoneInputData?.phone?.country_phone_code && phoneInputData?.phone?.cellphone) {
|
|
232
|
-
setWillVerifyOtpState(true)
|
|
232
|
+
setWillVerifyOtpState?.(true)
|
|
233
233
|
}
|
|
234
234
|
}, [phoneInputData])
|
|
235
235
|
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
TextInput,
|
|
8
8
|
SafeAreaView,
|
|
9
9
|
TouchableOpacity,
|
|
10
|
+
ScrollView,
|
|
10
11
|
} from 'react-native';
|
|
11
12
|
import {
|
|
12
13
|
UserVerification as UserVerificationController,
|
|
@@ -81,7 +82,6 @@ const UserVerificationUI = (props: any) => {
|
|
|
81
82
|
const [containerIsFocused, setContainerIsFocused] = useState(false);
|
|
82
83
|
|
|
83
84
|
const [phoneState, setPhoneState] = useState<any>(null)
|
|
84
|
-
const [modalIsOpen, setModalIsOpen] = useState(false)
|
|
85
85
|
const [verificationState, setVerificationState] = useState({ email: false, phone: false })
|
|
86
86
|
|
|
87
87
|
const codeDigitsArray = new Array(CODE_LENGTH).fill(0);
|
|
@@ -155,7 +155,7 @@ const UserVerificationUI = (props: any) => {
|
|
|
155
155
|
|
|
156
156
|
const containerStyle =
|
|
157
157
|
containerIsFocused && isFocused
|
|
158
|
-
? {...style.inputContainer, ...style.inputContainerFocused}
|
|
158
|
+
? { ...style.inputContainer, ...style.inputContainerFocused }
|
|
159
159
|
: style.inputContainer;
|
|
160
160
|
|
|
161
161
|
return (
|
|
@@ -250,8 +250,8 @@ const UserVerificationUI = (props: any) => {
|
|
|
250
250
|
showToast(
|
|
251
251
|
ToastType.Error,
|
|
252
252
|
verifyEmailState?.errorSendCode?.[0]
|
|
253
|
-
|
|
254
|
-
|
|
253
|
+
?? verifyEmailState?.errorCheckCode?.[0]
|
|
254
|
+
?? t('ERROR', 'Error'),
|
|
255
255
|
);
|
|
256
256
|
setTimeout(() => {
|
|
257
257
|
cleanErrorsState();
|
|
@@ -264,8 +264,8 @@ const UserVerificationUI = (props: any) => {
|
|
|
264
264
|
showToast(
|
|
265
265
|
ToastType.Error,
|
|
266
266
|
verifyPhoneState?.errorSendCode?.[0]
|
|
267
|
-
|
|
268
|
-
|
|
267
|
+
?? verifyPhoneState?.errorCheckCode?.[0]
|
|
268
|
+
?? t('ERROR', 'Error'),
|
|
269
269
|
);
|
|
270
270
|
setTimeout(() => {
|
|
271
271
|
cleanErrorsState();
|
|
@@ -296,209 +296,195 @@ const UserVerificationUI = (props: any) => {
|
|
|
296
296
|
|
|
297
297
|
return (
|
|
298
298
|
<SafeAreaView style={{ flex: 1 }}>
|
|
299
|
-
<
|
|
300
|
-
<
|
|
301
|
-
<
|
|
302
|
-
<
|
|
303
|
-
{
|
|
304
|
-
|
|
305
|
-
{isEmailVerifyRequired && (
|
|
306
|
-
<OText size={14} color={theme.colors.disabled} style={{ textAlign: 'center', paddingVertical: 20 }}>
|
|
307
|
-
{!verificationState.email ? (
|
|
308
|
-
t('VERIFICATION_EMAIL_CODE_MESSAGE', 'In order to continue using our platform please verify your email')
|
|
309
|
-
) : (
|
|
310
|
-
t('VERIFICATION_EMAIL_CODE_SENT_MESSAGE', 'Please type the verification code sent to your email')
|
|
311
|
-
)}
|
|
299
|
+
<ScrollView>
|
|
300
|
+
<Container>
|
|
301
|
+
<WrapperActions>
|
|
302
|
+
<WrapperText>
|
|
303
|
+
<OText size={22} weight='bold' style={{ marginBottom: 10 }}>
|
|
304
|
+
{t('VERIFICATION_CODE', 'Verification Code')}
|
|
312
305
|
</OText>
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
{timer}
|
|
349
|
-
</OText>
|
|
350
|
-
</CountDownContainer>
|
|
351
|
-
</WrappCountdown>
|
|
352
|
-
|
|
353
|
-
<InputsSection>
|
|
354
|
-
<OtpSection>
|
|
355
|
-
<DigitInput
|
|
356
|
-
disabled={otpState.length === CODE_LENGTH}
|
|
357
|
-
onPress={handleOnPress}
|
|
358
|
-
>
|
|
359
|
-
{codeDigitsArray.map(toDigitInput)}
|
|
360
|
-
</DigitInput>
|
|
361
|
-
<TextInput
|
|
362
|
-
ref={ref}
|
|
363
|
-
value={otpState}
|
|
364
|
-
placeholder='0'
|
|
365
|
-
onChangeText={setOtpState}
|
|
366
|
-
onSubmitEditing={handleOnBlur}
|
|
367
|
-
keyboardType="number-pad"
|
|
368
|
-
returnKeyType="done"
|
|
369
|
-
textContentType="oneTimeCode"
|
|
370
|
-
maxLength={CODE_LENGTH}
|
|
371
|
-
style={style.hiddenCodeInput}
|
|
372
|
-
/>
|
|
373
|
-
</OtpSection>
|
|
374
|
-
</InputsSection>
|
|
375
|
-
|
|
376
|
-
<WrapperText>
|
|
377
|
-
<TouchableOpacity
|
|
378
|
-
onPress={() => handleSendOtp()}
|
|
379
|
-
>
|
|
380
|
-
<OText color={theme.colors.primary}>
|
|
381
|
-
{t('RESEND_AGAIN', 'Resend again?')}
|
|
382
|
-
</OText>
|
|
383
|
-
</TouchableOpacity>
|
|
384
|
-
</WrapperText>
|
|
385
|
-
</>
|
|
386
|
-
)
|
|
387
|
-
)}
|
|
388
|
-
|
|
389
|
-
{isPhoneVerifyRequired && !isEmailVerifyRequired && (
|
|
390
|
-
!verificationState.phone ? (
|
|
391
|
-
phoneState?.formatted ? (
|
|
392
|
-
<>
|
|
393
|
-
<InputWrapper phone>
|
|
394
|
-
<PhoneInputNumber
|
|
395
|
-
handleData={() => {}}
|
|
396
|
-
defaultValue={phoneState?.cellphone}
|
|
397
|
-
defaultCode={phoneState?.country_phone_code.replace('+', '')}
|
|
398
|
-
boxStyle={style.phoneSelect}
|
|
399
|
-
inputStyle={style.phoneInputStyle}
|
|
400
|
-
textStyle={{ color: theme.colors.textNormal, fontSize: 12, padding: 0 }}
|
|
401
|
-
noDropIcon
|
|
402
|
-
isDisabled
|
|
403
|
-
/>
|
|
404
|
-
</InputWrapper>
|
|
405
|
-
</>
|
|
306
|
+
{isEmailVerifyRequired && (
|
|
307
|
+
<OText size={14} color={theme.colors.disabled} style={{ textAlign: 'center', paddingVertical: 20 }}>
|
|
308
|
+
{!verificationState.email ? (
|
|
309
|
+
t('VERIFICATION_EMAIL_CODE_MESSAGE', 'In order to continue using our platform please verify your email')
|
|
310
|
+
) : (
|
|
311
|
+
t('VERIFICATION_EMAIL_CODE_SENT_MESSAGE', 'Please type the verification code sent to your email')
|
|
312
|
+
)}
|
|
313
|
+
</OText>
|
|
314
|
+
)}
|
|
315
|
+
|
|
316
|
+
{isPhoneVerifyRequired && !isEmailVerifyRequired && (
|
|
317
|
+
<OText size={14} color={theme.colors.disabled} style={{ textAlign: 'center', paddingVertical: 20 }}>
|
|
318
|
+
{!verificationState.phone ? (
|
|
319
|
+
t('VERIFICATION_PHONE_CODE_MESSAGE', 'In order to continue using our platform please verify your phone number')
|
|
320
|
+
) : (
|
|
321
|
+
t('VERIFICATION_PHONE_CODE_SENT_MESSAGE', 'Please, enter the verification code we sent to your mobile ending with :number').replace(':number', lastNumbers)
|
|
322
|
+
)}
|
|
323
|
+
</OText>
|
|
324
|
+
)}
|
|
325
|
+
</WrapperText>
|
|
326
|
+
<View style={{ position: 'absolute', top: 0, right: 0 }}>
|
|
327
|
+
<LogoutButton iconSize={20} />
|
|
328
|
+
</View>
|
|
329
|
+
</WrapperActions>
|
|
330
|
+
|
|
331
|
+
{isEmailVerifyRequired && (
|
|
332
|
+
!verificationState.email ? (
|
|
333
|
+
<InputWrapper>
|
|
334
|
+
<OInput
|
|
335
|
+
placeholder={user?.email}
|
|
336
|
+
style={style.inputStyle}
|
|
337
|
+
icon={theme.images.general.email}
|
|
338
|
+
isDisabled
|
|
339
|
+
/>
|
|
340
|
+
</InputWrapper>
|
|
406
341
|
) : (
|
|
407
342
|
<>
|
|
343
|
+
<WrappCountdown>
|
|
344
|
+
<CountDownContainer color={timer === '00:00' ? theme.colors.error : theme.colors.success}>
|
|
345
|
+
<OText
|
|
346
|
+
size={26}
|
|
347
|
+
color={timer === '00:00' ? theme.colors.error : theme.colors.success}
|
|
348
|
+
>
|
|
349
|
+
{timer}
|
|
350
|
+
</OText>
|
|
351
|
+
</CountDownContainer>
|
|
352
|
+
</WrappCountdown>
|
|
353
|
+
|
|
354
|
+
<InputsSection>
|
|
355
|
+
<OtpSection>
|
|
356
|
+
<DigitInput
|
|
357
|
+
disabled={otpState.length === CODE_LENGTH}
|
|
358
|
+
onPress={handleOnPress}
|
|
359
|
+
>
|
|
360
|
+
{codeDigitsArray.map(toDigitInput)}
|
|
361
|
+
</DigitInput>
|
|
362
|
+
<TextInput
|
|
363
|
+
ref={ref}
|
|
364
|
+
value={otpState}
|
|
365
|
+
placeholder='0'
|
|
366
|
+
onChangeText={setOtpState}
|
|
367
|
+
onSubmitEditing={handleOnBlur}
|
|
368
|
+
keyboardType="number-pad"
|
|
369
|
+
returnKeyType="done"
|
|
370
|
+
textContentType="oneTimeCode"
|
|
371
|
+
maxLength={CODE_LENGTH}
|
|
372
|
+
style={style.hiddenCodeInput}
|
|
373
|
+
/>
|
|
374
|
+
</OtpSection>
|
|
375
|
+
</InputsSection>
|
|
376
|
+
|
|
377
|
+
<WrapperText>
|
|
378
|
+
<TouchableOpacity
|
|
379
|
+
onPress={() => handleSendOtp()}
|
|
380
|
+
>
|
|
381
|
+
<OText color={theme.colors.primary}>
|
|
382
|
+
{t('RESEND_AGAIN', 'Resend again?')}
|
|
383
|
+
</OText>
|
|
384
|
+
</TouchableOpacity>
|
|
385
|
+
</WrapperText>
|
|
386
|
+
</>
|
|
387
|
+
)
|
|
388
|
+
)}
|
|
389
|
+
|
|
390
|
+
{isPhoneVerifyRequired && !isEmailVerifyRequired && (
|
|
391
|
+
!verificationState.phone ? (
|
|
392
|
+
phoneState?.formatted ? (
|
|
393
|
+
<>
|
|
394
|
+
<InputWrapper phone>
|
|
395
|
+
<PhoneInputNumber
|
|
396
|
+
handleData={() => { }}
|
|
397
|
+
defaultValue={phoneState?.cellphone}
|
|
398
|
+
defaultCode={phoneState?.country_phone_code.replace('+', '')}
|
|
399
|
+
boxStyle={style.phoneSelect}
|
|
400
|
+
inputStyle={style.phoneInputStyle}
|
|
401
|
+
textStyle={{ color: theme.colors.textNormal, fontSize: 12, padding: 0 }}
|
|
402
|
+
noDropIcon
|
|
403
|
+
isDisabled
|
|
404
|
+
/>
|
|
405
|
+
</InputWrapper>
|
|
406
|
+
</>
|
|
407
|
+
) : (
|
|
408
408
|
<OText size={14} color={theme.colors.disabled} style={{ textAlign: 'center', paddingVertical: 20 }}>
|
|
409
409
|
{t('WARNING_PHONE_CODE_VALIDATION', 'Please update your phone number to continue')}
|
|
410
410
|
</OText>
|
|
411
|
+
)
|
|
412
|
+
) : (
|
|
413
|
+
<>
|
|
414
|
+
<WrappCountdown>
|
|
415
|
+
<CountDownContainer color={timer === '00:00' ? theme.colors.error : theme.colors.success}>
|
|
416
|
+
<OText
|
|
417
|
+
size={26}
|
|
418
|
+
color={timer === '00:00' ? theme.colors.error : theme.colors.success}
|
|
419
|
+
>
|
|
420
|
+
{timer}
|
|
421
|
+
</OText>
|
|
422
|
+
</CountDownContainer>
|
|
423
|
+
</WrappCountdown>
|
|
424
|
+
|
|
425
|
+
<InputsSection>
|
|
426
|
+
<OtpSection>
|
|
427
|
+
<DigitInput
|
|
428
|
+
disabled={otpState.length === CODE_LENGTH}
|
|
429
|
+
onPress={handleOnPress}
|
|
430
|
+
>
|
|
431
|
+
{codeDigitsArray.map(toDigitInput)}
|
|
432
|
+
</DigitInput>
|
|
433
|
+
<TextInput
|
|
434
|
+
ref={ref}
|
|
435
|
+
value={otpState}
|
|
436
|
+
placeholder='0'
|
|
437
|
+
onChangeText={setOtpState}
|
|
438
|
+
onSubmitEditing={handleOnBlur}
|
|
439
|
+
keyboardType="number-pad"
|
|
440
|
+
returnKeyType="done"
|
|
441
|
+
textContentType="oneTimeCode"
|
|
442
|
+
maxLength={CODE_LENGTH}
|
|
443
|
+
style={style.hiddenCodeInput}
|
|
444
|
+
/>
|
|
445
|
+
</OtpSection>
|
|
446
|
+
</InputsSection>
|
|
447
|
+
|
|
411
448
|
<WrapperText>
|
|
412
449
|
<TouchableOpacity
|
|
413
|
-
onPress={() =>
|
|
450
|
+
onPress={() => handleSendOtp('phone')}
|
|
451
|
+
disabled={verifyPhoneState?.loadingSendCode || verifyPhoneState?.loadingCheckCode}
|
|
414
452
|
>
|
|
415
453
|
<OText color={theme.colors.primary}>
|
|
416
|
-
{t('
|
|
454
|
+
{t('RESEND_AGAIN', 'Resend again?')}
|
|
417
455
|
</OText>
|
|
418
456
|
</TouchableOpacity>
|
|
419
457
|
</WrapperText>
|
|
420
458
|
</>
|
|
421
459
|
)
|
|
422
|
-
)
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
onChangeText={setOtpState}
|
|
448
|
-
onSubmitEditing={handleOnBlur}
|
|
449
|
-
keyboardType="number-pad"
|
|
450
|
-
returnKeyType="done"
|
|
451
|
-
textContentType="oneTimeCode"
|
|
452
|
-
maxLength={CODE_LENGTH}
|
|
453
|
-
style={style.hiddenCodeInput}
|
|
454
|
-
/>
|
|
455
|
-
</OtpSection>
|
|
456
|
-
</InputsSection>
|
|
457
|
-
|
|
458
|
-
<WrapperText>
|
|
459
|
-
<TouchableOpacity
|
|
460
|
-
onPress={() => handleSendOtp('phone')}
|
|
461
|
-
disabled={verifyPhoneState?.loadingSendCode || verifyPhoneState?.loadingCheckCode}
|
|
462
|
-
>
|
|
463
|
-
<OText color={theme.colors.primary}>
|
|
464
|
-
{t('RESEND_AGAIN', 'Resend again?')}
|
|
465
|
-
</OText>
|
|
466
|
-
</TouchableOpacity>
|
|
467
|
-
</WrapperText>
|
|
468
|
-
</>
|
|
469
|
-
)
|
|
470
|
-
)}
|
|
471
|
-
|
|
472
|
-
</Container>
|
|
473
|
-
<ButtonsActions>
|
|
474
|
-
<View style={{ width: '100%' }}>
|
|
475
|
-
<OButton
|
|
476
|
-
onClick={(verificationState.email || verificationState.phone)
|
|
477
|
-
? () => setVerificationState({ email: false, phone: false })
|
|
478
|
-
: () => handleSendOtp(isPhoneVerifyRequired && !isEmailVerifyRequired ? 'phone' : '')
|
|
479
|
-
}
|
|
480
|
-
text={(verificationState.email || verificationState.phone) ? t('CANCEL', 'Cancel') : t('SEND_CODE', 'Send code')}
|
|
481
|
-
bgColor={(verificationState.email || verificationState.phone) ? theme.colors.secundary : theme.colors.primary}
|
|
482
|
-
borderColor={(verificationState.email || verificationState.phone) ? theme.colors.secundary : theme.colors.primary}
|
|
483
|
-
textStyle={{ color: (verificationState.email || verificationState.phone) ? 'black' : 'white' }}
|
|
484
|
-
imgRightSrc={null}
|
|
485
|
-
isLoading={verifyEmailState?.loadingSendCode || verifyEmailState?.loadingCheckCode || verifyPhoneState?.loadingSendCode || verifyPhoneState?.loadingCheckCode}
|
|
486
|
-
style={(verificationState.email || verificationState.phone) ? style.btnStyle : { borderRadius: 7.6 }}
|
|
460
|
+
)}
|
|
461
|
+
|
|
462
|
+
</Container>
|
|
463
|
+
<ButtonsActions>
|
|
464
|
+
<View style={{ width: '100%' }}>
|
|
465
|
+
<OButton
|
|
466
|
+
onClick={(verificationState.email || verificationState.phone)
|
|
467
|
+
? () => setVerificationState({ email: false, phone: false })
|
|
468
|
+
: () => handleSendOtp(isPhoneVerifyRequired && !isEmailVerifyRequired ? 'phone' : '')
|
|
469
|
+
}
|
|
470
|
+
text={(verificationState.email || verificationState.phone) ? t('CANCEL', 'Cancel') : t('SEND_CODE', 'Send code')}
|
|
471
|
+
bgColor={(verificationState.email || verificationState.phone) ? theme.colors.secundary : theme.colors.primary}
|
|
472
|
+
borderColor={(verificationState.email || verificationState.phone) ? theme.colors.secundary : theme.colors.primary}
|
|
473
|
+
textStyle={{ color: (verificationState.email || verificationState.phone) ? 'black' : 'white' }}
|
|
474
|
+
imgRightSrc={null}
|
|
475
|
+
isLoading={verifyEmailState?.loadingSendCode || verifyEmailState?.loadingCheckCode || verifyPhoneState?.loadingSendCode || verifyPhoneState?.loadingCheckCode}
|
|
476
|
+
style={(verificationState.email || verificationState.phone) ? style.btnStyle : { borderRadius: 7.6 }}
|
|
477
|
+
/>
|
|
478
|
+
</View>
|
|
479
|
+
</ButtonsActions>
|
|
480
|
+
<View style={{ paddingHorizontal: 20, paddingBottom: 80 }}>
|
|
481
|
+
<UserDetails
|
|
482
|
+
user={user}
|
|
483
|
+
isEdit
|
|
484
|
+
isVerifiedPhone
|
|
487
485
|
/>
|
|
488
486
|
</View>
|
|
489
|
-
</
|
|
490
|
-
|
|
491
|
-
<OModal
|
|
492
|
-
open={modalIsOpen}
|
|
493
|
-
entireModal
|
|
494
|
-
customClose
|
|
495
|
-
onClose={() => setModalIsOpen(false)}
|
|
496
|
-
>
|
|
497
|
-
<UserDetails
|
|
498
|
-
user={user}
|
|
499
|
-
handleSuccessUpdate={() => setModalIsOpen(false)}
|
|
500
|
-
/>
|
|
501
|
-
</OModal>
|
|
487
|
+
</ScrollView>
|
|
502
488
|
</SafeAreaView>
|
|
503
489
|
)
|
|
504
490
|
}
|