ordering-ui-react-native 0.15.14 → 0.15.17
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/business/src/components/OrdersOption/index.tsx +16 -67
- package/themes/business/src/components/OrdersOption/styles.tsx +2 -5
- package/themes/kiosk/src/components/BusinessProductsListing/index.tsx +2 -2
- package/themes/original/src/components/BusinessesListing/index.tsx +1 -1
- package/themes/original/src/components/Cart/index.tsx +40 -7
- package/themes/original/src/components/Checkout/index.tsx +19 -10
- package/themes/original/src/components/Messages/index.tsx +1 -1
- package/themes/original/src/components/OrderDetails/index.tsx +36 -36
- package/themes/original/src/components/OrderSummary/index.tsx +33 -0
- package/themes/original/src/components/PlaceSpot/index.tsx +114 -0
- package/themes/original/src/components/PlaceSpot/styles.tsx +11 -0
- package/themes/original/src/components/ProductForm/index.tsx +10 -6
- package/themes/original/src/types/index.tsx +9 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useEffect, useState, useRef } from 'react';
|
|
2
2
|
import { View, Pressable, StyleSheet, ScrollView, RefreshControl, Linking, Platform, TextInput } from 'react-native';
|
|
3
|
-
import { useLanguage, useUtils, useToast, ToastType, OrderListGroups } from 'ordering-components/native';
|
|
3
|
+
import { useLanguage, useUtils, useToast, ToastType, OrderListGroups, useConfig } from 'ordering-components/native';
|
|
4
4
|
import SelectDropdown from 'react-native-select-dropdown'
|
|
5
5
|
import { Placeholder, PlaceholderLine, Fade } from 'rn-placeholder';
|
|
6
6
|
import FeatherIcon from 'react-native-vector-icons/Feather';
|
|
@@ -400,20 +400,6 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
|
|
|
400
400
|
setOpenSLASettingModal(false)
|
|
401
401
|
}
|
|
402
402
|
|
|
403
|
-
const [settingTimeErrorMessage, setSettingTimeErrorMessage] = useState('')
|
|
404
|
-
|
|
405
|
-
const handlSLASettingTime = () => {
|
|
406
|
-
if (!hour || !minute) {
|
|
407
|
-
setSettingTimeErrorMessage(t('SLA_SETTING_ERROR', 'Time value is invalid'))
|
|
408
|
-
return
|
|
409
|
-
}
|
|
410
|
-
const _settingTimeSecond = hour * 3600 + minute * 60
|
|
411
|
-
setSlaSettingTime(_settingTimeSecond)
|
|
412
|
-
handleClose()
|
|
413
|
-
showToast(ToastType.Success, t('SLA_SETTING_UPDATED', 'SLAs setting updated'))
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
|
|
417
403
|
useEffect(() => {
|
|
418
404
|
setCurrentFilters(null)
|
|
419
405
|
onFiltered && onFiltered(null)
|
|
@@ -859,24 +845,10 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
|
|
|
859
845
|
key={i}
|
|
860
846
|
item={item}
|
|
861
847
|
last={i + 1 === selectedTabStatus.length}
|
|
862
|
-
setHour={setHour}
|
|
863
|
-
setMinute={setMinute}
|
|
864
|
-
setSettingTimeErrorMessage={setSettingTimeErrorMessage}
|
|
865
848
|
/>
|
|
866
849
|
))}
|
|
867
850
|
<VerticalLine />
|
|
868
851
|
</DeliveryStatusWrapper>
|
|
869
|
-
{settingTimeErrorMessage !== '' && (
|
|
870
|
-
<OText style={styles.errorMessage}>{settingTimeErrorMessage}</OText>
|
|
871
|
-
)}
|
|
872
|
-
<Actions>
|
|
873
|
-
<OButton
|
|
874
|
-
text={t('ACCEPT', 'Accept')}
|
|
875
|
-
textStyle={{ color: 'white', fontSize: 14 }}
|
|
876
|
-
onClick={handlSLASettingTime}
|
|
877
|
-
style={styles.acceptButtonStyle}
|
|
878
|
-
/>
|
|
879
|
-
</Actions>
|
|
880
852
|
</SlaSettingModalContent>
|
|
881
853
|
)}
|
|
882
854
|
</ModalContainer>
|
|
@@ -887,7 +859,7 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
|
|
|
887
859
|
};
|
|
888
860
|
|
|
889
861
|
export const StatusBlock = (props: any) => {
|
|
890
|
-
const { item, last
|
|
862
|
+
const { item, last } = props
|
|
891
863
|
const [showTime, setShowTime] = useState(false)
|
|
892
864
|
|
|
893
865
|
useEffect(() => {
|
|
@@ -898,7 +870,7 @@ export const StatusBlock = (props: any) => {
|
|
|
898
870
|
|
|
899
871
|
return (
|
|
900
872
|
<StatusItems>
|
|
901
|
-
<Pressable
|
|
873
|
+
<Pressable style={{ marginBottom: 10 }}>
|
|
902
874
|
<ItemHeader>
|
|
903
875
|
<IconWrapper>
|
|
904
876
|
<OIcon
|
|
@@ -916,11 +888,7 @@ export const StatusBlock = (props: any) => {
|
|
|
916
888
|
<OText>{item?.des}</OText>
|
|
917
889
|
</ItemContent>
|
|
918
890
|
{showTime && (
|
|
919
|
-
<Timer
|
|
920
|
-
setHour={setHour}
|
|
921
|
-
setMinute={setMinute}
|
|
922
|
-
setSettingTimeErrorMessage={setSettingTimeErrorMessage}
|
|
923
|
-
/>
|
|
891
|
+
<Timer />
|
|
924
892
|
)}
|
|
925
893
|
{last && (
|
|
926
894
|
<OverLine />
|
|
@@ -929,47 +897,28 @@ export const StatusBlock = (props: any) => {
|
|
|
929
897
|
)
|
|
930
898
|
}
|
|
931
899
|
|
|
932
|
-
export const Timer = (
|
|
933
|
-
const { setHour, setMinute, setSettingTimeErrorMessage } = props
|
|
900
|
+
export const Timer = () => {
|
|
934
901
|
const [, t] = useLanguage()
|
|
935
902
|
const theme = useTheme()
|
|
903
|
+
const [{ configs }] = useConfig();
|
|
936
904
|
|
|
937
905
|
const styles = StyleSheet.create({
|
|
938
|
-
|
|
939
|
-
paddingHorizontal: 7,
|
|
940
|
-
paddingVertical: 2,
|
|
941
|
-
borderRadius: 0,
|
|
906
|
+
settingTime: {
|
|
942
907
|
fontSize: 14,
|
|
908
|
+
borderWidth: 1,
|
|
909
|
+
borderRadius: 7.6,
|
|
910
|
+
margin: 0,
|
|
911
|
+
marginRight: 10,
|
|
912
|
+
paddingHorizontal: 10,
|
|
913
|
+
paddingTop: 5,
|
|
914
|
+
borderColor: theme.colors.disabled
|
|
943
915
|
}
|
|
944
916
|
})
|
|
945
917
|
|
|
946
|
-
const handleChangeInput = (val: any, type: string) => {
|
|
947
|
-
setSettingTimeErrorMessage('')
|
|
948
|
-
if (type === 'hour') {
|
|
949
|
-
setHour(val)
|
|
950
|
-
}
|
|
951
|
-
if (type === 'minute') {
|
|
952
|
-
setMinute(val)
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
|
|
956
918
|
return (
|
|
957
919
|
<TimerInputWrapper>
|
|
958
|
-
<
|
|
959
|
-
|
|
960
|
-
keyboardType='number-pad'
|
|
961
|
-
maxLength={2}
|
|
962
|
-
style={{ ...styles.inputStyle, width: 36 }}
|
|
963
|
-
onChangeText={hour => handleChangeInput(hour, 'hour')}
|
|
964
|
-
/>
|
|
965
|
-
<OText color={theme.colors.disabled}>:</OText>
|
|
966
|
-
<TextInput
|
|
967
|
-
placeholder='MM'
|
|
968
|
-
keyboardType='number-pad'
|
|
969
|
-
maxLength={2}
|
|
970
|
-
style={{ ...styles.inputStyle, width: 40 }}
|
|
971
|
-
onChangeText={minute => handleChangeInput(minute, 'minute')}
|
|
972
|
-
/>
|
|
920
|
+
<OText style={styles.settingTime} color={theme.colors.disabled}>{configs?.order_deadlines_delayed_time?.value}</OText>
|
|
921
|
+
<OText>{t('MIN', 'min')}</OText>
|
|
973
922
|
</TimerInputWrapper>
|
|
974
923
|
)
|
|
975
924
|
}
|
|
@@ -130,15 +130,12 @@ export const ItemContent = styled.View`
|
|
|
130
130
|
`
|
|
131
131
|
|
|
132
132
|
export const TimerInputWrapper = styled.View`
|
|
133
|
-
border-width: 1px;
|
|
134
|
-
border-radius: 7.6px;
|
|
135
133
|
color: ${(props: any) => props.theme.colors.disabled};
|
|
136
|
-
|
|
134
|
+
margin-top: 15px;
|
|
137
135
|
margin-left: 30px;
|
|
138
136
|
margin-right: 30px;
|
|
139
137
|
flex-direction: row;
|
|
140
|
-
align-items:
|
|
141
|
-
width: 80px;
|
|
138
|
+
align-items: flex-end;
|
|
142
139
|
`
|
|
143
140
|
export const OverLine = styled.View`
|
|
144
141
|
position: absolute;
|
|
@@ -93,7 +93,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
93
93
|
>
|
|
94
94
|
<Category
|
|
95
95
|
style={cardStyle}
|
|
96
|
-
source={{uri: item.images}}
|
|
96
|
+
source={item.images ? {uri: item.images} : theme.images.categories.all}
|
|
97
97
|
resizeMode="cover"
|
|
98
98
|
w={widthScreen}
|
|
99
99
|
borderRadius={16}
|
|
@@ -172,7 +172,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
|
|
|
172
172
|
<OCard
|
|
173
173
|
key={category.id}
|
|
174
174
|
title={category?.name || ''}
|
|
175
|
-
image={{uri: category
|
|
175
|
+
image={category.images ? {uri: category.images} : theme.images.categories.all}
|
|
176
176
|
style={{
|
|
177
177
|
width:
|
|
178
178
|
orientationState?.orientation === LANDSCAPE
|
|
@@ -168,7 +168,7 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
|
|
|
168
168
|
|
|
169
169
|
useEffect(() => {
|
|
170
170
|
if (businessesList.businesses.length > 0) {
|
|
171
|
-
const fb = businessesList.businesses.filter((b) => b.featured
|
|
171
|
+
const fb = businessesList.businesses.filter((b) => b.featured === true && b?.open);
|
|
172
172
|
const ary = [];
|
|
173
173
|
while (fb.length > 0) {
|
|
174
174
|
ary.push(fb.splice(0, 2));
|
|
@@ -24,6 +24,7 @@ import AntIcon from 'react-native-vector-icons/AntDesign'
|
|
|
24
24
|
import { TaxInformation } from '../TaxInformation';
|
|
25
25
|
import { CartStoresListing } from '../CartStoresListing';
|
|
26
26
|
import { OAlert } from '../../../../../src/components/shared'
|
|
27
|
+
import { PlaceSpot } from '../PlaceSpot'
|
|
27
28
|
|
|
28
29
|
const CartUI = (props: any) => {
|
|
29
30
|
const {
|
|
@@ -54,12 +55,14 @@ const CartUI = (props: any) => {
|
|
|
54
55
|
const [canOpenUpselling, setCanOpenUpselling] = useState(false)
|
|
55
56
|
const [openTaxModal, setOpenTaxModal] = useState<any>({ open: false, data: null, type: '' })
|
|
56
57
|
const [confirm, setConfirm] = useState<any>({ open: false, content: null, handleOnAccept: null, id: null, title: null })
|
|
58
|
+
const [openPlaceModal, setOpenPlaceModal] = useState(false)
|
|
57
59
|
|
|
58
60
|
const isCartPending = cart?.status === 2
|
|
59
61
|
const isCouponEnabled = validationFields?.fields?.checkout?.coupon?.enabled
|
|
60
62
|
|
|
61
63
|
const business: any = (orderState?.carts && Object.values(orderState.carts).find((_cart: any) => _cart?.uuid === props.cartuuid)) ?? {}
|
|
62
64
|
const businessId = business?.business_id ?? null
|
|
65
|
+
const placeSpotTypes = [3, 4]
|
|
63
66
|
|
|
64
67
|
const momentFormatted = !orderState?.option?.moment
|
|
65
68
|
? t('RIGHT_NOW', 'Right Now')
|
|
@@ -353,6 +356,24 @@ const CartUI = (props: any) => {
|
|
|
353
356
|
</OText>
|
|
354
357
|
</OSTable>
|
|
355
358
|
</OSTotal>
|
|
359
|
+
{placeSpotTypes.includes(orderState?.options?.type) && (
|
|
360
|
+
<OSTable style={{ marginTop: 15 }}>
|
|
361
|
+
<OText size={14} lineHeight={21} weight={'600'}>
|
|
362
|
+
{t('SPOT', 'Spot')}: {cart?.place?.name || t('NO_SELECTED', 'No selected')}
|
|
363
|
+
</OText>
|
|
364
|
+
<TouchableOpacity onPress={() => setOpenPlaceModal(true)}>
|
|
365
|
+
<OText
|
|
366
|
+
size={14}
|
|
367
|
+
lineHeight={21}
|
|
368
|
+
weight={'600'}
|
|
369
|
+
color={theme.colors.primary}
|
|
370
|
+
style={{ textDecorationLine: 'underline' }}
|
|
371
|
+
>
|
|
372
|
+
{t('EDIT', 'Edit')}
|
|
373
|
+
</OText>
|
|
374
|
+
</TouchableOpacity>
|
|
375
|
+
</OSTable>
|
|
376
|
+
)}
|
|
356
377
|
{cart?.status !== 2 && (
|
|
357
378
|
<OSTable>
|
|
358
379
|
<View style={{ width: '100%', marginTop: 20 }}>
|
|
@@ -434,14 +455,26 @@ const CartUI = (props: any) => {
|
|
|
434
455
|
products={cart?.products}
|
|
435
456
|
/>
|
|
436
457
|
</OModal>
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
458
|
+
<OModal
|
|
459
|
+
open={openPlaceModal}
|
|
460
|
+
title={t('CHOOSE_YOUR_SPOT', 'Choose your spot')}
|
|
461
|
+
onClose={() => setOpenPlaceModal(false)}
|
|
462
|
+
entireModal
|
|
463
|
+
>
|
|
464
|
+
<PlaceSpot
|
|
465
|
+
cart={cart}
|
|
466
|
+
isOpenPlaceSpot={openPlaceModal}
|
|
467
|
+
setOpenPlaceModal={setOpenPlaceModal}
|
|
444
468
|
/>
|
|
469
|
+
</OModal>
|
|
470
|
+
<OAlert
|
|
471
|
+
open={confirm.open}
|
|
472
|
+
title={confirm.title}
|
|
473
|
+
content={confirm.content}
|
|
474
|
+
onAccept={confirm.handleOnAccept}
|
|
475
|
+
onCancel={() => setConfirm({ ...confirm, open: false, title: null })}
|
|
476
|
+
onClose={() => setConfirm({ ...confirm, open: false, title: null })}
|
|
477
|
+
/>
|
|
445
478
|
</CContainer>
|
|
446
479
|
)
|
|
447
480
|
}
|
|
@@ -132,10 +132,11 @@ const CheckoutUI = (props: any) => {
|
|
|
132
132
|
const [isDeliveryOptionModalVisible, setIsDeliveryOptionModalVisible] = useState(false)
|
|
133
133
|
const [showGateway, setShowGateway] = useState<any>({ closedByUsed: false, open: false });
|
|
134
134
|
const [webviewPaymethod, setWebviewPaymethod] = useState<any>(null)
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
|
|
136
|
+
const placeSpotTypes = [3, 4]
|
|
137
137
|
const isWalletEnabled = configs?.wallet_enabled?.value === '1' && (configs?.wallet_cash_enabled?.value === '1' || configs?.wallet_credit_point_enabled?.value === '1')
|
|
138
138
|
const isPreOrder = configs?.preorder_status_enabled?.value === '1'
|
|
139
|
+
const isDisabledButtonPlace = loading || !cart?.valid || (!paymethodSelected && cart?.balance > 0) || placing || errorCash || cart?.subtotal < cart?.minimum || (placeSpotTypes.includes(options?.type) && !cart?.place)
|
|
139
140
|
|
|
140
141
|
const driverTipsOptions = typeof configs?.driver_tip_options?.value === 'string'
|
|
141
142
|
? JSON.parse(configs?.driver_tip_options?.value) || []
|
|
@@ -156,7 +157,7 @@ const CheckoutUI = (props: any) => {
|
|
|
156
157
|
navigation.navigate('MomentOption')
|
|
157
158
|
}
|
|
158
159
|
}
|
|
159
|
-
|
|
160
|
+
|
|
160
161
|
const handlePlaceOrder = () => {
|
|
161
162
|
if (!userErrors.length) {
|
|
162
163
|
handlerClickPlaceOrder && handlerClickPlaceOrder()
|
|
@@ -201,8 +202,8 @@ const CheckoutUI = (props: any) => {
|
|
|
201
202
|
if (
|
|
202
203
|
!user?.cellphone &&
|
|
203
204
|
((validationFields?.fields?.checkout?.cellphone?.enabled &&
|
|
204
|
-
|
|
205
|
-
|
|
205
|
+
validationFields?.fields?.checkout?.cellphone?.required) ||
|
|
206
|
+
configs?.verification_phone_required?.value === '1')
|
|
206
207
|
) {
|
|
207
208
|
errors.push(t('VALIDATION_ERROR_MOBILE_PHONE_REQUIRED', 'The field Phone number is required'))
|
|
208
209
|
}
|
|
@@ -268,15 +269,15 @@ const CheckoutUI = (props: any) => {
|
|
|
268
269
|
/>
|
|
269
270
|
</CHMomentWrapper>
|
|
270
271
|
<CHMomentWrapper
|
|
271
|
-
|
|
272
|
-
|
|
272
|
+
onPress={() => handleMomentClick()}
|
|
273
|
+
disabled={loading}
|
|
273
274
|
>
|
|
274
275
|
<OText size={12} numberOfLines={1} ellipsizeMode='tail' color={theme.colors.textSecondary}>
|
|
275
276
|
{options?.moment
|
|
276
277
|
? parseDate(options?.moment, { outputFormat: configs?.dates_moment_format?.value })
|
|
277
278
|
: t('ASAP_ABBREVIATION', 'ASAP')}
|
|
278
279
|
</OText>
|
|
279
|
-
{
|
|
280
|
+
{isPreOrder && (
|
|
280
281
|
<OIcon
|
|
281
282
|
src={theme.images.general.arrow_down}
|
|
282
283
|
width={10}
|
|
@@ -648,6 +649,14 @@ const CheckoutUI = (props: any) => {
|
|
|
648
649
|
{t('WARNING_INVALID_PRODUCTS', 'Some products are invalid, please check them.')}
|
|
649
650
|
</OText>
|
|
650
651
|
)}
|
|
652
|
+
{placeSpotTypes.includes(options?.type) && !cart?.place && (
|
|
653
|
+
<OText
|
|
654
|
+
color={theme.colors.error}
|
|
655
|
+
size={12}
|
|
656
|
+
>
|
|
657
|
+
{t('WARNING_PLACE_SPOT', 'Please, select your spot to place order.')}
|
|
658
|
+
</OText>
|
|
659
|
+
)}
|
|
651
660
|
</ChErrors>
|
|
652
661
|
</View>
|
|
653
662
|
)}
|
|
@@ -667,8 +676,8 @@ const CheckoutUI = (props: any) => {
|
|
|
667
676
|
{!cartState.loading && cart && cart?.status !== 2 && (
|
|
668
677
|
<FloatingButton
|
|
669
678
|
handleClick={() => handlePlaceOrder()}
|
|
670
|
-
isSecondaryBtn={
|
|
671
|
-
disabled={
|
|
679
|
+
isSecondaryBtn={isDisabledButtonPlace}
|
|
680
|
+
disabled={isDisabledButtonPlace}
|
|
672
681
|
btnText={cart?.subtotal >= cart?.minimum
|
|
673
682
|
? (
|
|
674
683
|
placing
|
|
@@ -97,7 +97,7 @@ const MessagesUI = (props: MessagesParams) => {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
const handleImagePicker = () => {
|
|
100
|
-
launchImageLibrary({ mediaType: 'photo', maxHeight:
|
|
100
|
+
launchImageLibrary({ mediaType: 'photo', maxHeight: 2048, maxWidth: 2048, includeBase64: true }, (response: any) => {
|
|
101
101
|
if (response.didCancel) {
|
|
102
102
|
console.log('User cancelled image picker');
|
|
103
103
|
} else if (response.errorMessage) {
|
|
@@ -293,18 +293,18 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
293
293
|
percentage: 95,
|
|
294
294
|
image: theme.images.order.status7,
|
|
295
295
|
},
|
|
296
|
-
{
|
|
297
|
-
key: 22,
|
|
298
|
-
value: t('ORDER_LOOKING_FOR_DRIVER', 'Looking for driver'),
|
|
299
|
-
slug: 'ORDER_LOOKING_FOR_DRIVER',
|
|
300
|
-
percentage: 35,
|
|
301
|
-
image: theme.images.order.status8
|
|
296
|
+
{
|
|
297
|
+
key: 22,
|
|
298
|
+
value: t('ORDER_LOOKING_FOR_DRIVER', 'Looking for driver'),
|
|
299
|
+
slug: 'ORDER_LOOKING_FOR_DRIVER',
|
|
300
|
+
percentage: 35,
|
|
301
|
+
image: theme.images.order.status8
|
|
302
302
|
},
|
|
303
|
-
{
|
|
304
|
-
key: 23,
|
|
305
|
-
value: t('ORDER_DRIVER_ON_WAY', 'Driver on way'),
|
|
306
|
-
slug: 'ORDER_DRIVER_ON_WAY',
|
|
307
|
-
percentage: 45,
|
|
303
|
+
{
|
|
304
|
+
key: 23,
|
|
305
|
+
value: t('ORDER_DRIVER_ON_WAY', 'Driver on way'),
|
|
306
|
+
slug: 'ORDER_DRIVER_ON_WAY',
|
|
307
|
+
percentage: 45,
|
|
308
308
|
image: theme.images.order.status8
|
|
309
309
|
}
|
|
310
310
|
];
|
|
@@ -430,10 +430,6 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
430
430
|
}
|
|
431
431
|
}, [driverLocation]);
|
|
432
432
|
|
|
433
|
-
useEffect(() => {
|
|
434
|
-
console.log('order: ', order)
|
|
435
|
-
}, [order]);
|
|
436
|
-
|
|
437
433
|
return (
|
|
438
434
|
<OrderDetailsContainer keyboardShouldPersistTaps="handled">
|
|
439
435
|
{(!order || Object.keys(order).length === 0) && (
|
|
@@ -481,7 +477,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
481
477
|
<PlaceholderLine width={65} height={10} />
|
|
482
478
|
<PlaceholderLine width={80} height={10} />
|
|
483
479
|
<PlaceholderLine width={70} height={10} />
|
|
484
|
-
<View style={{marginTop: 10}}>
|
|
480
|
+
<View style={{ marginTop: 10 }}>
|
|
485
481
|
<PlaceholderLine width={60} height={20} />
|
|
486
482
|
<PlaceholderLine width={40} height={10} />
|
|
487
483
|
</View>
|
|
@@ -594,18 +590,20 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
594
590
|
{order?.business?.name}
|
|
595
591
|
</OText>
|
|
596
592
|
<Icons>
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
593
|
+
{!!order?.business?.cellphone && (
|
|
594
|
+
<TouchableOpacity
|
|
595
|
+
onPress={() => order?.business?.cellphone &&
|
|
596
|
+
Linking.openURL(`tel:${order?.business?.cellphone}`)
|
|
597
|
+
}
|
|
598
|
+
style={{ paddingEnd: 5 }}
|
|
599
|
+
>
|
|
600
|
+
<OIcon
|
|
601
|
+
src={theme.images.general.phone}
|
|
602
|
+
width={16}
|
|
603
|
+
color={theme.colors.disabled}
|
|
604
|
+
/>
|
|
605
|
+
</TouchableOpacity>
|
|
606
|
+
)}
|
|
609
607
|
<TouchableOpacity
|
|
610
608
|
style={{ paddingStart: 5 }}
|
|
611
609
|
onPress={() => handleOpenMessagesForBusiness()}>
|
|
@@ -624,13 +622,15 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
624
622
|
mBottom={2}>
|
|
625
623
|
{order?.business?.email}
|
|
626
624
|
</OText>
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
625
|
+
{!!order?.business?.cellphone && (
|
|
626
|
+
<OText
|
|
627
|
+
size={12}
|
|
628
|
+
lineHeight={18}
|
|
629
|
+
color={theme.colors.textNormal}
|
|
630
|
+
mBottom={2}>
|
|
631
|
+
{order?.business?.cellphone}
|
|
632
|
+
</OText>
|
|
633
|
+
)}
|
|
634
634
|
<OText size={12} lineHeight={18} color={theme.colors.textNormal}>
|
|
635
635
|
{order?.business?.address}
|
|
636
636
|
</OText>
|
|
@@ -978,7 +978,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
978
978
|
marginTop: 10
|
|
979
979
|
}}
|
|
980
980
|
>
|
|
981
|
-
{order?.payment_events?.map((event: any) => (
|
|
981
|
+
{order?.payment_events?.map((event: any) => event.amount > 0 && (
|
|
982
982
|
<View
|
|
983
983
|
key={event.id}
|
|
984
984
|
style={{
|
|
@@ -26,6 +26,7 @@ import AntIcon from 'react-native-vector-icons/AntDesign'
|
|
|
26
26
|
import { TaxInformation } from '../TaxInformation';
|
|
27
27
|
import { TouchableOpacity } from 'react-native';
|
|
28
28
|
import { OAlert } from '../../../../../src/components/shared'
|
|
29
|
+
import { PlaceSpot } from '../PlaceSpot'
|
|
29
30
|
|
|
30
31
|
const OrderSummaryUI = (props: any) => {
|
|
31
32
|
const {
|
|
@@ -49,7 +50,9 @@ const OrderSummaryUI = (props: any) => {
|
|
|
49
50
|
const [validationFields] = useValidationFields();
|
|
50
51
|
const [openTaxModal, setOpenTaxModal] = useState<any>({ open: false, data: null, type: '' })
|
|
51
52
|
const [confirm, setConfirm] = useState<any>({ open: false, content: null, handleOnAccept: null, id: null, title: null })
|
|
53
|
+
const [openPlaceModal, setOpenPlaceModal] = useState(false)
|
|
52
54
|
const isCouponEnabled = validationFields?.fields?.checkout?.coupon?.enabled;
|
|
55
|
+
const placeSpotTypes = [3, 4]
|
|
53
56
|
|
|
54
57
|
const handleDeleteClick = (product: any) => {
|
|
55
58
|
removeProduct(product, cart)
|
|
@@ -301,6 +304,24 @@ const OrderSummaryUI = (props: any) => {
|
|
|
301
304
|
</OSTable>
|
|
302
305
|
</View>
|
|
303
306
|
)}
|
|
307
|
+
{placeSpotTypes.includes(orderState?.options?.type) && (
|
|
308
|
+
<OSTable style={{ marginTop: 15 }}>
|
|
309
|
+
<OText size={14} lineHeight={21} weight={'600'}>
|
|
310
|
+
{t('SPOT', 'Spot')}: {cart?.place?.name || t('NO_SELECTED', 'No selected')}
|
|
311
|
+
</OText>
|
|
312
|
+
<TouchableOpacity onPress={() => setOpenPlaceModal(true)}>
|
|
313
|
+
<OText
|
|
314
|
+
size={14}
|
|
315
|
+
lineHeight={21}
|
|
316
|
+
weight={'600'}
|
|
317
|
+
color={theme.colors.primary}
|
|
318
|
+
style={{ textDecorationLine: 'underline' }}
|
|
319
|
+
>
|
|
320
|
+
{t('EDIT', 'Edit')}
|
|
321
|
+
</OText>
|
|
322
|
+
</TouchableOpacity>
|
|
323
|
+
</OSTable>
|
|
324
|
+
)}
|
|
304
325
|
{cart?.status !== 2 && (
|
|
305
326
|
<OSTable>
|
|
306
327
|
<View style={{ width: '100%', marginTop: 20 }}>
|
|
@@ -349,6 +370,18 @@ const OrderSummaryUI = (props: any) => {
|
|
|
349
370
|
products={cart?.products}
|
|
350
371
|
/>
|
|
351
372
|
</OModal>
|
|
373
|
+
<OModal
|
|
374
|
+
open={openPlaceModal}
|
|
375
|
+
title={t('CHOOSE_YOUR_SPOT', 'Choose your spot')}
|
|
376
|
+
onClose={() => setOpenPlaceModal(false)}
|
|
377
|
+
entireModal
|
|
378
|
+
>
|
|
379
|
+
<PlaceSpot
|
|
380
|
+
cart={cart}
|
|
381
|
+
isOpenPlaceSpot={openPlaceModal}
|
|
382
|
+
setOpenPlaceModal={setOpenPlaceModal}
|
|
383
|
+
/>
|
|
384
|
+
</OModal>
|
|
352
385
|
<OAlert
|
|
353
386
|
open={confirm.open}
|
|
354
387
|
title={confirm.title}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react'
|
|
2
|
+
import { View } from 'react-native'
|
|
3
|
+
import { PlaceSpot as PlaceSpotController, useLanguage } from 'ordering-components/native'
|
|
4
|
+
import { PlaceGroupContainer, PlaceSpotContainer } from './styles'
|
|
5
|
+
import { NotFoundSource } from '../NotFoundSource'
|
|
6
|
+
import { OText, ODropDown } from '../shared'
|
|
7
|
+
import { Placeholder, PlaceholderLine } from 'rn-placeholder'
|
|
8
|
+
import { PlaceSpotParams } from '../../types'
|
|
9
|
+
|
|
10
|
+
const PlaceSpotUI = (props: PlaceSpotParams) => {
|
|
11
|
+
const {
|
|
12
|
+
isOpenPlaceSpot,
|
|
13
|
+
cart,
|
|
14
|
+
placesState,
|
|
15
|
+
handleChangePlace,
|
|
16
|
+
getPlacesList,
|
|
17
|
+
setOpenPlaceModal
|
|
18
|
+
} = props
|
|
19
|
+
|
|
20
|
+
const [, t] = useLanguage()
|
|
21
|
+
const [placeGroupSelected, setPlaceGroupSelected] = useState<any>(null)
|
|
22
|
+
|
|
23
|
+
const getPlacesGroups = () => {
|
|
24
|
+
const groups = placesState.placeGroups?.filter((group: any) => group?.enabled && placesState?.places?.find((place: any) => place?.enabled && place?.place_group_id === group?.id))
|
|
25
|
+
return groups.map((group: any) => ({
|
|
26
|
+
value: group,
|
|
27
|
+
content: group?.name,
|
|
28
|
+
showOnSelected: group?.name
|
|
29
|
+
}))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const getPlaces = () => {
|
|
33
|
+
const places = placeGroupSelected && placesState?.places?.filter((place: any) => place?.enabled && place?.place_group_id === placeGroupSelected?.id)
|
|
34
|
+
return places.map((place: any) => ({
|
|
35
|
+
value: place,
|
|
36
|
+
content: place.name,
|
|
37
|
+
showOnSelected: place.name
|
|
38
|
+
}))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const handlerChangePlace = (place: any) => {
|
|
42
|
+
setOpenPlaceModal(false)
|
|
43
|
+
handleChangePlace(place)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
if (!placesState?.loading) {
|
|
49
|
+
const placeGroupOnCart = placesState?.placeGroups.find((group: any) => group?.id === cart?.place?.place_group_id)
|
|
50
|
+
setPlaceGroupSelected(placeGroupOnCart)
|
|
51
|
+
}
|
|
52
|
+
}, [placesState])
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
getPlacesList()
|
|
56
|
+
}, [isOpenPlaceSpot])
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<PlaceSpotContainer>
|
|
60
|
+
{(placesState.error || placesState?.placeGroups?.length === 0) && !placesState?.loading && (
|
|
61
|
+
<NotFoundSource
|
|
62
|
+
content={t('NO_PLACES_THIS_BUSINESS', 'There are not places for this business')}
|
|
63
|
+
/>
|
|
64
|
+
)}
|
|
65
|
+
{placesState?.loading && (
|
|
66
|
+
<Placeholder>
|
|
67
|
+
<PlaceGroupContainer>
|
|
68
|
+
<PlaceholderLine width={100} height={25} />
|
|
69
|
+
<PlaceholderLine height={30} />
|
|
70
|
+
</PlaceGroupContainer>
|
|
71
|
+
<View>
|
|
72
|
+
<PlaceholderLine width={120} height={25} />
|
|
73
|
+
<PlaceholderLine height={30} />
|
|
74
|
+
</View>
|
|
75
|
+
</Placeholder>
|
|
76
|
+
)}
|
|
77
|
+
{!(placesState.error || placesState?.placeGroups?.length === 0) && !placesState?.loading && (
|
|
78
|
+
<>
|
|
79
|
+
<PlaceGroupContainer>
|
|
80
|
+
<OText size={16} mBottom={10}>{t('PLACE_GROUP', 'Place group')}</OText>
|
|
81
|
+
<ODropDown
|
|
82
|
+
placeholder={t('PLACE_GROUP', 'Place group')}
|
|
83
|
+
options={getPlacesGroups()}
|
|
84
|
+
onSelect={(group: any) => setPlaceGroupSelected(group)}
|
|
85
|
+
defaultValue={placeGroupSelected ?? cart?.place}
|
|
86
|
+
isModal
|
|
87
|
+
/>
|
|
88
|
+
</PlaceGroupContainer>
|
|
89
|
+
{placeGroupSelected && (
|
|
90
|
+
<View>
|
|
91
|
+
<OText size={16} mBottom={10}>{t('SELECT_YOUR_SPOT', 'Select your spot')}</OText>
|
|
92
|
+
<ODropDown
|
|
93
|
+
onSelect={(place: any) => handlerChangePlace(place)}
|
|
94
|
+
placeholder={t('SELECT_YOUR_SPOT', 'Select your spot')}
|
|
95
|
+
options={getPlaces()}
|
|
96
|
+
defaultValue={placesState?.places?.find((place : any) => place?.id === cart?.place_id)}
|
|
97
|
+
isModal
|
|
98
|
+
/>
|
|
99
|
+
</View>
|
|
100
|
+
)}
|
|
101
|
+
</>
|
|
102
|
+
)}
|
|
103
|
+
</PlaceSpotContainer>
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const PlaceSpot = (props: PlaceSpotParams) => {
|
|
108
|
+
const placeSpotProps = {
|
|
109
|
+
...props,
|
|
110
|
+
UIComponent: PlaceSpotUI
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return <PlaceSpotController {...placeSpotProps} />
|
|
114
|
+
}
|
|
@@ -872,9 +872,13 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
872
872
|
</ScrollView>
|
|
873
873
|
{!loading && !error && product && (
|
|
874
874
|
<ProductActions ios={Platform?.OS === 'ios'}>
|
|
875
|
-
<
|
|
876
|
-
{
|
|
877
|
-
|
|
875
|
+
<View>
|
|
876
|
+
<OText size={16} lineHeight={24} weight={'600'}>
|
|
877
|
+
{productCart.total ? parsePrice(productCart?.total) : ''}
|
|
878
|
+
</OText>
|
|
879
|
+
{product?.minimum_per_order && productCart?.quantity < product?.minimum_per_order && <OText size={12} color={theme.colors?.red}>{t('MOBILE_MINIMUM_TO_ORDER', 'Min. _number_ ').replace('_number_', product?.minimum_per_order)}</OText>}
|
|
880
|
+
{product?.maximum_per_order && productCart?.quantity > product?.maximum_per_order && <OText size={12} color={theme.colors?.red}>{t('MOBILE_MAXIMUM_TO_ORDER', 'Max. _number_'.replace('_number_', product?.maximum_per_order))}</OText>}
|
|
881
|
+
</View>
|
|
878
882
|
{productCart && !isSoldOut && maxProductQuantity > 0 && (
|
|
879
883
|
<View style={styles.quantityControl}>
|
|
880
884
|
<TouchableOpacity
|
|
@@ -987,14 +991,14 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
987
991
|
? t('UPDATE', 'Update')
|
|
988
992
|
: t('ADD', 'Add')
|
|
989
993
|
}`}
|
|
990
|
-
isDisabled={isSoldOut || maxProductQuantity <= 0}
|
|
994
|
+
isDisabled={isSoldOut || maxProductQuantity <= 0 || productCart?.quantity < product?.minimum_per_order || productCart?.quantity > product?.maximum_per_order}
|
|
991
995
|
textStyle={{
|
|
992
996
|
color: saveErrors || isSoldOut || maxProductQuantity <= 0 ? theme.colors.primary : theme.colors.white,
|
|
993
997
|
fontSize: orderState.loading || editMode ? 10 : 14
|
|
994
998
|
}}
|
|
995
999
|
style={{
|
|
996
|
-
backgroundColor: saveErrors || isSoldOut || maxProductQuantity <= 0 ? theme.colors.lightGray : theme.colors.primary,
|
|
997
|
-
borderColor: saveErrors || isSoldOut || maxProductQuantity <= 0 ? theme.colors.white : theme.colors.primary,
|
|
1000
|
+
backgroundColor: saveErrors || isSoldOut || maxProductQuantity <= 0 || productCart?.quantity < product?.minimum_per_order || productCart?.quantity > product?.maximum_per_order ? theme.colors.lightGray : theme.colors.primary,
|
|
1001
|
+
borderColor: saveErrors || isSoldOut || maxProductQuantity <= 0 || productCart?.quantity < product?.minimum_per_order || productCart?.quantity > product?.maximum_per_order ? theme.colors.white : theme.colors.primary,
|
|
998
1002
|
opacity: saveErrors || isSoldOut || maxProductQuantity <= 0 ? 0.3 : 1,
|
|
999
1003
|
borderRadius: 7.6,
|
|
1000
1004
|
height: 44,
|
|
@@ -546,3 +546,12 @@ export interface BusinessSearchParams {
|
|
|
546
546
|
export interface NoNetworkParams {
|
|
547
547
|
image?: any,
|
|
548
548
|
}
|
|
549
|
+
|
|
550
|
+
export interface PlaceSpotParams {
|
|
551
|
+
isOpenPlaceSpot?: boolean,
|
|
552
|
+
cart?: any ,
|
|
553
|
+
placesState?: any,
|
|
554
|
+
handleChangePlace?: any,
|
|
555
|
+
getPlacesList?: any,
|
|
556
|
+
setOpenPlaceModal?: any
|
|
557
|
+
}
|