ordering-ui-react-native 0.12.76 → 0.12.80

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 (31) hide show
  1. package/package.json +1 -1
  2. package/src/components/BusinessesListing/index.tsx +35 -3
  3. package/src/components/BusinessesListing/styles.tsx +10 -0
  4. package/src/components/Checkout/index.tsx +77 -8
  5. package/src/components/Messages/index.tsx +3 -3
  6. package/src/components/PaymentOptions/index.tsx +2 -2
  7. package/src/theme.json +3 -1
  8. package/src/utils/index.tsx +27 -0
  9. package/themes/business/src/components/OrderDetails/Delivery.tsx +134 -131
  10. package/themes/business/src/components/OrderDetails/OrderHeaderComponent.tsx +1 -1
  11. package/themes/doordash/src/components/BusinessesListing/index.tsx +33 -1
  12. package/themes/doordash/src/components/BusinessesListing/styles.tsx +11 -1
  13. package/themes/doordash/src/utils/index.tsx +27 -0
  14. package/themes/instacart/src/components/BusinessesListing/index.tsx +35 -3
  15. package/themes/instacart/src/components/BusinessesListing/styles.tsx +11 -1
  16. package/themes/instacart/src/utils/index.tsx +27 -0
  17. package/themes/original/index.tsx +2 -0
  18. package/themes/original/src/components/ActiveOrders/index.tsx +36 -16
  19. package/themes/original/src/components/ActiveOrders/styles.tsx +10 -0
  20. package/themes/original/src/components/MessageListing/index.tsx +298 -0
  21. package/themes/original/src/components/MessageListing/styles.tsx +16 -0
  22. package/themes/original/src/components/Messages/index.tsx +123 -81
  23. package/themes/original/src/components/Messages/styles.tsx +8 -0
  24. package/themes/original/src/components/UserProfile/index.tsx +10 -0
  25. package/themes/original/src/utils/index.tsx +18 -0
  26. package/themes/single-business/src/components/BusinessesListing/index.tsx +33 -0
  27. package/themes/single-business/src/components/BusinessesListing/styles.tsx +9 -0
  28. package/themes/single-business/src/utils/index.tsx +27 -0
  29. package/themes/uber-eats/src/components/BusinessesListing/index.tsx +36 -3
  30. package/themes/uber-eats/src/components/BusinessesListing/styles.tsx +8 -0
  31. package/themes/uber-eats/src/utils/index.tsx +27 -0
@@ -0,0 +1,16 @@
1
+ import styled from 'styled-components/native'
2
+
3
+ export const MessageListingWrapper = styled.View`
4
+ position: relative;
5
+ `
6
+
7
+ export const MessageContainer = styled.View`
8
+ position: absolute;
9
+ top: 0;
10
+ left: 0;
11
+ margin: 0;
12
+ width: 100%;
13
+ height: 100%;
14
+ `
15
+
16
+
@@ -7,13 +7,12 @@ import { USER_TYPE } from '../../config/constants'
7
7
  import MaterialCommunityIcon from 'react-native-vector-icons/MaterialCommunityIcons'
8
8
  import { OIcon, OIconButton, OText, OButton } from '../shared'
9
9
  import { TouchableOpacity, ActivityIndicator, StyleSheet, View, Platform, Keyboard } from 'react-native'
10
- import { Header, TitleHeader, Wrapper, QuickMessageContainer } from './styles'
10
+ import { Header, TitleHeader, Wrapper, QuickMessageContainer, ProfileMessageHeader } from './styles'
11
11
  import { MessagesParams } from '../../types'
12
12
  import { useWindowDimensions } from 'react-native'
13
13
  import { useSafeAreaInsets } from 'react-native-safe-area-context'
14
14
 
