ordering-ui-react-native 0.15.91 → 0.15.92
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/components/Checkout/index.tsx +23 -2
- package/themes/business/src/components/LoginForm/index.tsx +6 -4
- package/themes/business/src/components/NewOrderNotification/index.tsx +24 -13
- package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +1 -0
- package/themes/business/src/components/OrdersOption/index.tsx +5 -2
- package/themes/original/src/components/BusinessListingSearch/index.tsx +54 -2
- package/themes/original/src/components/BusinessListingSearch/styles.tsx +4 -0
- package/themes/original/src/components/BusinessesListing/index.tsx +3 -1
- package/themes/original/src/components/Checkout/index.tsx +36 -28
- package/themes/original/src/components/Help/index.tsx +21 -4
- package/themes/original/src/components/LastOrders/index.tsx +12 -1
- package/themes/original/src/components/LoginForm/index.tsx +40 -7
- package/themes/original/src/components/OrderDetails/index.tsx +18 -21
- package/themes/original/src/components/PaymentOptionWallet/index.tsx +1 -0
- package/themes/original/src/components/Promotions/index.tsx +18 -2
- package/themes/original/src/types/index.tsx +1 -0
package/package.json
CHANGED
|
@@ -592,6 +592,19 @@ const CheckoutUI = (props: any) => {
|
|
|
592
592
|
{t('WARNING_INVALID_PRODUCTS', 'Some products are invalid, please check them.')}
|
|
593
593
|
</OText>
|
|
594
594
|
)}
|
|
595
|
+
|
|
596
|
+
{options.type === 1 &&
|
|
597
|
+
validationFields?.fields?.checkout?.driver_tip?.enabled &&
|
|
598
|
+
validationFields?.fields?.checkout?.driver_tip?.required &&
|
|
599
|
+
(Number(cart?.driver_tip) <= 0) && (
|
|
600
|
+
<OText
|
|
601
|
+
style={{ textAlign: 'center' }}
|
|
602
|
+
color={theme.colors.error}
|
|
603
|
+
size={14}
|
|
604
|
+
>
|
|
605
|
+
{t('WARNING_INVALID_DRIVER_TIP', 'Driver Tip is required.')}
|
|
606
|
+
</OText>
|
|
607
|
+
)}
|
|
595
608
|
</ChErrors>
|
|
596
609
|
</ChSection>
|
|
597
610
|
)}
|
|
@@ -602,8 +615,16 @@ const CheckoutUI = (props: any) => {
|
|
|
602
615
|
<>
|
|
603
616
|
<FloatingButton
|
|
604
617
|
handleClick={() => handlePlaceOrder()}
|
|
605
|
-
isSecondaryBtn={loading || !cart?.valid || !paymethodSelected || placing || errorCash || cart?.subtotal_to_calculate < cart?.minimum || paymethodSelected?.gateway === 'paypal'
|
|
606
|
-
|
|
618
|
+
isSecondaryBtn={loading || !cart?.valid || !paymethodSelected || placing || errorCash || cart?.subtotal_to_calculate < cart?.minimum || paymethodSelected?.gateway === 'paypal' ||
|
|
619
|
+
(options.type === 1 &&
|
|
620
|
+
validationFields?.fields?.checkout?.driver_tip?.enabled &&
|
|
621
|
+
validationFields?.fields?.checkout?.driver_tip?.required &&
|
|
622
|
+
(Number(cart?.driver_tip) <= 0))}
|
|
623
|
+
disabled={loading || !cart?.valid || !paymethodSelected || placing || errorCash || cart?.subtotal_to_calculate < cart?.minimum || paymethodSelected?.gateway === 'paypal' ||
|
|
624
|
+
(options.type === 1 &&
|
|
625
|
+
validationFields?.fields?.checkout?.driver_tip?.enabled &&
|
|
626
|
+
validationFields?.fields?.checkout?.driver_tip?.required &&
|
|
627
|
+
(Number(cart?.driver_tip) <= 0))}
|
|
607
628
|
btnText={cart?.subtotal_to_calculate >= cart?.minimum
|
|
608
629
|
? (
|
|
609
630
|
placing
|
|
@@ -67,7 +67,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
67
67
|
const inputRef = useRef<any>(null);
|
|
68
68
|
const inputMailRef = useRef<any>(null);
|
|
69
69
|
|
|
70
|
-
const [projectName, setProjectName] = useState('');
|
|
70
|
+
const [projectName, setProjectName] = useState({name: '', isFocued: false});
|
|
71
71
|
const [passwordSee, setPasswordSee] = useState(false);
|
|
72
72
|
const [isLoadingVerifyModal, setIsLoadingVerifyModal] = useState(false);
|
|
73
73
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
|
@@ -125,15 +125,16 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
125
125
|
|
|
126
126
|
useEffect(() => {
|
|
127
127
|
const projectInputInterval = setInterval(() => {
|
|
128
|
-
if (projectName && useRootPoint) {
|
|
128
|
+
if (projectName.name && useRootPoint && projectName.isFocued) {
|
|
129
129
|
setOrdering({
|
|
130
130
|
...ordering,
|
|
131
|
-
project: projectName
|
|
131
|
+
project: projectName.name
|
|
132
132
|
})
|
|
133
133
|
}
|
|
134
134
|
}, 1500)
|
|
135
135
|
return () => clearInterval(projectInputInterval);
|
|
136
136
|
}, [projectName])
|
|
137
|
+
|
|
137
138
|
const getTraduction = (key: string) => {
|
|
138
139
|
const keyList: any = {
|
|
139
140
|
// Add the key and traduction that you need below
|
|
@@ -515,7 +516,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
515
516
|
icon={theme.images.general.project}
|
|
516
517
|
iconColor={theme.colors.arrowColor}
|
|
517
518
|
onChange={(e: any) => {
|
|
518
|
-
setProjectName(e?.target?.value)
|
|
519
|
+
setProjectName({name: e?.target?.value, isFocued: true})
|
|
519
520
|
onChange(e?.target?.value);
|
|
520
521
|
setSubmitted(false);
|
|
521
522
|
}}
|
|
@@ -544,6 +545,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
544
545
|
icon={theme.images.logos.emailInputIcon}
|
|
545
546
|
iconColor={theme.colors.arrowColor}
|
|
546
547
|
onChange={(e: any) => {
|
|
548
|
+
setProjectName({...projectName, isFocued: false})
|
|
547
549
|
handleChangeInputEmail(e, onChange);
|
|
548
550
|
}}
|
|
549
551
|
selectionColor={theme.colors.primary}
|
|
@@ -23,7 +23,7 @@ const NewOrderNotificationUI = (props: any) => {
|
|
|
23
23
|
const [ordering] = useApi()
|
|
24
24
|
const { getCurrentLocation } = useLocation();
|
|
25
25
|
const [soundTimeout, setSoundTimeout] = useState<any>(null)
|
|
26
|
-
|
|
26
|
+
let [currentEvent, setCurrentEvent] = useState<any>(null)
|
|
27
27
|
|
|
28
28
|
const evtList: any = {
|
|
29
29
|
1: {
|
|
@@ -46,6 +46,7 @@ const NewOrderNotificationUI = (props: any) => {
|
|
|
46
46
|
const notificationSound = new Sound(theme.sounds.notification, (e) => { console.log(e) });
|
|
47
47
|
|
|
48
48
|
const handlePlayNotificationSound = () => {
|
|
49
|
+
if (currentEvent) return
|
|
49
50
|
let times = 0
|
|
50
51
|
const _timeout = setInterval(function () {
|
|
51
52
|
notificationSound.play(success => {
|
|
@@ -63,30 +64,40 @@ const NewOrderNotificationUI = (props: any) => {
|
|
|
63
64
|
|
|
64
65
|
const handleCloseModal = () => {
|
|
65
66
|
clearInterval(soundTimeout)
|
|
67
|
+
currentEvent = null
|
|
66
68
|
setCurrentEvent({ evt: null })
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
const handleEventNotification = async (evtType: number, value: any) => {
|
|
70
72
|
if (value?.driver) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
73
|
+
try {
|
|
74
|
+
const location = await getCurrentLocation()
|
|
75
|
+
await fetch(`${ordering.root}/users/${user.id}/locations`, {
|
|
76
|
+
method: 'POST',
|
|
77
|
+
body: JSON.stringify({
|
|
78
|
+
location: JSON.stringify({location: `{lat: ${location.latitude}, lng: ${location.longitude}}`})
|
|
79
|
+
}),
|
|
80
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` }
|
|
81
|
+
})
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.log(error)
|
|
84
|
+
}
|
|
85
|
+
const duration = moment.duration(moment().diff(moment.utc(value?.last_driver_assigned_at)))
|
|
86
|
+
const assignedSecondsDiff = duration.asSeconds()
|
|
87
|
+
if (assignedSecondsDiff < 5 && !isBusinessApp) {
|
|
81
88
|
handlePlayNotificationSound()
|
|
82
89
|
clearInterval(soundTimeout)
|
|
90
|
+
currentEvent = { evt: 2, orderId: value?.id }
|
|
83
91
|
setCurrentEvent({ evt: 2, orderId: value?.id })
|
|
84
92
|
}
|
|
85
|
-
return
|
|
86
93
|
}
|
|
87
|
-
if (evtType === 3) return
|
|
94
|
+
if (evtType === 3 || value.author_id === user.id) return
|
|
88
95
|
handlePlayNotificationSound()
|
|
89
96
|
clearInterval(soundTimeout)
|
|
97
|
+
currentEvent = {
|
|
98
|
+
evt: evtType,
|
|
99
|
+
orderId: evtList[evtType].event === 'messages' ? value?.order_id : value?.id
|
|
100
|
+
}
|
|
90
101
|
setCurrentEvent({
|
|
91
102
|
evt: evtType,
|
|
92
103
|
orderId: evtList[evtType].event === 'messages' ? value?.order_id : value?.id
|
|
@@ -725,8 +725,11 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
|
|
|
725
725
|
</ScrollView>
|
|
726
726
|
</View>
|
|
727
727
|
{/* </GestureRecognizer> */}
|
|
728
|
-
|
|
729
|
-
|
|
728
|
+
|
|
729
|
+
{isBusinessApp && (
|
|
730
|
+
<NewOrderNotification isBusinessApp={isBusinessApp} />
|
|
731
|
+
)}
|
|
732
|
+
|
|
730
733
|
{(openSearchModal || openSLASettingModal) && (
|
|
731
734
|
<OModal open={openSearchModal || openSLASettingModal} entireModal customClose>
|
|
732
735
|
<ModalContainer
|
|
@@ -24,7 +24,8 @@ import {
|
|
|
24
24
|
TagsContainer,
|
|
25
25
|
SortContainer,
|
|
26
26
|
BrandContainer,
|
|
27
|
-
BrandItem
|
|
27
|
+
BrandItem,
|
|
28
|
+
PriceFilterWrapper
|
|
28
29
|
} from './styles'
|
|
29
30
|
import FastImage from 'react-native-fast-image'
|
|
30
31
|
import { convertHoursToMinutes } from '../../utils'
|
|
@@ -67,6 +68,14 @@ export const BusinessListingSearchUI = (props : BusinessSearchParams) => {
|
|
|
67
68
|
{ text: t('PICKUP_TIME', 'Pickup time'), value: 'pickup_time' }
|
|
68
69
|
]
|
|
69
70
|
|
|
71
|
+
const priceList = [
|
|
72
|
+
{ level: '1', content: '$' },
|
|
73
|
+
{ level: '2', content: '$$' },
|
|
74
|
+
{ level: '3', content: '$$$' },
|
|
75
|
+
{ level: '4', content: '$$$$' },
|
|
76
|
+
{ level: '5', content: '$$$$$' }
|
|
77
|
+
]
|
|
78
|
+
|
|
70
79
|
const styles = StyleSheet.create({
|
|
71
80
|
container: {
|
|
72
81
|
paddingHorizontal: 40,
|
|
@@ -93,6 +102,12 @@ export const BusinessListingSearchUI = (props : BusinessSearchParams) => {
|
|
|
93
102
|
flexWrap: 'wrap',
|
|
94
103
|
justifyContent: 'center'
|
|
95
104
|
},
|
|
105
|
+
priceContainer: {
|
|
106
|
+
width: '100%',
|
|
107
|
+
flexDirection: 'row',
|
|
108
|
+
flexWrap: 'wrap',
|
|
109
|
+
justifyContent: 'space-between'
|
|
110
|
+
},
|
|
96
111
|
categoryStyle: {
|
|
97
112
|
marginRight: 10,
|
|
98
113
|
marginTop: 10,
|
|
@@ -104,6 +119,16 @@ export const BusinessListingSearchUI = (props : BusinessSearchParams) => {
|
|
|
104
119
|
height: 28,
|
|
105
120
|
borderWidth: 0
|
|
106
121
|
},
|
|
122
|
+
priceItem: {
|
|
123
|
+
marginRight: 10,
|
|
124
|
+
marginTop: 10,
|
|
125
|
+
borderRadius: 50,
|
|
126
|
+
paddingVertical: 4,
|
|
127
|
+
paddingLeft: 5,
|
|
128
|
+
paddingRight: 5,
|
|
129
|
+
height: 27,
|
|
130
|
+
borderWidth: 0
|
|
131
|
+
},
|
|
107
132
|
applyButton: {
|
|
108
133
|
paddingHorizontal: 40,
|
|
109
134
|
width: '100%',
|
|
@@ -116,7 +141,7 @@ export const BusinessListingSearchUI = (props : BusinessSearchParams) => {
|
|
|
116
141
|
}
|
|
117
142
|
|
|
118
143
|
const handleCloseFilters = () => {
|
|
119
|
-
setFilters({ business_types: [], orderBy: 'default', franchise_ids: [] })
|
|
144
|
+
setFilters({ business_types: [], orderBy: 'default', franchise_ids: [], price_level: null })
|
|
120
145
|
setOpenFilters(false)
|
|
121
146
|
}
|
|
122
147
|
|
|
@@ -142,6 +167,11 @@ export const BusinessListingSearchUI = (props : BusinessSearchParams) => {
|
|
|
142
167
|
handleChangeFilters && handleChangeFilters('franchise_ids', franchiseIds)
|
|
143
168
|
}
|
|
144
169
|
|
|
170
|
+
const handleChangePriceRange = (value: string) => {
|
|
171
|
+
if (value === filters?.price_level) handleChangeFilters('price_level', null)
|
|
172
|
+
else handleChangeFilters('price_level', value)
|
|
173
|
+
}
|
|
174
|
+
|
|
145
175
|
const handleApplyFilters = () => {
|
|
146
176
|
handleSearchbusinessAndProducts(true)
|
|
147
177
|
setOpenFilters(false)
|
|
@@ -473,6 +503,28 @@ export const BusinessListingSearchUI = (props : BusinessSearchParams) => {
|
|
|
473
503
|
<OText size={14} weight='400'>{t('NO_RESULTS_FOUND', 'Sorry, no results found')}</OText>
|
|
474
504
|
)}
|
|
475
505
|
</BrandContainer>
|
|
506
|
+
<PriceFilterWrapper>
|
|
507
|
+
<OText
|
|
508
|
+
size={16}
|
|
509
|
+
weight='bold'
|
|
510
|
+
lineHeight={24}
|
|
511
|
+
style={{ marginBottom: 5 }}
|
|
512
|
+
>
|
|
513
|
+
{t('PRICE_RANGE', 'Price range')}
|
|
514
|
+
</OText>
|
|
515
|
+
<View style={styles.priceContainer}>
|
|
516
|
+
{priceList.map((price: any, i: number) => (
|
|
517
|
+
<OButton
|
|
518
|
+
key={i}
|
|
519
|
+
bgColor={(filters?.price_level === price?.level) ? theme.colors.primary : theme.colors.backgroundGray200}
|
|
520
|
+
onClick={() => handleChangePriceRange(price?.level)}
|
|
521
|
+
text={`${price.content} ${(filters?.price_level === price?.level) ? ' X' : ''}`}
|
|
522
|
+
style={styles.priceItem}
|
|
523
|
+
textStyle={{ fontSize: 10, color: (filters?.price_level === price?.level) ? theme.colors.backgroundLight : theme.colors.textNormal }}
|
|
524
|
+
/>
|
|
525
|
+
))}
|
|
526
|
+
</View>
|
|
527
|
+
</PriceFilterWrapper>
|
|
476
528
|
{orderState?.options?.type === 1 && (
|
|
477
529
|
<MaxSectionItem
|
|
478
530
|
title={t('MAX_DELIVERY_FEE', 'Max delivery fee')}
|
|
@@ -59,7 +59,8 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
59
59
|
handleBusinessClick,
|
|
60
60
|
paginationProps,
|
|
61
61
|
handleChangeSearch,
|
|
62
|
-
businessId
|
|
62
|
+
businessId,
|
|
63
|
+
isGuestUser
|
|
63
64
|
} = props;
|
|
64
65
|
const theme = useTheme();
|
|
65
66
|
const isFocused = useIsFocused();
|
|
@@ -242,6 +243,7 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
242
243
|
: navigation.navigate('AddressForm', {
|
|
243
244
|
address: orderState.options?.address,
|
|
244
245
|
isFromBusinesses: true,
|
|
246
|
+
isGuestUser: isGuestUser
|
|
245
247
|
})
|
|
246
248
|
}>
|
|
247
249
|
<OIcon
|
|
@@ -113,7 +113,10 @@ const CheckoutUI = (props: any) => {
|
|
|
113
113
|
right: Platform.OS === 'ios' ? 5 : (I18nManager.isRTL ? 30 : 0),
|
|
114
114
|
position: 'absolute',
|
|
115
115
|
fontSize: 20
|
|
116
|
-
}
|
|
116
|
+
},
|
|
117
|
+
wrapperNavbar: Platform.OS === 'ios'
|
|
118
|
+
? { paddingVertical: 0, paddingHorizontal: 40 }
|
|
119
|
+
: { paddingVertical: 20, paddingHorizontal: 40 }
|
|
117
120
|
})
|
|
118
121
|
|
|
119
122
|
const [, { showToast }] = useToast();
|
|
@@ -133,20 +136,20 @@ const CheckoutUI = (props: any) => {
|
|
|
133
136
|
const [isDeliveryOptionModalVisible, setIsDeliveryOptionModalVisible] = useState(false)
|
|
134
137
|
const [showGateway, setShowGateway] = useState<any>({ closedByUsed: false, open: false });
|
|
135
138
|
const [webviewPaymethod, setWebviewPaymethod] = useState<any>(null)
|
|
136
|
-
|
|
139
|
+
|
|
137
140
|
const placeSpotTypes = [3, 4]
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
141
|
+
const businessConfigs = businessDetails?.business?.configs ?? []
|
|
142
|
+
const isWalletCashEnabled = businessConfigs.find((config: any) => config.key === 'wallet_cash_enabled')?.value === '1'
|
|
143
|
+
const isWalletCreditPointsEnabled = businessConfigs.find((config: any) => config.key === 'wallet_credit_point_enabled')?.value === '1'
|
|
144
|
+
const isWalletEnabled = configs?.cash_wallet?.value && configs?.wallet_enabled?.value === '1' && (isWalletCashEnabled || isWalletCreditPointsEnabled)
|
|
142
145
|
|
|
143
146
|
const isPreOrder = configs?.preorder_status_enabled?.value === '1'
|
|
144
147
|
const isDisabledButtonPlace = loading || !cart?.valid || (!paymethodSelected && cart?.balance > 0) || placing || errorCash ||
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
cart?.subtotal < cart?.minimum || (placeSpotTypes.includes(options?.type) && !cart?.place) ||
|
|
149
|
+
(options.type === 1 &&
|
|
150
|
+
validationFields?.fields?.checkout?.driver_tip?.enabled &&
|
|
151
|
+
validationFields?.fields?.checkout?.driver_tip?.required &&
|
|
152
|
+
(Number(cart?.driver_tip) <= 0))
|
|
150
153
|
|
|
151
154
|
const driverTipsOptions = typeof configs?.driver_tip_options?.value === 'string'
|
|
152
155
|
? JSON.parse(configs?.driver_tip_options?.value) || []
|
|
@@ -259,13 +262,18 @@ const CheckoutUI = (props: any) => {
|
|
|
259
262
|
return (
|
|
260
263
|
<>
|
|
261
264
|
<Container noPadding>
|
|
262
|
-
<
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
265
|
+
<View style={styles.wrapperNavbar}>
|
|
266
|
+
<NavBar
|
|
267
|
+
title={t('CHECKOUT', 'Checkout')}
|
|
268
|
+
titleAlign={'center'}
|
|
269
|
+
onActionLeft={() => navigation?.canGoBack() && navigation.goBack()}
|
|
270
|
+
showCall={false}
|
|
271
|
+
btnStyle={{ paddingLeft: 0 }}
|
|
272
|
+
style={{ flexDirection: 'column', alignItems: 'flex-start', marginTop: Platform.OS === 'ios' ? 0 : 20 }}
|
|
273
|
+
titleWrapStyle={{ paddingHorizontal: 0 }}
|
|
274
|
+
titleStyle={{ marginRight: 0, marginLeft: 0 }}
|
|
275
|
+
/>
|
|
276
|
+
</View>
|
|
269
277
|
<ChContainer style={styles.pagePadding}>
|
|
270
278
|
<ChSection style={{ paddingTop: 0 }}>
|
|
271
279
|
<ChHeader>
|
|
@@ -668,16 +676,16 @@ const CheckoutUI = (props: any) => {
|
|
|
668
676
|
</OText>
|
|
669
677
|
)}
|
|
670
678
|
{options.type === 1 &&
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
679
|
+
validationFields?.fields?.checkout?.driver_tip?.enabled &&
|
|
680
|
+
validationFields?.fields?.checkout?.driver_tip?.required &&
|
|
681
|
+
(Number(cart?.driver_tip) <= 0) && (
|
|
682
|
+
<OText
|
|
683
|
+
color={theme.colors.error}
|
|
684
|
+
size={12}
|
|
685
|
+
>
|
|
686
|
+
{t('WARNING_INVALID_DRIVER_TIP', 'Driver Tip is required.')}
|
|
687
|
+
</OText>
|
|
688
|
+
)}
|
|
681
689
|
</ChErrors>
|
|
682
690
|
</View>
|
|
683
691
|
)}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import { RefreshControl } from 'react-native'
|
|
2
3
|
import { HelpParams } from '../../types'
|
|
3
4
|
import { useLanguage } from 'ordering-components/native'
|
|
4
5
|
import NavBar from '../NavBar'
|
|
5
6
|
import { OText } from '../shared'
|
|
6
7
|
import { LastOrders } from '../LastOrders'
|
|
8
|
+
import { Container } from '../../layouts/Container'
|
|
7
9
|
|
|
8
10
|
import {
|
|
9
11
|
HelpSubItem,
|
|
@@ -15,13 +17,28 @@ export const Help = (props: HelpParams) => {
|
|
|
15
17
|
navigation
|
|
16
18
|
} = props
|
|
17
19
|
const [, t] = useLanguage()
|
|
20
|
+
const [refreshing] = useState(false);
|
|
21
|
+
const [refresh, setRefresh] = useState(false)
|
|
18
22
|
|
|
19
23
|
const goToBack = () => navigation?.canGoBack() && navigation.goBack()
|
|
20
24
|
const onRedirect = (route: string, params?: any) => {
|
|
21
25
|
navigation.navigate(route, params)
|
|
22
26
|
}
|
|
27
|
+
|
|
28
|
+
const handleOnRefresh = () => {
|
|
29
|
+
setRefresh(true)
|
|
30
|
+
}
|
|
31
|
+
|
|
23
32
|
return (
|
|
24
|
-
|
|
33
|
+
<Container
|
|
34
|
+
noPadding
|
|
35
|
+
refreshControl={
|
|
36
|
+
<RefreshControl
|
|
37
|
+
refreshing={refreshing}
|
|
38
|
+
onRefresh={() => handleOnRefresh()}
|
|
39
|
+
/>
|
|
40
|
+
}
|
|
41
|
+
>
|
|
25
42
|
<NavBar
|
|
26
43
|
title={t('HELP', 'Help')}
|
|
27
44
|
titleAlign={'center'}
|
|
@@ -48,8 +65,8 @@ export const Help = (props: HelpParams) => {
|
|
|
48
65
|
|
|
49
66
|
<LastOrdersContainer>
|
|
50
67
|
<OText size={18} weight={600}>{t('LAST_ORDERS', 'Last Orders')}</OText>
|
|
51
|
-
<LastOrders {...props} onRedirect={onRedirect} />
|
|
68
|
+
<LastOrders {...props} onRedirect={onRedirect} refresh={refresh} setRefresh={setRefresh} />
|
|
52
69
|
</LastOrdersContainer>
|
|
53
|
-
|
|
70
|
+
</Container>
|
|
54
71
|
)
|
|
55
72
|
}
|
|
@@ -18,11 +18,15 @@ import {
|
|
|
18
18
|
OrderContainer,
|
|
19
19
|
OrderInfo
|
|
20
20
|
} from './styles'
|
|
21
|
+
import { useEffect } from 'react'
|
|
21
22
|
|
|
22
23
|
const LastOrdersUI = (props: LastOrdersParams) => {
|
|
23
24
|
const {
|
|
24
25
|
orderList,
|
|
25
|
-
onRedirect
|
|
26
|
+
onRedirect,
|
|
27
|
+
loadOrders,
|
|
28
|
+
refresh,
|
|
29
|
+
setRefresh
|
|
26
30
|
} = props
|
|
27
31
|
const { loading, error, orders } = orderList
|
|
28
32
|
|
|
@@ -46,6 +50,13 @@ const LastOrdersUI = (props: LastOrdersParams) => {
|
|
|
46
50
|
onRedirect && onRedirect('OrderDetails', { orderId: uuid })
|
|
47
51
|
}
|
|
48
52
|
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if(refresh){
|
|
55
|
+
loadOrders(false, false, false, true)
|
|
56
|
+
setRefresh && setRefresh(false)
|
|
57
|
+
}
|
|
58
|
+
}, [refresh])
|
|
59
|
+
|
|
49
60
|
return (
|
|
50
61
|
<>
|
|
51
62
|
{loading ? (
|
|
@@ -93,6 +93,8 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
93
93
|
const [recaptchaConfig, setRecaptchaConfig] = useState<any>({})
|
|
94
94
|
const [recaptchaVerified, setRecaptchaVerified] = useState(false)
|
|
95
95
|
const [alertState, setAlertState] = useState({ open: false, title: '', content: [] })
|
|
96
|
+
const [tabLayouts, setTabLayouts] = useState<any>({})
|
|
97
|
+
const tabsRef = useRef<any>(null)
|
|
96
98
|
|
|
97
99
|
const theme = useTheme();
|
|
98
100
|
const isOtpEmail = loginTab === 'otp' && otpType === 'email'
|
|
@@ -146,9 +148,10 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
146
148
|
const passwordRef = useRef<any>({});
|
|
147
149
|
const recaptchaRef = useRef<any>({});
|
|
148
150
|
|
|
149
|
-
const handleChangeTab = (val: string) => {
|
|
151
|
+
const handleChangeTab = (val: string, otpType?: string) => {
|
|
150
152
|
props.handleChangeTab(val);
|
|
151
153
|
setPasswordSee(false);
|
|
154
|
+
handleCategoryScroll(otpType ? `${val}_${otpType}` : val)
|
|
152
155
|
};
|
|
153
156
|
|
|
154
157
|
const onSubmit = (values?: any) => {
|
|
@@ -231,7 +234,7 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
231
234
|
}
|
|
232
235
|
|
|
233
236
|
const handleChangeOtpType = (type: string) => {
|
|
234
|
-
handleChangeTab('otp')
|
|
237
|
+
handleChangeTab('otp', type)
|
|
235
238
|
setOtpType(type)
|
|
236
239
|
}
|
|
237
240
|
|
|
@@ -248,6 +251,20 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
248
251
|
})
|
|
249
252
|
}
|
|
250
253
|
|
|
254
|
+
const handleCategoryScroll = (opc : string) => {
|
|
255
|
+
tabsRef.current.scrollTo({
|
|
256
|
+
x: tabLayouts?.[opc]?.x - 40,
|
|
257
|
+
animated: true
|
|
258
|
+
})
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const handleOnLayout = (event: any, opc: string) => {
|
|
262
|
+
const _tabLayouts = { ...tabLayouts }
|
|
263
|
+
const categoryKey = opc
|
|
264
|
+
_tabLayouts[categoryKey] = event.nativeEvent.layout
|
|
265
|
+
setTabLayouts(_tabLayouts)
|
|
266
|
+
}
|
|
267
|
+
|
|
251
268
|
useEffect(() => {
|
|
252
269
|
if (configs && Object.keys(configs).length > 0 && enableReCaptcha) {
|
|
253
270
|
setRecaptchaConfig({
|
|
@@ -331,9 +348,16 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
331
348
|
<FormSide>
|
|
332
349
|
{((useLoginByEmail && useLoginByCellphone) || useLoginOtp) && (
|
|
333
350
|
<LoginWith>
|
|
334
|
-
<OTabs
|
|
351
|
+
<OTabs
|
|
352
|
+
horizontal
|
|
353
|
+
showsHorizontalScrollIndicator={false}
|
|
354
|
+
ref={tabsRef}
|
|
355
|
+
>
|
|
335
356
|
{useLoginByEmail && (
|
|
336
|
-
<TabBtn
|
|
357
|
+
<TabBtn
|
|
358
|
+
onPress={() => handleChangeTab('email')}
|
|
359
|
+
onLayout={(event: any) => handleOnLayout(event, 'email')}
|
|
360
|
+
>
|
|
337
361
|
<OTab
|
|
338
362
|
style={{
|
|
339
363
|
borderBottomColor:
|
|
@@ -355,7 +379,10 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
355
379
|
</TabBtn>
|
|
356
380
|
)}
|
|
357
381
|
{useLoginByCellphone && (
|
|
358
|
-
<TabBtn
|
|
382
|
+
<TabBtn
|
|
383
|
+
onPress={() => handleChangeTab('cellphone')}
|
|
384
|
+
onLayout={(event: any) => handleOnLayout(event, 'cellphone')}
|
|
385
|
+
>
|
|
359
386
|
<OTab
|
|
360
387
|
style={{
|
|
361
388
|
borderBottomColor:
|
|
@@ -377,7 +404,10 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
377
404
|
</TabBtn>
|
|
378
405
|
)}
|
|
379
406
|
{useLoginOtpEmail && (
|
|
380
|
-
<TabBtn
|
|
407
|
+
<TabBtn
|
|
408
|
+
onPress={() => handleChangeOtpType('email')}
|
|
409
|
+
onLayout={(event: any) => handleOnLayout(event, 'otp_email')}
|
|
410
|
+
>
|
|
381
411
|
<OTab
|
|
382
412
|
style={{
|
|
383
413
|
borderBottomColor:
|
|
@@ -399,7 +429,10 @@ const LoginFormUI = (props: LoginParams) => {
|
|
|
399
429
|
</TabBtn>
|
|
400
430
|
)}
|
|
401
431
|
{useLoginOtpCellphone && (
|
|
402
|
-
<TabBtn
|
|
432
|
+
<TabBtn
|
|
433
|
+
onPress={() => handleChangeOtpType('cellphone')}
|
|
434
|
+
onLayout={(event: any) => handleOnLayout(event, 'otp_cellphone')}
|
|
435
|
+
>
|
|
403
436
|
<OTab
|
|
404
437
|
style={{
|
|
405
438
|
borderBottomColor:
|
|
@@ -42,7 +42,7 @@ import { OSRow } from '../OrderSummary/styles';
|
|
|
42
42
|
import AntIcon from 'react-native-vector-icons/AntDesign'
|
|
43
43
|
import { TaxInformation } from '../TaxInformation';
|
|
44
44
|
import { Placeholder, PlaceholderLine } from 'rn-placeholder';
|
|
45
|
-
|
|
45
|
+
import NavBar from '../NavBar'
|
|
46
46
|
export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
47
47
|
const {
|
|
48
48
|
navigation,
|
|
@@ -82,7 +82,8 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
82
82
|
justifyContent: 'flex-start',
|
|
83
83
|
paddingLeft: 0,
|
|
84
84
|
height: 30,
|
|
85
|
-
width:
|
|
85
|
+
width: 30,
|
|
86
|
+
marginTop: Platform.OS === 'ios' ? 0 : 30
|
|
86
87
|
},
|
|
87
88
|
});
|
|
88
89
|
|
|
@@ -364,7 +365,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
364
365
|
}
|
|
365
366
|
|
|
366
367
|
const RenderGoogleMap = () => {
|
|
367
|
-
const driverLocationString = typeof order?.driver?.location?.location === 'string' && order?.driver?.location?.location?.split(',').map((l
|
|
368
|
+
const driverLocationString = typeof order?.driver?.location?.location === 'string' && order?.driver?.location?.location?.split(',').map((l: string) => l.replace(/[^-.0-9]/g, ''))
|
|
368
369
|
const parsedLocations = locations.map(location => typeof location?.location === 'string' ? {
|
|
369
370
|
...location,
|
|
370
371
|
lat: parseFloat(location?.location?.split(',')[0].replace(/[^-.0-9]/g, '')),
|
|
@@ -498,27 +499,23 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
498
499
|
{order && Object.keys(order).length > 0 && (
|
|
499
500
|
<>
|
|
500
501
|
<Header>
|
|
501
|
-
<
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
502
|
+
<NavBar
|
|
503
|
+
title={`${t('ORDER', 'Order')} #${order?.id}`}
|
|
504
|
+
titleAlign={'center'}
|
|
505
|
+
onActionLeft={handleArrowBack}
|
|
506
|
+
showCall={false}
|
|
507
|
+
btnStyle={{ paddingLeft: 0 }}
|
|
508
|
+
style={{ flexDirection: 'column', alignItems: 'flex-start', marginTop: Platform.OS === 'ios' ? 0 : 20 }}
|
|
509
|
+
titleWrapStyle={{ paddingHorizontal: 0 }}
|
|
510
|
+
titleStyle={{ marginRight: 0, marginLeft: 0 }}
|
|
511
|
+
subTitle={<OText size={12} lineHeight={18} color={theme.colors.textNormal}>
|
|
512
|
+
{order?.delivery_datetime_utc
|
|
513
|
+
? parseDate(order?.delivery_datetime_utc)
|
|
514
|
+
: parseDate(order?.delivery_datetime, { utc: false })}
|
|
515
|
+
</OText>}
|
|
507
516
|
/>
|
|
508
517
|
<OrderInfo>
|
|
509
518
|
<OrderData>
|
|
510
|
-
<OText
|
|
511
|
-
size={20}
|
|
512
|
-
lineHeight={30}
|
|
513
|
-
weight={'600'}
|
|
514
|
-
color={theme.colors.textNormal}>
|
|
515
|
-
{t('ORDER', 'Order')} #{order?.id}
|
|
516
|
-
</OText>
|
|
517
|
-
<OText size={12} lineHeight={18} color={theme.colors.textNormal}>
|
|
518
|
-
{order?.delivery_datetime_utc
|
|
519
|
-
? parseDate(order?.delivery_datetime_utc)
|
|
520
|
-
: parseDate(order?.delivery_datetime, { utc: false })}
|
|
521
|
-
</OText>
|
|
522
519
|
{
|
|
523
520
|
(
|
|
524
521
|
parseInt(order?.status) === 1 ||
|
|
@@ -112,6 +112,7 @@ const PaymentOptionWalletUI = (props: any) => {
|
|
|
112
112
|
true: theme.colors.primary,
|
|
113
113
|
false: theme.colors.disabled
|
|
114
114
|
}}
|
|
115
|
+
onChange={() => handleOnChange(idx, wallet)}
|
|
115
116
|
tintColor={theme.colors.disabled}
|
|
116
117
|
onCheckColor={theme.colors.primary}
|
|
117
118
|
onTintColor={theme.colors.primary}
|
|
@@ -17,7 +17,7 @@ import { useTheme } from 'styled-components/native';
|
|
|
17
17
|
import { OButton, OIcon, OModal, OText } from '../shared'
|
|
18
18
|
import { Placeholder, PlaceholderLine } from 'rn-placeholder'
|
|
19
19
|
import { NotFoundSource } from '../NotFoundSource'
|
|
20
|
-
import { View, StyleSheet, ScrollView, Platform } from 'react-native'
|
|
20
|
+
import { View, StyleSheet, ScrollView, Platform, RefreshControl } from 'react-native'
|
|
21
21
|
import FastImage from 'react-native-fast-image'
|
|
22
22
|
import { PromotionParams } from '../../types'
|
|
23
23
|
import { Container } from '../../layouts/Container'
|
|
@@ -28,6 +28,7 @@ const PromotionsUI = (props: PromotionParams) => {
|
|
|
28
28
|
offersState,
|
|
29
29
|
handleSearchValue,
|
|
30
30
|
searchValue,
|
|
31
|
+
loadOffers,
|
|
31
32
|
offerSelected,
|
|
32
33
|
setOfferSelected
|
|
33
34
|
} = props
|
|
@@ -68,6 +69,7 @@ const PromotionsUI = (props: PromotionParams) => {
|
|
|
68
69
|
const [, t] = useLanguage()
|
|
69
70
|
const [{ parseDate, parsePrice, optimizeImage }] = useUtils()
|
|
70
71
|
const [openModal, setOpenModal] = useState(false)
|
|
72
|
+
const [refreshing] = useState(false);
|
|
71
73
|
|
|
72
74
|
const handleClickOffer = (offer: any) => {
|
|
73
75
|
setOpenModal(true)
|
|
@@ -79,6 +81,12 @@ const PromotionsUI = (props: PromotionParams) => {
|
|
|
79
81
|
navigation.navigate('Business', { store: store.slug })
|
|
80
82
|
}
|
|
81
83
|
|
|
84
|
+
const handleOnRefresh = () => {
|
|
85
|
+
if (!offersState.loading) {
|
|
86
|
+
loadOffers();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
82
90
|
const filteredOffers = offersState?.offers?.filter((offer: any) => offer.name.toLowerCase().includes(searchValue.toLowerCase()))
|
|
83
91
|
const targetString = offerSelected?.target === 1
|
|
84
92
|
? t('SUBTOTAL', 'Subtotal')
|
|
@@ -87,7 +95,15 @@ const PromotionsUI = (props: PromotionParams) => {
|
|
|
87
95
|
: t('SERVICE_FEE', 'Service fee')
|
|
88
96
|
|
|
89
97
|
return (
|
|
90
|
-
<Container
|
|
98
|
+
<Container
|
|
99
|
+
noPadding
|
|
100
|
+
refreshControl={
|
|
101
|
+
<RefreshControl
|
|
102
|
+
refreshing={refreshing}
|
|
103
|
+
onRefresh={() => handleOnRefresh()}
|
|
104
|
+
/>
|
|
105
|
+
}
|
|
106
|
+
>
|
|
91
107
|
<NavBar
|
|
92
108
|
title={t('PROMOTIONS', 'Promotions')}
|
|
93
109
|
titleAlign={'center'}
|
|
@@ -153,6 +153,7 @@ export interface BusinessesListingParams {
|
|
|
153
153
|
defaultBusinessType?: any;
|
|
154
154
|
franchiseId?: any;
|
|
155
155
|
businessId?: any;
|
|
156
|
+
isGuestUser?: any;
|
|
156
157
|
}
|
|
157
158
|
export interface HighestRatedBusinessesParams {
|
|
158
159
|
businessesList: { businesses: Array<any>, loading: boolean, error: null | string };
|