ordering-ui-react-native 0.12.61 → 0.12.65

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 (25) hide show
  1. package/package.json +2 -1
  2. package/src/components/BusinessProductsListing/index.tsx +2 -1
  3. package/src/components/Messages/index.tsx +4 -4
  4. package/src/components/OrderCreating/index.tsx +1 -2
  5. package/src/components/OrderDetails/index.tsx +7 -1
  6. package/src/navigators/HomeNavigator.tsx +0 -1
  7. package/themes/business/src/components/Chat/index.tsx +31 -16
  8. package/themes/original/index.tsx +4 -0
  9. package/themes/original/src/components/BusinessBasicInformation/index.tsx +1 -1
  10. package/themes/original/src/components/BusinessController/index.tsx +9 -2
  11. package/themes/original/src/components/BusinessMenuList/index.tsx +132 -0
  12. package/themes/original/src/components/BusinessMenuList/styles.tsx +15 -0
  13. package/themes/original/src/components/BusinessPreorder/index.tsx +474 -0
  14. package/themes/original/src/components/BusinessPreorder/styles.tsx +60 -0
  15. package/themes/original/src/components/BusinessesListing/index.tsx +2 -1
  16. package/themes/original/src/components/HighestRatedBusinesses/index.tsx +3 -1
  17. package/themes/original/src/types/index.tsx +22 -1
  18. package/themes/single-business/src/components/BusinessBasicInformation/index.tsx +2 -2
  19. package/themes/single-business/src/components/BusinessProductsListing/index.tsx +2 -2
  20. package/themes/single-business/src/components/BusinessesListing/index.tsx +1 -1
  21. package/themes/single-business/src/components/Cart/index.tsx +47 -26
  22. package/themes/single-business/src/components/Cart/styles.tsx +9 -0
  23. package/themes/single-business/src/components/TaxInformation/index.tsx +22 -17
  24. package/themes/single-business/src/components/TaxInformation/styles.tsx +3 -2
  25. package/themes/single-business/src/types/index.tsx +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ordering-ui-react-native",
3
- "version": "0.12.61",
3
+ "version": "0.12.65",
4
4
  "description": "Reusable components made in react native",
5
5
  "main": "src/index.tsx",
6
6
  "author": "ordering.inc",
@@ -69,6 +69,7 @@
69
69
  "react-native-background-timer": "^2.4.1",
70
70
  "react-native-bootsplash": "^3.2.3",
71
71
  "react-native-calendar-picker": "^7.1.2",
72
+ "react-native-calendar-strip": "^2.2.5",
72
73
  "react-native-country-picker-modal": "^2.0.0",
73
74
  "react-native-credit-card-input": "^0.4.1",
74
75
  "react-native-document-picker": "^5.2.0",
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useEffect } from 'react'
2
- import { View, TouchableOpacity, StyleSheet } from 'react-native'
2
+ import { View, TouchableOpacity, StyleSheet, Platform } from 'react-native'
3
3
  import MaterialIcon from 'react-native-vector-icons/MaterialIcons'