15
15
  const MessagesUI = (props: MessagesParams) => {
16
-
17
16
  const {
18
17
  type,
19
18
  order,
@@ -27,6 +26,7 @@ const MessagesUI = (props: MessagesParams) => {
27
26
  setImage,
28
27
  readMessages,
29
28
  onClose,
29
+ isMeesageListing
30
30
  } = props
31
31
 
32
32
  const [{ user }] = useSession()
@@ -37,22 +37,22 @@ const MessagesUI = (props: MessagesParams) => {
37
37
  const [formattedMessages, setFormattedMessages] = useState<Array<any>>([])
38
38
  const [isKeyboardShow, setIsKeyboardShow] = useState(false)
39
39
  const previousStatus = [1, 2, 5, 6, 10, 11, 12, 16, 17]
40
- const chatDisabled = previousStatus.includes(order?.status)
40
+ const chatDisabled = previousStatus.includes(order?.status)
41
41
  const { height } = useWindowDimensions();
42
42
  const { top, bottom } = useSafeAreaInsets();
43
43
 
44
44
  const theme = useTheme();
45
45
 
46
46
  const quickMessageList = [
47
- { key: 'customer_message_1', text: t('CUSTOMER_MESSAGE_1', 'Lorem ipsum 1') },
48
- { key: 'customer_message_2', text: t('CUSTOMER_MESSAGE_2', 'Lorem ipsum 2') },
49
- { key: 'customer_message_3', text: t('CUSTOMER_MESSAGE_3', 'Lorem ipsum 3') },
50
- { key: 'customer_message_4', text: t('CUSTOMER_MESSAGE_4', 'Lorem ipsum 4') }
51
- ]
47
+ { key: 'customer_message_1', text: t('CUSTOMER_MESSAGE_1', 'Lorem ipsum 1') },
48
+ { key: 'customer_message_2', text: t('CUSTOMER_MESSAGE_2', 'Lorem ipsum 2') },
49
+ { key: 'customer_message_3', text: t('CUSTOMER_MESSAGE_3', 'Lorem ipsum 3') },
50
+ { key: 'customer_message_4', text: t('CUSTOMER_MESSAGE_4', 'Lorem ipsum 4') }
51
+ ]
52
52
 
53
- const handleClickQuickMessage = (text: string) => {
54
- setMessage && setMessage(`${message}${text}`)
55
- }
53
+ const handleClickQuickMessage = (text: string) => {
54
+ setMessage && setMessage(`${message}${text}`)
55
+ }
56
56
 
57
57
  const onChangeMessage = (val: string) => {
58
58
  setMessage && setMessage(val)
@@ -239,37 +239,37 @@ const MessagesUI = (props: MessagesParams) => {
239
239
  }
240
240
 
241
241
  const renderAccessory = () => {
242
- return (
243
- <QuickMessageContainer
244
- style={{
245
- marginLeft: 10,
246
- marginBottom: 10
247
- }}
248
- contentContainerStyle={{
249
- alignItems: 'center',
250
- }}
251
- horizontal
252
- showsHorizontalScrollIndicator={false}
253
- >
254
- {quickMessageList.map((quickMessage, i) => (
255
- <OButton
256
- key={i}
257
- text={quickMessage.text}
258
- bgColor='#E9ECEF'
259
- borderColor='#E9ECEF'
260
- imgRightSrc={null}
261
- textStyle={{
262
- fontSize: 11,
263
- lineHeight: 16,
264
- color: '#414954'
265
- }}
266
- style={{ ...styles.editButton }}
267
- onClick={() => handleClickQuickMessage(quickMessage.text)}
268
- />
269
- ))}
270
- </QuickMessageContainer>
271
- )
272
- }
242
+ return (
243
+ <QuickMessageContainer
244
+ style={{
245
+ marginLeft: 10,
246
+ marginBottom: 10
247
+ }}
248
+ contentContainerStyle={{
249
+ alignItems: 'center',
250
+ }}
251
+ horizontal
252
+ showsHorizontalScrollIndicator={false}
253
+ >
254
+ {quickMessageList.map((quickMessage, i) => (
255
+ <OButton
256
+ key={i}
257
+ text={quickMessage.text}
258
+ bgColor='#E9ECEF'
259
+ borderColor='#E9ECEF'
260
+ imgRightSrc={null}
261
+ textStyle={{
262
+ fontSize: 11,
263
+ lineHeight: 16,
264
+ color: '#414954'
265
+ }}
266
+ style={{ ...styles.editButton }}
267
+ onClick={() => handleClickQuickMessage(quickMessage.text)}
268
+ />
269
+ ))}
270
+ </QuickMessageContainer>
271
+ )
272
+ }
273
273
 
274
274
  const renderInputToolbar = (props: typeof InputToolbarProps) => (
275
275
  <InputToolbar
@@ -285,20 +285,20 @@ const MessagesUI = (props: MessagesParams) => {
285
285
 
286
286
  const renderComposer = (props: typeof ComposerProps) => (
287
287
  chatDisabled ? (
288
- <View
289
- style={{
290
- width: '100%',
291
- flexDirection: 'column',
292
- alignItems: 'center'
293
- }}
294
- >
295
- <MaterialCommunityIcon
296
- name='close-octagon-outline'
297
- size={24}
298
- />
299
- <OText size={14}>{t('NOT_SEND_MESSAGES', 'You can\'t send messages because the order has ended')}</OText>
300
- </View>
301
- ) : (
288
+ <View
289
+ style={{
290
+ width: '100%',
291
+ flexDirection: 'column',
292
+ alignItems: 'center'
293
+ }}
294
+ >
295
+ <MaterialCommunityIcon
296
+ name='close-octagon-outline'
297
+ size={24}
298
+ />
299
+ <OText size={14}>{t('NOT_SEND_MESSAGES', 'You can\'t send messages because the order has ended')}</OText>
300
+ </View>
301
+ ) : (
302
302
  <View style={{
303
303
  flexDirection: 'row', width: '80%', alignItems: 'center', backgroundColor: theme.colors.backgroundGray100,
304
304
  borderRadius: 7.6,
@@ -387,7 +387,7 @@ const MessagesUI = (props: MessagesParams) => {
387
387
 
388
388
  const getViewHeight = () => {
389
389
  if (Platform.OS === 'android') {
390
- return height - top - bottom - (isKeyboardShow ? 270 : 24);
390
+ return height - top - bottom - (isKeyboardShow ? 300 : 24);
391
391
  } else {
392
392
  return height - top - bottom - 10;
393
393
  }
@@ -396,21 +396,53 @@ const MessagesUI = (props: MessagesParams) => {
396
396
  return (
397
397
  <View style={{ height: getViewHeight(), width: '100%', paddingTop: 12, backgroundColor: 'white' }}>
398
398
  <Wrapper>
399
- <Header>
400
- <OIconButton icon={theme.images.general.arrow_left} style={{ paddingStart: 10, borderColor: theme.colors.clear }} onClick={onClose} />
401
- <View style={{ marginRight: 10, shadowColor: theme.colors.black, shadowOpacity: 0.1, shadowOffset: { width: 0, height: 1 }, shadowRadius: 2 }}>
402
- <OIcon
403
- url={type === USER_TYPE.DRIVER ? order?.driver?.photo : order?.business?.logo}
404
- width={32}
405
- height={32}
406
- style={{ borderRadius: 7.6 }}
407
- />
408
- </View>
409
- <TitleHeader>
410
- <OText size={14} lineHeight={21} weight={'600'}>{type === USER_TYPE.DRIVER ? order?.driver?.name : order?.business?.name}</OText>
411
- <OText size={12} color={theme.colors.textSecondary}>{type === USER_TYPE.DRIVER ? t('DRIVER', 'Driver') : t('BUSINESS', 'Business')}</OText>
412
- </TitleHeader>
413
- </Header>
399
+ {!isMeesageListing ? (
400
+ <Header>
401
+ <OIconButton icon={theme.images.general.arrow_left} style={{ paddingStart: 10, borderColor: theme.colors.clear }} onClick={onClose} />
402
+ <View style={{ marginRight: 10, shadowColor: theme.colors.black, shadowOpacity: 0.1, shadowOffset: { width: 0, height: 1 }, shadowRadius: 2 }}>
403
+ <OIcon
404
+ url={type === USER_TYPE.DRIVER ? order?.driver?.photo : order?.business?.logo}
405
+ width={32}
406
+ height={32}
407
+ style={{ borderRadius: 7.6 }}
408
+ />
409
+ </View>
410
+ <TitleHeader>
411
+ <OText size={14} lineHeight={21} weight={'600'}>{type === USER_TYPE.DRIVER ? order?.driver?.name : order?.business?.name}</OText>
412
+ <OText size={12} color={theme.colors.textSecondary}>{type === USER_TYPE.DRIVER ? t('DRIVER', 'Driver') : t('BUSINESS', 'Business')}</OText>
413
+ </TitleHeader>
414
+ </Header>
415
+ ) : (
416
+ <ProfileMessageHeader>
417
+ <View style={{ ...styles.headerTitle }}>
418
+ <TouchableOpacity
419
+ style={styles.headerItem}
420
+ onPress={onClose}>
421
+ <OIcon src={theme.images.general.arrow_left} width={16} />
422
+ </TouchableOpacity>
423
+ <OText size={18}>{t('ORDER', theme?.defaultLanguages?.ORDER || 'Order')} #{order?.id}</OText>
424
+ </View>
425
+ <View>
426
+ {order.business && (
427
+ <OIcon
428
+ url={order?.business?.logo}
429
+ width={32}
430
+ height={32}
431
+ style={{ borderRadius: 7.6 }}
432
+ />
433
+ )}
434
+
435
+ {order?.driver && (
436
+ <OIcon
437
+ url={order?.driver?.photo}
438
+ width={32}
439
+ height={32}
440
+ style={{ borderRadius: 7.6 }}
441
+ />
442
+ )}
443
+ </View>
444
+ </ProfileMessageHeader>
445
+ )}
414
446
  <GiftedChat
415
447
  messages={formattedMessages}
416
448
  user={{
@@ -460,15 +492,25 @@ const styles = StyleSheet.create({
460
492
  justifyContent: 'center',
461
493
  marginHorizontal: 4
462
494
  },
463
- editButton : {
464
- borderRadius: 50,
465
- backgroundColor: '#E9ECEF',
466
- marginRight: 10,
467
- height: 24,
468
- borderWidth: 1,
469
- paddingLeft: 0,
470
- paddingRight: 0
471
- }
495
+ editButton: {
496
+ borderRadius: 50,
497
+ backgroundColor: '#E9ECEF',
498
+ marginRight: 10,
499
+ height: 24,
500
+ borderWidth: 1,
501
+ paddingLeft: 0,
502
+ paddingRight: 0
503
+ },
504
+ headerTitle: {
505
+ flexDirection: 'row',
506
+ alignItems: 'center'
507
+ },
508
+ headerItem: {
509
+ overflow: 'hidden',
510
+ width: 35,
511
+ marginVertical: 18,
512
+ }
513
+
472
514
  })
473
515
 
474
516
  export const Messages = (props: MessagesParams) => {
@@ -17,3 +17,11 @@ export const Header = styled.View`
17
17
  export const TitleHeader = styled.View``
18
18
 
19
19
  export const QuickMessageContainer = styled.ScrollView``
20
+
21
+ export const ProfileMessageHeader = styled.View`
22
+ flex-direction: row;
23
+ justify-content: space-between;
24
+ align-items: center;
25
+ padding-bottom: 0px;
26
+ padding-horizontal: 20px;
27
+ `
@@ -13,6 +13,7 @@ import { Platform, StyleSheet, TouchableOpacity, View } from 'react-native';
13
13
  import { ProfileParams } from '../../types';
14
14
  import { LogoutButton } from '../LogoutButton'
15
15
  import { LanguageSelector } from '../LanguageSelector'
16
+ import MessageCircle from 'react-native-vector-icons/AntDesign'
16
17
 
17
18
  import {
18
19
  OIcon,
@@ -78,6 +79,11 @@ const ProfileListUI = (props: ProfileParams) => {
78
79
  pagePadding: {
79
80
  paddingLeft: 40,
80
81
  paddingRight: 40
82
+ },
83
+ messageIconStyle: {
84
+ fontSize: 18,
85
+ fontWeight: 'bold',
86
+ marginEnd: 14
81
87
  }
82
88
  });
83
89
 
@@ -150,6 +156,10 @@ const ProfileListUI = (props: ProfileParams) => {
150
156
  <OIcon src={theme.images.general.pin} width={16} color={theme.colors.textNormal} style={{ marginEnd: 14 }} />
151
157
  <OText size={14} lineHeight={24} weight={'400'} color={theme.colors.textNormal}>{t('MY_SAVED_PLACES', 'My saved places')}</OText>
152
158
  </ListItem>
159
+ <ListItem onPress={() => onRedirect('Messages', { isFromProfile: true, isGoBack: true })} activeOpacity={0.7}>
160
+ <MessageCircle name='message1' style={styles.messageIconStyle} color={theme.colors.textNormal} />
161
+ <OText size={14} lineHeight={24} weight={'400'} color={theme.colors.textNormal}>{t('MESSAGES', 'Messages')}</OText>
162
+ </ListItem>
153
163
  <ListItem onPress={() => navigation.navigate('Help', {})} activeOpacity={0.7}>
154
164
  <OIcon src={theme.images.general.ic_help} width={16} color={theme.colors.textNormal} style={{ marginEnd: 14 }} />
155
165
  <OText size={14} lineHeight={24} weight={'400'} color={theme.colors.textNormal}>{t('HELP', 'Help')}</OText>
@@ -177,4 +177,22 @@ export const getTypesText = (value: number) => {
177
177
  */
178
178
  export const convertToRadian = (value: number) => {
179
179
  return value * Math.PI / 180
180
+ }
181
+
182
+ /**
183
+ * Function to distance between two locations
184
+ * @param lat1 Lat for first location
185
+ * @param lon1 Lon for first location
186
+ * @param lat2 Lat for second location
187
+ * @param lon2 Lon for second location
188
+ */
189
+ export const getDistance = (lat1: any, lon1: any, lat2: any, lon2: any) => {
190
+ const R = 6371 // km
191
+ const dLat = convertToRadian(lat2 - lat1)
192
+ const dLon = convertToRadian(lon2 - lon1)
193
+ const curLat1 = convertToRadian(lat1)
194
+ const curLat2 = convertToRadian(lat2)
195
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(curLat1) * Math.cos(curLat2)
196
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
197
+ return R * c
180
198
  }
@@ -1,5 +1,6 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder';
3
+ import Geolocation from '@react-native-community/geolocation'
3
4
  import {
4
5
  View,
5
6
  StyleSheet,
@@ -28,6 +29,7 @@ import {
28
29
  TopHeader,
29
30
  DropOptionButton,
30
31
  WrapSearchBar,
32
+ FarAwayMessage
31
33
  } from './styles';
32
34
 
33
35
  import { SearchBar } from '../SearchBar';
@@ -41,6 +43,8 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
41
43
  import { BusinessFeaturedController } from '../BusinessFeaturedController';
42
44
  import { getTypesText } from '../../utils';
43
45
  import NavBar from '../NavBar';
46
+ import { getDistance } from '../../utils'
47
+ import Ionicons from 'react-native-vector-icons/Ionicons'
44
48
 
45
49
  const PIXELS_TO_SCROLL = 1000;
46
50
 
@@ -97,6 +101,15 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
97
101
  height: 260,
98
102
  paddingHorizontal: 40
99
103
  },
104
+ iconStyle: {
105
+ fontSize: 18,
106
+ color: theme.colors.warning5,
107
+ marginRight: 8
108
+ },
109
+ farAwayMsg: {
110
+ paddingVertical: 6,
111
+ paddingHorizontal: 20
112
+ }
100
113
  });
101
114
 
102
115
 
@@ -109,6 +122,7 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
109
122
  const { top } = useSafeAreaInsets();
110
123
 
111
124
  const [featuredBusiness, setFeaturedBusinesses] = useState(Array);
125
+ const [isFarAway, setIsFarAway] = useState(false)
112
126
 
113
127
  const configTypes = configs?.order_types_allowed?.value.split('|').map((value: any) => Number(value)) || [];
114
128
 
@@ -135,6 +149,19 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
135
149
  }
136
150
  }, [businessesList.businesses]);
137
151
 
152
+ useEffect(() => {
153
+ Geolocation.getCurrentPosition((pos) => {
154
+ const crd = pos.coords
155
+ const distance = getDistance(crd.latitude, crd.longitude, orderState?.options?.address?.location?.lat, orderState?.options?.address?.location?.lng)
156
+ if (distance > 20) setIsFarAway(true)
157
+ else setIsFarAway(false)
158
+ }, (err) => {
159
+ console.log(`ERROR(${err.code}): ${err.message}`)
160
+ }, {
161
+ enableHighAccuracy: true, timeout: 15000, maximumAge: 10000
162
+ })
163
+ }, [orderState?.options?.address?.location])
164
+
138
165
  return (
139
166
  <ScrollView
140
167
  style={styles.container}
@@ -171,6 +198,12 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
171
198
  {orderState?.options?.address?.address}
172
199
  </OText>
173
200
  </AddressInput>
201
+ {isFarAway && (
202
+ <FarAwayMessage style={styles.farAwayMsg}>
203
+ <Ionicons name='md-warning-outline' style={styles.iconStyle} />
204
+ <OText size={12} numberOfLines={1} ellipsizeMode={'tail'} color={theme.colors.textNormal}>{t('YOU_ARE_FAR_FROM_ADDRESS', 'Your are far from this address')}</OText>
205
+ </FarAwayMessage>
206
+ )}
174
207
  <OrderControlContainer>
175
208
  <View style={styles.wrapperOrderOptions}>
176
209
  <DropOptionButton
@@ -95,3 +95,12 @@ export const WrapSearchBar = styled.View`
95
95
  background-color: ${(props: any) => props.theme.colors.white};
96
96
  flex: 1;
97
97
  `
98
+
99
+ export const FarAwayMessage = styled.View`
100
+ flex-direction: row;
101
+ align-items: center;
102
+ background-color: ${(props: any) => props.theme.colors.warning1};
103
+ border-radius: 7.6px;
104
+ border: 1px solid ${(props: any) => props.theme.colors.warning5};
105
+ width: 100%;
106
+ `
@@ -251,3 +251,30 @@ export const getTextOrderStatus = (s: string, t: any) => {
251
251
  const objectStatus = orderStatus.find((o) => o.key === status)
252
252
  return objectStatus && objectStatus
253
253
  }
254
+
255
+ /**
256
+ * Function to transform degree to radian
257
+ * @param {number} value for transform
258
+ *
259
+ */
260
+ export const convertToRadian = (value: number) => {
261
+ return value * Math.PI / 180
262
+ }
263
+
264
+ /**
265
+ * Function to distance between two locations
266
+ * @param lat1 Lat for first location
267
+ * @param lon1 Lon for first location
268
+ * @param lat2 Lat for second location
269
+ * @param lon2 Lon for second location
270
+ */
271
+ export const getDistance = (lat1: any, lon1: any, lat2: any, lon2: any) => {
272
+ const R = 6371 // km
273
+ const dLat = convertToRadian(lat2 - lat1)
274
+ const dLon = convertToRadian(lon2 - lon1)
275
+ const curLat1 = convertToRadian(lat1)
276
+ const curLat2 = convertToRadian(lat2)
277
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(curLat1) * Math.cos(curLat2)
278
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
279
+ return R * c
280
+ }
@@ -1,7 +1,10 @@
1
- import React, { useState } from 'react'
1
+ import React, { useState, useEffect } from 'react'
2
2
  import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder'
3
3
  import { View, StyleSheet, ScrollView, Platform, PanResponder, I18nManager } from 'react-native'
4
4
  import MaterialIcon from 'react-native-vector-icons/MaterialIcons'
5
+ import Geolocation from '@react-native-community/geolocation'
6
+ import Ionicons from 'react-native-vector-icons/Ionicons'
7
+
5
8
  import {
6
9
  BusinessList as BusinessesListingController,
7
10
  useLanguage,
@@ -13,7 +16,7 @@ import {
13
16
  useToast
14
17
  } from 'ordering-components/native'
15
18
 
16
- import { BusinessListContainer, Divider, Search, OrderControlContainer, AddressInput, WrapMomentOption } from './styles'
19
+ import { BusinessListContainer, Divider, Search, OrderControlContainer, AddressInput, WrapMomentOption, FarAwayMessage } from './styles'
17
20
 
18
21
  import NavBar from '../NavBar'
19
22
  import { SearchBar } from '../SearchBar'
@@ -27,6 +30,7 @@ import { OrderTypeSelector } from '../OrderTypeSelector'
27
30
  import { MomentOption } from '../MomentOption'
28
31
  import { HighestRatedBusinesses } from '../HighestRatedBusinesses'
29
32
  import { useTheme } from 'styled-components/native'
33
+ import { getDistance } from '../../utils'
30
34
 
31
35
  const PIXELS_TO_SCROLL = 1200
32
36
 
@@ -61,7 +65,16 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
61
65
  borderColor: theme.colors.backgroundGray,
62
66
  borderWidth: 1,
63
67
  borderRadius: 10,
64
- }
68
+ },
69
+ iconStyle: {
70
+ fontSize: 18,
71
+ color: theme.colors.warning5,
72
+ marginRight: 8
73
+ },
74
+ farAwayMsg: {
75
+ paddingVertical: 6,
76
+ paddingHorizontal: 20
77
+ }
65
78
  })
66
79
 
67
80
  const [, t] = useLanguage()
@@ -73,6 +86,7 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
73
86
 
74
87
  const [openMomentOption, setOpenMomentOption] = useState(false)
75
88
  const configTypes = configs?.order_types_allowed?.value.split('|').map((value: any) => Number(value)) || []
89
+ const [isFarAway, setIsFarAway] = useState(false)
76
90
 
77
91
  const handleScroll = ({ nativeEvent }: any) => {
78
92
  const y = nativeEvent.contentOffset.y
@@ -85,6 +99,19 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
85
99
  }
86
100
  }
87
101
 
102
+ useEffect(() => {
103
+ Geolocation.getCurrentPosition((pos) => {
104
+ const crd = pos.coords
105
+ const distance = getDistance(crd.latitude, crd.longitude, orderState?.options?.address?.location?.lat, orderState?.options?.address?.location?.lng)
106
+ if (distance > 20) setIsFarAway(true)
107
+ else setIsFarAway(false)
108
+ }, (err) => {
109
+ console.log(`ERROR(${err.code}): ${err.message}`)
110
+ }, {
111
+ enableHighAccuracy: true, timeout: 15000, maximumAge: 10000
112
+ })
113
+ }, [orderState?.options?.address?.location])
114
+
88
115
  return (
89
116
  <BusinessListContainer>
90
117
  {!auth && (
@@ -114,6 +141,12 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
114
141
  style={{ marginRight: 10 }}
115
142
  />
116
143
  </AddressInput>
144
+ {isFarAway && (
145
+ <FarAwayMessage style={styles.farAwayMsg}>
146
+ <Ionicons name='md-warning-outline' style={styles.iconStyle} />
147
+ <OText size={12} numberOfLines={1} ellipsizeMode={'tail'} color={theme.colors.textNormal}>{t('YOU_ARE_FAR_FROM_ADDRESS', 'Your are far from this address')}</OText>
148
+ </FarAwayMessage>
149
+ )}
117
150
  <View style={styles.wrapperOrderOptions}>
118
151
  <OrderTypeSelector configTypes={configTypes} />
119
152
  <WrapMomentOption
@@ -52,3 +52,11 @@ export const WrapMomentOption = styled.TouchableOpacity`
52
52
  margin-horizontal: 10px;
53
53
  max-width: 240px;
54
54
  `
55
+
56
+ export const FarAwayMessage = styled.View`
57
+ flex-direction: row;
58
+ align-items: center;
59
+ background-color: ${(props: any) => props.theme.colors.warning1};
60
+ border-radius: 7.6px;
61
+ border: 1px solid ${(props: any) => props.theme.colors.warning5};
62
+ `
@@ -162,3 +162,30 @@ export const transformCountryCode = (countryCode : number) => {
162
162
  return parser(value)
163
163
  }
164
164
  }
165
+
166
+ /**
167
+ * Function to transform degree to radian
168
+ * @param {number} value for transform
169
+ *
170
+ */
171
+ export const convertToRadian = (value: number) => {
172
+ return value * Math.PI / 180
173
+ }
174
+
175
+ /**
176
+ * Function to distance between two locations
177
+ * @param lat1 Lat for first location
178
+ * @param lon1 Lon for first location
179
+ * @param lat2 Lat for second location
180
+ * @param lon2 Lon for second location
181
+ */
182
+ export const getDistance = (lat1: any, lon1: any, lat2: any, lon2: any) => {
183
+ const R = 6371 // km
184
+ const dLat = convertToRadian(lat2 - lat1)
185
+ const dLon = convertToRadian(lon2 - lon1)
186
+ const curLat1 = convertToRadian(lat1)
187
+ const curLat2 = convertToRadian(lat2)
188
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(curLat1) * Math.cos(curLat2)
189
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
190
+ return R * c
191
+ }