ordering-ui-react-native 0.17.2-release → 0.17.3-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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ordering-ui-react-native",
3
- "version": "0.17.2-release",
3
+ "version": "0.17.3-release",
4
4
  "description": "Reusable components made in react native",
5
5
  "main": "src/index.tsx",
6
6
  "author": "ordering.inc",
@@ -226,6 +226,7 @@ const CartUI = (props: any) => {
226
226
  key={`${product.code}_${i}`}
227
227
  isCartPending={isCartPending}
228
228
  isCartProduct
229
+ isDisabledEdit={!cart?.business_id}
229
230
  product={product}
230
231
  changeQuantity={changeQuantity}
231
232
  getProductMax={getProductMax}
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useEffect } from 'react';
2
- import { View, StyleSheet, TouchableOpacity, Platform, I18nManager, Vibration, ScrollView } from 'react-native';
2
+ import { View, StyleSheet, TouchableOpacity, Platform, I18nManager, ScrollView } from 'react-native';
3
3
  import { initStripe, useConfirmPayment } from '@stripe/stripe-react-native';
4
4
  import Picker from 'react-native-country-picker-modal';
5
5
  import MaterialIcons from 'react-native-vector-icons/MaterialIcons'
@@ -52,7 +52,7 @@ import { FloatingButton } from '../FloatingButton';
52
52
  import { Container } from '../../layouts/Container';
53
53
  import NavBar from '../NavBar';
54
54
  import { OrderSummary } from '../OrderSummary';
55
- import { getTypesText } from '../../utils';
55
+ import { getTypesText, vibrateApp } from '../../utils';
56
56
  import { CartStoresListing } from '../CartStoresListing';
57
57
  import { PaymentOptionsWebView } from '../../../../../src/components/PaymentOptionsWebView';
58
58
 
@@ -152,7 +152,7 @@ const CheckoutUI = (props: any) => {
152
152
  const [isOpen, setIsOpen] = useState(false)
153
153
  const [requiredFields, setRequiredFields] = useState<any>([])
154
154
  const [openModal, setOpenModal] = useState({ login: false, signup: false })
155
- const [allowedGuest, setAllowedGuest] = useState(false)
155
+ const [allowedGuest, setAllowedGuest] = useState(false)
156
156
 
157
157
  const placeSpotTypes = [3, 4, 5]
158
158
  const placeSpotsEnabled = placeSpotTypes.includes(options?.type)
@@ -177,12 +177,16 @@ const CheckoutUI = (props: any) => {
177
177
  return acc = acc + item?.summary?.tax
178
178
  return acc = acc
179
179
  }, cart?.subtotal)
180
+
181
+ const validateCommentsCartField = validationFields?.fields?.checkout?.comments?.enabled && validationFields?.fields?.checkout?.comments?.required && (cart?.comment === null || cart?.comment?.trim().length === 0)
182
+
180
183
  const isDisabledButtonPlace = loading || !cart?.valid || (!paymethodSelected && cart?.balance > 0) ||
181
184
  placing || errorCash || subtotalWithTaxes < cart?.minimum ||
182
185
  (options.type === 1 &&
183
186
  validationFields?.fields?.checkout?.driver_tip?.enabled &&
184
187
  validationFields?.fields?.checkout?.driver_tip?.required &&
185
- (Number(cart?.driver_tip) <= 0))
188
+ (Number(cart?.driver_tip) <= 0)) ||
189
+ (validateCommentsCartField)
186
190
 
187
191
  const driverTipsOptions = typeof configs?.driver_tip_options?.value === 'string'
188
192
  ? JSON.parse(configs?.driver_tip_options?.value) || []
