ordering-ui-react-native 0.12.24 → 0.12.28
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 +1 -1
- package/src/components/ProductForm/index.tsx +18 -11
- package/themes/business/index.tsx +2 -0
- package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +19 -22
- package/themes/business/src/components/LoginForm/index.tsx +1 -0
- package/themes/business/src/components/OrderDetails/Delivery.tsx +4 -8
- package/themes/business/src/components/OrderDetails/OrderContentComponent.tsx +40 -3
- package/themes/business/src/components/OrdersOptionDate/index.tsx +2 -1
- package/themes/business/src/components/ReviewCustomer/index.tsx +314 -0
- package/themes/business/src/components/ReviewCustomer/styles.tsx +28 -0
- package/themes/business/src/components/shared/ODropDownCalendar.tsx +20 -18
- package/themes/business/src/types/index.tsx +14 -1
- package/themes/single-business/index.tsx +4 -0
- package/themes/single-business/src/components/OrderListOption/index.tsx +231 -0
- package/themes/single-business/src/components/OrderListOption/styles.tsx +62 -0
- package/themes/single-business/src/components/OrdersListing/index.tsx +112 -0
- package/themes/single-business/src/components/UserProfile/index.tsx +7 -1
- package/themes/single-business/src/utils/index.tsx +32 -1
package/package.json
CHANGED
|
@@ -131,22 +131,29 @@ export const ProductOptionsUI = (props: any) => {
|
|
|
131
131
|
</Placeholder>
|
|
132
132
|
) : (
|
|
133
133
|
<>
|
|
134
|
-
<
|
|
135
|
-
|
|
134
|
+
<View style={{ flexDirection: 'column', width: '100%' }}>
|
|
135
|
+
<OText size={20} style={{ flex: I18nManager.isRTL ? 0 : 1, marginBottom: 10 }}>{product?.name || productCart.name}{'price'}</OText>
|
|
136
|
+
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginBottom: 10 }}>
|
|
137
|
+
<OText size={16} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={theme.colors.primary}>{productCart.price ? parsePrice(productCart.price) : ''}</OText>
|
|
138
|
+
<OText size={14} style={{ flex: I18nManager.isRTL ? 1 : 0 }} color={'#909BA9'}>
|
|
139
|
+
{
|
|
140
|
+
((product?.sku && product?.sku !== '-1' && product?.sku !== '1') || (productCart?.sku && productCart?.sku !== '-1' && productCart?.sku !== '1'))
|
|
141
|
+
&& <>{t('SKU', 'Sku')}{' '}{product?.sku || productCart?.sku}</>
|
|
142
|
+
}
|
|
143
|
+
{product?.sku && product?.sku !== '-1' && product?.sku !== '1' && product?.estimated_person && (
|
|
144
|
+
<> · </>
|
|
145
|
+
)}
|
|
146
|
+
{product?.estimated_person
|
|
147
|
+
&& <>{product?.estimated_person}{' '}{t('ESTIMATED_PERSONS', 'persons')}</>
|
|
148
|
+
}
|
|
149
|
+
</OText>
|
|
150
|
+
</View>
|
|
151
|
+
</View>
|
|
136
152
|
</>
|
|
137
153
|
)}
|
|
138
154
|
</ProductTitle>
|
|
139
155
|
<ProductDescription>
|
|
140
156
|
<OText>{product?.description || productCart?.description}</OText>
|
|
141
|
-
{(
|
|
142
|
-
(product?.sku && product?.sku !== '-1' && product?.sku !== '1') ||
|
|
143
|
-
(productCart?.sku && productCart?.sku !== '-1' && productCart?.sku !== '1')
|
|
144
|
-
) && (
|
|
145
|
-
<>
|
|
146
|
-
<OText size={20}>{t('SKU', 'Sku')}</OText>
|
|
147
|
-
<OText>{product?.sku || productCart?.sku}</OText>
|
|
148
|
-
</>
|
|
149
|
-
)}
|
|
150
157
|
</ProductDescription>
|
|
151
158
|
{loading && !product ? (
|
|
152
159
|
<>
|
|
@@ -27,6 +27,7 @@ import { PhoneInputNumber } from './src/components/PhoneInputNumber';
|
|
|
27
27
|
import { PreviousMessages } from './src/components/PreviousMessages';
|
|
28
28
|
import { PreviousOrders } from './src/components/PreviousOrders';
|
|
29
29
|
import { ProductItemAccordion } from './src/components/ProductItemAccordion';
|
|
30
|
+
import { ReviewCustomer } from './src/components/ReviewCustomer'
|
|
30
31
|
import { SearchBar } from './src/components/SearchBar';
|
|
31
32
|
import { SignupForm } from './src/components/SignupForm';
|
|
32
33
|
import { StoresList } from './src/components/StoresList';
|
|
@@ -91,6 +92,7 @@ export {
|
|
|
91
92
|
PreviousMessages,
|
|
92
93
|
PreviousOrders,
|
|
93
94
|
ProductItemAccordion,
|
|
95
|
+
ReviewCustomer,
|
|
94
96
|
SafeAreaContainerLayout,
|
|
95
97
|
SearchBar,
|
|
96
98
|
SignupForm,
|
|
@@ -25,9 +25,7 @@ export const AcceptOrRejectOrder = (props: AcceptOrRejectOrderParams) => {
|
|
|
25
25
|
closeModal,
|
|
26
26
|
orderId,
|
|
27
27
|
notShowCustomerPhone,
|
|
28
|
-
|
|
29
|
-
titleReject,
|
|
30
|
-
titleNotReady,
|
|
28
|
+
orderTitle,
|
|
31
29
|
appTitle,
|
|
32
30
|
} = props;
|
|
33
31
|
|
|
@@ -45,7 +43,9 @@ export const AcceptOrRejectOrder = (props: AcceptOrRejectOrderParams) => {
|
|
|
45
43
|
const phoneNumber = customerCellphone;
|
|
46
44
|
let codeNumberPhone, numberPhone, numberToShow;
|
|
47
45
|
const { top, bottom } = useSafeAreaInsets()
|
|
48
|
-
|
|
46
|
+
const titleOrder = t(orderTitle[action].key, orderTitle[action].text)
|
|
47
|
+
const buttonText = t(orderTitle[action].btnKey, orderTitle[action].btnText)
|
|
48
|
+
const showTextArea = ['reject', 'deliveryFailed', 'pickupFailed', 'notReady'].includes(action)
|
|
49
49
|
const handleFocus = () => {
|
|
50
50
|
viewRef?.current?.measure((x: any, y: any) => {
|
|
51
51
|
scrollViewRef?.current?.scrollTo({ x: 0, y });
|
|
@@ -112,7 +112,7 @@ export const AcceptOrRejectOrder = (props: AcceptOrRejectOrderParams) => {
|
|
|
112
112
|
openTimerIOnput();
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
if (actions &&
|
|
115
|
+
if (actions && showTextArea) {
|
|
116
116
|
openTextTareaOInput();
|
|
117
117
|
}
|
|
118
118
|
}, []);
|
|
@@ -179,7 +179,11 @@ export const AcceptOrRejectOrder = (props: AcceptOrRejectOrderParams) => {
|
|
|
179
179
|
comment: comments,
|
|
180
180
|
status: 6,
|
|
181
181
|
},
|
|
182
|
-
|
|
182
|
+
pickupFailedByDriver: {
|
|
183
|
+
comment: comments,
|
|
184
|
+
status: 10
|
|
185
|
+
},
|
|
186
|
+
deliveryFailedByDriver: {
|
|
183
187
|
comment: comments,
|
|
184
188
|
status: 12
|
|
185
189
|
},
|
|
@@ -195,8 +199,11 @@ export const AcceptOrRejectOrder = (props: AcceptOrRejectOrderParams) => {
|
|
|
195
199
|
if (actions && action === 'reject') {
|
|
196
200
|
bodyToSend = orderStatus[actions.reject];
|
|
197
201
|
}
|
|
198
|
-
if (actions && action === '
|
|
199
|
-
bodyToSend = orderStatus[actions.
|
|
202
|
+
if (actions && action === 'pickupFailed') {
|
|
203
|
+
bodyToSend = orderStatus[actions.pickupFailed]
|
|
204
|
+
}
|
|
205
|
+
if (actions && action === 'deliveryFailed') {
|
|
206
|
+
bodyToSend = orderStatus[actions.deliveryFailed]
|
|
200
207
|
}
|
|
201
208
|
if (actions && action === 'notReady') {
|
|
202
209
|
bodyToSend = orderStatus[actions.notReady]
|
|
@@ -233,11 +240,7 @@ export const AcceptOrRejectOrder = (props: AcceptOrRejectOrderParams) => {
|
|
|
233
240
|
fontStyle: 'normal',
|
|
234
241
|
}}
|
|
235
242
|
weight="600">
|
|
236
|
-
{
|
|
237
|
-
? `${t(titleAccept?.key, titleAccept?.text)}:`
|
|
238
|
-
: action === 'notReady'
|
|
239
|
-
? t(titleNotReady?.key, titleNotReady?.text)
|
|
240
|
-
: t(titleReject?.key, titleReject?.text)}
|
|
243
|
+
{titleOrder}
|
|
241
244
|
</OText>
|
|
242
245
|
</View>
|
|
243
246
|
<Content showsVerticalScrollIndicator={false} ref={scrollViewRef}>
|
|
@@ -362,11 +365,11 @@ export const AcceptOrRejectOrder = (props: AcceptOrRejectOrderParams) => {
|
|
|
362
365
|
onEndEditing={handleFixTime}
|
|
363
366
|
/>
|
|
364
367
|
|
|
365
|
-
{
|
|
368
|
+
{showTextArea && (
|
|
366
369
|
<Comments ref={viewRef}>
|
|
367
370
|
<OTextarea
|
|
368
371
|
textTareaRef={textTareaRef}
|
|
369
|
-
autoFocus
|
|
372
|
+
autoFocus
|
|
370
373
|
onFocus={handleFocus}
|
|
371
374
|
placeholder={t(
|
|
372
375
|
'PLEASE_TYPE_YOUR_COMMENTS_IN_HERE',
|
|
@@ -385,13 +388,7 @@ export const AcceptOrRejectOrder = (props: AcceptOrRejectOrderParams) => {
|
|
|
385
388
|
firstButtonClick={() => {
|
|
386
389
|
handleAcceptOrReject();
|
|
387
390
|
}}
|
|
388
|
-
btnText={
|
|
389
|
-
action === 'accept'
|
|
390
|
-
? t('ACCEPT', 'Accept')
|
|
391
|
-
: action === 'notReady'
|
|
392
|
-
? t('ORDER_NOT_READY', 'Order not ready')
|
|
393
|
-
: t('REJECT', 'Reject')
|
|
394
|
-
}
|
|
391
|
+
btnText={buttonText}
|
|
395
392
|
color={action === 'accept' ? theme.colors.green : theme.colors.red}
|
|
396
393
|
widthButton={'100%'}
|
|
397
394
|
/>
|
|
@@ -48,9 +48,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
48
48
|
updateDriverPosition,
|
|
49
49
|
driverUpdateLocation,
|
|
50
50
|
setDriverUpdateLocation,
|
|
51
|
-
|
|
52
|
-
titleReject,
|
|
53
|
-
titleNotReady,
|
|
51
|
+
orderTitle,
|
|
54
52
|
appTitle,
|
|
55
53
|
} = props;
|
|
56
54
|
|
|
@@ -343,9 +341,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
343
341
|
orderId={order?.id}
|
|
344
342
|
notShowCustomerPhone
|
|
345
343
|
actions={actions}
|
|
346
|
-
|
|
347
|
-
titleReject={titleReject}
|
|
348
|
-
titleNotReady={titleNotReady}
|
|
344
|
+
orderTitle={orderTitle}
|
|
349
345
|
appTitle={appTitle}
|
|
350
346
|
/>
|
|
351
347
|
</OModal>
|
|
@@ -391,7 +387,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
391
387
|
handleChangeOrderStatus && handleChangeOrderStatus(9)
|
|
392
388
|
}
|
|
393
389
|
firstButtonClick={() =>
|
|
394
|
-
handleViewActionOrder && handleViewActionOrder('
|
|
390
|
+
handleViewActionOrder && handleViewActionOrder('pickupFailed')
|
|
395
391
|
}
|
|
396
392
|
secondBtnText={t('PICKUP_COMPLETE', 'Pickup complete')}
|
|
397
393
|
secondButton={true}
|
|
@@ -410,7 +406,7 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
410
406
|
handleChangeOrderStatus && handleChangeOrderStatus(11)
|
|
411
407
|
}
|
|
412
408
|
firstButtonClick={() =>
|
|
413
|
-
handleViewActionOrder && handleViewActionOrder('
|
|
409
|
+
handleViewActionOrder && handleViewActionOrder('deliveryFailed')
|
|
414
410
|
}
|
|
415
411
|
secondBtnText={t('DELIVERY_COMPLETE', 'Delivery complete')}
|
|
416
412
|
secondButton={true}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
2
|
|
|
3
3
|
import { Platform, StyleSheet, View } from 'react-native';
|
|
4
4
|
|
|
5
|
-
import { OText, OLink } from '../shared'
|
|
5
|
+
import { OButton, OText, OLink, OModal } from '../shared'
|
|
6
6
|
import {
|
|
7
7
|
OrderContent,
|
|
8
8
|
OrderBusiness,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
useConfig,
|
|
24
24
|
} from 'ordering-components/native';
|
|
25
25
|
import { useTheme } from 'styled-components/native';
|
|
26
|
-
|
|
26
|
+
import { ReviewCustomer } from '../ReviewCustomer'
|
|
27
27
|
|
|
28
28
|
interface OrderContent {
|
|
29
29
|
order: any
|
|
@@ -37,6 +37,10 @@ export const OrderContentComponent = (props: OrderContent) => {
|
|
|
37
37
|
|
|
38
38
|
const [{ parsePrice, parseNumber }] = useUtils();
|
|
39
39
|
const [{ configs }] = useConfig();
|
|
40
|
+
const [openReviewModal, setOpenReviewModal] = useState(false)
|
|
41
|
+
const [isCustomerReviewed, setIsCustomerReviewed] = useState(false)
|
|
42
|
+
|
|
43
|
+
const pastOrderStatuses = [1, 2, 5, 6, 10, 11, 12, 16, 17]
|
|
40
44
|
|
|
41
45
|
const styles = StyleSheet.create({
|
|
42
46
|
linkWithIcons: {
|
|
@@ -51,8 +55,18 @@ export const OrderContentComponent = (props: OrderContent) => {
|
|
|
51
55
|
},
|
|
52
56
|
textLink: {
|
|
53
57
|
color: '#365CC7'
|
|
58
|
+
},
|
|
59
|
+
btnReview: {
|
|
60
|
+
borderWidth: 0,
|
|
61
|
+
backgroundColor: theme.colors.primary,
|
|
62
|
+
borderRadius: 8,
|
|
54
63
|
}
|
|
55
64
|
})
|
|
65
|
+
|
|
66
|
+
const handleSuccessReviewed = () => {
|
|
67
|
+
setOpenReviewModal(false)
|
|
68
|
+
setIsCustomerReviewed(true)
|
|
69
|
+
}
|
|
56
70
|
return (
|
|
57
71
|
<OrderContent>
|
|
58
72
|
<OrderBusiness>
|
|
@@ -232,6 +246,16 @@ export const OrderContentComponent = (props: OrderContent) => {
|
|
|
232
246
|
{order?.customer?.zipcode}
|
|
233
247
|
</OText>
|
|
234
248
|
)}
|
|
249
|
+
|
|
250
|
+
{!order?.user_review && pastOrderStatuses.includes(order?.status) && !isCustomerReviewed && (
|
|
251
|
+
<OButton
|
|
252
|
+
style={styles.btnReview}
|
|
253
|
+
textStyle={{ color: theme.colors.white }}
|
|
254
|
+
text={t('REVIEW_CUSTOMER', 'Review customer')}
|
|
255
|
+
imgRightSrc={false}
|
|
256
|
+
onClick={() => setOpenReviewModal(true)}
|
|
257
|
+
/>
|
|
258
|
+
)}
|
|
235
259
|
</OrderCustomer>
|
|
236
260
|
|
|
237
261
|
<OrderProducts>
|
|
@@ -386,6 +410,19 @@ export const OrderContentComponent = (props: OrderContent) => {
|
|
|
386
410
|
</Table>
|
|
387
411
|
</Total>
|
|
388
412
|
</OrderBill>
|
|
413
|
+
|
|
414
|
+
<OModal
|
|
415
|
+
open={openReviewModal}
|
|
416
|
+
onClose={() => setOpenReviewModal(false)}
|
|
417
|
+
entireModal
|
|
418
|
+
customClose
|
|
419
|
+
>
|
|
420
|
+
<ReviewCustomer
|
|
421
|
+
order={order}
|
|
422
|
+
closeModal={() => setOpenReviewModal(false)}
|
|
423
|
+
onClose={() => handleSuccessReviewed()}
|
|
424
|
+
/>
|
|
425
|
+
</OModal>
|
|
389
426
|
</OrderContent>
|
|
390
427
|
)
|
|
391
428
|
}
|
|
@@ -42,10 +42,11 @@ export const OrdersOptionDate = (props: any) => {
|
|
|
42
42
|
bgcolor={theme.colors.inputDisabled}
|
|
43
43
|
textcolor={theme.colors.unselectText}
|
|
44
44
|
placeholder={t('SELECT_DATE', 'Select Date')}
|
|
45
|
-
dropViewMaxHeight={
|
|
45
|
+
dropViewMaxHeight={220}
|
|
46
46
|
isCalendar
|
|
47
47
|
rangeDate={search.date}
|
|
48
48
|
handleChangeDate={handleChangeDate}
|
|
49
|
+
isCalendarAlwaysVisible
|
|
49
50
|
/>
|
|
50
51
|
</Container>
|
|
51
52
|
);
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
useLanguage,
|
|
4
|
+
useUtils,
|
|
5
|
+
ReviewCustomer as ReviewCustomerController
|
|
6
|
+
} from 'ordering-components/native'
|
|
7
|
+
import {
|
|
8
|
+
KeyboardAvoidingView,
|
|
9
|
+
Platform,
|
|
10
|
+
View,
|
|
11
|
+
StyleSheet,
|
|
12
|
+
I18nManager,
|
|
13
|
+
TouchableOpacity
|
|
14
|
+
} from 'react-native'
|
|
15
|
+
import { useTheme } from 'styled-components/native'
|
|
16
|
+
import { ReviewCustomerParams } from '../../types'
|
|
17
|
+
import { OButton, OText, OIconButton, OIcon, OInput } from '../shared'
|
|
18
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
19
|
+
import { FloatingButton } from '../FloatingButton'
|
|
20
|
+
import LinearGradient from 'react-native-linear-gradient'
|
|
21
|
+
import Alert from '../../providers/AlertProvider'
|
|
22
|
+
|
|
23
|
+
import {
|
|
24
|
+
Content,
|
|
25
|
+
ActionButtonWrapper,
|
|
26
|
+
CustomerInfoContainer,
|
|
27
|
+
RatingBarContainer,
|
|
28
|
+
RatingTextContainer,
|
|
29
|
+
CommentsButtonGroup
|
|
30
|
+
} from './styles'
|
|
31
|
+
|
|
32
|
+
const ReviewCustomerUI = (props: ReviewCustomerParams) => {
|
|
33
|
+
const {
|
|
34
|
+
order,
|
|
35
|
+
closeModal,
|
|
36
|
+
reviewState,
|
|
37
|
+
setReviewState,
|
|
38
|
+
actionState,
|
|
39
|
+
handleChangeQualification,
|
|
40
|
+
handleSendCustomerReview
|
|
41
|
+
} = props
|
|
42
|
+
|
|
43
|
+
const theme = useTheme()
|
|
44
|
+
const [, t] = useLanguage()
|
|
45
|
+
const [{ optimizeImage }] = useUtils()
|
|
46
|
+
const [alertState, setAlertState] = useState<{
|
|
47
|
+
open: boolean;
|
|
48
|
+
content: Array<string>;
|
|
49
|
+
key?: string | null;
|
|
50
|
+
}>({ open: false, content: [] })
|
|
51
|
+
const { top, bottom } = useSafeAreaInsets()
|
|
52
|
+
const [comments, setComments] = useState<Array<any>>([])
|
|
53
|
+
const [extraComment, setExtraComment] = useState('')
|
|
54
|
+
|
|
55
|
+
const styles = StyleSheet.create({
|
|
56
|
+
photoWrapper: {
|
|
57
|
+
shadowColor: theme.colors.black,
|
|
58
|
+
shadowRadius: 3,
|
|
59
|
+
shadowOffset: {width: 1, height: 4},
|
|
60
|
+
elevation: 3,
|
|
61
|
+
borderRadius: 8,
|
|
62
|
+
shadowOpacity: 0.1,
|
|
63
|
+
overflow: 'hidden'
|
|
64
|
+
},
|
|
65
|
+
statusBar: {
|
|
66
|
+
transform: [{ scaleX: I18nManager.isRTL ? -1 : 1 }],
|
|
67
|
+
height: 8,
|
|
68
|
+
borderRadius: 5,
|
|
69
|
+
marginTop: 5
|
|
70
|
+
},
|
|
71
|
+
ratingItemContainer: {
|
|
72
|
+
position: 'absolute',
|
|
73
|
+
top: -18
|
|
74
|
+
},
|
|
75
|
+
ratingItem: {
|
|
76
|
+
left: '-50%',
|
|
77
|
+
flexDirection: 'column',
|
|
78
|
+
alignItems: 'center'
|
|
79
|
+
},
|
|
80
|
+
ratingLineStyle: {
|
|
81
|
+
height: 8,
|
|
82
|
+
width: 1,
|
|
83
|
+
marginBottom: 10,
|
|
84
|
+
backgroundColor: theme.colors.lightGray
|
|
85
|
+
},
|
|
86
|
+
inputTextArea: {
|
|
87
|
+
borderColor: theme.colors.lightGray,
|
|
88
|
+
borderRadius: 8,
|
|
89
|
+
marginTop: 10,
|
|
90
|
+
marginBottom: 40,
|
|
91
|
+
height: 100,
|
|
92
|
+
alignItems: 'flex-start'
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
const qualificationList = [
|
|
97
|
+
{ key: 1, text: t('TERRIBLE', 'Terrible'), percent: 0, parentStyle: { left: '0%' }, isInnerStyle: false, pointerColor: false },
|
|
98
|
+
{ key: 2, text: t('BAD', 'Bad'), percent: 0.25, parentStyle: { left: '25%' }, isInnerStyle: true, pointerColor: true },
|
|
99
|
+
{ key: 3, text: t('OKAY', 'Okay'), percent: 0.5, parentStyle: { left: '50%' }, isInnerStyle: true, pointerColor: true },
|
|
100
|
+
{ key: 4, text: t('GOOD', 'Good'), percent: 0.75, parentStyle: { left: '75%' }, isInnerStyle: true, pointerColor: true },
|
|
101
|
+
{ key: 5, text: t('GREAT', 'Great'), percent: 1, parentStyle: { right: '0%' }, isInnerStyle: false, pointerColor: false }
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
const commentsList = [
|
|
105
|
+
{ key: 0, content: t('RESPECTFUL', 'Respectful') },
|
|
106
|
+
{ key: 1, content: t('EXCELLENT_COMMUNICATION', "Excellent communication") },
|
|
107
|
+
{ key: 2, content: t('CORDIAL_SERVICE', 'Cordial service') }
|
|
108
|
+
]
|
|
109
|
+
const isSelectedComment = (commentKey: number) => {
|
|
110
|
+
const found = comments.find((comment: any) => comment?.key === commentKey)
|
|
111
|
+
return found
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const handleChangeComment = (commentItem: any) => {
|
|
115
|
+
const found = comments.find((comment: any) => comment?.key === commentItem.key)
|
|
116
|
+
if (found) {
|
|
117
|
+
const _comments = comments.filter((comment: any) => comment?.key !== commentItem.key)
|
|
118
|
+
setComments(_comments)
|
|
119
|
+
} else {
|
|
120
|
+
setComments([...comments, commentItem])
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
let _comments = ''
|
|
126
|
+
if (comments.length > 0) {
|
|
127
|
+
comments.map((comment: any) => (_comments += comment.content + '. '))
|
|
128
|
+
}
|
|
129
|
+
const _comment = _comments + extraComment
|
|
130
|
+
setReviewState({ ...reviewState, comment: _comment })
|
|
131
|
+
}, [comments, extraComment])
|
|
132
|
+
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
if (!actionState.error) return
|
|
135
|
+
setAlertState({
|
|
136
|
+
open: true,
|
|
137
|
+
content: actionState.error
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
}, [actionState.error])
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<KeyboardAvoidingView
|
|
144
|
+
enabled
|
|
145
|
+
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
|
146
|
+
style={{
|
|
147
|
+
flex: 1,
|
|
148
|
+
paddingHorizontal: 30,
|
|
149
|
+
paddingTop: 28,
|
|
150
|
+
marginTop: top,
|
|
151
|
+
marginBottom: bottom,
|
|
152
|
+
justifyContent: 'space-between'
|
|
153
|
+
}}
|
|
154
|
+
>
|
|
155
|
+
<View>
|
|
156
|
+
<OIconButton
|
|
157
|
+
icon={theme.images.general.arrow_left}
|
|
158
|
+
borderColor={theme.colors.clear}
|
|
159
|
+
iconStyle={{ width: 20, height: 16 }}
|
|
160
|
+
style={{
|
|
161
|
+
maxWidth: 40,
|
|
162
|
+
height: 20,
|
|
163
|
+
justifyContent: 'flex-end',
|
|
164
|
+
marginBottom: 20,
|
|
165
|
+
}}
|
|
166
|
+
onClick={() => closeModal()}
|
|
167
|
+
/>
|
|
168
|
+
<OText
|
|
169
|
+
size={20}
|
|
170
|
+
weight="600"
|
|
171
|
+
>
|
|
172
|
+
{t('REVIEW_CUSTOMER', 'Review customer')}
|
|
173
|
+
</OText>
|
|
174
|
+
</View>
|
|
175
|
+
|
|
176
|
+
<Content
|
|
177
|
+
showsVerticalScrollIndicator={false}
|
|
178
|
+
contentContainerStyle={{ paddingBottom: 30 }}
|
|
179
|
+
>
|
|
180
|
+
<CustomerInfoContainer>
|
|
181
|
+
<View
|
|
182
|
+
style={{
|
|
183
|
+
...styles.photoWrapper,
|
|
184
|
+
backgroundColor: theme.colors.white,
|
|
185
|
+
padding: !order?.customer?.photo ? 5 : 0
|
|
186
|
+
}}
|
|
187
|
+
>
|
|
188
|
+
<OIcon
|
|
189
|
+
url={optimizeImage(order?.customer?.photo, 'h_100,c_limit')}
|
|
190
|
+
src={!order?.customer?.photo && theme.images.general.user}
|
|
191
|
+
width={72}
|
|
192
|
+
height={72}
|
|
193
|
+
style={{ borderRadius: 7.6 }}
|
|
194
|
+
/>
|
|
195
|
+
</View>
|
|
196
|
+
<OText
|
|
197
|
+
size={14}
|
|
198
|
+
weight="500"
|
|
199
|
+
style={{
|
|
200
|
+
marginTop: 16
|
|
201
|
+
}}
|
|
202
|
+
>
|
|
203
|
+
{order?.customer?.name} {order?.customer?.middle_name} {order?.customer?.lastname} {order?.customer?.second_lastname}
|
|
204
|
+
</OText>
|
|
205
|
+
</CustomerInfoContainer>
|
|
206
|
+
<OText
|
|
207
|
+
size={12}
|
|
208
|
+
>
|
|
209
|
+
{t('HOW_WAS_YOUR_CUSTOMER', 'How was your experience with _name_?').replace('_name_', `${order?.customer?.name} ${order?.customer?.middle_name} ${order?.customer?.lastname} ${order?.customer?.second_lastname}`)}
|
|
210
|
+
</OText>
|
|
211
|
+
<RatingBarContainer>
|
|
212
|
+
<LinearGradient
|
|
213
|
+
start={{ x: 0.0, y: 0.0 }}
|
|
214
|
+
end={{ x: qualificationList[reviewState?.qualification - 1]?.percent || 0, y: 0 }}
|
|
215
|
+
locations={[.9999, .9999]}
|
|
216
|
+
colors={[theme.colors.primary, theme.colors.tabBar]}
|
|
217
|
+
style={styles.statusBar}
|
|
218
|
+
/>
|
|
219
|
+
<RatingTextContainer>
|
|
220
|
+
{qualificationList.map((qualification: any) => (
|
|
221
|
+
<View
|
|
222
|
+
key={qualification.key}
|
|
223
|
+
style={{ ...qualification.parentStyle, ...styles.ratingItemContainer }}
|
|
224
|
+
>
|
|
225
|
+
<TouchableOpacity
|
|
226
|
+
style={qualification.isInnerStyle && styles.ratingItem}
|
|
227
|
+
onPress={() => handleChangeQualification(qualification.key)}
|
|
228
|
+
>
|
|
229
|
+
<View
|
|
230
|
+
style={{
|
|
231
|
+
...styles.ratingLineStyle,
|
|
232
|
+
backgroundColor: (qualification.pointerColor && !(reviewState?.qualification >= qualification.key)) ? theme.colors.dusk : 'transparent'
|
|
233
|
+
}}
|
|
234
|
+
/>
|
|
235
|
+
<OText
|
|
236
|
+
size={12}
|
|
237
|
+
color={
|
|
238
|
+
reviewState?.qualification === qualification.key
|
|
239
|
+
? theme.colors.darkText
|
|
240
|
+
: theme.colors.lightGray
|
|
241
|
+
}
|
|
242
|
+
>
|
|
243
|
+
{qualification.text}
|
|
244
|
+
</OText>
|
|
245
|
+
</TouchableOpacity>
|
|
246
|
+
</View>
|
|
247
|
+
))}
|
|
248
|
+
</RatingTextContainer>
|
|
249
|
+
</RatingBarContainer>
|
|
250
|
+
<OText
|
|
251
|
+
size={12}
|
|
252
|
+
style={{ marginTop: 30 }}
|
|
253
|
+
>
|
|
254
|
+
{t('COMMENTS', 'Comments')}
|
|
255
|
+
</OText>
|
|
256
|
+
<CommentsButtonGroup>
|
|
257
|
+
{commentsList.map(commentItem => (
|
|
258
|
+
<OButton
|
|
259
|
+
key={commentItem.key}
|
|
260
|
+
text={commentItem.content}
|
|
261
|
+
bgColor={isSelectedComment(commentItem.key) ? theme.colors.primary : theme.colors.tabBar}
|
|
262
|
+
borderColor={isSelectedComment(commentItem.key) ? theme.colors.primary : theme.colors.tabBar}
|
|
263
|
+
textStyle={{
|
|
264
|
+
color: isSelectedComment(commentItem.key) ? theme.colors.white : theme.colors.darkText,
|
|
265
|
+
fontSize: 12,
|
|
266
|
+
paddingRight: isSelectedComment(commentItem.key) ? 15 : 0
|
|
267
|
+
}}
|
|
268
|
+
style={{ height: 35, paddingLeft: 5, paddingRight: 5, marginHorizontal: 3, marginVertical: 10 }}
|
|
269
|
+
imgRightSrc={isSelectedComment(commentItem.key) ? theme.images.general.close : null}
|
|
270
|
+
imgRightStyle={{ tintColor: theme.colors.white, right: 5, margin: 5 }}
|
|
271
|
+
onClick={() => handleChangeComment(commentItem) }
|
|
272
|
+
/>
|
|
273
|
+
))}
|
|
274
|
+
</CommentsButtonGroup>
|
|
275
|
+
<OText
|
|
276
|
+
size={12}
|
|
277
|
+
style={{ marginTop: 30 }}
|
|
278
|
+
>
|
|
279
|
+
{t('REVIEW_COMMENT_QUESTION', 'Do you want to add something?')}
|
|
280
|
+
</OText>
|
|
281
|
+
<OInput
|
|
282
|
+
name='comments'
|
|
283
|
+
onChange={(val: any) => setExtraComment(val.target.value)}
|
|
284
|
+
style={styles.inputTextArea}
|
|
285
|
+
multiline
|
|
286
|
+
/>
|
|
287
|
+
</Content>
|
|
288
|
+
|
|
289
|
+
<ActionButtonWrapper>
|
|
290
|
+
<FloatingButton
|
|
291
|
+
firstButtonClick={() => handleSendCustomerReview()}
|
|
292
|
+
btnText={actionState.loading ? t('LOADING', 'Loading') : t('SEND_REVIEW', 'Send Review')}
|
|
293
|
+
color={theme.colors.primary}
|
|
294
|
+
widthButton={'100%'}
|
|
295
|
+
/>
|
|
296
|
+
</ActionButtonWrapper>
|
|
297
|
+
<Alert
|
|
298
|
+
open={alertState.open}
|
|
299
|
+
onAccept={() => setAlertState({ open: false, content: [] })}
|
|
300
|
+
onClose={() => setAlertState({ open: false, content: [] })}
|
|
301
|
+
content={alertState.content}
|
|
302
|
+
title={t('ERROR', 'Error')}
|
|
303
|
+
/>
|
|
304
|
+
</KeyboardAvoidingView>
|
|
305
|
+
)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export const ReviewCustomer = (props: any) => {
|
|
309
|
+
const reviewCustomerProps = {
|
|
310
|
+
...props,
|
|
311
|
+
UIComponent: ReviewCustomerUI
|
|
312
|
+
}
|
|
313
|
+
return <ReviewCustomerController {...reviewCustomerProps} />
|
|
314
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import styled from 'styled-components/native'
|
|
2
|
+
|
|
3
|
+
export const Content = styled.ScrollView`
|
|
4
|
+
background-color: ${(props: any) => props.theme.colors.white};
|
|
5
|
+
margin-bottom: 30px;
|
|
6
|
+
`;
|
|
7
|
+
export const ActionButtonWrapper = styled.View`
|
|
8
|
+
margin-bottom: 10px;
|
|
9
|
+
`
|
|
10
|
+
export const CustomerInfoContainer = styled.View`
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
align-items: center;
|
|
13
|
+
margin: 25px 0;
|
|
14
|
+
`
|
|
15
|
+
export const RatingBarContainer = styled.View`
|
|
16
|
+
margin-top: 13px;
|
|
17
|
+
margin-bottom: 25px;
|
|
18
|
+
`
|
|
19
|
+
export const RatingTextContainer = styled.View`
|
|
20
|
+
flex-direction: row;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: space-between;
|
|
23
|
+
margin-top: 10px;
|
|
24
|
+
`
|
|
25
|
+
export const CommentsButtonGroup = styled.View`
|
|
26
|
+
flex-direction: row;
|
|
27
|
+
flex-wrap: wrap;
|
|
28
|
+
`
|
|
@@ -22,7 +22,8 @@ interface Props {
|
|
|
22
22
|
textcolor?: string,
|
|
23
23
|
isCalendar?: boolean,
|
|
24
24
|
handleChangeDate?: any,
|
|
25
|
-
rangeDate?: any
|
|
25
|
+
rangeDate?: any,
|
|
26
|
+
isCalendarAlwaysVisible?: boolean
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
const Wrapper = styled.View`
|
|
@@ -94,7 +95,8 @@ const ODropDownCalendar = (props: Props) => {
|
|
|
94
95
|
isModal,
|
|
95
96
|
isCalendar,
|
|
96
97
|
handleChangeDate,
|
|
97
|
-
rangeDate
|
|
98
|
+
rangeDate,
|
|
99
|
+
isCalendarAlwaysVisible
|
|
98
100
|
} = props
|
|
99
101
|
|
|
100
102
|
const theme = useTheme();
|
|
@@ -127,13 +129,13 @@ const ODropDownCalendar = (props: Props) => {
|
|
|
127
129
|
}
|
|
128
130
|
|
|
129
131
|
const customDayHeaderStylesCallback = () => {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
132
|
+
return {
|
|
133
|
+
textStyle: {
|
|
134
|
+
color: theme.colors.unselectText,
|
|
135
|
+
fontSize: 12,
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
};
|
|
137
139
|
|
|
138
140
|
const calendarText = (from: any, to: any, placeholder: any) => {
|
|
139
141
|
const end = ` ~ ${to}`
|
|
@@ -204,9 +206,9 @@ const ODropDownCalendar = (props: Props) => {
|
|
|
204
206
|
</ScrollView>
|
|
205
207
|
) : (
|
|
206
208
|
<CustomScrollView style={{
|
|
207
|
-
maxHeight: dropViewMaxHeight || null
|
|
209
|
+
maxHeight: dropViewMaxHeight || null,
|
|
208
210
|
}}
|
|
209
|
-
|
|
211
|
+
nestedScrollEnabled={true}
|
|
210
212
|
>
|
|
211
213
|
{options.map((option: any, index: number) => (
|
|
212
214
|
<CustomTouchableOpacity
|
|
@@ -243,8 +245,8 @@ const ODropDownCalendar = (props: Props) => {
|
|
|
243
245
|
alignItems: 'center',
|
|
244
246
|
marginTop: 10
|
|
245
247
|
}}>
|
|
246
|
-
<View style={{marginRight: 10, flex: 1, marginBottom: 15}}>
|
|
247
|
-
<Text style={{marginBottom: 5}}>{t('FROM', 'From')}</Text>
|
|
248
|
+
<View style={{ marginRight: 10, flex: 1, marginBottom: 15 }}>
|
|
249
|
+
<Text style={{ marginBottom: 5 }}>{t('FROM', 'From')}</Text>
|
|
248
250
|
<DateInput
|
|
249
251
|
value={rangeDate.from}
|
|
250
252
|
placeholder={t('FROM', 'From')}
|
|
@@ -259,12 +261,12 @@ const ODropDownCalendar = (props: Props) => {
|
|
|
259
261
|
name='close'
|
|
260
262
|
color={theme.colors.disabled}
|
|
261
263
|
size={20}
|
|
262
|
-
style={{position: 'absolute', bottom: 13, right: 10}}
|
|
264
|
+
style={{ position: 'absolute', bottom: 13, right: 10 }}
|
|
263
265
|
onPress={() => handleChangeDate('', rangeDate.to)}
|
|
264
266
|
/>
|
|
265
267
|
</View>
|
|
266
|
-
<View style={{marginLeft: 10, flex: 1, marginBottom: 15}}>
|
|
267
|
-
<Text style={{marginBottom: 5}}>{t('TO', 'To')}</Text>
|
|
268
|
+
<View style={{ marginLeft: 10, flex: 1, marginBottom: 15 }}>
|
|
269
|
+
<Text style={{ marginBottom: 5 }}>{t('TO', 'To')}</Text>
|
|
268
270
|
<DateInput
|
|
269
271
|
value={rangeDate.to}
|
|
270
272
|
placeholder={t('TO', 'To')}
|
|
@@ -279,13 +281,13 @@ const ODropDownCalendar = (props: Props) => {
|
|
|
279
281
|
name='close'
|
|
280
282
|
color={theme.colors.disabled}
|
|
281
283
|
size={20}
|
|
282
|
-
style={{position: 'absolute', bottom: 13, right: 10}}
|
|
284
|
+
style={{ position: 'absolute', bottom: 13, right: 10 }}
|
|
283
285
|
onPress={() => handleChangeDate(rangeDate.from, '')}
|
|
284
286
|
/>
|
|
285
287
|
</View>
|
|
286
288
|
</View>
|
|
287
289
|
{
|
|
288
|
-
defaultValue === 'calendar' && (
|
|
290
|
+
(defaultValue === 'calendar' || isCalendarAlwaysVisible) && (
|
|
289
291
|
<CalendarPicker
|
|
290
292
|
previousComponent={
|
|
291
293
|
<FeatherIcon
|
|
@@ -365,6 +365,7 @@ export interface OrderDetailsParams {
|
|
|
365
365
|
updateDriverPosition?: any;
|
|
366
366
|
driverUpdateLocation?: any;
|
|
367
367
|
setDriverUpdateLocation?: any;
|
|
368
|
+
orderTitle?: any
|
|
368
369
|
}
|
|
369
370
|
export interface ProductItemAccordionParams {
|
|
370
371
|
isCartPending?: boolean;
|
|
@@ -520,7 +521,8 @@ export interface TagsParams {
|
|
|
520
521
|
interface actions {
|
|
521
522
|
accept: string;
|
|
522
523
|
reject: string;
|
|
523
|
-
|
|
524
|
+
pickupFailed: string;
|
|
525
|
+
deliveryFailed: string;
|
|
524
526
|
notReady: string;
|
|
525
527
|
}
|
|
526
528
|
|
|
@@ -542,6 +544,7 @@ export interface AcceptOrRejectOrderParams {
|
|
|
542
544
|
titleReject?: textTranslate;
|
|
543
545
|
titleNotReady?: textTranslate;
|
|
544
546
|
appTitle?: textTranslate;
|
|
547
|
+
orderTitle?: any
|
|
545
548
|
}
|
|
546
549
|
|
|
547
550
|
export interface MapViewParams {
|
|
@@ -553,3 +556,13 @@ export interface MapViewParams {
|
|
|
553
556
|
alertState: { open: boolean, content: Array<string>, key?: string | null },
|
|
554
557
|
setAlertState: ({open, content, key} : { open: boolean, content: Array<string>, key?: string | null }) => void
|
|
555
558
|
}
|
|
559
|
+
|
|
560
|
+
export interface ReviewCustomerParams {
|
|
561
|
+
order?: any,
|
|
562
|
+
closeModal?: any,
|
|
563
|
+
reviewState?: any,
|
|
564
|
+
setReviewState?: any,
|
|
565
|
+
actionState?: any,
|
|
566
|
+
handleChangeQualification?: any,
|
|
567
|
+
handleSendCustomerReview?: any,
|
|
568
|
+
}
|
|
@@ -45,6 +45,8 @@ import { OrderDetails } from './src/components/OrderDetails';
|
|
|
45
45
|
import { OrdersOption } from './src/components/OrdersOption';
|
|
46
46
|
import { OrderSummary } from './src/components/OrderSummary';
|
|
47
47
|
import { OrderTypeSelector } from './src/components/OrderTypeSelector';
|
|
48
|
+
import { OrdersListing } from './src/components/OrdersListing';
|
|
49
|
+
import { OrderListOption } from './src/components/OrderListOption';
|
|
48
50
|
import { PaymentOptionCash } from './src/components/PaymentOptionCash';
|
|
49
51
|
import { PaymentOptions } from './src/components/PaymentOptions';
|
|
50
52
|
import { PaymentOptionStripe } from './src/components/PaymentOptionStripe';
|
|
@@ -125,6 +127,8 @@ export {
|
|
|
125
127
|
HelpOrder,
|
|
126
128
|
HelpAccountAndPayment,
|
|
127
129
|
OrderTypeSelector,
|
|
130
|
+
OrdersListing,
|
|
131
|
+
OrderListOption,
|
|
128
132
|
Notifications,
|
|
129
133
|
BottomWrapper,
|
|
130
134
|
BusinessBasicInformation,
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { StyleSheet, TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import { useLanguage, useUtils } from 'ordering-components/native';
|
|
4
|
+
import {
|
|
5
|
+
OrdersContainer,
|
|
6
|
+
Card,
|
|
7
|
+
Information,
|
|
8
|
+
OrderInformation,
|
|
9
|
+
BusinessInformation,
|
|
10
|
+
Price,
|
|
11
|
+
OptionTitle,
|
|
12
|
+
Status,
|
|
13
|
+
} from './styles';
|
|
14
|
+
|
|
15
|
+
import { useTheme } from 'styled-components/native';
|
|
16
|
+
import { getTextOrderStatus } from '../../utils';
|
|
17
|
+
import { OButton, OText } from '../shared'
|
|
18
|
+
|
|
19
|
+
export const OrderListOption = (props: any) => {
|
|
20
|
+
const {
|
|
21
|
+
orders,
|
|
22
|
+
titleContent,
|
|
23
|
+
typeStyle,
|
|
24
|
+
allowedOrderStatus,
|
|
25
|
+
isLoadingReorder,
|
|
26
|
+
handleReorder,
|
|
27
|
+
onNavigationRedirect,
|
|
28
|
+
} = props;
|
|
29
|
+
|
|
30
|
+
const theme = useTheme();
|
|
31
|
+
const [, t] = useLanguage();
|
|
32
|
+
const [{ parseDate, parsePrice }] = useUtils();
|
|
33
|
+
|
|
34
|
+
const [reorderSelected, setReorderSelected] = useState<number | null>(null);
|
|
35
|
+
const [isReviewedOrders, setIsReviewedOrders] = useState<Array<any>>([])
|
|
36
|
+
|
|
37
|
+
const handleClickCard = (uuid: string) => {
|
|
38
|
+
onNavigationRedirect &&
|
|
39
|
+
onNavigationRedirect('OrderDetails', { orderId: uuid });
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const handleReviewState = (orderId: any) => {
|
|
43
|
+
if (!orderId || isReviewedOrders.includes(orderId)) return
|
|
44
|
+
setIsReviewedOrders([...isReviewedOrders, orderId])
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const handleClickOrderReview = (order: any) => {
|
|
48
|
+
onNavigationRedirect &&
|
|
49
|
+
onNavigationRedirect('ReviewOrder', {
|
|
50
|
+
order: {
|
|
51
|
+
id: order?.id,
|
|
52
|
+
business_id: order?.business_id,
|
|
53
|
+
logo: order.business?.logo,
|
|
54
|
+
driver: order?.driver,
|
|
55
|
+
products: order?.products,
|
|
56
|
+
review: order?.review,
|
|
57
|
+
user_review: order?.user_review
|
|
58
|
+
},
|
|
59
|
+
handleReviewState: handleReviewState
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const handleReorderClick = (id: number) => {
|
|
64
|
+
setReorderSelected(id);
|
|
65
|
+
handleReorder(id);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const styles = StyleSheet.create({
|
|
69
|
+
reorderbutton: {
|
|
70
|
+
height: 23,
|
|
71
|
+
paddingLeft: 10,
|
|
72
|
+
paddingRight: 10,
|
|
73
|
+
borderRadius: 23,
|
|
74
|
+
shadowOpacity: 0,
|
|
75
|
+
backgroundColor: theme.colors.primaryContrast,
|
|
76
|
+
borderWidth: 0,
|
|
77
|
+
width: 80
|
|
78
|
+
},
|
|
79
|
+
reorderLoading: {
|
|
80
|
+
width: 80,
|
|
81
|
+
height: 23,
|
|
82
|
+
borderRadius: 23,
|
|
83
|
+
paddingHorizontal: 10,
|
|
84
|
+
},
|
|
85
|
+
reviewButton: {
|
|
86
|
+
width: 80,
|
|
87
|
+
height: 23,
|
|
88
|
+
maxHeight: 23,
|
|
89
|
+
backgroundColor: theme.colors.white,
|
|
90
|
+
alignItems: 'center',
|
|
91
|
+
justifyContent: 'center',
|
|
92
|
+
paddingHorizontal: 10,
|
|
93
|
+
borderRadius: 23,
|
|
94
|
+
borderWidth: 1,
|
|
95
|
+
borderColor: theme.colors.primaryContrast,
|
|
96
|
+
},
|
|
97
|
+
buttonText: {
|
|
98
|
+
color: theme.colors.primary,
|
|
99
|
+
fontSize: 10,
|
|
100
|
+
marginLeft: 2,
|
|
101
|
+
marginRight: 2,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const OrderStyleOne = ({ order }: any) => (
|
|
106
|
+
<Card
|
|
107
|
+
activeOpacity={1}
|
|
108
|
+
onPress={() => handleClickCard(order?.uuid)}
|
|
109
|
+
>
|
|
110
|
+
<Information>
|
|
111
|
+
<OrderInformation>
|
|
112
|
+
<BusinessInformation>
|
|
113
|
+
<OText size={12} lineHeight={18} weight={600} numberOfLines={1} ellipsizeMode={'tail'}>
|
|
114
|
+
{`${t('ORDER_NO', 'Order No')}.${order.id}`}
|
|
115
|
+
</OText>
|
|
116
|
+
<OText size={10} lineHeight={21} color={theme.colors.textSecondary}>
|
|
117
|
+
{order?.delivery_datetime_utc
|
|
118
|
+
? parseDate(order?.delivery_datetime_utc)
|
|
119
|
+
: parseDate(order?.delivery_datetime, { utc: false })}
|
|
120
|
+
</OText>
|
|
121
|
+
<OText
|
|
122
|
+
color={theme.colors.primary}
|
|
123
|
+
size={10}
|
|
124
|
+
lineHeight={15}
|
|
125
|
+
weight={400}
|
|
126
|
+
numberOfLines={2}>
|
|
127
|
+
{getTextOrderStatus(order.status, t)?.value}
|
|
128
|
+
</OText>
|
|
129
|
+
</BusinessInformation>
|
|
130
|
+
<Price>
|
|
131
|
+
<OText size={12} lineHeight={18}>
|
|
132
|
+
{parsePrice(order?.summary?.total || order?.total)}
|
|
133
|
+
</OText>
|
|
134
|
+
</Price>
|
|
135
|
+
</OrderInformation>
|
|
136
|
+
</Information>
|
|
137
|
+
</Card>
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const OrderStyleTwo = ({ order }: any) => (
|
|
141
|
+
<TouchableOpacity
|
|
142
|
+
onPress={() => handleClickCard(order?.uuid)}
|
|
143
|
+
activeOpacity={1}
|
|
144
|
+
style={{ flexDirection: 'row' }}
|
|
145
|
+
>
|
|
146
|
+
<Card themetwo>
|
|
147
|
+
<Information themetwo>
|
|
148
|
+
<OText size={12} lineHeight={18} weight={'600'} numberOfLines={1} ellipsizeMode={'tail'}>
|
|
149
|
+
{`${t('ORDER_NO', 'Order No')}.${order.id}`}
|
|
150
|
+
</OText>
|
|
151
|
+
<OText
|
|
152
|
+
size={10}
|
|
153
|
+
lineHeight={21}
|
|
154
|
+
color={theme.colors.textSecondary}
|
|
155
|
+
style={{ marginVertical: 3 }}
|
|
156
|
+
numberOfLines={1}>
|
|
157
|
+
{order?.delivery_datetime_utc
|
|
158
|
+
? parseDate(order?.delivery_datetime_utc)
|
|
159
|
+
: parseDate(order?.delivery_datetime, { utc: false })}
|
|
160
|
+
</OText>
|
|
161
|
+
<OText
|
|
162
|
+
color={theme.colors.primary}
|
|
163
|
+
size={10}
|
|
164
|
+
lineHeight={15}
|
|
165
|
+
numberOfLines={1}>
|
|
166
|
+
{getTextOrderStatus(order.status, t)?.value}
|
|
167
|
+
</OText>
|
|
168
|
+
</Information>
|
|
169
|
+
<Status>
|
|
170
|
+
<OButton
|
|
171
|
+
text={t('REORDER', 'Reorder')}
|
|
172
|
+
imgRightSrc={''}
|
|
173
|
+
textStyle={styles.buttonText}
|
|
174
|
+
style={
|
|
175
|
+
isLoadingReorder && order.id === reorderSelected
|
|
176
|
+
? styles.reorderLoading
|
|
177
|
+
: styles.reorderbutton
|
|
178
|
+
}
|
|
179
|
+
onClick={() => handleReorderClick(order.id)}
|
|
180
|
+
isLoading={isLoadingReorder && order.id === reorderSelected}
|
|
181
|
+
/>
|
|
182
|
+
{allowedOrderStatus.includes(parseInt(order?.status)) &&
|
|
183
|
+
!order.review && !isReviewedOrders.includes(order?.id) &&
|
|
184
|
+
(
|
|
185
|
+
<TouchableOpacity
|
|
186
|
+
onPress={() => handleClickOrderReview(order)}
|
|
187
|
+
style={styles.reviewButton}>
|
|
188
|
+
<OText size={10} color={theme.colors.primary} numberOfLines={1}>
|
|
189
|
+
{t('REVIEW', 'Review')}
|
|
190
|
+
</OText>
|
|
191
|
+
</TouchableOpacity>
|
|
192
|
+
)}
|
|
193
|
+
</Status>
|
|
194
|
+
</Card>
|
|
195
|
+
</TouchableOpacity>
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<>
|
|
200
|
+
<OptionTitle>
|
|
201
|
+
<OText
|
|
202
|
+
size={16}
|
|
203
|
+
color={theme.colors.textPrimary}
|
|
204
|
+
mBottom={10}
|
|
205
|
+
>
|
|
206
|
+
{titleContent}
|
|
207
|
+
</OText>
|
|
208
|
+
</OptionTitle>
|
|
209
|
+
<OrdersContainer>
|
|
210
|
+
{orders.length > 0 &&
|
|
211
|
+
orders.map((order: any, index: any) => (
|
|
212
|
+
<React.Fragment key={order?.id || order?.uuid}>
|
|
213
|
+
{typeStyle === 1 && (
|
|
214
|
+
<OrderStyleOne order={order} />
|
|
215
|
+
)}
|
|
216
|
+
{typeStyle === 2 && (
|
|
217
|
+
<OrderStyleTwo order={order} />
|
|
218
|
+
)}
|
|
219
|
+
</React.Fragment>
|
|
220
|
+
))}
|
|
221
|
+
</OrdersContainer>
|
|
222
|
+
<View
|
|
223
|
+
style={{
|
|
224
|
+
height: 8,
|
|
225
|
+
backgroundColor: theme.colors.backgroundGray100,
|
|
226
|
+
marginBottom: 10
|
|
227
|
+
}}
|
|
228
|
+
/>
|
|
229
|
+
</>
|
|
230
|
+
);
|
|
231
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import styled, { css } from 'styled-components/native'
|
|
2
|
+
|
|
3
|
+
export const OrdersContainer = styled.View`
|
|
4
|
+
margin-bottom: 10px;
|
|
5
|
+
`
|
|
6
|
+
|
|
7
|
+
export const Card = styled.TouchableOpacity`
|
|
8
|
+
${(props: any) => props.themetwo ? css`
|
|
9
|
+
padding-vertical: 5px;
|
|
10
|
+
margin-bottom: 12px;
|
|
11
|
+
flex-direction: row;
|
|
12
|
+
width: 100%;
|
|
13
|
+
` : css`
|
|
14
|
+
flex: 1;
|
|
15
|
+
`};
|
|
16
|
+
`
|
|
17
|
+
|
|
18
|
+
export const Map = styled.View`
|
|
19
|
+
flex: 1;
|
|
20
|
+
height: 125px;
|
|
21
|
+
margin-bottom: 22px;
|
|
22
|
+
`
|
|
23
|
+
|
|
24
|
+
export const Information = styled.View`
|
|
25
|
+
${(props: any) => props.themetwo ? css`
|
|
26
|
+
justify-content: center;
|
|
27
|
+
align-items: flex-start;
|
|
28
|
+
margin-end: 7px;
|
|
29
|
+
flex: 1;
|
|
30
|
+
` : css`
|
|
31
|
+
flex-direction: row;
|
|
32
|
+
align-items: center;
|
|
33
|
+
padding-vertical: 5px;
|
|
34
|
+
margin-bottom: 12px;
|
|
35
|
+
`};
|
|
36
|
+
`
|
|
37
|
+
|
|
38
|
+
export const OrderInformation = styled.View`
|
|
39
|
+
flex-direction: row;
|
|
40
|
+
justify-content: space-between;
|
|
41
|
+
flex: 1;
|
|
42
|
+
`
|
|
43
|
+
|
|
44
|
+
export const BusinessInformation = styled.View`
|
|
45
|
+
flex-basis: 65%;
|
|
46
|
+
`
|
|
47
|
+
|
|
48
|
+
export const Price = styled.View`
|
|
49
|
+
justify-content: flex-start;
|
|
50
|
+
align-items: flex-end;
|
|
51
|
+
margin-left: 10px;
|
|
52
|
+
width: 30%;
|
|
53
|
+
`
|
|
54
|
+
|
|
55
|
+
export const OptionTitle = styled.View`
|
|
56
|
+
margin-top: 10px;
|
|
57
|
+
`
|
|
58
|
+
|
|
59
|
+
export const Status = styled.View`
|
|
60
|
+
align-items: center;
|
|
61
|
+
justify-content: space-between;
|
|
62
|
+
`
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { View, useWindowDimensions } from 'react-native'
|
|
3
|
+
import { useTheme } from 'styled-components/native'
|
|
4
|
+
import { useLanguage, OrderVerticalList } from 'ordering-components/native'
|
|
5
|
+
import { Placeholder, PlaceholderLine, Fade } from "rn-placeholder";
|
|
6
|
+
import { OButton, OText } from '../shared'
|
|
7
|
+
import { NotFoundSource } from '../NotFoundSource'
|
|
8
|
+
import { OrderListOption } from '../OrderListOption'
|
|
9
|
+
|
|
10
|
+
const OrdersListingUI = (props: any) => {
|
|
11
|
+
const {
|
|
12
|
+
ordersGroup,
|
|
13
|
+
reorderLoading,
|
|
14
|
+
loadMoreOrders,
|
|
15
|
+
handleReorder,
|
|
16
|
+
onNavigationRedirect,
|
|
17
|
+
} = props
|
|
18
|
+
|
|
19
|
+
const theme = useTheme()
|
|
20
|
+
const [, t] = useLanguage()
|
|
21
|
+
const { height } = useWindowDimensions()
|
|
22
|
+
|
|
23
|
+
const imageFails = theme.images.general.emptyActiveOrders
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<>
|
|
27
|
+
<OText size={20} style={{ marginTop: 20 }}>
|
|
28
|
+
{t('MY_ORDERS', 'My Orders')}
|
|
29
|
+
</OText>
|
|
30
|
+
|
|
31
|
+
{!ordersGroup.error && ordersGroup.all?.orders?.length > 0 && (
|
|
32
|
+
<>
|
|
33
|
+
{ordersGroup.upcoming?.orders?.length > 0 && (
|
|
34
|
+
<OrderListOption
|
|
35
|
+
titleContent={t('UPCOMING', 'Upcoming')}
|
|
36
|
+
typeStyle={1}
|
|
37
|
+
orders={ordersGroup.upcoming?.orders}
|
|
38
|
+
onNavigationRedirect={onNavigationRedirect}
|
|
39
|
+
/>
|
|
40
|
+
)}
|
|
41
|
+
{ordersGroup.active?.orders?.length > 0 && (
|
|
42
|
+
<OrderListOption
|
|
43
|
+
titleContent={t('ACTIVE', 'Active')}
|
|
44
|
+
typeStyle={1}
|
|
45
|
+
orders={ordersGroup.active?.orders}
|
|
46
|
+
onNavigationRedirect={onNavigationRedirect}
|
|
47
|
+
/>
|
|
48
|
+
)}
|
|
49
|
+
{ordersGroup.past?.orders?.length > 0 && (
|
|
50
|
+
<OrderListOption
|
|
51
|
+
titleContent={t('PAST', 'Past')}
|
|
52
|
+
typeStyle={2}
|
|
53
|
+
orders={ordersGroup.past?.orders}
|
|
54
|
+
allowedOrderStatus={[1, 2, 5, 6, 10, 11, 12]}
|
|
55
|
+
isLoadingReorder={reorderLoading}
|
|
56
|
+
handleReorder={handleReorder}
|
|
57
|
+
onNavigationRedirect={onNavigationRedirect}
|
|
58
|
+
/>
|
|
59
|
+
)}
|
|
60
|
+
{!ordersGroup.loading &&
|
|
61
|
+
ordersGroup?.pagination?.totalPages &&
|
|
62
|
+
ordersGroup?.pagination?.currentPage < ordersGroup?.pagination?.totalPages &&
|
|
63
|
+
(
|
|
64
|
+
<View>
|
|
65
|
+
<OButton
|
|
66
|
+
text={t('LOAD_MORE_ORDERS', 'Load more orders')}
|
|
67
|
+
imgRightSrc={null}
|
|
68
|
+
textStyle={{ color: theme.colors.white }}
|
|
69
|
+
style={{ borderRadius: 8, shadowOpacity: 0, marginTop: 20 }}
|
|
70
|
+
onClick={loadMoreOrders}
|
|
71
|
+
/>
|
|
72
|
+
</View>
|
|
73
|
+
)}
|
|
74
|
+
</>
|
|
75
|
+
)}
|
|
76
|
+
|
|
77
|
+
{ordersGroup.loading && (
|
|
78
|
+
<View style={{ marginTop: 20 }}>
|
|
79
|
+
{[...Array(6)].map((_, i) => (
|
|
80
|
+
<Placeholder key={i} Animation={Fade}>
|
|
81
|
+
<View style={{ width: '100%', flexDirection: 'row' }}>
|
|
82
|
+
<PlaceholderLine width={20} height={70} style={{ marginRight: 20, marginBottom: 20 }} />
|
|
83
|
+
<Placeholder>
|
|
84
|
+
<PlaceholderLine width={30} style={{ marginTop: 5 }} />
|
|
85
|
+
<PlaceholderLine width={50} />
|
|
86
|
+
<PlaceholderLine width={20} />
|
|
87
|
+
</Placeholder>
|
|
88
|
+
</View>
|
|
89
|
+
</Placeholder>
|
|
90
|
+
))}
|
|
91
|
+
</View>
|
|
92
|
+
)}
|
|
93
|
+
|
|
94
|
+
{!ordersGroup.loading && ordersGroup.all?.orders?.length === 0 && (
|
|
95
|
+
<View style={{ height: height * 0.7, justifyContent: 'center' }}>
|
|
96
|
+
<NotFoundSource
|
|
97
|
+
content={t('NO_RESULTS_FOUND', 'Sorry, no results found')}
|
|
98
|
+
image={imageFails}
|
|
99
|
+
/>
|
|
100
|
+
</View>
|
|
101
|
+
)}
|
|
102
|
+
</>
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export const OrdersListing = (props: any) => {
|
|
107
|
+
const ordersProps = {
|
|
108
|
+
...props,
|
|
109
|
+
UIComponent: OrdersListingUI,
|
|
110
|
+
}
|
|
111
|
+
return <OrderVerticalList {...ordersProps} />
|
|
112
|
+
}
|
|
@@ -123,6 +123,12 @@ const ProfileListUI = (props: ProfileParams) => {
|
|
|
123
123
|
onNavigationRedirect: (route: string, params: any) => props.navigation.navigate(route, params)
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
const getName = () => {
|
|
127
|
+
return user?.lastname
|
|
128
|
+
? `${user?.name} ${user?.lastname}`
|
|
129
|
+
: user?.name
|
|
130
|
+
}
|
|
131
|
+
|
|
126
132
|
return (
|
|
127
133
|
<View style={{ flex: 1, height: height - top - bottom - 62 }}>
|
|
128
134
|
<OText size={24} color={theme.colors.textNormal} lineHeight={36} weight={Platform.OS === 'ios' ? '600' : 'bold'} style={{ marginTop: 14, marginBottom: 24, ...styles.pagePadding }}>{t('PROFILE', 'Profile')}</OText>
|
|
@@ -136,7 +142,7 @@ const ProfileListUI = (props: ProfileParams) => {
|
|
|
136
142
|
/>
|
|
137
143
|
</View>
|
|
138
144
|
<View style={{ flexBasis: '70%' }}>
|
|
139
|
-
<OText size={20} lineHeight={30} weight={Platform.OS === 'ios' ? '500' : 'bold'} color={theme.colors.textNormal}>{
|
|
145
|
+
<OText size={20} lineHeight={30} weight={Platform.OS === 'ios' ? '500' : 'bold'} color={theme.colors.textNormal}>{getName()}</OText>
|
|
140
146
|
<TouchableOpacity onPress={() => navigation.navigate('ProfileForm', { ...detailProps })}>
|
|
141
147
|
<OText size={12} lineHeight={18} color={theme.colors.primary} style={{ textDecorationLine: 'underline' }}>{t('VIEW_ACCOUNT', 'View account')}</OText>
|
|
142
148
|
</TouchableOpacity>
|
|
@@ -219,4 +219,35 @@ export const getOrderStatus = (status: number) => {
|
|
|
219
219
|
default:
|
|
220
220
|
return status
|
|
221
221
|
}
|
|
222
|
-
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export const getTextOrderStatus = (s: string, t: any) => {
|
|
225
|
+
const status = parseInt(s)
|
|
226
|
+
const orderStatus = [
|
|
227
|
+
{ key: 0, value: t('PENDING', 'Pending') },
|
|
228
|
+
{ key: 1, value: t('COMPLETED', 'Completed') },
|
|
229
|
+
{ key: 2, value: t('REJECTED', 'Rejected') },
|
|
230
|
+
{ key: 3, value: t('DRIVER_IN_BUSINESS', 'Driver in business') },
|
|
231
|
+
{ key: 4, value: t('PREPARATION_COMPLETED', 'Preparation Completed') },
|
|
232
|
+
{ key: 5, value: t('REJECTED_BY_BUSINESS', 'Rejected by business') },
|
|
233
|
+
{ key: 6, value: t('REJECTED_BY_DRIVER', 'Rejected by Driver') },
|
|
234
|
+
{ key: 7, value: t('ACCEPTED_BY_BUSINESS', 'Accepted by business') },
|
|
235
|
+
{ key: 8, value: t('ACCEPTED_BY_DRIVER', 'Accepted by driver') },
|
|
236
|
+
{ key: 9, value: t('PICK_UP_COMPLETED_BY_DRIVER', 'Pick up completed by driver') },
|
|
237
|
+
{ key: 10, value: t('PICK_UP_FAILED_BY_DRIVER', 'Pick up Failed by driver') },
|
|
238
|
+
{ key: 11, value: t('DELIVERY_COMPLETED_BY_DRIVER', 'Delivery completed by driver') },
|
|
239
|
+
{ key: 12, value: t('DELIVERY_FAILED_BY_DRIVER', 'Delivery Failed by driver') },
|
|
240
|
+
{ key: 13, value: t('PREORDER', 'PreOrder') },
|
|
241
|
+
{ key: 14, value: t('ORDER_NOT_READY', 'Order not ready') },
|
|
242
|
+
{ key: 15, value: t('ORDER_PICKEDUP_COMPLETED_BY_CUSTOMER', 'Order picked up completed by customer') },
|
|
243
|
+
{ key: 16, value: t('CANCELLED_BY_CUSTOMER', 'Cancelled by customer') },
|
|
244
|
+
{ key: 17, value: t('ORDER_NOT_PICKEDUP_BY_CUSTOMER', 'Order not picked up by customer') },
|
|
245
|
+
{ key: 18, value: t('DRIVER_ALMOST_ARRIVED_TO_BUSINESS', 'Driver almost arrived to business') },
|
|
246
|
+
{ key: 19, value: t('DRIVER_ALMOST_ARRIVED_TO_CUSTOMER', 'Driver almost arrived to customer') },
|
|
247
|
+
{ key: 20, value: t('ORDER_CUSTOMER_ALMOST_ARRIVED_BUSINESS', 'Customer almost arrived to business') },
|
|
248
|
+
{ key: 21, value: t('ORDER_CUSTOMER_ARRIVED_BUSINESS', 'Customer arrived to business') }
|
|
249
|
+
]
|
|
250
|
+
|
|
251
|
+
const objectStatus = orderStatus.find((o) => o.key === status)
|
|
252
|
+
return objectStatus && objectStatus
|
|
253
|
+
}
|