ordering-ui-react-native 0.12.1 → 0.12.5

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 (29) hide show
  1. package/package.json +1 -1
  2. package/themes/business/src/components/MapView/index.tsx +52 -21
  3. package/themes/business/src/components/shared/OFab.tsx +8 -3
  4. package/themes/business/src/types/index.tsx +3 -1
  5. package/themes/franchises/src/components/Checkout/index.tsx +2 -2
  6. package/themes/franchises/src/components/ForgotPasswordForm/index.tsx +1 -1
  7. package/themes/franchises/src/components/LanguageSelector/index.tsx +8 -2
  8. package/themes/franchises/src/components/LoginForm/index.tsx +1 -1
  9. package/themes/franchises/src/components/PaymentOptions/index.tsx +5 -7
  10. package/themes/franchises/src/components/PaymentOptions/styles.tsx +2 -1
  11. package/themes/franchises/src/components/ProductItemAccordion/index.tsx +1 -1
  12. package/themes/franchises/src/components/SignupForm/index.tsx +1 -1
  13. package/themes/franchises/src/components/StripeRedirectForm/index.tsx +1 -1
  14. package/themes/franchises/src/components/UserFormDetails/index.tsx +1 -1
  15. package/themes/franchises/src/components/UserProfile/index.tsx +1 -1
  16. package/themes/franchises/src/components/UserProfileForm/index.tsx +1 -1
  17. package/themes/franchises/src/components/shared/OToast.tsx +1 -1
  18. package/themes/instacart/src/components/BusinessProductsList/index.tsx +14 -5
  19. package/themes/instacart/src/components/BusinessProductsListing/index.tsx +44 -5
  20. package/themes/instacart/src/components/SingleProductCard/index.tsx +8 -4
  21. package/themes/instacart/src/components/SingleProductCard/styles.tsx +0 -3
  22. package/themes/instacart/src/types/index.tsx +4 -2
  23. package/themes/kiosk/src/components/BusinessMenu/index.tsx +49 -5
  24. package/themes/kiosk/src/components/BusinessProductsListing/index.tsx +6 -2
  25. package/themes/kiosk/src/components/CartBottomSheet/index.tsx +10 -1
  26. package/themes/kiosk/src/components/CartContent/index.tsx +7 -1
  27. package/themes/kiosk/src/components/CategoriesMenu/index.tsx +11 -1
  28. package/themes/kiosk/src/components/UpsellingProducts/index.tsx +13 -3
  29. package/themes/kiosk/src/types/index.d.ts +5 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ordering-ui-react-native",
3
- "version": "0.12.1",
3
+ "version": "0.12.5",
4
4
  "description": "Reusable components made in react native",
5
5
  "main": "src/index.tsx",
6
6
  "author": "ordering.inc",
@@ -12,16 +12,17 @@ import Alert from '../../providers/AlertProvider';
12
12
  import { useTheme } from 'styled-components/native';
13
13
  import { useLocation } from '../../hooks/useLocation';
14
14
  import Icon from 'react-native-vector-icons/FontAwesome5';
15
- import { OIcon, OText } from '../shared'
16
-
15
+ import { OIcon, OText, OFab } from '../shared'
17
16
  const MapViewComponent = (props: MapViewParams) => {
18
17
 
19
18
  const {
20
- onNavigationRedirect,
21
19
  isLoadingBusinessMarkers,
22
- getBusinessLocations,
23
20
  markerGroups,
24
- customerMarkerGroups
21
+ customerMarkerGroups,
22
+ alertState,
23
+ setAlertState,
24
+ onNavigationRedirect,
25
+ getBusinessLocations,
25
26
  } = props;
26
27
 
27
28
  const theme = useTheme();
@@ -29,16 +30,10 @@ const MapViewComponent = (props: MapViewParams) => {
29
30
  const [{ user }] = useSession()
30
31
  const { width, height } = Dimensions.get('window');
31
32
  const ASPECT_RATIO = width / height;
32
- const mapRef = useRef<MapView>(null);
33
+ const mapRef = useRef<MapView | any>(null);
33
34
  const following = useRef<boolean>(true);
34
35
  const [isFocused, setIsFocused] = useState(false)
35
36
  const [locationSelected, setLocationSelected] = useState<any>(null)
36
- const [alertState, setAlertState] = useState<{
37
- open: boolean;
38
- content: Array<string>;
39
- key?: string | null;
40
- }>({ open: false, content: [], key: null });
41
-
42
37
  const {
43
38
  initialPosition,
44
39
  userLocation,
@@ -72,6 +67,24 @@ const MapViewComponent = (props: MapViewParams) => {
72
67
  }
73
68
  };
74
69
 
70
+ const onPressZoomIn = () => {
71
+ const lastRegion = mapRef?.current?.__lastRegion
72
+ mapRef?.current && mapRef.current.animateToRegion({
73
+ ...mapRef?.current?.__lastRegion,
74
+ longitudeDelta: lastRegion.longitudeDelta / 8,
75
+ latitudeDelta: lastRegion.longitudeDelta / 8
76
+ })
77
+ }
78
+
79
+ const onPressZoomOut = () => {
80
+ const lastRegion = mapRef?.current?.__lastRegion
81
+ mapRef?.current && mapRef.current.animateToRegion({
82
+ ...lastRegion,
83
+ longitudeDelta: lastRegion.longitudeDelta * 8,
84
+ latitudeDelta: lastRegion.longitudeDelta * 8
85
+ })
86
+ }
87
+
75
88
  useEffect(() => {
76
89
  fitCoordinates(locationSelected || userLocation);
77
90
  }, [userLocation, locationSelected]);
@@ -91,7 +104,6 @@ const MapViewComponent = (props: MapViewParams) => {
91
104
  };
92
105
  }, []);
