ordering-ui-react-native 0.14.21-release → 0.14.23

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.
Files changed (24) hide show
  1. package/package.json +2 -2
  2. package/src/components/ProductForm/index.tsx +15 -13
  3. package/themes/doordash/src/components/ProductForm/index.tsx +16 -14
  4. package/themes/instacart/src/components/ProductForm/index.tsx +15 -13
  5. package/themes/kiosk/src/components/ProductForm/index.tsx +15 -13
  6. package/themes/original/index.tsx +4 -0
  7. package/themes/original/src/components/BusinessesListing/index.tsx +25 -19
  8. package/themes/original/src/components/Checkout/index.tsx +15 -4
  9. package/themes/original/src/components/Checkout/styles.tsx +5 -1
  10. package/themes/original/src/components/Help/index.tsx +2 -2
  11. package/themes/original/src/components/OrderDetails/index.tsx +54 -0
  12. package/themes/original/src/components/OrderProgress/index.tsx +2 -2
  13. package/themes/original/src/components/OrderSummary/index.tsx +58 -2
  14. package/themes/original/src/components/PaymentOptionWallet/index.tsx +163 -0
  15. package/themes/original/src/components/PaymentOptionWallet/styles.tsx +38 -0
  16. package/themes/original/src/components/ProductForm/index.tsx +21 -19
  17. package/themes/original/src/components/UserProfile/index.tsx +5 -0
  18. package/themes/original/src/components/WalletTransactionItem/index.tsx +68 -0
  19. package/themes/original/src/components/WalletTransactionItem/styles.tsx +37 -0
  20. package/themes/original/src/components/Wallets/index.tsx +204 -0
  21. package/themes/original/src/components/Wallets/styles.tsx +43 -0
  22. package/themes/original/src/types/index.tsx +4 -2
  23. package/themes/single-business/src/components/ProductForm/index.tsx +29 -28
  24. package/themes/uber-eats/src/components/ProductForm/index.tsx +15 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ordering-ui-react-native",
3
- "version": "0.14.21-release",
3
+ "version": "0.14.23",
4
4
  "description": "Reusable components made in react native",
5
5
  "main": "src/index.tsx",
6
6
  "author": "ordering.inc",
@@ -55,7 +55,7 @@
55
55
  "@types/styled-components": "^5.1.3",
56
56
  "axios": "^0.21.0",
57
57
  "moment": "^2.29.1",
58
- "ordering-components": "github:Ordering-Inc/ordering-components#release",
58
+ "ordering-components": "github:Ordering-Inc/ordering-components#development",
59
59
  "patch-package": "^6.4.7",
60
60
  "postinstall-postinstall": "^2.1.0",
61
61
  "prop-types": "^15.7.2",
@@ -232,19 +232,21 @@ export const ProductOptionsUI = (props: any) => {
232
232
  </React.Fragment>
233
233
  )
234
234
  }))}
235
- <ProductComment>
236
- <SectionTitle>
237
- <OText size={16}>{t('SPECIAL_COMMENT', 'Special comment')}</OText>
238
- </SectionTitle>
239
- <OInput
240
- multiline
241
- placeholder={t('SPECIAL_COMMENT', 'Special comment')}
242
- value={productCart.comment}
243
- onChange={(val: string) => handleChangeCommentState({ target: { value: val } })}
244
- isDisabled={!(productCart && !isSoldOut && maxProductQuantity)}
245
- style={styles.comment}
246
- />
247
- </ProductComment>
235
+ {!product?.hide_special_instructions && (
236
+ <ProductComment>
237
+ <SectionTitle>
238
+ <OText size={16}>{t('SPECIAL_COMMENT', 'Special comment')}</OText>
239
+ </SectionTitle>
240
+ <OInput
241
+ multiline
242
+ placeholder={t('SPECIAL_COMMENT', 'Special comment')}
243
+ value={productCart.comment}
244
+ onChange={(val: string) => handleChangeCommentState({ target: { value: val } })}
245
+ isDisabled={!(productCart && !isSoldOut && maxProductQuantity)}
246
+ style={styles.comment}
247
+ />
248
+ </ProductComment>
249
+ )}
248
250
  </ProductEditions>
249
251
  )}
250
252
  </WrapContent>
@@ -287,20 +287,22 @@ export const ProductOptionsUI = (props: any) => {
287
287
  </React.Fragment>
288
288
  )
289
289
  }))}
290
- <ProductComment onLayout={(e: any) => setCommentY(e.nativeEvent.layout.y + e.nativeEvent.layout.height)}>
291
- <SectionTitle>
292
- <OText style={theme.labels.middle as TextStyle}>{t('SPECIAL_COMMENT', 'Special comment')}</OText>
293
- </SectionTitle>
294
- <OInput
295
- multiline
296
- placeholder={t('SPECIAL_COMMENT', 'Special comment')}
297
- value={productCart.comment}
298
- onChange={(val: string) => handleChangeCommentState({ target: { value: val } })}
299
- isDisabled={!(productCart && !isSoldOut && maxProductQuantity)}
300
- style={styles.comment}
301
- inputStyle={{ fontSize: 12, paddingBottom: 7, paddingTop: 17 }}
302
- />
303
- </ProductComment>
290
+ {!product?.hide_special_instructions && (
291
+ <ProductComment onLayout={(e: any) => setCommentY(e.nativeEvent.layout.y + e.nativeEvent.layout.height)}>
292
+ <SectionTitle>
293
+ <OText style={theme.labels.middle as TextStyle}>{t('SPECIAL_COMMENT', 'Special comment')}</OText>
294
+ </SectionTitle>
295
+ <OInput
296
+ multiline
297
+ placeholder={t('SPECIAL_COMMENT', 'Special comment')}
298
+ value={productCart.comment}
299
+ onChange={(val: string) => handleChangeCommentState({ target: { value: val } })}
300
+ isDisabled={!(productCart && !isSoldOut && maxProductQuantity)}
301
+ style={styles.comment}
302
+ inputStyle={{ fontSize: 12, paddingBottom: 7, paddingTop: 17 }}
303
+ />
304
+ </ProductComment>
305
+ )}
304
306
  {productCart && !isSoldOut && maxProductQuantity > 0 && (
305
307
  <View style={{ paddingVertical: 4, marginBottom: 10 }}>
306
308
  <SectionTitle>
@@ -235,19 +235,21 @@ export const ProductOptionsUI = (props: any) => {
235
235
  </React.Fragment>
236
236
  )
237
237
  }))}
