ordering-ui-react-native 0.14.11 → 0.14.15

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 (30) hide show
  1. package/package.json +1 -1
  2. package/themes/business/src/components/MessagesOption/index.tsx +0 -1
  3. package/themes/business/src/components/NewOrderNotification/index.tsx +45 -13
  4. package/themes/business/src/components/OrdersOption/index.tsx +3 -1
  5. package/themes/doordash/src/components/BusinessProductsListing/index.tsx +4 -0
  6. package/themes/doordash/src/components/Home/index.tsx +1 -1
  7. package/themes/doordash/src/components/LoginForm/index.tsx +2 -1
  8. package/themes/doordash/src/components/Messages/index.tsx +24 -7
  9. package/themes/doordash/src/components/SignupForm/index.tsx +2 -1
  10. package/themes/doordash/src/components/UserFormDetails/index.tsx +2 -1
  11. package/themes/original/src/components/BusinessBasicInformation/index.tsx +1 -1
  12. package/themes/original/src/components/BusinessMenuList/index.tsx +2 -2
  13. package/themes/original/src/components/BusinessPreorder/index.tsx +2 -2
  14. package/themes/original/src/components/BusinessProductsList/index.tsx +12 -8
  15. package/themes/original/src/components/BusinessProductsListing/index.tsx +1 -0
  16. package/themes/original/src/components/BusinessReviews/index.tsx +14 -9
  17. package/themes/original/src/components/Cart/index.tsx +17 -17
  18. package/themes/original/src/components/Checkout/index.tsx +48 -51
  19. package/themes/original/src/components/DriverTips/index.tsx +28 -31
  20. package/themes/original/src/components/FloatingButton/index.tsx +2 -1
  21. package/themes/original/src/components/Messages/index.tsx +6 -2
  22. package/themes/original/src/components/OrderSummary/index.tsx +1 -1
  23. package/themes/original/src/components/ProductForm/index.tsx +2 -1
  24. package/themes/original/src/components/ProductItemAccordion/index.tsx +5 -4
  25. package/themes/original/src/components/ProductItemAccordion/styles.tsx +1 -1
  26. package/themes/original/src/components/ProductOptionSubOption/styles.tsx +1 -1
  27. package/themes/original/src/components/SingleProductCard/index.tsx +19 -2
  28. package/themes/original/src/components/SingleProductCard/styles.tsx +4 -0
  29. package/themes/original/src/components/UpsellingProducts/index.tsx +19 -21
  30. package/themes/original/src/types/index.tsx +4 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ordering-ui-react-native",
3
- "version": "0.14.11",
3
+ "version": "0.14.15",
4
4
  "description": "Reusable components made in react native",
5
5
  "main": "src/index.tsx",
6
6
  "author": "ordering.inc",
@@ -12,7 +12,6 @@ import { Placeholder, PlaceholderLine, Fade } from 'rn-placeholder';
12
12
  import { OText, OButton } from '../shared';
13
13
  import { NotFoundSource } from '../NotFoundSource';
14
14
  import { PreviousMessages } from '../PreviousMessages';
15
- // import { Contacts } from '../Contacts';
16
15
  import { FiltersTab, TabsContainer, TagsContainer, Tag } from './styles';
17
16
  import { MessagesOptionParams } from '../../types';
18
17
  import { useDeviceOrientation } from '../../../../../src/hooks/DeviceOrientation';
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useEffect, useCallback } from 'react'
2
- import { useEvent, useLanguage, useUtils, useSession, useApi } from 'ordering-components/native'
2
+ import { useEvent, useLanguage, useUtils, useSession, useApi, NewOrderNotification as NewOrderNotificationController } from 'ordering-components/native'
3
3
  import { View, Modal, StyleSheet, TouchableOpacity, Dimensions } from 'react-native'
4
4
  import { OText, OIcon } from '../shared'
5
5
  import { useTheme } from 'styled-components/native'
@@ -13,7 +13,7 @@ Sound.setCategory('Playback')
13
13
 
14
14
  const windowWidth = Dimensions.get('screen').width
15
15
 
