ordering-ui-react-native 0.14.70 → 0.14.73

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 (34) hide show
  1. package/package.json +1 -1
  2. package/src/components/ProductForm/index.tsx +1 -1
  3. package/themes/kiosk/index.tsx +6 -0
  4. package/themes/kiosk/src/components/BusinessController/index.tsx +67 -0
  5. package/themes/kiosk/src/components/BusinessController/styles.tsx +23 -0
  6. package/themes/kiosk/src/components/BusinessesListing/index.tsx +119 -0
  7. package/themes/kiosk/src/components/BusinessesListing/styles.tsx +24 -0
  8. package/themes/kiosk/src/components/LoginForm/index.tsx +62 -2
  9. package/themes/kiosk/src/components/LogoutButton/index.tsx +74 -0
  10. package/themes/kiosk/src/types/index.d.ts +1 -0
  11. package/themes/original/src/components/BusinessBasicInformation/index.tsx +32 -1
  12. package/themes/original/src/components/BusinessInformation/index.tsx +7 -2
  13. package/themes/original/src/components/BusinessesListing/index.tsx +8 -9
  14. package/themes/original/src/components/Cart/index.tsx +8 -8
  15. package/themes/original/src/components/Checkout/index.tsx +82 -70
  16. package/themes/original/src/components/LoginForm/index.tsx +6 -4
  17. package/themes/original/src/components/OrderDetails/index.tsx +58 -6
  18. package/themes/original/src/components/OrderProgress/index.tsx +39 -31
  19. package/themes/original/src/components/OrderSummary/index.tsx +8 -8
  20. package/themes/original/src/components/OrdersOption/index.tsx +40 -16
  21. package/themes/original/src/components/OrdersOption/styles.tsx +5 -0
  22. package/themes/original/src/components/PhoneInputNumber/index.tsx +1 -1
  23. package/themes/original/src/components/PhoneInputNumber/styles.tsx +1 -1
  24. package/themes/original/src/components/ProductForm/index.tsx +42 -11
  25. package/themes/original/src/components/ProductForm/styles.tsx +1 -1
  26. package/themes/original/src/components/ProductOptionSubOption/index.tsx +1 -1
  27. package/themes/original/src/components/ProductOptionSubOption/styles.tsx +1 -1
  28. package/themes/original/src/components/SingleProductCard/index.tsx +15 -8
  29. package/themes/original/src/components/UpsellingProducts/index.tsx +1 -4
  30. package/themes/original/src/components/UserProfile/index.tsx +13 -11
  31. package/themes/original/src/components/WalletTransactionItem/index.tsx +5 -5
  32. package/themes/original/src/components/Wallets/styles.tsx +1 -1
  33. package/themes/original/src/components/shared/OInput.tsx +6 -2
  34. package/themes/original/src/utils/index.tsx +7 -0
@@ -2,12 +2,12 @@ import React, { useState, useEffect } from 'react'
2
2
  import { OrderList, useLanguage, useOrder, ToastType, useToast } from 'ordering-components/native'
3
3
  import { useTheme } from 'styled-components/native';
4
4
  import { useFocusEffect } from '@react-navigation/native'
5
- import { OText } from '../shared'
5
+ import { OText, OButton } from '../shared'
6
6
  import { NotFoundSource } from '../NotFoundSource'
7
7
  import { ActiveOrders } from '../ActiveOrders'
8
8
  import { PreviousOrders } from '../PreviousOrders'
9
9
 
10
- import { OptionTitle } from './styles'
10
+ import { OptionTitle, NoOrdersWrapper } from './styles'
11
11
  import { OrdersOptionParams } from '../../types'
12
12
 
13
13
  import {
@@ -32,6 +32,8 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
32
32
  loadMoreStatus,
33
33
  loadMoreOrders,
34
34
  loadOrders,
35
+ setOrdersLength,
36
+ ordersLength
35
37
  } = props
36
38
 
37
39
  const theme = useTheme();
@@ -112,28 +114,50 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
112
114
  }
113
115
  }, [loadMoreStatus, loading, pagination])
114
116
 