238
- <ProductComment>
239
- <SectionTitle>
240
- <OText style={theme.labels.middle}>{t('SPECIAL_COMMENT', 'Special comment')}</OText>
241
- </SectionTitle>
242
- <OInput
243
- multiline
244
- placeholder={t('SPECIAL_COMMENT', 'Special comment')}
245
- value={productCart.comment}
246
- onChange={(val: string) => handleChangeCommentState({ target: { value: val } })}
247
- isDisabled={!(productCart && !isSoldOut && maxProductQuantity)}
248
- style={{ ...styles.comment, borderColor: theme.colors.border }}
249
- />
250
- </ProductComment>
238
+ {!product?.hide_special_instructions && (
239
+ <ProductComment>
240
+ <SectionTitle>
241
+ <OText style={theme.labels.middle}>{t('SPECIAL_COMMENT', 'Special comment')}</OText>
242
+ </SectionTitle>
243
+ <OInput
244
+ multiline
245
+ placeholder={t('SPECIAL_COMMENT', 'Special comment')}
246
+ value={productCart.comment}
247
+ onChange={(val: string) => handleChangeCommentState({ target: { value: val } })}
248
+ isDisabled={!(productCart && !isSoldOut && maxProductQuantity)}
249
+ style={{ ...styles.comment, borderColor: theme.colors.border }}
250
+ />
251
+ </ProductComment>
252
+ )}
251
253
  </ProductEditions>
252
254
  )}
253
255
  </WrapContent>
@@ -438,19 +438,21 @@ export const ProductOptionsUI = (props: any) => {
438
438
  </React.Fragment>
439
439
  )
440
440
  }))}
441
- <ProductComment>
442
- <SectionTitle>
443
- <OText size={28} weight="bold">{t('SPECIAL_COMMENT', 'Special comment')}</OText>
444
- </SectionTitle>
445
- <OInput
446
- multiline
447
- placeholder={t('SPECIAL_COMMENT', 'Special comment')}
448
- value={productCart.comment}
449
- onChange={(val: string) => handleChangeCommentState({ target: { value: val } })}
450
- isDisabled={!(productCart && !isSoldOut && maxProductQuantity)}
451
- style={styles.comment}
452
- />
453
- </ProductComment>
441
+ {!product?.hide_special_instructions && (
442
+ <ProductComment>
443
+ <SectionTitle>
444
+ <OText size={28} weight="bold">{t('SPECIAL_COMMENT', 'Special comment')}</OText>
445
+ </SectionTitle>
446
+ <OInput
447
+ multiline
448
+ placeholder={t('SPECIAL_COMMENT', 'Special comment')}
449
+ value={productCart.comment}
450
+ onChange={(val: string) => handleChangeCommentState({ target: { value: val } })}
451
+ isDisabled={!(productCart && !isSoldOut && maxProductQuantity)}
452
+ style={styles.comment}
453
+ />
454
+ </ProductComment>
455
+ )}
454
456
  </ProductEditions>
455
457
  </WrapContent>
456
458
  </View>
@@ -28,6 +28,8 @@ import { HelpGuide } from './src/components/HelpGuide';
28
28
  import { HelpOrder } from './src/components/HelpOrder';
29
29
  import { NotFoundSource } from './src/components/NotFoundSource';
30
30
  import { OrderTypeSelector } from './src/components/OrderTypeSelector';
31
+ import { Wallets } from './src/components/Wallets';
32
+ import { PaymentOptionWallet } from './src/components/PaymentOptionWallet';
31
33
 
32
34
  import { Toast } from './src/components/shared/OToast';
33
35
  import {
@@ -86,6 +88,8 @@ export {
86
88
  HelpOrder,
87
89
  NotFoundSource,
88
90
  OrderTypeSelector,
91
+ Wallets,
92
+ PaymentOptionWallet,
89
93
 
90
94
  // OComponents
91
95
  Toast,
@@ -57,6 +57,7 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
57
57
  handleBusinessClick,
58
58
  paginationProps,
59
59
  handleChangeSearch,
60
+ businessId
60
61
  } = props;
61
62
 
62
63
  const theme = useTheme();
@@ -256,17 +257,20 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
256
257
  />
257
258
  </WrapMomentOption>
258
259
 
259
- <SearchBar
260
- onSearch={handleChangeSearch}
261
- searchValue={searchValue}
262
- lazyLoad
263
- isCancelXButtonShow={!!searchValue}
264
- borderStyle={styles.borderStyle}
265
- onCancel={() => handleChangeSearch('')}
266
- placeholder={t('SEARCH', 'Search')}
267
- height={26}
268
- inputStyle={{ ...styles.searchInput, ...Platform.OS === 'ios' ? {} : { paddingBottom: 4 } }}
269
- />
260
+ {!businessId && (
261
+ <SearchBar
262
+ onSearch={handleChangeSearch}
263
+ searchValue={searchValue}
264
+ lazyLoad
265
+ isCancelXButtonShow={!!searchValue}
266
+ borderStyle={styles.borderStyle}
267
+ onCancel={() => handleChangeSearch('')}
268
+ placeholder={t('SEARCH', 'Search')}
269
+ height={26}
270
+ inputStyle={{ ...styles.searchInput, ...Platform.OS === 'ios' ? {} : { paddingBottom: 4 } }}
271
+ />
272
+ )}
273
+
270
274
  </View>
271
275
  </OrderControlContainer>
272
276
  </HeaderWrapper>
@@ -277,7 +281,7 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
277
281
  />
278
282
  </OrderProgressWrapper>
279
283
  )}