93
106
 
94
-
95
107
  useFocusEffect(
96
108
  useCallback(() => {
97
109
  setIsFocused(true)
@@ -125,8 +137,6 @@ const MapViewComponent = (props: MapViewParams) => {
125
137
  markerRef?.current?.props?.coordinate?.longitude === locationSelected?.longitude
126
138
  ) {
127
139
  markerRef?.current?.showCallout()
128
- } else {
129
- markerRef?.current?.hideCallout()
130
140
  }
131
141
  }, [locationSelected])
132
142
 
@@ -200,19 +210,20 @@ const MapViewComponent = (props: MapViewParams) => {
200
210
  </Marker>
201
211
  )
202
212
  }
213
+
203
214
  return (
204
215
  <SafeAreaView style={{ flex: 1 }}>
205
216
  <View style={{ flex: 1 }}>
206
- <View style={{ flex: 1 }}>
207
- {typeof initialPosition?.latitude === 'number' && !isLoadingBusinessMarkers && isFocused && (
217
+ {!isLoadingBusinessMarkers && isFocused && (
218
+ <View style={{ flex: 1 }}>
208
219
  <MapView
209
220
  ref={mapRef}
210
221
  provider={PROVIDER_GOOGLE}
211
222
  initialRegion={{
212
223
  latitude: initialPosition.latitude,
213
224
  longitude: initialPosition.longitude,
214
- latitudeDelta: 0.01,
215
- longitudeDelta: 0.01 * ASPECT_RATIO,
225
+ latitudeDelta: 0.001,
226
+ longitudeDelta: 0.001 * ASPECT_RATIO,
216
227
  }}
217
228
  style={{ flex: 1 }}
218
229
  zoomTapEnabled
@@ -261,8 +272,28 @@ const MapViewComponent = (props: MapViewParams) => {
261
272
  </Marker>
262
273
  </>
263
274
  </MapView>
264
- )}
265
- </View>
275
+ <OFab
276
+ materialIcon
277
+ iconName="plus"
278
+ onPress={() => onPressZoomIn()}
279
+ style={{
280
+ position: 'absolute',
281
+ bottom: 75,
282
+ right: 20,
283
+ }}
284
+ />
285
+ <OFab
286
+ materialIcon
287
+ iconName="minus"
288
+ onPress={() => onPressZoomOut()}
289
+ style={{
290
+ position: 'absolute',
291
+ bottom: 35,
292
+ right: 20,
293
+ }}
294
+ />
295
+ </View>
296
+ )}
266
297
  </View>
267
298
  <View>
268
299
  <Alert
@@ -7,20 +7,25 @@ import {
7
7
  TouchableOpacity,
8
8
  } from 'react-native';
9
9
  import Icon from 'react-native-vector-icons/Ionicons';
10
-
10
+ import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'
11
11
  interface Props {
12
12
  iconName: string;
13
13
  onPress: () => void;
14
14
  style?: StyleProp<ViewStyle>;
15
+ materialIcon?: boolean
15
16
  }
16
- const OFab = ({ iconName, onPress, style = {} }: Props) => {
17
+ const OFab = ({ iconName, materialIcon, onPress, style = {} }: Props) => {
17
18
  return (
18
19
  <View style={{ ...(style as any) }}>
19
20
  <TouchableOpacity
20
21
  activeOpacity={0.8}
21
22
  onPress={onPress}
22
23
  style={styles.blackButton}>
23
- <Icon name={iconName} color="white" size={20} />
24
+ {materialIcon ? (
25
+ <MaterialIcon name={iconName} color="white" size={20} />
26
+ ) : (
27
+ <Icon name={iconName} color="white" size={20} />
28
+ )}
24
29
  </TouchableOpacity>
25
30
  </View>
26
31
  );
@@ -545,5 +545,7 @@ export interface MapViewParams {
545
545
  getBusinessLocations: () => void,
546
546
  isLoadingBusinessMarkers?: boolean,
547
547
  markerGroups: Array<any>,
548
- customerMarkerGroups: Array<any>
548
+ customerMarkerGroups: Array<any>,
549
+ alertState: { open: boolean, content: Array<string>, key?: string | null },
550
+ setAlertState: ({open, content, key} : { open: boolean, content: Array<string>, key?: string | null }) => void
549
551
  }
@@ -96,7 +96,7 @@ const CheckoutUI = (props: any) => {
96
96
  }
97
97
  })
98
98
 
99
- const { showToast } = useToast();
99
+ const [, { showToast }] = useToast();
100
100
  const [, t] = useLanguage();
101
101
  const [{ user }] = useSession();
102
102
  const [{ configs }] = useConfig();
@@ -514,7 +514,7 @@ export const Checkout = (props: any) => {
514
514
  onNavigationRedirect,
515
515
  } = props
516
516
 
517
- const { showToast } = useToast();
517
+ const [, { showToast }] = useToast();
518
518
  const [, t] = useLanguage();
519
519
  const [{ token }] = useSession();
520
520
  const [ordering] = useApi();
@@ -22,7 +22,7 @@ const ForgotPasswordUI = (props: any) => {
22
22
  handleButtonForgotPasswordClick,
23
23
  } = props;
24
24
  const [, t] = useLanguage();
25
- const { showToast } = useToast();
25
+ const [, { showToast }] = useToast();
26
26
  const { control, handleSubmit, errors } = useForm();
27
27
 
28
28
  const theme = useTheme();
@@ -1,4 +1,4 @@
1
- import React from 'react'
1
+ import React, { useCallback } from 'react'
2
2
  import { LanguageSelector as LanguageSelectorController, useOrder } from 'ordering-components/native'
3
3
  import { useTheme } from 'styled-components/native';
4
4
  import { Platform, StyleSheet, View } from 'react-native'
@@ -61,13 +61,19 @@ const LanguageSelectorUI = (props: LanguageSelectorParams) => {
61
61
  (a.content > b.content) ? 1 : ((b.content > a.content) ? -1 : 0)
62
62
  )
63
63
 
64
+ const changeLang = useCallback((lang) => {
65
+ if (lang !== currentLanguage || orderState.loading) {
66
+ handleChangeLanguage(lang);
67
+ }
68
+ }, []);
69
+
64
70
  return (
65
71
  <Container>
66
72
  {languagesState?.languages && (
67
73
  <>
68
74
  {iconColor && <OIcon src={theme.images.general.language} color={iconColor} style={{ marginEnd: 14 }} width={16} />}
69
75
  <RNPickerSelect
70
- onValueChange={handleChangeLanguage}
76
+ onValueChange={changeLang}
71
77
  items={_languages || []}
72
78
  value={currentLanguage}
73
79
  style={pickerStyle ? pickerStyle : _pickerStyle}
@@ -58,7 +58,7 @@ const LoginFormUI = (props: LoginParams) => {
58
58
  onNavigationRedirect,
59
59
  } = props;
60
60
 
61
- const { showToast } = useToast();
61
+ const [, { showToast }] = useToast();
62
62
  const [, t] = useLanguage();
63
63
  const [{ configs }] = useConfig();
64
64
  const [, { login }] = useSession();
@@ -1,5 +1,5 @@
1
1
  import React, { useEffect, useState } from 'react';
2
- import { FlatList, TouchableOpacity, View, StyleSheet, KeyboardAvoidingView, Platform } from 'react-native';
2
+ import { View, StyleSheet, KeyboardAvoidingView, Platform } from 'react-native';
3
3
  import {
4
4
  Placeholder,
5
5
  PlaceholderLine,
@@ -24,12 +24,10 @@ import { OText, OIcon, OModal, OButton } from '../shared';
24
24
  import {
25
25
  PMContainer,
26
26
  PMItem,
27
- PMCardSelected,
28
- PMCardItemContent,
29
27
  PMDropDownWrapper,
30
28
  PMDropDownCont
31
29
  } from './styles'
32
- import { getIconCard, flatArray } from '../../utils';
30
+ import { TouchableOpacity } from 'react-native-gesture-handler';
33
31
 
34
32
  const stripeOptions: any = ['stripe_direct', 'stripe', 'stripe_connect']
35
33
  // const stripeRedirectOptions = [
@@ -134,7 +132,7 @@ const PaymentOptionsUI = (props: any) => {
134
132
  />
135
133
  <OText
136
134
  size={10}
137
- style={{ marginStart: 12 }}
135
+ style={{ marginLeft: 12, marginRight: 12 }}
138
136
  color={paymethodSelected?.id === item.id ? theme.colors.white : '#000'}
139
137
  >
140
138
  {t(item.gateway.toUpperCase(), item.name)}
@@ -151,8 +149,8 @@ const PaymentOptionsUI = (props: any) => {
151
149
  return (
152
150
  <PMContainer>
153
151
  {paymethodsList.paymethods.length > 0 && (
154
- <PMDropDownWrapper onPress={() => setShowMethods(true)}>
155
- <OText color={theme.colors.textSecondary} style={{marginStart: 14}}>{paymethodSelected?.paymethod?.name || t('SELECT_PAYMENT_METHOD', 'Select Paymethod')}</OText>
152
+ <PMDropDownWrapper onPress={() => setShowMethods(!isShowMethods)}>
153
+ <OText color={theme.colors.textSecondary} style={{marginLeft: 14, marginRight: 14}}>{paymethodSelected?.paymethod?.name || t('SELECT_PAYMENT_METHOD', 'Select Paymethod')}</OText>
156
154
  <OIcon color={theme.colors.textSecondary} width={16} src={theme.images.general.chevron_right} style={{transform: [{rotate: '90deg'}], marginEnd: 14}} />
157
155
  {isShowMethods && <PMDropDownCont>
158
156
  {
@@ -73,4 +73,5 @@ export const PMDropDownCont = styled.View`
73
73
  width: 100%;
74
74
  padding: 10px 16px;
75
75
  box-shadow: 0 2px 3px #0000004D;
76
- `;
76
+ border: 1px solid #EEE;
77
+ `;
@@ -142,7 +142,7 @@ export const ProductItemAccordion = (props: ProductItemAccordionParams) => {
142
142
  activeOpacity={1}
143
143
  >
144
144
  <View style={{ flexDirection: 'row', alignItems: 'flex-start' }}>
145
- <ContentInfo>
145
+ <ContentInfo style={{alignItems: 'center'}}>
146
146
  {product?.images && (
147
147
  <ProductImage>
148
148
  {isFromCheckout ? (
@@ -95,7 +95,7 @@ const SignupFormUI = (props: SignupParams) => {
95
95
  const showInputPhoneNumber =
96
96
  validationFields?.fields?.checkout?.cellphone?.enabled ?? false;
97
97
 
98
- const { showToast } = useToast();
98
+ const [, { showToast }] = useToast();
99
99
  const [, t] = useLanguage();
100
100
  const [, { login }] = useSession();
101
101
  const [{ configs }] = useConfig();
@@ -26,7 +26,7 @@ const StripeRedirectFormUI = (props: any) => {
26
26
  // // androidPayMode: 'test', // Android only
27
27
  // })
28
28
 
29
- const { showToast } = useToast();
29
+ const [, { showToast }] = useToast();
30
30
  const { control, handleSubmit, errors } = useForm();
31
31
 
32
32
  const [{ user }] = useSession();
@@ -62,7 +62,7 @@ export const UserFormDetailsUI = (props: any) => {
62
62
  });
63
63
 
64
64
  const [, t] = useLanguage();
65
- const { showToast } = useToast();
65
+ const [, { showToast }] = useToast();
66
66
  const { handleSubmit, control, errors, setValue } = useForm();
67
67
 
68
68
  const [{ user }] = useSession();
@@ -84,7 +84,7 @@ const ProfileListUI = (props: ProfileParams) => {
84
84
 
85
85
  const [{ user }] = useSession();
86
86
  const [, t] = useLanguage();
87
- const { showToast } = useToast();
87
+ const [, { showToast }] = useToast();
88
88
  const { errors } = useForm();
89
89
 
90
90
  const { height } = useWindowDimensions();
@@ -52,7 +52,7 @@ const ProfileUI = (props: ProfileParams) => {
52
52
 
53
53
  const [{ user }] = useSession();
54
54
  const [, t] = useLanguage();
55
- const { showToast } = useToast();
55
+ const [, { showToast }] = useToast();
56
56
  const { handleSubmit, errors, setValue, control } = useForm();
57
57
 
58
58
  const [phoneInputData, setPhoneInputData] = useState({
@@ -9,7 +9,7 @@ const bottomPosition = 20;
9
9
  export const Toast: React.FC = () => {
10
10
  const theme = useTheme();
11
11
  // const insets = useSafeAreaInsets();
12
- const { toastConfig, hideToast } = useToast();
12
+ const [, { toastConfig, hideToast }] = useToast();
13
13
  const opacity = React.useRef(new Animated.Value(0)).current;
14
14
 
15
15
  const fadeIn = React.useCallback(() => {
@@ -10,7 +10,7 @@ import {
10
10
  WrapperNotFound
11
11
  } from './styles'
12
12
  import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder'
13
- import { Platform, View } from 'react-native'
13
+ import { Platform, View, TouchableOpacity } from 'react-native'
14
14
  import { useTheme } from 'styled-components/native'
15
15
  import { ScrollView } from 'react-native-gesture-handler'
16
16
 
@@ -28,7 +28,8 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
28
28
  handleSearchRedirect,
29
29
  handleClearSearch,
30
30
  errorQuantityProducts,
31
- handleCancelSearch
31
+ handleCancelSearch,
32
+ handlerClickCategory
32
33
  } = props
33
34
 
34
35
  const [, t] = useLanguage()
@@ -52,7 +53,11 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
52
53
  !category.id && (
53
54
  featured && categoryState?.products?.find((product: any) => product.featured) && (
54
55
  <>
55
- <OText style={{...theme.labels.subtitle, fontWeight: Platform.OS == 'ios' ? '600' : 'bold'}} mBottom={10}>{t('FEATURED', 'Featured')}</OText>
56
+ <TouchableOpacity
57
+ onPress={() => handlerClickCategory({ id: 'featured', name: 'Featured' })}
58
+ >
59
+ <OText style={{...theme.labels.subtitle, fontWeight: Platform.OS == 'ios' ? '600' : 'bold'}} mBottom={10}>{t('FEATURED', 'Featured')}</OText>
60
+ </TouchableOpacity>
56
61
  <ScrollView horizontal showsHorizontalScrollIndicator={false}>
57
62
  {categoryState.products?.map((product: any) => product.featured && (
58
63
  <SingleProductCard
@@ -77,7 +82,11 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
77
82
  {
78
83
  products.length > 0 && (
79
84
  <>
80
- <OText style={{...theme.labels.subtitle, fontWeight: Platform.OS === 'ios' ? '600' : 'bold'}} mBottom={10}>{category.name}</OText>
85
+ <TouchableOpacity
86
+ onPress={() => handlerClickCategory(category)}
87
+ >
88
+ <OText style={{...theme.labels.subtitle, fontWeight: Platform.OS === 'ios' ? '600' : 'bold'}} mBottom={10}>{category.name}</OText>
89
+ </TouchableOpacity>
81
90
  <ScrollView horizontal showsHorizontalScrollIndicator={false}>
82
91
  {
83
92
  products.map((product: any) => (
@@ -104,7 +113,7 @@ const BusinessProductsListUI = (props: BusinessProductsListParams) => {
104
113
  <>
105
114
  {[...Array(categoryState?.pagination?.nextPageItems).keys()].map((item, i) => (
106
115
  <Placeholder key={i} style={{ padding: 5, marginBottom: 20 }} Animation={Fade}>
107
- <PlaceholderLine width={70} height={20} style={{ marginBottom: 20 }} />
116
+ <PlaceholderLine width={50} height={20} style={{ marginBottom: 20 }} />
108
117
  <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
109
118
  <View style={{flexBasis: '47%'}}>
110
119
  <PlaceholderLine width={80} height={100} style={{ marginBottom: 10 }} />
@@ -1,5 +1,5 @@
1
1
  import React, { useState } from 'react'
2
- import { View, TouchableOpacity, StyleSheet } from 'react-native'
2
+ import { View, TouchableOpacity, StyleSheet, ScrollView } from 'react-native'
3
3
  import MaterialIcon from 'react-native-vector-icons/MaterialIcons'
4
4
  import {
5
5
  BusinessAndProductList,
@@ -29,6 +29,8 @@ import { useTheme } from 'styled-components/native'
29
29
  import { useSafeAreaInsets } from 'react-native-safe-area-context'
30
30
  import { OrderSummary } from '../OrderSummary'
31
31
  import { Cart } from '../Cart'
32
+ import { SingleProductCard } from '../../../../../src/components/SingleProductCard'
33
+ import NavBar from '../NavBar'
32
34
 
33
35
  const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
34
36
  const {
@@ -151,20 +153,21 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
151
153
  handleClearSearch={handleChangeSearch}
152
154
  errorQuantityProducts={errorQuantityProducts}
153
155
  handleCancelSearch={handleCancel}
156
+ handlerClickCategory={handleChangeCategory}
154
157
  />
155
158
  </WrapContent>
156
159
  </>
157
160
  )}
158
161
  {loading && !error && (
159
162
  <>
160
- <BusinessProductsCategories
163
+ {/* <BusinessProductsCategories
161
164
  categories={[]}
162
165
  categorySelected={categorySelected}
163
166
  onClickCategory={handleChangeCategory}
164
167
  featured={featuredProducts}
165
168
  openBusinessInformation={openBusinessInformation}
166
169
  loading={loading}
167
- />
170
+ /> */}
168
171
  <WrapContent>
169
172
  <BusinessProductsList
170
173
  categories={[]}
@@ -209,6 +212,40 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
209
212
  />
210
213
  </OModal>
211
214
 
215
+ <OModal
216
+ open={categorySelected.id !== null}
217
+ onClose={() => handleChangeCategory({ id: null, name: 'All' })}
218
+ entireModal
219
+ customClose
220
+ >
221
+ <ScrollView
222
+ contentContainerStyle={{
223
+ paddingHorizontal: 40,
224
+ paddingVertical: 20
225
+ }}
226
+ >
227
+ <NavBar
228
+ title={categorySelected?.name}
229
+ onActionLeft={() => handleChangeCategory({ id: null, name: 'All' })}
230
+ showCall={false}
231
+ style={{ paddingHorizontal: 0, marginHorizontal: -7 }}
232
+ />
233
+ <View>
234
+ {categorySelected.id && (
235
+ categoryState.products?.map((product: any) => (
236
+ <SingleProductCard
237
+ key={product.id}
238
+ isSoldOut={(product.inventoried && !product.quantity)}
239
+ product={product}
240
+ businessId={business.id}
241
+ onProductClick={() => onProductClick(product)}
242
+ />
243
+ ))
244
+ )}
245
+ </View>
246
+ </ScrollView>
247
+ </OModal>
248
+
212
249
  {openUpselling && (
213
250
  <UpsellingProducts
214
251
  businessId={currentCart?.business_id}
@@ -239,9 +276,11 @@ const styles = StyleSheet.create({
239
276
  btnBackArrow: {
240
277
  borderWidth: 0,
241
278
  color: '#FFF',
242
- backgroundColor: 'transparent',
243
- borderRadius: 24,
279
+ backgroundColor: 'rgba(0,0,0,0.3)',
280
+ borderRadius: 16,
281
+ paddingHorizontal: 15,
244
282
  marginRight: 15,
283
+ marginTop: 20
245
284
  },
246
285
  searchIcon: {
247
286
  borderWidth: 0,
@@ -6,7 +6,7 @@ import {
6
6
  CardInfo,
7
7
  SoldOut
8
8
  } from './styles'
9
- import { StyleSheet, TouchableOpacity } from 'react-native'
9
+ import { StyleSheet, TouchableOpacity, Dimensions } from 'react-native'
10
10
  import { OText, OIcon } from '../shared'
11
11
  import { useTheme } from 'styled-components/native'
12
12
 
@@ -19,10 +19,13 @@ export const SingleProductCard = (props: SingleProductCardParams) => {
19
19
  } = props
20
20
 
21
21
  const theme = useTheme();
22
+ const windowWidth = Dimensions.get('window').width;
22
23
 
23
24
  const styles = StyleSheet.create({
24
25
  container: {
25
26
  marginBottom: 15,
27
+ width: (windowWidth - 140) / 2,
28
+ minHeight: (windowWidth - 140) / 2 + 50
26
29
  },
27
30
  textStyle: {
28
31
  flex: 1,
@@ -34,8 +37,8 @@ export const SingleProductCard = (props: SingleProductCardParams) => {
34
37
  lineHeight: 18
35
38
  },
36
39
  productStyle: {
37
- width: 100,
38
- height: 100,
40
+ width: (windowWidth - 200) / 2,
41
+ height: (windowWidth - 200) / 2,
39
42
  borderRadius: 3,
40
43
  marginTop: 5
41
44
  },
@@ -74,10 +77,11 @@ export const SingleProductCard = (props: SingleProductCardParams) => {
74
77
  return (
75
78
  <CardContainer style={styles.container}
76
79
  onPress={() => onProductClick(product)}
77
- activeOpacity={0.8}
80
+ activeOpacity={0.8}
78
81
  >
79
82
  <OIcon
80
83
  url={optimizeImage(product?.images, 'h_200,c_limit')}
84
+ src={!product?.images && theme.images.dummies.product}
81
85
  style={{...styles.productStyle, opacity: (isSoldOut || maxProductQuantity <= 0) ? 0.4 : 1}}
82
86
  />
83
87
  <CardInfo>
@@ -5,11 +5,8 @@ export const CardContainer = styled.TouchableOpacity`
5
5
  align-items: flex-start;
6
6
  padding: 10px;
7
7
  position: relative;
8
- max-width: 150px;
9
- width: 150px;
10
8
  margin-end: 10px;
11
9
  border-radius: 3px;
12
- min-height: 200px;
13
10
  `
14
11
  export const CardInfo = styled.View`
15
12
  flex: 1;
@@ -162,7 +162,7 @@ export interface BusinessProductsListingParams {
162
162
  productModal?: any;
163
163
  handleChangeCategory: (value: any) => {};
164
164
  setProductLogin?: () => {};
165
- updateProductModal?: (value: any) => {}
165
+ updateProductModal?: (value: any) => {},
166
166
  }
167
167
  export interface BusinessBasicInformationParams {
168
168
  navigation?: any;
@@ -196,9 +196,11 @@ export interface BusinessProductsListParams {
196
196
  handleClearSearch?: (value: any) => {};
197
197
  isBusinessLoading?: any,
198
198
  errorQuantityProducts?: boolean,
199
- handleCancelSearch?: () => void
199
+ handleCancelSearch?: () => void,
200
+ handlerClickCategory?: any,
200
201
  }
201
202
  export interface SingleProductCardParams {
203
+ isFullCategoryView?: boolean,
202
204
  businessId: any,
203
205
  product: any;
204
206
  isSoldOut: boolean;
@@ -1,5 +1,5 @@
1
- import React from 'react';
2
- import { TouchableOpacity, View } from 'react-native';
1
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { PanResponder, TouchableOpacity, View } from 'react-native';
3
3
  import {
4
4
  useLanguage,
5
5
  useOrder,
@@ -27,7 +27,8 @@ const BusinessMenu = (props:any): React.ReactElement => {
27
27
 
28
28
  const { navigation, businessProductsListingProps } = props;
29
29
 
30
- const [{ carts }] = useOrder();
30
+ const [{ carts }, {clearCart} ] = useOrder();
31
+ const [isClearCart, setClearCart] = useState(false)
31
32
  const cartsList = (carts && Object.values(carts).filter((cart: any) => cart.products.length > 0)) || []
32
33
  const VISIBLE_CART_BOTTOM_SHEET_HEIGHT = orientationState?.dimensions?.height * (orientationState.orientation === PORTRAIT ? 0.5 : 1);
33
34
 
@@ -36,6 +37,39 @@ const BusinessMenu = (props:any): React.ReactElement => {
36
37
  if (cartsList?.length > 0) {
37
38
  cart = cartsList?.find((item: any) => item.business_id == businessProductsListingProps.slug);
38
39
  }
40
+ const clearCartWhenTimeOut = () => {
41
+ if (cart?.uuid) clearCart(cart?.uuid)
42
+ }
43
+ const timerId = useRef(false);
44
+
45
+ const clearInactivityTimeout = () =>{
46
+ clearTimeout(timerId.current);
47
+ }
48
+ const panResponder = React.useRef(
49
+ PanResponder.create({
50
+ onStartShouldSetPanResponderCapture: () => {
51
+ resetInactivityTimeout()
52
+ },
53
+ })
54
+ ).current
55
+ const resetInactivityTimeout = useCallback(() => {
56
+ clearTimeout(timerId.current);
57
+ timerId.current = setTimeout(() => {
58
+ setClearCart(true)
59
+ navigation.reset({
60
+ routes: [{ name: 'Intro' }],
61
+ })
62
+ }, 60000*2);
63
+ }, []);
64
+
65
+ useEffect(() => {
66
+ if(isClearCart && cart?.uuid) clearCart(cart?.uuid)
67
+ }, [cart, isClearCart]);
68
+
69
+ useEffect(() => {
70
+ resetInactivityTimeout();
71
+ hideCartBottomSheet()
72
+ }, []);
39
73
 
40
74
  const cartProps = {
41
75
  ...props,
@@ -51,7 +85,10 @@ const BusinessMenu = (props:any): React.ReactElement => {
51
85
  showNotFound: false
52
86
  }
53
87
 
54
- const goToBack = () => navigation.goBack()
88
+ const goToBack = () => {
89
+ clearInactivityTimeout()
90
+ navigation.goBack()
91
+ }
55
92
 
56
93
  const onToggleCart = () => {
57
94
  if (bottomSheetVisibility) hideCartBottomSheet();
@@ -62,7 +99,9 @@ const BusinessMenu = (props:any): React.ReactElement => {
62
99
  <View style={{
63
100
  flex: 1,
64
101
  flexDirection: orientationState?.orientation === PORTRAIT ? 'column' : 'row'
65
- }}>
102
+ }}
103
+ {...panResponder.panHandlers}
104
+ >
66
105
  <View
67
106
  style={{
68
107
  flex: 1,
@@ -100,6 +139,9 @@ const BusinessMenu = (props:any): React.ReactElement => {
100
139
 
101
140
  <BusinessProductsListing
102
141
  { ...businessProductsListingProps }
142
+ resetInactivityTimeout={resetInactivityTimeout}
143
+ clearInactivityTimeout={clearInactivityTimeout}
144
+ bottomSheetVisibility={bottomSheetVisibility}
103
145
  />
104
146
  </Container>
105
147
  </View>
@@ -112,6 +154,8 @@ const BusinessMenu = (props:any): React.ReactElement => {
112
154
  >
113
155
  <CartContent
114
156
  {...cartProps}
157
+ resetInactivityTimeout={resetInactivityTimeout}
158
+ clearInactivityTimeout={clearInactivityTimeout}
115
159
  />
116
160
  </View>
117
161
  </View>
@@ -11,7 +11,7 @@ import { LANDSCAPE, useDeviceOrientation } from '../../../../../src/hooks/Device
11
11
  import { useTheme } from 'styled-components/native';
12
12
 
13
13
  const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
14
- const {navigation, businessState} = props;
14
+ const {navigation, businessState, resetInactivityTimeout, clearInactivityTimeout, bottomSheetVisibility } = props;
15
15
 
16
16
  const business: Business = businessState.business;
17
17
 
@@ -47,6 +47,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
47
47
  image={{uri: item?.images}}
48
48
  isOutOfStock={!item?.inventoried}
49
49
  onPress={() => {
50
+ resetInactivityTimeout()
50
51
  navigation.navigate('ProductDetails', {
51
52
  businessId: business?.api?.businessId,
52
53
  businessSlug: business?.slug,
@@ -99,15 +100,18 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
99
100
  style={{
100
101
  width:
101
102
  orientationState?.orientation === LANDSCAPE
102
- ? orientationState?.dimensions?.width * 0.16
103
+ ? bottomSheetVisibility ? orientationState?.dimensions?.width * 0.15 :orientationState?.dimensions?.width * 0.16
103
104
  : orientationState?.dimensions?.width * 0.21,
104
105
  }}
105
106
  onPress={() => {
107
+ resetInactivityTimeout()
106
108
  navigation.navigate('Category', {
107
109
  category,
108
110
  categories: business.original.categories,
109
111
  businessId: business?.api?.businessId,
110
112
  businessSlug: business?.slug,
113
+ clearInactivityTimeout,
114
+ resetInactivityTimeout,
111
115
  });
112
116
  }}
113
117
  titleStyle={{textAlign: 'center'}}
@@ -34,6 +34,8 @@ const CartBottomSheetUI = (props: CartBottomSheetUIProps): React.ReactElement |
34
34
  setIsCartsLoading,
35
35
  isFromCart,
36
36
  navigation,
37
+ clearInactivityTimeout,
38
+ resetInactivityTimeout,
37
39
  } = props
38
40
 
39
41
  const theme = useTheme()
@@ -87,6 +89,7 @@ const CartBottomSheetUI = (props: CartBottomSheetUIProps): React.ReactElement |
87
89
  }
88
90
 
89
91
  const handleUpsellingPage = () => {
92
+ clearInactivityTimeout()
90
93
  onCloseUpselling()
91
94
  navigation?.navigate('Cart', { businessId: cart?.business_id })
92
95
  }
@@ -159,7 +162,10 @@ const CartBottomSheetUI = (props: CartBottomSheetUIProps): React.ReactElement |
159
162
  borderColor={theme.colors.primary}
160
163
  imgRightSrc={null}
161
164
  textStyle={{ color: 'white', textAlign: 'center', flex: 1 }}
162
- onClick={() => setOpenUpselling(true)}
165
+ onClick={() => {
166
+ resetInactivityTimeout()
167
+ setOpenUpselling(true)
168
+ }}
163
169
  style={{width: '100%', flexDirection: 'row', justifyContent: 'center'}}
164
170
  />
165
171
  </StyledBottomContent>
@@ -192,6 +198,7 @@ const CartBottomSheetUI = (props: CartBottomSheetUIProps): React.ReactElement |
192
198
  canOpenUpselling={canOpenUpselling}
193
199
  setCanOpenUpselling={setCanOpenUpselling}
194
200
  onClose={onCloseUpselling}
201
+ resetInactivityTimeout={resetInactivityTimeout}
195
202
  />
196
203
  )}
197
204
  </StyledContainer>
@@ -251,6 +258,8 @@ interface CartBottomSheetUIProps {
251
258
  isFromCart: any,
252
259
  navigation: any,
253
260
  onNavigationRedirect: any,
261
+ clearInactivityTimeout: any,
262
+ resetInactivityTimeout: any,
254
263
  }
255
264
 
256
265
  export const CartBottomSheet = (props: any) => {
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import { useLanguage } from 'ordering-components/native';
3
3
 
4
4
  import { CCNotCarts } from './styles';
@@ -16,6 +16,8 @@ export const CartContent = (props: any) => {
16
16
  CustomCartComponent,
17
17
  extraPropsCustomCartComponent,
18
18
  showNotFound,
19
+ clearInactivityTimeout,
20
+ resetInactivityTimeout,
19
21
  }: Props = props
20
22
 
21
23
  const [, t] = useLanguage()
@@ -27,6 +29,8 @@ export const CartContent = (props: any) => {
27
29
  onNavigationRedirect: props.onNavigationRedirect,
28
30
  isCartsLoading,
29
31
  setIsCartsLoading,
32
+ clearInactivityTimeout,
33
+ resetInactivityTimeout,
30
34
  }
31
35
 
32
36
  const content = (
@@ -67,4 +71,6 @@ interface Props {
67
71
  CustomCartComponent?: any,
68
72
  extraPropsCustomCartComponent?: JSON,
69
73
  showNotFound?: boolean,
74
+ clearInactivityTimeout: any,
75
+ resetInactivityTimeout: any,
70
76
  }
@@ -31,6 +31,8 @@ const CategoriesMenu = (props: any): React.ReactElement => {
31
31
  categories,
32
32
  businessId,
33
33
  businessSlug,
34
+ clearInactivityTimeout,
35
+ resetInactivityTimeout
34
36
  }: Params = route.params;
35
37
 
36
38
  const theme = useTheme()
@@ -40,7 +42,10 @@ const CategoriesMenu = (props: any): React.ReactElement => {
40
42
  const [orientationState] = useDeviceOrientation();
41
43
  const [bottomSheetVisibility, { showCartBottomSheet, hideCartBottomSheet }] = useCartBottomSheet();
42
44
 
43
- const onChangeTabs = (idx: number) => setIndexCateg(idx);
45
+ const onChangeTabs = (idx: number) => {
46
+ resetInactivityTimeout();
47
+ setIndexCateg(idx);
48
+ }
44
49
 
45
50
  const goToBack = () => navigation.goBack()
46
51
 
@@ -64,6 +69,8 @@ const CategoriesMenu = (props: any): React.ReactElement => {
64
69
  orientationState,
65
70
  height: VISIBLE_CART_BOTTOM_SHEET_HEIGHT,
66
71
  visible: bottomSheetVisibility,
72
+ clearInactivityTimeout,
73
+ resetInactivityTimeout,
67
74
  },
68
75
  showNotFound: false,
69
76
  showCartBottomSheet,
@@ -133,6 +140,7 @@ const CategoriesMenu = (props: any): React.ReactElement => {
133
140
  }}
134
141
  titleStyle={{marginTop: Platform.OS === 'ios' ? 10 : 0}}
135
142
  onPress={() => {
143
+ resetInactivityTimeout()
136
144
  navigation.navigate('ProductDetails', {
137
145
  businessId,
138
146
  businessSlug,
@@ -167,6 +175,8 @@ interface Params {
167
175
  categories: Category[];
168
176
  businessId: string;
169
177
  businessSlug: string;
178
+ clearInactivityTimeout: any;
179
+ resetInactivityTimeout: any;
170
180
  }
171
181
 
172
182
  export default CategoriesMenu;
@@ -31,6 +31,7 @@ const UpsellingProductsUI = (props: UpsellingProductsParams) => {
31
31
  canOpenUpselling,
32
32
  setCanOpenUpselling,
33
33
  onClose,
34
+ resetInactivityTimeout,
34
35
  } = props
35
36
  const [actualProduct, setActualProduct] = useState<any>(null)
36
37
  const [modalIsOpen, setModalIsOpen] = useState(false)
@@ -150,7 +151,10 @@ const UpsellingProductsUI = (props: UpsellingProductsParams) => {
150
151
  style={{ height: 40, width: '100%' }}
151
152
  bgColor="#EAF2FE"
152
153
  borderColor="#EAF2FE"
153
- onClick={() => handleFormProduct(product)}
154
+ onClick={() => {
155
+ resetInactivityTimeout()
156
+ handleFormProduct(product)
157
+ }}
154
158
  />
155
159
  </Item>
156
160
  )) : (
@@ -221,7 +225,10 @@ const UpsellingProductsUI = (props: UpsellingProductsParams) => {
221
225
  style={{ minHeight: 40, height: 'auto', width: '100%' }}
222
226
  bgColor="#EAF2FE"
223
227
  borderColor="#EAF2FE"
224
- onClick={() => handleFormProduct(product)}
228
+ onClick={() => {
229
+ resetInactivityTimeout()
230
+ handleFormProduct(product)
231
+ }}
225
232
  />
226
233
  </Item>
227
234
  )}
@@ -251,7 +258,10 @@ const UpsellingProductsUI = (props: UpsellingProductsParams) => {
251
258
  imgRightSrc=''
252
259
  text={t('I_AM_FINE_THANK_YOU', 'I’m fine, thank you')}
253
260
  style={styles.closeUpsellingButton}
254
- onClick={() => handleUpsellingPage()}
261
+ onClick={() => {
262
+ resetInactivityTimeout()
263
+ handleUpsellingPage()
264
+ }}
255
265
  />
256
266
  </CloseUpsellingLand>
257
267
  </View>
@@ -12,6 +12,9 @@ export interface BusinessProductsListingParams {
12
12
  errorQuantityProducts?: boolean;
13
13
  header?: any;
14
14
  logo?: any;
15
+ resetInactivityTimeout: any;
16
+ clearInactivityTimeout: any;
17
+ bottomSheetVisibility: any;
15
18
  }
16
19
 
17
20
  export interface OrderDetailsParams {
@@ -49,6 +52,7 @@ export interface UpsellingProductsParams {
49
52
  canOpenUpselling?: boolean;
50
53
  setCanOpenUpselling?: (value: any) => void;
51
54
  onClose?: () => void;
55
+ resetInactivityTimeout: any;
52
56
  }
53
57
 
54
58
  export interface LanguageSelectorParams {
@@ -464,4 +468,5 @@ export interface Cart {
464
468
  service_fee_with_discount: number;
465
469
  delivery_price_with_discount: number;
466
470
  total: number;
471
+ clearInactivityTimeout: any;
467
472
  }