ordering-ui-react-native 0.14.89 → 0.14.91-release
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 +6 -3
- package/src/DeliveryApp.tsx +34 -2
- package/src/assets/images/no-network.png +0 -0
- package/src/components/BusinessTypeFilter/index.tsx +9 -2
- package/src/components/BusinessTypeFilter/styles.tsx +1 -1
- package/src/components/BusinessesListing/index.tsx +1 -1
- package/src/components/Cart/index.tsx +1 -1
- package/src/components/Checkout/index.tsx +0 -1
- package/src/components/Home/index.tsx +3 -5
- package/src/components/LanguageSelector/index.tsx +65 -97
- package/src/components/LanguageSelector/styles.tsx +4 -17
- package/src/components/Messages/index.tsx +38 -30
- package/src/components/MomentOption/index.tsx +3 -1
- package/src/components/OrderDetails/index.tsx +26 -5
- package/src/components/PaymentOptions/index.tsx +7 -16
- package/src/components/PaymentOptionsWebView/index.tsx +123 -124
- package/src/components/ProductForm/index.tsx +1 -1
- package/src/components/ProductForm/styles.tsx +1 -0
- package/src/components/StripeElementsForm/index.tsx +27 -48
- package/src/components/UserProfileForm/index.tsx +35 -1
- package/src/components/VerifyPhone/styles.tsx +1 -2
- package/src/config.json +0 -2
- package/src/pages/Checkout.tsx +1 -1
- package/src/providers/AlertProvider.tsx +4 -1
- package/src/theme.json +2 -1
- package/src/types/index.tsx +2 -9
- package/src/utils/index.tsx +2 -1
- package/themes/business/index.tsx +4 -0
- package/themes/business/src/components/Chat/index.tsx +32 -31
- package/themes/business/src/components/NetworkError/index.tsx +61 -0
- package/themes/business/src/components/NetworkError/styles.tsx +11 -0
- package/themes/business/src/components/OrderDetails/Business.tsx +1 -0
- package/themes/business/src/components/OrderDetails/OrderHeaderComponent.tsx +85 -17
- package/themes/business/src/components/OrdersListManager/index.tsx +871 -0
- package/themes/business/src/components/OrdersListManager/styles.tsx +123 -0
- package/themes/business/src/components/OrdersListManager/utils.tsx +216 -0
- package/themes/business/src/components/OrdersOption/index.tsx +18 -68
- package/themes/business/src/components/OrdersOption/styles.tsx +2 -5
- package/themes/business/src/components/PreviousOrders/index.tsx +80 -23
- package/themes/business/src/components/ReviewCustomer/index.tsx +5 -1
- package/themes/business/src/types/index.tsx +4 -0
- package/themes/doordash/src/components/BusinessesListing/index.tsx +1 -1
- package/themes/doordash/src/components/LoginForm/index.tsx +1 -2
- package/themes/instacart/src/components/BusinessesListing/index.tsx +1 -1
- package/themes/kiosk/index.tsx +2 -0
- package/themes/kiosk/src/components/BusinessController/index.tsx +27 -6
- package/themes/kiosk/src/components/BusinessController/styles.tsx +1 -1
- package/themes/kiosk/src/components/BusinessProductsListing/index.tsx +51 -24
- package/themes/kiosk/src/components/Cart/index.tsx +1 -1
- package/themes/kiosk/src/components/CartBottomSheet/index.tsx +1 -1
- package/themes/kiosk/src/components/CartBottomSheet/styles.tsx +1 -1
- package/themes/kiosk/src/components/CartContent/index.tsx +13 -3
- package/themes/kiosk/src/components/CartItem/index.tsx +20 -8
- package/themes/kiosk/src/components/CategoriesMenu/index.tsx +7 -5
- package/themes/kiosk/src/components/CustomerName/index.tsx +89 -88
- package/themes/kiosk/src/components/Intro/index.tsx +13 -13
- package/themes/kiosk/src/components/LanguageSelector/index.tsx +12 -8
- package/themes/kiosk/src/components/NavBar/index.tsx +14 -14
- package/themes/kiosk/src/components/NetworkError/index.tsx +60 -0
- package/themes/kiosk/src/components/NetworkError/styles.tsx +11 -0
- package/themes/kiosk/src/components/OptionCard/index.tsx +1 -1
- package/themes/kiosk/src/components/OrderDetails/index.tsx +2 -2
- package/themes/kiosk/src/components/OrderSummary/index.tsx +1 -1
- package/themes/kiosk/src/components/OrderTypeCardSelector/index.tsx +10 -12
- package/themes/kiosk/src/components/ProductForm/index.tsx +172 -124
- package/themes/kiosk/src/components/ProductForm/styles.tsx +1 -1
- package/themes/kiosk/src/components/ProductOption/index.tsx +1 -0
- package/themes/kiosk/src/components/ProductOption/styles.tsx +1 -0
- package/themes/kiosk/src/components/UpsellingProducts/index.tsx +48 -34
- package/themes/kiosk/src/components/shared/OButton.tsx +5 -18
- package/themes/kiosk/src/components/shared/OCard.tsx +112 -78
- package/themes/kiosk/src/types/index.d.ts +4 -0
- package/themes/original/index.tsx +36 -6
- package/themes/original/src/components/AddressForm/index.tsx +15 -10
- package/themes/original/src/components/AddressList/index.tsx +27 -1
- package/themes/original/src/components/AnalyticsSegment/index.tsx +127 -0
- package/themes/original/src/components/BusinessBasicInformation/index.tsx +11 -7
- package/themes/original/src/components/BusinessController/index.tsx +5 -4
- package/themes/original/src/components/BusinessMenuList/index.tsx +4 -2
- package/themes/original/src/components/BusinessPreorder/index.tsx +142 -121
- package/themes/original/src/components/BusinessProductsCategories/index.tsx +1 -1
- package/themes/original/src/components/BusinessProductsList/index.tsx +50 -6
- package/themes/original/src/components/BusinessProductsListing/index.tsx +13 -10
- package/themes/original/src/components/BusinessReviews/index.tsx +4 -3
- package/themes/original/src/components/BusinessesListing/index.tsx +23 -22
- package/themes/original/src/components/Cart/index.tsx +43 -10
- package/themes/original/src/components/CartContent/index.tsx +2 -2
- package/themes/original/src/components/Checkout/index.tsx +54 -30
- package/themes/original/src/components/Checkout/styles.tsx +7 -0
- package/themes/original/src/components/CouponControl/index.tsx +1 -0
- package/themes/original/src/components/DriverTips/index.tsx +1 -1
- package/themes/original/src/components/ForgotPasswordForm/index.tsx +8 -12
- package/themes/original/src/components/HighestRatedBusinesses/index.tsx +9 -2
- package/themes/original/src/components/LoginForm/index.tsx +83 -68
- package/themes/original/src/components/Messages/index.tsx +24 -21
- package/themes/original/src/components/Messages/styles.tsx +1 -3
- package/themes/original/src/components/MomentOption/index.tsx +127 -152
- package/themes/original/src/components/MomentOption/styles.tsx +42 -18
- package/themes/original/src/components/NetworkError/index.tsx +61 -0
- package/themes/original/src/components/NetworkError/styles.tsx +11 -0
- package/themes/original/src/components/OrderDetails/index.tsx +103 -124
- package/themes/original/src/components/OrderDetails/styles.tsx +3 -1
- package/themes/original/src/components/OrderProgress/index.tsx +2 -3
- package/themes/original/src/components/OrderSummary/index.tsx +35 -2
- package/themes/original/src/components/OrdersOption/index.tsx +16 -40
- package/themes/original/src/components/OrdersOption/styles.tsx +0 -5
- package/themes/original/src/components/PaymentOptionWallet/index.tsx +1 -1
- package/themes/original/src/components/PaymentOptions/index.tsx +21 -24
- package/themes/original/src/components/PhoneInputNumber/index.tsx +15 -8
- 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/PreviousOrders/index.tsx +4 -0
- package/themes/original/src/components/ProductForm/index.tsx +154 -105
- package/themes/original/src/components/ProductForm/styles.tsx +5 -3
- package/themes/original/src/components/ProductOptionSubOption/index.tsx +6 -1
- package/themes/original/src/components/ReviewDriver/index.tsx +2 -1
- package/themes/original/src/components/ReviewOrder/index.tsx +2 -17
- package/themes/original/src/components/SignupForm/index.tsx +173 -154
- package/themes/original/src/components/SingleProductCard/index.tsx +6 -13
- package/themes/original/src/components/SingleProductCard/styles.tsx +1 -1
- package/themes/original/src/components/SingleProductReview/index.tsx +4 -0
- package/themes/original/src/components/StripeElementsForm/index.tsx +55 -72
- package/themes/original/src/components/UpsellingProducts/index.tsx +6 -6
- package/themes/original/src/components/UserDetails/index.tsx +4 -95
- package/themes/original/src/components/UserFormDetails/index.tsx +2 -14
- package/themes/original/src/components/UserProfile/index.tsx +16 -9
- package/themes/original/src/components/UserProfileForm/index.tsx +16 -8
- package/themes/original/src/components/VerifyPhone/index.tsx +10 -7
- package/themes/original/src/components/VerifyPhone/styles.tsx +2 -1
- package/themes/original/src/components/shared/HeaderTitle.tsx +20 -0
- package/themes/original/src/components/shared/index.tsx +2 -0
- package/themes/original/src/types/index.tsx +18 -8
- package/themes/single-business/src/components/OrderTypeSelector/index.tsx +5 -5
- package/themes/uber-eats/src/components/BusinessesListing/index.tsx +1 -1
- package/src/components/StripeMethodForm/index.tsx +0 -163
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
PaymentOptions as PaymentOptionsController,
|
|
11
11
|
useLanguage,
|
|
12
|
+
ToastType,
|
|
13
|
+
useToast,
|
|
12
14
|
} from 'ordering-components/native';
|
|
13
15
|
import { useTheme } from 'styled-components/native';
|
|
14
16
|
import { PaymentOptionCash } from '../PaymentOptionCash';
|
|
@@ -30,8 +32,6 @@ import {
|
|
|
30
32
|
import { getIconCard, flatArray } from '../../utils';
|
|
31
33
|
|
|
32
34
|
const stripeOptions: any = ['stripe_direct', 'stripe', 'stripe_connect']
|
|
33
|
-
const methodsPay = ['google_pay', 'apple_pay']
|
|
34
|
-
const stripeDirectMethods = ['stripe_direct', ...methodsPay]
|
|
35
35
|
// const stripeRedirectOptions = [
|
|
36
36
|
// { name: 'Bancontact', value: 'bancontact' },
|
|
37
37
|
// { name: 'Alipay', value: 'alipay' },
|
|
@@ -54,12 +54,11 @@ const PaymentOptionsUI = (props: any) => {
|
|
|
54
54
|
handlePaymethodClick,
|
|
55
55
|
handlePaymethodDataChange,
|
|
56
56
|
isOpenMethod,
|
|
57
|
-
handlePaymentMethodClickCustom
|
|
58
|
-
handlePlaceOrder
|
|
57
|
+
handlePaymentMethodClickCustom
|
|
59
58
|
} = props
|
|
60
59
|
|
|
61
60
|
const theme = useTheme();
|
|
62
|
-
|
|
61
|
+
const [, { showToast }] = useToast();
|
|
63
62
|
|
|
64
63
|
const getPayIcon = (method: string) => {
|
|
65
64
|
switch (method) {
|
|
@@ -95,11 +94,18 @@ const PaymentOptionsUI = (props: any) => {
|
|
|
95
94
|
// ]
|
|
96
95
|
|
|
97
96
|
const handlePaymentMethodClick = (paymethod: any) => {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
if (cart?.balance > 0) {
|
|
98
|
+
const isPopupMethod = ['stripe', 'stripe_direct', 'stripe_connect', 'stripe_redirect', 'paypal'].includes(paymethod?.gateway)
|
|
99
|
+
if (webViewPaymentGateway.includes(paymethod?.gateway)) {
|
|
100
|
+
handlePaymentMethodClickCustom(paymethod)
|
|
101
|
+
}
|
|
102
|
+
handlePaymethodClick(paymethod, isPopupMethod)
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
showToast(
|
|
106
|
+
ToastType.Error,
|
|
107
|
+
t('CART_BALANCE_ZERO', 'Sorry, the amount to pay is equal to zero and it is not necessary to select a payment method'))
|
|
108
|
+
;
|
|
103
109
|
}
|
|
104
110
|
|
|
105
111
|
useEffect(() => {
|
|
@@ -120,12 +126,6 @@ const PaymentOptionsUI = (props: any) => {
|
|
|
120
126
|
}
|
|
121
127
|
}, [props.paySelected])
|
|
122
128
|
|
|
123
|
-
useEffect(() => {
|
|
124
|
-
if (methodsPay.includes(paymethodSelected?.gateway) && paymethodData?.id && paymethodSelected?.data?.card) {
|
|
125
|
-
handlePlaceOrder()
|
|
126
|
-
}
|
|
127
|
-
}, [paymethodData, paymethodSelected])
|
|
128
|
-
|
|
129
129
|
const renderPaymethods = ({ item }: any) => {
|
|
130
130
|
return (
|
|
131
131
|
<TouchableOpacity
|
|
@@ -154,7 +154,7 @@ const PaymentOptionsUI = (props: any) => {
|
|
|
154
154
|
)
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
const excludeIds: any = [32]; //exclude paypal & connect & redirect
|
|
157
|
+
const excludeIds: any = [32, 66]; //exclude paypal & connect & redirect
|
|
158
158
|
|
|
159
159
|
return (
|
|
160
160
|
<PMContainer>
|
|
@@ -287,11 +287,11 @@ const PaymentOptionsUI = (props: any) => {
|
|
|
287
287
|
</KeyboardAvoidingView>
|
|
288
288
|
</OModal>
|
|
289
289
|
|
|
290
|
-
{/* Stripe direct
|
|
290
|
+
{/* Stripe direct */}
|
|
291
291
|
<OModal
|
|
292
292
|
entireModal
|
|
293
293
|
title={t('ADD_CREDIT_OR_DEBIT_CARD', 'Add credit or debit card')}
|
|
294
|
-
open={
|
|
294
|
+
open={isOpenMethod?.paymethod?.gateway === 'stripe_direct' && !paymethodData?.id}
|
|
295
295
|
onClose={() => handlePaymethodClick(null)}
|
|
296
296
|
>
|
|
297
297
|
<KeyboardAvoidingView
|
|
@@ -300,13 +300,10 @@ const PaymentOptionsUI = (props: any) => {
|
|
|
300
300
|
enabled={Platform.OS === 'ios' ? true : false}
|
|
301
301
|
>
|
|
302
302
|
<StripeElementsForm
|
|
303
|
-
cart={cart}
|
|
304
|
-
paymethod={isOpenMethod?.paymethod?.gateway}
|
|
305
|
-
methodsPay={methodsPay}
|
|
306
303
|
businessId={props.businessId}
|
|
307
|
-
publicKey={isOpenMethod?.paymethod?.credentials?.publishable
|
|
304
|
+
publicKey={isOpenMethod?.paymethod?.credentials?.publishable}
|
|
308
305
|
handleSource={handlePaymethodDataChange}
|
|
309
|
-
onCancel={() => handlePaymethodClick(
|
|
306
|
+
onCancel={() => handlePaymethodClick(false)}
|
|
310
307
|
/>
|
|
311
308
|
</KeyboardAvoidingView>
|
|
312
309
|
</OModal>
|
|
@@ -22,18 +22,23 @@ export const PhoneInputNumber = (props: PhoneInputParams) => {
|
|
|
22
22
|
textStyle,
|
|
23
23
|
flagStyle,
|
|
24
24
|
noDropIcon,
|
|
25
|
-
isDisabled
|
|
25
|
+
isDisabled,
|
|
26
|
+
isStartValidation
|
|
26
27
|
} = props
|
|
27
28
|
|
|
28
29
|
const theme = useTheme();
|
|
29
30
|
|
|
31
|
+
const [, t] = useLanguage()
|
|
32
|
+
const [{ configs }] = useConfig()
|
|
33
|
+
const phoneInput = useRef<PhoneInput>(null);
|
|
34
|
+
const [userphoneNumber, setUserphoneNumber] = useState('');
|
|
30
35
|
|
|
31
36
|
const style = StyleSheet.create({
|
|
32
37
|
input: {
|
|
33
38
|
backgroundColor: theme.colors.white,
|
|
34
39
|
borderRadius: 7.6,
|
|
35
40
|
borderWidth: 1,
|
|
36
|
-
borderColor: theme.colors.border,
|
|
41
|
+
borderColor: (isStartValidation && userphoneNumber === '') ? theme.colors.danger5 : theme.colors.border,
|
|
37
42
|
paddingBottom: 0,
|
|
38
43
|
paddingTop: 0,
|
|
39
44
|
flexGrow: 1,
|
|
@@ -48,12 +53,6 @@ export const PhoneInputNumber = (props: PhoneInputParams) => {
|
|
|
48
53
|
}
|
|
49
54
|
})
|
|
50
55
|
|
|
51
|
-
|
|
52
|
-
const [, t] = useLanguage()
|
|
53
|
-
const [{ configs }] = useConfig()
|
|
54
|
-
const phoneInput = useRef<PhoneInput>(null);
|
|
55
|
-
const [userphoneNumber, setUserphoneNumber] = useState('');
|
|
56
|
-
|
|
57
56
|
const handleChangeNumber = (number: any) => {
|
|
58
57
|
setUserphoneNumber(number)
|
|
59
58
|
}
|
|
@@ -97,6 +96,14 @@ export const PhoneInputNumber = (props: PhoneInputParams) => {
|
|
|
97
96
|
|
|
98
97
|
return (
|
|
99
98
|
<Wrapper onPress={() => forwardRef?.current?.focus?.()}>
|
|
99
|
+
{(isStartValidation && userphoneNumber === '') && (
|
|
100
|
+
<OText
|
|
101
|
+
size={14}
|
|
102
|
+
color={theme.colors.danger5}
|
|
103
|
+
>
|
|
104
|
+
{t('VALIDATION_ERROR_MOBILE_PHONE_REQUIRED', 'The field Mobile phone is required').replace('_attribute_', t('CELLPHONE', 'Cellphone'))}*
|
|
105
|
+
</OText>
|
|
106
|
+
)}
|
|
100
107
|
<PhoneInput
|
|
101
108
|
ref={phoneInput}
|
|
102
109
|
disabled={isDisabled}
|
|
@@ -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
|
+
}
|
|
@@ -86,6 +86,10 @@ export const PreviousOrders = (props: PreviousOrdersParams) => {
|
|
|
86
86
|
id: order?.id,
|
|
87
87
|
business_id: order?.business_id,
|
|
88
88
|
logo: order.business?.logo,
|
|
89
|
+
driver: order?.driver,
|
|
90
|
+
products: order?.products,
|
|
91
|
+
review: order?.review,
|
|
92
|
+
user_review: order?.user_review
|
|
89
93
|
},
|
|
90
94
|
});
|
|
91
95
|
};
|
|
@@ -37,7 +37,8 @@ import {
|
|
|
37
37
|
ExtraOptionWrap,
|
|
38
38
|
WeightUnitSwitch,
|
|
39
39
|
WeightUnitItem,
|
|
40
|
-
TopActions
|
|
40
|
+
TopActions,
|
|
41
|
+
ProductSummary
|
|
41
42
|
} from './styles';
|
|
42
43
|
import { OButton, OIcon, OInput, OText } from '../shared';
|
|
43
44
|
import { ScrollView } from 'react-native-gesture-handler';
|
|
@@ -45,7 +46,6 @@ import { ProductOptionSubOption } from '../ProductOptionSubOption';
|
|
|
45
46
|
import { NotFoundSource } from '../NotFoundSource';
|
|
46
47
|
import { Placeholder, PlaceholderLine, Fade } from 'rn-placeholder';
|
|
47
48
|
import { useState } from 'react';
|
|
48
|
-
|
|
49
49
|
const windowHeight = Dimensions.get('window').height;
|
|
50
50
|
const windowWidth = Dimensions.get('window').width;
|
|
51
51
|
|
|
@@ -170,8 +170,11 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
170
170
|
pieces: true
|
|
171
171
|
})
|
|
172
172
|
const [pricePerWeightUnit, setPricePerWeightUnit] = useState<any>(null)
|
|
173
|
-
|
|
173
|
+
const scrollViewRef = useRef<any>(null);
|
|
174
174
|
const swiperRef: any = useRef(null)
|
|
175
|
+
const [optionLayout, setOptionLayout] = useState<any>({})
|
|
176
|
+
const [headerRefHeight, setHeaderRefHeight] = useState(0)
|
|
177
|
+
const [summaryRefHeight, setSummaryRefHeight] = useState(0)
|
|
175
178
|
|
|
176
179
|
const isError = (id: number) => {
|
|
177
180
|
let bgColor = theme.colors.white;
|
|
@@ -253,6 +256,28 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
253
256
|
handleChangeProductCartQuantity(quantity)
|
|
254
257
|
}
|
|
255
258
|
|
|
259
|
+
const scrollDown = (id: any) => {
|
|
260
|
+
const isErrors = Object.values(errors).length > 0
|
|
261
|
+
if (!isErrors) {
|
|
262
|
+
return
|
|
263
|
+
}
|
|
264
|
+
const targetOptionId = Object.getOwnPropertyNames(errors).filter(item => !item.includes(id))[0]
|
|
265
|
+
const targetY = optionLayout[targetOptionId]?.y
|
|
266
|
+
if (targetY) {
|
|
267
|
+
scrollViewRef.current.scrollTo({
|
|
268
|
+
y: targetY + headerRefHeight + summaryRefHeight,
|
|
269
|
+
animated: true
|
|
270
|
+
})
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const handleOnLayout = (event: any, optionId: any) => {
|
|
275
|
+
const _optionLayout = { ...optionLayout }
|
|
276
|
+
const optionKey = 'id:' + optionId
|
|
277
|
+
_optionLayout[optionKey] = { y: event.nativeEvent.layout?.y }
|
|
278
|
+
setOptionLayout(_optionLayout)
|
|
279
|
+
}
|
|
280
|
+
|
|
256
281
|
useEffect(() => {
|
|
257
282
|
const imageList: any = []
|
|
258
283
|
const videoList: any = []
|
|
@@ -264,8 +289,24 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
264
289
|
}
|
|
265
290
|
if (img?.video) {
|
|
266
291
|
const keys = img?.video.split('/')
|
|
267
|
-
|
|
268
|
-
|
|
292
|
+
let _videoId = keys[keys.length - 1]
|
|
293
|
+
|
|
294
|
+
if (_videoId.includes('watch')) {
|
|
295
|
+
const __url = _videoId.split('=')[1]
|
|
296
|
+
_videoId = __url
|
|
297
|
+
} else if (_videoId.includes('?')) {
|
|
298
|
+
const __url = _videoId.split('?')[0]
|
|
299
|
+
_videoId = __url
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (_videoId.search(/&/i) >= 0) {
|
|
303
|
+
_videoId = _videoId.split('&')[0]
|
|
304
|
+
} else if (_videoId.search(/\?/i) >= 0) {
|
|
305
|
+
_videoId = _videoId.split('?')[0]
|
|
306
|
+
}
|
|
307
|
+
if ((_videoId.length === 11)) {
|
|
308
|
+
videoList.push(_videoId)
|
|
309
|
+
}
|
|
269
310
|
}
|
|
270
311
|
}
|
|
271
312
|
}
|
|
@@ -304,9 +345,9 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
304
345
|
</OText>
|
|
305
346
|
</TouchableOpacity>
|
|
306
347
|
)}
|
|
307
|
-
{options.map(({ id, name, respect_to }: any) => (
|
|
348
|
+
{options.map(({ id, name, respect_to, suboptions }: any) => (
|
|
308
349
|
<React.Fragment key={`cont_key_${id}`}>
|
|
309
|
-
{respect_to == null && (
|
|
350
|
+
{respect_to == null && suboptions?.length > 0 && (
|
|
310
351
|
<TouchableOpacity
|
|
311
352
|
key={`eopt_key_${id}`}
|
|
312
353
|
onPress={() => setSelectedOpt(id)}
|
|
@@ -343,10 +384,10 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
343
384
|
<OIcon src={theme.images.general.arrow_left} width={15} />
|
|
344
385
|
</TopActions>
|
|
345
386
|
</TopHeader>
|
|
346
|
-
<ScrollView>
|
|
387
|
+
<ScrollView ref={scrollViewRef}>
|
|
347
388
|
{!error && (
|
|
348
389
|
<View style={{ paddingBottom: 80 }}>
|
|
349
|
-
<WrapHeader>
|
|
390
|
+
<WrapHeader onLayout={(event: any) => setHeaderRefHeight(event.nativeEvent.layout?.height)}>
|
|
350
391
|
{loading && !product ? (
|
|
351
392
|
<View style={styles.productHeaderSkeleton}>
|
|
352
393
|
<Placeholder Animation={Fade}>
|
|
@@ -396,7 +437,7 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
396
437
|
<FastImage
|
|
397
438
|
style={{ height: '100%', opacity: isSoldOut ? 0.5 : 1 }}
|
|
398
439
|
source={{
|
|
399
|
-
uri: optimizeImage(img, '
|
|
440
|
+
uri: optimizeImage(img, 'h_1024,c_limit'),
|
|
400
441
|
priority: FastImage.priority.normal,
|
|
401
442
|
}}
|
|
402
443
|
/>
|
|
@@ -470,96 +511,98 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
470
511
|
)}
|
|
471
512
|
</WrapHeader>
|
|
472
513
|
<WrapContent>
|
|
473
|
-
<
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
<
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
<
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
{!!product?.calories && (
|
|
496
|
-
<OText size={16} style={{ color: '#808080' }}>{product?.calories} cal
|
|
514
|
+
<ProductSummary onLayout={(event: any) => setSummaryRefHeight(event.nativeEvent.layout?.height)}>
|
|
515
|
+
<ProductTitle>
|
|
516
|
+
{loading && !product ? (
|
|
517
|
+
<Placeholder Animation={Fade}>
|
|
518
|
+
<View
|
|
519
|
+
style={{
|
|
520
|
+
flexDirection: 'row',
|
|
521
|
+
justifyContent: 'space-between',
|
|
522
|
+
}}>
|
|
523
|
+
<PlaceholderLine width={40} height={20} />
|
|
524
|
+
<PlaceholderLine width={30} height={20} />
|
|
525
|
+
</View>
|
|
526
|
+
</Placeholder>
|
|
527
|
+
) : (
|
|
528
|
+
<>
|
|
529
|
+
<View style={{ flexDirection: 'row' }}>
|
|
530
|
+
<OText
|
|
531
|
+
size={20}
|
|
532
|
+
lineHeight={30}
|
|
533
|
+
weight={'600'}
|
|
534
|
+
style={{ flex: 1, marginBottom: 10 }}>
|
|
535
|
+
{product?.name || productCart.name}
|
|
497
536
|
</OText>
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
<OText size={14} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={'#909BA9'} mBottom={7}>
|
|
502
|
-
{
|
|
503
|
-
((product?.sku && product?.sku !== '-1' && product?.sku !== '1') || (productCart?.sku && productCart?.sku !== '-1' && productCart?.sku !== '1'))
|
|
504
|
-
&& <>{t('SKU', 'Sku')}{' '}{product?.sku || productCart?.sku}</>
|
|
505
|
-
}
|
|
506
|
-
{product?.sku && product?.sku !== '-1' && product?.sku !== '1' && product?.estimated_person && (
|
|
507
|
-
<> · </>
|
|
508
|
-
)}
|
|
509
|
-
{product?.estimated_person
|
|
510
|
-
&& <>{product?.estimated_person}{' '}{t('ESTIMATED_PERSONS', 'persons')}</>
|
|
511
|
-
}
|
|
512
|
-
</OText>
|
|
513
|
-
)}
|
|
514
|
-
{isHaveWeight ? (
|
|
515
|
-
<OText size={16} lineHeight={24} color={theme.colors.primary}>{parsePrice(pricePerWeightUnit)} / {product?.weight_unit}</OText>
|
|
516
|
-
) : (
|
|
517
|
-
<View style={{ flexDirection: 'row', marginBottom: 10 }}>
|
|
518
|
-
<OText size={16} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={theme.colors.primary}>{productCart.price ? parsePrice(productCart.price) : ''}</OText>
|
|
519
|
-
{product?.offer_price !== null && product?.in_offer && (
|
|
520
|
-
<OText style={{
|
|
521
|
-
fontSize: 14,
|
|
522
|
-
color: '#808080',
|
|
523
|
-
textDecorationLine: 'line-through',
|
|
524
|
-
marginLeft: 7,
|
|
525
|
-
marginRight: 7
|
|
526
|
-
}}>{product?.offer_price ? parsePrice(product?.offer_price) : ''}</OText>
|
|
537
|
+
{!!product?.calories && (
|
|
538
|
+
<OText size={16} style={{ color: '#808080' }}>{product?.calories} cal
|
|
539
|
+
</OText>
|
|
527
540
|
)}
|
|
528
541
|
</View>
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
542
|
+
{((!!product?.sku && product?.sku !== '-1' && product?.sku !== '1') || (!!product?.estimated_person)) && (
|
|
543
|
+
<OText size={14} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={'#909BA9'} mBottom={7}>
|
|
544
|
+
{
|
|
545
|
+
((product?.sku && product?.sku !== '-1' && product?.sku !== '1') || (productCart?.sku && productCart?.sku !== '-1' && productCart?.sku !== '1'))
|
|
546
|
+
&& <>{t('SKU', 'Sku')}{' '}{product?.sku || productCart?.sku}</>
|
|
547
|
+
}
|
|
548
|
+
{product?.sku && product?.sku !== '-1' && product?.sku !== '1' && product?.estimated_person && (
|
|
549
|
+
<> · </>
|
|
550
|
+
)}
|
|
551
|
+
{product?.estimated_person
|
|
552
|
+
&& <>{product?.estimated_person}{' '}{t('ESTIMATED_PERSONS', 'persons')}</>
|
|
553
|
+
}
|
|
554
|
+
</OText>
|
|
555
|
+
)}
|
|
556
|
+
{isHaveWeight ? (
|
|
557
|
+
<OText size={16} lineHeight={24} color={theme.colors.primary}>{parsePrice(pricePerWeightUnit)} / {product?.weight_unit}</OText>
|
|
558
|
+
) : (
|
|
559
|
+
<View style={{ flexDirection: 'row', marginBottom: 10 }}>
|
|
560
|
+
<OText size={16} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={theme.colors.primary}>{productCart.price ? parsePrice(productCart.price) : ''}</OText>
|
|
561
|
+
{product?.offer_price !== null && product?.in_offer && (
|
|
562
|
+
<OText style={{
|
|
563
|
+
fontSize: 14,
|
|
564
|
+
color: '#808080',
|
|
565
|
+
textDecorationLine: 'line-through',
|
|
566
|
+
marginLeft: 7,
|
|
567
|
+
marginRight: 7
|
|
568
|
+
}}>{product?.offer_price ? parsePrice(product?.offer_price) : ''}</OText>
|
|
569
|
+
)}
|
|
570
|
+
</View>
|
|
571
|
+
)}
|
|
572
|
+
</>
|
|
573
|
+
)}
|
|
574
|
+
</ProductTitle>
|
|
575
|
+
<ProductDescription>
|
|
576
|
+
<OText color={theme.colors.textSecondary} size={12} lineHeight={18}>
|
|
577
|
+
{product?.description || productCart?.description}
|
|
578
|
+
</OText>
|
|
579
|
+
</ProductDescription>
|
|
580
|
+
<ScrollView
|
|
581
|
+
horizontal
|
|
582
|
+
showsHorizontalScrollIndicator={false}
|
|
583
|
+
contentContainerStyle={{ paddingBottom: 30 }}
|
|
584
|
+
>
|
|
585
|
+
{product?.tags?.map((tag: any) => (
|
|
586
|
+
<View
|
|
587
|
+
key={tag.id}
|
|
588
|
+
style={styles.productTagWrapper}
|
|
589
|
+
>
|
|
590
|
+
{!!tag?.image ? (
|
|
591
|
+
<OIcon
|
|
592
|
+
url={optimizeImage(tag?.image, 'h_40,c_limit')}
|
|
593
|
+
style={styles.productTagImageStyle}
|
|
594
|
+
/>
|
|
595
|
+
) : (
|
|
596
|
+
<OIcon
|
|
597
|
+
src={theme.images?.dummies?.product}
|
|
598
|
+
style={styles.productTagImageStyle}
|
|
599
|
+
/>
|
|
600
|
+
)}
|
|
601
|
+
<OText color={theme.colors.textSecondary} size={12} style={styles.productTagNameStyle}>{tag.name}</OText>
|
|
602
|
+
</View>
|
|
603
|
+
))}
|
|
604
|
+
</ScrollView>
|
|
605
|
+
</ProductSummary>
|
|
563
606
|
{loading && !product ? (
|
|
564
607
|
<>
|
|
565
608
|
{[...Array(2)].map((item, i) => (
|
|
@@ -658,7 +701,7 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
658
701
|
return (
|
|
659
702
|
<React.Fragment key={`popt_${option.id}`}>
|
|
660
703
|
{showOption(option) && (
|
|
661
|
-
<View style={styles.optionContainer}>
|
|
704
|
+
<View style={styles.optionContainer} onLayout={(event: any) => handleOnLayout(event, option?.id)}>
|
|
662
705
|
<ProductOption
|
|
663
706
|
option={option}
|
|
664
707
|
currentState={currentState}
|
|
@@ -695,6 +738,8 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
695
738
|
isSoldOut ||
|
|
696
739
|
maxProductQuantity <= 0
|
|
697
740
|
}
|
|
741
|
+
scrollDown={scrollDown}
|
|
742
|
+
error={errors[`id:${option.id}`]}
|
|
698
743
|
/>
|
|
699
744
|
);
|
|
700
745
|
},
|
|
@@ -834,9 +879,13 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
834
879
|
</ScrollView>
|
|
835
880
|
{!loading && !error && product && (
|
|
836
881
|
<ProductActions ios={Platform?.OS === 'ios'}>
|
|
837
|
-
<
|
|
838
|
-
{
|
|
839
|
-
|
|
882
|
+
<View>
|
|
883
|
+
<OText size={16} lineHeight={24} weight={'600'}>
|
|
884
|
+
{productCart.total ? parsePrice(productCart?.total) : ''}
|
|
885
|
+
</OText>
|
|
886
|
+
{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>}
|
|
887
|
+
{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>}
|
|
888
|
+
</View>
|
|
840
889
|
{productCart && !isSoldOut && maxProductQuantity > 0 && (
|
|
841
890
|
<View style={styles.quantityControl}>
|
|
842
891
|
<TouchableOpacity
|
|
@@ -855,7 +904,7 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
855
904
|
{qtyBy?.pieces && (
|
|
856
905
|
<TextInput
|
|
857
906
|
keyboardType='numeric'
|
|
858
|
-
value={`${productCart?.quantity > 0 ? productCart?.quantity: ''}`}
|
|
907
|
+
value={`${productCart?.quantity > 0 ? productCart?.quantity : ''}`}
|
|
859
908
|
onChangeText={(val: any) => onChangeProductCartQuantity(parseInt(val))}
|
|
860
909
|
editable={!orderState.loading}
|
|
861
910
|
style={{
|
|
@@ -949,14 +998,14 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
949
998
|
? t('UPDATE', 'Update')
|
|
950
999
|
: t('ADD', 'Add')
|
|
951
1000
|
}`}
|
|
952
|
-
isDisabled={isSoldOut || maxProductQuantity <= 0}
|
|
1001
|
+
isDisabled={isSoldOut || maxProductQuantity <= 0 || (product?.minimum_per_order && (productCart?.quantity < product?.minimum_per_order)) || (product?.maximum_per_order && (productCart?.quantity > product?.maximum_per_order))}
|
|
953
1002
|
textStyle={{
|
|
954
1003
|
color: saveErrors || isSoldOut || maxProductQuantity <= 0 ? theme.colors.primary : theme.colors.white,
|
|
955
1004
|
fontSize: orderState.loading || editMode ? 10 : 14
|
|
956
1005
|
}}
|
|
957
1006
|
style={{
|
|
958
|
-
backgroundColor: saveErrors || isSoldOut || maxProductQuantity <= 0 ? theme.colors.lightGray : theme.colors.primary,
|
|
959
|
-
borderColor: saveErrors || isSoldOut || maxProductQuantity <= 0 ? theme.colors.white : theme.colors.primary,
|
|
1007
|
+
backgroundColor: saveErrors || isSoldOut || maxProductQuantity <= 0 || (product?.minimum_per_order && (productCart?.quantity < product?.minimum_per_order)) || (product?.maximum_per_order && (productCart?.quantity > product?.maximum_per_order)) ? theme.colors.lightGray : theme.colors.primary,
|
|
1008
|
+
borderColor: saveErrors || isSoldOut || maxProductQuantity <= 0 || (product?.minimum_per_order && (productCart?.quantity < product?.minimum_per_order)) || (product?.maximum_per_order && (productCart?.quantity > product?.maximum_per_order)) ? theme.colors.white : theme.colors.primary,
|
|
960
1009
|
opacity: saveErrors || isSoldOut || maxProductQuantity <= 0 ? 0.3 : 1,
|
|
961
1010
|
borderRadius: 7.6,
|
|
962
1011
|
height: 44,
|