117
+ useEffect(() => {
118
+ if (loading) return
119
+
120
+ const updateOrders = orders.filter((order: any) => orderStatus.includes(order.status))
121
+
122
+ if (activeOrders) {
123
+ setOrdersLength && setOrdersLength({ ...ordersLength, activeOrdersLength: updateOrders?.length })
124
+ } else if (!preOrders) {
125
+ setOrdersLength && setOrdersLength({ ...ordersLength, previousOrdersLength: updateOrders?.length })
126
+ }
127
+ }, [orders?.length])
128
+
115
129
  return (
116
130
  <>
117
- {(orders.length > 0) && (
118
- <>
119
- <OptionTitle>
120
- <OText size={16} lineHeight={24} weight={'500'} color={theme.colors.textNormal} mBottom={10} >
121
- {titleContent || (activeOrders
122
- ? t('ACTIVE', 'Active')
123
- : preOrders
124
- ? t('PREORDERS', 'Preorders')
125
- : t('PAST', 'Past'))}
126
- </OText>
127
- </OptionTitle>
128
- </>
129
- )}
130
- {!loading && orders.length === 0 && (
131
+ <OptionTitle>
132
+ <OText size={16} lineHeight={24} weight={'500'} color={theme.colors.textNormal} mBottom={10} >
133
+ {titleContent || (activeOrders
134
+ ? t('ACTIVE', 'Active')
135
+ : preOrders
136
+ ? t('PREORDERS', 'Preorders')
137
+ : t('PAST', 'Past'))}
138
+ </OText>
139
+ </OptionTitle>
140
+ {!(activeOrders && ordersLength.activeOrdersLength === 0 && ordersLength.previousOrdersLength === 0) && !loading && orders.length === 0 && (
131
141
  <NotFoundSource
132
142
  content={t('NO_RESULTS_FOUND', 'Sorry, no results found')}
133
143
  image={imageFails}
134
144
  conditioned
135
145
  />
136
146
  )}
147
+ {!loading && ordersLength.activeOrdersLength === 0 && ordersLength.previousOrdersLength === 0 && activeOrders && (
148
+ <NoOrdersWrapper>
149
+ <OText size={14} numberOfLines={1}>
150
+ {t('YOU_DONT_HAVE_ORDERS', 'You don\'t have any orders')}
151
+ </OText>
152
+ <OButton
153
+ text={t('ORDER_NOW', 'Order now')}
154
+ onClick={() => onNavigationRedirect && onNavigationRedirect('BusinessList')}
155
+ textStyle={{ color: 'white', fontSize: 14 }}
156
+ style={{ borderRadius: 7.6, marginBottom: 10, marginTop: 10, height: 44, paddingLeft: 10, paddingRight: 10 }}
157
+ />
158
+
159
+ </NoOrdersWrapper>
160
+ )}
137
161
  {loading && (
138
162
  <>
139
163
  {!activeOrders ? (
@@ -3,3 +3,8 @@ import styled from 'styled-components/native'
3
3
  export const OptionTitle = styled.View`
4
4
  margin-top: 24px;
5
5
  `
6
+
7
+ export const NoOrdersWrapper = styled.View`
8
+ flex-direction: column;
9
+ align-items: center;
10
+ `
@@ -96,7 +96,7 @@ export const PhoneInputNumber = (props: PhoneInputParams) => {
96
96
  }, [userphoneNumber])
97
97
 
98
98
  return (
99
- <Wrapper>
99
+ <Wrapper onPress={() => forwardRef?.current?.focus?.()}>
100
100
  <PhoneInput
101
101
  ref={phoneInput}
102
102
  disabled={isDisabled}
@@ -1,3 +1,3 @@
1
1
  import styled from 'styled-components/native';
2
2
 
3
- export const Wrapper = styled.View``
3
+ export const Wrapper = styled.Pressable``
@@ -4,7 +4,9 @@ import {
4
4
  useSession,
5
5
  useLanguage,
6
6
  useOrder,
7
- useUtils
7
+ useUtils,
8
+ ToastType,
9
+ useToast
8
10
  } from 'ordering-components/native';
9
11
  import { useTheme } from 'styled-components/native';
10
12
  import { ProductIngredient } from '../ProductIngredient';
@@ -13,11 +15,12 @@ import Swiper from 'react-native-swiper'
13
15
  import FastImage from 'react-native-fast-image';
14
16
  import IconAntDesign from 'react-native-vector-icons/AntDesign';
15
17
  import YoutubePlayer from "react-native-youtube-iframe"
18
+ import { TextInput } from 'react-native'
16
19
  import {
17
20
  Grayscale
18
21
  } from 'react-native-color-matrix-image-filters'
19
22
 
20
- import { View, TouchableOpacity, StyleSheet, Dimensions, I18nManager, SafeAreaView, Button, Alert } from 'react-native';
23
+ import { View, TouchableOpacity, StyleSheet, Dimensions, I18nManager, SafeAreaView, Platform, Button } from 'react-native';
21
24
 
22
25
  import {
23
26
  WrapHeader,
@@ -54,6 +57,7 @@ export const ProductOptionsUI = (props: any) => {
54
57
  productCart,
55
58
  increment,
56
59
  decrement,
60
+ handleChangeProductCartQuantity,
57
61
  showOption,
58
62
  maxProductQuantity,
59
63
  errors,
@@ -65,6 +69,7 @@ export const ProductOptionsUI = (props: any) => {
65
69
  } = props;
66
70
 
67
71
  const theme = useTheme();
72
+ const [, { showToast }] = useToast()
68
73
 
69
74
  const styles = StyleSheet.create({
70
75
  mainContainer: {
@@ -236,6 +241,14 @@ export const ProductOptionsUI = (props: any) => {
236
241
  setPlaying((prev) => !prev);
237
242
  }, []);
238
243
 
244
+ const onChangeProductCartQuantity = (quantity: number) => {
245
+ if (quantity >= maxProductQuantity) {
246
+ showToast(ToastType.Error, t('MAX_QUANTITY', 'The max quantity is _number_').replace('_number_', maxProductQuantity))
247
+ return
248
+ }
249
+ handleChangeProductCartQuantity(quantity)
250
+ }
251
+
239
252
  useEffect(() => {
240
253
  const imageList: any = []
241
254
  const videoList: any = []
@@ -816,7 +829,7 @@ export const ProductOptionsUI = (props: any) => {
816
829
  )}
817
830
  </ScrollView>
818
831
  {!loading && !error && product && (
819
- <ProductActions>
832
+ <ProductActions ios={Platform?.OS === 'ios'}>
820
833
  <OText size={16} lineHeight={24} weight={'600'}>
821
834
  {productCart.total ? parsePrice(productCart?.total) : ''}
822
835
  </OText>
@@ -835,14 +848,32 @@ export const ProductOptionsUI = (props: any) => {
835
848
  }
836
849
  />
837
850
  </TouchableOpacity>
838
- <OText
839
- size={12}
840
- lineHeight={18}
841
- style={{ minWidth: 40, textAlign: 'center' }}
842
- >
843
- {qtyBy?.pieces && productCart.quantity}
844
- {qtyBy?.weight_unit && productCart.quantity * product?.weight}
845
- </OText>
851
+ {qtyBy?.pieces && (
852
+ <TextInput
853
+ keyboardType='numeric'
854
+ value={`${productCart.quantity}` || ''}
855
+ onChangeText={(val: any) => onChangeProductCartQuantity(parseInt(val))}
856
+ editable={!orderState.loading}
857
+ style={{
858
+ borderWidth: 1,
859
+ textAlign: 'center',
860
+ minWidth: 60,
861
+ borderRadius: 8,
862
+ borderColor: theme.colors.inputBorderColor,
863
+ height: 44,
864
+ marginHorizontal: 10
865
+ }}
866
+ />
867
+ )}
868
+ {qtyBy?.weight_unit && (
869
+ <OText
870
+ size={12}
871
+ lineHeight={18}
872
+ style={{ minWidth: 40, textAlign: 'center' }}
873
+ >
874
+ {productCart.quantity * product?.weight}
875
+ </OText>
876
+ )}
846
877
  <TouchableOpacity
847
878
  onPress={increment}
848
879
  disabled={
@@ -71,7 +71,7 @@ export const ProductActions = styled.View`
71
71
  position: absolute;
72
72
  bottom: 0px;
73
73
  min-height: 70px;
74
- padding-top: 12px;
74
+ padding-top: ${(props : any) => props.ios ? '20px' : '0'};
75
75
  padding-horizontal: 40px;
76
76
  width: 100%;
77
77
  flex-direction: row;
@@ -52,7 +52,7 @@ export const ProductOptionSubOptionUI = (props: any) => {
52
52
  const disableIncrement = option?.limit_suboptions_by_max ? balance === option?.max : state.quantity === suboption?.max || (!state.selected && balance === option?.max)
53
53
  const price = option?.with_half_option && suboption?.half_price && state.position !== 'whole' ? suboption?.half_price : suboption?.price
54
54
  return (
55
- <Container>
55
+ <Container onPress={() => handleSuboptionClick()}>
56
56
  <IconControl disabled={disabled} onPress={() => handleSuboptionClick()}>
57
57
  {((option?.min === 0 && option?.max === 1) || option?.max > 1) ? (
58
58
  state?.selected ? (
@@ -1,6 +1,6 @@
1
1
  import styled, { css } from 'styled-components/native'
2
2
 
3
- export const Container = styled.View`
3
+ export const Container = styled.TouchableOpacity`
4
4
  flex-direction: row;
5
5
  align-items: center;
6
6
  justify-content: space-between;
@@ -135,14 +135,21 @@ export const SingleProductCard = (props: SingleProductCardParams) => {
135
135
  {product?.description}
136
136
  </OText>
137
137
  </CardInfo>
138
- <FastImage
139
- style={styles.productStyle}
140
- source={{
141
- uri: optimizeImage(product?.images, 'h_75,c_limit'),
142
- priority: FastImage.priority.normal,
143
- }}
144
- resizeMode={FastImage.resizeMode.cover}
145
- />
138
+ {product?.images ? (
139
+ <FastImage
140
+ style={styles.productStyle}
141
+ source={{
142
+ uri: optimizeImage(product?.images, 'h_75,c_limit'),
143
+ priority: FastImage.priority.normal,
144
+ }}
145
+ resizeMode={FastImage.resizeMode.cover}
146
+ />
147
+ ) : (
148
+ <OIcon
149
+ src={theme?.images?.dummies?.product}
150
+ style={styles.productStyle}
151
+ />
152
+ )}
146
153
  {(isSoldOut || maxProductQuantity <= 0) && (
147
154
  <SoldOut>
148
155
  <OText size={12} weight="bold" color={theme.colors.textSecondary} style={styles.soldOutTextStyle}>
@@ -155,9 +155,6 @@ const UpsellingProductsUI = (props: UpsellingProductsParams) => {
155
155
  <TopActions onPress={() => onGoBack()}>
156
156
  <OIcon src={theme.images.general.arrow_left} width={15} />
157
157
  </TopActions>
158
- <TopActions style={styles.cancelBtn} onPress={() => handleUpsellingPage()}>
159
- <OText size={12} color={theme.colors.textSecondary}>{t('CANCEL', 'Cancel')}</OText>
160
- </TopActions>
161
158
  </TopBar>
162
159
  <ScrollView style={{ marginBottom: props.isPage ? 40 : bottom + (Platform.OS == 'ios' ? 96 : 130) }} showsVerticalScrollIndicator={false}>
163
160
  <View style={{ paddingHorizontal: 40 }}>
@@ -178,7 +175,7 @@ const UpsellingProductsUI = (props: UpsellingProductsParams) => {
178
175
  <View
179
176
  style={{
180
177
  alignItems: 'center',
181
- bottom: props.isPage ? 20 : Platform.OS === 'ios' ? bottom + 59 : bottom + 125
178
+ bottom: props.isPage ? Platform.OS === 'ios' ? 0 : 20 : Platform.OS === 'ios' ? bottom + 59 : bottom + 125
182
179
  }}
183
180
  >
184
181
  <OButton
@@ -5,7 +5,7 @@ import {
5
5
  useLanguage,
6
6
  ToastType,
7
7
  useToast,
8
- useConfig
8
+ useConfig
9
9
  } from 'ordering-components/native';
10
10
  import { useTheme } from 'styled-components/native';
11
11
  import { useForm } from 'react-hook-form';
@@ -85,7 +85,7 @@ const ProfileListUI = (props: ProfileParams) => {
85
85
  messageIconStyle: {
86
86
  fontSize: 18,
87
87
  fontWeight: 'bold',
88
- marginEnd: 14
88
+ marginEnd: 14
89
89
  }
90
90
  });
91
91
 
@@ -99,7 +99,7 @@ const ProfileListUI = (props: ProfileParams) => {
99
99
  const { height } = useWindowDimensions();
100
100
  const { top, bottom } = useSafeAreaInsets();
101
101
 
102
- const isWalletEnabled = configs?.wallet_enabled?.value === '1' && (configs?.wallet_cash_enabled?.value === '1' || configs?.wallet_credit_point_enabled?.value === '1')
102
+ const isWalletEnabled = configs?.wallet_enabled?.value === '1' && (configs?.wallet_cash_enabled?.value === '1' || configs?.wallet_credit_point_enabled?.value === '1')
103
103
 
104
104
  const onRedirect = (route: string, params?: any) => {
105
105
  navigation.navigate(route, params)
@@ -136,7 +136,9 @@ const ProfileListUI = (props: ProfileParams) => {
136
136
 
137
137
  return (
138
138
  <View style={{ flex: 1, height: height - top - bottom - 62 }}>
139
- <OText size={24} color={theme.colors.textNormal} lineHeight={36} weight={Platform.OS === 'ios' ? '600' : 'bold'} style={{ marginTop: 14, marginBottom: 24, ...styles.pagePadding }}>{t('PROFILE', 'Profile')}</OText>
139
+ <OText size={24} style={{ marginTop: 15, paddingHorizontal: 40 }}>
140
+ {t('PROFILE', 'Profile')}
141
+ </OText>
140
142
  <CenterView style={styles.pagePadding}>
141
143
  <View style={styles.photo}>
142
144
  <OIcon
@@ -147,7 +149,7 @@ const ProfileListUI = (props: ProfileParams) => {
147
149
  />
148
150
  </View>
149
151
  <View style={{ flexBasis: '70%' }}>
150
- <OText size={20} lineHeight={30} weight={Platform.OS === 'ios' ? '500' : 'bold'} color={theme.colors.textNormal}>{`${user?.name} ${user?.lastname}`}</OText>
152
+ <OText size={20} lineHeight={30} weight={Platform.OS === 'ios' ? '500' : 'bold'} color={theme.colors.textNormal}>{user?.name} {user?.lastname}</OText>
151
153
  <TouchableOpacity onPress={() => navigation.navigate('ProfileForm', { ...detailProps })}>
152
154
  <OText size={12} lineHeight={18} color={theme.colors.textSecondary} style={{ textDecorationLine: 'underline' }}>{t('VIEW_ACCOUNT', 'View account')}</OText>
153
155
  </TouchableOpacity>
@@ -165,12 +167,12 @@ const ProfileListUI = (props: ProfileParams) => {
165
167
  <MessageCircle name='message1' style={styles.messageIconStyle} color={theme.colors.textNormal} />
166
168
  <OText size={14} lineHeight={24} weight={'400'} color={theme.colors.textNormal}>{t('MESSAGES', 'Messages')}</OText>
167
169
  </ListItem>
168
- {!isWalletEnabled && (
169
- <ListItem onPress={() => onRedirect('Wallets', { isFromProfile: true, isGoBack: true })} activeOpacity={0.7}>
170
- <Ionicons name='wallet-outline' style={styles.messageIconStyle} color={theme.colors.textNormal} />
171
- <OText size={14} lineHeight={24} weight={'400'} color={theme.colors.textNormal}>{t('WALLETS', 'Wallets')}</OText>
172
- </ListItem>
173
- )}
170
+ {isWalletEnabled && (
171
+ <ListItem onPress={() => onRedirect('Wallets', { isFromProfile: true, isGoBack: true })} activeOpacity={0.7}>
172
+ <Ionicons name='wallet-outline' style={styles.messageIconStyle} color={theme.colors.textNormal} />
173
+ <OText size={14} lineHeight={24} weight={'400'} color={theme.colors.textNormal}>{t('WALLETS', 'Wallets')}</OText>
174
+ </ListItem>
175
+ )}
174
176
  <ListItem onPress={() => navigation.navigate('Help', {})} activeOpacity={0.7}>
175
177
  <OIcon src={theme.images.general.ic_help} width={16} color={theme.colors.textNormal} style={{ marginEnd: 14 }} />
176
178
  <OText size={14} lineHeight={24} weight={'400'} color={theme.colors.textNormal}>{t('HELP', 'Help')}</OText>
@@ -22,10 +22,10 @@ export const WalletTransactionItem = (props: any) => {
22
22
  const [{ parsePrice, parseDate }] = useUtils()
23
23
  const [, t] = useLanguage()
24
24
 
25
- const LANG_EVENT_KEY = `WALLET_${type.toUpperCase()}_${item?.event.toUpperCase()}_${item?.event_type.toUpperCase()}_${item?.amount >= 0 ? 'POSITIVE': 'NEGATIVE'}`
25
+ const LANG_EVENT_KEY = `WALLET_${type.toUpperCase()}_${item?.event.toUpperCase()}_${item?.event_type.toUpperCase()}_${item?.amount >= 0 ? 'POSITIVE' : 'NEGATIVE'}`
26
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`
27
+ ? `:author${item?.amount >= 0 ? 'Add' : 'Reduce'} money in Order No. :order_id`
28
+ : `:author${item?.amount >= 0 ? 'Add' : 'Reduce'} money`
29
29
 
30
30
  return (
31
31
  <Container>
@@ -44,8 +44,8 @@ export const WalletTransactionItem = (props: any) => {
44
44
  <MessageBlock>
45
45
  <OText>
46
46
  {t(LANG_EVENT_KEY, lang_event_text)
47
- .replace(':author', item?.event?.author?.name ?? '')
48
- .replace(':order_id', item?.event?.order_id ?? '')}
47
+ .replace(':author', item?.event?.author?.name ? item?.event?.author?.name + ' ' : '')
48
+ .replace(':order_id', item?.event?.order_id ? item?.event?.order_id + ' ' : '')}
49
49
  </OText>
50
50
  </MessageBlock>
51
51
  {!!item?.description && (
@@ -27,7 +27,7 @@ export const BalanceElement = styled.View`
27
27
  display: flex;
28
28
  flex-direction: row;
29
29
  justify-content: center;
30
- align-items: flex-end;
30
+ align-items: center;
31
31
  background-color: ${(props: any) => props.theme.colors.backgroundGray100};
32
32
  border-radius: 8px;
33
33
  `
@@ -37,9 +37,10 @@ interface Props extends TextInputProps {
37
37
  vectorIconColor?: string;
38
38
  forwardRef?: any;
39
39
  inputStyle?: TextStyle;
40
+ wrapperRef?: any;
40
41
  }
41
42
 
42
- const Wrapper = styled.View`
43
+ const Wrapper = styled.Pressable`
43
44
  background-color: ${(props: any) => props.theme.colors.backgroundLight};
44
45
  border-radius: 25px;
45
46
  border-width: 1px;
@@ -54,6 +55,7 @@ const Wrapper = styled.View`
54
55
  const OInput = (props: Props): React.ReactElement => {
55
56
  return (
56
57
  <Wrapper
58
+ onPress={() => props.forwardRef?.current?.focus?.()}
57
59
  style={{
58
60
  backgroundColor: props.bgColor,
59
61
  borderColor: props.borderColor,
@@ -87,7 +89,9 @@ const OInput = (props: Props): React.ReactElement => {
87
89
  returnKeyType={props.returnKeyType}
88
90
  onSubmitEditing={props.onSubmitEditing}
89
91
  blurOnSubmit={props.blurOnSubmit}
90
- ref={props.forwardRef}
92
+ ref={(e : any) => {
93
+ props.forwardRef.current = e
94
+ }}
91
95
  style={props?.inputStyle}
92
96
  />
93
97
  {props.iconRight && (
@@ -195,4 +195,11 @@ export const getDistance = (lat1: any, lon1: any, lat2: any, lon2: any) => {
195
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
196
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
197
197
  return R * c
198
+ }
199
+
200
+ export const formatUrlVideo = (url : string) => {
201
+ const regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/
202
+ const match = url.match(regExp)
203
+ const id = (match && match[7].length === 11) ? match[7] : false
204
+ return `https://www.youtube-nocookie.com/embed/${id}`
198
205
  }