ordering-ui-react-native 0.12.62 → 0.12.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ordering-ui-react-native",
3
- "version": "0.12.62",
3
+ "version": "0.12.63",
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",
@@ -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) => {};