ordering-ui-react-native 0.12.16 → 0.12.20
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 +1 -1
- package/src/config.json +2 -2
- package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +168 -156
- package/themes/business/src/components/NewOrderNotification/index.tsx +14 -1
- package/themes/business/src/components/OrderDetails/Delivery.tsx +3 -1
- package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +1 -1
- package/themes/business/src/components/OrdersOption/index.tsx +88 -123
- package/themes/business/src/components/PreviousOrders/index.tsx +69 -94
- package/themes/business/src/components/PreviousOrders/styles.tsx +0 -7
- package/themes/business/src/components/ProductItemAccordion/index.tsx +25 -27
- package/themes/business/src/components/shared/OIcon.tsx +0 -2
- package/themes/business/src/types/index.tsx +4 -1
- package/themes/doordash/src/components/BusinessProductsCategories/index.tsx +60 -5
- package/themes/doordash/src/components/BusinessProductsList/index.tsx +144 -79
- package/themes/doordash/src/components/BusinessProductsListing/index.tsx +58 -26
- package/themes/doordash/src/components/ForgotPasswordForm/index.tsx +37 -35
- package/themes/doordash/src/components/ForgotPasswordForm/styles.tsx +7 -0
- package/themes/doordash/src/components/Help/index.tsx +1 -1
- package/themes/doordash/src/components/LastOrders/index.tsx +9 -3
- package/themes/doordash/src/components/LastOrders/styles.tsx +1 -1
- package/themes/doordash/src/components/ProductForm/index.tsx +1 -1
- package/themes/doordash/src/types/index.tsx +11 -1
- package/themes/kiosk/src/components/CategoriesMenu/index.tsx +128 -83
- package/themes/kiosk/src/components/DrawerView/index.tsx +57 -0
- package/themes/kiosk/src/components/DrawerView/styles.tsx +30 -0
- package/themes/kiosk/src/components/ProductForm/index.tsx +22 -20
- package/themes/kiosk/src/components/ProductForm/styles.tsx +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react'
|
|
2
2
|
import { BusinessProductsCategories as ProductsCategories } from 'ordering-components/native'
|
|
3
3
|
import { I18nManager, ScrollView, StyleSheet, View } from 'react-native'
|
|
4
4
|
import { Tab } from './styles'
|
|
@@ -15,8 +15,20 @@ const BusinessProductsCategoriesUI = (props: any) => {
|
|
|
15
15
|
categorySelected,
|
|
16
16
|
loading,
|
|
17
17
|
contentStyle,
|
|
18
|
+
scrollViewRef,
|
|
19
|
+
productListLayout,
|
|
20
|
+
categoriesLayout,
|
|
21
|
+
selectedCategoryId,
|
|
22
|
+
lazyLoadProductsRecommended,
|
|
23
|
+
setSelectedCategoryId,
|
|
24
|
+
setCategoryClicked
|
|
18
25
|
} = props
|
|
19
26
|
|
|
27
|
+
const [tabLayouts, setTabLayouts] = useState<any>({});
|
|
28
|
+
const [scrollOffsetX, setScrollOffsetX] = useState<any>(0);
|
|
29
|
+
const tabsRef = useRef<any>(null);
|
|
30
|
+
|
|
31
|
+
|
|
20
32
|
const theme = useTheme();
|
|
21
33
|
|
|
22
34
|
const styles = StyleSheet.create({
|
|
@@ -41,8 +53,50 @@ const BusinessProductsCategoriesUI = (props: any) => {
|
|
|
41
53
|
}
|
|
42
54
|
})
|
|
43
55
|
|
|
56
|
+
const handleCategoryScroll = (category: any) => {
|
|
57
|
+
setCategoryClicked(true);
|
|
58
|
+
setSelectedCategoryId(`cat_${category?.id}`);
|
|
59
|
+
|
|
60
|
+
if (!lazyLoadProductsRecommended) {
|
|
61
|
+
if (category?.id) {
|
|
62
|
+
scrollViewRef.current.scrollTo({
|
|
63
|
+
y: categoriesLayout[`cat_${category?.id}`]?.y + productListLayout?.y + 270,
|
|
64
|
+
animated: true
|
|
65
|
+
})
|
|
66
|
+
} else {
|
|
67
|
+
scrollViewRef.current.scrollTo({
|
|
68
|
+
y: productListLayout?.y - 70,
|
|
69
|
+
animated: true
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
handlerClickCategory(category)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
const handleOnLayout = (event: any, categoryId: any) => {
|
|
79
|
+
const _tabLayouts = { ...tabLayouts }
|
|
80
|
+
const categoryKey = 'cat_' + categoryId
|
|
81
|
+
_tabLayouts[categoryKey] = event.nativeEvent.layout
|
|
82
|
+
setTabLayouts(_tabLayouts)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (!selectedCategoryId || Object.keys(tabLayouts).length === 0) return
|
|
87
|
+
tabsRef.current.scrollTo({
|
|
88
|
+
x: tabLayouts[selectedCategoryId]?.x - 40,
|
|
89
|
+
animated: true
|
|
90
|
+
})
|
|
91
|
+
}, [selectedCategoryId, tabLayouts])
|
|
92
|
+
|
|
93
|
+
|
|
44
94
|
return (
|
|
45
|
-
<ScrollView horizontal contentContainerStyle={contentStyle}
|
|
95
|
+
<ScrollView ref={tabsRef} horizontal contentContainerStyle={contentStyle}
|
|
96
|
+
style={{ ...styles.container, borderBottomWidth: loading ? 0 : 1 }} showsHorizontalScrollIndicator={false}
|
|
97
|
+
onScroll={(e: any) => setScrollOffsetX(e.nativeEvent.contentOffset.x)}
|
|
98
|
+
scrollEventThrottle={16}
|
|
99
|
+
>
|
|
46
100
|
{loading && (
|
|
47
101
|
<Placeholder Animation={Fade}>
|
|
48
102
|
<View style={{ flexDirection: 'row' }}>
|
|
@@ -56,15 +110,16 @@ const BusinessProductsCategoriesUI = (props: any) => {
|
|
|
56
110
|
!loading && categories && categories.length && categories.map((category: any) => (
|
|
57
111
|
<Tab
|
|
58
112
|
key={category.name}
|
|
59
|
-
onPress={() =>
|
|
113
|
+
onPress={() => handleCategoryScroll(category)}
|
|
60
114
|
style={{ ...(category.id === 'featured') && !featured && styles.featuredStyle }}
|
|
115
|
+
onLayout={(event: any) => handleOnLayout(event, category.id)}
|
|
61
116
|
>
|
|
62
117
|
<OText
|
|
63
|
-
color={
|
|
118
|
+
color={selectedCategoryId === `cat_${category.id}` ? theme.colors.textPrimary : theme.colors.textSecondary}
|
|
64
119
|
>
|
|
65
120
|
{category.name}
|
|
66
121
|
</OText>
|
|
67
|
-
<View style={
|
|
122
|
+
<View style={selectedCategoryId === `cat_${category.id}` ? styles.tabStyle : styles.tabDeactived} />
|
|
68
123
|
</Tab>
|
|
69
124
|
))
|
|
70
125
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react'
|
|
2
|
-
import { ProductsList, useLanguage } from 'ordering-components/native'
|
|
1
|
+
import React, { useState, useEffect, Fragment } from 'react'
|
|
2
|
+
import { ProductsList, useLanguage, useUtils } from 'ordering-components/native'
|
|
3
3
|
import { SingleProductCard } from '../SingleProductCard'
|
|
4
4
|
import { NotFoundSource } from '../NotFoundSource'
|
|
5
5
|
import { BusinessProductsListParams } from '../../types'
|
|
6
|
-
import { OText } from '../shared'
|
|
6
|
+
import { OIcon, OText } from '../shared'
|
|
7
7
|
import {
|
|
8
8
|
ProductsContainer,
|
|
9
9
|
ErrorMessage,
|
|
10
10
|
WrapperNotFound
|
|
11
11
|
} from './styles'
|
|
12
12
|
import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder'
|
|
13
|
-
import { Platform, View } from 'react-native'
|
|
13
|
+
import { Platform, StyleSheet, View } from 'react-native'
|
|
14
14
|
|
|
15
15
|
const BusinessProductsListUI = (props: BusinessProductsListParams) => {
|
|
16
16
|
const {
|
|
@@ -27,120 +27,173 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
|
|
|
27
27
|
handleClearSearch,
|
|
28
28
|
errorQuantityProducts,
|
|
29
29
|
handleCancelSearch,
|
|
30
|
-
sortBy
|
|
30
|
+
sortBy,
|
|
31
|
+
categoriesLayout,
|
|
32
|
+
setCategoriesLayout
|
|
31
33
|
} = props
|
|
32
34
|
|
|
33
35
|
const [, t] = useLanguage()
|
|
34
|
-
const [
|
|
35
|
-
const [allProducts, setAllProducts] = useState(categoryState.products);
|
|
36
|
+
const [{optimizeImage}] = useUtils();
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
38
|
+
const handleOnLayout = (event: any, categoryId: any) => {
|
|
39
|
+
const _categoriesLayout = { ...categoriesLayout }
|
|
40
|
+
const categoryKey = 'cat_' + categoryId
|
|
41
|
+
_categoriesLayout[categoryKey] = event.nativeEvent.layout
|
|
42
|
+
setCategoriesLayout(_categoriesLayout)
|
|
43
|
+
}
|
|
43
44
|
|
|
44
45
|
return (
|
|
45
46
|
<ProductsContainer>
|
|
46
|
-
{category.id &&
|
|
47
|
-
|
|
47
|
+
{category.id &&
|
|
48
|
+
categoryState.products?.map((product: any) => (
|
|
48
49
|
<SingleProductCard
|
|
49
|
-
key={product.id}
|
|
50
|
-
isSoldOut={
|
|
50
|
+
key={'prod_' + product.id}
|
|
51
|
+
isSoldOut={product.inventoried && !product.quantity}
|
|
51
52
|
product={product}
|
|
52
53
|
businessId={businessId}
|
|
53
54
|
onProductClick={() => onProductClick(product)}
|
|
54
55
|
/>
|
|
55
|
-
))
|
|
56
|
-
)}
|
|
56
|
+
))}
|
|
57
57
|
|
|
58
|
-
{
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
{!category.id &&
|
|
59
|
+
featured &&
|
|
60
|
+
categoryState?.products?.find((product: any) => product.featured) && (
|
|
61
|
+
<View
|
|
62
|
+
onLayout={(event: any) => handleOnLayout(event, 'featured')}
|
|
63
|
+
>
|
|
64
|
+
<OText size={16} weight={'600'} mBottom={15}>
|
|
65
|
+
{t('FEATURED', 'Featured')}
|
|
66
|
+
</OText>
|
|
61
67
|
<>
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
{categoryState.products?.map(
|
|
69
|
+
(product: any, i: any) =>
|
|
70
|
+
product.featured && (
|
|
71
|
+
<SingleProductCard
|
|
72
|
+
key={i}
|
|
73
|
+
isSoldOut={product.inventoried && !product.quantity}
|
|
74
|
+
product={product}
|
|
75
|
+
businessId={businessId}
|
|
76
|
+
onProductClick={onProductClick}
|
|
77
|
+
/>
|
|
78
|
+
),
|
|
79
|
+
)}
|
|
72
80
|
</>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
81
|
+
</View>
|
|
82
|
+
)}
|
|
83
|
+
|
|
76
84
|
|
|
77
|
-
{
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
{!category.id &&
|
|
86
|
+
categories &&
|
|
87
|
+
categories
|
|
88
|
+
.filter((category) => category.id !== null)
|
|
89
|
+
.map((category, i, _categories) => {
|
|
90
|
+
const products =
|
|
91
|
+
categoryState.products?.filter(
|
|
92
|
+
(product: any) => product.category_id === category.id,
|
|
93
|
+
) || [];
|
|
94
|
+
return (
|
|
95
|
+
<React.Fragment key={'cat_' + category.id}>
|
|
96
|
+
{products.length > 0 && (
|
|
97
|
+
<Fragment>
|
|
98
|
+
<View
|
|
99
|
+
style={bpStyles.catWrap}
|
|
100
|
+
onLayout={(event: any) => handleOnLayout(event, category.id)}
|
|
101
|
+
>
|
|
102
|
+
<View style={bpStyles.catIcon}>
|
|
103
|
+
<OIcon
|
|
104
|
+
url={optimizeImage(category.image, 'h_100,c_limit')}
|
|
105
|
+
width={41}
|
|
106
|
+
height={41}
|
|
107
|
+
style={{ borderRadius: 7.6 }}
|
|
108
|
+
/>
|
|
109
|
+
</View>
|
|
110
|
+
<OText size={16} weight="600">
|
|
111
|
+
{category.name}
|
|
112
|
+
</OText>
|
|
113
|
+
</View>
|
|
114
|
+
<Fragment>
|
|
115
|
+
{products.map((product: any, i: any) => (
|
|
89
116
|
<SingleProductCard
|
|
90
|
-
key={
|
|
117
|
+
key={i}
|
|
91
118
|
isSoldOut={product.inventoried && !product.quantity}
|
|
92
119
|
businessId={businessId}
|
|
93
120
|
product={product}
|
|
94
121
|
onProductClick={onProductClick}
|
|
95
122
|
/>
|
|
96
|
-
))
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
)
|
|
104
|
-
})
|
|
105
|
-
}
|
|
123
|
+
))}
|
|
124
|
+
</Fragment>
|
|
125
|
+
</Fragment>
|
|
126
|
+
)}
|
|
127
|
+
</React.Fragment>
|
|
128
|
+
);
|
|
129
|
+
})}
|
|
106
130
|
|
|
107
|
-
{
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
131
|
+
{(categoryState.loading || isBusinessLoading) && (
|
|
132
|
+
<>
|
|
133
|
+
{[...Array(categoryState?.pagination?.nextPageItems).keys()].map(
|
|
134
|
+
(item, i) => (
|
|
111
135
|
<Placeholder key={i} style={{ padding: 5 }} Animation={Fade}>
|
|
112
136
|
<View style={{ flexDirection: 'row' }}>
|
|
113
|
-
<PlaceholderLine
|
|
137
|
+
<PlaceholderLine
|
|
138
|
+
width={24}
|
|
139
|
+
height={70}
|
|
140
|
+
style={{ marginRight: 10, marginBottom: 10 }}
|
|
141
|
+
/>
|
|
114
142
|
<Placeholder style={{ paddingVertical: 10 }}>
|
|
115
|
-
|
|
116
|
-
|
|
143
|
+
<PlaceholderLine width={60} style={{ marginBottom: 25 }} />
|
|
144
|
+
<PlaceholderLine width={20} />
|
|
117
145
|
</Placeholder>
|
|
118
146
|
</View>
|
|
119
147
|
</Placeholder>
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
148
|
+
),
|
|
149
|
+
)}
|
|
150
|
+
</>
|
|
151
|
+
)}
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
{!categoryState.loading &&
|
|
155
|
+
!isBusinessLoading &&
|
|
156
|
+
categoryState.products.length === 0 &&
|
|
157
|
+
!errors &&
|
|
158
|
+
!(
|
|
159
|
+
(searchValue && errorQuantityProducts) ||
|
|
160
|
+
(!searchValue && !errorQuantityProducts)
|
|
161
|
+
) && (
|
|
126
162
|
<WrapperNotFound>
|
|
127
163
|
<NotFoundSource
|
|
128
|
-
content={
|
|
129
|
-
|
|
130
|
-
|
|
164
|
+
content={
|
|
165
|
+
!searchValue
|
|
166
|
+
? t(
|
|
167
|
+
'ERROR_NOT_FOUND_PRODUCTS_TIME',
|
|
168
|
+
'No products found at this time',
|
|
169
|
+
)
|
|
170
|
+
: t(
|
|
171
|
+
'ERROR_NOT_FOUND_PRODUCTS',
|
|
172
|
+
'No products found, please change filters.',
|
|
173
|
+
)
|
|
174
|
+
}
|
|
175
|
+
btnTitle={
|
|
176
|
+
!searchValue
|
|
177
|
+
? t('SEARCH_REDIRECT', 'Go to Businesses')
|
|
178
|
+
: t('CLEAR_FILTERS', 'Clear filters')
|
|
179
|
+
}
|
|
180
|
+
onClickButton={() =>
|
|
181
|
+
!searchValue
|
|
182
|
+
? handleSearchRedirect && handleSearchRedirect()
|
|
183
|
+
: handleCancelSearch && handleCancelSearch()
|
|
184
|
+
}
|
|
131
185
|
/>
|
|
132
186
|
</WrapperNotFound>
|
|
133
|
-
)
|
|
134
|
-
}
|
|
187
|
+
)}
|
|
135
188
|
|
|
136
|
-
{errors &&
|
|
189
|
+
{errors &&
|
|
190
|
+
errors.length > 0 &&
|
|
137
191
|
errors.map((e: any, i: number) => (
|
|
138
192
|
<ErrorMessage key={i}>
|
|
139
193
|
<OText space>ERROR:</OText>
|
|
140
194
|
<OText>{e}</OText>
|
|
141
195
|
</ErrorMessage>
|
|
142
|
-
))
|
|
143
|
-
)}
|
|
196
|
+
))}
|
|
144
197
|
</ProductsContainer>
|
|
145
198
|
)
|
|
146
199
|
}
|
|
@@ -155,3 +208,15 @@ export const BusinessProductsList = (props: BusinessProductsListParams) => {
|
|
|
155
208
|
<ProductsList {...businessProductsListProps} />
|
|
156
209
|
)
|
|
157
210
|
}
|
|
211
|
+
|
|
212
|
+
const bpStyles = StyleSheet.create({
|
|
213
|
+
catWrap: { flexDirection: 'row', alignItems: 'center', height: 41, marginBottom: 19 },
|
|
214
|
+
catIcon: {
|
|
215
|
+
borderRadius: 7.6,
|
|
216
|
+
shadowColor: '#000000',
|
|
217
|
+
shadowOpacity: 0.1,
|
|
218
|
+
shadowOffset: { width: 0, height: 0 },
|
|
219
|
+
shadowRadius: 1,
|
|
220
|
+
marginEnd: 13,
|
|
221
|
+
},
|
|
222
|
+
});
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import React, { useState } from 'react'
|
|
1
|
+
import React, { useState, useRef, useCallback } from 'react'
|
|
2
2
|
import { View, TouchableOpacity, StyleSheet, TextStyle, ScrollView, I18nManager, Platform } from 'react-native'
|
|
3
3
|
import {
|
|
4
4
|
BusinessAndProductList,
|
|
5
5
|
useLanguage,
|
|
6
6
|
useOrder,
|
|
7
7
|
useSession,
|
|
8
|
-
useUtils
|
|
8
|
+
useUtils,
|
|
9
|
+
useToast,
|
|
10
|
+
ToastType
|
|
9
11
|
} from 'ordering-components/native'
|
|
10
12
|
import { OButton, OIcon, OModal, OText } from '../shared'
|
|
11
13
|
import { BusinessBasicInformation } from '../BusinessBasicInformation'
|
|
@@ -35,6 +37,8 @@ import { OrderSummary } from '../OrderSummary'
|
|
|
35
37
|
import NavBar from '../NavBar'
|
|
36
38
|
import SocialShareFav from '../SocialShare'
|
|
37
39
|
|
|
40
|
+
const PIXELS_TO_SCROLL = 1000
|
|
41
|
+
|
|
38
42
|
const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
39
43
|
const {
|
|
40
44
|
navigation,
|
|
@@ -52,7 +56,8 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
52
56
|
productModal,
|
|
53
57
|
handleChangeCategory,
|
|
54
58
|
setProductLogin,
|
|
55
|
-
updateProductModal
|
|
59
|
+
updateProductModal,
|
|
60
|
+
getNextProducts
|
|
56
61
|
} = props
|
|
57
62
|
const theme = useTheme()
|
|
58
63
|
|
|
@@ -97,14 +102,19 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
97
102
|
const [{ auth }] = useSession()
|
|
98
103
|
const [orderState] = useOrder()
|
|
99
104
|
const [{ parsePrice }] = useUtils()
|
|
105
|
+
const [ ,{showToast}] = useToast()
|
|
100
106
|
const { business, loading, error } = businessState
|
|
101
107
|
const [openBusinessInformation, setOpenBusinessInformation] = useState(false)
|
|
102
108
|
const [curProduct, setCurProduct] = useState(null)
|
|
103
109
|
const [openUpselling, setOpenUpselling] = useState(false)
|
|
104
110
|
const [openCart, setOpenCart] = useState(false)
|
|
105
|
-
const [
|
|
111
|
+
const [isCategoryClicked, setCategoryClicked] = useState(false)
|
|
112
|
+
const [categoriesLayout, setCategoriesLayout] = useState<any>({})
|
|
113
|
+
const [productListLayout, setProductListLayout] = useState<any>(null)
|
|
114
|
+
const [selectedCategoryId, setSelectedCategoryId] = useState<any>('cat_all')
|
|
115
|
+
|
|
116
|
+
const scrollViewRef = useRef<any>(null)
|
|
106
117
|
|
|
107
|
-
const [isStickyCategory, setStickyCategory] = useState(false);
|
|
108
118
|
const { top } = useSafeAreaInsets();
|
|
109
119
|
const [sortBy, setSortBy] = useState('alphabet');
|
|
110
120
|
|
|
@@ -146,19 +156,36 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
146
156
|
setOpenCart(false)
|
|
147
157
|
}
|
|
148
158
|
|
|
149
|
-
const handlePageScroll = (
|
|
150
|
-
const
|
|
151
|
-
if (
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
159
|
+
const handlePageScroll = useCallback(({ nativeEvent }: any) => {
|
|
160
|
+
const scrollOffset = nativeEvent.contentOffset.y
|
|
161
|
+
if (businessState?.business?.lazy_load_products_recommended) {
|
|
162
|
+
const height = nativeEvent.contentSize.height
|
|
163
|
+
const hasMore = !(categoryState.pagination.totalPages === categoryState.pagination.currentPage)
|
|
164
|
+
if (scrollOffset + PIXELS_TO_SCROLL > height && !loading && hasMore && getNextProducts) {
|
|
165
|
+
getNextProducts()
|
|
166
|
+
showToast(ToastType.Info, t('LOADING_MORE_PRODUCTS', 'Loading more products'))
|
|
167
|
+
}
|
|
168
|
+
} else {
|
|
169
|
+
if (!scrollOffset || !categoriesLayout || !productListLayout || isCategoryClicked) return
|
|
170
|
+
|
|
171
|
+
for (const key in categoriesLayout) {
|
|
172
|
+
const categoryOffset = categoriesLayout[key].y + productListLayout?.y - 70
|
|
173
|
+
if (scrollOffset < 10) {
|
|
174
|
+
setSelectedCategoryId('cat_all');
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (categoryOffset - 50 <= scrollOffset && scrollOffset <= categoryOffset + 50) {
|
|
178
|
+
if (selectedCategoryId !== key) {
|
|
179
|
+
setSelectedCategoryId(key)
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
155
183
|
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
// }, [orderState.loading])
|
|
184
|
+
}, [isCategoryClicked, selectedCategoryId])
|
|
185
|
+
|
|
186
|
+
const handleTouchDrag = useCallback(() => {
|
|
187
|
+
setCategoryClicked(false);
|
|
188
|
+
}, []);
|
|
162
189
|
|
|
163
190
|
return (
|
|
164
191
|
<>
|
|
@@ -172,11 +199,6 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
172
199
|
onClick={() => (navigation?.canGoBack() && navigation.goBack()) || (auth && navigation.navigate('BottomTab'))}
|
|
173
200
|
imgLeftStyle={{ tintColor: theme.colors.textPrimary }}
|
|
174
201
|
/>
|
|
175
|
-
{isStickyCategory && (
|
|
176
|
-
<Animated.View style={{ flexBasis: '74%', paddingHorizontal: 10, alignItems: 'center' }}>
|
|
177
|
-
<OText style={theme.labels.middle as TextStyle} numberOfLines={1} ellipsizeMode={'tail'}>{business?.name}</OText>
|
|
178
|
-
</Animated.View>
|
|
179
|
-
)}
|
|
180
202
|
{!errorQuantityProducts && (
|
|
181
203
|
<View style={{ ...styles.headerItem }}>
|
|
182
204
|
<View
|
|
@@ -196,8 +218,10 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
196
218
|
style={styles.mainContainer}
|
|
197
219
|
isActiveFloatingButtom={currentCart?.products?.length > 0 && categoryState.products.length !== 0}
|
|
198
220
|
stickyHeaderIndices={[1]}
|
|
221
|
+
ref={scrollViewRef}
|
|
199
222
|
onScroll={handlePageScroll}
|
|
200
|
-
|
|
223
|
+
onScrollBeginDrag={handleTouchDrag}
|
|
224
|
+
scrollEventThrottle={16}
|
|
201
225
|
>
|
|
202
226
|
<WrapHeader>
|
|
203
227
|
<BusinessBasicInformation
|
|
@@ -211,7 +235,6 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
211
235
|
<WrapSearchBar>
|
|
212
236
|
<SearchBar
|
|
213
237
|
onSearch={handleChangeSearch}
|
|
214
|
-
// onCancel={() => handleCancel()}
|
|
215
238
|
isCancelXButtonShow
|
|
216
239
|
noBorderShow
|
|
217
240
|
placeholder={t('SEARCH', 'Search')}
|
|
@@ -232,18 +255,25 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
232
255
|
{!loading && business?.id && !(business?.categories?.length === 0) && (
|
|
233
256
|
<CategoryWrap>
|
|
234
257
|
<BusinessProductsCategories
|
|
235
|
-
categories={[{ id:
|
|
258
|
+
categories={[{ id: 'all', name: t('ALL', 'All') }, { id: 'featured', name: t('FEATURED', 'Featured') }, ...business?.categories.sort((a: any, b: any) => a.rank - b.rank)]}
|
|
236
259
|
categorySelected={categorySelected}
|
|
237
260
|
onClickCategory={handleChangeCategory}
|
|
238
261
|
featured={featuredProducts}
|
|
239
262
|
openBusinessInformation={openBusinessInformation}
|
|
263
|
+
scrollViewRef={scrollViewRef}
|
|
240
264
|
contentStyle={{ paddingHorizontal: 40 }}
|
|
265
|
+
productListLayout={productListLayout}
|
|
266
|
+
categoriesLayout={categoriesLayout}
|
|
267
|
+
selectedCategoryId={selectedCategoryId}
|
|
268
|
+
setSelectedCategoryId={setSelectedCategoryId}
|
|
269
|
+
setCategoryClicked={setCategoryClicked}
|
|
270
|
+
lazyLoadProductsRecommended={business?.lazy_load_products_recommended}
|
|
241
271
|
/>
|
|
242
272
|
</CategoryWrap>
|
|
243
273
|
)}
|
|
244
274
|
<View>
|
|
245
275
|
{!loading && business?.id && (
|
|
246
|
-
<WrapContent>
|
|
276
|
+
<WrapContent onLayout={(event: any) => setProductListLayout(event.nativeEvent.layout)}>
|
|
247
277
|
<BusinessProductsList
|
|
248
278
|
categories={[
|
|
249
279
|
{ id: null, name: t('ALL', 'All') },
|
|
@@ -262,6 +292,8 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
262
292
|
errorQuantityProducts={errorQuantityProducts}
|
|
263
293
|
handleCancelSearch={handleCancel}
|
|
264
294
|
sortBy={sortBy}
|
|
295
|
+
categoriesLayout={categoriesLayout}
|
|
296
|
+
setCategoriesLayout={setCategoriesLayout}
|
|
265
297
|
/>
|
|
266
298
|
</WrapContent>
|
|
267
299
|
)}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
|
|
11
11
|
import NavBar from '../NavBar';
|
|
12
12
|
import { FormInput, FormSide } from '../LoginForm/styles'
|
|
13
|
-
import { Container } from './styles'
|
|
13
|
+
import { Container, InputWrap } from './styles'
|
|
14
14
|
|
|
15
15
|
import { OButton, OInput, OText } from '../shared';
|
|
16
16
|
import { useTheme } from 'styled-components/native';
|
|
@@ -26,9 +26,8 @@ const ForgotPasswordUI = (props: any) => {
|
|
|
26
26
|
|
|
27
27
|
const styles = StyleSheet.create({
|
|
28
28
|
inputStyle: {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
borderColor: theme.colors.disabled
|
|
29
|
+
borderWidth: 0,
|
|
30
|
+
minHeight: 44
|
|
32
31
|
}
|
|
33
32
|
});
|
|
34
33
|
|
|
@@ -84,47 +83,50 @@ const ForgotPasswordUI = (props: any) => {
|
|
|
84
83
|
onActionLeft={() => navigation?.canGoBack() && navigation.goBack()}
|
|
85
84
|
rightImg={null}
|
|
86
85
|
paddingTop={0}
|
|
86
|
+
style={{paddingLeft: 0, paddingRight: 0}}
|
|
87
87
|
/>
|
|
88
88
|
<FormSide>
|
|
89
89
|
<OText
|
|
90
90
|
color={'gray'}
|
|
91
91
|
size={16}
|
|
92
92
|
weight={'300'}
|
|
93
|
-
style={{ marginBottom: 30 }}
|
|
93
|
+
style={{ marginBottom: 30, marginTop: 30 }}
|
|
94
94
|
>
|
|
95
95
|
{t('FORGOT_PASSWORD_TEXT_MESSAGE', "Enter your email address and we'll sent a link to reset your password.")}
|
|
96
96
|
</OText>
|
|
97
97
|
<FormInput>
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
98
|
+
<InputWrap>
|
|
99
|
+
<OText weight="bold">Email</OText>
|
|
100
|
+
<Controller
|
|
101
|
+
control={control}
|
|
102
|
+
render={({ onChange, value }: any) => (
|
|
103
|
+
<OInput
|
|
104
|
+
placeholder={t('EXAMPLE@MAIL.COM', 'your@email.com')}
|
|
105
|
+
style={styles.inputStyle}
|
|
106
|
+
onChange={(e: any) => {
|
|
107
|
+
handleChangeInputEmail(e, onChange)
|
|
108
|
+
}}
|
|
109
|
+
value={value}
|
|
110
|
+
autoCapitalize='none'
|
|
111
|
+
autoCorrect={false}
|
|
112
|
+
type='email-address'
|
|
113
|
+
autoCompleteType='email'
|
|
114
|
+
returnKeyType='done'
|
|
115
|
+
blurOnSubmit
|
|
116
|
+
onSubmitEditing={handleSubmit(onSubmit)}
|
|
117
|
+
/>
|
|
118
|
+
)}
|
|
119
|
+
name="email"
|
|
120
|
+
rules={{
|
|
121
|
+
required: t('VALIDATION_ERROR_EMAIL_REQUIRED', 'The field Email is required').replace('_attribute_', t('EMAIL', 'Email')),
|
|
122
|
+
pattern: {
|
|
123
|
+
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
|
|
124
|
+
message: t('INVALID_ERROR_EMAIL', 'Invalid email address').replace('_attribute_', t('EMAIL', 'Email'))
|
|
125
|
+
}
|
|
126
|
+
}}
|
|
127
|
+
defaultValue=""
|
|
128
|
+
/>
|
|
129
|
+
</InputWrap>
|
|
128
130
|
|
|
129
131
|
<OButton
|
|
130
132
|
text={emailSent && !formState.result?.error ? t('LINK_SEND_FORGOT_PASSWORD', 'Link Sent') : t('FRONT_RECOVER_PASSWORD', 'Recover Password')}
|
|
@@ -9,3 +9,10 @@ export const Wrapper = styled.View`
|
|
|
9
9
|
export const Container = styled.View`
|
|
10
10
|
padding-bottom: 40px;
|
|
11
11
|
`
|
|
12
|
+
export const InputWrap = styled.View`
|
|
13
|
+
flex-direction: row;
|
|
14
|
+
align-items: center;
|
|
15
|
+
border-bottom-width: 1px;
|
|
16
|
+
border-bottom-color: #D7D7D7;
|
|
17
|
+
margin-bottom: 35px;
|
|
18
|
+
`
|