280
- {!props.franchiseId && featuredBusiness && featuredBusiness.length > 0 && (
284
+ {!businessId && !props.franchiseId && featuredBusiness && featuredBusiness.length > 0 && (
281
285
  <FeaturedWrapper>
282
286
  <OText size={16} style={{ marginLeft: 40 }} weight={Platform.OS === 'ios' ? '600' : 'bold'}>{t('FEATURED_BUSINESS', 'Featured business')}</OText>
283
287
  <ScrollView
@@ -306,17 +310,19 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
306
310
  </FeaturedWrapper>
307
311
  )}
308
312
  <View style={{ height: 8, backgroundColor: theme.colors.backgroundGray100 }} />
309
- {!props.franchiseId && (
313
+ {!businessId && !props.franchiseId && (
310
314
  <HighestRatedBusinesses onBusinessClick={handleBusinessClick} navigation={navigation} />
311
315
  )}
312
316
  <View style={{ height: 8, backgroundColor: theme.colors.backgroundGray100 }} />
313
317
  <ListWrapper>
314
- <BusinessTypeFilter
315
- images={props.images}
316
- businessTypes={props.businessTypes}
317
- defaultBusinessType={props.defaultBusinessType}
318
- handleChangeBusinessType={handleChangeBusinessType}
319
- />
318
+ {!businessId && (
319
+ <BusinessTypeFilter
320
+ images={props.images}
321
+ businessTypes={props.businessTypes}
322
+ defaultBusinessType={props.defaultBusinessType}
323
+ handleChangeBusinessType={handleChangeBusinessType}
324
+ />
325
+ )}
320
326
  {!businessesList.loading && businessesList.businesses.length === 0 && (
321
327
  <NotFoundSource
322
328
  content={t(
@@ -23,6 +23,7 @@ import { PaymentOptions } from '../PaymentOptions';
23
23
  import { DriverTips } from '../DriverTips';
24
24
  import { NotFoundSource } from '../NotFoundSource';
25
25
  import { UserDetails } from '../UserDetails';
26
+ import { PaymentOptionWallet } from '../PaymentOptionWallet';
26
27
 
27
28
  import {
28
29
  ChContainer,
@@ -37,7 +38,8 @@ import {
37
38
  ChUserDetails,
38
39
  ChCart,
39
40
  DeliveryOptionsContainer,
40
- DeliveryOptionItem
41
+ DeliveryOptionItem,
42
+ WalletPaymentOptionContainer
41
43
  } from './styles';
42
44
  import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
43
45
 
@@ -504,6 +506,15 @@ const CheckoutUI = (props: any) => {
504
506
  </ChSection>
505
507
  )}
506
508
 
509
+ {!cartState.loading && cart && (
510
+ <WalletPaymentOptionContainer>
511
+ <PaymentOptionWallet
512
+ cart={cart}
513
+ />
514
+ </WalletPaymentOptionContainer>
515
+ )}
516
+
517
+
507
518
  {!cartState.loading && cart && (
508
519
  <ChSection>
509
520
  <ChCart>
@@ -543,8 +554,8 @@ const CheckoutUI = (props: any) => {
543
554
  )}
544
555
 
545
556
  {!cartState.loading && cart && (
546
- <ChSection style={{ paddingTop: 0, paddingBottom: 20, paddingHorizontal: 20 }}>
547
- <ChErrors>
557
+ <View>
558
+ <ChErrors style={{ marginBottom: 0 }}>
548
559
  {!cart?.valid_address && cart?.status !== 2 && (
549
560
  <OText
550
561
  color={theme.colors.error}
@@ -572,7 +583,7 @@ const CheckoutUI = (props: any) => {
572
583
  </OText>
573
584
  )}
574
585
  </ChErrors>
575
- </ChSection>
586
+ </View>
576
587
  )}
577
588
  <OModal
578
589
  open={openChangeStore && props.isFranchiseApp}
@@ -74,6 +74,10 @@ export const ChDriverTips = styled(ChPaymethods)``
74
74
 
75
75
  export const ChCart = styled(ChPaymethods)``
76
76
 
77
+ export const WalletPaymentOptionContainer = styled(ChPaymethods)`
78
+ padding-bottom: 0;
79
+ `
80
+
77
81
  export const ChPlaceOrderBtn = styled.View`
78
82
  width: 100%;
79
83
  display: flex;
@@ -99,4 +103,4 @@ export const DeliveryOptionItem = styled.View`
99
103
  align-items: center;
100
104
  flex-direction: row;
101
105
  background-color: ${(props : any) => props?.backgroundColor ?? '#fff'};
102
- `;
106
+ `;
@@ -48,8 +48,8 @@ export const Help = (props: HelpParams) => {
48
48
 
49
49
  <LastOrdersContainer>
50
50
  <OText size={18} weight={600}>{t('LAST_ORDERS', 'Last Orders')}</OText>
51
- <LastOrders onRedirect={onRedirect} />
51
+ <LastOrders businessId={props.businessId} onRedirect={onRedirect} />
52
52
  </LastOrdersContainer>
53
53
  </>
54
54
  )
55
- }
55
+ }
@@ -104,6 +104,15 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
104
104
 
105
105
  const { order, businessData } = props.order;
106
106
 
107
+ const walletName: any = {
108
+ cash: {
109
+ name: t('PAY_WITH_CASH_WALLET', 'Pay with Cash Wallet'),
110
+ },
111
+ credit_point: {
112
+ name: t('PAY_WITH_CREDITS_POINTS_WALLET', 'Pay with Credit Points Wallet'),
113
+ }
114
+ }
115
+
107
116
  const getOrderStatus = (s: string) => {
108
117
  const status = parseInt(s);
109
118
  const orderStatus = [
@@ -826,6 +835,51 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
826
835
  </OText>
827
836
  </Table>
828
837
  </Total>
838
+ {order?.payment_events?.length > 0 && (
839
+ <View style={{marginTop: 10}}>
840
+ <OText size={20} weight='bold' color={theme.colors.textNormal}>{t('PAYMENTS', 'Payments')}</OText>
841
+ <View
842
+ style={{
843
+ width: '100%',
844
+ marginTop: 10
845
+ }}
846
+ >
847
+ {order?.payment_events?.map((event: any) => (
848
+ <View
849
+ key={event.id}
850
+ style={{
851
+ display: 'flex',
852
+ flexDirection: 'row',
853
+ justifyContent: 'space-between',
854
+ alignItems: 'center',
855
+ marginBottom: 10
856
+ }}
857
+ >
858
+ <View
859
+ style={{
860
+ display: 'flex',
861
+ flexDirection: 'column',
862
+ }}
863
+ >
864
+ <OText>
865
+ {event?.wallet_event
866
+ ? walletName[event?.wallet_event?.wallet?.type]?.name
867
+ : event?.paymethod?.name}
868
+ </OText>
869
+ {event?.data?.charge_id && (
870
+ <OText>
871
+ {`${t('CODE', 'Code')}: ${event?.data?.charge_id}`}
872
+ </OText>
873
+ )}
874
+ </View>
875
+ <OText>
876
+ -{parsePrice(event.amount)}
877
+ </OText>
878
+ </View>
879
+ ))}
880
+ </View>
881
+ </View>
882
+ )}
829
883
  </OrderBill>
830
884
  </OrderContent>
831
885
  </>
@@ -193,13 +193,13 @@ const OrderProgressUI = (props: any) => {
193
193
  </View>
194
194
  </View>
195
195
  )}
196
- {!orderList?.loading && orderList?.orders?.length === 0 && (
196
+ {/* {!orderList?.loading && orderList?.orders?.length === 0 && (
197
197
  <NotFoundSource
198
198
  image={imageFails}
199
199
  content={t('NO_RESULTS_FOUND', 'Sorry, no results found')}
200
200
  conditioned
201
201
  />
202
- )}
202
+ )} */}
203
203
  </>
204
204
  )
205
205
  }
@@ -28,7 +28,6 @@ import { TouchableOpacity } from 'react-native';
28
28
 
29
29
  const OrderSummaryUI = (props: any) => {
30
30
  const {
31
- cart,
32
31
  changeQuantity,
33
32
  getProductMax,
34
33
  offsetDisabled,
@@ -76,6 +75,16 @@ const OrderSummaryUI = (props: any) => {
76
75
  }
77
76
  }
78
77
 
78
+ const cart = orderState?.carts?.[`businessId:${props.cart.business_id}`]
79
+
80
+ const walletName: any = {
81
+ cash: {
82
+ name: t('PAY_WITH_CASH_WALLET', 'Pay with Cash Wallet'),
83
+ },
84
+ credit_point: {
85
+ name: t('PAY_WITH_CREDITS_POINTS_WALLET', 'Pay with Credit Points Wallet'),
86
+ }
87
+ }
79
88
 
80
89
  return (
81
90
  <OSContainer>
@@ -205,7 +214,8 @@ const OrderSummaryUI = (props: any) => {
205
214
  height: 100,
206
215
  borderColor: theme.colors.border,
207
216
  paddingRight: 50,
208
- marginTop: 10
217
+ marginTop: 10,
218
+ borderRadius: 8
209
219
  }}
210
220
  multiline
211
221
  />
@@ -222,6 +232,52 @@ const OrderSummaryUI = (props: any) => {
222
232
  </View>
223
233
  </OSTable>
224
234
  )}
235
+ {cart?.payment_events?.length > 0 && (
236
+ <View
237
+ style={{
238
+ width: '100%',
239
+ marginTop: 20
240
+ }}
241
+ >
242
+ {cart?.payment_events?.map((event: any) => (
243
+ <View
244
+ key={event.id}
245
+ style={{
246
+ display: 'flex',
247
+ flexDirection: 'row',
248
+ justifyContent: 'space-between',
249
+ marginBottom: 10
250
+ }}
251
+ >
252
+ <OText>
253
+ {walletName[cart?.wallets?.find((wallet: any) => wallet.id === event.wallet_id)?.type]?.name}
254
+ </OText>
255
+ <OText>
256
+ -{parsePrice(event.amount)}
257
+ </OText>
258
+ </View>
259
+ ))}
260
+ <View
261
+ style={{
262
+ display: 'flex',
263
+ flexDirection: 'row',
264
+ justifyContent: 'space-between',
265
+ marginBottom: 10
266
+ }}
267
+ >
268
+ <OText
269
+ weight={'bold'}
270
+ >
271
+ {t('TOTAL_TO_PAY', 'Total to pay')}
272
+ </OText>
273
+ <OText
274
+ weight={'bold'}
275
+ >
276
+ {parsePrice(cart?.balance)}
277
+ </OText>
278
+ </View>
279
+ </View>
280
+ )}
225
281
  </OSBill>
226
282
  )}
227
283
  <OModal
@@ -0,0 +1,163 @@
1
+ import React, { useState, useEffect } from 'react'
2
+ import { Platform, StyleSheet, View } from 'react-native'
3
+ import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
4
+ import { useTheme } from 'styled-components/native'
5
+ import CheckBox from '@react-native-community/checkbox';
6
+ import {
7
+ PaymentOptionWallet as PaymentOptionWalletController,
8
+ useLanguage,
9
+ useUtils,
10
+ } from 'ordering-components/native'
11
+
12
+ import {
13
+ Container,
14
+ SectionLeft,
15
+ } from './styles'
16
+
17
+ import { OText } from '../shared'
18
+
19
+ const PaymentOptionWalletUI = (props: any) => {
20
+ const {
21
+ cart,
22
+ walletsState,
23
+ selectWallet,
24
+ deletetWalletSelected
25
+ } = props
26
+
27
+ const theme = useTheme()
28
+ const [, t] = useLanguage()
29
+ const [{ parsePrice }] = useUtils()
30
+
31
+ const styles = StyleSheet.create({
32
+ checkBoxStyle: {
33
+ width: 25,
34
+ height: 25,
35
+ }
36
+ });
37
+
38
+ const [checkedState, setCheckedState] = useState(
39
+ new Array(walletsState.result?.length).fill(false)
40
+ );
41
+
42
+ const creditBalance = (wallet: any) => ` = ${parsePrice((wallet.balance * wallet.redemption_rate) / 100)}`
43
+
44
+ const walletName: any = {
45
+ cash: {
46
+ name: t('PAY_WITH_CASH_WALLET', 'Pay with Cash Wallet'),
47
+ },
48
+ credit_point: {
49
+ name: t('PAY_WITH_CREDITS_POINTS_WALLET', 'Pay with Credit Points Wallet'),
50
+ }
51
+ }
52
+
53
+ const handleOnChange = (position: any, wallet: any) => {
54
+ const updatedCheckedState = checkedState.map((item, index) =>
55
+ index === position ? !item : item
56
+ );
57
+
58
+ if (!checkedState[position]) {
59
+ selectWallet(wallet)
60
+ } else {
61
+ deletetWalletSelected(wallet)
62
+ }
63
+
64
+ setCheckedState(updatedCheckedState);
65
+ };
66
+
67
+ useEffect(() => {
68
+ if (!walletsState.loading) {
69
+ setCheckedState(
70
+ walletsState.result.map((wallet: any) => {
71
+ return !!cart?.wallets?.find((w: any) => w.id === wallet.id)
72
+ })
73
+ )
74
+ }
75
+ }, [walletsState.result?.length])
76
+
77
+ return (
78
+ <>
79
+ {!walletsState.loading &&
80
+ !walletsState.error &&
81
+ walletsState.result?.length > 0 &&
82
+ (
83
+ <>
84
+ {walletsState.result?.map((wallet: any, idx: any) => wallet.valid && (
85
+ <Container
86
+ key={wallet.id}
87
+ isBottomBorder={idx === walletsState.result?.filter((wallet: any) => wallet.valid)?.length - 1}
88
+ >
89
+ <SectionLeft>
90
+ <CheckBox
91
+ value={checkedState[idx]}
92
+ onValueChange={() => handleOnChange(idx, wallet)}
93
+ disabled={(cart?.balance === 0 && !checkedState[idx]) || wallet.balance === 0 }
94
+ boxType={'square'}
95
+ tintColors={{
96
+ true: theme.colors.primary,
97
+ false: theme.colors.disabled
98
+ }}
99
+ tintColor={theme.colors.disabled}
100
+ onCheckColor={theme.colors.primary}
101
+ onTintColor={theme.colors.primary}
102
+ style={Platform.OS === 'ios' && styles.checkBoxStyle}
103
+ />
104
+ <View style={{ alignItems: 'baseline' }}>
105
+ <View>
106
+ <OText
107
+ style={((cart?.balance === 0 && !checkedState[idx]) || wallet.balance === 0) ?{
108
+ color: theme.colors.disabled
109
+ } : {}}
110
+ >
111
+ {walletName[wallet.type]?.name}
112
+ </OText>
113
+ </View>
114
+ </View>
115
+ </SectionLeft>
116
+
117
+ <View style={{maxWidth: '40%', alignItems: 'flex-end' }}>
118
+ {wallet.type === 'cash' && (
119
+ <OText>
120
+ {parsePrice(wallet?.balance)}
121
+ </OText>
122
+ )}
123
+ {wallet.type === 'credit_point' && (
124
+ <OText>
125
+ <OText color={theme.colors.primary} weight='bold'>
126
+ {`${wallet?.balance} ${t('POINTS', 'Points')}`}
127
+ </OText>
128
+ <OText>
129
+ {`${wallet.balance > 0 && creditBalance(wallet)}`}
130
+ </OText>
131
+ </OText>
132
+ )}
133
+ </View>
134
+ </Container>
135
+ ))}
136
+ </>
137
+ )}
138
+
139
+ {walletsState?.loading && (
140
+ <View>
141
+ {[...Array(2).keys()].map(i => (
142
+ <View style={{ marginBottom: 10 }} key={i}>
143
+ <Placeholder Animation={Fade}>
144
+ <PlaceholderLine width={100} height={40} style={{ marginBottom: 0, borderRadius: 8 }} />
145
+ </Placeholder>
146
+ </View>
147
+ ))}
148
+ </View>
149
+ )}
150
+ </>
151
+ )
152
+ }
153
+
154
+ export const PaymentOptionWallet = (props: any) => {
155
+ const paymentWalletProps = {
156
+ ...props,
157
+ UIComponent: PaymentOptionWalletUI
158
+ }
159
+
160
+ return (
161
+ <PaymentOptionWalletController {...paymentWalletProps} />
162
+ )
163
+ }
@@ -0,0 +1,38 @@
1
+ import styled, { css } from 'styled-components/native'
2
+
3
+ export const Container = styled.View`
4
+ width: 100%;
5
+ display: flex;
6
+ padding: 20px 0;
7
+ margin-top: 10px;
8
+ flex-direction: row;
9
+ justify-content: space-between;
10
+ align-items: center;
11
+ border-top-width: 1px;
12
+ border-top-color: ${(props: any) => props.theme.colors.backgroundGray200};
13
+ ${(props: any) => props.isBottomBorder && css`
14
+ border-bottom-width: 1px;
15
+ border-bottom-color: ${(props: any) => props.theme.colors.backgroundGray200};
16
+ `}
17
+ `
18
+
19
+ export const SectionLeft = styled.View`
20
+ max-width: 55%;
21
+ display: flex;
22
+ flex-direction: row;
23
+ align-items: center;
24
+ justify-content: center;
25
+ `
26
+
27
+ export const SectionLeftText = styled.View`
28
+ alignSelf: flex-start;
29
+ display: flex;
30
+ flex-direction: column;
31
+ flex-wrap: wrap;
32
+ `
33
+
34
+ export const SectionWrapper = styled.View`
35
+ padding-top: 10px;
36
+ display: flex;
37
+ flex-direction: column;
38
+ `
@@ -663,25 +663,27 @@ export const ProductOptionsUI = (props: any) => {
663
663
  )}
664
664
  </>
665
665
  )}
666
- <ProductComment>
667
- <SectionTitle>
668
- <OText size={16} weight={'600'} lineHeight={24}>
669
- {t('SPECIAL_COMMENT', 'Special comment')}
670
- </OText>
671
- </SectionTitle>
672
- <OInput
673
- multiline
674
- placeholder={t('SPECIAL_COMMENT', 'Special comment')}
675
- value={productCart.comment}
676
- onChange={(val: string) =>
677
- handleChangeCommentState({ target: { value: val } })
678
- }
679
- isDisabled={
680
- !(productCart && !isSoldOut && maxProductQuantity)
681
- }
682
- style={styles.comment}
683
- />
684
- </ProductComment>
666
+ {!product?.hide_special_instructions && (
667
+ <ProductComment>
668
+ <SectionTitle>
669
+ <OText size={16} weight={'600'} lineHeight={24}>
670
+ {t('SPECIAL_COMMENT', 'Special comment')}
671
+ </OText>
672
+ </SectionTitle>
673
+ <OInput
674
+ multiline
675
+ placeholder={t('SPECIAL_COMMENT', 'Special comment')}
676
+ value={productCart.comment}
677
+ onChange={(val: string) =>
678
+ handleChangeCommentState({ target: { value: val } })
679
+ }
680
+ isDisabled={
681
+ !(productCart && !isSoldOut && maxProductQuantity)
682
+ }
683
+ style={styles.comment}
684
+ />
685
+ </ProductComment>
686
+ )}
685
687
  </ProductEditions>
686
688
  )}
687
689
  </WrapContent>
@@ -14,6 +14,7 @@ import { ProfileParams } from '../../types';
14
14
  import { LogoutButton } from '../LogoutButton'
15
15
  import { LanguageSelector } from '../LanguageSelector'
16
16
  import MessageCircle from 'react-native-vector-icons/AntDesign'
17
+ import Ionicons from 'react-native-vector-icons/Ionicons'
17
18
 
18
19
  import {
19
20
  OIcon,
@@ -160,6 +161,10 @@ const ProfileListUI = (props: ProfileParams) => {
160
161
  <MessageCircle name='message1' style={styles.messageIconStyle} color={theme.colors.textNormal} />
161
162
  <OText size={14} lineHeight={24} weight={'400'} color={theme.colors.textNormal}>{t('MESSAGES', 'Messages')}</OText>
162
163
  </ListItem>
164
+ <ListItem onPress={() => onRedirect('Wallets', { isFromProfile: true, isGoBack: true })} activeOpacity={0.7}>
165
+ <Ionicons name='wallet-outline' style={styles.messageIconStyle} color={theme.colors.textNormal} />
166
+ <OText size={14} lineHeight={24} weight={'400'} color={theme.colors.textNormal}>{t('WALLETS', 'Wallets')}</OText>
167
+ </ListItem>
163
168
  <ListItem onPress={() => navigation.navigate('Help', {})} activeOpacity={0.7}>
164
169
  <OIcon src={theme.images.general.ic_help} width={16} color={theme.colors.textNormal} style={{ marginEnd: 14 }} />
165
170
  <OText size={14} lineHeight={24} weight={'400'} color={theme.colors.textNormal}>{t('HELP', 'Help')}</OText>
@@ -0,0 +1,68 @@
1
+ import React from 'react'
2
+ import { useTheme } from 'styled-components/native'
3
+ import { useLanguage, useUtils } from 'ordering-components/native'
4
+
5
+ import {
6
+ Container,
7
+ DateBlock,
8
+ MessageBlock,
9
+ DescriptionBlock,
10
+ Dot
11
+ } from './styles'
12
+ import { OIcon, OText } from '../shared';
13
+
14
+ export const WalletTransactionItem = (props: any) => {
15
+ const {
16
+ item,
17
+ idx,
18
+ type
19
+ } = props
20
+
21
+ const theme = useTheme()
22
+ const [{ parsePrice, parseDate }] = useUtils()
23
+ const [, t] = useLanguage()
24
+
25
+ const LANG_EVENT_KEY = `WALLET_${type.toUpperCase()}_${item?.event.toUpperCase()}_${item?.event_type.toUpperCase()}_${item?.amount >= 0 ? 'POSITIVE': 'NEGATIVE'}`
26
+ const lang_event_text = !!item?.event?.order_id
27
+ ? `:author ${item?.amount >= 0 ? 'add' : 'reduce'} money in Order No. :order_id`
28
+ : `:author ${item?.amount >= 0 ? 'add' : 'reduce'} money`
29
+
30
+ return (
31
+ <Container>
32
+ <Dot isTop={idx === 0} />
33
+ <DateBlock>
34
+ <OText color={theme.colors.disabled}>{parseDate(item?.created_at)}</OText>
35
+ <OText
36
+ style={{
37
+ color: item?.amount > 0 && theme.colors.primary,
38
+ fontWeight: 'bold'
39
+ }}
40
+ >
41
+ {item?.amount > 0 && '+ '}{parsePrice(item?.amount)}
42
+ </OText>
43
+ </DateBlock>
44
+ <MessageBlock>
45
+ <OText>
46
+ {t(LANG_EVENT_KEY, lang_event_text)
47
+ .replace(':author', item?.event?.author?.name ?? '')
48
+ .replace(':order_id', item?.event?.order_id ?? '')}
49
+ </OText>
50
+ </MessageBlock>
51
+ {!!item?.description && (
52
+ <DescriptionBlock>
53
+ <OText>{item?.description}</OText>
54
+ </DescriptionBlock>
55
+ )}
56
+ {!!item?.code && (
57
+ <DescriptionBlock>
58
+ <OText weight={'bold'}>
59
+ {t('CODE', 'Code')}
60
+ <OText weight={'100'}>
61
+ {': '}{item?.code}
62
+ </OText>
63
+ </OText>
64
+ </DescriptionBlock>
65
+ )}
66
+ </Container>
67
+ )
68
+ }
@@ -0,0 +1,37 @@
1
+ import styled from 'styled-components/native'
2
+
3
+ export const Container = styled.View`
4
+ display: flex;
5
+ flex-direction: column;
6
+ margin-bottom: 20px;
7
+ position: relative;
8
+ padding-left: 10px;
9
+ `
10
+
11
+ export const DateBlock = styled.View`
12
+ display: flex;
13
+ flex-direction: row;
14
+ justify-content: space-between;
15
+ align-items: center;
16
+ `
17
+
18
+ export const MessageBlock = styled.View`
19
+ display: flex;
20
+ font-size: 14px;
21
+ `
22
+
23
+ export const Dot = styled.View`
24
+ position: absolute;
25
+ top: ${(props: any) => props.isTop ? 0 : 6}px;
26
+ left: -4px;
27
+ width: 6px;
28
+ height: 6px;
29
+ border-radius: 50px;
30
+ background-color: ${(props: any) => props.theme.colors.disabled};
31
+ `
32
+
33
+ export const DescriptionBlock = styled(MessageBlock)`
34
+ display: flex;
35
+ flex-direction: row;
36
+ flex-wrap: wrap;
37
+ `
@@ -0,0 +1,204 @@
1
+ import React, { useState } from 'react'
2
+ import { Pressable, View } from 'react-native';
3
+ import { useTheme } from 'styled-components/native'
4
+ import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
5
+ import {
6
+ WalletList,
7
+ useLanguage,
8
+ useUtils,
9
+ useConfig
10
+ } from 'ordering-components/native'
11
+
12
+ import {
13
+ Container,
14
+ BalanceElement,
15
+ TransactionsWrapper,
16
+ OTabs,
17
+ OTab,
18
+ SectionContent
19
+ } from './styles'
20
+
21
+ import NavBar from '../NavBar'
22
+ import { OIcon, OText } from '../shared';
23
+ import { NotFoundSource } from '../NotFoundSource';
24
+ import { WalletTransactionItem } from '../WalletTransactionItem'
25
+
26
+ const WalletsUI = (props: any) => {
27
+ const {
28
+ navigation,
29
+ walletList,
30
+ transactionsList,
31
+ setWalletSelected
32
+ } = props
33
+
34
+ const [, t] = useLanguage()
35
+ const theme = useTheme()
36
+ const [{ parsePrice, parseDate }] = useUtils()
37
+ const [{ configs }] = useConfig()
38
+
39
+ const [tabSelected, setTabSelected] = useState('cash')
40
+
41
+ const currentWalletSelected = (walletList.wallets?.length > 0 && walletList.wallets?.find((w: any) => w.type === tabSelected)) ?? null
42
+
43
+ const walletName: any = {
44
+ cash: {
45
+ name: t('CASH_WALLET', 'Cash Wallet'),
46
+ value: 0
47
+ },
48
+ credit_point: {
49
+ name: t('CREDITS_POINTS_WALLET', 'Credit Points Wallet'),
50
+ value: 1
51
+ }
52
+ }
53
+
54
+ const handleChangeTab = (wallet: any) => {
55
+ setTabSelected(wallet.type)
56
+ setWalletSelected(wallet.id)
57
+ }
58
+
59
+ const goToBack = () => {
60
+ navigation?.canGoBack() && navigation.goBack()
61
+ }
62
+
63
+ return (
64
+ <Container>
65
+ <NavBar
66
+ title={t('WALLETS', 'Wallets')}
67
+ titleAlign={'center'}
68
+ onActionLeft={goToBack}
69
+ showCall={false}
70
+ paddingTop={10}
71
+ btnStyle={{ paddingLeft: 0 }}
72
+ />
73
+
74
+ {!walletList.loading &&
75
+ !walletList.error &&
76
+ walletList.wallets?.length > 0 &&
77
+ (
78
+ <>
79
+ <OTabs>
80
+ {walletList.wallets?.map((wallet: any) =>(
81
+ <Pressable
82
+ key={wallet.id}
83
+ onPress={() => handleChangeTab(wallet)}
84
+ >
85
+ <OTab>
86
+ <OText size={18} color={tabSelected === wallet.type ? theme.colors.primary : theme.colors.disabled}>
87
+ {walletName[wallet.type]?.name}
88
+ </OText>
89
+ </OTab>
90
+ </Pressable>
91
+ ))}
92
+ </OTabs>
93
+
94
+ <SectionContent>
95
+ <BalanceElement>
96
+ <OText size={20} style={{fontWeight: '600'}}>
97
+ {currentWalletSelected?.type === 'cash'
98
+ ? parsePrice(currentWalletSelected?.balance)
99
+ : currentWalletSelected?.balance
100
+ }
101
+ </OText>
102
+ <OText style={{ paddingLeft: 5 }}>
103
+ {currentWalletSelected?.type === 'cash'
104
+ ? configs?.stripe_currency?.value
105
+ : t('POINTS', 'Points')}
106
+ </OText>
107
+ </BalanceElement>
108
+ {console.log(transactionsList)}
109
+
110
+ <View style={{ marginTop: 20, width: '100%', paddingHorizontal: 1, paddingBottom: 40 }}>
111
+ {!transactionsList?.loading &&
112
+ !transactionsList?.error &&
113
+ transactionsList.list?.[`wallet:${currentWalletSelected?.id}`]?.length > 0 &&
114
+ (
115
+ <>
116
+ <OText style={{fontSize: 20}}>
117
+ {t('TRANSACTIONS_HISTORY', 'Transactions history')}
118
+ </OText>
119
+ <TransactionsWrapper>
120
+ {transactionsList.list?.[`wallet:${currentWalletSelected?.id}`]?.map((transaction: any, i: number) =>(
121
+ <WalletTransactionItem
122
+ idx={i}
123
+ type={currentWalletSelected?.type}
124
+ key={transaction.id}
125
+ item={transaction}
126
+ />
127
+ ))}
128
+ </TransactionsWrapper>
129
+ </>
130
+ )}
131
+
132
+ {(transactionsList?.loading || !transactionsList.list?.[`wallet:${currentWalletSelected?.id}`]) && (
133
+ <View>
134
+ {[...Array(4).keys()].map(i => (
135
+ <View style={{ marginBottom: 10 }} key={i}>
136
+ <Placeholder Animation={Fade}>
137
+ <PlaceholderLine width={100} height={100} style={{ marginBottom: 0, borderRadius: 8 }} />
138
+ </Placeholder>
139
+ </View>
140
+ ))}
141
+ </View>
142
+ )}
143
+
144
+ {!(transactionsList?.loading && transactionsList.list?.[`wallet:${currentWalletSelected?.id}`]) &&
145
+ (transactionsList?.error ||
146
+ !transactionsList.list?.[`wallet:${currentWalletSelected?.id}`]?.length) &&
147
+ (
148
+ <NotFoundSource
149
+ content={transactionsList?.error
150
+ ? t('ERROR_NOT_FOUND_TRANSACTIONS', 'Sorry, an error has occurred')
151
+ : t('NOT_FOUND_TRANSACTIONS', 'No transactions to show at this time.')
152
+ }
153
+ />
154
+ )}
155
+ </View>
156
+ </SectionContent>
157
+ </>
158
+ )}
159
+
160
+ {walletList?.loading && (
161
+ <>
162
+ <View>
163
+ <Placeholder Animation={Fade}>
164
+ <PlaceholderLine width={100} height={40} style={{ marginBottom: 0 }} />
165
+ </Placeholder>
166
+ </View>
167
+ <View style={{ marginTop: 10, marginBottom: 20 }}>
168
+ <Placeholder Animation={Fade}>
169
+ <PlaceholderLine width={100} height={40} style={{ marginBottom: 0 }} />
170
+ </Placeholder>
171
+ </View>
172
+ <View>
173
+ {[...Array(4).keys()].map(i => (
174
+ <View style={{ marginBottom: 10 }} key={i}>
175
+ <Placeholder Animation={Fade}>
176
+ <PlaceholderLine width={100} height={60} style={{ marginBottom: 0 }} />
177
+ </Placeholder>
178
+ </View>
179
+ ))}
180
+ </View>
181
+ </>
182
+ )}
183
+
184
+ {!walletList?.loading && (walletList?.error || !walletList?.wallets?.length) && (
185
+ <NotFoundSource
186
+ content={walletList?.error
187
+ ? t('ERROR_NOT_FOUND_WALLETS', 'Sorry, an error has occurred')
188
+ : t('NOT_FOUND_WALLETS', 'No wallets to show at this time.')
189
+ }
190
+ />
191
+ )}
192
+ </Container>
193
+ )
194
+ }
195
+
196
+ export const Wallets = (props: any) => {
197
+ const walletsProps = {
198
+ ...props,
199
+ UIComponent: WalletsUI
200
+ }
201
+ return (
202
+ <WalletList {...walletsProps} />
203
+ )
204
+ }
@@ -0,0 +1,43 @@
1
+ import styled from 'styled-components/native'
2
+
3
+ export const Container = styled.View`
4
+ display: flex;
5
+ flex-direction: column;
6
+ `
7
+
8
+ export const SectionContent = styled.View`
9
+ width: 100%;
10
+ display: flex;
11
+ flex-direction: column;
12
+ align-items: center;
13
+ justify-content: center;
14
+ margin-top: 20px;
15
+ `
16
+
17
+ export const TransactionsWrapper = styled.View`
18
+ display: flex;
19
+ flex-direction: column;
20
+ border-left-width: 2px;
21
+ border-left-color: ${(props: any) => props.theme.colors.disabled};
22
+ `
23
+
24
+ export const BalanceElement = styled.View`
25
+ width: 100%;
26
+ padding: 10px 0;
27
+ display: flex;
28
+ flex-direction: row;
29
+ justify-content: center;
30
+ align-items: flex-end;
31
+ background-color: ${(props: any) => props.theme.colors.backgroundGray100};
32
+ border-radius: 8px;
33
+ `
34
+
35
+ export const OTabs = styled.View`
36
+ flex-direction: row;
37
+ width: 100%;
38
+ flex-wrap: wrap;
39
+ `;
40
+
41
+ export const OTab = styled.View`
42
+ padding-horizontal: 10px;
43
+ `;
@@ -129,6 +129,7 @@ export interface BusinessesListingParams {
129
129
  businessTypes?: any;
130
130
  defaultBusinessType?: any;
131
131
  franchiseId?: any;
132
+ businessId?: any;
132
133
  }
133
134
  export interface HighestRatedBusinessesParams {
134
135
  businessesList: { businesses: Array<any>, loading: boolean, error: null | string };
@@ -344,8 +345,8 @@ export interface MessagesParams {
344
345
  onClose?: () => void,
345
346
  isMeesageListing?: boolean,
346
347
  setCanRead?: any,
347
- business: boolean,
348
- driver: boolean,
348
+ business?: boolean,
349
+ driver?: boolean,
349
350
  onMessages?: any
350
351
  }
351
352
  export interface ViewInterface {
@@ -455,6 +456,7 @@ export interface GoogleMapsParams {
455
456
 
456
457
  export interface HelpParams {
457
458
  navigation: any;
459
+ businessId?: any;
458
460
  }
459
461
 
460
462
  export interface LastOrdersParams {
@@ -527,34 +527,35 @@ export const ProductOptionsUI = (props: any) => {
527
527
  );
528
528
  }))}
529
529
  </View>
530
-
531
- <ProductComment>
532
- <SectionTitle>
533
- <OText size={16} weight={'600'} lineHeight={24}>
534
- {t('SPECIAL_COMMENT', 'Special comment')}
535
- </OText>
536
- </SectionTitle>
537
- <OInput
538
- multiline={true}
539
- numberOfLines={10}
540
- placeholder={t('SPECIAL_COMMENT', 'Special comment')}
541
- value={productCart.comment}
542
- onChange={(val: string) =>
543
- handleChangeCommentState({ target: { value: val } })
544
- }
545
- isDisabled={
546
- !(productCart && !isSoldOut && maxProductQuantity)
547
- }
548
- style={{
549
- height: 100,
550
- justifyContent: "flex-end",
551
- alignItems: 'flex-start',
552
- borderWidth: 1,
553
- borderRadius: 8,
554
- borderColor: theme.colors.border,
555
- }}
556
- />
557
- </ProductComment>
530
+ {!product?.hide_special_instructions && (
531
+ <ProductComment>
532
+ <SectionTitle>
533
+ <OText size={16} weight={'600'} lineHeight={24}>
534
+ {t('SPECIAL_COMMENT', 'Special comment')}
535
+ </OText>
536
+ </SectionTitle>
537
+ <OInput
538
+ multiline={true}
539
+ numberOfLines={10}
540
+ placeholder={t('SPECIAL_COMMENT', 'Special comment')}
541
+ value={productCart.comment}
542
+ onChange={(val: string) =>
543
+ handleChangeCommentState({ target: { value: val } })
544
+ }
545
+ isDisabled={
546
+ !(productCart && !isSoldOut && maxProductQuantity)
547
+ }
548
+ style={{
549
+ height: 100,
550
+ justifyContent: "flex-end",
551
+ alignItems: 'flex-start',
552
+ borderWidth: 1,
553
+ borderRadius: 8,
554
+ borderColor: theme.colors.border,
555
+ }}
556
+ />
557
+ </ProductComment>
558
+ )}
558
559
  </ProductEditions>
559
560
  )}
560
561
  </WrapContent>
@@ -327,19 +327,21 @@ export const ProductOptionsUI = (props: any) => {
327
327
  </React.Fragment>
328
328
  )
329
329
  }))}
