@optifye/dashboard-core 6.5.8 → 6.5.10
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/dist/index.js +699 -190
- package/dist/index.mjs +699 -190
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -889,40 +889,140 @@ var dashboardService = {
|
|
|
889
889
|
if (hasOutputHourlyData) {
|
|
890
890
|
console.log("Using new output_hourly column for workspace:", data.workspace_name);
|
|
891
891
|
console.log("Raw output_hourly data:", outputHourly);
|
|
892
|
-
const isNightShift = data.shift_id === 1;
|
|
893
|
-
const shiftStart = data.shift_start || (isNightShift ? "22:00" : "06:00");
|
|
894
|
-
const shiftEnd = data.shift_end || (isNightShift ? "06:00" : "14:00");
|
|
892
|
+
const isNightShift = data.shift_id === (shiftConfig.nightShift?.id ?? 1);
|
|
893
|
+
const shiftStart = data.shift_start || (isNightShift ? shiftConfig.nightShift?.startTime || "22:00" : shiftConfig.dayShift?.startTime || "06:00");
|
|
894
|
+
const shiftEnd = data.shift_end || (isNightShift ? shiftConfig.nightShift?.endTime || "06:00" : shiftConfig.dayShift?.endTime || "14:00");
|
|
895
895
|
const startHour = parseInt(shiftStart.split(":")[0]);
|
|
896
896
|
const startMinute = parseInt(shiftStart.split(":")[1] || "0");
|
|
897
897
|
const endHour = parseInt(shiftEnd.split(":")[0]);
|
|
898
898
|
const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
|
|
899
899
|
let shiftDuration = endHour - startHour;
|
|
900
|
-
if (endMinute > startMinute) {
|
|
901
|
-
shiftDuration += 1;
|
|
902
|
-
}
|
|
903
900
|
if (shiftDuration <= 0) {
|
|
904
901
|
shiftDuration += 24;
|
|
905
902
|
}
|
|
903
|
+
const hasPartialLastHour = endMinute > 0 && endMinute < 60;
|
|
904
|
+
const hourCount = hasPartialLastHour ? Math.ceil(shiftDuration + endMinute / 60) : shiftDuration;
|
|
906
905
|
let expectedHours = [];
|
|
907
|
-
for (let i = 0; i <
|
|
906
|
+
for (let i = 0; i < hourCount; i++) {
|
|
908
907
|
expectedHours.push((startHour + i) % 24);
|
|
909
908
|
}
|
|
910
909
|
console.log("Expected shift hours:", expectedHours);
|
|
911
910
|
console.log("Available data hours:", Object.keys(outputHourly));
|
|
912
|
-
hourlyActionCounts = expectedHours.map((expectedHour) => {
|
|
913
|
-
let
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
911
|
+
hourlyActionCounts = expectedHours.map((expectedHour, index) => {
|
|
912
|
+
let hourSum = 0;
|
|
913
|
+
const hourData = outputHourly[expectedHour.toString()] || [];
|
|
914
|
+
if (startMinute > 0) {
|
|
915
|
+
if (index === 0) {
|
|
916
|
+
if (Array.isArray(hourData)) {
|
|
917
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
918
|
+
const val = hourData[i];
|
|
919
|
+
if (val !== "x" && typeof val === "number") {
|
|
920
|
+
hourSum += val;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
925
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
926
|
+
if (Array.isArray(nextHourData)) {
|
|
927
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
928
|
+
const val = nextHourData[i];
|
|
929
|
+
if (val !== "x" && typeof val === "number") {
|
|
930
|
+
hourSum += val;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
} else if (index < expectedHours.length - 1) {
|
|
935
|
+
if (Array.isArray(hourData)) {
|
|
936
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
937
|
+
const val = hourData[i];
|
|
938
|
+
if (val !== "x" && typeof val === "number") {
|
|
939
|
+
hourSum += val;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
944
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
945
|
+
if (Array.isArray(nextHourData)) {
|
|
946
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
947
|
+
const val = nextHourData[i];
|
|
948
|
+
if (val !== "x" && typeof val === "number") {
|
|
949
|
+
hourSum += val;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
} else {
|
|
954
|
+
if (hasPartialLastHour && endMinute > 0) {
|
|
955
|
+
if (startMinute > 0) {
|
|
956
|
+
if (Array.isArray(hourData)) {
|
|
957
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
958
|
+
const val = hourData[i];
|
|
959
|
+
if (val !== "x" && typeof val === "number") {
|
|
960
|
+
hourSum += val;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
965
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
966
|
+
if (Array.isArray(nextHourData)) {
|
|
967
|
+
for (let i = 0; i < endMinute && i < nextHourData.length; i++) {
|
|
968
|
+
const val = nextHourData[i];
|
|
969
|
+
if (val !== "x" && typeof val === "number") {
|
|
970
|
+
hourSum += val;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
} else {
|
|
975
|
+
if (Array.isArray(hourData)) {
|
|
976
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
977
|
+
const val = hourData[i];
|
|
978
|
+
if (val !== "x" && typeof val === "number") {
|
|
979
|
+
hourSum += val;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
} else {
|
|
985
|
+
if (Array.isArray(hourData)) {
|
|
986
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
987
|
+
const val = hourData[i];
|
|
988
|
+
if (val !== "x" && typeof val === "number") {
|
|
989
|
+
hourSum += val;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
994
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
995
|
+
if (Array.isArray(nextHourData)) {
|
|
996
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
997
|
+
const val = nextHourData[i];
|
|
998
|
+
if (val !== "x" && typeof val === "number") {
|
|
999
|
+
hourSum += val;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
} else {
|
|
1006
|
+
if (Array.isArray(hourData)) {
|
|
1007
|
+
hourData.forEach((val) => {
|
|
1008
|
+
if (val !== "x" && typeof val === "number") {
|
|
1009
|
+
hourSum += val;
|
|
1010
|
+
}
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
if (index === expectedHours.length - 1 && hasPartialLastHour && endMinute > 0) {
|
|
1014
|
+
hourSum = 0;
|
|
1015
|
+
if (Array.isArray(hourData)) {
|
|
1016
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
1017
|
+
const val = hourData[i];
|
|
1018
|
+
if (val !== "x" && typeof val === "number") {
|
|
1019
|
+
hourSum += val;
|
|
1020
|
+
}
|
|
921
1021
|
}
|
|
922
1022
|
}
|
|
923
1023
|
}
|
|
924
1024
|
}
|
|
925
|
-
return
|
|
1025
|
+
return hourSum;
|
|
926
1026
|
});
|
|
927
1027
|
console.log("Final hourly action counts:", hourlyActionCounts);
|
|
928
1028
|
} else {
|
|
@@ -2123,136 +2223,142 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
|
|
|
2123
2223
|
const now2 = /* @__PURE__ */ new Date();
|
|
2124
2224
|
const currentHour = now2.getHours();
|
|
2125
2225
|
const currentMinute = now2.getMinutes();
|
|
2126
|
-
|
|
2127
|
-
|
|
2226
|
+
const dayShiftStart = shiftConfig?.dayShift?.startTime || "08:00";
|
|
2227
|
+
const dayShiftEnd = shiftConfig?.dayShift?.endTime || "19:30";
|
|
2228
|
+
const nightShiftStart = shiftConfig?.nightShift?.startTime || "19:30";
|
|
2229
|
+
const nightShiftEnd = shiftConfig?.nightShift?.endTime || "06:00";
|
|
2230
|
+
const parseShiftTime = (timeStr) => {
|
|
2231
|
+
const [hour, minute] = timeStr.split(":").map(Number);
|
|
2232
|
+
return { hour, minute };
|
|
2233
|
+
};
|
|
2234
|
+
let shiftStart, shiftEnd;
|
|
2128
2235
|
if (currentShiftId === 0) {
|
|
2129
|
-
|
|
2130
|
-
|
|
2236
|
+
shiftStart = parseShiftTime(dayShiftStart);
|
|
2237
|
+
shiftEnd = parseShiftTime(dayShiftEnd);
|
|
2131
2238
|
} else {
|
|
2132
|
-
|
|
2133
|
-
|
|
2239
|
+
shiftStart = parseShiftTime(nightShiftStart);
|
|
2240
|
+
shiftEnd = parseShiftTime(nightShiftEnd);
|
|
2134
2241
|
}
|
|
2135
2242
|
let elapsedMinutes = 0;
|
|
2136
2243
|
if (currentShiftId === 0) {
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2244
|
+
const shiftStartTotalMinutes = shiftStart.hour * 60 + shiftStart.minute;
|
|
2245
|
+
const currentTotalMinutes = currentHour * 60 + currentMinute;
|
|
2246
|
+
const shiftEndTotalMinutes = shiftEnd.hour * 60 + shiftEnd.minute;
|
|
2247
|
+
if (currentTotalMinutes >= shiftStartTotalMinutes && currentTotalMinutes < shiftEndTotalMinutes) {
|
|
2248
|
+
elapsedMinutes = currentTotalMinutes - shiftStartTotalMinutes;
|
|
2249
|
+
} else if (currentTotalMinutes >= shiftEndTotalMinutes) {
|
|
2250
|
+
elapsedMinutes = shiftEndTotalMinutes - shiftStartTotalMinutes;
|
|
2141
2251
|
}
|
|
2142
2252
|
} else {
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2253
|
+
const shiftStartTotalMinutes = shiftStart.hour * 60 + shiftStart.minute;
|
|
2254
|
+
const currentTotalMinutes = currentHour * 60 + currentMinute;
|
|
2255
|
+
const shiftEndTotalMinutes = shiftEnd.hour * 60 + shiftEnd.minute;
|
|
2256
|
+
if (currentHour >= shiftStart.hour || currentHour < shiftEnd.hour) {
|
|
2257
|
+
if (currentHour >= shiftStart.hour) {
|
|
2258
|
+
elapsedMinutes = currentTotalMinutes - shiftStartTotalMinutes;
|
|
2259
|
+
} else {
|
|
2260
|
+
elapsedMinutes = 24 * 60 - shiftStartTotalMinutes + currentTotalMinutes;
|
|
2261
|
+
}
|
|
2262
|
+
if (currentHour >= shiftEnd.hour && currentTotalMinutes >= shiftEndTotalMinutes) {
|
|
2263
|
+
const totalShiftMinutes = 24 * 60 - shiftStartTotalMinutes + shiftEndTotalMinutes;
|
|
2264
|
+
elapsedMinutes = Math.min(elapsedMinutes, totalShiftMinutes);
|
|
2265
|
+
}
|
|
2147
2266
|
}
|
|
2148
2267
|
}
|
|
2149
2268
|
const tableName = `performance_metrics_${companyId.replace(/-/g, "_")}`;
|
|
2150
|
-
const query = `
|
|
2151
|
-
WITH workspace_uptime AS (
|
|
2152
|
-
SELECT
|
|
2153
|
-
workspace_id,
|
|
2154
|
-
workspace_display_name,
|
|
2155
|
-
idle_time_hourly,
|
|
2156
|
-
output_hourly,
|
|
2157
|
-
shift_start,
|
|
2158
|
-
shift_end
|
|
2159
|
-
FROM ${tableName}
|
|
2160
|
-
WHERE date = $1::date
|
|
2161
|
-
AND shift_id = $2
|
|
2162
|
-
),
|
|
2163
|
-
calculated_uptime AS (
|
|
2164
|
-
SELECT
|
|
2165
|
-
workspace_id,
|
|
2166
|
-
workspace_display_name,
|
|
2167
|
-
-- Calculate actual minutes from hourly data
|
|
2168
|
-
(
|
|
2169
|
-
SELECT COALESCE(SUM(
|
|
2170
|
-
CASE
|
|
2171
|
-
WHEN jsonb_array_length(idle_time_hourly->key::text) >= 58 THEN 60
|
|
2172
|
-
WHEN jsonb_array_length(idle_time_hourly->key::text) > 0 THEN jsonb_array_length(idle_time_hourly->key::text)
|
|
2173
|
-
ELSE 0
|
|
2174
|
-
END
|
|
2175
|
-
), 0)
|
|
2176
|
-
FROM jsonb_object_keys(idle_time_hourly) AS key
|
|
2177
|
-
WHERE key::int >= $3 AND key::int < $4
|
|
2178
|
-
) +
|
|
2179
|
-
-- Add current hour's data if applicable
|
|
2180
|
-
CASE
|
|
2181
|
-
WHEN $4::int >= $3 AND $4::int < $5 THEN
|
|
2182
|
-
LEAST($6::int,
|
|
2183
|
-
COALESCE(jsonb_array_length(idle_time_hourly->$4::text), 0))
|
|
2184
|
-
ELSE 0
|
|
2185
|
-
END as actual_minutes
|
|
2186
|
-
FROM workspace_uptime
|
|
2187
|
-
)
|
|
2188
|
-
SELECT
|
|
2189
|
-
workspace_id,
|
|
2190
|
-
workspace_display_name,
|
|
2191
|
-
actual_minutes,
|
|
2192
|
-
$7::int as expected_minutes,
|
|
2193
|
-
ROUND(
|
|
2194
|
-
CASE
|
|
2195
|
-
WHEN $7::int > 0 THEN (actual_minutes::numeric / $7::numeric) * 100
|
|
2196
|
-
ELSE 100
|
|
2197
|
-
END, 1
|
|
2198
|
-
) as uptime_percentage
|
|
2199
|
-
FROM calculated_uptime
|
|
2200
|
-
`;
|
|
2201
2269
|
try {
|
|
2202
|
-
const { data, error } = await supabase.
|
|
2203
|
-
query_text: query,
|
|
2204
|
-
params: [
|
|
2205
|
-
currentDate,
|
|
2206
|
-
currentShiftId,
|
|
2207
|
-
shiftStartHour,
|
|
2208
|
-
currentHour,
|
|
2209
|
-
shiftEndHour,
|
|
2210
|
-
currentMinute,
|
|
2211
|
-
elapsedMinutes
|
|
2212
|
-
]
|
|
2213
|
-
}).single();
|
|
2270
|
+
const { data: queryData, error } = await supabase.from(tableName).select("workspace_id, workspace_display_name, output_hourly").eq("date", currentDate).eq("shift_id", currentShiftId);
|
|
2214
2271
|
if (error) {
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2272
|
+
console.error("Error fetching performance metrics:", error);
|
|
2273
|
+
return /* @__PURE__ */ new Map();
|
|
2274
|
+
}
|
|
2275
|
+
const uptimeMap = /* @__PURE__ */ new Map();
|
|
2276
|
+
for (const record of queryData || []) {
|
|
2277
|
+
let actualMinutes = 0;
|
|
2278
|
+
let totalPossibleMinutes = 0;
|
|
2279
|
+
const outputHourly = record.output_hourly || {};
|
|
2280
|
+
const hoursElapsed = Math.ceil(elapsedMinutes / 60);
|
|
2281
|
+
for (let hourIndex = 0; hourIndex < hoursElapsed; hourIndex++) {
|
|
2282
|
+
const actualHour = (shiftStart.hour + hourIndex) % 24;
|
|
2283
|
+
let hourData = [];
|
|
2284
|
+
let minutesInThisHour = 60;
|
|
2285
|
+
if (shiftStart.minute > 0) {
|
|
2286
|
+
if (hourIndex === 0) {
|
|
2287
|
+
const firstHourData = outputHourly[actualHour.toString()] || [];
|
|
2288
|
+
const nextHour = (actualHour + 1) % 24;
|
|
2289
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
2290
|
+
hourData = [
|
|
2291
|
+
...Array.isArray(firstHourData) ? firstHourData.slice(shiftStart.minute) : [],
|
|
2292
|
+
...Array.isArray(nextHourData) ? nextHourData.slice(0, shiftStart.minute) : []
|
|
2293
|
+
];
|
|
2294
|
+
} else if (hourIndex < hoursElapsed - 1) {
|
|
2295
|
+
const currentHourData = outputHourly[actualHour.toString()] || [];
|
|
2296
|
+
const nextHour = (actualHour + 1) % 24;
|
|
2297
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
2298
|
+
hourData = [
|
|
2299
|
+
...Array.isArray(currentHourData) ? currentHourData.slice(shiftStart.minute) : [],
|
|
2300
|
+
...Array.isArray(nextHourData) ? nextHourData.slice(0, shiftStart.minute) : []
|
|
2301
|
+
];
|
|
2302
|
+
} else {
|
|
2303
|
+
const isLastHourPartial = hourIndex === hoursElapsed - 1 && elapsedMinutes % 60 > 0;
|
|
2304
|
+
if (isLastHourPartial) {
|
|
2305
|
+
minutesInThisHour = elapsedMinutes % 60;
|
|
2306
|
+
const currentHourData = outputHourly[actualHour.toString()] || [];
|
|
2307
|
+
if (shiftStart.minute > 0) {
|
|
2308
|
+
const nextHour = (actualHour + 1) % 24;
|
|
2309
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
2310
|
+
const firstPart = Array.isArray(currentHourData) ? currentHourData.slice(shiftStart.minute) : [];
|
|
2311
|
+
const secondPart = Array.isArray(nextHourData) ? nextHourData.slice(0, Math.min(shiftStart.minute, minutesInThisHour)) : [];
|
|
2312
|
+
hourData = [...firstPart, ...secondPart].slice(0, minutesInThisHour);
|
|
2313
|
+
} else {
|
|
2314
|
+
hourData = Array.isArray(currentHourData) ? currentHourData.slice(0, minutesInThisHour) : [];
|
|
2315
|
+
}
|
|
2316
|
+
} else {
|
|
2317
|
+
const currentHourData = outputHourly[actualHour.toString()] || [];
|
|
2318
|
+
const nextHour = (actualHour + 1) % 24;
|
|
2319
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
2320
|
+
hourData = [
|
|
2321
|
+
...Array.isArray(currentHourData) ? currentHourData.slice(shiftStart.minute) : [],
|
|
2322
|
+
...Array.isArray(nextHourData) ? nextHourData.slice(0, shiftStart.minute) : []
|
|
2323
|
+
];
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
} else {
|
|
2327
|
+
hourData = outputHourly[actualHour.toString()] || [];
|
|
2328
|
+
if (hourIndex === hoursElapsed - 1) {
|
|
2329
|
+
const remainingMinutes = elapsedMinutes % 60;
|
|
2330
|
+
if (remainingMinutes > 0) {
|
|
2331
|
+
minutesInThisHour = remainingMinutes;
|
|
2332
|
+
hourData = Array.isArray(hourData) ? hourData.slice(0, minutesInThisHour) : [];
|
|
2233
2333
|
}
|
|
2234
2334
|
}
|
|
2235
2335
|
}
|
|
2236
|
-
const
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
});
|
|
2336
|
+
const hasXArchitecture = Array.isArray(hourData) && hourData.some((val) => val === "x");
|
|
2337
|
+
if (hasXArchitecture) {
|
|
2338
|
+
const xCount = hourData.filter((val) => val === "x").length;
|
|
2339
|
+
if (xCount <= 2) {
|
|
2340
|
+
actualMinutes += minutesInThisHour;
|
|
2341
|
+
} else {
|
|
2342
|
+
const uptimeCount = hourData.filter((val) => val !== "x").length;
|
|
2343
|
+
actualMinutes += Math.min(uptimeCount, minutesInThisHour);
|
|
2344
|
+
}
|
|
2345
|
+
} else {
|
|
2346
|
+
const arrayLength = Array.isArray(hourData) ? hourData.length : 0;
|
|
2347
|
+
if (arrayLength >= Math.min(58, minutesInThisHour - 2)) {
|
|
2348
|
+
actualMinutes += minutesInThisHour;
|
|
2349
|
+
} else {
|
|
2350
|
+
actualMinutes += Math.min(arrayLength, minutesInThisHour);
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
totalPossibleMinutes += minutesInThisHour;
|
|
2255
2354
|
}
|
|
2355
|
+
const percentage = totalPossibleMinutes > 0 ? Math.round(actualMinutes / totalPossibleMinutes * 1e3) / 10 : 100;
|
|
2356
|
+
uptimeMap.set(record.workspace_id, {
|
|
2357
|
+
expectedMinutes: totalPossibleMinutes,
|
|
2358
|
+
actualMinutes,
|
|
2359
|
+
percentage,
|
|
2360
|
+
lastCalculated: (/* @__PURE__ */ new Date()).toISOString()
|
|
2361
|
+
});
|
|
2256
2362
|
}
|
|
2257
2363
|
return uptimeMap;
|
|
2258
2364
|
} catch (error) {
|
|
@@ -5703,39 +5809,139 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
5703
5809
|
console.log("Using new output_hourly column for workspace (fallback):", recentData.workspace_name);
|
|
5704
5810
|
console.log("Raw output_hourly data (fallback):", outputHourly2);
|
|
5705
5811
|
const isNightShift = recentData.shift_id === 1;
|
|
5706
|
-
const shiftStart = recentData.shift_start || (isNightShift ? "22:00" : "06:00");
|
|
5707
|
-
const shiftEnd = recentData.shift_end || (isNightShift ? "06:00" : "14:00");
|
|
5812
|
+
const shiftStart = recentData.shift_start || (isNightShift ? shiftConfig.nightShift?.startTime || "22:00" : shiftConfig.dayShift?.startTime || "06:00");
|
|
5813
|
+
const shiftEnd = recentData.shift_end || (isNightShift ? shiftConfig.nightShift?.endTime || "06:00" : shiftConfig.dayShift?.endTime || "14:00");
|
|
5708
5814
|
const startHour = parseInt(shiftStart.split(":")[0]);
|
|
5709
5815
|
const startMinute = parseInt(shiftStart.split(":")[1] || "0");
|
|
5710
5816
|
const endHour = parseInt(shiftEnd.split(":")[0]);
|
|
5711
5817
|
const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
|
|
5712
5818
|
let shiftDuration = endHour - startHour;
|
|
5713
|
-
if (endMinute > startMinute) {
|
|
5714
|
-
shiftDuration += 1;
|
|
5715
|
-
}
|
|
5716
5819
|
if (shiftDuration <= 0) {
|
|
5717
5820
|
shiftDuration += 24;
|
|
5718
5821
|
}
|
|
5822
|
+
const hasPartialLastHour = endMinute > 0 && endMinute < 60;
|
|
5823
|
+
const hourCount = hasPartialLastHour ? Math.ceil(shiftDuration + endMinute / 60) : shiftDuration;
|
|
5719
5824
|
let expectedHours = [];
|
|
5720
|
-
for (let i = 0; i <
|
|
5825
|
+
for (let i = 0; i < hourCount; i++) {
|
|
5721
5826
|
expectedHours.push((startHour + i) % 24);
|
|
5722
5827
|
}
|
|
5723
5828
|
console.log("Expected shift hours (fallback):", expectedHours);
|
|
5724
5829
|
console.log("Available data hours (fallback):", Object.keys(outputHourly2));
|
|
5725
|
-
hourlyActionCounts2 = expectedHours.map((expectedHour) => {
|
|
5726
|
-
let
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5830
|
+
hourlyActionCounts2 = expectedHours.map((expectedHour, index) => {
|
|
5831
|
+
let hourSum = 0;
|
|
5832
|
+
const hourData = outputHourly2[expectedHour.toString()] || [];
|
|
5833
|
+
if (startMinute > 0) {
|
|
5834
|
+
if (index === 0) {
|
|
5835
|
+
if (Array.isArray(hourData)) {
|
|
5836
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
5837
|
+
const val = hourData[i];
|
|
5838
|
+
if (val !== "x" && typeof val === "number") {
|
|
5839
|
+
hourSum += val;
|
|
5840
|
+
}
|
|
5841
|
+
}
|
|
5842
|
+
}
|
|
5843
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
5844
|
+
const nextHourData = outputHourly2[nextHour.toString()] || [];
|
|
5845
|
+
if (Array.isArray(nextHourData)) {
|
|
5846
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
5847
|
+
const val = nextHourData[i];
|
|
5848
|
+
if (val !== "x" && typeof val === "number") {
|
|
5849
|
+
hourSum += val;
|
|
5850
|
+
}
|
|
5851
|
+
}
|
|
5852
|
+
}
|
|
5853
|
+
} else if (index < expectedHours.length - 1) {
|
|
5854
|
+
if (Array.isArray(hourData)) {
|
|
5855
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
5856
|
+
const val = hourData[i];
|
|
5857
|
+
if (val !== "x" && typeof val === "number") {
|
|
5858
|
+
hourSum += val;
|
|
5859
|
+
}
|
|
5860
|
+
}
|
|
5861
|
+
}
|
|
5862
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
5863
|
+
const nextHourData = outputHourly2[nextHour.toString()] || [];
|
|
5864
|
+
if (Array.isArray(nextHourData)) {
|
|
5865
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
5866
|
+
const val = nextHourData[i];
|
|
5867
|
+
if (val !== "x" && typeof val === "number") {
|
|
5868
|
+
hourSum += val;
|
|
5869
|
+
}
|
|
5870
|
+
}
|
|
5871
|
+
}
|
|
5872
|
+
} else {
|
|
5873
|
+
if (hasPartialLastHour && endMinute > 0) {
|
|
5874
|
+
if (startMinute > 0) {
|
|
5875
|
+
if (Array.isArray(hourData)) {
|
|
5876
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
5877
|
+
const val = hourData[i];
|
|
5878
|
+
if (val !== "x" && typeof val === "number") {
|
|
5879
|
+
hourSum += val;
|
|
5880
|
+
}
|
|
5881
|
+
}
|
|
5882
|
+
}
|
|
5883
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
5884
|
+
const nextHourData = outputHourly2[nextHour.toString()] || [];
|
|
5885
|
+
if (Array.isArray(nextHourData)) {
|
|
5886
|
+
for (let i = 0; i < endMinute && i < nextHourData.length; i++) {
|
|
5887
|
+
const val = nextHourData[i];
|
|
5888
|
+
if (val !== "x" && typeof val === "number") {
|
|
5889
|
+
hourSum += val;
|
|
5890
|
+
}
|
|
5891
|
+
}
|
|
5892
|
+
}
|
|
5893
|
+
} else {
|
|
5894
|
+
if (Array.isArray(hourData)) {
|
|
5895
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
5896
|
+
const val = hourData[i];
|
|
5897
|
+
if (val !== "x" && typeof val === "number") {
|
|
5898
|
+
hourSum += val;
|
|
5899
|
+
}
|
|
5900
|
+
}
|
|
5901
|
+
}
|
|
5902
|
+
}
|
|
5903
|
+
} else {
|
|
5904
|
+
if (Array.isArray(hourData)) {
|
|
5905
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
5906
|
+
const val = hourData[i];
|
|
5907
|
+
if (val !== "x" && typeof val === "number") {
|
|
5908
|
+
hourSum += val;
|
|
5909
|
+
}
|
|
5910
|
+
}
|
|
5911
|
+
}
|
|
5912
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
5913
|
+
const nextHourData = outputHourly2[nextHour.toString()] || [];
|
|
5914
|
+
if (Array.isArray(nextHourData)) {
|
|
5915
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
5916
|
+
const val = nextHourData[i];
|
|
5917
|
+
if (val !== "x" && typeof val === "number") {
|
|
5918
|
+
hourSum += val;
|
|
5919
|
+
}
|
|
5920
|
+
}
|
|
5921
|
+
}
|
|
5922
|
+
}
|
|
5923
|
+
}
|
|
5924
|
+
} else {
|
|
5925
|
+
if (Array.isArray(hourData)) {
|
|
5926
|
+
hourData.forEach((val) => {
|
|
5927
|
+
if (val !== "x" && typeof val === "number") {
|
|
5928
|
+
hourSum += val;
|
|
5929
|
+
}
|
|
5930
|
+
});
|
|
5931
|
+
}
|
|
5932
|
+
if (index === expectedHours.length - 1 && hasPartialLastHour && endMinute > 0) {
|
|
5933
|
+
hourSum = 0;
|
|
5934
|
+
if (Array.isArray(hourData)) {
|
|
5935
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
5936
|
+
const val = hourData[i];
|
|
5937
|
+
if (val !== "x" && typeof val === "number") {
|
|
5938
|
+
hourSum += val;
|
|
5939
|
+
}
|
|
5734
5940
|
}
|
|
5735
5941
|
}
|
|
5736
5942
|
}
|
|
5737
5943
|
}
|
|
5738
|
-
return
|
|
5944
|
+
return hourSum;
|
|
5739
5945
|
});
|
|
5740
5946
|
console.log("Final hourly action counts (fallback):", hourlyActionCounts2);
|
|
5741
5947
|
} else {
|
|
@@ -5762,8 +5968,8 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
5762
5968
|
date: recentData.date,
|
|
5763
5969
|
shift_id: recentData.shift_id,
|
|
5764
5970
|
action_name: recentData.action_name || "",
|
|
5765
|
-
shift_start: recentData.shift_start || "06:00",
|
|
5766
|
-
shift_end: recentData.shift_end || "14:00",
|
|
5971
|
+
shift_start: recentData.shift_start || (recentData.shift_id === 1 ? shiftConfig.nightShift?.startTime || "22:00" : shiftConfig.dayShift?.startTime || "06:00"),
|
|
5972
|
+
shift_end: recentData.shift_end || (recentData.shift_id === 1 ? shiftConfig.nightShift?.endTime || "06:00" : shiftConfig.dayShift?.endTime || "14:00"),
|
|
5767
5973
|
shift_type: recentData.shift_type || (recentData.shift_id === 0 ? "Day" : "Night"),
|
|
5768
5974
|
pph_threshold: recentData.pph_threshold || 0,
|
|
5769
5975
|
target_output: recentData.total_day_output || 0,
|
|
@@ -5819,39 +6025,139 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
5819
6025
|
console.log("\u2705 Using new output_hourly column for workspace:", data.workspace_name);
|
|
5820
6026
|
console.log("Raw output_hourly data:", JSON.stringify(outputHourly));
|
|
5821
6027
|
const isNightShift = data.shift_id === 1;
|
|
5822
|
-
const shiftStart = data.shift_start || (isNightShift ? "22:00" : "06:00");
|
|
5823
|
-
const shiftEnd = data.shift_end || (isNightShift ? "06:00" : "14:00");
|
|
6028
|
+
const shiftStart = data.shift_start || (isNightShift ? shiftConfig.nightShift?.startTime || "22:00" : shiftConfig.dayShift?.startTime || "06:00");
|
|
6029
|
+
const shiftEnd = data.shift_end || (isNightShift ? shiftConfig.nightShift?.endTime || "06:00" : shiftConfig.dayShift?.endTime || "14:00");
|
|
5824
6030
|
const startHour = parseInt(shiftStart.split(":")[0]);
|
|
5825
6031
|
const startMinute = parseInt(shiftStart.split(":")[1] || "0");
|
|
5826
6032
|
const endHour = parseInt(shiftEnd.split(":")[0]);
|
|
5827
6033
|
const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
|
|
5828
6034
|
let shiftDuration = endHour - startHour;
|
|
5829
|
-
if (endMinute > startMinute) {
|
|
5830
|
-
shiftDuration += 1;
|
|
5831
|
-
}
|
|
5832
6035
|
if (shiftDuration <= 0) {
|
|
5833
6036
|
shiftDuration += 24;
|
|
5834
6037
|
}
|
|
6038
|
+
const hasPartialLastHour = endMinute > 0 && endMinute < 60;
|
|
6039
|
+
const hourCount = hasPartialLastHour ? Math.ceil(shiftDuration + endMinute / 60) : shiftDuration;
|
|
5835
6040
|
let expectedHours = [];
|
|
5836
|
-
for (let i = 0; i <
|
|
6041
|
+
for (let i = 0; i < hourCount; i++) {
|
|
5837
6042
|
expectedHours.push((startHour + i) % 24);
|
|
5838
6043
|
}
|
|
5839
6044
|
console.log("Expected shift hours:", expectedHours);
|
|
5840
6045
|
console.log("Available data hours:", Object.keys(outputHourly));
|
|
5841
|
-
hourlyActionCounts = expectedHours.map((expectedHour) => {
|
|
5842
|
-
let
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
6046
|
+
hourlyActionCounts = expectedHours.map((expectedHour, index) => {
|
|
6047
|
+
let hourSum = 0;
|
|
6048
|
+
const hourData = outputHourly[expectedHour.toString()] || [];
|
|
6049
|
+
if (startMinute > 0) {
|
|
6050
|
+
if (index === 0) {
|
|
6051
|
+
if (Array.isArray(hourData)) {
|
|
6052
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
6053
|
+
const val = hourData[i];
|
|
6054
|
+
if (val !== "x" && typeof val === "number") {
|
|
6055
|
+
hourSum += val;
|
|
6056
|
+
}
|
|
6057
|
+
}
|
|
6058
|
+
}
|
|
6059
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
6060
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
6061
|
+
if (Array.isArray(nextHourData)) {
|
|
6062
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
6063
|
+
const val = nextHourData[i];
|
|
6064
|
+
if (val !== "x" && typeof val === "number") {
|
|
6065
|
+
hourSum += val;
|
|
6066
|
+
}
|
|
6067
|
+
}
|
|
6068
|
+
}
|
|
6069
|
+
} else if (index < expectedHours.length - 1) {
|
|
6070
|
+
if (Array.isArray(hourData)) {
|
|
6071
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
6072
|
+
const val = hourData[i];
|
|
6073
|
+
if (val !== "x" && typeof val === "number") {
|
|
6074
|
+
hourSum += val;
|
|
6075
|
+
}
|
|
6076
|
+
}
|
|
6077
|
+
}
|
|
6078
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
6079
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
6080
|
+
if (Array.isArray(nextHourData)) {
|
|
6081
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
6082
|
+
const val = nextHourData[i];
|
|
6083
|
+
if (val !== "x" && typeof val === "number") {
|
|
6084
|
+
hourSum += val;
|
|
6085
|
+
}
|
|
6086
|
+
}
|
|
6087
|
+
}
|
|
6088
|
+
} else {
|
|
6089
|
+
if (hasPartialLastHour && endMinute > 0) {
|
|
6090
|
+
if (startMinute > 0) {
|
|
6091
|
+
if (Array.isArray(hourData)) {
|
|
6092
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
6093
|
+
const val = hourData[i];
|
|
6094
|
+
if (val !== "x" && typeof val === "number") {
|
|
6095
|
+
hourSum += val;
|
|
6096
|
+
}
|
|
6097
|
+
}
|
|
6098
|
+
}
|
|
6099
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
6100
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
6101
|
+
if (Array.isArray(nextHourData)) {
|
|
6102
|
+
for (let i = 0; i < endMinute && i < nextHourData.length; i++) {
|
|
6103
|
+
const val = nextHourData[i];
|
|
6104
|
+
if (val !== "x" && typeof val === "number") {
|
|
6105
|
+
hourSum += val;
|
|
6106
|
+
}
|
|
6107
|
+
}
|
|
6108
|
+
}
|
|
6109
|
+
} else {
|
|
6110
|
+
if (Array.isArray(hourData)) {
|
|
6111
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
6112
|
+
const val = hourData[i];
|
|
6113
|
+
if (val !== "x" && typeof val === "number") {
|
|
6114
|
+
hourSum += val;
|
|
6115
|
+
}
|
|
6116
|
+
}
|
|
6117
|
+
}
|
|
6118
|
+
}
|
|
6119
|
+
} else {
|
|
6120
|
+
if (Array.isArray(hourData)) {
|
|
6121
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
6122
|
+
const val = hourData[i];
|
|
6123
|
+
if (val !== "x" && typeof val === "number") {
|
|
6124
|
+
hourSum += val;
|
|
6125
|
+
}
|
|
6126
|
+
}
|
|
6127
|
+
}
|
|
6128
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
6129
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
6130
|
+
if (Array.isArray(nextHourData)) {
|
|
6131
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
6132
|
+
const val = nextHourData[i];
|
|
6133
|
+
if (val !== "x" && typeof val === "number") {
|
|
6134
|
+
hourSum += val;
|
|
6135
|
+
}
|
|
6136
|
+
}
|
|
6137
|
+
}
|
|
6138
|
+
}
|
|
6139
|
+
}
|
|
6140
|
+
} else {
|
|
6141
|
+
if (Array.isArray(hourData)) {
|
|
6142
|
+
hourData.forEach((val) => {
|
|
6143
|
+
if (val !== "x" && typeof val === "number") {
|
|
6144
|
+
hourSum += val;
|
|
6145
|
+
}
|
|
6146
|
+
});
|
|
6147
|
+
}
|
|
6148
|
+
if (index === expectedHours.length - 1 && hasPartialLastHour && endMinute > 0) {
|
|
6149
|
+
hourSum = 0;
|
|
6150
|
+
if (Array.isArray(hourData)) {
|
|
6151
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
6152
|
+
const val = hourData[i];
|
|
6153
|
+
if (val !== "x" && typeof val === "number") {
|
|
6154
|
+
hourSum += val;
|
|
6155
|
+
}
|
|
5850
6156
|
}
|
|
5851
6157
|
}
|
|
5852
6158
|
}
|
|
5853
6159
|
}
|
|
5854
|
-
return
|
|
6160
|
+
return hourSum;
|
|
5855
6161
|
});
|
|
5856
6162
|
console.log("Final hourly action counts:", hourlyActionCounts);
|
|
5857
6163
|
} else {
|
|
@@ -5881,8 +6187,8 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
5881
6187
|
date: data.date,
|
|
5882
6188
|
shift_id: data.shift_id,
|
|
5883
6189
|
action_name: data.action_name || "",
|
|
5884
|
-
shift_start: data.shift_start || "06:00",
|
|
5885
|
-
shift_end: data.shift_end || "14:00",
|
|
6190
|
+
shift_start: data.shift_start || (data.shift_id === 1 ? shiftConfig.nightShift?.startTime || "22:00" : shiftConfig.dayShift?.startTime || "06:00"),
|
|
6191
|
+
shift_end: data.shift_end || (data.shift_id === 1 ? shiftConfig.nightShift?.endTime || "06:00" : shiftConfig.dayShift?.endTime || "14:00"),
|
|
5886
6192
|
shift_type: data.shift_type || (data.shift_id === 0 ? "Day" : "Night"),
|
|
5887
6193
|
pph_threshold: data.pph_threshold || 0,
|
|
5888
6194
|
target_output: data.total_day_output || 0,
|
|
@@ -21273,18 +21579,41 @@ var HourlyOutputChartComponent = ({
|
|
|
21273
21579
|
return { hour, minute, decimalHour };
|
|
21274
21580
|
};
|
|
21275
21581
|
const shiftStartTime = getTimeFromTimeString(shiftStart);
|
|
21276
|
-
const
|
|
21582
|
+
const { shiftDuration, shiftEndTime, hasPartialLastHour } = React19__namespace.default.useMemo(() => {
|
|
21583
|
+
console.log("[HourlyOutputChart] Calculating shift duration with:", {
|
|
21584
|
+
shiftStart,
|
|
21585
|
+
shiftEnd,
|
|
21586
|
+
shiftStartTime
|
|
21587
|
+
});
|
|
21277
21588
|
if (!shiftEnd) {
|
|
21278
|
-
|
|
21589
|
+
console.log("[HourlyOutputChart] No shiftEnd provided, using default 11 hours");
|
|
21590
|
+
return {
|
|
21591
|
+
shiftDuration: 11,
|
|
21592
|
+
shiftEndTime: null,
|
|
21593
|
+
hasPartialLastHour: false
|
|
21594
|
+
};
|
|
21279
21595
|
}
|
|
21280
21596
|
const endTime = getTimeFromTimeString(shiftEnd);
|
|
21281
21597
|
let duration = endTime.decimalHour - shiftStartTime.decimalHour;
|
|
21282
21598
|
if (duration <= 0) {
|
|
21283
21599
|
duration += 24;
|
|
21284
21600
|
}
|
|
21285
|
-
|
|
21601
|
+
const hasPartial = endTime.minute > 0 && endTime.minute < 60;
|
|
21602
|
+
const hourCount = hasPartial ? Math.ceil(duration) : Math.round(duration);
|
|
21603
|
+
console.log("[HourlyOutputChart] Shift calculation results:", {
|
|
21604
|
+
endTime,
|
|
21605
|
+
duration,
|
|
21606
|
+
hasPartial,
|
|
21607
|
+
hourCount
|
|
21608
|
+
});
|
|
21609
|
+
return {
|
|
21610
|
+
shiftDuration: hourCount,
|
|
21611
|
+
shiftEndTime: endTime,
|
|
21612
|
+
hasPartialLastHour: hasPartial
|
|
21613
|
+
};
|
|
21286
21614
|
}, [shiftEnd, shiftStartTime.decimalHour]);
|
|
21287
|
-
const SHIFT_DURATION =
|
|
21615
|
+
const SHIFT_DURATION = shiftDuration;
|
|
21616
|
+
shiftEndTime ? shiftEndTime.hour : (shiftStartTime.hour + SHIFT_DURATION) % 24;
|
|
21288
21617
|
const [animatedData, setAnimatedData] = React19__namespace.default.useState(
|
|
21289
21618
|
() => Array(SHIFT_DURATION).fill(0)
|
|
21290
21619
|
);
|
|
@@ -21395,12 +21724,19 @@ var HourlyOutputChartComponent = ({
|
|
|
21395
21724
|
};
|
|
21396
21725
|
}, []);
|
|
21397
21726
|
const formatHour = React19__namespace.default.useCallback((hourIndex) => {
|
|
21727
|
+
const isLastHour = hourIndex === SHIFT_DURATION - 1;
|
|
21398
21728
|
const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
|
|
21399
21729
|
const startHour = Math.floor(startDecimalHour) % 24;
|
|
21400
21730
|
const startMinute = Math.round(startDecimalHour % 1 * 60);
|
|
21401
|
-
|
|
21402
|
-
|
|
21403
|
-
|
|
21731
|
+
let endHour, endMinute;
|
|
21732
|
+
if (isLastHour && shiftEndTime) {
|
|
21733
|
+
endHour = shiftEndTime.hour;
|
|
21734
|
+
endMinute = shiftEndTime.minute;
|
|
21735
|
+
} else {
|
|
21736
|
+
const endDecimalHour = startDecimalHour + 1;
|
|
21737
|
+
endHour = Math.floor(endDecimalHour) % 24;
|
|
21738
|
+
endMinute = Math.round(endDecimalHour % 1 * 60);
|
|
21739
|
+
}
|
|
21404
21740
|
const formatTime3 = (h, m) => {
|
|
21405
21741
|
const period = h >= 12 ? "PM" : "AM";
|
|
21406
21742
|
const hour12 = h === 0 ? 12 : h > 12 ? h - 12 : h;
|
|
@@ -21410,26 +21746,85 @@ var HourlyOutputChartComponent = ({
|
|
|
21410
21746
|
return `${hour12}:${m.toString().padStart(2, "0")}${period}`;
|
|
21411
21747
|
};
|
|
21412
21748
|
return `${formatTime3(startHour, startMinute)}-${formatTime3(endHour, endMinute)}`;
|
|
21413
|
-
}, [shiftStartTime.decimalHour]);
|
|
21749
|
+
}, [shiftStartTime.decimalHour, SHIFT_DURATION, shiftEndTime]);
|
|
21414
21750
|
const formatTimeRange = React19__namespace.default.useCallback((hourIndex) => {
|
|
21751
|
+
const isLastHour = hourIndex === SHIFT_DURATION - 1;
|
|
21415
21752
|
const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
|
|
21416
21753
|
const startHour = Math.floor(startDecimalHour) % 24;
|
|
21417
21754
|
const startMinute = Math.round(startDecimalHour % 1 * 60);
|
|
21418
|
-
|
|
21419
|
-
|
|
21420
|
-
|
|
21755
|
+
let endHour, endMinute;
|
|
21756
|
+
if (isLastHour && shiftEndTime) {
|
|
21757
|
+
endHour = shiftEndTime.hour;
|
|
21758
|
+
endMinute = shiftEndTime.minute;
|
|
21759
|
+
} else {
|
|
21760
|
+
const endDecimalHour = startDecimalHour + 1;
|
|
21761
|
+
endHour = Math.floor(endDecimalHour) % 24;
|
|
21762
|
+
endMinute = Math.round(endDecimalHour % 1 * 60);
|
|
21763
|
+
}
|
|
21421
21764
|
const formatTime3 = (h, m) => {
|
|
21422
21765
|
const period = h >= 12 ? "PM" : "AM";
|
|
21423
21766
|
const hour12 = h === 0 ? 12 : h > 12 ? h - 12 : h;
|
|
21424
21767
|
return `${hour12}:${m.toString().padStart(2, "0")} ${period}`;
|
|
21425
21768
|
};
|
|
21426
21769
|
return `${formatTime3(startHour, startMinute)} - ${formatTime3(endHour, endMinute)}`;
|
|
21427
|
-
}, [shiftStartTime.decimalHour]);
|
|
21770
|
+
}, [shiftStartTime.decimalHour, SHIFT_DURATION, shiftEndTime]);
|
|
21428
21771
|
const chartData = React19__namespace.default.useMemo(() => {
|
|
21429
21772
|
return Array.from({ length: SHIFT_DURATION }, (_, i) => {
|
|
21430
21773
|
const actualHour = (shiftStartTime.hour + i) % 24;
|
|
21431
|
-
const
|
|
21432
|
-
|
|
21774
|
+
const startMinute = shiftStartTime.minute;
|
|
21775
|
+
let idleArray = [];
|
|
21776
|
+
let idleMinutes = 0;
|
|
21777
|
+
if (idleTimeHourly) {
|
|
21778
|
+
if (startMinute > 0) {
|
|
21779
|
+
if (i === 0) {
|
|
21780
|
+
const firstHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
21781
|
+
const nextHour = (actualHour + 1) % 24;
|
|
21782
|
+
const nextHourData = idleTimeHourly[nextHour.toString()] || [];
|
|
21783
|
+
idleArray = [
|
|
21784
|
+
...firstHourData.slice(startMinute) || [],
|
|
21785
|
+
...nextHourData.slice(0, startMinute) || []
|
|
21786
|
+
];
|
|
21787
|
+
} else if (i < SHIFT_DURATION - 1) {
|
|
21788
|
+
const currentHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
21789
|
+
const nextHour = (actualHour + 1) % 24;
|
|
21790
|
+
const nextHourData = idleTimeHourly[nextHour.toString()] || [];
|
|
21791
|
+
idleArray = [
|
|
21792
|
+
...currentHourData.slice(startMinute) || [],
|
|
21793
|
+
...nextHourData.slice(0, startMinute) || []
|
|
21794
|
+
];
|
|
21795
|
+
} else {
|
|
21796
|
+
const hasPartialLastHour2 = shiftEndTime && shiftEndTime.minute > 0 && shiftEndTime.minute < 60;
|
|
21797
|
+
if (hasPartialLastHour2) {
|
|
21798
|
+
const currentHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
21799
|
+
const nextHour = (actualHour + 1) % 24;
|
|
21800
|
+
const nextHourData = idleTimeHourly[nextHour.toString()] || [];
|
|
21801
|
+
if (startMinute > 0) {
|
|
21802
|
+
const firstPart = currentHourData.slice(startMinute) || [];
|
|
21803
|
+
const secondPart = nextHourData.slice(0, shiftEndTime.minute) || [];
|
|
21804
|
+
idleArray = [...firstPart, ...secondPart];
|
|
21805
|
+
} else {
|
|
21806
|
+
idleArray = currentHourData.slice(0, shiftEndTime.minute) || [];
|
|
21807
|
+
}
|
|
21808
|
+
} else {
|
|
21809
|
+
const currentHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
21810
|
+
const nextHour = (actualHour + 1) % 24;
|
|
21811
|
+
const nextHourData = idleTimeHourly[nextHour.toString()] || [];
|
|
21812
|
+
idleArray = [
|
|
21813
|
+
...currentHourData.slice(startMinute) || [],
|
|
21814
|
+
...nextHourData.slice(0, startMinute) || []
|
|
21815
|
+
];
|
|
21816
|
+
}
|
|
21817
|
+
}
|
|
21818
|
+
} else {
|
|
21819
|
+
const currentHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
21820
|
+
if (i === SHIFT_DURATION - 1 && shiftEndTime && shiftEndTime.minute > 0 && shiftEndTime.minute < 60) {
|
|
21821
|
+
idleArray = currentHourData.slice(0, shiftEndTime.minute) || [];
|
|
21822
|
+
} else {
|
|
21823
|
+
idleArray = currentHourData || [];
|
|
21824
|
+
}
|
|
21825
|
+
}
|
|
21826
|
+
}
|
|
21827
|
+
idleMinutes = idleArray.filter((val) => val === "1" || val === 1).length;
|
|
21433
21828
|
return {
|
|
21434
21829
|
hour: formatHour(i),
|
|
21435
21830
|
timeRange: formatTimeRange(i),
|
|
@@ -21441,7 +21836,7 @@ var HourlyOutputChartComponent = ({
|
|
|
21441
21836
|
idleArray
|
|
21442
21837
|
};
|
|
21443
21838
|
});
|
|
21444
|
-
}, [animatedData, data, pphThreshold, idleTimeHourly, shiftStartTime.hour, formatHour, formatTimeRange]);
|
|
21839
|
+
}, [animatedData, data, pphThreshold, idleTimeHourly, shiftStartTime.hour, shiftStartTime.minute, shiftEndTime, formatHour, formatTimeRange, SHIFT_DURATION]);
|
|
21445
21840
|
const IdleBar = React19__namespace.default.useMemo(() => {
|
|
21446
21841
|
if (!idleBarState.visible) return null;
|
|
21447
21842
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -21601,13 +21996,13 @@ var HourlyOutputChartComponent = ({
|
|
|
21601
21996
|
if (showIdleTime && data2.idleArray) {
|
|
21602
21997
|
let currentRange = null;
|
|
21603
21998
|
data2.idleArray.forEach((val, idx) => {
|
|
21604
|
-
if (val === "1") {
|
|
21999
|
+
if (val === "1" || val === 1) {
|
|
21605
22000
|
if (!currentRange) {
|
|
21606
22001
|
currentRange = { start: idx, end: idx };
|
|
21607
22002
|
} else {
|
|
21608
22003
|
currentRange.end = idx;
|
|
21609
22004
|
}
|
|
21610
|
-
} else if (currentRange) {
|
|
22005
|
+
} else if (val !== "x" && currentRange) {
|
|
21611
22006
|
idleRanges.push(currentRange);
|
|
21612
22007
|
currentRange = null;
|
|
21613
22008
|
}
|
|
@@ -34149,21 +34544,135 @@ var KPIDetailView = ({
|
|
|
34149
34544
|
const shiftStart = metrics2.shift_start || (isNightShift ? "22:00" : "06:00");
|
|
34150
34545
|
const shiftEnd = metrics2.shift_end || (isNightShift ? "06:00" : "14:00");
|
|
34151
34546
|
const startHour = parseInt(shiftStart.split(":")[0]);
|
|
34547
|
+
const startMinute = parseInt(shiftStart.split(":")[1] || "0");
|
|
34152
34548
|
const endHour = parseInt(shiftEnd.split(":")[0]);
|
|
34549
|
+
const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
|
|
34153
34550
|
let shiftDuration = endHour - startHour;
|
|
34154
34551
|
if (shiftDuration <= 0) {
|
|
34155
34552
|
shiftDuration += 24;
|
|
34156
34553
|
}
|
|
34554
|
+
const hasPartialLastHour = endMinute > 0 && endMinute < 60;
|
|
34555
|
+
const hourCount = hasPartialLastHour ? Math.ceil(shiftDuration + endMinute / 60) : shiftDuration;
|
|
34157
34556
|
let expectedHours = [];
|
|
34158
|
-
for (let i = 0; i <
|
|
34557
|
+
for (let i = 0; i < hourCount; i++) {
|
|
34159
34558
|
expectedHours.push((startHour + i) % 24);
|
|
34160
34559
|
}
|
|
34161
|
-
return expectedHours.map((
|
|
34162
|
-
|
|
34163
|
-
|
|
34164
|
-
|
|
34560
|
+
return expectedHours.map((expectedHour, index) => {
|
|
34561
|
+
let hourSum = 0;
|
|
34562
|
+
const outputHourly = metrics2.output_hourly;
|
|
34563
|
+
const hourData = outputHourly[expectedHour.toString()] || [];
|
|
34564
|
+
if (startMinute > 0) {
|
|
34565
|
+
if (index === 0) {
|
|
34566
|
+
if (Array.isArray(hourData)) {
|
|
34567
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
34568
|
+
const val = hourData[i];
|
|
34569
|
+
if (val !== "x" && typeof val === "number") {
|
|
34570
|
+
hourSum += val;
|
|
34571
|
+
}
|
|
34572
|
+
}
|
|
34573
|
+
}
|
|
34574
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
34575
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
34576
|
+
if (Array.isArray(nextHourData)) {
|
|
34577
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
34578
|
+
const val = nextHourData[i];
|
|
34579
|
+
if (val !== "x" && typeof val === "number") {
|
|
34580
|
+
hourSum += val;
|
|
34581
|
+
}
|
|
34582
|
+
}
|
|
34583
|
+
}
|
|
34584
|
+
} else if (index < expectedHours.length - 1) {
|
|
34585
|
+
if (Array.isArray(hourData)) {
|
|
34586
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
34587
|
+
const val = hourData[i];
|
|
34588
|
+
if (val !== "x" && typeof val === "number") {
|
|
34589
|
+
hourSum += val;
|
|
34590
|
+
}
|
|
34591
|
+
}
|
|
34592
|
+
}
|
|
34593
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
34594
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
34595
|
+
if (Array.isArray(nextHourData)) {
|
|
34596
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
34597
|
+
const val = nextHourData[i];
|
|
34598
|
+
if (val !== "x" && typeof val === "number") {
|
|
34599
|
+
hourSum += val;
|
|
34600
|
+
}
|
|
34601
|
+
}
|
|
34602
|
+
}
|
|
34603
|
+
} else {
|
|
34604
|
+
if (hasPartialLastHour && endMinute > 0) {
|
|
34605
|
+
if (startMinute > 0) {
|
|
34606
|
+
if (Array.isArray(hourData)) {
|
|
34607
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
34608
|
+
const val = hourData[i];
|
|
34609
|
+
if (val !== "x" && typeof val === "number") {
|
|
34610
|
+
hourSum += val;
|
|
34611
|
+
}
|
|
34612
|
+
}
|
|
34613
|
+
}
|
|
34614
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
34615
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
34616
|
+
if (Array.isArray(nextHourData)) {
|
|
34617
|
+
for (let i = 0; i < endMinute && i < nextHourData.length; i++) {
|
|
34618
|
+
const val = nextHourData[i];
|
|
34619
|
+
if (val !== "x" && typeof val === "number") {
|
|
34620
|
+
hourSum += val;
|
|
34621
|
+
}
|
|
34622
|
+
}
|
|
34623
|
+
}
|
|
34624
|
+
} else {
|
|
34625
|
+
if (Array.isArray(hourData)) {
|
|
34626
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
34627
|
+
const val = hourData[i];
|
|
34628
|
+
if (val !== "x" && typeof val === "number") {
|
|
34629
|
+
hourSum += val;
|
|
34630
|
+
}
|
|
34631
|
+
}
|
|
34632
|
+
}
|
|
34633
|
+
}
|
|
34634
|
+
} else {
|
|
34635
|
+
if (Array.isArray(hourData)) {
|
|
34636
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
34637
|
+
const val = hourData[i];
|
|
34638
|
+
if (val !== "x" && typeof val === "number") {
|
|
34639
|
+
hourSum += val;
|
|
34640
|
+
}
|
|
34641
|
+
}
|
|
34642
|
+
}
|
|
34643
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
34644
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
34645
|
+
if (Array.isArray(nextHourData)) {
|
|
34646
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
34647
|
+
const val = nextHourData[i];
|
|
34648
|
+
if (val !== "x" && typeof val === "number") {
|
|
34649
|
+
hourSum += val;
|
|
34650
|
+
}
|
|
34651
|
+
}
|
|
34652
|
+
}
|
|
34653
|
+
}
|
|
34654
|
+
}
|
|
34655
|
+
} else {
|
|
34656
|
+
if (Array.isArray(hourData)) {
|
|
34657
|
+
hourData.forEach((val) => {
|
|
34658
|
+
if (val !== "x" && typeof val === "number") {
|
|
34659
|
+
hourSum += val;
|
|
34660
|
+
}
|
|
34661
|
+
});
|
|
34662
|
+
}
|
|
34663
|
+
if (index === expectedHours.length - 1 && hasPartialLastHour && endMinute > 0) {
|
|
34664
|
+
hourSum = 0;
|
|
34665
|
+
if (Array.isArray(hourData)) {
|
|
34666
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
34667
|
+
const val = hourData[i];
|
|
34668
|
+
if (val !== "x" && typeof val === "number") {
|
|
34669
|
+
hourSum += val;
|
|
34670
|
+
}
|
|
34671
|
+
}
|
|
34672
|
+
}
|
|
34673
|
+
}
|
|
34165
34674
|
}
|
|
34166
|
-
return
|
|
34675
|
+
return hourSum;
|
|
34167
34676
|
});
|
|
34168
34677
|
}
|
|
34169
34678
|
if (metrics2.output_array) {
|