ordering-ui-react-native 0.18.28 → 0.18.30

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.18.28",
3
+ "version": "0.18.30",
4
4
  "description": "Reusable components made in react native",
5
5
  "main": "src/index.tsx",
6
6
  "author": "ordering.inc",
@@ -45,7 +45,7 @@ const NewOrderNotificationUI = (props: any) => {
45
45
  },
46
46
  }
47
47
 
48
- const notificationSound = new Sound(theme.sounds.notification, '', () => {});
48
+ const notificationSound = new Sound(theme.sounds.notification, '', () => { });
49
49
 
50
50
  let _timeout: any = null
51
51
 
@@ -75,11 +75,11 @@ const NewOrderNotificationUI = (props: any) => {
75
75
  await fetch(`${ordering.root}/users/${user.id}/locations`, {
76
76
  method: 'POST',
77
77
  body: JSON.stringify({
78
- location: JSON.stringify({location: `{lat: ${location.latitude}, lng: ${location.longitude}}`})
78
+ location: JSON.stringify({ location: `{lat: ${location.latitude}, lng: ${location.longitude}}` })
79
79
  }),
80
80
  headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` }
81
81
  })
82
- } catch {}
82
+ } catch { }
83
83
  const duration = moment.duration(moment().diff(moment.utc(value?.last_driver_assigned_at)))
84
84
  const assignedSecondsDiff = duration.asSeconds()
85
85
  if (assignedSecondsDiff < 5 && !isBusinessApp) {
@@ -89,7 +89,7 @@ const NewOrderNotificationUI = (props: any) => {
89
89
  if (evtType === 3 || value.author_id === user.id) return
90
90
  handlePlayNotificationSound({
91
91
  evt: evtType,
92
- orderId: evtList[evtType].event === 'messages' ? value?.order_id : value?.id
92
+ orderId: value?.order_id
93
93
  })
94
94
  }
95
95
 
@@ -16,6 +16,8 @@ import {
16
16
  useToast,
17
17
  ToastType
18
18
  } from 'ordering-components/native';
19
+ import { DeviceOrientationMethods } from '../../../../../src/hooks/DeviceOrientation'
20
+
19
21
  import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
20
22
  import Spinner from 'react-native-loading-spinner-overlay';
21
23
  import { useForm, Controller } from 'react-hook-form';
@@ -38,6 +40,8 @@ import {
38
40
  import { GPSButton } from '../GPSButton';
39
41
  import { ScrollView } from 'react-native-gesture-handler';
40
42
 
43
+ const { useDeviceOrientation } = DeviceOrientationMethods
44
+
41
45
  const inputNames = [
42
46
  { name: 'address', code: 'Address' },
43
47
  { name: 'internal_number', code: 'Internal number' },
@@ -66,6 +70,8 @@ const AddressFormUI = (props: AddressFormParams) => {
66
70
  } = props;
67
71
 
68
72
  const theme = useTheme();
73
+ const [orientationState] = useDeviceOrientation();
74
+
69
75
  const [autoCompleteInputFocused, setAutoCompleteInputFocused] = useState(false)
70
76
 
71
77
  const tagsName = [
@@ -75,6 +81,8 @@ const AddressFormUI = (props: AddressFormParams) => {
75
81
  { icon: theme.images.general.tag_plus, value: 'other' },
76
82
  ];
77
83
 
84
+ const HEIGHT_SCREEN = orientationState?.dimensions?.height
85
+
78
86
  const styles = StyleSheet.create({
79
87
  iconContainer: {
80
88
  display: 'flex',
@@ -524,7 +532,7 @@ const AddressFormUI = (props: AddressFormParams) => {
524
532
  />
525
533
  </View>
526
534
  <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
527
- <AddressFormContainer style={{ height: 600, overflow: 'scroll' }}>
535
+ <AddressFormContainer style={{ height: HEIGHT_SCREEN * .78, overflow: 'scroll' }}>
528
536
  <View>
529
537
  <FormInput>
530
538
  <AutocompleteInput>
@@ -216,6 +216,25 @@ export const AnalyticsSegment = (props: any) => {
216
216
  })
217
217
  }
218
218
 
219
+ const handleProductAddedToWishlist = (product: any) => {
220
+ segmentClient.track('Product Added to Wishlist', product)
221
+ }
222
+
223
+ const handleProductRemovedFromWishlist = (product: any) => {
224
+ segmentClient.track('Product Removed from Wishlist', product)
225
+ }
226
+
227
+ const handleWishlistProductAddedToCart = (product: any, result: any) => {
228
+ segmentClient.track('Wishlist Product Added to Cart', {
229
+ cart_id: result.uuid,
230
+ product_id: product.id,
231
+ name: product.name,
232
+ category: product.categoryId,
233
+ price: product.price,
234
+ quantity: product.quantity
235
+ })
236
+ }
237
+
219
238
  useEffect(() => {
220
239
  if (segmentClient?.config?.writeKey) {
221
240
  events.on('products_searched', handleProductsSearched)
@@ -237,6 +256,9 @@ export const AnalyticsSegment = (props: any) => {
237
256
  events.on('userLogin', handleLogin)
238
257
  events.on('order_placed', handleOrderPlaced)
239
258
  events.on('order_added', handleAddOrder)
259
+ events.on('product_added_to_wishlist', handleProductAddedToWishlist)
260
+ events.on('product_removed_from_wishlist', handleProductRemovedFromWishlist)
261
+ events.on('wishlist_product_added_to_cart', handleWishlistProductAddedToCart)
240
262
  }
241
263
  return () => {
242
264
  if (segmentClient?.config?.writeKey) {
@@ -259,6 +281,9 @@ export const AnalyticsSegment = (props: any) => {
259
281
  events.off('userLogin', handleLogin)
260
282
  events.off('order_placed', handleOrderPlaced)
261
283
  events.off('order_added', handleAddOrder)
284
+ events.off('product_added_to_wishlist', handleProductAddedToWishlist)
285
+ events.off('product_removed_from_wishlist', handleProductRemovedFromWishlist)
286
+ events.off('wishlist_product_added_to_cart', handleWishlistProductAddedToCart)
262
287
  }
263
288
  }
264
289
  }, [segmentClient])
@@ -278,6 +303,5 @@ export const AnalyticsSegment = (props: any) => {
278
303
  {children}
279
304
  </AnalyticsProvider>
280
305
  </>
281
-
282
306
  )
283
307
  }
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback, useEffect, useRef, useState } from 'react'
2
- import { View, TouchableOpacity, StyleSheet, SafeAreaView, Dimensions, Platform, KeyboardAvoidingViewBase, KeyboardAvoidingView, Vibration } from 'react-native'
2
+ import { View, TouchableOpacity, StyleSheet, SafeAreaView, Dimensions, Platform, KeyboardAvoidingViewBase, KeyboardAvoidingView, Vibration, BackHandler } from 'react-native'
3
3
  import { IOScrollView } from 'react-native-intersection-observer'
4
4
  import { useSafeAreaInsets } from 'react-native-safe-area-context'
5
5
  import { useTheme } from 'styled-components/native';
@@ -343,6 +343,17 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
343
343
  }
344
344
  }, [business?.lazy_load_products_recommended, selectedCategoryId, categorySelected?.id, viewedCategory])
345
345
 
346
+ useEffect(() => {
347
+ const handleArrowBack: any = () => {
348
+ navigation.goBack()
349
+ return true
350
+ }
351
+ BackHandler.addEventListener('hardwareBackPress', handleArrowBack);
352
+ return () => {
353
+ BackHandler.removeEventListener('hardwareBackPress', handleArrowBack);
354
+ }
355
+ }, [])
356
+
346
357
  return (
347
358
  <>
348
359
  <View style={{ flex: 1, backgroundColor: backgroundColor }}>
@@ -3,6 +3,7 @@ import {
3
3
  BusinessReviews as BusinessReviewController,
4
4
  useLanguage,
5
5
  useOrder,
6
+ useUtils
6
7
  } from 'ordering-components/native';
7
8
  import { useTheme } from 'styled-components/native';
8
9
  import IconAntDesign from 'react-native-vector-icons/AntDesign';
@@ -30,6 +31,7 @@ const BusinessReviewsUI = (props: BusinessReviewsParams) => {
30
31
  const theme = useTheme();
31
32
  const [searchReview, setSearchReview] = useState('')
32
33
  const [orderState] = useOrder();
34
+ const [{ parseDate }] = useUtils()
33
35
 
34
36
  const styles = StyleSheet.create({
35
37
  starIcon: {
@@ -94,7 +96,7 @@ const BusinessReviewsUI = (props: BusinessReviewsParams) => {
94
96
  const ReviewItem = ({ comment, created_at, total }: any) => (
95
97
  <View style={{ marginBottom: 30 }}>
96
98
  <OText size={12} color={theme.colors.textSecondary}>
97
- {moment(created_at).format('MMMM d, yyyy • hh:mm')}
99
+ {parseDate(created_at, { outputFormat: 'MMMM D, YYYY • hh:mm A' })}
98
100
  </OText>
99
101
  <OText size={12} color={theme.colors.textNormal}>{comment}</OText>
100
102
  </View>
@@ -3,7 +3,7 @@ import {
3
3
  useLanguage,
4
4
  PurchaseGiftCard as PurchaseGiftCardController
5
5
  } from 'ordering-components/native'
6
- import { StyleSheet, View, TouchableOpacity } from 'react-native'
6
+ import { StyleSheet, View, TouchableOpacity, ScrollView } from 'react-native'
7
7
  import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
8
8
  import { useTheme } from 'styled-components/native';
9
9
  import { OText, OButton, OIcon } from '../../shared';
@@ -44,7 +44,11 @@ const PurchaseGiftCardUI = (props: any) => {
44
44
  <Container>
45
45
  <OText color={theme.colors.textNormal} weight='bold' size={20} mBottom={40}>{t('PURCHASE_GIFT_CARD', 'Purchase gift card')}</OText>
46
46
  <OText color={theme.colors.textNormal} size={14}>{t('SELECT_ONE_OPTION', 'Select one option')}</OText>
47
- <View>
47
+ <ScrollView
48
+ contentContainerStyle={{
49
+ flexGrow: 1
50
+ }}
51
+ >
48
52
  {productsListState.loading && (
49
53
  [...Array(5).keys()].map(i => (
50
54
  <View key={i} style={style.itemStyle}>
@@ -72,7 +76,7 @@ const PurchaseGiftCardUI = (props: any) => {
72
76
  <OText color={theme.colors.textNormal} size={14}>{product.name}</OText>
73
77
  </TouchableOpacity>
74
78
  ))}
75
- </View>
79
+ </ScrollView>
76
80
  <OButton
77
81
  onClick={() => handleAccept()}
78
82
  text={t('ACCEPT', 'Accept')}
@@ -3,4 +3,6 @@ import styled from 'styled-components/native'
3
3
  export const Container = styled.View`
4
4
  width: 100%;
5
5
  padding-horizontal: 40px;
6
+ flex: 1;
7
+ padding-bottom: 30px;
6
8
  `
@@ -25,6 +25,7 @@ const MultiCartsPaymethodsAndWalletsUI = (props: any) => {
25
25
  businessIds,
26
26
  paymethodsAndWallets,
27
27
  walletsState,
28
+ walletsPaymethod,
28
29
  paymethodSelected,
29
30
  handleSelectPaymethod,
30
31
  handleSelectWallet,
@@ -52,6 +53,8 @@ const MultiCartsPaymethodsAndWalletsUI = (props: any) => {
52
53
  }
53
54
  }
54
55
 
56
+ const creditBalance: any = (wallet: any) => ` = ${parsePrice(wallet.balance / wallet.redemption_rate, { isTruncable: true })}`
57
+
55
58
  const getPayIcon = (method: string) => {
56
59
  switch (method) {
57
60
  case 'cash':
@@ -169,13 +172,16 @@ const MultiCartsPaymethodsAndWalletsUI = (props: any) => {
169
172
  </>
170
173
  ) : (
171
174
  <>
172
- {walletsState?.result?.filter((wallet: any) => paymethodsAndWallets.wallets.find((item: any) => item.type === wallet.type)).map((wallet: any, idx: any) => walletName[wallet.type]?.isActive && (
175
+ {walletsState?.result?.filter((wallet: any) =>
176
+ paymethodsAndWallets.wallets.find((item: any) => item.type === wallet.type))
177
+ .map((wallet: any, idx: any) => walletName[wallet.type]?.isActive &&
178
+ (
173
179
  <WalletItem
174
180
  key={wallet.type}
175
181
  isBottomBorder={idx === paymethodsAndWallets.wallets?.length - 1}
176
- onPress={() => handleSelectWallet(paymethodSelected.wallet_id === wallet.id ? false : true, wallet)}
182
+ onPress={() => handleSelectWallet(!!!walletsPaymethod?.find((walletPay: any) => walletPay.wallet_id === wallet.id)?.id, wallet)}
177
183
  >
178
- {paymethodSelected.wallet_id === wallet.id ? (
184
+ {!!walletsPaymethod?.find((walletPay: any) => walletPay.wallet_id === wallet.id)?.id ? (
179
185
  <MaterialCommunityIcons
180
186
  name="checkbox-marked"
181
187
  size={25}
@@ -189,7 +195,23 @@ const MultiCartsPaymethodsAndWalletsUI = (props: any) => {
189
195
  />
190
196
  )}
191
197
  <OText size={12} style={{ flex: 1, marginLeft: 15 }}>{walletName[wallet.type]?.name}</OText>
192
- <OText size={12}>{parsePrice(wallet.balance)}</OText>
198
+ {wallet.type === 'cash' && (
199
+ <OText>
200
+ {parsePrice(wallet?.balance, { isTruncable: true })}
201
+ </OText>
202
+ )}
203
+ {wallet.type === 'credit_point' && (
204
+ <OText>
205
+ <OText color={theme.colors.primary} weight='bold'>
206
+ {`${wallet?.balance} ${t('POINTS', 'Points')}`}
207
+ </OText>
208
+ <OText>
209
+ {wallet?.balance > 0
210
+ ? creditBalance(wallet)
211
+ : null}
212
+ </OText>
213
+ </OText>
214
+ )}
193
215
  </WalletItem>
194
216
  ))}
195
217
  </>
@@ -63,6 +63,7 @@ const MultiCheckoutUI = (props: any) => {
63
63
  loyaltyPlansState,
64
64
  totalCartsFee,
65
65
  cartGroup,
66
+ walletState,
66
67
  onNavigationRedirectReplace
67
68
  } = props
68
69
 
@@ -86,8 +87,11 @@ const MultiCheckoutUI = (props: any) => {
86
87
  const configTypes = configs?.order_types_allowed?.value.split('|').map((value: any) => Number(value)) || []
87
88
  const isPreOrder = configs?.preorder_status_enabled?.value === '1'
88
89
  const isMultiDriverTips = configs?.checkout_multi_business_enabled?.value === '1'
89
- const isDisablePlaceOrderButton = !(paymethodSelected?.paymethod_id || paymethodSelected?.wallet_id) || (paymethodSelected?.paymethod?.gateway === 'stripe' && !paymethodSelected?.paymethod_data)
90
90
  const walletCarts = (Object.values(carts)?.filter((cart: any) => cart?.products && cart?.products?.length && cart?.status !== 2 && cart?.valid_schedule && cart?.valid_products && cart?.valid_address && cart?.valid_maximum && cart?.valid_minimum && cart?.wallets) || null) || []
91
+ const isDisablePlaceOrderButton = cartGroup?.loading || (!(paymethodSelected?.paymethod_id || paymethodSelected?.wallet_id) && cartGroup?.result?.balance > 0) ||
92
+ (paymethodSelected?.paymethod?.gateway === 'stripe' && !paymethodSelected?.paymethod_data) ||
93
+ walletCarts.length > 0
94
+
91
95
  const driverTipsOptions = typeof configs?.driver_tip_options?.value === 'string'
92
96
  ? JSON.parse(configs?.driver_tip_options?.value) || []
93
97
  : configs?.driver_tip_options?.value || []
@@ -171,6 +175,12 @@ const MultiCheckoutUI = (props: any) => {
171
175
  }
172
176
  }, [openCarts])
173
177
 
178
+ useEffect(() => {
179
+ if (walletState.error) {
180
+ showToast(ToastType.Error, t(walletState.error, walletState.error?.[0]?.replace(/_/g, ' ')))
181
+ }
182
+ }, [walletState.error])
183
+
174
184
  return (
175
185
  <>
176
186
  <Container noPadding>
@@ -248,6 +258,7 @@ const MultiCheckoutUI = (props: any) => {
248
258
  <MultiCartsPaymethodsAndWallets
249
259
  openCarts={openCarts}
250
260
  paymethodSelected={paymethodSelected}
261
+ walletsPaymethod={cartGroup?.result?.wallets}
251
262
  handleSelectPaymethod={handleSelectPaymethod}
252
263
  handleSelectWallet={handleSelectWallet}
253
264
  handlePaymethodDataChange={handlePaymethodDataChange}
@@ -346,12 +357,14 @@ const MultiCheckoutUI = (props: any) => {
346
357
  )}
347
358
  {openCarts.length > 1 && (
348
359
  <ChCartsTotal>
349
- {totalCartsFee && configs?.multi_business_checkout_show_combined_delivery_fee?.value === '1' && (
360
+ {!!totalCartsFee && configs?.multi_business_checkout_show_combined_delivery_fee?.value === '1' && (
350
361
  <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
351
362
  <OText size={14} lineHeight={24} color={theme.colors.textNormal} weight={'400'}>
352
363
  {t('TOTAL_DELIVERY_FEE', 'Total delivery fee')}
353
364
  </OText>
354
- <OText size={14} lineHeight={24} color={theme.colors.textNormal} weight={'400'}>{parsePrice(totalCartsFee)}</OText>
365
+ <OText size={14} lineHeight={24} color={theme.colors.textNormal} weight={'400'}>
366
+ {parsePrice(totalCartsFee)}
367
+ </OText>
355
368
  </View>
356
369
  )}
357
370
  {openCarts.reduce((sum: any, cart: any) => sum + cart?.driver_tip, 0) > 0 &&
@@ -44,7 +44,7 @@ const PageBannerUI = (props: any) => {
44
44
  })
45
45
 
46
46
  const onRedirect = (route: string, params?: any) => {
47
- navigation.navigate(route, params)
47
+ navigation.push(route, params)
48
48
  }
49
49
 
50
50
  const handleGoToPage = (item: any) => {
@@ -212,7 +212,7 @@ const PromotionsUI = (props: PromotionParams) => {
212
212
  </OText>
213
213
  <ScrollView
214
214
  showsVerticalScrollIndicator={false}
215
- style={{ height: '75%' }}
215
+ style={{ height: '68%' }}
216
216
  >
217
217
  {offerSelected?.businesses?.map((business: any) => {
218
218
  return (