330
- <ProductComment>
331
- <SectionTitle>
332
- <OText size={16}>{t('SPECIAL_COMMENT', 'Special comment')}</OText>
333
- </SectionTitle>
334
- <OInput
335
- multiline
336
- placeholder={t('SPECIAL_COMMENT', 'Special comment')}
337
- value={productCart.comment}
338
- onChange={(val: string) => handleChangeCommentState({ target: { value: val } })}
339
- isDisabled={!(productCart && !isSoldOut && maxProductQuantity)}
340
- style={styles.comment}
341
- />
342
- </ProductComment>
330
+ {!product?.hide_special_instructions && (
331
+ <ProductComment>
332
+ <SectionTitle>
333
+ <OText size={16}>{t('SPECIAL_COMMENT', 'Special comment')}</OText>
334
+ </SectionTitle>
335
+ <OInput
336
+ multiline
337
+ placeholder={t('SPECIAL_COMMENT', 'Special comment')}
338
+ value={productCart.comment}
339
+ onChange={(val: string) => handleChangeCommentState({ target: { value: val } })}
340
+ isDisabled={!(productCart && !isSoldOut && maxProductQuantity)}
341
+ style={styles.comment}
342
+ />
343
+ </ProductComment>
344
+ )}
343
345
  </ProductEditions>
344
346
  )}
345
347
  </WrapContent>