@@ -218,7 +222,7 @@ const CheckoutUI = (props: any) => {
218
222
 
219
223
  const handlePlaceOrder = (confirmPayment: any, forcePlace: boolean = false) => {
220
224
  if (!userErrors.length && (!requiredFields?.length || allowedGuest) || forcePlace) {
221
- Vibration.vibrate()
225
+ vibrateApp()
222
226
  handlerClickPlaceOrder && handlerClickPlaceOrder(null, null, confirmPayment)
223
227
  return
224
228
  }
@@ -257,7 +261,7 @@ const CheckoutUI = (props: any) => {
257
261
  const checkValidationFields = () => {
258
262
  setUserErrors([])
259
263
  const errors = []
260
- const notFields = ['coupon', 'driver_tip', 'mobile_phone', 'address', 'zipcode', 'address_notes']
264
+ const notFields = ['coupon', 'driver_tip', 'mobile_phone', 'address', 'zipcode', 'address_notes', 'comments']
261
265
  const _requiredFields: any = []
262
266
 
263
267
  Object.values(validationFields?.fields?.checkout).map((field: any) => {
@@ -347,6 +351,7 @@ const CheckoutUI = (props: any) => {
347
351
  btnStyle={{ paddingLeft: 0, paddingTop: Platform.OS == 'ios' ? 0 : 2 }}
348
352
  titleWrapStyle={{ paddingHorizontal: 0 }}
349
353
  titleStyle={{ marginRight: 0, marginLeft: 0 }}
354
+ style={{ marginTop: 20 }}
350
355
  />
351
356
  </View>
352
357
  <ChContainer style={styles.pagePadding}>
@@ -751,7 +756,7 @@ const CheckoutUI = (props: any) => {
751
756
 
752
757
  {!cartState.loading && cart && (
753
758
  <View>
754
- <ChErrors style={{ marginBottom: 30 }}>
759
+ <ChErrors style={{ marginBottom: Platform.OS === 'ios' ? 35 : 10 }}>
755
760
  {!cart?.valid_address && cart?.status !== 2 && (
756
761
  <OText
757
762
  color={theme.colors.error}
@@ -797,6 +802,15 @@ const CheckoutUI = (props: any) => {
797
802
  {t('WARNING_INVALID_DRIVER_TIP', 'Driver Tip is required.')}
798
803
  </OText>
799
804
  )}
805
+
806
+ {validateCommentsCartField && (
807
+ <OText
808
+ color={theme.colors.error}
809
+ size={12}
810
+ >
811
+ {t('WARNING_INVALID_CART_COMMENTS', 'Cart comments is required.')}
812
+ </OText>
813
+ )}
800
814
  </ChErrors>
801
815
  </View>
802
816
  )}
@@ -869,7 +883,7 @@ const CheckoutUI = (props: any) => {
869
883
  </Container>
870
884
  {!cartState.loading && cart && cart?.status !== 2 && (
871
885
  <FloatingButton
872
- handleClick={isDisabledButtonPlace ? () => Vibration.vibrate() : () => handlePlaceOrder(null)}
886
+ handleClick={isDisabledButtonPlace ? () => vibrateApp() : () => handlePlaceOrder(null)}
873
887
  isSecondaryBtn={isDisabledButtonPlace}
874
888
  disabled={isDisabledButtonPlace}
875
889
  btnText={subtotalWithTaxes >= cart?.minimum
@@ -0,0 +1,96 @@
1
+ import React, { useState } from 'react';
2
+ import { StyleSheet, View } from 'react-native';
3
+ import { useLanguage } from 'ordering-components/native';
4
+ import Feather from 'react-native-vector-icons/Feather'
5
+ import { useTheme } from 'styled-components/native';
6
+ import { OText, OButton } from '../../shared';
7
+ import { OModal } from '../../../../../../src/components/shared';
8
+ import { PurchaseGiftCard } from '../PurchaseGiftCard'
9
+ import { RedeemGiftCard } from '../RedeemGiftCard'
10
+
11
+ import {
12
+ Container
13
+ } from './styles'
14
+
15
+ export const GiftCardUI = React.memo((props: any) => {
16
+ const {
17
+ navigation
18
+ } = props
19
+ const [, t] = useLanguage()
20
+ const theme = useTheme()
21
+ const [openModal, setOpenModal] = useState<any>(null)
22
+
23
+ const style = StyleSheet.create({
24
+ title: {
25
+ flexDirection: 'row',
26
+ alignItems: 'center'
27
+ },
28
+ actionWrapper: {
29
+ flexDirection: 'row',
30
+ alignItems: 'center',
31
+ marginTop: 10
32
+ },
33
+ btnStyle: {
34
+ borderRadius: 7.6,
35
+ paddingLeft: 0,
36
+ paddingRight: 0,
37
+ height: 44
38
+ }
39
+ })
40
+
41
+ const handleCustomGoToCheckout = (uuid: any) => {
42
+ setOpenModal(null)
43
+ navigation.navigate('CheckoutNavigator', {
44
+ screen: 'CheckoutPage',
45
+ cartUuid: uuid
46
+ })
47
+ }
48
+
49
+ return (
50
+ <Container>
51
+ <View style={style.title}>
52
+ <OText size={16} color={theme.colors.textNormal} weight='bold' mBottom={0} mRight={12}>{t('GIFT_CARD', 'Gift card')}</OText>
53
+ <Feather name='gift' color={theme.colors.textNormal} size={16} />
54
+ </View>
55
+
56
+ <View style={style.actionWrapper}>
57
+ <OButton
58
+ onClick={() => setOpenModal('purchase')}
59
+ text={t('PURCHASE_GIFT_CARD', 'Purchase gift card')}
60
+ bgColor={theme.colors.primary}
61
+ borderColor={theme.colors.primary}
62
+ textStyle={{ color: 'white', fontSize: 13 }}
63
+ imgRightSrc={null}
64
+ style={{ ...style.btnStyle, marginRight: 14 }}
65
+ />
66
+
67
+ <OButton
68
+ onClick={() => setOpenModal('redeem')}
69
+ text={t('REDEEM_GIFT_CARD', 'Redeem gift card')}
70
+ bgColor={theme.colors.lightPrimary}
71
+ borderColor={theme.colors.lightPrimary}
72
+ textStyle={{ color: theme.colors.primary, fontSize: 13 }}
73
+ imgRightSrc={null}
74
+ style={style.btnStyle}
75
+ />
76
+ </View>
77
+
78
+ <OModal
79
+ open={openModal === 'purchase'}
80
+ onClose={() => setOpenModal(null)}
81
+ entireModal
82
+ >
83
+ <PurchaseGiftCard handleCustomGoToCheckout={handleCustomGoToCheckout} />
84
+ </OModal>
85
+ <OModal
86
+ open={openModal === 'redeem'}
87
+ onClose={() => setOpenModal(null)}
88
+ entireModal
89
+ >
90
+ <RedeemGiftCard
91
+ onClose={() => setOpenModal(null)}
92
+ />
93
+ </OModal>
94
+ </Container>
95
+ )
96
+ })
@@ -0,0 +1,5 @@
1
+ import styled from 'styled-components/native'
2
+
3
+ export const Container = styled.View`
4
+ width: 100%;
5
+ `
@@ -0,0 +1,100 @@
1
+ import React from 'react'
2
+ import {
3
+ useLanguage,
4
+ PurchaseGiftCard as PurchaseGiftCardController
5
+ } from 'ordering-components/native'
6
+ import { StyleSheet, View, TouchableOpacity, ScrollView } from 'react-native'
7
+ import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
8
+ import { useTheme } from 'styled-components/native';
9
+ import { OText, OButton, OIcon } from '../../shared';
10
+
11
+ import {
12
+ Container
13
+ } from './styles'
14
+
15
+ const PurchaseGiftCardUI = (props: any) => {
16
+ const {
17
+ productsListState,
18
+ selectedProduct,
19
+ setSelectedProduct,
20
+ handleAccept
21
+ } = props
22
+
23
+ const theme = useTheme()
24
+ const [, t] = useLanguage()
25
+
26
+ const style = StyleSheet.create({
27
+ itemStyle: {
28
+ flexDirection: 'row',
29
+ alignItems: 'center',
30
+ paddingVertical: 15,
31
+ borderBottomWidth: 1,
32
+ borderBottomColor: theme.colors.disabled
33
+ },
34
+ btnStyle: {
35
+ borderRadius: 7.6,
36
+ paddingLeft: 0,
37
+ paddingRight: 0,
38
+ height: 44,
39
+ marginTop: 50
40
+ }
41
+ })
42
+
43
+ return (
44
+ <Container>
45
+ <OText color={theme.colors.textNormal} weight='bold' size={20} mBottom={40}>{t('PURCHASE_GIFT_CARD', 'Purchase gift card')}</OText>
46
+ <OText color={theme.colors.textNormal} size={14}>{t('SELECT_ONE_OPTION', 'Select one option')}</OText>
47
+ <ScrollView
48
+ contentContainerStyle={{
49
+ flexGrow: 1
50
+ }}
51
+ >
52
+ {productsListState.loading && (
53
+ [...Array(5).keys()].map(i => (
54
+ <View key={i} style={style.itemStyle}>
55
+ <Placeholder
56
+ Animation={Fade}
57
+ >
58
+ <PlaceholderLine width={80} height={20} style={{ marginBottom: 0 }} />
59
+ </Placeholder>
60
+ </View>
61
+ ))
62
+ )}
63
+ {productsListState.products.map(product => (
64
+ <TouchableOpacity
65
+ key={product.id}
66
+ style={style.itemStyle}
67
+ onPress={() => setSelectedProduct(product)}
68
+ >
69
+ <View style={{ marginRight: 10 }}>
70
+ {selectedProduct?.id === product.id ? (
71
+ <OIcon src={theme.images.general.radio_act} color={theme.colors.primary} width={16} />
72
+ ) : (
73
+ <OIcon src={theme.images.general.radio_nor} color={theme.colors.disabled} width={16} />
74
+ )}
75
+ </View>
76
+ <OText color={theme.colors.textNormal} size={14}>{product.name}</OText>
77
+ </TouchableOpacity>
78
+ ))}
79
+ </ScrollView>
80
+ <OButton
81
+ onClick={() => handleAccept()}
82
+ text={t('ACCEPT', 'Accept')}
83
+ bgColor={theme.colors.primary}
84
+ borderColor={theme.colors.primary}
85
+ textStyle={{ color: 'white', fontSize: 13 }}
86
+ imgRightSrc={null}
87
+ style={style.btnStyle}
88
+ isDisabled={!selectedProduct}
89
+ />
90
+ </Container>
91
+ )
92
+ }
93
+
94
+ export const PurchaseGiftCard = (props: any) => {
95
+ const purchaseGiftCardProps = {
96
+ ...props,
97
+ UIComponent: PurchaseGiftCardUI
98
+ }
99
+ return <PurchaseGiftCardController {...purchaseGiftCardProps} />
100
+ }
@@ -0,0 +1,8 @@
1
+ import styled from 'styled-components/native'
2
+
3
+ export const Container = styled.View`
4
+ width: 100%;
5
+ padding-horizontal: 40px;
6
+ flex: 1;
7
+ padding-bottom: 30px;
8
+ `
@@ -0,0 +1,178 @@
1
+ import React, { useEffect } from 'react'
2
+ import {
3
+ useLanguage, useUtils, RedeemGiftCard as RedeemGiftCardController
4
+ } from 'ordering-components/native'
5
+ import { useForm, Controller } from 'react-hook-form'
6
+ import { StyleSheet, View, Alert } from 'react-native';
7
+ import { useTheme } from 'styled-components/native';
8
+ import { OText, OButton, OInput } from '../../shared';
9
+
10
+ import {
11
+ Container,
12
+ FormController
13
+ } from './styles'
14
+
15
+ const RedeemGiftCardUI = (props: any) => {
16
+ const {
17
+ actionState,
18
+ redeemedGiftCard,
19
+ handleApply,
20
+ onClose,
21
+ setRedeemedGiftCard
22
+ } = props
23
+
24
+ const theme = useTheme()
25
+ const [, t] = useLanguage()
26
+ const { handleSubmit, control, errors } = useForm()
27
+ const [{ parsePrice }] = useUtils()
28
+
29
+ const style = StyleSheet.create({
30
+ btnStyle: {
31
+ borderRadius: 7.6,
32
+ height: 44,
33
+ marginTop: 20
34
+ },
35
+ inputStyle: {
36
+ borderWidth: 1,
37
+ borderColor: theme.colors.border,
38
+ borderRadius: 7.6,
39
+ },
40
+ })
41
+
42
+ const onSubmit = (values) => {
43
+ handleApply(values)
44
+ }
45
+
46
+ useEffect(() => {
47
+ if (Object.keys(errors).length > 0) {
48
+ const list = Object.values(errors)
49
+ let stringError = ''
50
+ list.map((item: any, i: number) => {
51
+ stringError += (i + 1) === list.length ? `- ${item.message}` : `- ${item.message}\n`
52
+ })
53
+ Alert.alert(
54
+ t('ERROR', 'Error'),
55
+ stringError,
56
+ [
57
+ { text: t('OK', 'oK'), onPress: () => {} }
58
+ ]
59
+ )
60
+ }
61
+ }, [errors])
62
+
63
+ useEffect(() => {
64
+ if (!actionState.error) return
65
+ let stringError = ''
66
+ if (typeof actionState.error === 'string') {
67
+ stringError = actionState.error
68
+ } else {
69
+ actionState.error.map(item => {
70
+ stringError += `- ${item}\n`
71
+ })
72
+ }
73
+ Alert.alert(
74
+ t('ERROR', 'Error'),
75
+ stringError,
76
+ [
77
+ { text: t('OK', 'oK'), onPress: () => {} }
78
+ ]
79
+ )
80
+ }, [actionState.error])
81
+
82
+ return (
83
+ <Container>
84
+ {!redeemedGiftCard ? (
85
+ <View>
86
+ <OText color={theme.colors.textNormal} weight='bold' size={20} mBottom={40}>{t('REDEEM_GIFT_CARD', 'Redeem a gift card')}</OText>
87
+ <FormController>
88
+ <OText color={theme.colors.textNormal} size={14} mBottom={10}>{t('GIFT_CARD_CODE', 'Gift card code')}</OText>
89
+ <Controller
90
+ control={control}
91
+ render={({ onChange, value }: any) => (
92
+ <OInput
93
+ placeholder='0000 0000'
94
+ value={value}
95
+ onChange={(val: any) => onChange(val)}
96
+ autoCapitalize='none'
97
+ autoCorrect={false}
98
+ blurOnSubmit={false}
99
+ style={style.inputStyle}
100
+ />
101
+ )}
102
+ name='code'
103
+ rules={{
104
+ required: t('VALIDATION_ERROR_REQUIRED', 'Code is required').replace('_attribute_', t('CODE', 'Code'))
105
+ }}
106
+ defaultValue=""
107
+ />
108
+ </FormController>
109
+ <FormController>
110
+ <OText color={theme.colors.textNormal} size={14} mBottom={10}>{t('PASSWORD', 'Password')}</OText>
111
+ <Controller
112
+ control={control}
113
+ render={({ onChange, value }: any) => (
114
+ <OInput
115
+ isSecured
116
+ placeholder={t('PASSWORD', 'Password')}
117
+ value={value}
118
+ onChange={(val: any) => onChange(val)}
119
+ autoCapitalize='none'
120
+ autoCompleteType='password'
121
+ autoCorrect={false}
122
+ blurOnSubmit={false}
123
+ style={style.inputStyle}
124
+ />
125
+ )}
126
+ name='password'
127
+ rules={{
128
+ required: t('VALIDATION_ERROR_REQUIRED', 'Password is required').replace('_attribute_', t('PASSWORD', 'Password'))
129
+ }}
130
+ defaultValue=""
131
+ />
132
+ </FormController>
133
+ <OButton
134
+ onClick={handleSubmit(onSubmit)}
135
+ text={actionState?.loading ? t('LOADING', 'Loading') : t('APPLY_TO_YOUR_BALANCE', 'Apply to your balance')}
136
+ bgColor={theme.colors.primary}
137
+ borderColor={theme.colors.primary}
138
+ textStyle={{ color: 'white', fontSize: 13 }}
139
+ imgRightSrc={null}
140
+ style={style.btnStyle}
141
+ isDisabled={actionState.loading}
142
+ />
143
+ </View>
144
+ ) : (
145
+ <>
146
+ <OText color={theme.colors.textNormal} weight='bold' size={20} mBottom={40}>{t('GIFT_CARD', 'Gift card')}</OText>
147
+ <View>
148
+ <OText color={theme.colors.textNormal} size={14} mBottom={6}>{t('TYPE', 'Type')}: {redeemedGiftCard?.type}</OText>
149
+ <OText color={theme.colors.textNormal} size={14} mBottom={6}>{t('AMOUNT', 'Amount')}: {parsePrice(redeemedGiftCard?.amount)}</OText>
150
+ <OText color={theme.colors.textNormal} size={14} mBottom={6}>{t('FROM', 'From')}: {redeemedGiftCard?.receiver?.name} {redeemedGiftCard?.receiver?.lastname}</OText>
151
+ {!!redeemedGiftCard?.title && <OText color={theme.colors.textNormal} size={14} mBottom={6}>{t('TITLE', 'Title')}: {redeemedGiftCard?.title}</OText>}
152
+ {!!redeemedGiftCard?.message && <OText color={theme.colors.textNormal} size={14} mBottom={6}>{t('MESSAGES', 'Messages')}: {redeemedGiftCard?.message}</OText>}
153
+ <OButton
154
+ onClick={() => {
155
+ setRedeemedGiftCard(null)
156
+ onClose()
157
+ }}
158
+ text={t('OK', 'Ok')}
159
+ bgColor={theme.colors.primary}
160
+ borderColor={theme.colors.primary}
161
+ textStyle={{ color: 'white', fontSize: 13 }}
162
+ imgRightSrc={null}
163
+ style={style.btnStyle}
164
+ />
165
+ </View>
166
+ </>
167
+ )}
168
+ </Container>
169
+ )
170
+ }
171
+
172
+ export const RedeemGiftCard = (props: any) => {
173
+ const redeemGiftCardProps = {
174
+ ...props,
175
+ UIComponent: RedeemGiftCardUI
176
+ }
177
+ return <RedeemGiftCardController {...redeemGiftCardProps} />
178
+ }
@@ -0,0 +1,8 @@
1
+ import styled from 'styled-components/native'
2
+
3
+ export const Container = styled.View`
4
+ padding-horizontal: 40px;
5
+ `
6
+ export const FormController = styled.View`
7
+ margin-bottom: 25px;
8
+ `
@@ -0,0 +1,165 @@
1
+ import React, { useEffect } from 'react'
2
+ import { StyleSheet, Platform, Alert } from 'react-native';
3
+ import { useLanguage, SendGiftCard as SendGiftCardController } from 'ordering-components/native';
4
+ import { useTheme } from 'styled-components/native';
5
+ import { OText, OButton, OInput } from '../../shared';
6
+ import { useForm, Controller } from 'react-hook-form'
7
+
8
+ import {
9
+ Container,
10
+ FormController
11
+ } from './styles'
12
+
13
+
14
+ const SendGiftCardUI = (props: any) => {
15
+ const {
16
+ actionState,
17
+ handleSendGiftCard
18
+ } = props
19
+
20
+ const theme = useTheme()
21
+ const [, t] = useLanguage()
22
+
23
+ const { handleSubmit, control, errors } = useForm()
24
+
25
+ const style = StyleSheet.create({
26
+ btnStyle: {
27
+ borderRadius: 7.6,
28
+ height: 44,
29
+ marginTop: 20
30
+ },
31
+ inputStyle: {
32
+ borderWidth: 1,
33
+ borderColor: theme.colors.border,
34
+ borderRadius: 7.6,
35
+ },
36
+ })
37
+
38
+ const onSubmit = (values) => {
39
+ handleSendGiftCard(values)
40
+ }
41
+
42
+ useEffect(() => {
43
+ if (Object.keys(errors).length > 0) {
44
+ const list = Object.values(errors)
45
+ let stringError = ''
46
+ list.map((item: any, i: number) => {
47
+ stringError += (i + 1) === list.length ? `- ${item.message}` : `- ${item.message}\n`
48
+ })
49
+ Alert.alert(
50
+ t('ERROR', 'Error'),
51
+ stringError,
52
+ [
53
+ { text: t('OK', 'oK'), onPress: () => {} }
54
+ ]
55
+ )
56
+ }
57
+ }, [errors])
58
+
59
+ return (
60
+ <Container>
61
+ <OText color={theme.colors.textNormal} size={20} mBottom={10} style={{ fontWeight: Platform.OS == 'ios' ? '600' : 'bold' }}>{t('GIFT_CARD_DETAILS', 'Gift Card details')}</OText>
62
+ <FormController>
63
+ <OText color={theme.colors.textNormal} size={14} mBottom={10}>{t('TO', 'To')}</OText>
64
+ <Controller
65
+ control={control}
66
+ render={({ onChange, value }: any) => (
67
+ <OInput
68
+ placeholder={t('ENTER_AN_EMAIL', 'Enter an email')}
69
+ value={value}
70
+ onChange={(val: any) => onChange(val)}
71
+ autoCompleteType='email'
72
+ autoCapitalize='none'
73
+ autoCorrect={false}
74
+ type='email-address'
75
+ blurOnSubmit={false}
76
+ style={style.inputStyle}
77
+ />
78
+ )}
79
+ name='email'
80
+ rules={{
81
+ required: t('VALIDATION_ERROR_REQUIRED', 'To email is required').replace('_attribute_', t('EMAIL', 'EMail'))
82
+ }}
83
+ defaultValue=""
84
+ />
85
+ </FormController>
86
+ <FormController>
87
+ <OText color={theme.colors.textNormal} size={14} mBottom={10}>{t('FROM', 'From')}</OText>
88
+ <Controller
89
+ control={control}
90
+ render={({ onChange, value }: any) => (
91
+ <OInput
92
+ placeholder={t('WRITE_YOUR_NAME', 'Write your name')}
93
+ value={value}
94
+ onChange={(val: any) => onChange(val)}
95
+ autoCapitalize='none'
96
+ autoCorrect={false}
97
+ blurOnSubmit={false}
98
+ style={style.inputStyle}
99
+ />
100
+ )}
101
+ name='user_name'
102
+ defaultValue=""
103
+ />
104
+ </FormController>
105
+ <FormController>
106
+ <OText color={theme.colors.textNormal} size={14} mBottom={10}>{t('TITLE', 'Title')}</OText>
107
+ <Controller
108
+ control={control}
109
+ render={({ onChange, value }: any) => (
110
+ <OInput
111
+ placeholder={t('TITLE', 'Title')}
112
+ value={value}
113
+ onChange={(val: any) => onChange(val)}
114
+ autoCapitalize='none'
115
+ autoCorrect={false}
116
+ blurOnSubmit={false}
117
+ style={style.inputStyle}
118
+ />
119
+ )}
120
+ name='title'
121
+ defaultValue=""
122
+ />
123
+ </FormController>
124
+ <FormController>
125
+ <OText color={theme.colors.textNormal} size={14} mBottom={10}>{t('MESSAGES', 'Messages')}</OText>
126
+ <Controller
127
+ control={control}
128
+ render={({ onChange, value }: any) => (
129
+ <OInput
130
+ multiline
131
+ placeholder={t('TYPE_YOUR_MESSAGE_HERE', 'Type your message here')}
132
+ value={value}
133
+ onChange={(val: any) => onChange(val)}
134
+ autoCapitalize='none'
135
+ autoCorrect={false}
136
+ blurOnSubmit={false}
137
+ style={{ ...style.inputStyle, height: 100, alignItems: 'flex-start', }}
138
+ />
139
+ )}
140
+ name='message'
141
+ defaultValue=""
142
+ />
143
+ </FormController>
144
+ <OButton
145
+ onClick={handleSubmit(onSubmit)}
146
+ text={actionState?.loading ? t('LOADING', 'Loading') : t('SEND_GIFT_CARD', 'Send gift card')}
147
+ bgColor={theme.colors.primary}
148
+ borderColor={theme.colors.primary}
149
+ textStyle={{ color: 'white', fontSize: 13 }}
150
+ imgRightSrc={null}
151
+ style={style.btnStyle}
152
+ isDisabled={actionState.loading}
153
+ />
154
+ </Container>
155
+ )
156
+ }
157
+
158
+ export const SendGiftCard = (props: any) => {
159
+ const sendGiftCardProps = {
160
+ ...props,
161
+ showToastMsg: true,
162
+ UIComponent: SendGiftCardUI
163
+ }
164
+ return <SendGiftCardController {...sendGiftCardProps} />
165
+ }
@@ -0,0 +1,9 @@
1
+ import styled from 'styled-components/native'
2
+
3
+ export const Container = styled.View`
4
+ padding-horizontal: 40px;
5
+ margin-bottom: 30px;
6
+ `
7
+ export const FormController = styled.View`
8
+ margin-bottom: 25px;
9
+ `
@@ -49,6 +49,7 @@ import NavBar from '../NavBar'
49
49
  import { OrderHistory } from './OrderHistory';
50
50
  import { PlaceSpot } from '../PlaceSpot'
51
51
  import { OrderEta } from './OrderEta'
52
+ import { SendGiftCard } from '../GiftCard/SendGiftCard'
52
53
  export const OrderDetailsUI = (props: OrderDetailsParams) => {
53
54
  const {
54
55
  navigation,
@@ -112,6 +113,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
112
113
  const [{ carts }] = useOrder()
113
114
 
114
115
  const [isReviewed, setIsReviewed] = useState(false)
116
+ const [isGiftCardSent, setIsGiftCardSent] = useState(false)
115
117
  const [isOrderHistory, setIsOrderHistory] = useState(false)
116
118
  const [openTaxModal, setOpenTaxModal] = useState<any>({ open: false, tax: null, type: '' })
117
119
  const [refreshing] = useState(false);
@@ -122,6 +124,8 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
122
124
  const activeStatus = [0, 3, 4, 7, 8, 9, 14, 18, 19, 20, 21, 22, 23]
123
125
  const enabledPoweredByOrdering = configs?.powered_by_ordering_module?.value
124
126
  const hideDeliveryDate = theme?.confirmation?.components?.order?.components?.date?.hidden
127
+ const isGiftCardOrder = !order?.business_id
128
+
125
129
  const walletName: any = {
126
130
  cash: {
127
131
  name: t('PAY_WITH_CASH_WALLET', 'Pay with Cash Wallet'),
@@ -412,175 +416,179 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
412
416
  </OText>
413
417
  </View>
414
418
  )}
415
- <OrderInfo>
416
- <OrderData>
417
- <View style={styles.linkWrapper}>
418
- {
419
- (
420
- parseInt(order?.status) === 1 ||
421
- parseInt(order?.status) === 11 ||
422
- parseInt(order?.status) === 15
423
- ) && !order.review && !isReviewed && (
424
- <TouchableOpacity
425
- activeOpacity={0.7}
426
- style={{ marginTop: 6, marginRight: 10 }}
427
- onPress={() => handleClickOrderReview(order)}
428
- >
429
- <OText
430
- size={12}
431
- lineHeight={15}
432
- color={theme.colors.primary}
433
- style={{ textDecorationLine: 'underline' }}
419
+ {!isGiftCardOrder && (
420
+ <OrderInfo>
421
+ <OrderData>
422
+ <View style={styles.linkWrapper}>
423
+ {
424
+ (
425
+ parseInt(order?.status) === 1 ||
426
+ parseInt(order?.status) === 11 ||
427
+ parseInt(order?.status) === 15
428
+ ) && !order.review && !isReviewed && (
429
+ <TouchableOpacity
430
+ activeOpacity={0.7}
431
+ style={{ marginTop: 6, marginRight: 10 }}
432
+ onPress={() => handleClickOrderReview(order)}
434
433
  >
435
- {t('REVIEW_YOUR_ORDER', 'Review your order')}
436
- </OText>
437
- </TouchableOpacity>
438
- )}
439
- <TouchableOpacity
440
- activeOpacity={0.7}
441
- style={{ marginTop: 6 }}
442
- onPress={() => setIsOrderHistory(true)}
443
-
444
- >
445
- <OText
446
- size={12}
447
- lineHeight={15}
448
- color={theme.colors.primary}
449
- style={{ textDecorationLine: 'underline', textTransform: 'capitalize' }}
434
+ <OText
435
+ size={12}
436
+ lineHeight={15}
437
+ color={theme.colors.primary}
438
+ style={{ textDecorationLine: 'underline' }}
439
+ >
440
+ {t('REVIEW_YOUR_ORDER', 'Review your order')}
441
+ </OText>
442
+ </TouchableOpacity>
443
+ )}
444
+ <TouchableOpacity
445
+ activeOpacity={0.7}
446
+ style={{ marginTop: 6 }}
447
+ onPress={() => setIsOrderHistory(true)}
448
+
450
449
  >
451
- {t('VIEW_DETAILS', 'View Details')}
452
- </OText>
453
- </TouchableOpacity>
454
- </View>
455
-
456
- <StaturBar>
457
- <LinearGradient
458
- start={{ x: 0.0, y: 0.0 }}
459
- end={{
460
- x: getOrderStatus(order?.status)?.percentage || 0,
461
- y: 0,
462
- }}
463
- locations={[0.9999, 0.9999]}
464
- colors={[theme.colors.primary, theme.colors.backgroundGray100]}
465
- style={styles.statusBar}
466
- />
467
- </StaturBar>
450
+ <OText
451
+ size={12}
452
+ lineHeight={15}
453
+ color={theme.colors.primary}
454
+ style={{ textDecorationLine: 'underline', textTransform: 'capitalize' }}
455
+ >
456
+ {t('VIEW_DETAILS', 'View Details')}
457
+ </OText>
458
+ </TouchableOpacity>
459
+ </View>
460
+
461
+ <StaturBar>
462
+ <LinearGradient
463
+ start={{ x: 0.0, y: 0.0 }}
464
+ end={{
465
+ x: getOrderStatus(order?.status)?.percentage || 0,
466
+ y: 0,
467
+ }}
468
+ locations={[0.9999, 0.9999]}
469
+ colors={[theme.colors.primary, theme.colors.backgroundGray100]}
470
+ style={styles.statusBar}
471
+ />
472
+ </StaturBar>
473
+ <OText
474
+ size={16}
475
+ lineHeight={24}
476
+ weight={'600'}
477
+ color={theme.colors.textNormal}>
478
+ {getOrderStatus(order?.status)?.value}
479
+ </OText>
480
+ </OrderData>
481
+ <View
482
+ style={{
483
+ height: 8,
484
+ backgroundColor: theme.colors.backgroundGray100,
485
+ marginTop: 18,
486
+ marginHorizontal: -40,
487
+ }}
488
+ />
489
+ </OrderInfo>
490
+ )}
491
+ </Header>
492
+ <OrderContent>
493
+ {!isGiftCardOrder && (
494
+ <OrderBusiness>
468
495
  <OText
469
496
  size={16}
470
497
  lineHeight={24}
471
- weight={'600'}
472
- color={theme.colors.textNormal}>
473
- {getOrderStatus(order?.status)?.value}
498
+ weight={'500'}
499
+ color={theme.colors.textNormal}
500
+ mBottom={12}>
501
+ {t('FROM', 'From')}
474
502
  </OText>
475
- </OrderData>
476
- <View
477
- style={{
478
- height: 8,
479
- backgroundColor: theme.colors.backgroundGray100,
480
- marginTop: 18,
481
- marginHorizontal: -40,
482
- }}
483
- />
484
- </OrderInfo>
485
- </Header>
486
- <OrderContent>
487
- <OrderBusiness>
488
- <OText
489
- size={16}
490
- lineHeight={24}
491
- weight={'500'}
492
- color={theme.colors.textNormal}
493
- mBottom={12}>
494
- {t('FROM', 'From')}
495
- </OText>
496
- <View
497
- style={{
498
- display: 'flex',
499
- flexDirection: 'column',
500
- alignItems: 'flex-start',
501
- }}>
502
503
  <View
503
504
  style={{
504
- flexDirection: 'row',
505
- alignItems: 'center',
506
- justifyContent: 'space-between',
505
+ display: 'flex',
506
+ flexDirection: 'column',
507
+ alignItems: 'flex-start',
507
508
  }}>
508
- <OText
509
- size={13}
510
- lineHeight={20}
511
- color={theme.colors.textNormal}
512
- style={{ flexGrow: 1, flexBasis: '80%' }}>
513
- {order?.business?.name}
514
- </OText>
515
- <Icons>
516
- {!!order?.business?.cellphone && (
509
+ <View
510
+ style={{
511
+ flexDirection: 'row',
512
+ alignItems: 'center',
513
+ justifyContent: 'space-between',
514
+ }}>
515
+ <OText
516
+ size={13}
517
+ lineHeight={20}
518
+ color={theme.colors.textNormal}
519
+ style={{ flexGrow: 1, flexBasis: '80%' }}>
520
+ {order?.business?.name}
521
+ </OText>
522
+ <Icons>
523
+ {!!order?.business?.cellphone && (
524
+ <TouchableOpacity
525
+ onPress={() => order?.business?.cellphone &&
526
+ Linking.openURL(`tel:${order?.business?.cellphone}`)
527
+ }
528
+ style={{ paddingEnd: 5 }}
529
+ >
530
+ <OIcon
531
+ src={theme.images.general.phone}
532
+ width={16}
533
+ color={theme.colors.disabled}
534
+ />
535
+ </TouchableOpacity>
536
+ )}
517
537
  <TouchableOpacity
518
- onPress={() => order?.business?.cellphone &&
519
- Linking.openURL(`tel:${order?.business?.cellphone}`)
520
- }
521
- style={{ paddingEnd: 5 }}
522
- >
538
+ style={{ paddingStart: 5 }}
539
+ onPress={() => handleGoToMessages('business')}>
523
540
  <OIcon
524
- src={theme.images.general.phone}
541
+ src={theme.images.general.chat}
525
542
  width={16}
526
543
  color={theme.colors.disabled}
527
544
  />
528
545
  </TouchableOpacity>
529
- )}
530
- <TouchableOpacity
531
- style={{ paddingStart: 5 }}
532
- onPress={() => handleGoToMessages('business')}>
533
- <OIcon
534
- src={theme.images.general.chat}
535
- width={16}
536
- color={theme.colors.disabled}
537
- />
538
- </TouchableOpacity>
539
- </Icons>
540
- </View>
541
- <OText
542
- size={12}
543
- lineHeight={18}
544
- color={theme.colors.textNormal}
545
- mBottom={2}>
546
- {order?.business?.email}
547
- </OText>
548
- {!!order?.business?.cellphone && (
546
+ </Icons>
547
+ </View>
549
548
  <OText
550
549
  size={12}
551
550
  lineHeight={18}
552
551
  color={theme.colors.textNormal}
553
552
  mBottom={2}>
554
- {order?.business?.cellphone}
553
+ {order?.business?.email}
555
554
  </OText>
555
+ {!!order?.business?.cellphone && (
556
+ <OText
557
+ size={12}
558
+ lineHeight={18}
559
+ color={theme.colors.textNormal}
560
+ mBottom={2}>
561
+ {order?.business?.cellphone}
562
+ </OText>
563
+ )}
564
+ <OText size={12} lineHeight={18} color={theme.colors.textNormal}>
565
+ {order?.business?.address}
566
+ </OText>
567
+ </View>
568
+ {directionTypes.includes(order?.delivery_type) && (
569
+ <OButton
570
+ text={t('GET_DIRECTIONS', 'Get Directions')}
571
+ imgRightSrc=''
572
+ textStyle={{ color: theme.colors.white }}
573
+ style={{
574
+ alignSelf: 'center',
575
+ borderRadius: 10,
576
+ marginTop: 30
577
+ }}
578
+ onClick={() => showLocation({
579
+ latitude: order?.business?.location?.lat,
580
+ longitude: order?.business?.location?.lng,
581
+ naverCallerName: 'com.reactnativeappstemplate5',
582
+ dialogTitle: t('GET_DIRECTIONS', 'Get Directions'),
583
+ dialogMessage: t('WHAT_APP_WOULD_YOU_USE', 'What app would you like to use?'),
584
+ cancelText: t('CANCEL', 'Cancel'),
585
+ })}
586
+ />
556
587
  )}
557
- <OText size={12} lineHeight={18} color={theme.colors.textNormal}>
558
- {order?.business?.address}
559
- </OText>
560
- </View>
561
- {directionTypes.includes(order?.delivery_type) && (
562
- <OButton
563
- text={t('GET_DIRECTIONS', 'Get Directions')}
564
- imgRightSrc=''
565
- textStyle={{ color: theme.colors.white }}
566
- style={{
567
- alignSelf: 'center',
568
- borderRadius: 10,
569
- marginTop: 30
570
- }}
571
- onClick={() => showLocation({
572
- latitude: order?.business?.location?.lat,
573
- longitude: order?.business?.location?.lng,
574
- naverCallerName: 'com.reactnativeappstemplate5',
575
- dialogTitle: t('GET_DIRECTIONS', 'Get Directions'),
576
- dialogMessage: t('WHAT_APP_WOULD_YOU_USE', 'What app would you like to use?'),
577
- cancelText: t('CANCEL', 'Cancel'),
578
- })}
579
- />
580
- )}
581
- </OrderBusiness>
588
+ </OrderBusiness>
589
+ )}
582
590
 
583
- {placeSpotTypes.includes(order?.delivery_type) && (
591
+ {!isGiftCardOrder && placeSpotTypes.includes(order?.delivery_type) && (
584
592
  <PlaceSpotWrapper>
585
593
  <PlaceSpot
586
594
  isInputMode
@@ -606,7 +614,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
606
614
  weight={'500'}
607
615
  color={theme.colors.textNormal}
608
616
  mBottom={12}>
609
- {t('TO', 'To')}
617
+ {isGiftCardOrder ? t('CUSTOMER', 'Customer') : t('TO', 'To')}
610
618
  </OText>
611
619
  <Customer>
612
620
  <InfoBlock>
@@ -635,7 +643,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
635
643
  )}
636
644
  </InfoBlock>
637
645
  </Customer>
638
- {order?.delivery_option !== undefined && order?.delivery_type === 1 && (
646
+ {!isGiftCardOrder && order?.delivery_option !== undefined && order?.delivery_type === 1 && (
639
647
  <View style={{ marginTop: 15 }}>
640
648
  <OText size={16} style={{ textAlign: 'left' }} color={theme.colors.textNormal}>
641
649
  {t('DELIVERY_PREFERENCE', 'Delivery Preference')}
@@ -817,7 +825,9 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
817
825
  </Table>
818
826
  ))
819
827
  }
820
- <Divider />
828
+ {!isGiftCardOrder && (
829
+ <Divider />
830
+ )}
821
831
  {order?.summary?.subtotal_with_discount > 0 && order?.summary?.discount > 0 && order?.summary?.total >= 0 && (
822
832
  <Table>
823
833
  <OText size={12} lineHeight={18} weight={'400'} color={theme.colors.textNormal}>{t('SUBTOTAL_WITH_DISCOUNT', 'Subtotal with discount')}</OText>
@@ -991,6 +1001,23 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
991
1001
  </View>
992
1002
  )}
993
1003
  </OrderBill>
1004
+ {isGiftCardOrder && order?.products[0]?.gift_card?.status === 'pending' && !isGiftCardSent && (
1005
+ <>
1006
+ <View
1007
+ style={{
1008
+ height: 8,
1009
+ backgroundColor: theme.colors.backgroundGray100,
1010
+ marginTop: 10,
1011
+ marginHorizontal: -40,
1012
+ marginBottom: 20
1013
+ }}
1014
+ />
1015
+ <SendGiftCard
1016
+ giftCardId={order?.products[0]?.gift_card?.id}
1017
+ setIsGiftCardSent={setIsGiftCardSent}
1018
+ />
1019
+ </>
1020
+ )}
994
1021
  </OrderContent>
995
1022
  </>
996
1023
  )}
@@ -287,7 +287,7 @@ const PaymentOptionsUI = (props: any) => {
287
287
  <StripeCardsList
288
288
  paymethod={isOpenMethod?.paymethod}
289
289
  businessId={props.businessId}
290
- publicKey={isOpenMethod?.paymethod?.credentials.publishable}
290
+ publicKey={isOpenMethod?.paymethod?.credentials?.publishable}
291
291
  payType={paymethodsList?.name}
292
292
  onSelectCard={handlePaymethodDataChange}
293
293
  onNavigationRedirect={onNavigationRedirect}
@@ -27,6 +27,7 @@ import { ProductItemAccordionParams } from '../../types'
27
27
  export const ProductItemAccordion = (props: ProductItemAccordionParams) => {
28
28
 
29
29
  const {
30
+ isDisabledEdit,
30
31
  isCartPending,
31
32
  isCartProduct,
32
33
  product,
@@ -203,7 +204,7 @@ export const ProductItemAccordion = (props: ProductItemAccordionParams) => {
203
204
  </View>
204
205
  ) : (
205
206
  <>
206
- {isCartProduct && !isCartPending && getProductMax && (
207
+ {!isDisabledEdit && isCartProduct && !isCartPending && getProductMax && (
207
208
  <ProductInfo>
208
209
  <RNPickerSelect
209
210
  items={productOptions}
@@ -225,7 +226,7 @@ export const ProductItemAccordion = (props: ProductItemAccordionParams) => {
225
226
  </ProductQuantity>
226
227
  )}
227
228
  <View style={{ flex: 1 }}>
228
- <OText size={12} lineHeight={18} weight={'400'}>{product.name}</OText>
229
+ <OText size={12} lineHeight={18} weight={'400'} mLeft={8}>{product.name}</OText>
229
230
  </View>
230
231
  </>
231
232
  )}
@@ -237,7 +238,7 @@ export const ProductItemAccordion = (props: ProductItemAccordionParams) => {
237
238
  )}
238
239
  </View>
239
240
  <View style={{ display: 'flex', flexDirection: 'row', justifyContent: 'flex-start', height: 20 }}>
240
- {onEditProduct && isCartProduct && !isCartPending && product?.valid_menu && (
241
+ {!isDisabledEdit && onEditProduct && isCartProduct && !isCartPending && product?.valid_menu && (
241
242
  <TouchableOpacity onPress={() => handleEditProduct(product)} style={{ marginRight: 5 }}>
242
243
  <MaterialCommunityIcon
243
244
  name='pencil-outline'
@@ -280,7 +280,7 @@ const SingleOrderCardUI = (props: SingleOrderCardParams) => {
280
280
  </OText>
281
281
  </TouchableOpacity>
282
282
  )}
283
- {order.cart && !hideReorderButton && (
283
+ {!hideReorderButton && (
284
284
  <OButton
285
285
  text={t('REORDER', 'Reorder')}
286
286
  imgRightSrc={''}
@@ -27,6 +27,7 @@ import {
27
27
  import { OButton, OIcon, OText, OModal } from '../shared';
28
28
  import { NotFoundSource } from '../NotFoundSource';
29
29
  import { WalletTransactions } from '../WalletTransactions'
30
+ import { GiftCardUI } from '../GiftCard/GiftCardUI'
30
31
 
31
32
  const WalletsUI = (props: any) => {
32
33
  const {
@@ -47,6 +48,7 @@ const WalletsUI = (props: any) => {
47
48
  const [{ parsePrice }] = useUtils()
48
49
  const [{ configs }] = useConfig()
49
50
 
51
+
50
52
  const styles = StyleSheet.create({
51
53
  logoStyle: {
52
54
  width: 120,
@@ -57,6 +59,13 @@ const WalletsUI = (props: any) => {
57
59
  flexDirection: 'column',
58
60
  justifyContent: 'center',
59
61
  alignItems: 'center',
62
+ },
63
+ dividerStyle: {
64
+ height: 8,
65
+ backgroundColor: theme.colors.backgroundGray100,
66
+ marginVertical: 25,
67
+ marginHorizontal: -40,
68
+ width: '100%'
60
69
  }
61
70
  });
62
71
 
@@ -207,6 +216,10 @@ const WalletsUI = (props: any) => {
207
216
  </OText>
208
217
  </BalanceElement>
209
218
 
219
+ <View style={styles.dividerStyle} />
220
+ <GiftCardUI navigation={navigation} />
221
+ <View style={styles.dividerStyle} />
222
+
210
223
  {!isChewLayout && (
211
224
  <WalletTransactions
212
225
  transactionsList={transactionsList}
@@ -444,7 +444,8 @@ export interface ProductItemAccordionParams {
444
444
  onDeleteProduct?: (product: any) => void,
445
445
  onEditProduct?: (product: any) => void,
446
446
  offsetDisabled?: any,
447
- isFromCheckout?: any
447
+ isFromCheckout?: any,
448
+ isDisabledEdit?: any
448
449
  }
449
450
  export interface ReviewOrderParams {
450
451
  order?: { id: number, business_id: number, logo: string, driver: any, products: Array<any>, review: any, user_review: any };