4
4
  import {
5
5
  BusinessAndProductList,
@@ -325,6 +325,7 @@ const styles = StyleSheet.create({
325
325
  export const BusinessProductsListing = (props: BusinessProductsListingParams) => {
326
326
  const businessProductslistingProps = {
327
327
  ...props,
328
+ isForceSearch: Platform.OS === 'ios',
328
329
  UIComponent: BusinessProductsListingUI
329
330
  }
330
331
  return (
@@ -67,10 +67,10 @@ const MessagesUI = (props: MessagesParams) => {
67
67
  const theme = useTheme();
68
68
 
69
69
  const quickMessageList = [
70
- { key: 'driver_message_1', text: t('DRIVER_MESSAGE_1', 'driver_message_1') },
71
- { key: 'driver_message_2', text: t('DRIVER_MESSAGE_2', 'driver_message_2') },
72
- { key: 'driver_message_3', text: t('DRIVER_MESSAGE_3', 'driver_message_3') },
73
- { key: 'driver_message_4', text: t('DRIVER_MESSAGE_4', 'driver_message_4') }
70
+ { key: 'customer_message_1', text: t('CUSTOMER_MESSAGE_1', 'customer_message_1') },
71
+ { key: 'customer_message_2', text: t('CUSTOMER_MESSAGE_2', 'customer_message_2') },
72
+ { key: 'customer_message_3', text: t('CUSTOMER_MESSAGE_3', 'customer_message_3') },
73
+ { key: 'customer_message_4', text: t('CUSTOMER_MESSAGE_4', 'customer_message_4') }
74
74
  ]
75
75
 
76
76
  const [formattedMessages, setFormattedMessages] = useState<Array<any>>([])
@@ -86,7 +86,7 @@ export const OrderCreating = (props: any) => {
86
86
  if (business?.address) {
87
87
  AsyncStorage.setItem(
88
88
  'business-address',
89
- JSON.stringify(business?.address)
89
+ business?.address
90
90
  );
91
91
  setAddress(business?.address)
92
92
  }
@@ -97,7 +97,6 @@ export const OrderCreating = (props: any) => {
97
97
  if (isOrderDetail) {
98
98
  try {
99
99
  const value = await AsyncStorage.getItem('business-address');
100
- value != null ? JSON.parse(value) : null;
101
100
  setAddress(value)
102
101
  } catch {
103
102
  console.log('err')
@@ -105,7 +105,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
105
105
  const [openModalForDriver, setOpenModalForDriver] = useState(false)
106
106
  const [unreadAlert, setUnreadAlert] = useState({ business: false, driver: false })
107
107
  const [isReviewed, setIsReviewed] = useState(false)
108
- const [openOrderCreating, setOpenOrderCreating] = useState(true)
108
+ const [openOrderCreating, setOpenOrderCreating] = useState(false)
109
109
  const [openTaxModal, setOpenTaxModal] = useState<any>({ open: false, data: null })
110
110
  const { order, loading, businessData, error } = props.order
111
111
  const isTaxIncluded = order?.tax_type === 1
@@ -245,6 +245,12 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
245
245
  }
246
246
  }, [loading])
247
247
 
248
+ useEffect(() => {
249
+ AsyncStorage.getItem('business-address', (err, result) => {
250
+ if (result !== null) setOpenOrderCreating(true)
251
+ })
252
+ }, [])
253
+
248
254
  return (
249
255
  <OrderDetailsContainer keyboardShouldPersistTaps='handled'>
250
256
  {order && order?.id && !error && !loading && (
@@ -21,7 +21,6 @@ import HelpOrder from '../pages/HelpOrder'
21
21
  import HelpGuide from '../pages/HelpGuide'
22
22
  import HelpAccountAndPayment from '../pages/HelpAccountAndPayment'
23
23
  import Splash from '../pages/Splash';
24
-
25
24
  const Stack = createStackNavigator();
26
25
 
27
26
  const HomeNavigator = (e : any) => {
@@ -66,14 +66,22 @@ const ChatUI = (props: MessagesParams) => {
66
66
  const [, t] = useLanguage();
67
67
  const [, { showToast }] = useToast();
68
68
  const theme = useTheme();
69
+ const [messageList, setMessageList] = useState<any>([])
69
70
 
70
- const quickMessageList = [
71
+ const storeMessageList: any = [
71
72
  { key: 'store_message_1', text: t('STORE_MESSAGE_1', 'store_message_1') },
72
73
  { key: 'store_message_2', text: t('STORE_MESSAGE_2', 'store_message_2') },
73
74
  { key: 'store_message_3', text: t('STORE_MESSAGE_3', 'store_message_3') },
74
75
  { key: 'store_message_4', text: t('STORE_MESSAGE_4', 'store_message_4') }
75
76
  ]
76
77
 
78
+ const driverMessageList: any = [
79
+ { key: 'driver_message_1', text: t('DRIVER_MESSAGE_1', 'driver_message_1') },
80
+ { key: 'driver_message_2', text: t('DRIVER_MESSAGE_2', 'driver_message_2') },
81
+ { key: 'driver_message_3', text: t('DRIVER_MESSAGE_3', 'driver_message_3') },
82
+ { key: 'driver_message_4', text: t('DRIVER_MESSAGE_4', 'driver_message_4') }
83
+ ]
84
+
77
85
  const handleClickQuickMessage = (text: string) => {
78
86
  setMessage && setMessage(`${message}${text}`)
79
87
  }
@@ -464,6 +472,12 @@ const ChatUI = (props: MessagesParams) => {
464
472
  );
465
473
  };
466
474
 
475
+ useEffect(() => {
476
+ if (user.level === 2) setMessageList(storeMessageList)
477
+ else if (user.level === 4) setMessageList(driverMessageList)
478
+ else setMessageList([])
479
+ }, [user])
480
+
467
481
  useEffect(() => {
468
482
  let newMessages: Array<any> = [];
469
483
  const console = (
@@ -754,21 +768,22 @@ const ChatUI = (props: MessagesParams) => {
754
768
  horizontal
755
769
  showsHorizontalScrollIndicator={false}
756
770
  >
757
- {quickMessageList.map((quickMessage, i) => (
758
- <OButton
759
- key={i}
760
- text={quickMessage.text}
761
- bgColor='#E9ECEF'
762
- borderColor='#E9ECEF'
763
- imgRightSrc={null}
764
- textStyle={{
765
- fontSize: 11,
766
- lineHeight: 16,
767
- color: '#414954'
768
- }}
769
- style={{ ...styles.editButton }}
770
- onClick={() => handleClickQuickMessage(quickMessage.text)}
771
- />
771
+ {messageList.map((quickMessage: any, i: number) => (
772
+ <React.Fragment key={i}>
773
+ <OButton
774
+ text={quickMessage.text}
775
+ bgColor='#E9ECEF'
776
+ borderColor='#E9ECEF'
777
+ imgRightSrc={null}
778
+ textStyle={{
779
+ fontSize: 11,
780
+ lineHeight: 16,
781
+ color: '#414954'
782
+ }}
783
+ style={{ ...styles.editButton }}
784
+ onClick={() => handleClickQuickMessage(quickMessage.text)}
785
+ />
786
+ </React.Fragment>
772
787
  ))}
773
788
  </QuickMessageContainer>
774
789
  </View>
@@ -15,6 +15,8 @@ import { MomentOption } from './src/components/MomentOption';
15
15
  import { OrdersOption } from './src/components/OrdersOption';
16
16
  import { OrderDetails } from './src/components/OrderDetails';
17
17
  import { OrderProgress } from './src/components/OrderProgress';
18
+ import { BusinessPreorder } from './src/components/BusinessPreorder';
19
+ import { BusinessMenuList } from './src/components/BusinessMenuList';
18
20
  import { UserProfileForm } from './src/components/UserProfileForm';
19
21
  import { ReviewOrder } from './src/components/ReviewOrder';
20
22
  import { UserProfile } from './src/components/UserProfile';
@@ -69,8 +71,10 @@ export {
69
71
  OrdersOption,
70
72
  OrderDetails,
71
73
  OrderProgress,
74
+ BusinessPreorder,
72
75
  UserProfileForm,
73
76
  ReviewOrder,
77
+ BusinessMenuList,
74
78
  UserProfile,
75
79
  Help,
76
80
  HelpAccountAndPayment,
@@ -231,4 +231,4 @@ const styles = StyleSheet.create({
231
231
  zIndex: 100,
232
232
  left: 40
233
233
  },
234
- });
234
+ });
@@ -25,7 +25,7 @@ import FontAwesomeIcon from 'react-native-vector-icons/FontAwesome5';
25
25
  import FastImage from 'react-native-fast-image'
26
26
 
27
27
  export const BusinessControllerUI = (props: BusinessControllerParams) => {
28
- const { business, handleClick } = props;
28
+ const { business, handleClick, navigation } = props;
29
29
  const [{ parsePrice, parseDistance, parseNumber, optimizeImage }] =
30
30
  useUtils();
31
31
  const [orderState] = useOrder();
@@ -98,8 +98,15 @@ export const BusinessControllerUI = (props: BusinessControllerParams) => {
98
98
  return _types.join(', ');
99
99
  };
100
100
 
101
+ const handleBusinessClick = (selectedBusiness: any) => {
102
+ if (business?.open) handleClick && handleClick(selectedBusiness)
103
+ else {
104
+ navigation.navigate('BusinessPreorder', { business: selectedBusiness, handleBusinessClick: handleClick })
105
+ }
106
+ }
107
+
101
108
  return (
102
- <Card activeOpacity={1} onPress={() => handleClick(business)}>
109
+ <Card activeOpacity={1} onPress={() => handleBusinessClick(business)}>
103
110
  <BusinessHero>
104
111
  <FastImage
105
112
  style={{ height: 120 }}
@@ -0,0 +1,132 @@
1
+ import React, { useState } from 'react'
2
+ import { useLanguage, BusinessMenuListing } from 'ordering-components/native'
3
+ import { OModal, OText } from '../shared'
4
+ import { BusinessMenuListParams } from '../../types'
5
+ import { View, StyleSheet, TouchableOpacity, Text } from 'react-native'
6
+ import { useTheme } from 'styled-components/native'
7
+ import IconAntDesign from 'react-native-vector-icons/AntDesign'
8
+ import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
9
+ import { Fade, Placeholder, PlaceholderLine } from 'rn-placeholder'
10
+ import { MenuListWrapper, DropOption } from './styles'
11
+
12
+ const BusinessMenuListUI = (props: BusinessMenuListParams) => {
13
+ const {
14
+ menu,
15
+ businessMenuList,
16
+ setMenu
17
+ } = props
18
+
19
+ const [, t] = useLanguage()
20
+ const theme = useTheme()
21
+ const [isShowMenuList, setIsShowMenuList] = useState(false)
22
+
23
+ const styles = StyleSheet.create({
24
+ selectOption: {
25
+ backgroundColor: theme.colors.backgroundGray100,
26
+ borderRadius: 7.6,
27
+ paddingVertical: 10,
28
+ paddingHorizontal: 14,
29
+ flexDirection: 'row',
30
+ alignItems: 'center',
31
+ justifyContent: 'space-between',
32
+ height: 44
33
+ }
34
+ })
35
+
36
+ const handleClickMenu = (option: any) => {
37
+ setMenu(option)
38
+ setIsShowMenuList(false)
39
+ }
40
+
41
+ return (
42
+ <>
43
+ {businessMenuList.loading ? (
44
+ <Placeholder Animation={Fade}>
45
+ <View>
46
+ <PlaceholderLine height={44}/>
47
+ </View>
48
+ </Placeholder>
49
+ ) : (
50
+ <TouchableOpacity onPress={() => setIsShowMenuList(true)}>
51
+ <View style={styles.selectOption}>
52
+ <OText
53
+ size={14}
54
+ color={theme.colors.disabled}
55
+ style={{
56
+ lineHeight: 24,
57
+ flex: 1
58
+ }}
59
+ numberOfLines={1}
60
+ ellipsizeMode="tail"
61
+ >
62
+ {menu?.name || t('MENU_NAME', 'Menu name')}
63
+ </OText>
64
+ <IconAntDesign
65
+ name='down'
66
+ color={theme.colors.textThird}
67
+ size={16}
68
+ />
69
+ </View>
70
+ </TouchableOpacity>
71
+ )}
72
+
73
+ <OModal
74
+ open={isShowMenuList}
75
+ onClose={() => setIsShowMenuList(false)}
76
+ customClose
77
+ entireModal
78
+ >
79
+ <MenuListWrapper>
80
+ <TouchableOpacity onPress={() => setIsShowMenuList(false)} style={{ marginBottom: 12 }}>
81
+ <IconAntDesign
82
+ name='close'
83
+ color={theme.colors.textThird}
84
+ size={24}
85
+ />
86
+ </TouchableOpacity>
87
+ {businessMenuList?.menus && businessMenuList?.menus.length > 0 && businessMenuList.menus.map((option: any, index: number) => (
88
+ <TouchableOpacity
89
+ key={index}
90
+ onPress={() => handleClickMenu(option)}
91
+ >
92
+ <DropOption
93
+ selected={option.id === menu.id}
94
+ >
95
+ <View style={{ marginRight: 10 }}>
96
+ {option.id === menu.id ? (
97
+ <MaterialCommunityIcons
98
+ name='radiobox-marked'
99
+ size={24}
100
+ color={theme.colors.primary}
101
+ />
102
+ ) : (
103
+ <MaterialCommunityIcons
104
+ name='radiobox-blank'
105
+ size={24}
106
+ color={theme.colors.arrowColor}
107
+ />
108
+ )}
109
+ </View>
110
+ <Text
111
+ numberOfLines={1}
112
+ ellipsizeMode="tail"
113
+ style={{flex: 1}}
114
+ >{option.name}</Text>
115
+ </DropOption>
116
+ </TouchableOpacity>
117
+ ))}
118
+ </MenuListWrapper>
119
+ </OModal>
120
+ </>
121
+
122
+ )
123
+ }
124
+
125
+ export const BusinessMenuList = (props: any) => {
126
+ const businessMenuListProps = {
127
+ ...props,
128
+ UIComponent: BusinessMenuListUI,
129
+ };
130
+
131
+ return <BusinessMenuListing {...businessMenuListProps} />;
132
+ };
@@ -0,0 +1,15 @@
1
+ import styled from 'styled-components/native'
2
+
3
+ export const MenuListWrapper = styled.ScrollView`
4
+ padding: 20px 40px 30px 40px;
5
+ `
6
+
7
+ export const DropOption = styled.View`
8
+ padding: 10px;
9
+ margin-bottom: 5px;
10
+ font-size: 16px;
11
+ border-bottom-width: 1px;
12
+ border-bottom-color: ${(props: any) => props.theme.colors.lightGray};
13
+ flex-direction: row;
14
+ align-items: center;
15
+ `
@@ -0,0 +1,474 @@
1
+ import React, { useState, useEffect } from 'react'
2
+ import { TouchableOpacity, StyleSheet, View, Text } from 'react-native'
3
+ import { useLanguage, useUtils, useConfig, useOrder, MomentOption } from 'ordering-components/native'
4
+ import { OButton, OModal, OText } from '../shared'
5
+ import { useTheme } from 'styled-components/native'
6
+ import IconAntDesign from 'react-native-vector-icons/AntDesign'
7
+ import FastImage from 'react-native-fast-image'
8
+ import CalendarStrip from 'react-native-calendar-strip'
9
+ import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
10
+ import { BusinessMenuList } from '../BusinessMenuList'
11
+ import Spinner from 'react-native-loading-spinner-overlay'
12
+ import { BusinessPreorderParams } from '../../types'
13
+ import moment from 'moment'
14
+ import {
15
+ PreOrderContainer,
16
+ BusinessInfoWrapper,
17
+ PreorderTypeWrapper,
18
+ MenuWrapper,
19
+ OrderTimeWrapper,
20
+ TimeListWrapper,
21
+ TimeContentWrapper,
22
+ TimeItem,
23
+ PreorderTypeListWrapper,
24
+ DropOption
25
+ } from './styles'
26
+
27
+ const BusinessPreorderUI = (props: BusinessPreorderParams) => {
28
+ const {
29
+ goToBack,
30
+ business,
31
+ datesList,
32
+ hoursList,
33
+ dateSelected,
34
+ timeSelected,
35
+ handleBusinessClick,
36
+ handleChangeDate,
37
+ handleChangeTime
38
+ } = props
39
+
40
+ const theme = useTheme()
41
+ const [, t] = useLanguage()
42
+ const [{ optimizeImage, parseTime }] = useUtils()
43
+ const [{ configs }] = useConfig()
44
+ const [orderState] = useOrder()
45
+ const [selectedPreorderType, setSelectedPreorderType] = useState({ key: 'business_hours', name: t('BUSINESS_HOURS', 'Business hours') })
46
+ const [isPreorderTypeList, setIsPreorderTypeList] = useState(false)
47
+ const [menu, setMenu] = useState({})
48
+ const [timeList, setTimeList] = useState<any>([])
49
+ const [selectDate, setSelectedDate] = useState<any>(null)
50
+ const [datesWhitelist, setDateWhitelist] = useState<any>([{start: null, end: null}])
51
+
52
+ const styles = StyleSheet.create({
53
+ businessLogo: {
54
+ backgroundColor: 'white',
55
+ width: 60,
56
+ height: 60,
57
+ borderRadius: 7.6,
58
+ justifyContent: 'center',
59
+ alignItems: 'center',
60
+ shadowColor: '#000000',
61
+ shadowOffset: { width: 0, height: 1 },
62
+ shadowOpacity: 0.1,
63
+ shadowRadius: 1,
64
+ elevation: 2
65
+ },
66
+ selectOption: {
67
+ backgroundColor: theme.colors.backgroundGray100,
68
+ borderRadius: 7.6,
69
+ paddingVertical: 10,
70
+ paddingHorizontal: 14,
71
+ flexDirection: 'row',
72
+ alignItems: 'center',
73
+ justifyContent: 'space-between',
74
+ height: 44
75
+ },
76
+ calendar: {
77
+ paddingBottom: 15,
78
+ borderBottomWidth: 1,
79
+ borderColor: theme.colors.backgroundGray200,
80
+ height: 90
81
+ },
82
+ calendarHeaderContainer: {
83
+ flex: 1,
84
+ justifyContent: 'flex-start',
85
+ textAlign: 'left',
86
+ marginBottom: 17,
87
+ borderBottomWidth: 1,
88
+ borderColor: theme.colors.backgroundGray200
89
+ },
90
+ calendarHeader: {
91
+ color: '#344050',
92
+ alignSelf: 'flex-start',
93
+ fontSize: 14,
94
+ fontWeight: '400'
95
+ },
96
+ dateNumber: {
97
+ color: '#B1BCCC',
98
+ fontSize: 16,
99
+ fontWeight: '500'
100
+ },
101
+ dateName: {
102
+ color: '#B1BCCC',
103
+ fontSize: 12,
104
+ textTransform: 'capitalize'
105
+ },
106
+ highlightDateName: {
107
+ color: '#344050',
108
+ fontSize: 12,
109
+ textTransform: 'capitalize'
110
+ },
111
+ highlightDateNumber: {
112
+ color: '#344050',
113
+ fontSize: 16,
114
+ textTransform: 'capitalize'
115
+ },
116
+ disabledDateName: {
117
+ color: '#B1BCCC',
118
+ fontSize: 10,
119
+ textTransform: 'capitalize',
120
+ opacity: 1
121
+ },
122
+ disabledDateNumber: {
123
+ color: '#B1BCCC',
124
+ fontSize: 14,
125
+ fontWeight: '500'
126
+ }
127
+ })
128
+
129
+ const preorderTypeList = [
130
+ { key: 'business_menu', name: t('BUSINESS_MENU', 'Business menu') },
131
+ { key: 'business_hours', name: t('BUSINESS_HOURS', 'Business hours') }
132
+ ]
133
+
134
+ const handleClickPreorderType = (option: any) => {
135
+ setSelectedPreorderType(option)
136
+ setIsPreorderTypeList(false)
137
+ }
138
+
139
+ const getTimes = (curdate: any, menu: any) => {
140
+ const date = new Date()
141
+ var dateSeleted = new Date(curdate)
142
+ var times = []
143
+ for (var k = 0; k < menu.schedule[dateSeleted.getDay()].lapses.length; k++) {
144
+ var open = {
145
+ hour: menu.schedule[dateSeleted.getDay()].lapses[k].open.hour,
146
+ minute: menu.schedule[dateSeleted.getDay()].lapses[k].open.minute
147
+ }
148
+ var close = {
149
+ hour: menu.schedule[dateSeleted.getDay()].lapses[k].close.hour,
150
+ minute: menu.schedule[dateSeleted.getDay()].lapses[k].close.minute
151
+ }
152
+ for (var i = open.hour; i <= close.hour; i++) {
153
+ if (date.getDate() !== dateSeleted.getDate() || i >= date.getHours()) {
154
+ let hour = ''
155
+ let meridian = ''
156
+ if (configs?.format_time?.value === '12') {
157
+ if (i === 0) {
158
+ hour = '12'
159
+ meridian = ' ' + t('AM', 'AM')
160
+ } else if (i > 0 && i < 12) {
161
+ hour = (i < 10 ? '0' + i : i)
162
+ meridian = ' ' + t('AM', 'AM')
163
+ } else if (i === 12) {
164
+ hour = '12'
165
+ meridian = ' ' + t('PM', 'PM')
166
+ } else {
167
+ hour = ((i - 12 < 10) ? '0' + (i - 12) : `${(i - 12)}`)
168
+ meridian = ' ' + t('PM', 'PM')
169
+ }
170
+ } else {
171
+ hour = i < 10 ? '0' + i : i
172
+ }
173
+ for (let j = (i === open.hour ? open.minute : 0); j <= (i === close.hour ? close.minute : 59); j += 15) {
174
+ if (i !== date.getHours() || j >= date.getMinutes() || date.getDate() !== dateSeleted.getDate()) {
175
+ times.push({
176
+ text: hour + ':' + (j < 10 ? '0' + j : j) + meridian,
177
+ value: (i < 10 ? '0' + i : i) + ':' + (j < 10 ? '0' + j : j)
178
+ })
179
+ }
180
+ }
181
+ }
182
+ }
183
+ }
184
+ return times
185
+ }
186
+
187
+ const onSelectDate = (val: any) => {
188
+ setSelectedDate(val)
189
+ if (handleChangeDate) handleChangeDate(moment(val).format('YYYY-MM-DD'))
190
+ }
191
+
192
+ const LeftSelector = () => {
193
+ return (
194
+ <View style={{height: '100%', justifyContent: 'flex-end'}}>
195
+ <IconAntDesign
196
+ name='caretleft'
197
+ color={theme.colors.textNormal}
198
+ size={16}
199
+ />
200
+ </View>
201
+ )
202
+ }
203
+
204
+ const RightSelector = () => {
205
+ return (
206
+ <View style={{height: '100%', justifyContent: 'flex-end'}}>
207
+ <IconAntDesign
208
+ name='caretright'
209
+ color={theme.colors.textNormal}
210
+ size={16}
211
+ />
212
+ </View>
213
+ )
214
+ }
215
+
216
+ useEffect(() => {
217
+ if (datesList?.length > 0) {
218
+ const _datesList = datesList.slice(0, Number(configs?.max_days_preorder?.value || 6))
219
+ const minDateParts = _datesList[0].split('-')
220
+ const maxDateParts = _datesList[_datesList.length - 1].split('-')
221
+ const _minDate = new Date(minDateParts[0], minDateParts[1] - 1, minDateParts[2])
222
+ const _maxDate = new Date(maxDateParts[0], maxDateParts[1] - 1, maxDateParts[2])
223
+ setDateWhitelist([{ start: _minDate, end: _maxDate }])
224
+ }
225
+ }, [datesList])
226
+
227
+ const handleClickBusiness = () => {
228
+ handleBusinessClick && handleBusinessClick(business)
229
+ }
230
+
231
+ useEffect(() => {
232
+ if (hoursList.length === 0) return
233
+ if (Object.keys(menu).length > 0) {
234
+ const _times: any = getTimes(selectDate, menu)
235
+ setTimeList(_times)
236
+ } else {
237
+ const _timeLists = hoursList.map((hour: any) => {
238
+ return {
239
+ value: hour.startTime,
240
+ text: configs?.format_time?.value === '12' ? (
241
+ hour.startTime.includes('12')
242
+ ? `${hour.startTime}PM`
243
+ : parseTime(moment(hour.startTime, 'HH:mm'), { outputFormat: 'hh:mma' })
244
+ ) : (
245
+ parseTime(moment(hour.startTime, 'HH:mm'), { outputFormat: 'HH:mm' })
246
+ )
247
+ }
248
+ })
249
+ setTimeList(_timeLists)
250
+ }
251
+ }, [selectDate, hoursList, menu])
252
+
253
+ useEffect(() => {
254
+ if (selectedPreorderType.key === 'business_hours' && Object.keys(menu).length > 0) setMenu({})
255
+ }, [selectedPreorderType])
256
+
257
+ useEffect(() => {
258
+ if (dateSelected) {
259
+ const dateParts = dateSelected.split('-')
260
+ const _dateSelected = new Date(dateParts[0], dateParts[1] - 1, dateParts[2])
261
+ setSelectedDate(_dateSelected)
262
+ }
263
+ }, [dateSelected])
264
+
265
+ return (
266
+ <>
267
+ <PreOrderContainer>
268
+ <TouchableOpacity onPress={() => goToBack && goToBack()} style={{ marginBottom: 12 }}>
269
+ <IconAntDesign
270
+ name='close'
271
+ color={theme.colors.textThird}
272
+ size={24}
273
+ />
274
+ </TouchableOpacity>
275
+ <BusinessInfoWrapper>
276
+ <OText
277
+ size={20}
278
+ style={{
279
+ fontWeight: '600'
280
+ }}
281
+ >{t('PREORDER', 'Preorder')}</OText>
282
+ <View style={styles.businessLogo}>
283
+ <FastImage
284
+ style={{ width: 59, height: 59 }}
285
+ source={{
286
+ uri: optimizeImage(business?.logo, 'h_60,c_limit'),
287
+ priority: FastImage.priority.normal,
288
+ }}
289
+ resizeMode={FastImage.resizeMode.cover}
290
+ />
291
+ </View>
292
+ </BusinessInfoWrapper>
293
+ <PreorderTypeWrapper>
294
+ <OText
295
+ size={16}
296
+ style={{
297
+ fontWeight: '600',
298
+ lineHeight: 24,
299
+ marginBottom: 12
300
+ }}
301
+ >
302
+ {t('PREORDER_TYPE', 'Preorder type')}
303
+ </OText>
304
+ <TouchableOpacity onPress={() => setIsPreorderTypeList(true)}>
305
+ <View style={styles.selectOption}>
306
+ <OText
307
+ size={14}
308
+ color={theme.colors.disabled}
309
+ style={{
310
+ lineHeight: 24
311
+ }}
312
+ >
313
+ {selectedPreorderType.name}
314
+ </OText>
315
+ <IconAntDesign
316
+ name='down'
317
+ color={theme.colors.textThird}
318
+ size={16}
319
+ />
320
+ </View>
321
+ </TouchableOpacity>
322
+ </PreorderTypeWrapper>
323
+ {selectedPreorderType?.key === 'business_menu' && (
324
+ <MenuWrapper>
325
+ <OText
326
+ size={16}
327
+ style={{
328
+ fontWeight: '600',
329
+ lineHeight: 24,
330
+ marginBottom: 12
331
+ }}
332
+ >
333
+ {t('MENU', 'Menu')}
334
+ </OText>
335
+ <BusinessMenuList
336
+ businessId={business.id}
337
+ setMenu={setMenu}
338
+ menu={menu}
339
+ />
340
+ </MenuWrapper>
341
+ )}
342
+ <OrderTimeWrapper>
343
+ <OText
344
+ size={16}
345
+ style={{
346
+ fontWeight: '600',
347
+ lineHeight: 24
348
+ }}
349
+ >
350
+ {t('ORDER_TIME', 'Order time')}
351
+ </OText>
352
+ <View style={{ flex: 1 }}>
353
+ {selectDate && datesWhitelist[0].start !== null && (
354
+ <CalendarStrip
355
+ scrollable
356
+ style={styles.calendar}
357
+ calendarHeaderContainerStyle={styles.calendarHeaderContainer}
358
+ calendarHeaderStyle={styles.calendarHeader}
359
+ dateNumberStyle={styles.dateNumber}
360
+ dateNameStyle={styles.dateName}
361
+ iconContainer={{flex: 0.1}}
362
+ highlightDateNameStyle={styles.highlightDateName}
363
+ highlightDateNumberStyle={styles.highlightDateNumber}
364
+ calendarHeaderFormat='MMMM, YYYY'
365
+ iconStyle={{borderWidth: 1}}
366
+ selectedDate={selectDate}
367
+ datesWhitelist={datesWhitelist}
368
+ disabledDateNameStyle={styles.disabledDateName}
369
+ disabledDateNumberStyle={styles.disabledDateNumber}
370
+ disabledDateOpacity={0.6}
371
+ onDateSelected={(date) => onSelectDate(date)}
372
+ leftSelector={<LeftSelector />}
373
+ rightSelector={<RightSelector />}
374
+ />
375
+ )}
376
+ </View>
377
+ <TimeListWrapper nestedScrollEnabled={true}>
378
+ <TimeContentWrapper>
379
+ {timeList.map((time: any, i: number) => (
380
+ <TouchableOpacity key={i} onPress={() => handleChangeTime(time.value)}>
381
+ <TimeItem active={timeSelected === time.value}>
382
+ <OText
383
+ size={14}
384
+ color={timeSelected === time.value ? theme.colors.primary: theme.colors.textNormal}
385
+ style={{
386
+ lineHeight: 24
387
+ }}
388
+ >{time.text}</OText>
389
+ </TimeItem>
390
+ </TouchableOpacity>
391
+ ))}
392
+ {timeList.length % 3 === 2 && (
393
+ <TimeItem style={{backgroundColor: 'transparent'}}/>
394
+ )}
395
+ </TimeContentWrapper>
396
+ </TimeListWrapper>
397
+ </OrderTimeWrapper>
398
+ <OButton
399
+ text={t('GO_TO_MENU', 'Go to menu')}
400
+ textStyle={{color: 'white'}}
401
+ style={{borderRadius: 7.6, marginBottom: 50, marginTop: 30}}
402
+ onClick={() => handleClickBusiness()}
403
+ />
404
+ </PreOrderContainer>
405
+ <Spinner visible={orderState.loading} />
406
+ <OModal
407
+ open={isPreorderTypeList}
408
+ onClose={() => setIsPreorderTypeList(false)}
409
+ customClose
410
+ entireModal
411
+ >
412
+ <PreorderTypeListWrapper>
413
+ <TouchableOpacity onPress={() => setIsPreorderTypeList(false)} style={{ marginBottom: 12 }}>
414
+ <IconAntDesign
415
+ name='close'
416
+ color={theme.colors.textThird}
417
+ size={24}
418
+ />
419
+ </TouchableOpacity>
420
+ {preorderTypeList?.map((option: any, index: number) => (
421
+ <TouchableOpacity
422
+ key={index}
423
+ onPress={() => handleClickPreorderType(option)}
424
+ >
425
+ <DropOption
426
+ numberOfLines={1}
427
+ selected={option.key === selectedPreorderType.key}
428
+ >
429
+ <View style={{ marginRight: 10 }}>
430
+ {option.key === selectedPreorderType.key ? (
431
+ <MaterialCommunityIcons
432
+ name='radiobox-marked'
433
+ size={24}
434
+ color={theme.colors.primary}
435
+ />
436
+ ) : (
437
+ <MaterialCommunityIcons
438
+ name='radiobox-blank'
439
+ size={24}
440
+ color={theme.colors.arrowColor}
441
+ />
442
+ )}
443
+ </View>
444
+ <Text>{option.name}</Text>
445
+ </DropOption>
446
+ </TouchableOpacity>
447
+ ))}
448
+ </PreorderTypeListWrapper>
449
+ </OModal>
450
+ </>
451
+ )
452
+ }
453
+
454
+ export const BusinessPreorder = (props: any) => {
455
+ const [{ configs }] = useConfig()
456
+
457
+ const limitDays = parseInt(configs?.max_days_preorder?.value, 10)
458
+
459
+ const currentDate = new Date()
460
+ const time = limitDays > 1
461
+ ? currentDate.getTime() + ((limitDays - 1) * 24 * 60 * 60 * 1000)
462
+ : limitDays === 1 ? currentDate.getTime() : currentDate.getTime() + (6 * 24 * 60 * 60 * 1000)
463
+
464
+ currentDate.setTime(time)
465
+ currentDate.setHours(23)
466
+ currentDate.setMinutes(59)
467
+
468
+ const businessPreorderProps = {
469
+ ...props,
470
+ UIComponent: BusinessPreorderUI,
471
+ maxDate: currentDate
472
+ }
473
+ return <MomentOption {...businessPreorderProps} />
474
+ }
@@ -0,0 +1,60 @@
1
+ import styled, { css } from 'styled-components/native'
2
+
3
+ export const PreOrderContainer = styled.ScrollView`
4
+ padding: 20px 40px 30px 40px;
5
+ `
6
+
7
+ export const BusinessInfoWrapper = styled.View`
8
+ flex-direction: row;
9
+ justify-content: space-between;
10
+ align-items: center;
11
+ `
12
+
13
+ export const PreorderTypeWrapper = styled.View`
14
+ margin-top: 23px;
15
+ `
16
+
17
+ export const MenuWrapper = styled(PreorderTypeWrapper)``
18
+
19
+ export const OrderTimeWrapper = styled.View`
20
+ margin-top: 34px;
21
+ `
22
+
23
+ export const TimeListWrapper = styled.ScrollView`
24
+ margin-top: 30px;
25
+ max-height: 160px;
26
+ `
27
+
28
+ export const TimeContentWrapper = styled.View`
29
+ flex: 1;
30
+ flex-wrap: wrap;
31
+ flex-direction: row;
32
+ justify-content: space-between;
33
+ `
34
+
35
+ export const TimeItem = styled.View`
36
+ width: 86px;
37
+ height: 34px;
38
+ background: #E9ECEF;
39
+ border-radius: 7.6px;
40
+ justify-content: center;
41
+ align-items: center;
42
+ margin: 10px 0px;
43
+ ${({ active }: any) => active && css`
44
+ background: #F5F9FF;
45
+ `}
46
+ `
47
+
48
+ export const PreorderTypeListWrapper = styled.ScrollView`
49
+ padding: 20px 40px 30px 40px;
50
+ `
51
+
52
+ export const DropOption = styled.View`
53
+ padding: 10px;
54
+ margin-bottom: 5px;
55
+ font-size: 16px;
56
+ border-bottom-width: 1px;
57
+ border-bottom-color: ${(props: any) => props.theme.colors.lightGray};
58
+ flex-direction: row;
59
+ align-items: center;
60
+ `
@@ -263,7 +263,7 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
263
263
  </FeaturedWrapper>
264
264
  )}
265
265
  <View style={{ height: 8, backgroundColor: theme.colors.backgroundGray100 }} />
266
- <HighestRatedBusinesses onBusinessClick={handleBusinessClick} />
266
+ <HighestRatedBusinesses onBusinessClick={handleBusinessClick} navigation={navigation} />
267
267
  <View style={{ height: 8, backgroundColor: theme.colors.backgroundGray100 }} />
268
268
  <ListWrapper>
269
269
  <BusinessTypeFilter
@@ -287,6 +287,7 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
287
287
  business={business}
288
288
  handleCustomClick={handleBusinessClick}
289
289
  orderType={orderState?.options?.type}
290
+ navigation={navigation}
290
291
  />
291
292
  )
292
293
  )}
@@ -17,7 +17,8 @@ import {
17
17
  const HighestRatedBusinessesUI = (props: HighestRatedBusinessesParams) => {
18
18
  const {
19
19
  businessesList,
20
- onBusinessClick
20
+ onBusinessClick,
21
+ navigation
21
22
  } = props;
22
23
 
23
24
  const [, t] = useLanguage()
@@ -104,6 +105,7 @@ const HighestRatedBusinessesUI = (props: HighestRatedBusinessesParams) => {
104
105
  business={business}
105
106
  handleCustomClick={onBusinessClick}
106
107
  orderType={orderState?.options?.type}
108
+ navigation={navigation}
107
109
  />
108
110
  </View>
109
111
  )
@@ -132,6 +132,7 @@ export interface BusinessesListingParams {
132
132
  export interface HighestRatedBusinessesParams {
133
133
  businessesList: { businesses: Array<any>, loading: boolean, error: null | string };
134
134
  onBusinessClick?: void;
135
+ navigation? :any;
135
136
  }
136
137
  export interface BusinessTypeFilterParams {
137
138
  businessTypes?: Array<any>;
@@ -149,7 +150,8 @@ export interface BusinessControllerParams {
149
150
  handleClick?: any;
150
151
  isBusinessOpen?: boolean;
151
152
  businessWillCloseSoonMinutes?: number
152
- isBusinessClose?: number
153
+ isBusinessClose?: number,
154
+ navigation?: any
153
155
  }
154
156
  export interface BusinessProductsListingParams {
155
157
  navigation?: any;
@@ -379,6 +381,25 @@ export interface MomentOptionParams {
379
381
  handleChangeDate: (value: any) => {};
380
382
  handleChangeTime: (value: any) => {};
381
383
  }
384
+ export interface BusinessPreorderParams {
385
+ navigation?: any;
386
+ datesList: Array<any>;
387
+ hoursList: Array<any>;
388
+ dateSelected?: any;
389
+ timeSelected?: any;
390
+ isAsap?: boolean;
391
+ handleAsap?: () => {};
392
+ handleChangeDate: (value: any) => {};
393
+ handleChangeTime: (value: any) => {};
394
+ goToBack: any;
395
+ business: any;
396
+ handleBusinessClick: (value: any) => {};
397
+ }
398
+ export interface BusinessMenuListParams {
399
+ menu: any;
400
+ businessMenuList: any;
401
+ setMenu: (value: any) => {};
402
+ }
382
403
  export interface OrderTypeSelectParams {
383
404
  navigation?: any;
384
405
  handleChangeOrderType: (value: any) => {};
@@ -65,8 +65,8 @@ export const BusinessBasicInformation = (
65
65
  <BusinessHeader
66
66
  style={
67
67
  isBusinessInfoShow
68
- ? {...styles.businesInfoheaderStyle, paddingTop: top}
69
- : { ...styles.headerStyle, paddingTop: top, backgroundColor: theme.colors.backgroundGray }
68
+ ? {...styles.businesInfoheaderStyle, paddingTop: 0}
69
+ : { ...styles.headerStyle, paddingTop: 0, backgroundColor: theme.colors.backgroundGray }
70
70
  }
71
71
  source={{
72
72
  uri:
@@ -182,7 +182,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
182
182
  >
183
183
  <WrapHeader>
184
184
  {(!auth || props.isFranchiseApp) && !loading &&
185
- <TopHeader style={{top: top}}>
185
+ <TopHeader style={{top: 0}}>
186
186
  <NavBar
187
187
  style={{ paddingBottom: 0, marginLeft: 20, backgroundColor: 'transparent' }}
188
188
  btnStyle={{ backgroundColor: 'transparent' }}
@@ -297,7 +297,7 @@ const BusinessProductsListingUI = (props: BusinessProductsListingParams) => {
297
297
  btnRightValue={parsePrice(currentCart?.total)}
298
298
  disabled={openUpselling || currentCart?.subtotal < currentCart?.minimum}
299
299
  handleClick={() => onRedirect('Cart')}
300
- hasBottom
300
+ hasBottom={false}
301
301
  />
302
302
  )}
303
303
  <OModal
@@ -163,7 +163,7 @@ const BusinessesListingUI = (props: BusinessesListingParams) => {
163
163
  isFromBusinesses: true,
164
164
  })
165
165
  }
166
- style={{ marginTop: !auth ? 36 : top > 0 ? 0 : 20 }}
166
+ style={{ marginTop: !auth ? 36 : 20 }}
167
167
  activeOpacity={0.8}
168
168
  >
169
169
  <OIcon src={theme.images.general.pin} width={16} color={theme.colors.textSecondary} />
@@ -8,7 +8,7 @@ import {
8
8
  useValidationFields,
9
9
  } from 'ordering-components/native';
10
10
  import { useTheme } from 'styled-components/native';
11
- import { ScrollView, View, useWindowDimensions, ActivityIndicator } from 'react-native';
11
+ import { ScrollView, View, useWindowDimensions, ActivityIndicator, StyleSheet } from 'react-native';
12
12
  import {
13
13
  CheckoutAction,
14
14
  OSBill,
@@ -20,7 +20,8 @@ import {
20
20
  BIHeader,
21
21
  BIInfo,
22
22
  BIContentInfo,
23
- BITotal
23
+ BITotal,
24
+ TopHeader
24
25
  } from './styles';
25
26
 
26
27
  import { ProductItemAccordion } from '../ProductItemAccordion';
@@ -187,6 +188,15 @@ const CartUI = (props: any) => {
187
188
  )
188
189
  }
189
190
 
191
+ const styles = StyleSheet.create({
192
+ headerItem: {
193
+ overflow: 'hidden',
194
+ backgroundColor: theme.colors.clear,
195
+ width: 35,
196
+ marginVertical: 18,
197
+ },
198
+ })
199
+
190
200
  return (
191
201
  cart?.products?.length > 0 ? (
192
202
  <ScrollView
@@ -307,32 +317,22 @@ const CartUI = (props: any) => {
307
317
  </OSTable>
308
318
  )}
309
319
 
310
- <OSTotal>
311
- <OSTable style={{ marginTop: 15 }}>
312
- <OText size={14} lineHeight={21} weight={'600'}>
313
- {t('TOTAL', 'Total')}
314
- </OText>
315
- <OText size={14} lineHeight={21} weight={'600'}>
316
- {cart?.total >= 1 && parsePrice(cart?.total)}
317
- </OText>
318
- </OSTable>
319
- </OSTotal>
320
320
  {cart?.status !== 2 && (
321
321
  <OSTable>
322
- <View style={{ width: '100%', marginTop: 20 }}>
323
- <OText size={12}>{t('COMMENTS', 'Comments')}</OText>
322
+ <View style={{ width: '100%', marginTop: 0 }}>
323
+ <OText size={14} style={{ marginBottom: 10 }}>{t('COMMENTS', 'Comments')}</OText>
324
324
  <View style={{ flex: 1, width: '100%' }}>
325
325
  <OInput
326
326
  value={cart?.comment}
327
327
  placeholder={t('SPECIAL_COMMENTS', 'Special Comments')}
328
328
  onChange={(value: string) => handleChangeComment(value)}
329
329
  style={{
330
+ borderColor: theme.colors.border,
331
+ borderRadius: 10,
332
+ marginBottom: 20,
333
+ height: 104,
334
+ maxHeight: 104,
330
335
  alignItems: 'flex-start',
331
- width: '100%',
332
- height: 100,
333
- borderColor: theme.colors.textSecondary,
334
- paddingRight: 50,
335
- marginTop: 10
336
336
  }}
337
337
  multiline
338
338
  />
@@ -349,6 +349,17 @@ const CartUI = (props: any) => {
349
349
  </View>
350
350
  </OSTable>
351
351
  )}
352
+
353
+ <OSTotal>
354
+ <OSTable style={{ marginTop: 15 }}>
355
+ <OText size={14} lineHeight={21} weight={'600'}>
356
+ {t('TOTAL', 'Total')}
357
+ </OText>
358
+ <OText size={14} lineHeight={21} weight={'600'}>
359
+ {cart?.total >= 1 && parsePrice(cart?.total)}
360
+ </OText>
361
+ </OSTable>
362
+ </OSTotal>
352
363
  </OSBill>
353
364
  )}
354
365
  </View>
@@ -427,7 +438,24 @@ const CartUI = (props: any) => {
427
438
  onSave={handlerProductAction}
428
439
  onClose={() => setModalIsOpen(false)}
429
440
  />
441
+ </OModal>
430
442
 
443
+ <OModal
444
+ open={openTaxModal.open}
445
+ onClose={() => setOpenTaxModal({ open: false, data: null })}
446
+ entireModal
447
+ customClose
448
+ >
449
+ <>
450
+ <TopHeader>
451
+ <TouchableOpacity
452
+ style={styles.headerItem}
453
+ onPress={() => setOpenTaxModal({ open: false, data: null })}>
454
+ <OIcon src={theme.images.general.close} width={16} />
455
+ </TouchableOpacity>
456
+ </TopHeader>
457
+ <TaxInformation data={openTaxModal.data} products={cart?.products} />
458
+ </>
431
459
  </OModal>
432
460
  </ScrollView>
433
461
  ) : (
@@ -445,13 +473,6 @@ const CartUI = (props: any) => {
445
473
  image={theme.images.general.notFound}
446
474
  />
447
475
  </View>
448
- <OModal
449
- open={openTaxModal.open}
450
- onClose={() => setOpenTaxModal({ open: false, data: null })}
451
- entireModal
452
- >
453
- <TaxInformation data={openTaxModal.data} products={cart?.products} />
454
- </OModal>
455
476
  </Container>
456
477
  )
457
478
  )
@@ -100,3 +100,12 @@ export const BITotal = styled.View`
100
100
  flex-direction: column;
101
101
  align-items: flex-end;
102
102
  `
103
+
104
+ export const TopHeader = styled.View`
105
+ width: 100%;
106
+ flex-direction: row;
107
+ align-items: center;
108
+ justify-content: space-between;
109
+ z-index: 1;
110
+ padding-horizontal: 40px;
111
+ `
@@ -21,31 +21,36 @@ export const TaxInformation = (props: taxInformationParams) => {
21
21
  const isTax = typeof data?.rate === 'number'
22
22
  const TaxFeeString = isTax ? 'tax' : 'fee'
23
23
  const includedOnPriceString = data?.type === 1 ? `(${t('INCLUDED_ON_PRICE', 'Included on price')})` : `(${t('NOT_INCLUDED_ON_PRICE', 'Not included on price')})`
24
+ const productsWithTaxes = products
25
+ .filter((product: any) => isTax
26
+ ? (product.tax?.id ? product.tax?.id === data?.id: product.tax?.id === null && data?.id === null)
27
+ : (product.fee?.id ? product.fee?.id === data?.id : (product.fee?.id === null && data?.id === null))) ?? []
24
28
 
25
29
  return (
26
30
  <TaxInformationContainer>
27
- <OText size={24} style={{ alignSelf: 'center', textAlign: 'center' }} mBottom={10}>
28
- {`${data?.name ||
29
- t('INHERIT_FROM_BUSINESS', 'Inherit from business')} (${typeof data?.rate === 'number' ? `${data?.rate}%` : `${parsePrice(data?.fixed ?? 0)} + ${data?.percentage}%`})`}
31
+ <OText size={18} style={{ alignSelf: 'flex-start', textAlign: 'left' }} mBottom={10}>
32
+ {`${data?.name ?? t('INHERIT_FROM_BUSINESS', 'Inherit from business')} (${typeof data?.rate === 'number' ? `${data?.rate}%` : `${parsePrice(data?.fixed ?? 0)} + ${data?.percentage}%`})`}
30
33
  </OText>
31
34
  {data?.description && (
32
- <OText mBottom={10} size={18} style={{ alignSelf: 'center', textAlign: 'center' }}>
35
+ <OText mBottom={10} size={16} style={{ alignSelf: 'flex-start', textAlign: 'left' }}>
33
36
  {t('DESCRIPTION', 'Description')}: {data?.description} {data?.type && includedOnPriceString}
34
37
  </OText>
35
38
  )}
36
- <OText>{t(`OTHER_PRODUCTS_WITH_THIS_${TaxFeeString.toUpperCase()}`, `Other products with this ${TaxFeeString}`)}:</OText>
37
- <ProductContainer>
38
- {
39
- products.filter((product: any) => isTax ? (product.tax?.id ? product.tax?.id === data?.id : product.tax?.id === null && data?.id === null) : (product.fee?.id ? product.fee?.id === data?.id : (product.fee?.id === null && data?.id === null))).map(product => (
40
- <SingleProductCard
41
- key={product.id}
42
- product={product}
43
- isSoldOut={false}
44
- businessId={product?.business_id}
45
- />
46
- ))
47
- }
48
- </ProductContainer>
39
+ {productsWithTaxes.length > 0 && (
40
+ <>
41
+ <OText>{`${t(`OTHER_PRODUCTS_WITH_THIS_${TaxFeeString.toUpperCase()}`, `Other products with this ${TaxFeeString}`)}:`}</OText>
42
+ <ProductContainer>
43
+ {productsWithTaxes.map(product => (
44
+ <SingleProductCard
45
+ key={product.id}
46
+ product={product}
47
+ isSoldOut={false}
48
+ businessId={product?.business_id}
49
+ />
50
+ ))}
51
+ </ProductContainer>
52
+ </>
53
+ )}
49
54
  </TaxInformationContainer>
50
55
  )
51
56
  }
@@ -1,9 +1,10 @@
1
1
  import styled from 'styled-components/native'
2
2
 
3
3
  export const TaxInformationContainer = styled.ScrollView`
4
- padding: 10px;
4
+ padding: 10px 40px;
5
5
  `
6
6
 
7
7
  export const ProductContainer = styled.View`
8
- flex: 1
8
+ flex: 1;
9
+ margin-top: 10px;
9
10
  `
@@ -215,7 +215,7 @@ export interface SingleProductCardParams {
215
215
  businessId: any,
216
216
  product: any;
217
217
  isSoldOut: boolean;
218
- onProductClick: any;
218
+ onProductClick?: any;
219
219
  }
220
220
  export interface BusinessInformationParams {
221
221
  navigation?: any,