ordering-ui-react-native 0.16.51 → 0.16.54
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/themes/original/src/components/BusinessBasicInformation/index.tsx +197 -142
- package/themes/original/src/components/BusinessBasicInformation/styles.tsx +2 -2
- package/themes/original/src/components/BusinessProductsListing/index.tsx +34 -8
- package/themes/original/src/components/BusinessProductsListing/styles.tsx +5 -0
- package/themes/original/src/components/BusinessesListing/Layout/Appointment/index.tsx +9 -1
- package/themes/original/src/components/BusinessesListing/Layout/Appointment/styles.tsx +3 -2
- package/themes/original/src/components/BusinessesListing/Layout/Original/index.tsx +216 -67
- package/themes/original/src/components/BusinessesListing/Layout/Original/styles.tsx +46 -2
- package/themes/original/src/components/BusinessesListing/index.tsx +69 -21
- package/themes/original/src/components/GoogleMap/index.tsx +10 -11
- package/themes/original/src/components/OrderDetails/index.tsx +32 -34
- package/themes/original/src/components/ReviewOrder/index.tsx +79 -99
- package/themes/original/src/components/ReviewOrder/styles.tsx +0 -9
- package/themes/original/src/components/ReviewTrigger/index.tsx +118 -0
- package/themes/original/src/components/ReviewTrigger/styles.tsx +34 -0
- package/themes/original/src/components/ServiceForm/index.tsx +15 -5
- package/themes/original/src/components/SingleProductCard/index.tsx +106 -88
- package/themes/original/src/components/SingleProductCard/styles.tsx +2 -2
- package/themes/original/src/components/shared/OBottomPopup.tsx +31 -9
- package/themes/original/src/components/shared/OButton.tsx +2 -0
- package/themes/original/src/types/index.tsx +16 -15
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
useOrder,
|
|
20
20
|
useConfig,
|
|
21
21
|
useUtils,
|
|
22
|
+
useOrderingTheme
|
|
22
23
|
} from 'ordering-components/native';
|
|
23
24
|
import { useTheme } from 'styled-components/native';
|
|
24
25
|
import Ionicons from 'react-native-vector-icons/Ionicons'
|
|
@@ -33,11 +34,14 @@ import {
|
|
|
33
34
|
FeaturedWrapper,
|
|
34
35
|
OrderProgressWrapper,
|
|
35
36
|
FarAwayMessage,
|
|
36
|
-
AddressInputContainer
|
|
37
|
+
AddressInputContainer,
|
|
38
|
+
PreorderInput,
|
|
39
|
+
OrderTypesContainer,
|
|
40
|
+
BusinessLogosContainer
|
|
37
41
|
} from './styles';
|
|
38
42
|
|
|
39
43
|
import { SearchBar } from '../../../SearchBar';
|
|
40
|
-
import { OIcon, OText } from '../../../shared';
|
|
44
|
+
import { OButton, OIcon, OText, OBottomPopup, OModal } from '../../../shared';
|
|
41
45
|
import { BusinessesListingParams } from '../../../../types';
|
|
42
46
|
import { NotFoundSource } from '../../../NotFoundSource';
|
|
43
47
|
import { BusinessTypeFilter } from '../../../BusinessTypeFilter';
|
|
@@ -49,6 +53,7 @@ import { HighestRatedBusinesses } from '../../../HighestRatedBusinesses';
|
|
|
49
53
|
import { getTypesText, convertToRadian } from '../../../../utils';
|
|
50
54
|
import { OrderProgress } from '../../../OrderProgress';
|
|
51
55
|
import { useFocusEffect, useIsFocused } from '@react-navigation/native';
|
|
56
|
+
import FastImage from 'react-native-fast-image';
|
|
52
57
|
|
|
53
58
|
const PIXELS_TO_SCROLL = 2000;
|
|
54
59
|
|
|
@@ -64,12 +69,19 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
64
69
|
handleChangeSearch,
|
|
65
70
|
businessId,
|
|
66
71
|
isGuestUser,
|
|
67
|
-
handleUpdateBusinessList
|
|
72
|
+
handleUpdateBusinessList,
|
|
73
|
+
citiesState,
|
|
74
|
+
actualSlug,
|
|
75
|
+
logosLayout
|
|
68
76
|
} = props;
|
|
69
77
|
const theme = useTheme();
|
|
78
|
+
const [orderingTheme] = useOrderingTheme()
|
|
70
79
|
const isFocused = useIsFocused();
|
|
71
80
|
const appState = useRef(AppState.currentState)
|
|
81
|
+
const searchBarRef = useRef<any>()
|
|
72
82
|
const [appStateVisible, setAppStateVisible] = useState(appState.current);
|
|
83
|
+
const isChewLayout = theme?.layouts?.header?.components?.layout?.type === 'chew'
|
|
84
|
+
const showCities = !orderingTheme?.theme?.business_listing_view?.components?.cities?.hidden
|
|
73
85
|
const [refreshing] = useState(false);
|
|
74
86
|
const styles = StyleSheet.create({
|
|
75
87
|
container: {
|
|
@@ -114,13 +126,20 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
114
126
|
backgroundColor: theme.colors.white,
|
|
115
127
|
borderColor: theme.colors.backgroundGray,
|
|
116
128
|
borderWidth: 1,
|
|
129
|
+
},
|
|
130
|
+
buttonCityStyle: {
|
|
131
|
+
backgroundColor: theme.colors.white,
|
|
132
|
+
borderColor: theme.colors.backgroundGray,
|
|
133
|
+
borderRadius: 8,
|
|
134
|
+
marginHorizontal: 40,
|
|
135
|
+
height: 45
|
|
117
136
|
}
|
|
118
137
|
});
|
|
119
138
|
|
|
120
139
|
|
|
121
140
|
const [, t] = useLanguage();
|
|
122
141
|
const [{ user, auth }] = useSession();
|
|
123
|
-
const [orderState] = useOrder();
|
|
142
|
+
const [orderState, { changeCityFilter }] = useOrder();
|
|
124
143
|
const [{ configs }] = useConfig();
|
|
125
144
|
const [{ parseDate }] = useUtils();
|
|
126
145
|
|
|
@@ -130,11 +149,13 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
130
149
|
const [isFarAway, setIsFarAway] = useState(false)
|
|
131
150
|
const [businessTypes, setBusinessTypes] = useState(null)
|
|
132
151
|
const [orderTypeValue, setOrderTypeValue] = useState(orderState?.options.value)
|
|
152
|
+
const [isOpenCities, setIsOpenCities] = useState(false)
|
|
133
153
|
const isPreorderEnabled = (configs?.preorder_status_enabled?.value === '1' || configs?.preorder_status_enabled?.value === 'true') &&
|
|
134
154
|
Number(configs?.max_days_preorder?.value) > 0
|
|
135
155
|
const isPreOrderSetting = configs?.preorder_status_enabled?.value === '1'
|
|
136
156
|
const timerId = useRef<any>(false)
|
|
137
157
|
const [favoriteIds, setFavoriteIds] = useState<any>([])
|
|
158
|
+
const chewOrderTypes = [{ name: t('DELIVERY', 'Delivery').toUpperCase(), value: 1 }, { name: t('PICKUP', 'Pickup').toUpperCase(), value: 2 }]
|
|
138
159
|
|
|
139
160
|
// const panResponder = useRef(
|
|
140
161
|
// PanResponder.create({
|
|
@@ -163,6 +184,7 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
163
184
|
const hasMore = !(
|
|
164
185
|
paginationProps.totalPages === paginationProps.currentPage
|
|
165
186
|
);
|
|
187
|
+
|
|
166
188
|
if (y + PIXELS_TO_SCROLL > height && !businessesList.loading && hasMore) {
|
|
167
189
|
getBusinesses();
|
|
168
190
|
}
|
|
@@ -180,10 +202,12 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
180
202
|
}
|
|
181
203
|
|
|
182
204
|
const resetInactivityTimeout = () => {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
205
|
+
if (!logosLayout) {
|
|
206
|
+
clearTimeout(timerId.current)
|
|
207
|
+
timerId.current = setInterval(() => {
|
|
208
|
+
getBusinesses(true)
|
|
209
|
+
}, 120000)
|
|
210
|
+
}
|
|
187
211
|
}
|
|
188
212
|
|
|
189
213
|
useEffect(() => {
|
|
@@ -224,7 +248,9 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
224
248
|
}
|
|
225
249
|
|
|
226
250
|
useEffect(() => {
|
|
227
|
-
|
|
251
|
+
if (!logosLayout) {
|
|
252
|
+
checkUserLocation()
|
|
253
|
+
}
|
|
228
254
|
}, [orderState?.options?.address?.location])
|
|
229
255
|
|
|
230
256
|
useEffect(() => {
|
|
@@ -251,6 +277,44 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
251
277
|
setFavoriteIds([...new Set(ids)])
|
|
252
278
|
}, [businessesList?.businesses?.length])
|
|
253
279
|
|
|
280
|
+
useEffect(() => {
|
|
281
|
+
setIsOpenCities(false)
|
|
282
|
+
}, [orderState?.options?.city_id])
|
|
283
|
+
|
|
284
|
+
if (logosLayout) {
|
|
285
|
+
return (
|
|
286
|
+
<BusinessLogosContainer horizontal>
|
|
287
|
+
{businessesList?.loading ? (
|
|
288
|
+
<Placeholder Animation={Fade}>
|
|
289
|
+
{[...Array(10).keys()].map(item => (
|
|
290
|
+
<PlaceholderLine key={item} width={56} height={56} />
|
|
291
|
+
))}
|
|
292
|
+
</Placeholder>
|
|
293
|
+
) : (
|
|
294
|
+
<>
|
|
295
|
+
{businessesList.businesses
|
|
296
|
+
?.filter(business => business?.slug !== actualSlug && business?.open)
|
|
297
|
+
?.map(business => (
|
|
298
|
+
<TouchableOpacity
|
|
299
|
+
key={business?.id}
|
|
300
|
+
onPress={() => handleBusinessClick && handleBusinessClick(business)}
|
|
301
|
+
>
|
|
302
|
+
<FastImage
|
|
303
|
+
style={{ width: 56, height: 56, marginRight: 20, borderRadius: 7.6 }}
|
|
304
|
+
source={{
|
|
305
|
+
uri: business?.logo,
|
|
306
|
+
priority: FastImage.priority.normal,
|
|
307
|
+
}}
|
|
308
|
+
resizeMode={FastImage.resizeMode.cover}
|
|
309
|
+
/>
|
|
310
|
+
</TouchableOpacity>
|
|
311
|
+
))}
|
|
312
|
+
</>
|
|
313
|
+
)}
|
|
314
|
+
</BusinessLogosContainer>
|
|
315
|
+
)
|
|
316
|
+
}
|
|
317
|
+
|
|
254
318
|
return (
|
|
255
319
|
<ScrollView style={styles.container} onScroll={(e) => handleScroll(e)} showsVerticalScrollIndicator={false}
|
|
256
320
|
refreshControl={
|
|
@@ -260,9 +324,27 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
260
324
|
/>
|
|
261
325
|
}
|
|
262
326
|
>
|
|
263
|
-
<View style={{
|
|
264
|
-
|
|
327
|
+
<View style={{
|
|
328
|
+
height: !isPreOrderSetting && isChewLayout ? 150 : isChewLayout ? 200 : isFarAway ? 150 : 100,
|
|
329
|
+
marginTop: Platform.OS == 'ios' ? 0 : 50,
|
|
330
|
+
backgroundColor: isChewLayout ? theme?.colors?.chew : theme.colors?.white
|
|
331
|
+
}}
|
|
332
|
+
>
|
|
333
|
+
{isChewLayout && (
|
|
334
|
+
<View style={{ marginTop: 30, paddingHorizontal: 30, flexDirection: 'row', justifyContent: 'space-between' }}>
|
|
335
|
+
<OText size={18} weight={700} color={theme.colors?.white}>
|
|
336
|
+
{t('WELCOME', 'Welcome')} {user?.name}!
|
|
337
|
+
</OText>
|
|
338
|
+
<TouchableOpacity
|
|
339
|
+
onPress={() => searchBarRef?.current?.focus?.()}
|
|
340
|
+
>
|
|
341
|
+
<Ionicons name='search' style={{ ...styles.iconStyle, color: theme.colors?.white }} />
|
|
342
|
+
</TouchableOpacity>
|
|
343
|
+
</View>
|
|
344
|
+
)}
|
|
345
|
+
<Search isChewLayout={isChewLayout}>
|
|
265
346
|
<AddressInput
|
|
347
|
+
isChewLayout={isChewLayout}
|
|
266
348
|
onPress={() =>
|
|
267
349
|
auth
|
|
268
350
|
? navigation.navigate('AddressList', { isFromBusinesses: true })
|
|
@@ -272,78 +354,108 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
272
354
|
isGuestUser: isGuestUser
|
|
273
355
|
})
|
|
274
356
|
}>
|
|
275
|
-
<AddressInputContainer>
|
|
357
|
+
<AddressInputContainer isChewLayout={isChewLayout}>
|
|
276
358
|
<OIcon
|
|
277
359
|
src={theme.images.general.pin}
|
|
278
360
|
color={theme.colors.disabled}
|
|
279
361
|
width={16}
|
|
280
|
-
style={{ marginRight: 10 }}
|
|
362
|
+
style={{ marginRight: isChewLayout ? 0 : 10 }}
|
|
281
363
|
/>
|
|
282
|
-
<OText size={12} numberOfLines={1}>
|
|
364
|
+
<OText size={12} numberOfLines={1} style={{ flex: 1 }}>
|
|
283
365
|
{orderState?.options?.address?.address}
|
|
284
366
|
</OText>
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
367
|
+
{!isChewLayout && (
|
|
368
|
+
<OIcon
|
|
369
|
+
src={theme.images.general.arrow_down}
|
|
370
|
+
width={10}
|
|
371
|
+
style={{ marginStart: 8 }}
|
|
372
|
+
/>
|
|
373
|
+
)}
|
|
290
374
|
</AddressInputContainer>
|
|
291
375
|
</AddressInput>
|
|
292
376
|
</Search>
|
|
293
|
-
{isFarAway && (
|
|
377
|
+
{isFarAway && !isChewLayout && (
|
|
294
378
|
<FarAwayMessage style={styles.farAwayMsg}>
|
|
295
379
|
<Ionicons name='md-warning-outline' style={styles.iconStyle} />
|
|
296
380
|
<OText size={12} numberOfLines={1} ellipsizeMode={'tail'} color={theme.colors.textNormal}>{t('YOU_ARE_FAR_FROM_ADDRESS', 'You are far from this address')}</OText>
|
|
297
381
|
</FarAwayMessage>
|
|
298
382
|
)}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
383
|
+
{!isChewLayout ? (
|
|
384
|
+
<OrderControlContainer>
|
|
385
|
+
<View style={styles.wrapperOrderOptions}>
|
|
386
|
+
{isPreOrderSetting && (
|
|
387
|
+
<WrapMomentOption
|
|
388
|
+
onPress={() => handleMomentClick()}>
|
|
389
|
+
<OText
|
|
390
|
+
size={12}
|
|
391
|
+
numberOfLines={1}
|
|
392
|
+
ellipsizeMode="tail"
|
|
393
|
+
color={theme.colors.textSecondary}>
|
|
394
|
+
{orderState.options?.moment
|
|
395
|
+
? parseDate(orderState.options?.moment, { outputFormat: configs?.dates_moment_format?.value })
|
|
396
|
+
: t('ASAP_ABBREVIATION', 'ASAP')}
|
|
397
|
+
</OText>
|
|
398
|
+
{isPreorderEnabled && (
|
|
399
|
+
<OIcon
|
|
400
|
+
src={theme.images.general.arrow_down}
|
|
401
|
+
width={10}
|
|
402
|
+
style={{ marginStart: 8 }}
|
|
403
|
+
/>
|
|
404
|
+
)}
|
|
405
|
+
</WrapMomentOption>
|
|
406
|
+
)}
|
|
407
|
+
<WrapMomentOption onPress={() => navigation.navigate('OrderTypes', { configTypes: configTypes, setOrderTypeValue })}>
|
|
408
|
+
<OText size={12} numberOfLines={1} ellipsizeMode={'tail'} color={theme.colors.textSecondary}>{t(getTypesText(orderTypeValue || orderState?.options?.type || 1), 'Delivery')}</OText>
|
|
409
|
+
<OIcon
|
|
410
|
+
src={theme.images.general.arrow_down}
|
|
411
|
+
width={10}
|
|
412
|
+
style={{ marginStart: 8 }}
|
|
413
|
+
/>
|
|
321
414
|
</WrapMomentOption>
|
|
415
|
+
</View>
|
|
416
|
+
</OrderControlContainer>
|
|
417
|
+
) : (
|
|
418
|
+
<>
|
|
419
|
+
{!isPreOrderSetting && (// cambiar
|
|
420
|
+
<View style={{ paddingHorizontal: 30 }}>
|
|
421
|
+
<PreorderInput
|
|
422
|
+
isChewLayout={isChewLayout}
|
|
423
|
+
onPress={() => handleMomentClick()}
|
|
424
|
+
>
|
|
425
|
+
<OText color={theme.colors.textSecondary}>
|
|
426
|
+
{orderState.options?.moment
|
|
427
|
+
? parseDate(orderState.options?.moment, { outputFormat: configs?.dates_moment_format?.value })
|
|
428
|
+
: t('ASAP_ABBREVIATION', 'ASAP')}</OText>
|
|
429
|
+
</PreorderInput>
|
|
430
|
+
</View>
|
|
322
431
|
)}
|
|
323
|
-
|
|
324
|
-
<OText size={12} numberOfLines={1} ellipsizeMode={'tail'} color={theme.colors.textSecondary}>{t(getTypesText(orderTypeValue || orderState?.options?.type || 1), 'Delivery')}</OText>
|
|
325
|
-
<OIcon
|
|
326
|
-
src={theme.images.general.arrow_down}
|
|
327
|
-
width={10}
|
|
328
|
-
style={{ marginStart: 8 }}
|
|
329
|
-
/>
|
|
330
|
-
</WrapMomentOption>
|
|
331
|
-
</View>
|
|
332
|
-
</OrderControlContainer>
|
|
333
|
-
</View>
|
|
334
|
-
<HeaderWrapper
|
|
335
|
-
source={theme.images.backgrounds.business_list_header}
|
|
336
|
-
style={{ paddingTop: top + 20 }}
|
|
337
|
-
resizeMode='stretch'
|
|
338
|
-
>
|
|
339
|
-
{!auth && (
|
|
340
|
-
<TouchableOpacity onPress={() => navigation?.canGoBack() && navigation.goBack()} style={{ position: 'absolute', marginStart: 40, paddingVertical: 20 }}>
|
|
341
|
-
<OIcon src={theme.images.general.arrow_left} width={20} style={{ tintColor: theme.colors.white }} />
|
|
342
|
-
</TouchableOpacity>
|
|
432
|
+
</>
|
|
343
433
|
)}
|
|
344
|
-
</
|
|
434
|
+
</View>
|
|
435
|
+
{!isChewLayout ? (
|
|
436
|
+
<HeaderWrapper
|
|
437
|
+
source={theme.images.general.homeHero}
|
|
438
|
+
style={{ paddingTop: top + 20 }}
|
|
439
|
+
resizeMode='stretch'
|
|
440
|
+
>
|
|
441
|
+
{!auth && (
|
|
442
|
+
<TouchableOpacity onPress={() => navigation?.canGoBack() && navigation.goBack()} style={{ position: 'absolute', marginStart: 40, paddingVertical: 20 }}>
|
|
443
|
+
<OIcon src={theme.images.general.arrow_left} width={20} style={{ tintColor: theme.colors.white }} />
|
|
444
|
+
</TouchableOpacity>
|
|
445
|
+
)}
|
|
446
|
+
</HeaderWrapper>
|
|
447
|
+
) : (
|
|
448
|
+
<OrderTypesContainer>
|
|
449
|
+
<OrderTypeSelector
|
|
450
|
+
handleChangeBusinessType={handleChangeBusinessType}
|
|
451
|
+
isChewLayout
|
|
452
|
+
chewOrderTypes={chewOrderTypes}
|
|
453
|
+
/>
|
|
454
|
+
</OrderTypesContainer>
|
|
455
|
+
)}
|
|
345
456
|
{!businessId && (
|
|
346
457
|
<SearchBar
|
|
458
|
+
forwardRef={searchBarRef}
|
|
347
459
|
onSearch={handleChangeSearch}
|
|
348
460
|
searchValue={searchValue}
|
|
349
461
|
lazyLoad
|
|
@@ -352,24 +464,33 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
352
464
|
onCancel={() => handleChangeSearch('')}
|
|
353
465
|
placeholder={t('SEARCH', 'Search')}
|
|
354
466
|
height={50}
|
|
355
|
-
isDisabled={!businessTypes
|
|
467
|
+
isDisabled={!businessTypes}
|
|
356
468
|
inputContainerStyles={styles.inputContainerStyles}
|
|
357
469
|
containerStyles={{
|
|
358
470
|
marginHorizontal: 40,
|
|
359
471
|
marginTop: 20
|
|
360
472
|
}}
|
|
361
473
|
inputStyle={{ ...styles.searchInput, ...Platform.OS === 'ios' ? { paddingBottom: 6 } : { paddingBottom: 4 } }}
|
|
362
|
-
onPress={() => { configs?.advanced_business_search_enabled?.value === '1' && navigation.navigate('BusinessSearch', { businessTypes }) }}
|
|
363
474
|
onSubmitEditing={() => { configs?.advanced_business_search_enabled?.value === '1' && navigation.navigate('BusinessSearch', { businessTypes, defaultTerm: searchValue }) }}
|
|
364
475
|
/>
|
|
365
476
|
)}
|
|
477
|
+
|
|
478
|
+
{showCities && (
|
|
479
|
+
<View style={{ marginTop: 10 }}>
|
|
480
|
+
<OButton
|
|
481
|
+
onClick={() => setIsOpenCities(true)}
|
|
482
|
+
text={citiesState?.cities?.find((city: any) => city?.id === orderState?.options?.city_id)?.name || t('FILTER_BY_CITY', 'Filter by city')}
|
|
483
|
+
style={styles?.buttonCityStyle}
|
|
484
|
+
textStyle={{ color: theme.colors.backgroundGray, fontWeight: 'bold', fontSize: 18 }}
|
|
485
|
+
/>
|
|
486
|
+
</View>
|
|
487
|
+
)}
|
|
366
488
|
<OrderProgressWrapper>
|
|
367
489
|
<OrderProgress
|
|
368
490
|
{...props}
|
|
369
491
|
isFocused={isFocused}
|
|
370
492
|
/>
|
|
371
493
|
</OrderProgressWrapper>
|
|
372
|
-
|
|
373
494
|
{
|
|
374
495
|
!businessId && !props.franchiseId && featuredBusiness && featuredBusiness.length > 0 && (
|
|
375
496
|
<FeaturedWrapper>
|
|
@@ -377,7 +498,9 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
377
498
|
<ScrollView
|
|
378
499
|
showsHorizontalScrollIndicator={false}
|
|
379
500
|
nestedScrollEnabled
|
|
380
|
-
horizontal
|
|
501
|
+
horizontal
|
|
502
|
+
contentContainerStyle={{ paddingHorizontal: 40 }}
|
|
503
|
+
>
|
|
381
504
|
{featuredBusiness.map((bAry: any, idx) => (
|
|
382
505
|
<View key={'f-listing_' + idx}>
|
|
383
506
|
<BusinessFeaturedController
|
|
@@ -431,6 +554,7 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
431
554
|
/>
|
|
432
555
|
)}
|
|
433
556
|
<IOScrollView>
|
|
557
|
+
|
|
434
558
|
{businessesList.businesses?.map(
|
|
435
559
|
(business: any, i: number) => (
|
|
436
560
|
<BusinessController
|
|
@@ -508,6 +632,31 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
508
632
|
</>
|
|
509
633
|
)}
|
|
510
634
|
</ListWrapper>
|
|
635
|
+
<OModal
|
|
636
|
+
open={isOpenCities}
|
|
637
|
+
onClose={() => setIsOpenCities(false)}
|
|
638
|
+
title={t('SELECT_A_CITY', 'Select a city')}
|
|
639
|
+
>
|
|
640
|
+
<View style={{ padding: 40, width: '100%' }}>
|
|
641
|
+
{citiesState?.cities?.map((city: any) => (
|
|
642
|
+
<TouchableOpacity
|
|
643
|
+
key={city?.id}
|
|
644
|
+
style={{
|
|
645
|
+
padding: 10,
|
|
646
|
+
borderBottomWidth: 1,
|
|
647
|
+
borderBottomColor: orderState?.options?.city_id === city?.id ? theme.colors.primary : theme.colors.backgroundGray,
|
|
648
|
+
marginBottom: 10,
|
|
649
|
+
}}
|
|
650
|
+
onPress={() => changeCityFilter(city?.id)}
|
|
651
|
+
disabled={orderState?.loading}
|
|
652
|
+
>
|
|
653
|
+
<OText color={orderState?.options?.city_id === city?.id ? theme.colors.primary : theme.colors.black}>
|
|
654
|
+
{city?.name}
|
|
655
|
+
</OText>
|
|
656
|
+
</TouchableOpacity>
|
|
657
|
+
))}
|
|
658
|
+
</View>
|
|
659
|
+
</OModal>
|
|
511
660
|
</ScrollView>
|
|
512
661
|
);
|
|
513
662
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import styled from 'styled-components/native'
|
|
1
|
+
import styled, { css } from 'styled-components/native'
|
|
2
2
|
|
|
3
3
|
export const WelcomeTitle = styled.View`
|
|
4
4
|
flex: 1;
|
|
@@ -16,6 +16,9 @@ export const Search = styled.View`
|
|
|
16
16
|
align-items: center;
|
|
17
17
|
margin-vertical: 10px;
|
|
18
18
|
margin-horizontal: 20px;
|
|
19
|
+
${(props: any) => props.isChewLayout && css`
|
|
20
|
+
margin-horizontal: 30px;
|
|
21
|
+
`}
|
|
19
22
|
`
|
|
20
23
|
|
|
21
24
|
export const AddressInput = styled.TouchableOpacity`
|
|
@@ -27,6 +30,9 @@ export const AddressInput = styled.TouchableOpacity`
|
|
|
27
30
|
width: 100%;
|
|
28
31
|
height: 44px;
|
|
29
32
|
max-height: 44px;
|
|
33
|
+
${(props: any) => props.isChewLayout && css`
|
|
34
|
+
border-radius: 8px;
|
|
35
|
+
`}
|
|
30
36
|
`
|
|
31
37
|
|
|
32
38
|
export const OrderControlContainer = styled.View`
|
|
@@ -89,5 +95,43 @@ export const AddressInputContainer = styled.View`
|
|
|
89
95
|
flex-direction: row;
|
|
90
96
|
width: 100%;
|
|
91
97
|
align-items: center;
|
|
92
|
-
justify-content: center
|
|
98
|
+
justify-content: center;
|
|
99
|
+
${(props: any) => props.isChewLayout && css`
|
|
100
|
+
flex-direction: row-reverse;
|
|
101
|
+
`}
|
|
102
|
+
`
|
|
103
|
+
|
|
104
|
+
export const PreorderInput = styled(AddressInput)`
|
|
105
|
+
justify-content: center;
|
|
106
|
+
`
|
|
107
|
+
|
|
108
|
+
export const OTabs = styled.View`
|
|
109
|
+
flex-direction: row;
|
|
110
|
+
justify-content: space-between;
|
|
111
|
+
align-items: center;
|
|
112
|
+
margin-bottom: -1px;
|
|
113
|
+
width: 100%;
|
|
114
|
+
`;
|
|
115
|
+
|
|
116
|
+
export const OTab = styled.TouchableOpacity`
|
|
117
|
+
padding-bottom: 10px;
|
|
118
|
+
border-bottom-width: 1px;
|
|
119
|
+
margin-end: 14px;
|
|
120
|
+
padding-horizontal: 5px;
|
|
121
|
+
`;
|
|
122
|
+
|
|
123
|
+
export const OrderTypesContainer = styled.View`
|
|
124
|
+
flex-direction: row;
|
|
125
|
+
font-size: 14px;
|
|
126
|
+
width: 180px;
|
|
127
|
+
justify-content: space-between;
|
|
128
|
+
align-items: center;
|
|
129
|
+
border-bottom-width: 1px;
|
|
130
|
+
border-bottom-color: ${(props: any) => props.theme.colors.border};
|
|
131
|
+
margin-top: 10px;
|
|
132
|
+
align-self: center;
|
|
133
|
+
`
|
|
134
|
+
|
|
135
|
+
export const BusinessLogosContainer = styled.ScrollView`
|
|
136
|
+
padding-bottom: 10px;
|
|
93
137
|
`
|
|
@@ -1,42 +1,75 @@
|
|
|
1
1
|
|
|
2
2
|
import React, { useState, useEffect } from 'react'
|
|
3
|
-
import { useOrder, useSession } from 'ordering-components/native';
|
|
3
|
+
import { useOrder, useSession, useLanguage } from 'ordering-components/native';
|
|
4
4
|
|
|
5
5
|
import { useTheme } from 'styled-components/native'
|
|
6
6
|
import { BusinessesListing as OriginalBusinessListing } from './Layout/Original'
|
|
7
7
|
import { BusinessesListing as AppointmentBusinessListing } from './Layout/Appointment'
|
|
8
|
+
import { OBottomPopup } from '../shared';
|
|
9
|
+
import { ReviewTrigger } from '../ReviewTrigger';
|
|
8
10
|
|
|
9
11
|
export const BusinessesListing = (props: any) => {
|
|
10
12
|
const theme = useTheme()
|
|
11
|
-
const layout = theme?.
|
|
13
|
+
const layout = theme?.layouts?.business_listing_view?.components?.layout?.type || 'original'
|
|
14
|
+
const [, t] = useLanguage();
|
|
12
15
|
const [{ auth }] = useSession()
|
|
13
16
|
const [, { getLastOrderHasNoReview }] = useOrder();
|
|
14
|
-
|
|
15
|
-
const
|
|
17
|
+
|
|
18
|
+
const [, setIsReviewed] = useState()
|
|
19
|
+
const defaultOrder = {
|
|
20
|
+
id: 0,
|
|
21
|
+
business_id: 0,
|
|
22
|
+
business_name: '',
|
|
23
|
+
logo: '',
|
|
24
|
+
driver: {},
|
|
25
|
+
products: [],
|
|
26
|
+
review: {},
|
|
27
|
+
user_review: {},
|
|
28
|
+
delivery_datetime: ''
|
|
29
|
+
}
|
|
30
|
+
const [lastOrderReview, setLastOrderReview] = useState({
|
|
31
|
+
isReviewOpen: false,
|
|
32
|
+
order: defaultOrder,
|
|
33
|
+
defaultStar: 5,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const _getLastOrderHasNoReview = async () => {
|
|
37
|
+
const lastOrderHasNoReview = await getLastOrderHasNoReview()
|
|
38
|
+
lastOrderHasNoReview && OrderReviewRequired(lastOrderHasNoReview)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const OrderReviewRequired = (order: any) => {
|
|
42
|
+
setLastOrderReview({
|
|
43
|
+
isReviewOpen: true,
|
|
44
|
+
order: {
|
|
45
|
+
id: order?.id,
|
|
46
|
+
business_id: order?.business_id,
|
|
47
|
+
business_name: order?.business?.name,
|
|
48
|
+
logo: order.business?.logo,
|
|
49
|
+
driver: order?.driver,
|
|
50
|
+
products: order?.products,
|
|
51
|
+
review: order?.review,
|
|
52
|
+
user_review: order?.user_review,
|
|
53
|
+
delivery_datetime: order?.delivery_datetime_utc
|
|
54
|
+
},
|
|
55
|
+
defaultStar: 5
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const handleOpenOrderReview = (star: number) => {
|
|
60
|
+
setLastOrderReview({
|
|
61
|
+
...lastOrderReview, isReviewOpen: false, order: defaultOrder
|
|
62
|
+
})
|
|
16
63
|
props?.navigation && props.navigation.navigate(
|
|
17
64
|
'ReviewOrder',
|
|
18
65
|
{
|
|
19
|
-
order:
|
|
20
|
-
|
|
21
|
-
business_id: order?.business_id,
|
|
22
|
-
business_name: order?.business?.name,
|
|
23
|
-
delivery_datetime: order?.delivery_datetime,
|
|
24
|
-
logo: order.business?.logo,
|
|
25
|
-
driver: order?.driver,
|
|
26
|
-
products: order?.products,
|
|
27
|
-
review: order?.review,
|
|
28
|
-
user_review: order?.user_review
|
|
29
|
-
},
|
|
66
|
+
order: lastOrderReview.order,
|
|
67
|
+
defaultStar: star || 5,
|
|
30
68
|
setIsReviewed
|
|
31
69
|
}
|
|
32
70
|
)
|
|
33
71
|
}
|
|
34
72
|
|
|
35
|
-
const _getLastOrderHasNoReview = async () => {
|
|
36
|
-
const lastOrderHasNoReview = await getLastOrderHasNoReview()
|
|
37
|
-
lastOrderHasNoReview && handleOrderReview(lastOrderHasNoReview)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
73
|
useEffect(() => {
|
|
41
74
|
auth && _getLastOrderHasNoReview()
|
|
42
75
|
}, [auth])
|
|
@@ -45,6 +78,21 @@ export const BusinessesListing = (props: any) => {
|
|
|
45
78
|
<>
|
|
46
79
|
{(layout === 'original') && <OriginalBusinessListing {...props} />}
|
|
47
80
|
{(layout === 'appointment') && <AppointmentBusinessListing {...props} />}
|
|
81
|
+
|
|
82
|
+
{lastOrderReview?.isReviewOpen && (
|
|
83
|
+
<OBottomPopup
|
|
84
|
+
open={lastOrderReview?.isReviewOpen}
|
|
85
|
+
transparent={true}
|
|
86
|
+
onClose={() => setLastOrderReview({ ...lastOrderReview, isReviewOpen: false, order: defaultOrder })}
|
|
87
|
+
title={t('HEY', 'Hey! ') + t('HOW_WAS_YOUR_ORDER', 'How was your order?')}
|
|
88
|
+
bottomContainerStyle={{ height: 'auto' }}
|
|
89
|
+
titleStyle={{ textAlign: 'center' }}
|
|
90
|
+
closeIcon={theme.images.general.close}
|
|
91
|
+
>
|
|
92
|
+
{lastOrderReview?.order && <ReviewTrigger order={lastOrderReview?.order} handleOpenOrderReview={handleOpenOrderReview} />}
|
|
93
|
+
|
|
94
|
+
</OBottomPopup>
|
|
95
|
+
)}
|
|
48
96
|
</>
|
|
49
97
|
)
|
|
50
|
-
}
|
|
98
|
+
}
|
|
@@ -32,6 +32,7 @@ export const GoogleMap = (props: GoogleMapsParams) => {
|
|
|
32
32
|
latitudeDelta: 0.0010,
|
|
33
33
|
longitudeDelta: 0.0010 * ASPECT_RATIO
|
|
34
34
|
})
|
|
35
|
+
const [MARKERS, SETMARKERS] = useState(locations)
|
|
35
36
|
let mapRef = useRef<any>(null)
|
|
36
37
|
const googleMapsApiKey = configState?.configs?.google_maps_api_key?.value
|
|
37
38
|
|
|
@@ -41,12 +42,7 @@ export const GoogleMap = (props: GoogleMapsParams) => {
|
|
|
41
42
|
ERROR_NOT_FOUND_ADDRESS: 'Sorry, we couldn\'t find an address',
|
|
42
43
|
ERROR_MAX_LIMIT_LOCATION: `Sorry, You can only set the position to ${maxLimitLocation}m`
|
|
43
44
|
}
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
latitude: location.lat,
|
|
47
|
-
longitude: location.lng
|
|
48
|
-
}
|
|
49
|
-
})
|
|
45
|
+
|
|
50
46
|
const geocodePosition = (pos: { latitude: number, longitude: number }) => {
|
|
51
47
|
Geocoder.from({
|
|
52
48
|
latitude: pos.latitude,
|
|
@@ -147,7 +143,7 @@ export const GoogleMap = (props: GoogleMapsParams) => {
|
|
|
147
143
|
}
|
|
148
144
|
|
|
149
145
|
const fitAllMarkers = () => {
|
|
150
|
-
mapRef.current.fitToCoordinates(MARKERS, {
|
|
146
|
+
mapRef.current.fitToCoordinates(MARKERS?.map(location => ({ latitude: location.lat, longitude: location.lng })), {
|
|
151
147
|
edgePadding: { top: 80, right: 80, bottom: 80, left: 80 },
|
|
152
148
|
animated: true,
|
|
153
149
|
});
|
|
@@ -170,6 +166,9 @@ export const GoogleMap = (props: GoogleMapsParams) => {
|
|
|
170
166
|
fitAllMarkers()
|
|
171
167
|
}
|
|
172
168
|
}, 1000)
|
|
169
|
+
if (locations) {
|
|
170
|
+
SETMARKERS(locations)
|
|
171
|
+
}
|
|
173
172
|
return () => clearInterval(interval)
|
|
174
173
|
}, [locations])
|
|
175
174
|
|
|
@@ -189,16 +188,16 @@ export const GoogleMap = (props: GoogleMapsParams) => {
|
|
|
189
188
|
>
|
|
190
189
|
{locations ? (
|
|
191
190
|
<>
|
|
192
|
-
{MARKERS && MARKERS.map((location: {
|
|
191
|
+
{MARKERS && MARKERS.map((location: { lat: number, lng: number }, i: number) => (
|
|
193
192
|
<React.Fragment key={i}>
|
|
194
193
|
{
|
|
195
194
|
<Marker
|
|
196
195
|
zIndex={i}
|
|
197
|
-
coordinate={location}
|
|
198
|
-
title={
|
|
196
|
+
coordinate={{ latitude: location.lat ?? 0, longitude: location.lng ?? 0 }}
|
|
197
|
+
title={MARKERS[i]?.title}
|
|
199
198
|
>
|
|
200
199
|
<View>
|
|
201
|
-
<OIcon url={
|
|
200
|
+
<OIcon url={MARKERS[i].icon} width={50} height={50} />
|
|
202
201
|
</View>
|
|
203
202
|
</Marker>
|
|
204
203
|
}
|