16
- export const NewOrderNotification = (props: any) => {
16
+ const NewOrderNotificationUI = (props: any) => {
17
17
  const [events] = useEvent()
18
18
  const theme = useTheme()
19
19
  const [, t] = useLanguage()
@@ -23,6 +23,7 @@ export const NewOrderNotification = (props: any) => {
23
23
  const { getCurrentLocation } = useLocation();
24
24
  const [modalOpen, setModalOpen] = useState(false)
25
25
  const [newOrderId, setNewOrderId] = useState(null)
26
+ const [messageOrderId, setMessageOrderId] = useState(null)
26
27
  const [soundTimeout, setSoundTimeout] = useState<any>(null)
27
28
  const [isFocused, setIsFocused] = useState(false)
28
29
 
@@ -34,7 +35,6 @@ export const NewOrderNotification = (props: any) => {
34
35
  console.log('loaded successfully');
35
36
  });
36
37
 
37
-
38
38
  const handlePlayNotificationSound = () => {
39
39
  let times = 0
40
40
  const _timeout = setInterval(function () {
@@ -57,6 +57,8 @@ export const NewOrderNotification = (props: any) => {
57
57
  const handleCloseModal = () => {
58
58
  clearInterval(soundTimeout)
59
59
  setModalOpen(false)
60
+ setNewOrderId(null)
61
+ setMessageOrderId(null)
60
62
  }
61
63
 
62
64
  const handleNotification = (order: any) => {
@@ -66,10 +68,20 @@ export const NewOrderNotification = (props: any) => {
66
68
  setNewOrderId(order.id)
67
69
  }
68
70
 
71
+ const handleMessageNotification = (message: any) => {
72
+ const { order_id: orderId } = message;
73
+ if (!modalOpen) setModalOpen(true)
74
+ clearInterval(soundTimeout)
75
+ handlePlayNotificationSound()
76
+ setMessageOrderId(orderId)
77
+ }
78
+
69
79
  useEffect(() => {
70
- events.on('order_added', handleNotification)
80
+ events.on('order_added_noification', handleNotification)
81
+ events.on('message_added_noification', handleMessageNotification)
71
82
  return () => {
72
- events.off('order_added', handleNotification)
83
+ events.off('order_added_noification', handleNotification)
84
+ events.off('message_added_noification', handleMessageNotification)
73
85
  }
74
86
  }, [])
75
87
 
@@ -97,9 +109,9 @@ export const NewOrderNotification = (props: any) => {
97
109
 
98
110
  useEffect(() => {
99
111
  if (user?.level !== 4) return
100
- events.on('order_updated', handleUpdateOrder)
112
+ events.on('order_updated_noification', handleUpdateOrder)
101
113
  return () => {
102
- events.off('order_updated', handleUpdateOrder)
114
+ events.off('order_updated_noification', handleUpdateOrder)
103
115
  }
104
116
  }, [handleUpdateOrder, user])
105
117
 
@@ -149,12 +161,23 @@ export const NewOrderNotification = (props: any) => {
149
161
  width={250}
150
162
  height={200}
151
163
  />
152
- <OText
153
- color={theme.colors.textGray}
154
- mBottom={15}
155
- >
156
- {t('ORDER_N_ORDERED', 'Order #_order_id_ has been ordered.').replace('_order_id_', newOrderId)}
157
- </OText>
164
+ {newOrderId && (
165
+ <OText
166
+ color={theme.colors.textGray}
167
+ mBottom={15}
168
+ >
169
+ {t('ORDER_N_ORDERED', 'Order #_order_id_ has been ordered.').replace('_order_id_', newOrderId)}
170
+ </OText>
171
+ )}
172
+
173
+ {messageOrderId && (
174
+ <OText
175
+ color={theme.colors.textGray}
176
+ mBottom={15}
177
+ >
178
+ {t('ORDER_N_UNREAD_MESSAGES', 'Order #_order_id_ has unread messages.').replace('_order_id_', messageOrderId)}
179
+ </OText>
180
+ )}
158
181
  </View>
159
182
  </NotificationContainer>
160
183
  </Modal>
@@ -178,3 +201,12 @@ const styles = StyleSheet.create({
178
201
  top: 20
179
202
  }
180
203
  })
204
+
205
+ export const NewOrderNotification = (props: any) => {
206
+ const newOrderNotificationProps = {
207
+ ...props,
208
+ UIComponent: NewOrderNotificationUI
209
+ };
210
+
211
+ return <NewOrderNotificationController {...newOrderNotificationProps} />;
212
+ };
@@ -6,6 +6,7 @@ import FeatherIcon from 'react-native-vector-icons/Feather';
6
6
  import FontistoIcon from 'react-native-vector-icons/Fontisto'
7
7
  import { useTheme } from 'styled-components/native';
8
8
  import { DeviceOrientationMethods } from '../../../../../src/hooks/DeviceOrientation'
9
+ import { NewOrderNotification } from '../NewOrderNotification';
9
10
 
10
11
  import { OText, OButton, OModal, OIconButton, OInput, OIcon } from '../shared';
11
12
  import { NotFoundSource } from '../NotFoundSource';
@@ -326,7 +327,7 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
326
327
  nestedScrollEnabled={true}
327
328
  >
328
329
  <TabsContainer>
329
- {isLogisticActivated && (
330
+ {(isLogisticActivated && !isBusinessApp) && (
330
331
  <Pressable
331
332
  style={styles.pressable}
332
333
  onPress={() => setCurrentTabSelected('logisticOrders')}>
@@ -550,6 +551,7 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
550
551
  </View>
551
552
  {/* </GestureRecognizer> */}
552
553
 
554
+ <NewOrderNotification />
553
555
  {openModal && (
554
556
  <OModal open={openModal} entireModal customClose>
555
557
  <ModalContainer
@@ -204,6 +204,10 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
204
204
  }
205
205
  }, [])
206
206
 
207
+ useEffect(() => {
208
+ isKeyboardOpen && Platform.OS === 'android' && cartRef?.current?.scrollToEnd()
209
+ }, [isKeyboardOpen, cartRef?.current])
210
+
207
211
  return (
208
212
  <>
209
213
  <Animated.View style={{ flex: 1, backgroundColor: theme.colors.white, position: 'absolute', width: '100%', top: top, zIndex: 1 }}>
@@ -182,7 +182,7 @@ export const Home = (props: any) => {
182
182
  </TouchableOpacity>
183
183
  </View>
184
184
 
185
- <OModal entireModal customClose transition={'pageSheet'} open={isAuth} onClose={() => setAuthState(false)} style={{borderRadius: 7.6}}>
185
+ <OModal overScreen={Platform.OS === 'ios'} entireModal customClose transition={'pageSheet'} open={isAuth} onClose={() => setAuthState(false)} style={{borderRadius: 7.6}}>
186
186
  <View style={styles.authHeader}>
187
187
  <TouchableOpacity onPress={() => setAuthState(false)} style={{}}>
188
188
  <OIcon src={theme.images.general.close} width={16} />
@@ -410,7 +410,8 @@ const LoginFormUI = (props: LoginParams) => {
410
410
  textInputProps={{
411
411
  returnKeyType: 'next',
412
412
  onSubmitEditing: () => inputRef?.current?.focus?.(),
413
- style: { borderWidth: 0, fontSize: 12 }
413
+ style: { borderWidth: 0, fontSize: 12 },
414
+ maxLength: 10
414
415
  }}
415
416
  textWrapStyle={{ borderColor: theme.colors.clear, borderWidth: 0, height: 40, paddingStart: 0 }}
416
417
  />
@@ -9,6 +9,8 @@ import { OIcon, OIconButton, OText, OButton } from '../shared'
9
9
  import { TouchableOpacity, ActivityIndicator, StyleSheet, View, Platform, Keyboard, I18nManager } from 'react-native'
10
10
  import { Header, TitleHeader, Wrapper, QuickMessageContainer } from './styles'
11
11
  import { MessagesParams } from '../../types'
12
+ import { useWindowDimensions } from 'react-native'
13
+ import { useSafeAreaInsets } from 'react-native-safe-area-context'
12
14
 
13
15
  const MessagesUI = (props: MessagesParams) => {
14
16
 
@@ -42,6 +44,9 @@ const MessagesUI = (props: MessagesParams) => {
42
44
 
43
45
  const [formattedMessages, setFormattedMessages] = useState<Array<any>>([])
44
46
  const [isKeyboardShow, setIsKeyboardShow] = useState(false)
47
+ const [keyboardHeight, setKeyboardHeight] = useState(0);
48
+ const { height } = useWindowDimensions();
49
+ const { top, bottom } = useSafeAreaInsets();
45
50
 
46
51
  const handleClickQuickMessage = (text: string) => {
47
52
  setMessage && setMessage(`${message}${text}`)
@@ -186,15 +191,22 @@ const MessagesUI = (props: MessagesParams) => {
186
191
  }, [messages.messages.length])
187
192
 
188
193
  useEffect(() => {
189
- const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', () => {
194
+ const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', (e) => {
190
195
  setIsKeyboardShow(true)
196
+ setKeyboardHeight(e.endCoordinates.height)
191
197
  })
192
198
  const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => {
193
199
  setIsKeyboardShow(false)
200
+ setKeyboardHeight(0)
194
201
  })
202
+ const keyboardWillHideListener = Keyboard.addListener('keyboardWillHide', (e) => {
203
+ setIsKeyboardShow(false)
204
+ setKeyboardHeight(0)
205
+ })
195
206
  return () => {
196
207
  keyboardDidShowListener.remove()
197
208
  keyboardDidHideListener.remove()
209
+ keyboardWillHideListener.remove()
198
210
  }
199
211
  }, [])
200
212
 
@@ -273,7 +285,6 @@ const MessagesUI = (props: MessagesParams) => {
273
285
  containerStyle={{
274
286
  padding: Platform.OS === 'ios' && isKeyboardShow ? 0 : 10,
275
287
  flexDirection: 'column-reverse',
276
- marginBottom: Platform.OS === 'ios' && isKeyboardShow ? 500 : 0
277
288
  }}
278
289
  primaryStyle={{ alignItems: 'center', justifyContent: 'flex-start' }}
279
290
  renderAccessory={() => renderAccessory()}
@@ -362,8 +373,16 @@ const MessagesUI = (props: MessagesParams) => {
362
373
  <MaterialCommunityIcon name='chevron-double-down' size={32} />
363
374
  )
364
375
 
376
+ const getViewHeight = () => {
377
+ if (Platform.OS === 'android') {
378
+ return '100%'
379
+ } else {
380
+ return height - top - bottom - (isKeyboardShow ? keyboardHeight - 240 : 48)
381
+ }
382
+ }
383
+
365
384
  return (
366
- <>
385
+ <View style={{ height: getViewHeight(), width: '100%', paddingTop: 12, backgroundColor: 'white' }}>
367
386
  <Wrapper>
368
387
  <Header>
369
388
  <OIcon
@@ -396,15 +415,13 @@ const MessagesUI = (props: MessagesParams) => {
396
415
  renderBubble={renderBubble}
397
416
  renderMessageImage={renderMessageImage}
398
417
  scrollToBottomComponent={() => renderScrollToBottomComponent()}
399
- messagesContainerStyle={{
400
- paddingBottom: 55
401
- }}
418
+
402
419
  isLoadingEarlier={messages.loading}
403
420
  renderLoading={() => <ActivityIndicator size="small" color="#000" />}
404
421
  keyboardShouldPersistTaps='handled'
405
422
  />
406
423
  </Wrapper>
407
- </>
424
+ </View>
408
425
  )
409
426
  }
410
427
 
@@ -452,7 +452,8 @@ const SignupFormUI = (props: SignupParams) => {
452
452
  textInputProps={{
453
453
  returnKeyType: 'next',
454
454
  onSubmitEditing: () => passwordRef?.current?.focus?.(),
455
- style: { borderWidth: 0, fontSize: 12 }
455
+ style: { borderWidth: 0, fontSize: 12 },
456
+ maxLength: 10
456
457
  }}
457
458
  textWrapStyle={{ borderColor: theme.colors.clear, borderWidth: 0, height: 40, paddingStart: 0 }}
458
459
  />
@@ -226,7 +226,8 @@ export const UserFormDetailsUI = (props: any) => {
226
226
  defaultValue={phoneUpdate ? '' : user?.cellphone}
227
227
  defaultCode={user?.country_phone_code || null}
228
228
  textInputProps={{
229
- style: { borderWidth: 0, fontSize: 12 }
229
+ style: { borderWidth: 0, fontSize: 12 },
230
+ maxLength: 10
230
231
  }}
231
232
  textWrapStyle={{ borderColor: theme.colors.clear, borderWidth: 0, height: 40, paddingStart: 0 }}
232
233
  countryButtonStyle={{ marginStart: -2, justifyContent: 'flex-start', flexBasis: '36%'}}
@@ -150,7 +150,7 @@ export const BusinessBasicInformation = (
150
150
  <WrapReviews>
151
151
  {!isBusinessInfoShow && (
152
152
  <>
153
- <TouchableOpacity onPress={() => navigation.navigate('MomentOption')}>
153
+ <TouchableOpacity onPress={() => navigation.navigate('BusinessPreorder', { business: businessState?.business, handleBusinessClick: () => navigation?.goBack() })}>
154
154
  <OText color={theme.colors.textSecondary} style={{ textDecorationLine: 'underline' }}>
155
155
  {t('PRE_ORDER', 'Preorder')}
156
156
  </OText>
@@ -2,7 +2,7 @@ import React from 'react'
2
2
  import { useLanguage, BusinessMenuListing } from 'ordering-components/native'
3
3
  import { OText } from '../shared'
4
4
  import { BusinessMenuListParams } from '../../types'
5
- import { View, StyleSheet, Dimensions } from 'react-native'
5
+ import { View, StyleSheet, Dimensions, Platform } from 'react-native'
6
6
  import { useTheme } from 'styled-components/native'
7
7
  import IconAntDesign from 'react-native-vector-icons/AntDesign'
8
8
  import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder'
@@ -81,7 +81,7 @@ const BusinessMenuListUI = (props: BusinessMenuListParams) => {
81
81
  dropdownStyle={{
82
82
  borderRadius: 8,
83
83
  borderColor: theme.colors.lightGray,
84
- marginTop: -15,
84
+ marginTop: Platform.OS === 'ios' ? 0 : -15,
85
85
  maxHeight: 160
86
86
  }}
87
87
  rowStyle={{
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useEffect } from 'react'
2
- import { TouchableOpacity, StyleSheet, View, Dimensions } from 'react-native'
2
+ import { TouchableOpacity, StyleSheet, View, Dimensions, Platform } from 'react-native'
3
3
  import { useLanguage, useUtils, useConfig, useOrder, MomentOption } from 'ordering-components/native'
4
4
  import { OButton, OText } from '../shared'
5
5
  import { useTheme } from 'styled-components/native'
@@ -335,7 +335,7 @@ const BusinessPreorderUI = (props: BusinessPreorderParams) => {
335
335
  dropdownStyle={{
336
336
  borderRadius: 8,
337
337
  borderColor: theme.colors.lightGray,
338
- marginTop: -15
338
+ marginTop: Platform.OS === 'ios' ? 0 : -25
339
339
  }}
340
340
  rowStyle={{
341
341
  borderBottomColor: theme.colors.backgroundGray100,
@@ -25,7 +25,8 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
25
25
  errorQuantityProducts,
26
26
  handleCancelSearch,
27
27
  categoriesLayout,
28
- setCategoriesLayout
28
+ setCategoriesLayout,
29
+ currentCart
29
30
  } = props;
30
31
 
31
32
  const [, t] = useLanguage();
@@ -48,6 +49,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
48
49
  product={product}
49
50
  businessId={businessId}
50
51
  onProductClick={() => onProductClick(product)}
52
+ productAddedToCart={currentCart?.products?.find((Cproduct: any) => Cproduct.id === product.id)}
51
53
  />
52
54
  ))}
53
55
 
@@ -70,6 +72,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
70
72
  product={product}
71
73
  businessId={businessId}
72
74
  onProductClick={onProductClick}
75
+ productAddedToCart={currentCart?.products?.find((Cproduct: any) => Cproduct.id === product.id)}
73
76
  />
74
77
  ),
75
78
  )}
@@ -92,7 +95,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
92
95
  <>
93
96
  <View
94
97
  style={bpStyles.catWrap}
95
- onLayout={(event: any) => handleOnLayout(event, category.id)}
98
+ onLayout={(event: any) => handleOnLayout(event, category.id)}
96
99
  >
97
100
  <View style={bpStyles.catIcon}>
98
101
  <OIcon
@@ -114,6 +117,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
114
117
  businessId={businessId}
115
118
  product={product}
116
119
  onProductClick={onProductClick}
120
+ productAddedToCart={currentCart?.products?.find((Cproduct: any) => Cproduct.id === product.id)}
117
121
  />
118
122
  ))}
119
123
  </>
@@ -157,13 +161,13 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
157
161
  content={
158
162
  !searchValue
159
163
  ? t(
160
- 'ERROR_NOT_FOUND_PRODUCTS_TIME',
161
- 'No products found at this time',
162
- )
164
+ 'ERROR_NOT_FOUND_PRODUCTS_TIME',
165
+ 'No products found at this time',
166
+ )
163
167
  : t(
164
- 'ERROR_NOT_FOUND_PRODUCTS',
165
- 'No products found, please change filters.',
166
- )
168
+ 'ERROR_NOT_FOUND_PRODUCTS',
169
+ 'No products found, please change filters.',
170
+ )
167
171
  }
168
172
  btnTitle={
169
173
  !searchValue
@@ -277,6 +277,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
277
277
  handleCancelSearch={handleCancel}
278
278
  categoriesLayout={categoriesLayout}
279
279
  setCategoriesLayout={setCategoriesLayout}
280
+ currentCart={currentCart}
280
281
  />
281
282
  </WrapContent>
282
283
  </>
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useState } from 'react';
2
2
  import {
3
3
  BusinessReviews as BusinessReviewController,
4
4
  useLanguage,
@@ -27,6 +27,7 @@ const BusinessReviewsUI = (props: BusinessReviewsParams) => {
27
27
  const { businessState, reviewsList } = props;
28
28
  const [, t] = useLanguage();
29
29
  const theme = useTheme();
30
+ const [searchReview, setSearchReview] = useState('')
30
31
  const [orderState] = useOrder();
31
32
 
32
33
  const styles = StyleSheet.create({
@@ -150,7 +151,9 @@ const BusinessReviewsUI = (props: BusinessReviewsParams) => {
150
151
  icon={theme.images.general.search}
151
152
  inputStyle={{ fontSize: 14 }}
152
153
  placeholder={t('SEARCH_REVIEWS', 'Search reviews')}
153
- style={{ paddingStart: 0 }}></OInput>
154
+ style={{ paddingStart: 0 }}
155
+ onChange={(txt: string) => setSearchReview(txt)}
156
+ />
154
157
  </ReviewSearchView>
155
158
  <ReviewProgressView>
156
159
  <OText style={{ marginBottom: 6 }}>
@@ -223,13 +226,15 @@ const BusinessReviewsUI = (props: BusinessReviewsParams) => {
223
226
  /> */}
224
227
  </PrincipalWrapView>
225
228
 
226
- {reviewsList?.reviews.map((review: any) => (
227
- <ReviewItem
228
- key={`review_key_${review.id}`}
229
- comment={review?.comment}
230
- created_at={review?.created_at}
231
- />
232
- ))}
229
+ {reviewsList?.reviews
230
+ .filter((review: any) => searchReview !== '' ? review.comment?.toLowerCase()?.includes(searchReview?.toLowerCase()) : true)
231
+ .map((review: any) => (
232
+ <ReviewItem
233
+ key={`review_key_${review.id}`}
234
+ comment={review?.comment}
235
+ created_at={review?.created_at}
236
+ />
237
+ ))}
233
238
  </>
234
239
  )}
235
240
  {!reviewsList.loading && reviewsList?.reviews.length === 0 && (
@@ -115,6 +115,19 @@ const CartUI = (props: any) => {
115
115
 
116
116
  return (
117
117
  <CContainer>
118
+ {openUpselling && (
119
+ <UpsellingProducts
120
+ handleUpsellingPage={handleUpsellingPage}
121
+ openUpselling={openUpselling}
122
+ businessId={cart?.business_id}
123
+ business={cart?.business}
124
+ cartProducts={cart?.products}
125
+ canOpenUpselling={canOpenUpselling}
126
+ setCanOpenUpselling={setCanOpenUpselling}
127
+ handleCloseUpsellingPage={() => { }}
128
+ isFromCart
129
+ />
130
+ )}
118
131
  <BusinessItemAccordion
119
132
  cart={cart}
120
133
  moment={momentFormatted}
@@ -243,7 +256,7 @@ const CartUI = (props: any) => {
243
256
  {cart?.status !== 2 && (
244
257
  <OSTable>
245
258
  <View style={{ width: '100%', marginTop: 20 }}>
246
- <OText size={12} lineHeight={18}>{t('COMMENTS', 'Comments')}</OText>
259
+ <OText size={16} lineHeight={18}>{t('COMMENTS', 'Comments')}</OText>
247
260
  <View style={{ flex: 1, width: '100%' }}>
248
261
  <OInput
249
262
  value={cart?.comment}
@@ -253,9 +266,10 @@ const CartUI = (props: any) => {
253
266
  alignItems: 'flex-start',
254
267
  width: '100%',
255
268
  height: 100,
256
- borderColor: theme.colors.textSecondary,
269
+ borderColor: theme.colors.border,
257
270
  paddingRight: 50,
258
- marginTop: 10
271
+ marginTop: 10,
272
+ borderRadius: 7.6
259
273
  }}
260
274
  multiline
261
275
  />
@@ -324,20 +338,6 @@ const CartUI = (props: any) => {
324
338
  onClose={() => setOpenChangeStore(false)}
325
339
  />
326
340
  </OModal>
327
-
328
- {openUpselling && (
329
- <UpsellingProducts
330
- handleUpsellingPage={handleUpsellingPage}
331
- openUpselling={openUpselling}
332
- businessId={businessId}
333
- business={cart?.business}
334
- cartProducts={cart?.products}
335
- canOpenUpselling={canOpenUpselling}
336
- setCanOpenUpselling={setCanOpenUpselling}
337
- handleCloseUpsellingPage={() => { }}
338
- isFromCart
339
- />
340
- )}
341
341
  <OModal
342
342
  open={openTaxModal.open}
343
343
  onClose={() => setOpenTaxModal({ open: false, data: null })}
@@ -72,7 +72,7 @@ const CheckoutUI = (props: any) => {
72
72
  errors,
73
73
  placing,
74
74
  cartState,
75
- cartUuid,
75
+ cartUuid,
76
76
  businessDetails,
77
77
  paymethodSelected,
78
78
  handlePaymethodChange,
@@ -122,7 +122,7 @@ const CheckoutUI = (props: any) => {
122
122
  const [userErrors, setUserErrors] = useState<any>([]);
123
123
  const [isUserDetailsEdit, setIsUserDetailsEdit] = useState(false);
124
124
  const [phoneUpdate, setPhoneUpdate] = useState(false);
125
- const [openChangeStore, setOpenChangeStore] = useState(false)
125
+ const [openChangeStore, setOpenChangeStore] = useState(false)
126
126
  const [isDeliveryOptionModalVisible, setIsDeliveryOptionModalVisible] = useState(false)
127
127
 
128
128
  const driverTipsOptions = typeof configs?.driver_tip_options?.value === 'string'
@@ -459,7 +459,7 @@ const CheckoutUI = (props: any) => {
459
459
  {t('DRIVER_TIPS', 'Driver Tips')}
460
460
  </OText>
461
461
  <DriverTips
462
- uuid={cartUuid}
462
+ uuid={cartUuid}
463
463
  businessId={cart?.business_id}
464
464
  driverTipsOptions={driverTipsOptions}
465
465
  isFixedPrice={parseInt(configs?.driver_tip_type?.value, 10) === 1 || !!parseInt(configs?.driver_tip_use_custom?.value, 10)}
@@ -517,21 +517,21 @@ const CheckoutUI = (props: any) => {
517
517
  <OText size={16} lineHeight={24} color={theme.colors.textNormal}>
518
518
  {t('ORDER_SUMMARY', 'Order Summary')}
519
519
  </OText>
520
- {props.isFranchiseApp && (
521
- <TouchableOpacity
522
- onPress={() => setOpenChangeStore(true)}
523
- style={{alignSelf: 'flex-start'}}
524
- >
525
- <OText
526
- size={12}
527
- lineHeight={18}
528
- color={theme.colors.textSecondary}
529
- style={{ textDecorationLine: 'underline' }}
530
- >
531
- {t('CHANGE_STORE', 'Change store')}
532
- </OText>
533
- </TouchableOpacity>
534
- )}
520
+ {props.isFranchiseApp && (
521
+ <TouchableOpacity
522
+ onPress={() => setOpenChangeStore(true)}
523
+ style={{ alignSelf: 'flex-start' }}
524
+ >
525
+ <OText
526
+ size={12}
527
+ lineHeight={18}
528
+ color={theme.colors.textSecondary}
529
+ style={{ textDecorationLine: 'underline' }}
530
+ >
531
+ {t('CHANGE_STORE', 'Change store')}
532
+ </OText>
533
+ </TouchableOpacity>
534
+ )}
535
535
  <OrderSummary
536
536
  cart={cart}
537
537
  isCartPending={cart?.status === 2}
@@ -574,41 +574,38 @@ const CheckoutUI = (props: any) => {
574
574
  </ChErrors>
575
575
  </ChSection>
576
576
  )}
577
- <OModal
578
- open={openChangeStore && props.isFranchiseApp}
579
- entireModal
580
- customClose
581
- onClose={() => setOpenChangeStore(false)}
582
- >
583
- <CartStoresListing
584
- cartuuid={cart?.uuid}
585
- onClose={() => setOpenChangeStore(false)}
586
- />
587
- </OModal>
577
+ <OModal
578
+ open={openChangeStore && props.isFranchiseApp}
579
+ entireModal
580
+ customClose
581
+ onClose={() => setOpenChangeStore(false)}
582
+ >
583
+ <CartStoresListing
584
+ cartuuid={cart?.uuid}
585
+ onClose={() => setOpenChangeStore(false)}
586
+ />
587
+ </OModal>
588
588
  </ChContainer>
589
589
  </Container>
590
590
  {!cartState.loading && cart && cart?.status !== 2 && (
591
- <>
592
- <>
593
- <FloatingButton
594
- handleClick={() => handlePlaceOrder()}
595
- isSecondaryBtn={loading || !cart?.valid || !paymethodSelected || placing || errorCash || cart?.subtotal < cart?.minimum}
596
- disabled={loading || !cart?.valid || !paymethodSelected || placing || errorCash || cart?.subtotal < cart?.minimum}
597
- btnText={cart?.subtotal >= cart?.minimum
598
- ? (
599
- placing
600
- ? t('PLACING', 'Placing')
601
- : loading
602
- ? t('LOADING', 'Loading')
603
- : t('PLACE_ORDER', 'Place Order')
604
- )
605
- : (`${t('MINIMUN_SUBTOTAL_ORDER', 'Minimum subtotal order:')} ${parsePrice(cart?.minimum)}`)
606
- }
607
- btnRightValueShow
608
- btnRightValue={parsePrice(cart?.total)}
609
- />
610
- </>
611
- </>
591
+ <FloatingButton
592
+ handleClick={() => handlePlaceOrder()}
593
+ isSecondaryBtn={loading || !cart?.valid || !paymethodSelected || placing || errorCash || cart?.subtotal < cart?.minimum}
594
+ disabled={loading || !cart?.valid || !paymethodSelected || placing || errorCash || cart?.subtotal < cart?.minimum}
595
+ btnText={cart?.subtotal >= cart?.minimum
596
+ ? (
597
+ placing
598
+ ? t('PLACING', 'Placing')
599
+ : loading
600
+ ? t('LOADING', 'Loading')
601
+ : t('PLACE_ORDER', 'Place Order')
602
+ )
603
+ : (`${t('MINIMUN_SUBTOTAL_ORDER', 'Minimum subtotal order:')} ${parsePrice(cart?.minimum)}`)
604
+ }
605
+ btnRightValueShow
606
+ btnRightValue={parsePrice(cart?.total)}
607
+ iosBottom={20}
608
+ />
612
609
  )}
613
610
  </>
614
611
  )
@@ -762,7 +759,7 @@ export const Checkout = (props: any) => {
762
759
  ...props,
763
760
  UIComponent: CheckoutUI,
764
761
  cartState,
765
- [props.isFranchiseApp ? 'uuid' : 'businessId']: props.isFranchiseApp ? cartUuid : cartState.cart?.business_id
762
+ [props.isFranchiseApp ? 'uuid' : 'businessId']: props.isFranchiseApp ? cartUuid : cartState.cart?.business_id
766
763
  }
767
764
 
768
765
  return (
@@ -62,36 +62,33 @@ const DriverTipsUI = (props: any) => {
62
62
 
63
63
  return (
64
64
  <DTContainer>
65
- {!isDriverTipUseCustom ? (
66
- <>
67
- <DTWrapperTips>
68
- {driverTipsOptions.map((option: any, i: number) => (
69
- <TouchableOpacity
70
- key={i}
71
- onPress={() => handlerChangeOption(option)}
72
- >
73
- <DTCard
74
- style={style.circle}
75
- isActive={option === optionSelected}
76
- >
77
- <OText size={13} color={option === optionSelected ? '#FFF' : theme.colors.textSecondary}>
78
- {`${isFixedPrice ? parsePrice(option) : `${option}%`}`}
79
- </OText>
80
- </DTCard>
81
- </TouchableOpacity>
82
- ))}
83
- </DTWrapperTips>
84
- {!driverTipsOptions.includes(driverTip) && driverTip > 0 && (
85
- <OText
86
- color={theme.colors.error}
87
- size={20}
88
- style={{ marginTop: 10, textAlign: 'center' }}
65
+ <DTWrapperTips>
66
+ {driverTipsOptions.map((option: any, i: number) => (
67
+ <TouchableOpacity
68
+ key={i}
69
+ onPress={() => handlerChangeOption(option)}
70
+ >
71
+ <DTCard
72
+ style={style.circle}
73
+ isActive={option === optionSelected}
89
74
  >
90
- {t('CUSTOM_DRIVER_TIP_AMOUNT', 'The driver\'s current tip comes from a custom option')}
91
- </OText>
92
- )}
93
- </>
94
- ) : (
75
+ <OText size={13} color={option === optionSelected ? '#FFF' : theme.colors.textSecondary}>
76
+ {`${isFixedPrice ? parsePrice(option) : `${option}%`}`}
77
+ </OText>
78
+ </DTCard>
79
+ </TouchableOpacity>
80
+ ))}
81
+ </DTWrapperTips>
82
+ {!driverTipsOptions.includes(driverTip) && driverTip > 0 && (
83
+ <OText
84
+ color={theme.colors.error}
85
+ size={16}
86
+ style={{ marginTop: 10, textAlign: 'center' }}
87
+ >
88
+ {t('CUSTOM_DRIVER_TIP_AMOUNT', 'The driver\'s current tip comes from a custom option')}
89
+ </OText>
90
+ )}
91
+ {isDriverTipUseCustom && (
95
92
  <DTForm>
96
93
  <DTLabel>
97
94
  {t('CUSTOM_DRIVER_TIP_MESSAGE', '100% of these tips go directly to your driver')}
@@ -110,7 +107,7 @@ const DriverTipsUI = (props: any) => {
110
107
  borderColor={theme.colors.primary}
111
108
  textStyle={{ color: 'white', fontSize: 14 }}
112
109
  imgRightSrc={null}
113
- style={{borderRadius: 5, height: 44}}
110
+ style={{ borderRadius: 5, height: 44 }}
114
111
  isDisabled={!(value > 0 && value !== driverTip) || !value}
115
112
  onClick={() => {
116
113
  handlerChangeOption(value)
@@ -121,7 +118,7 @@ const DriverTipsUI = (props: any) => {
121
118
  {parseFloat(driverTip || 0) > 0 && (
122
119
  <OText
123
120
  color={theme.colors.error}
124
- size={20}
121
+ size={16}
125
122
  style={{ marginTop: 10, textAlign: 'center' }}
126
123
  >
127
124
  {t('CURRENT_DRIVER_TIP_AMOUNT', 'Current driver tip amount')}: {parsePrice(driverTip)}
@@ -22,6 +22,7 @@ const FloatingButtonUI = (props: FloatingButtonParams) => {
22
22
  disabled,
23
23
  isSecondaryBtn,
24
24
  handleEmpty,
25
+ iosBottom
25
26
  } = props;
26
27
 
27
28
  const [, t] = useLanguage();
@@ -61,7 +62,7 @@ const FloatingButtonUI = (props: FloatingButtonParams) => {
61
62
  return (
62
63
  <Container
63
64
  style={{
64
- paddingBottom: Platform.OS === 'ios' ? 0 : bottom + 16
65
+ paddingBottom: Platform.OS === 'ios' ? iosBottom ?? 0 : bottom + 16
65
66
  }}>
66
67
 
67
68
  <View style={styles.infoCont}>
@@ -218,9 +218,13 @@ const MessagesUI = (props: MessagesParams) => {
218
218
  const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => {
219
219
  setIsKeyboardShow(false)
220
220
  })
221
+ const keyboardWillHideListener = Keyboard.addListener('keyboardWillHide', () => {
222
+ setIsKeyboardShow(false)
223
+ })
221
224
  return () => {
222
225
  keyboardDidShowListener.remove()
223
226
  keyboardDidHideListener.remove()
227
+ keyboardWillHideListener.remove()
224
228
  }
225
229
  }, [])
226
230
 
@@ -411,9 +415,9 @@ const MessagesUI = (props: MessagesParams) => {
411
415
 
412
416
  const getViewHeight = () => {
413
417
  if (Platform.OS === 'android') {
414
- return height - top - bottom - (isKeyboardShow ? 300 : 24);
418
+ return '100%';
415
419
  } else {
416
- return height - top - bottom - 10;
420
+ return height - top - bottom - (isKeyboardShow ? 48 : 0);
417
421
  }
418
422
  }
419
423
 
@@ -203,7 +203,7 @@ const OrderSummaryUI = (props: any) => {
203
203
  alignItems: 'flex-start',
204
204
  width: '100%',
205
205
  height: 100,
206
- borderColor: theme.colors.textSecondary,
206
+ borderColor: theme.colors.border,
207
207
  paddingRight: 50,
208
208
  marginTop: 10
209
209
  }}
@@ -173,7 +173,7 @@ export const ProductOptionsUI = (props: any) => {
173
173
  const sel = option[0]?.suboptions?.filter(
174
174
  ({ id }: any) => id === respect_id,
175
175
  );
176
- return sel[0]?.id !== undefined;
176
+ return sel?.[0]?.id !== undefined;
177
177
  };
178
178
 
179
179
  const handleChangeMainIndex = (index: number) => {
@@ -523,6 +523,7 @@ export const ProductOptionsUI = (props: any) => {
523
523
  <WrapperSubOption
524
524
  style={{
525
525
  backgroundColor: isError(option.id),
526
+ borderRadius: 7.6
526
527
  }}>
527
528
  {option.suboptions.map(
528
529
  (suboption: any) => {
@@ -210,12 +210,13 @@ export const ProductItemAccordion = (props: ProductItemAccordionParams) => {
210
210
  </View>
211
211
  </ContentInfo>
212
212
  </View>
213
-
214
213
  {((isCartProduct && !isCartPending && product?.valid_menu && !product?.valid_quantity) ||
215
214
  (!product?.valid_menu && isCartProduct && !isCartPending)) && (
216
- <OText size={20} color={theme.colors.red} style={{ textAlign: 'center', marginTop: 10 }}>
217
- {t('NOT_AVAILABLE', 'Not available')}
218
- </OText>
215
+ <View style={{ alignItems: 'flex-end', width: '100%' }}>
216
+ <OText size={14} color={theme.colors.red} style={{ textAlign: 'right', bottom: 20 }}>
217
+ {t('NOT_AVAILABLE', 'Not available')}
218
+ </OText>
219
+ </View>
219
220
  )}
220
221
  </Accordion>
221
222
 
@@ -11,7 +11,7 @@ export const Accordion = styled.TouchableOpacity`
11
11
  align-items: center;
12
12
 
13
13
  ${(props: any) => !props.isValid && css`
14
- background-color: rgba(0, 0, 0, 0.1);
14
+ opacity: 0.7;
15
15
  `}
16
16
  `
17
17
 
@@ -4,7 +4,7 @@ export const Container = styled.View`
4
4
  flex-direction: row;
5
5
  align-items: center;
6
6
  justify-content: space-between;
7
- padding: 10px 0;
7
+ padding: 10px;
8
8
  `
9
9
 
10
10
  export const IconControl = styled.TouchableOpacity`
@@ -7,13 +7,13 @@ import {
7
7
  } from 'ordering-components/native';
8
8
  import { useTheme } from 'styled-components/native';
9
9
  import { SingleProductCardParams } from '../../types';
10
- import { CardContainer, CardInfo, SoldOut } from './styles';
10
+ import { CardContainer, CardInfo, SoldOut, QuantityContainer } from './styles';
11
11
  import { StyleSheet } from 'react-native';
12
12
  import { OText, OIcon } from '../shared';
13
13
  import FastImage from 'react-native-fast-image'
14
14
 
15
15
  export const SingleProductCard = (props: SingleProductCardParams) => {
16
- const { businessId, product, isSoldOut, onProductClick } = props;
16
+ const { businessId, product, isSoldOut, onProductClick, productAddedToCart } = props;
17
17
 
18
18
  const theme = useTheme();
19
19
 
@@ -42,6 +42,16 @@ export const SingleProductCard = (props: SingleProductCardParams) => {
42
42
  borderRadius: 7.6,
43
43
  marginStart: 12
44
44
  },
45
+ quantityContainer: {
46
+ position: 'absolute',
47
+ left: '100%',
48
+ bottom: '100%',
49
+ width: 25,
50
+ height: 25,
51
+ textAlign: 'center',
52
+ borderRadius: 25,
53
+ alignItems: 'center'
54
+ }
45
55
  });
46
56
 
47
57
 
@@ -88,6 +98,13 @@ export const SingleProductCard = (props: SingleProductCardParams) => {
88
98
  (isSoldOut || maxProductQuantity <= 0) && styles.soldOutBackgroundStyle,
89
99
  ]}
90
100
  onPress={() => onProductClick?.(product)}>
101
+ {productAddedToCart && productAddedToCart?.quantity > 0 && (
102
+ <QuantityContainer style={[styles.quantityContainer, {
103
+ transform: [{ translateX: 10 }, { translateY: -10 }],
104
+ }]}>
105
+ <OText color={theme.colors.white}>{productAddedToCart?.quantity}</OText>
106
+ </QuantityContainer>
107
+ )}
91
108
  <CardInfo>
92
109
  <OText
93
110
  size={12}
@@ -21,3 +21,7 @@ export const SoldOut = styled.View`
21
21
  top: 37px;
22
22
  end: 10px;
23
23
  `
24
+
25
+ export const QuantityContainer = styled.View`
26
+ background: ${({ theme } : any) => theme.colors.primary};
27
+ `
@@ -52,9 +52,10 @@ const UpsellingProductsUI = (props: UpsellingProductsParams) => {
52
52
  borderColor: theme.colors.primary,
53
53
  backgroundColor: theme.colors.primary,
54
54
  borderWidth: 1,
55
+ alignSelf: 'center',
55
56
  height: 44,
56
- marginBottom: 10,
57
- shadowOpacity: 0
57
+ shadowOpacity: 0,
58
+ width: '80%',
58
59
  },
59
60
  cancelBtn: {
60
61
  paddingHorizontal: 18,
@@ -165,7 +166,13 @@ const UpsellingProductsUI = (props: UpsellingProductsParams) => {
165
166
  <OText size={12} color={theme.colors.textSecondary}>{t('CANCEL', 'Cancel')}</OText>
166
167
  </TopActions>
167
168
  </TopBar>
168
- <ScrollView style={{ marginBottom: bottom + (Platform.OS == 'ios' ? 46 : 70) }} showsVerticalScrollIndicator={false}>
169
+ <ScrollView style={{ marginBottom: bottom + (Platform.OS == 'ios' ? 96 : 130) }} showsVerticalScrollIndicator={false}>
170
+ {upsellingProducts?.products?.length > 0 &&
171
+ <View style={{ paddingHorizontal: 40, overflow: 'visible' }}>
172
+ <OText size={16} lineHeight={24} weight={'500'}>{t('WANT_SOMETHING_ELSE', 'Do you want something else?')}</OText>
173
+ <UpsellingLayout />
174
+ </View>
175
+ }
169
176
  <View style={{ paddingHorizontal: 40 }}>
170
177
  <OText size={20} lineHeight={30} weight={600} style={{ marginTop: 10, marginBottom: 17 }}>{t('YOUR_CART', 'Your cart')}</OText>
171
178
  <OrderSummary
@@ -173,25 +180,16 @@ const UpsellingProductsUI = (props: UpsellingProductsParams) => {
173
180
  isCartPending={cart?.status === 2}
174
181
  />
175
182
  </View>
176
- <View style={{ height: 8, backgroundColor: theme.colors.backgroundGray100, marginHorizontal: -40, marginBottom: 23 }} />
177
- <View style={{ paddingHorizontal: 40, overflow: 'visible' }}>
178
- {upsellingProducts?.products?.length > 0 &&
179
- <>
180
- <OText size={16} lineHeight={24} weight={'500'}>{t('WANT_SOMETHING_ELSE', 'Do you want something else?')}</OText>
181
- <UpsellingLayout />
182
- </>
183
- }
184
- <CloseUpselling>
185
- <OButton
186
- imgRightSrc=''
187
- text={t('CHECKOUT', 'Checkout')}
188
- style={styles.closeUpsellingButton}
189
- textStyle={{ color: theme.colors.white, fontSize: 14 }}
190
- onClick={() => handleUpsellingPage()}
191
- />
192
- </CloseUpselling>
193
- </View>
194
183
  </ScrollView>
184
+ <View style={{alignItems: 'center', bottom: Platform.OS === 'ios' ? bottom + 59 : bottom + 125}}>
185
+ <OButton
186
+ imgRightSrc=''
187
+ text={t('CHECKOUT', 'Checkout')}
188
+ style={{...styles.closeUpsellingButton}}
189
+ textStyle={{ color: theme.colors.white, fontSize: 14 }}
190
+ onClick={() => handleUpsellingPage()}
191
+ />
192
+ </View>
195
193
  </OBottomPopup>
196
194
  )}
197
195
  </>
@@ -212,13 +212,15 @@ export interface BusinessProductsListParams {
212
212
  errorQuantityProducts?: boolean,
213
213
  handleCancelSearch?: () => void,
214
214
  categoriesLayout?: any,
215
- setCategoriesLayout?: any
215
+ setCategoriesLayout?: any,
216
+ currentCart?: any
216
217
  }
217
218
  export interface SingleProductCardParams {
218
219
  businessId: any,
219
220
  product: any;
220
221
  isSoldOut: boolean;
221
222
  onProductClick: any;
223
+ productAddedToCart?: any
222
224
  }
223
225
  export interface BusinessInformationParams {
224
226
  navigation?: any,
@@ -381,6 +383,7 @@ export interface FloatingButtonParams {
381
383
  btnRightValueShow?: boolean;
382
384
  handleClick?: any;
383
385
  handleEmpty?: any;
386
+ iosBottom?: number
384
387
  }
385
388
  export interface MomentOptionParams {
386
389
  navigation: any;