ordering-ui-react-native 0.22.91 → 0.22.93
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/context/OfflineActions/index.tsx +194 -0
- package/src/index.tsx +3 -0
- package/themes/business/src/components/AcceptOrRejectOrder/index.tsx +25 -3
- package/themes/business/src/components/LanguageSelector/index.tsx +1 -1
- package/themes/business/src/components/OrderDetails/Delivery.tsx +35 -13
- package/themes/business/src/components/OrdersOption/index.tsx +60 -13
- package/themes/business/src/components/PreviousOrders/OrderItem.tsx +35 -7
- package/themes/business/src/layouts/SafeAreaContainer.tsx +35 -19
- package/themes/business/src/types/index.tsx +2 -2
package/package.json
CHANGED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import React, { useState, createContext, useEffect, useContext } from 'react';
|
|
2
|
+
import { useApi, useSession, useEvent } from 'ordering-components/native'
|
|
3
|
+
import { useNetInfo } from '@react-native-community/netinfo';
|
|
4
|
+
|
|
5
|
+
import { _retrieveStoreData, _setStoreData, _removeStoreData } from '../../providers/StoreUtil'
|
|
6
|
+
|
|
7
|
+
type State = {
|
|
8
|
+
isNetConnected: boolean | null
|
|
9
|
+
isCombinedTabs: boolean | null
|
|
10
|
+
canSaveChangesOffline: boolean | null
|
|
11
|
+
actions: Array<{ [key: string]: any }>
|
|
12
|
+
orders: { [key: string]: any } | null
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type Functions = {
|
|
16
|
+
applyOffAction: (changes: any) => any
|
|
17
|
+
registerOffOrder: (order: any) => any
|
|
18
|
+
setState: React.Dispatch<React.SetStateAction<State>>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const defaultState = {
|
|
22
|
+
isNetConnected: null,
|
|
23
|
+
isCombinedTabs: null,
|
|
24
|
+
canSaveChangesOffline: false,
|
|
25
|
+
actions: [],
|
|
26
|
+
orders: null,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
export const OfflineActionsContext = createContext<[State, Functions]>([
|
|
31
|
+
defaultState,
|
|
32
|
+
{
|
|
33
|
+
applyOffAction: () => {},
|
|
34
|
+
registerOffOrder: () => {},
|
|
35
|
+
setState: () => {}
|
|
36
|
+
}
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
export const OfflineActionsProvider = (props: any) => {
|
|
40
|
+
const netInfo = useNetInfo()
|
|
41
|
+
const [ordering] = useApi()
|
|
42
|
+
const [{ token }] = useSession()
|
|
43
|
+
const [events] = useEvent()
|
|
44
|
+
|
|
45
|
+
const [state, setState] = useState<State>({
|
|
46
|
+
isNetConnected: netInfo.isConnected,
|
|
47
|
+
isCombinedTabs: false,
|
|
48
|
+
canSaveChangesOffline: false,
|
|
49
|
+
actions: [],
|
|
50
|
+
orders: null
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const getStatusById = (id: number) => {
|
|
54
|
+
if (!id && id !== 0) return
|
|
55
|
+
const active = [0, 3, 4, 7, 8, 9, 13, 14, 18, 19, 20, 21]
|
|
56
|
+
const pending = [0, 13]
|
|
57
|
+
const inProgress = [3, 4, 7, 8, 9, 14, 18, 19, 20, 21]
|
|
58
|
+
const completed = [1, 11, 15]
|
|
59
|
+
|
|
60
|
+
const status = pending.includes(id)
|
|
61
|
+
? 'pending'
|
|
62
|
+
: inProgress.includes(id)
|
|
63
|
+
? 'inProgress'
|
|
64
|
+
: completed.includes(id)
|
|
65
|
+
? 'completed'
|
|
66
|
+
: 'cancelled'
|
|
67
|
+
|
|
68
|
+
const combinedStatus = active.includes(id)
|
|
69
|
+
? 'active'
|
|
70
|
+
: completed.includes(id)
|
|
71
|
+
? 'completed'
|
|
72
|
+
: 'cancelled'
|
|
73
|
+
|
|
74
|
+
return state.isCombinedTabs ? combinedStatus : status
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const applyOffAction = async (changes: any) => {
|
|
78
|
+
if (state.canSaveChangesOffline === false) return false
|
|
79
|
+
|
|
80
|
+
const actions = [...new Set([...state.actions, changes])]
|
|
81
|
+
|
|
82
|
+
setState(state => ({ ...state, actions }))
|
|
83
|
+
await _setStoreData('offline_actions_array', actions)
|
|
84
|
+
return true
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const registerOffOrder = async (order: any) => {
|
|
88
|
+
if (!order) return
|
|
89
|
+
|
|
90
|
+
const oldStatusString = getStatusById(order?.oldStatus)
|
|
91
|
+
const newStatusString = getStatusById(order?.status)
|
|
92
|
+
|
|
93
|
+
const orderStatuses: any = [oldStatusString]
|
|
94
|
+
oldStatusString !== newStatusString && orderStatuses.push(newStatusString)
|
|
95
|
+
|
|
96
|
+
const ordersStoraged: any = {}
|
|
97
|
+
for (const status of orderStatuses) {
|
|
98
|
+
ordersStoraged[status] = await _retrieveStoreData(`${status}_orders`)
|
|
99
|
+
|
|
100
|
+
if (ordersStoraged[status]) {
|
|
101
|
+
if (orderStatuses.length === 1) {
|
|
102
|
+
ordersStoraged[status] = [
|
|
103
|
+
...ordersStoraged[status].filter((_order: any) => _order.id !== order.id),
|
|
104
|
+
order
|
|
105
|
+
].sort((a: any, b: any) => b.id - a.id)
|
|
106
|
+
} else if (orderStatuses.length === 2) {
|
|
107
|
+
if (status === oldStatusString) {
|
|
108
|
+
ordersStoraged[status] = ordersStoraged[status]
|
|
109
|
+
.filter((_order: any) => _order.id !== order.id)
|
|
110
|
+
.sort((a: any, b: any) => b.id - a.id)
|
|
111
|
+
}
|
|
112
|
+
if (status === newStatusString) {
|
|
113
|
+
ordersStoraged[status] = [
|
|
114
|
+
...ordersStoraged[status],
|
|
115
|
+
order
|
|
116
|
+
].sort((a: any, b: any) => b.id - a.id)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
await _setStoreData(`${status}_orders`, ordersStoraged[status]);
|
|
120
|
+
} else {
|
|
121
|
+
ordersStoraged[status] = [order]
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (Object.keys(ordersStoraged).length) {
|
|
125
|
+
setState(state => ({ ...state, orders: ordersStoraged }))
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const syncChanges = async (changes: any) => {
|
|
130
|
+
const data = []
|
|
131
|
+
for (const action of changes) {
|
|
132
|
+
const eventFunction = eventsDictiorary[action.event];
|
|
133
|
+
if (eventFunction) {
|
|
134
|
+
const id = await eventFunction(action.data);
|
|
135
|
+
id && data.push(id)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
data.length && events.emit('offline_order_updated', data)
|
|
139
|
+
await _removeStoreData('offline_actions_array');
|
|
140
|
+
setState(state => ({ ...state, actions: [] }));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const actionsFromStorage = async (isConnected: boolean) => {
|
|
144
|
+
setState(state => ({ ...state, isNetConnected: isConnected }))
|
|
145
|
+
const _storedActions = await _retrieveStoreData('offline_actions_array');
|
|
146
|
+
const storedActions: any = [...new Set(_storedActions)]
|
|
147
|
+
|
|
148
|
+
if (isConnected && storedActions?.length) {
|
|
149
|
+
syncChanges(storedActions)
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
storedActions?.length && setState(state => ({ ...state, actions: storedActions }));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
if (netInfo.isConnected === null || state.canSaveChangesOffline === false) return
|
|
158
|
+
actionsFromStorage(netInfo.isConnected)
|
|
159
|
+
}, [netInfo.isConnected])
|
|
160
|
+
|
|
161
|
+
const functions: any = {
|
|
162
|
+
applyOffAction,
|
|
163
|
+
registerOffOrder,
|
|
164
|
+
setState
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const updateOrderStatus = async (offlineData: any) => {
|
|
168
|
+
try {
|
|
169
|
+
const { content: { result: order, error } } = await ordering
|
|
170
|
+
.setAccessToken(token)
|
|
171
|
+
.orders(offlineData?.orderId)
|
|
172
|
+
.save(offlineData?.body)
|
|
173
|
+
|
|
174
|
+
return error ? null : order?.id
|
|
175
|
+
} catch {
|
|
176
|
+
return null
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const eventsDictiorary: any = {
|
|
181
|
+
evt_off_change_order_status: updateOrderStatus
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<OfflineActionsContext.Provider value={[{ ...state, isNetConnected: netInfo.isConnected }, functions]}>
|
|
186
|
+
{props.children}
|
|
187
|
+
</OfflineActionsContext.Provider>
|
|
188
|
+
);
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export const useOfflineActions = () => {
|
|
192
|
+
const actionsManager = useContext(OfflineActionsContext)
|
|
193
|
+
return actionsManager || [defaultState, {}]
|
|
194
|
+
}
|
package/src/index.tsx
CHANGED
|
@@ -94,6 +94,7 @@ import { StoreMethods } from './providers/StoreUtil';
|
|
|
94
94
|
|
|
95
95
|
// contexts
|
|
96
96
|
import { ThemeProvider, useTheme } from './context/Theme';
|
|
97
|
+
import { OfflineActionsProvider, useOfflineActions } from './context/OfflineActions';
|
|
97
98
|
|
|
98
99
|
// hooks
|
|
99
100
|
import { DeviceOrientationMethods } from './hooks/DeviceOrientation';
|
|
@@ -190,6 +191,8 @@ export {
|
|
|
190
191
|
// contexts
|
|
191
192
|
ThemeProvider,
|
|
192
193
|
useTheme,
|
|
194
|
+
OfflineActionsProvider,
|
|
195
|
+
useOfflineActions,
|
|
193
196
|
// hooks
|
|
194
197
|
DeviceOrientationMethods,
|
|
195
198
|
//types
|
|
@@ -16,7 +16,7 @@ import { useLanguage } from 'ordering-components/native';
|
|
|
16
16
|
import { Content, Timer, TimeField, Header, Comments, CommentsButtonGroup, TopActions } from './styles';
|
|
17
17
|
import { OText, OButton, OTextarea, OIcon } from '../shared';
|
|
18
18
|
import { AcceptOrRejectOrderParams } from '../../types';
|
|
19
|
-
|
|
19
|
+
import { useOfflineActions } from '../../../../../src/context/OfflineActions';
|
|
20
20
|
import { orderCommentList } from '../../../../../src/utils'
|
|
21
21
|
|
|
22
22
|
export const AcceptOrRejectOrder = (props: AcceptOrRejectOrderParams) => {
|
|
@@ -36,6 +36,8 @@ export const AcceptOrRejectOrder = (props: AcceptOrRejectOrderParams) => {
|
|
|
36
36
|
|
|
37
37
|
const [, t] = useLanguage();
|
|
38
38
|
const theme = useTheme();
|
|
39
|
+
const [{ isNetConnected, canSaveChangesOffline }, { applyOffAction, registerOffOrder }] = useOfflineActions()
|
|
40
|
+
|
|
39
41
|
const scrollViewRef = useRef<any>(null);
|
|
40
42
|
const viewRef = useRef<any>(null);
|
|
41
43
|
const timerRef = useRef() as React.MutableRefObject<TextInput>;
|
|
@@ -201,7 +203,7 @@ export const AcceptOrRejectOrder = (props: AcceptOrRejectOrderParams) => {
|
|
|
201
203
|
}
|
|
202
204
|
};
|
|
203
205
|
|
|
204
|
-
const handleAcceptOrReject = () => {
|
|
206
|
+
const handleAcceptOrReject = async () => {
|
|
205
207
|
handleFixTime();
|
|
206
208
|
let minsToSend = min;
|
|
207
209
|
|
|
@@ -278,7 +280,27 @@ export const AcceptOrRejectOrder = (props: AcceptOrRejectOrderParams) => {
|
|
|
278
280
|
}
|
|
279
281
|
|
|
280
282
|
bodyToSend.id = orderId;
|
|
281
|
-
|
|
283
|
+
|
|
284
|
+
if (!isNetConnected && canSaveChangesOffline !== false) {
|
|
285
|
+
const body = Object.keys(bodyToSend || {}).length > 0
|
|
286
|
+
? bodyToSend
|
|
287
|
+
: { status: bodyToSend.status }
|
|
288
|
+
|
|
289
|
+
const result = applyOffAction({
|
|
290
|
+
event: 'evt_off_change_order_status',
|
|
291
|
+
data: { orderId, body }
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
const orderUpdated = await handleUpdateOrder?.(
|
|
295
|
+
bodyToSend.status,
|
|
296
|
+
bodyToSend,
|
|
297
|
+
{ dataToSave: { ...body, unsync: true } }
|
|
298
|
+
)
|
|
299
|
+
await registerOffOrder(orderUpdated)
|
|
300
|
+
closeModal && closeModal()
|
|
301
|
+
} else {
|
|
302
|
+
handleUpdateOrder?.(bodyToSend.status, bodyToSend);
|
|
303
|
+
}
|
|
282
304
|
};
|
|
283
305
|
|
|
284
306
|
useEffect(() => {
|
|
@@ -49,7 +49,7 @@ const LanguageSelectorUI = (props: LanguageSelectorParams) => {
|
|
|
49
49
|
},
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
return (
|
|
52
|
+
return !languagesState?.loading && languagesState?.languages?.length > 1 && (
|
|
53
53
|
<Container style={{ backgroundColor: theme.colors.inputChat }}>
|
|
54
54
|
{languagesState?.languages && (
|
|
55
55
|
<CountryPicker
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
//React & React Native
|
|
2
1
|
import React, { useState, useEffect } from 'react';
|
|
3
2
|
import { StyleSheet, View } from 'react-native';
|
|
4
3
|
|
|
5
|
-
// Thirds
|
|
6
4
|
import { Placeholder, PlaceholderLine, Fade } from 'rn-placeholder';
|
|
7
5
|
import Clipboard from '@react-native-clipboard/clipboard';
|
|
6
|
+
import MCIcon from 'react-native-vector-icons/MaterialCommunityIcons';
|
|
8
7
|
|
|
9
|
-
//OrderingComponent
|
|
10
8
|
import {
|
|
11
9
|
useLanguage,
|
|
12
10
|
OrderDetails as OrderDetailsConTableoller,
|
|
@@ -17,13 +15,12 @@ import {
|
|
|
17
15
|
useConfig
|
|
18
16
|
} from 'ordering-components/native';
|
|
19
17
|
|
|
20
|
-
//Components
|
|
21
18
|
import Alert from '../../providers/AlertProvider';
|
|
22
19
|
import { AcceptOrRejectOrder } from '../AcceptOrRejectOrder';
|
|
23
20
|
import { Chat } from '../Chat';
|
|
24
21
|
import { FloatingButton } from '../FloatingButton';
|
|
25
22
|
import { DriverMap } from '../DriverMap';
|
|
26
|
-
import { OButton } from '../shared';
|
|
23
|
+
import { OButton, OText } from '../shared';
|
|
27
24
|
import { OModal } from '../shared';
|
|
28
25
|
import { OrderDetailsParams } from '../../types';
|
|
29
26
|
import { USER_TYPE } from '../../config/constants';
|
|
@@ -32,7 +29,6 @@ import { NotFoundSource } from '../NotFoundSource';
|
|
|
32
29
|
import { verifyDecimals, getProductPrice, getOrderStatus } from '../../utils';
|
|
33
30
|
import { OrderHeaderComponent } from './OrderHeaderComponent';
|
|
34
31
|
import { OrderContentComponent } from './OrderContentComponent';
|
|
35
|
-
//Styles
|
|
36
32
|
import { OrderDetailsContainer, Pickup } from './styles';
|
|
37
33
|
|
|
38
34
|
export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
@@ -56,8 +52,9 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
56
52
|
forceUpdate,
|
|
57
53
|
getPermissions,
|
|
58
54
|
orderAssingId,
|
|
59
|
-
isGrantedPermissions
|
|
55
|
+
isGrantedPermissions
|
|
60
56
|
} = props;
|
|
57
|
+
|
|
61
58
|
const [, { showToast }] = useToast();
|
|
62
59
|
const [{ parsePrice, parseNumber }] = useUtils();
|
|
63
60
|
const [{ configs }] = useConfig();
|
|
@@ -548,6 +545,28 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
548
545
|
{!((!order || Object.keys(order).length === 0) &&
|
|
549
546
|
(props.order?.error?.length < 1 || !props.order?.error)) && order?.id && (
|
|
550
547
|
<View style={{ flex: 1 }}>
|
|
548
|
+
{order?.unsync && (
|
|
549
|
+
<View
|
|
550
|
+
style={{
|
|
551
|
+
flexDirection: 'row',
|
|
552
|
+
justifyContent: 'flex-start',
|
|
553
|
+
alignItems: 'center'
|
|
554
|
+
}}
|
|
555
|
+
>
|
|
556
|
+
<MCIcon
|
|
557
|
+
name={'cloud-sync'}
|
|
558
|
+
color={'#444'}
|
|
559
|
+
size={16}
|
|
560
|
+
/>
|
|
561
|
+
<OText
|
|
562
|
+
size={14}
|
|
563
|
+
color={theme.colors.textGray}
|
|
564
|
+
style={{ marginLeft: 5 }}
|
|
565
|
+
>
|
|
566
|
+
{t('PENDING_SYNC_CHANGES', 'Pending sync changes')}
|
|
567
|
+
</OText>
|
|
568
|
+
</View>
|
|
569
|
+
)}
|
|
551
570
|
<OrderHeaderComponent
|
|
552
571
|
order={order}
|
|
553
572
|
handleOpenMapView={handleOpenMapView}
|
|
@@ -612,16 +631,19 @@ export const OrderDetailsUI = (props: OrderDetailsParams) => {
|
|
|
612
631
|
{showFloatButtonsAcceptOrReject[order?.status] && (
|
|
613
632
|
<FloatingButton
|
|
614
633
|
disabled={props.order?.loading}
|
|
634
|
+
widthButton={isHideRejectButtons ? '100%' : '45%'}
|
|
635
|
+
isHideRejectButtons={isHideRejectButtons}
|
|
615
636
|
btnText={t('REJECT', 'Reject')}
|
|
637
|
+
firstColorCustom={theme.colors.red}
|
|
638
|
+
firstButtonClick={() => order?.isLogistic && (order?.order_group || logisticOrderStatus.includes(order?.status))
|
|
639
|
+
? handleRejectLogisticOrder()
|
|
640
|
+
: handleViewActionOrder('reject')
|
|
641
|
+
}
|
|
616
642
|
isSecondaryBtn={false}
|
|
617
|
-
secondButtonClick={() => hideTimer ? handleChangeOrderStatus && handleChangeOrderStatus(8) : (order?.isLogistic && (order?.order_group || logisticOrderStatus.includes(order?.status))) ? handleAcceptLogisticOrder(order) : handleViewActionOrder('accept')}
|
|
618
|
-
firstButtonClick={() => order?.isLogistic && (order?.order_group || logisticOrderStatus.includes(order?.status)) ? handleRejectLogisticOrder() : handleViewActionOrder('reject')}
|
|
619
|
-
secondBtnText={t('ACCEPT', 'Accept')}
|
|
620
643
|
secondButton={true}
|
|
621
|
-
|
|
644
|
+
secondBtnText={t('ACCEPT', 'Accept')}
|
|
645
|
+
secondButtonClick={() => hideTimer ? handleChangeOrderStatus && handleChangeOrderStatus(8) : (order?.isLogistic && (order?.order_group || logisticOrderStatus.includes(order?.status))) ? handleAcceptLogisticOrder(order) : handleViewActionOrder('accept')}
|
|
622
646
|
secondColorCustom={theme.colors.green}
|
|
623
|
-
widthButton={isHideRejectButtons ? '100%' : '45%'}
|
|
624
|
-
isHideRejectButtons={isHideRejectButtons}
|
|
625
647
|
/>
|
|
626
648
|
)}
|
|
627
649
|
</>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useEffect, useState, useRef } from 'react';
|
|
2
2
|
import { View, Pressable, StyleSheet, ScrollView, RefreshControl, Platform, TouchableOpacity } from 'react-native';
|
|
3
|
-
import { useLanguage, useUtils,
|
|
3
|
+
import { useLanguage, useUtils, OrderListGroups, useConfig } from 'ordering-components/native';
|
|
4
4
|
import SelectDropdown from 'react-native-select-dropdown'
|
|
5
5
|
import { Placeholder, PlaceholderLine, Fade } from 'rn-placeholder';
|
|
6
6
|
import FeatherIcon from 'react-native-vector-icons/Feather';
|
|
@@ -13,7 +13,8 @@ import { DeviceOrientationMethods } from '../../../../../src/hooks/DeviceOrienta
|
|
|
13
13
|
import { NotificationSetting } from '../../../../../src/components/NotificationSetting'
|
|
14
14
|
import { NewOrderNotification } from '../NewOrderNotification';
|
|
15
15
|
import { WebsocketStatus } from '../WebsocketStatus'
|
|
16
|
-
import { _retrieveStoreData, _setStoreData } from '../../providers/StoreUtil'
|
|
16
|
+
import { _retrieveStoreData, _setStoreData, _removeStoreData } from '../../providers/StoreUtil'
|
|
17
|
+
import { useOfflineActions } from '../../../../../src/context/OfflineActions'
|
|
17
18
|
|
|
18
19
|
import { OText, OButton, OModal, OInput, OIcon } from '../shared';
|
|
19
20
|
import { NotFoundSource } from '../NotFoundSource';
|
|
@@ -99,6 +100,7 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
|
|
|
99
100
|
const [, t] = useLanguage();
|
|
100
101
|
const [{ parseDate }] = useUtils()
|
|
101
102
|
const [configState] = useConfig()
|
|
103
|
+
const [offlineActionsState] = useOfflineActions()
|
|
102
104
|
|
|
103
105
|
const [orientationState] = useDeviceOrientation();
|
|
104
106
|
const [openSearchModal, setOpenSearchModal] = useState(false)
|
|
@@ -406,10 +408,17 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
|
|
|
406
408
|
const manageStoragedOrders = async () => {
|
|
407
409
|
setInternetLoading(true)
|
|
408
410
|
let lastConnection = await _retrieveStoreData('last_date_connection');
|
|
411
|
+
let allowSaveChangesOffline = await _retrieveStoreData('allow_save_changes_offline');
|
|
409
412
|
let _combineTabs = await _retrieveStoreData('combine_pending_and_progress_orders')
|
|
413
|
+
|
|
414
|
+
if (allowSaveChangesOffline === false) {
|
|
415
|
+
setInternetLoading(false)
|
|
416
|
+
return
|
|
417
|
+
}
|
|
418
|
+
|
|
410
419
|
let ordersStoraged: any = {}
|
|
411
420
|
for (const status of orderStatuses) {
|
|
412
|
-
ordersStoraged[status] = await _retrieveStoreData(`${status}_orders`) ?? []
|
|
421
|
+
ordersStoraged[status] = offlineActionsState.orders?.[status] ?? await _retrieveStoreData(`${status}_orders`) ?? []
|
|
413
422
|
}
|
|
414
423
|
|
|
415
424
|
if (_combineTabs || !_combineTabs && combineTabs) {
|
|
@@ -427,8 +436,9 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
|
|
|
427
436
|
|
|
428
437
|
if (Object.values(ordersStoraged).every((key: any) => Array.isArray(key) && !key?.length)) {
|
|
429
438
|
for (const status of orderStatuses) {
|
|
430
|
-
|
|
431
|
-
|
|
439
|
+
const currentOrders = offlineActionsState.orders?.[status] ?? ordersGroup[status]?.orders
|
|
440
|
+
ordersStoraged[status] = currentOrders
|
|
441
|
+
_setStoreData(`${status}_orders`, currentOrders);
|
|
432
442
|
}
|
|
433
443
|
}
|
|
434
444
|
|
|
@@ -449,13 +459,14 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
|
|
|
449
459
|
};
|
|
450
460
|
|
|
451
461
|
if (isNetConnected) {
|
|
452
|
-
|
|
453
|
-
|
|
462
|
+
_removeStoreData('last_date_connection');
|
|
463
|
+
_removeStoreData('combine_pending_and_progress_orders');
|
|
464
|
+
_removeStoreData('allow_save_changes_offline');
|
|
454
465
|
orderStatuses.forEach((key: any) => _setStoreData(`${key}_orders`, null))
|
|
455
466
|
} else if (isNetConnected === false) {
|
|
456
467
|
manageStoragedOrders()
|
|
457
468
|
}
|
|
458
|
-
}, [isNetConnected]);
|
|
469
|
+
}, [isNetConnected, JSON.stringify(offlineActionsState.orders)]);
|
|
459
470
|
|
|
460
471
|
return (
|
|
461
472
|
<>
|
|
@@ -609,7 +620,8 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
|
|
|
609
620
|
borderRadius: 8,
|
|
610
621
|
paddingVertical: 3,
|
|
611
622
|
backgroundColor: theme.colors.danger500,
|
|
612
|
-
marginBottom: 10
|
|
623
|
+
marginBottom: 10,
|
|
624
|
+
flexDirection: 'column'
|
|
613
625
|
}}
|
|
614
626
|
>
|
|
615
627
|
<OText
|
|
@@ -617,6 +629,13 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
|
|
|
617
629
|
>
|
|
618
630
|
{`${t('LAST_UPDATE', 'Last Update')}: ${lastDateConnection}`}
|
|
619
631
|
</OText>
|
|
632
|
+
{offlineActionsState?.actions?.length > 0 && (
|
|
633
|
+
<OText
|
|
634
|
+
style={{ color: 'white', textAlign: 'center' }}
|
|
635
|
+
>
|
|
636
|
+
{t('NUMBER_CHANGES_PENDING_SYNC', '_value_ changes pending sync').replace('_value_', offlineActionsState?.actions?.length)}
|
|
637
|
+
</OText>
|
|
638
|
+
)}
|
|
620
639
|
</View>
|
|
621
640
|
)}
|
|
622
641
|
<ScrollView
|
|
@@ -652,7 +671,7 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
|
|
|
652
671
|
/>
|
|
653
672
|
)}
|
|
654
673
|
{!logisticOrders?.error?.length &&
|
|
655
|
-
logisticOrders?.orders?.length > 0 &&
|
|
674
|
+
logisticOrders && logisticOrders?.orders?.length > 0 &&
|
|
656
675
|
currentTabSelected === 'logisticOrders' && (
|
|
657
676
|
<PreviousOrders
|
|
658
677
|
orders={logisticOrders?.orders?.filter((order: any) => !order?.expired).map((order: any) => ({ ...order, isLogistic: true }))}
|
|
@@ -727,7 +746,7 @@ const OrdersOptionUI = (props: OrdersOptionParams) => {
|
|
|
727
746
|
(currentOrdersGroup?.error?.length ||
|
|
728
747
|
currentOrdersGroup?.orders?.length === 0)) ||
|
|
729
748
|
(currentTabSelected === 'logisticOrders' &&
|
|
730
|
-
(logisticOrders?.error?.length > 0 || logisticOrders?.orders?.length === 0 || !logisticOrders?.orders?.some(order => !order?.expired)))
|
|
749
|
+
(logisticOrders && logisticOrders?.error?.length > 0 || logisticOrders?.orders?.length === 0 || !logisticOrders?.orders?.some(order => !order?.expired)))
|
|
731
750
|
) &&
|
|
732
751
|
(
|
|
733
752
|
<NotFoundSource
|
|
@@ -1025,10 +1044,38 @@ export const Timer = () => {
|
|
|
1025
1044
|
export const OrdersOption = (props: OrdersOptionParams) => {
|
|
1026
1045
|
const [, t] = useLanguage();
|
|
1027
1046
|
const [configState] = useConfig()
|
|
1047
|
+
const [, offlineMethods] = useOfflineActions()
|
|
1048
|
+
|
|
1028
1049
|
const [checkNotificationStatus, setCheckNotificationStatus] = useState({ open: false, checked: false })
|
|
1050
|
+
const [combineTabs, setCombineTabs] = useState(null)
|
|
1029
1051
|
|
|
1030
|
-
|
|
1031
|
-
|
|
1052
|
+
useEffect(() => {
|
|
1053
|
+
const getCombineTabsStoraged = async () => {
|
|
1054
|
+
try {
|
|
1055
|
+
const storagedValue = await _retrieveStoreData('combine_pending_and_progress_orders');
|
|
1056
|
+
const saveChangesOffline = await _retrieveStoreData('allow_save_changes_offline');
|
|
1057
|
+
|
|
1058
|
+
const _combineTabs = typeof configState?.configs?.combine_pending_and_progress_orders === 'object'
|
|
1059
|
+
? configState?.configs?.combine_pending_and_progress_orders?.value === '1'
|
|
1060
|
+
: storagedValue
|
|
1061
|
+
|
|
1062
|
+
const canSaveChangesOffline = typeof configState?.configs?.allow_save_changes_offline === 'object'
|
|
1063
|
+
? (configState?.configs?.allow_save_changes_offline?.value ?? '')?.toString() === 'true'
|
|
1064
|
+
: saveChangesOffline
|
|
1065
|
+
|
|
1066
|
+
offlineMethods.setState((state: any) => ({
|
|
1067
|
+
...state,
|
|
1068
|
+
isCombinedTabs: _combineTabs,
|
|
1069
|
+
canSaveChangesOffline
|
|
1070
|
+
}))
|
|
1071
|
+
setCombineTabs(_combineTabs)
|
|
1072
|
+
return _combineTabs;
|
|
1073
|
+
} catch {
|
|
1074
|
+
return null
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
getCombineTabsStoraged()
|
|
1078
|
+
}, [])
|
|
1032
1079
|
|
|
1033
1080
|
const ordersProps = {
|
|
1034
1081
|
...props,
|
|
@@ -2,8 +2,9 @@ import React, { useEffect, useState } from 'react';
|
|
|
2
2
|
import { Platform, PlatformIOSStatic, Pressable, StyleSheet, View } from 'react-native';
|
|
3
3
|
import DeviceInfo from 'react-native-device-info';
|
|
4
4
|
import { useTheme } from 'styled-components/native';
|
|
5
|
-
import { useLanguage, useUtils, useConfig } from 'ordering-components/native';
|
|
5
|
+
import { useLanguage, useUtils, useConfig, useEvent } from 'ordering-components/native';
|
|
6
6
|
import EntypoIcon from 'react-native-vector-icons/Entypo'
|
|
7
|
+
import MCIcon from 'react-native-vector-icons/MaterialCommunityIcons';
|
|
7
8
|
import FastImage from 'react-native-fast-image'
|
|
8
9
|
import moment from 'moment'
|
|
9
10
|
|
|
@@ -39,10 +40,12 @@ export const OrderItem = React.memo((props: any) => {
|
|
|
39
40
|
|
|
40
41
|
const theme = useTheme()
|
|
41
42
|
const [, t] = useLanguage()
|
|
43
|
+
const [events] = useEvent()
|
|
42
44
|
const [configState] = useConfig()
|
|
43
|
-
const [{ parseDate
|
|
45
|
+
const [{ parseDate }] = useUtils();
|
|
44
46
|
const [orientationState] = useDeviceOrientation();
|
|
45
47
|
|
|
48
|
+
const [ordersOffUpdated, setOrdersOffUpdated] = useState<number[]>([])
|
|
46
49
|
const [allowColumns, setAllowColumns] = useState({
|
|
47
50
|
timer: configState?.configs?.order_deadlines_enabled?.value === '1',
|
|
48
51
|
slaBar: configState?.configs?.order_deadlines_enabled?.value === '1',
|
|
@@ -136,6 +139,17 @@ export const OrderItem = React.memo((props: any) => {
|
|
|
136
139
|
})
|
|
137
140
|
}, [configState.loading])
|
|
138
141
|
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
const handleOfflineOrder = (ids: any) => {
|
|
144
|
+
ids && setOrdersOffUpdated(ids)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
events.on('offline_order_updated', handleOfflineOrder)
|
|
148
|
+
return () => {
|
|
149
|
+
events.off('offline_order_updated', handleOfflineOrder)
|
|
150
|
+
}
|
|
151
|
+
}, [])
|
|
152
|
+
|
|
139
153
|
return (
|
|
140
154
|
<Pressable
|
|
141
155
|
disabled={order?.locked && isLogisticOrder}
|
|
@@ -164,11 +178,25 @@ export const OrderItem = React.memo((props: any) => {
|
|
|
164
178
|
<OText>{(t('INVOICE_GROUP_NO', 'Group No.') + order?.order_group_id)}</OText>
|
|
165
179
|
</OText>
|
|
166
180
|
)}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
181
|
+
<View
|
|
182
|
+
style={{
|
|
183
|
+
flexDirection: 'row',
|
|
184
|
+
justifyContent: 'space-between'
|
|
185
|
+
}}
|
|
186
|
+
>
|
|
187
|
+
{!!order.business?.name && (
|
|
188
|
+
<OText numberOfLines={1} style={styles.title}>
|
|
189
|
+
{order.business?.name}
|
|
190
|
+
</OText>
|
|
191
|
+
)}
|
|
192
|
+
{order?.unsync && !ordersOffUpdated?.includes(order?.id) && (
|
|
193
|
+
<MCIcon
|
|
194
|
+
name={'cloud-sync'}
|
|
195
|
+
color={'#444'}
|
|
196
|
+
size={18}
|
|
197
|
+
/>
|
|
198
|
+
)}
|
|
199
|
+
</View>
|
|
172
200
|
{!!order?.showNotification && (
|
|
173
201
|
<NotificationIcon>
|
|
174
202
|
<EntypoIcon
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Dimensions,
|
|
4
4
|
Platform,
|
|
5
5
|
StatusBar,
|
|
6
|
-
StyleSheet,
|
|
7
6
|
View,
|
|
8
7
|
} from 'react-native';
|
|
9
|
-
import styled from 'styled-components/native';
|
|
8
|
+
import styled, { useTheme } from 'styled-components/native';
|
|
9
|
+
import { useNetInfo } from '@react-native-community/netinfo';
|
|
10
10
|
|
|
11
11
|
export const SafeAreaContainer = styled.SafeAreaView`
|
|
12
12
|
flex: 1;
|
|
@@ -14,6 +14,10 @@ export const SafeAreaContainer = styled.SafeAreaView`
|
|
|
14
14
|
`;
|
|
15
15
|
|
|
16
16
|
export const SafeAreaContainerLayout = (props: any) => {
|
|
17
|
+
const theme = useTheme();
|
|
18
|
+
const netInfo = useNetInfo()
|
|
19
|
+
|
|
20
|
+
const [statusColor, setStatusColor] = useState<string | null>(null)
|
|
17
21
|
const [orientation, setOrientation] = useState(
|
|
18
22
|
Dimensions.get('window').width < Dimensions.get('window').height
|
|
19
23
|
? 'Portrait'
|
|
@@ -28,22 +32,34 @@ export const SafeAreaContainerLayout = (props: any) => {
|
|
|
28
32
|
}
|
|
29
33
|
});
|
|
30
34
|
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (netInfo.isConnected === false) {
|
|
37
|
+
setStatusColor(theme.colors.danger500)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (netInfo.isConnected && statusColor) {
|
|
41
|
+
setStatusColor(theme.colors.success500)
|
|
42
|
+
setTimeout(() => {
|
|
43
|
+
setStatusColor(null)
|
|
44
|
+
}, 2000);
|
|
45
|
+
}
|
|
46
|
+
}, [netInfo.isConnected])
|
|
47
|
+
|
|
31
48
|
return (
|
|
32
|
-
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
</>
|
|
49
|
+
<SafeAreaContainer>
|
|
50
|
+
<View
|
|
51
|
+
style={{
|
|
52
|
+
paddingHorizontal: 30,
|
|
53
|
+
paddingTop: 30,
|
|
54
|
+
paddingBottom: 0,
|
|
55
|
+
flex: 1,
|
|
56
|
+
}}>
|
|
57
|
+
<StatusBar
|
|
58
|
+
barStyle={Platform.OS === 'ios' ? 'dark-content' : 'default'}
|
|
59
|
+
{...statusColor && ({ backgroundColor: statusColor })}
|
|
60
|
+
/>
|
|
61
|
+
{props.children}
|
|
62
|
+
</View>
|
|
63
|
+
</SafeAreaContainer>
|
|
48
64
|
);
|
|
49
65
|
};
|
|
@@ -321,7 +321,7 @@ export interface OrdersOptionParams {
|
|
|
321
321
|
handleChangeOrderStatus?: () => void;
|
|
322
322
|
handleSendCustomerReview?: () => void;
|
|
323
323
|
orderDetailsProps?: any;
|
|
324
|
-
isNetConnected?: boolean;
|
|
324
|
+
isNetConnected?: boolean | null;
|
|
325
325
|
isDriverApp?: boolean;
|
|
326
326
|
combineTabs?: boolean;
|
|
327
327
|
setCombineTabsState?: any;
|
|
@@ -591,7 +591,7 @@ export interface AcceptOrRejectOrderParams {
|
|
|
591
591
|
loading?: boolean;
|
|
592
592
|
action: string;
|
|
593
593
|
orderId?: number;
|
|
594
|
-
handleUpdateOrder?: (p1: any, p2: any) => {};
|
|
594
|
+
handleUpdateOrder?: (p1: any, p2: any, p3?: any) => {};
|
|
595
595
|
notShowCustomerPhone?: boolean | undefined;
|
|
596
596
|
actions?: any;
|
|
597
597
|
titleAccept?: textTranslate;
|