@janiscommerce/app-tracking-shift 1.0.1
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/README.md +1 -0
- package/lib/Formatter.js +214 -0
- package/lib/OfflineData.js +91 -0
- package/lib/Shift.js +538 -0
- package/lib/ShiftWorklogs.js +92 -0
- package/lib/StaffApiServices.js +151 -0
- package/lib/TrackerRecords.js +103 -0
- package/lib/components/WithShiftTracking/index.js +36 -0
- package/lib/constant/index.js +33 -0
- package/lib/context/ShiftTrackingContext.js +7 -0
- package/lib/db/StorageService.js +5 -0
- package/lib/db/TimeTrackerService.js +5 -0
- package/lib/hooks/useMMKVObject/index.js +19 -0
- package/lib/index.js +7 -0
- package/lib/provider/ShiftTrackingProvider.js +174 -0
- package/lib/utils/crashlytics/index.js +5 -0
- package/lib/utils/helpers/index.js +20 -0
- package/lib/utils/provider/downloadWorkLogTypes/index.js +30 -0
- package/lib/utils/provider/getShiftWorkLogsFromJanis/index.js +18 -0
- package/lib/utils/provider/index.js +5 -0
- package/lib/utils/provider/isAuthorizedToUseStaffMS/index.js +39 -0
- package/lib/utils/provider/openShift/index.js +69 -0
- package/lib/utils/provider/saveWorkLogTimesInDB/index.js +38 -0
- package/lib/utils/request/index.js +15 -0
- package/lib/utils/storage/getShiftData/index.js +33 -0
- package/lib/utils/storage/getStaffAuthorizationData/index.js +24 -0
- package/lib/utils/storage/getWorkLogTypesData/index.js +37 -0
- package/lib/utils/storage/index.js +19 -0
- package/lib/utils/userInfo/getUserId/index.js +12 -0
- package/package.json +92 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @janiscommerce/app-tracking-shift
|
package/lib/Formatter.js
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import {isArray, isEmptyArray, isNumber} from './utils/helpers';
|
|
2
|
+
import {INTERNAL_WORKLOGS} from './constant';
|
|
3
|
+
|
|
4
|
+
class Formatter {
|
|
5
|
+
/**
|
|
6
|
+
* Formats shift activities by pairing start and finish events and calculating durations.
|
|
7
|
+
*
|
|
8
|
+
* Processes an array of shift activity events to create structured activity objects
|
|
9
|
+
* with paired start/finish events and calculated durations.
|
|
10
|
+
*
|
|
11
|
+
* @param {Array<{
|
|
12
|
+
* type: string,
|
|
13
|
+
* id: string,
|
|
14
|
+
* time: string,
|
|
15
|
+
* payload: object}>} shiftActivities - Array of shift activity events with start/finish types
|
|
16
|
+
* @returns {Array<{
|
|
17
|
+
* id: string,
|
|
18
|
+
* name: string,
|
|
19
|
+
* type: string,
|
|
20
|
+
* startDate: string,
|
|
21
|
+
* endDate?: string,
|
|
22
|
+
* duration: number
|
|
23
|
+
* }>} Array of formatted activity objects.
|
|
24
|
+
*
|
|
25
|
+
* @property {string} id - Unique identifier for the activity
|
|
26
|
+
* @property {string} name - Activity name extracted from event payload
|
|
27
|
+
* @property {string} type - Activity type extracted from event payload (e.g., 'work', 'pause')
|
|
28
|
+
* @property {string} startDate - ISO timestamp when the activity started
|
|
29
|
+
* @property {string} [endDate] - ISO timestamp when the activity ended (optional, only if finish event exists)
|
|
30
|
+
* @property {number} duration - Duration of the activity in milliseconds (0 if no finish event)
|
|
31
|
+
*/
|
|
32
|
+
static formatShiftActivities(shiftActivities) {
|
|
33
|
+
if (!isArray(shiftActivities) || isEmptyArray(shiftActivities)) return [];
|
|
34
|
+
|
|
35
|
+
const parsedActivities = shiftActivities.reduce((acc, activity, index, activities) => {
|
|
36
|
+
const {type, time, id, payload} = activity || {};
|
|
37
|
+
|
|
38
|
+
if (type !== 'start') return acc;
|
|
39
|
+
|
|
40
|
+
// Buscamos el evento 'finish' correspondiente
|
|
41
|
+
const finishEvent = activities.find(
|
|
42
|
+
(event, eventIndex) => eventIndex > index && event.type === 'finish' && event.id === id
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
let parsedActivity = {
|
|
46
|
+
id,
|
|
47
|
+
name: payload?.name,
|
|
48
|
+
type: payload?.type,
|
|
49
|
+
startDate: time,
|
|
50
|
+
duration: 0,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
if (finishEvent) {
|
|
54
|
+
const startTime = new Date(time);
|
|
55
|
+
const finishTime = new Date(finishEvent?.time);
|
|
56
|
+
const duration = finishTime.getTime() - startTime.getTime();
|
|
57
|
+
|
|
58
|
+
parsedActivity = {
|
|
59
|
+
...parsedActivity,
|
|
60
|
+
endDate: finishEvent.time,
|
|
61
|
+
...(isNumber(duration) && {duration}),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
acc.push(parsedActivity);
|
|
66
|
+
|
|
67
|
+
return acc;
|
|
68
|
+
}, []);
|
|
69
|
+
|
|
70
|
+
return parsedActivities;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Formats work log types by filtering and standardizing the data structure.
|
|
75
|
+
*
|
|
76
|
+
* Processes an array of work log type objects from the API to create standardized
|
|
77
|
+
* work log type objects with consistent structure and default values.
|
|
78
|
+
*
|
|
79
|
+
* @param {Array<Object>} workLogTypes - Array of work log type objects from API
|
|
80
|
+
* @returns {Array<{
|
|
81
|
+
* id: string,
|
|
82
|
+
* referenceId: string,
|
|
83
|
+
* name: string,
|
|
84
|
+
* type: string,
|
|
85
|
+
* description: string,
|
|
86
|
+
* suggestedTime: number
|
|
87
|
+
* }>} Array of formatted work log type objects.
|
|
88
|
+
*
|
|
89
|
+
* @property {string} id - Unique identifier for the work log type
|
|
90
|
+
* @property {string} referenceId - Reference identifier used for API operations
|
|
91
|
+
* @property {string} name - Display name of the work log type
|
|
92
|
+
* @property {string} type - Type classification of the work log (defaults to empty string)
|
|
93
|
+
* @property {string} description - Description of the work log type (defaults to empty string)
|
|
94
|
+
* @property {number} suggestedTime - Suggested duration in minutes (defaults to 0)
|
|
95
|
+
*/
|
|
96
|
+
static formatWorkLogTypes(workLogTypes = []) {
|
|
97
|
+
if (!isArray(workLogTypes) || isEmptyArray(workLogTypes)) return [];
|
|
98
|
+
|
|
99
|
+
const formattedWorkLogTypes = workLogTypes.map((workType) => {
|
|
100
|
+
const {
|
|
101
|
+
id,
|
|
102
|
+
referenceId,
|
|
103
|
+
name,
|
|
104
|
+
description = '',
|
|
105
|
+
type = '',
|
|
106
|
+
suggestedTime = 0,
|
|
107
|
+
} = workType || {};
|
|
108
|
+
|
|
109
|
+
if (!id || !referenceId) return undefined;
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
id,
|
|
113
|
+
referenceId,
|
|
114
|
+
name,
|
|
115
|
+
type,
|
|
116
|
+
description,
|
|
117
|
+
suggestedTime,
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
return formattedWorkLogTypes.filter(Boolean);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
static formatWorkLogId(workLog, id) {
|
|
125
|
+
const workLogMapper = {
|
|
126
|
+
[INTERNAL_WORKLOGS.PICKING_WORK.referenceId]: `picking-${id}`,
|
|
127
|
+
[INTERNAL_WORKLOGS.DELIVERY_WORK.referenceId]: `delivery-${id}`,
|
|
128
|
+
default: id,
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
return workLogMapper[workLog] || workLogMapper.default;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
static formatWorkLogsFromJanis(workLogs = []) {
|
|
135
|
+
if (!isArray(workLogs)) {
|
|
136
|
+
workLogs = [workLogs].filter(Boolean);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (isEmptyArray(workLogs)) return [];
|
|
140
|
+
|
|
141
|
+
return workLogs.map((workLog) => {
|
|
142
|
+
const {id, shiftId, workLogTypeRefId, startDate, endDate, status, workLogTypeName} = workLog;
|
|
143
|
+
|
|
144
|
+
const formattedId = Formatter.formatWorkLogId(workLogTypeRefId, id);
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
id: formattedId,
|
|
148
|
+
shiftId,
|
|
149
|
+
referenceId: workLogTypeRefId,
|
|
150
|
+
startDate,
|
|
151
|
+
endDate,
|
|
152
|
+
status,
|
|
153
|
+
name: workLogTypeName,
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
static splitWorkLogsByStatus(workLogs = []) {
|
|
159
|
+
if (!isArray(workLogs) || isEmptyArray(workLogs)) return [[], []];
|
|
160
|
+
|
|
161
|
+
return workLogs.reduce(
|
|
162
|
+
([openWorkLogs, finishedWorkLogs], workLog) => {
|
|
163
|
+
const {status} = workLog || {};
|
|
164
|
+
|
|
165
|
+
if (status === 'inProgress') {
|
|
166
|
+
openWorkLogs.push(workLog);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (status === 'finished') {
|
|
170
|
+
finishedWorkLogs.push(workLog);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return [openWorkLogs, finishedWorkLogs];
|
|
174
|
+
},
|
|
175
|
+
[[], []]
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Formats offline work logs for sending to the server.
|
|
181
|
+
*
|
|
182
|
+
* @param {Array<Object>} offlineWorkLog - Array of offline work log objects
|
|
183
|
+
* @returns {Array<{
|
|
184
|
+
* workLogTypeRefId: string,
|
|
185
|
+
* startDate: string,
|
|
186
|
+
* endDate: string
|
|
187
|
+
* }>} Array of formatted work log objects for sending to the server.
|
|
188
|
+
*
|
|
189
|
+
* @property {string} workLogTypeRefId - Reference identifier for the work log type
|
|
190
|
+
* @property {string | null} startDate - ISO timestamp when the work log started
|
|
191
|
+
* @property {string | null} endDate - ISO timestamp when the work log ended
|
|
192
|
+
*/
|
|
193
|
+
static formatOfflineWorkLog(offlineWorkLog = []) {
|
|
194
|
+
if (!isArray(offlineWorkLog)) {
|
|
195
|
+
offlineWorkLog = [offlineWorkLog];
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return offlineWorkLog
|
|
199
|
+
.map((workLog) => {
|
|
200
|
+
const {referenceId, startDate, endDate} = workLog || {};
|
|
201
|
+
|
|
202
|
+
if (!referenceId) return null;
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
workLogTypeRefId: referenceId,
|
|
206
|
+
...(startDate && {startDate}),
|
|
207
|
+
...(endDate && {endDate}),
|
|
208
|
+
};
|
|
209
|
+
})
|
|
210
|
+
.filter(Boolean);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export default Formatter;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {OFFLINE_DATA} from './constant';
|
|
2
|
+
import Storage from './db/StorageService';
|
|
3
|
+
import {isArray, isEmptyArray} from './utils/helpers';
|
|
4
|
+
import {setObject, getObject} from './utils/storage';
|
|
5
|
+
|
|
6
|
+
class OfflineData {
|
|
7
|
+
get hasData() {
|
|
8
|
+
const offlineData = getObject(OFFLINE_DATA, {});
|
|
9
|
+
return Object.keys(offlineData).length > 0;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Saves data to the offline data storage.
|
|
14
|
+
*
|
|
15
|
+
* @param {string} storageId - The ID of the storage to save the data to.
|
|
16
|
+
* @param {Object} data - The data to save.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
save(storageId, data) {
|
|
20
|
+
try {
|
|
21
|
+
const offlineData = getObject(OFFLINE_DATA, {});
|
|
22
|
+
offlineData[storageId] = {...offlineData[storageId], ...data};
|
|
23
|
+
setObject(OFFLINE_DATA, offlineData);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
throw new Error(error);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Gets data from the offline data storage.
|
|
31
|
+
*
|
|
32
|
+
* @param {string | Array<string> | null} storageId - The ID of the storage to get the data from.
|
|
33
|
+
* @returns {Array<Object>} The data from the storage.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
get(storageId = null) {
|
|
37
|
+
try {
|
|
38
|
+
const offlineData = getObject(OFFLINE_DATA, {});
|
|
39
|
+
|
|
40
|
+
if (!isArray(storageId)) {
|
|
41
|
+
storageId = [storageId].filter(Boolean);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (isEmptyArray(storageId)) return Object.values(offlineData);
|
|
45
|
+
|
|
46
|
+
return storageId.map((id) => offlineData[id]);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
throw new Error(error);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Deletes data from the offline data storage.
|
|
54
|
+
*
|
|
55
|
+
* @param {string | Array<string>} storageId - The ID of the storage to delete the data from.
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
delete(storageId) {
|
|
59
|
+
try {
|
|
60
|
+
const offlineData = getObject(OFFLINE_DATA, {});
|
|
61
|
+
|
|
62
|
+
if (!isArray(storageId)) {
|
|
63
|
+
storageId = [storageId].filter(Boolean);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (isEmptyArray(storageId)) return;
|
|
67
|
+
|
|
68
|
+
storageId.forEach((id) => {
|
|
69
|
+
delete offlineData[id];
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
setObject(OFFLINE_DATA, offlineData);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
throw new Error(error);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Deletes all data from the offline data storage.
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
deleteAll() {
|
|
83
|
+
try {
|
|
84
|
+
Storage.delete(OFFLINE_DATA);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
throw new Error(error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export default new OfflineData();
|