@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.mjs
CHANGED
|
@@ -859,40 +859,140 @@ var dashboardService = {
|
|
|
859
859
|
if (hasOutputHourlyData) {
|
|
860
860
|
console.log("Using new output_hourly column for workspace:", data.workspace_name);
|
|
861
861
|
console.log("Raw output_hourly data:", outputHourly);
|
|
862
|
-
const isNightShift = data.shift_id === 1;
|
|
863
|
-
const shiftStart = data.shift_start || (isNightShift ? "22:00" : "06:00");
|
|
864
|
-
const shiftEnd = data.shift_end || (isNightShift ? "06:00" : "14:00");
|
|
862
|
+
const isNightShift = data.shift_id === (shiftConfig.nightShift?.id ?? 1);
|
|
863
|
+
const shiftStart = data.shift_start || (isNightShift ? shiftConfig.nightShift?.startTime || "22:00" : shiftConfig.dayShift?.startTime || "06:00");
|
|
864
|
+
const shiftEnd = data.shift_end || (isNightShift ? shiftConfig.nightShift?.endTime || "06:00" : shiftConfig.dayShift?.endTime || "14:00");
|
|
865
865
|
const startHour = parseInt(shiftStart.split(":")[0]);
|
|
866
866
|
const startMinute = parseInt(shiftStart.split(":")[1] || "0");
|
|
867
867
|
const endHour = parseInt(shiftEnd.split(":")[0]);
|
|
868
868
|
const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
|
|
869
869
|
let shiftDuration = endHour - startHour;
|
|
870
|
-
if (endMinute > startMinute) {
|
|
871
|
-
shiftDuration += 1;
|
|
872
|
-
}
|
|
873
870
|
if (shiftDuration <= 0) {
|
|
874
871
|
shiftDuration += 24;
|
|
875
872
|
}
|
|
873
|
+
const hasPartialLastHour = endMinute > 0 && endMinute < 60;
|
|
874
|
+
const hourCount = hasPartialLastHour ? Math.ceil(shiftDuration + endMinute / 60) : shiftDuration;
|
|
876
875
|
let expectedHours = [];
|
|
877
|
-
for (let i = 0; i <
|
|
876
|
+
for (let i = 0; i < hourCount; i++) {
|
|
878
877
|
expectedHours.push((startHour + i) % 24);
|
|
879
878
|
}
|
|
880
879
|
console.log("Expected shift hours:", expectedHours);
|
|
881
880
|
console.log("Available data hours:", Object.keys(outputHourly));
|
|
882
|
-
hourlyActionCounts = expectedHours.map((expectedHour) => {
|
|
883
|
-
let
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
881
|
+
hourlyActionCounts = expectedHours.map((expectedHour, index) => {
|
|
882
|
+
let hourSum = 0;
|
|
883
|
+
const hourData = outputHourly[expectedHour.toString()] || [];
|
|
884
|
+
if (startMinute > 0) {
|
|
885
|
+
if (index === 0) {
|
|
886
|
+
if (Array.isArray(hourData)) {
|
|
887
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
888
|
+
const val = hourData[i];
|
|
889
|
+
if (val !== "x" && typeof val === "number") {
|
|
890
|
+
hourSum += val;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
895
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
896
|
+
if (Array.isArray(nextHourData)) {
|
|
897
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
898
|
+
const val = nextHourData[i];
|
|
899
|
+
if (val !== "x" && typeof val === "number") {
|
|
900
|
+
hourSum += val;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
} else if (index < expectedHours.length - 1) {
|
|
905
|
+
if (Array.isArray(hourData)) {
|
|
906
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
907
|
+
const val = hourData[i];
|
|
908
|
+
if (val !== "x" && typeof val === "number") {
|
|
909
|
+
hourSum += val;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
914
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
915
|
+
if (Array.isArray(nextHourData)) {
|
|
916
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
917
|
+
const val = nextHourData[i];
|
|
918
|
+
if (val !== "x" && typeof val === "number") {
|
|
919
|
+
hourSum += val;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
} else {
|
|
924
|
+
if (hasPartialLastHour && endMinute > 0) {
|
|
925
|
+
if (startMinute > 0) {
|
|
926
|
+
if (Array.isArray(hourData)) {
|
|
927
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
928
|
+
const val = hourData[i];
|
|
929
|
+
if (val !== "x" && typeof val === "number") {
|
|
930
|
+
hourSum += val;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
935
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
936
|
+
if (Array.isArray(nextHourData)) {
|
|
937
|
+
for (let i = 0; i < endMinute && i < nextHourData.length; i++) {
|
|
938
|
+
const val = nextHourData[i];
|
|
939
|
+
if (val !== "x" && typeof val === "number") {
|
|
940
|
+
hourSum += val;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
} else {
|
|
945
|
+
if (Array.isArray(hourData)) {
|
|
946
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
947
|
+
const val = hourData[i];
|
|
948
|
+
if (val !== "x" && typeof val === "number") {
|
|
949
|
+
hourSum += val;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
} else {
|
|
955
|
+
if (Array.isArray(hourData)) {
|
|
956
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
957
|
+
const val = hourData[i];
|
|
958
|
+
if (val !== "x" && typeof val === "number") {
|
|
959
|
+
hourSum += val;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
964
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
965
|
+
if (Array.isArray(nextHourData)) {
|
|
966
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
967
|
+
const val = nextHourData[i];
|
|
968
|
+
if (val !== "x" && typeof val === "number") {
|
|
969
|
+
hourSum += val;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
} else {
|
|
976
|
+
if (Array.isArray(hourData)) {
|
|
977
|
+
hourData.forEach((val) => {
|
|
978
|
+
if (val !== "x" && typeof val === "number") {
|
|
979
|
+
hourSum += val;
|
|
980
|
+
}
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
if (index === expectedHours.length - 1 && hasPartialLastHour && endMinute > 0) {
|
|
984
|
+
hourSum = 0;
|
|
985
|
+
if (Array.isArray(hourData)) {
|
|
986
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
987
|
+
const val = hourData[i];
|
|
988
|
+
if (val !== "x" && typeof val === "number") {
|
|
989
|
+
hourSum += val;
|
|
990
|
+
}
|
|
891
991
|
}
|
|
892
992
|
}
|
|
893
993
|
}
|
|
894
994
|
}
|
|
895
|
-
return
|
|
995
|
+
return hourSum;
|
|
896
996
|
});
|
|
897
997
|
console.log("Final hourly action counts:", hourlyActionCounts);
|
|
898
998
|
} else {
|
|
@@ -2093,136 +2193,142 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
|
|
|
2093
2193
|
const now2 = /* @__PURE__ */ new Date();
|
|
2094
2194
|
const currentHour = now2.getHours();
|
|
2095
2195
|
const currentMinute = now2.getMinutes();
|
|
2096
|
-
|
|
2097
|
-
|
|
2196
|
+
const dayShiftStart = shiftConfig?.dayShift?.startTime || "08:00";
|
|
2197
|
+
const dayShiftEnd = shiftConfig?.dayShift?.endTime || "19:30";
|
|
2198
|
+
const nightShiftStart = shiftConfig?.nightShift?.startTime || "19:30";
|
|
2199
|
+
const nightShiftEnd = shiftConfig?.nightShift?.endTime || "06:00";
|
|
2200
|
+
const parseShiftTime = (timeStr) => {
|
|
2201
|
+
const [hour, minute] = timeStr.split(":").map(Number);
|
|
2202
|
+
return { hour, minute };
|
|
2203
|
+
};
|
|
2204
|
+
let shiftStart, shiftEnd;
|
|
2098
2205
|
if (currentShiftId === 0) {
|
|
2099
|
-
|
|
2100
|
-
|
|
2206
|
+
shiftStart = parseShiftTime(dayShiftStart);
|
|
2207
|
+
shiftEnd = parseShiftTime(dayShiftEnd);
|
|
2101
2208
|
} else {
|
|
2102
|
-
|
|
2103
|
-
|
|
2209
|
+
shiftStart = parseShiftTime(nightShiftStart);
|
|
2210
|
+
shiftEnd = parseShiftTime(nightShiftEnd);
|
|
2104
2211
|
}
|
|
2105
2212
|
let elapsedMinutes = 0;
|
|
2106
2213
|
if (currentShiftId === 0) {
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2214
|
+
const shiftStartTotalMinutes = shiftStart.hour * 60 + shiftStart.minute;
|
|
2215
|
+
const currentTotalMinutes = currentHour * 60 + currentMinute;
|
|
2216
|
+
const shiftEndTotalMinutes = shiftEnd.hour * 60 + shiftEnd.minute;
|
|
2217
|
+
if (currentTotalMinutes >= shiftStartTotalMinutes && currentTotalMinutes < shiftEndTotalMinutes) {
|
|
2218
|
+
elapsedMinutes = currentTotalMinutes - shiftStartTotalMinutes;
|
|
2219
|
+
} else if (currentTotalMinutes >= shiftEndTotalMinutes) {
|
|
2220
|
+
elapsedMinutes = shiftEndTotalMinutes - shiftStartTotalMinutes;
|
|
2111
2221
|
}
|
|
2112
2222
|
} else {
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2223
|
+
const shiftStartTotalMinutes = shiftStart.hour * 60 + shiftStart.minute;
|
|
2224
|
+
const currentTotalMinutes = currentHour * 60 + currentMinute;
|
|
2225
|
+
const shiftEndTotalMinutes = shiftEnd.hour * 60 + shiftEnd.minute;
|
|
2226
|
+
if (currentHour >= shiftStart.hour || currentHour < shiftEnd.hour) {
|
|
2227
|
+
if (currentHour >= shiftStart.hour) {
|
|
2228
|
+
elapsedMinutes = currentTotalMinutes - shiftStartTotalMinutes;
|
|
2229
|
+
} else {
|
|
2230
|
+
elapsedMinutes = 24 * 60 - shiftStartTotalMinutes + currentTotalMinutes;
|
|
2231
|
+
}
|
|
2232
|
+
if (currentHour >= shiftEnd.hour && currentTotalMinutes >= shiftEndTotalMinutes) {
|
|
2233
|
+
const totalShiftMinutes = 24 * 60 - shiftStartTotalMinutes + shiftEndTotalMinutes;
|
|
2234
|
+
elapsedMinutes = Math.min(elapsedMinutes, totalShiftMinutes);
|
|
2235
|
+
}
|
|
2117
2236
|
}
|
|
2118
2237
|
}
|
|
2119
2238
|
const tableName = `performance_metrics_${companyId.replace(/-/g, "_")}`;
|
|
2120
|
-
const query = `
|
|
2121
|
-
WITH workspace_uptime AS (
|
|
2122
|
-
SELECT
|
|
2123
|
-
workspace_id,
|
|
2124
|
-
workspace_display_name,
|
|
2125
|
-
idle_time_hourly,
|
|
2126
|
-
output_hourly,
|
|
2127
|
-
shift_start,
|
|
2128
|
-
shift_end
|
|
2129
|
-
FROM ${tableName}
|
|
2130
|
-
WHERE date = $1::date
|
|
2131
|
-
AND shift_id = $2
|
|
2132
|
-
),
|
|
2133
|
-
calculated_uptime AS (
|
|
2134
|
-
SELECT
|
|
2135
|
-
workspace_id,
|
|
2136
|
-
workspace_display_name,
|
|
2137
|
-
-- Calculate actual minutes from hourly data
|
|
2138
|
-
(
|
|
2139
|
-
SELECT COALESCE(SUM(
|
|
2140
|
-
CASE
|
|
2141
|
-
WHEN jsonb_array_length(idle_time_hourly->key::text) >= 58 THEN 60
|
|
2142
|
-
WHEN jsonb_array_length(idle_time_hourly->key::text) > 0 THEN jsonb_array_length(idle_time_hourly->key::text)
|
|
2143
|
-
ELSE 0
|
|
2144
|
-
END
|
|
2145
|
-
), 0)
|
|
2146
|
-
FROM jsonb_object_keys(idle_time_hourly) AS key
|
|
2147
|
-
WHERE key::int >= $3 AND key::int < $4
|
|
2148
|
-
) +
|
|
2149
|
-
-- Add current hour's data if applicable
|
|
2150
|
-
CASE
|
|
2151
|
-
WHEN $4::int >= $3 AND $4::int < $5 THEN
|
|
2152
|
-
LEAST($6::int,
|
|
2153
|
-
COALESCE(jsonb_array_length(idle_time_hourly->$4::text), 0))
|
|
2154
|
-
ELSE 0
|
|
2155
|
-
END as actual_minutes
|
|
2156
|
-
FROM workspace_uptime
|
|
2157
|
-
)
|
|
2158
|
-
SELECT
|
|
2159
|
-
workspace_id,
|
|
2160
|
-
workspace_display_name,
|
|
2161
|
-
actual_minutes,
|
|
2162
|
-
$7::int as expected_minutes,
|
|
2163
|
-
ROUND(
|
|
2164
|
-
CASE
|
|
2165
|
-
WHEN $7::int > 0 THEN (actual_minutes::numeric / $7::numeric) * 100
|
|
2166
|
-
ELSE 100
|
|
2167
|
-
END, 1
|
|
2168
|
-
) as uptime_percentage
|
|
2169
|
-
FROM calculated_uptime
|
|
2170
|
-
`;
|
|
2171
2239
|
try {
|
|
2172
|
-
const { data, error } = await supabase.
|
|
2173
|
-
query_text: query,
|
|
2174
|
-
params: [
|
|
2175
|
-
currentDate,
|
|
2176
|
-
currentShiftId,
|
|
2177
|
-
shiftStartHour,
|
|
2178
|
-
currentHour,
|
|
2179
|
-
shiftEndHour,
|
|
2180
|
-
currentMinute,
|
|
2181
|
-
elapsedMinutes
|
|
2182
|
-
]
|
|
2183
|
-
}).single();
|
|
2240
|
+
const { data: queryData, error } = await supabase.from(tableName).select("workspace_id, workspace_display_name, output_hourly").eq("date", currentDate).eq("shift_id", currentShiftId);
|
|
2184
2241
|
if (error) {
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2242
|
+
console.error("Error fetching performance metrics:", error);
|
|
2243
|
+
return /* @__PURE__ */ new Map();
|
|
2244
|
+
}
|
|
2245
|
+
const uptimeMap = /* @__PURE__ */ new Map();
|
|
2246
|
+
for (const record of queryData || []) {
|
|
2247
|
+
let actualMinutes = 0;
|
|
2248
|
+
let totalPossibleMinutes = 0;
|
|
2249
|
+
const outputHourly = record.output_hourly || {};
|
|
2250
|
+
const hoursElapsed = Math.ceil(elapsedMinutes / 60);
|
|
2251
|
+
for (let hourIndex = 0; hourIndex < hoursElapsed; hourIndex++) {
|
|
2252
|
+
const actualHour = (shiftStart.hour + hourIndex) % 24;
|
|
2253
|
+
let hourData = [];
|
|
2254
|
+
let minutesInThisHour = 60;
|
|
2255
|
+
if (shiftStart.minute > 0) {
|
|
2256
|
+
if (hourIndex === 0) {
|
|
2257
|
+
const firstHourData = outputHourly[actualHour.toString()] || [];
|
|
2258
|
+
const nextHour = (actualHour + 1) % 24;
|
|
2259
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
2260
|
+
hourData = [
|
|
2261
|
+
...Array.isArray(firstHourData) ? firstHourData.slice(shiftStart.minute) : [],
|
|
2262
|
+
...Array.isArray(nextHourData) ? nextHourData.slice(0, shiftStart.minute) : []
|
|
2263
|
+
];
|
|
2264
|
+
} else if (hourIndex < hoursElapsed - 1) {
|
|
2265
|
+
const currentHourData = outputHourly[actualHour.toString()] || [];
|
|
2266
|
+
const nextHour = (actualHour + 1) % 24;
|
|
2267
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
2268
|
+
hourData = [
|
|
2269
|
+
...Array.isArray(currentHourData) ? currentHourData.slice(shiftStart.minute) : [],
|
|
2270
|
+
...Array.isArray(nextHourData) ? nextHourData.slice(0, shiftStart.minute) : []
|
|
2271
|
+
];
|
|
2272
|
+
} else {
|
|
2273
|
+
const isLastHourPartial = hourIndex === hoursElapsed - 1 && elapsedMinutes % 60 > 0;
|
|
2274
|
+
if (isLastHourPartial) {
|
|
2275
|
+
minutesInThisHour = elapsedMinutes % 60;
|
|
2276
|
+
const currentHourData = outputHourly[actualHour.toString()] || [];
|
|
2277
|
+
if (shiftStart.minute > 0) {
|
|
2278
|
+
const nextHour = (actualHour + 1) % 24;
|
|
2279
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
2280
|
+
const firstPart = Array.isArray(currentHourData) ? currentHourData.slice(shiftStart.minute) : [];
|
|
2281
|
+
const secondPart = Array.isArray(nextHourData) ? nextHourData.slice(0, Math.min(shiftStart.minute, minutesInThisHour)) : [];
|
|
2282
|
+
hourData = [...firstPart, ...secondPart].slice(0, minutesInThisHour);
|
|
2283
|
+
} else {
|
|
2284
|
+
hourData = Array.isArray(currentHourData) ? currentHourData.slice(0, minutesInThisHour) : [];
|
|
2285
|
+
}
|
|
2286
|
+
} else {
|
|
2287
|
+
const currentHourData = outputHourly[actualHour.toString()] || [];
|
|
2288
|
+
const nextHour = (actualHour + 1) % 24;
|
|
2289
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
2290
|
+
hourData = [
|
|
2291
|
+
...Array.isArray(currentHourData) ? currentHourData.slice(shiftStart.minute) : [],
|
|
2292
|
+
...Array.isArray(nextHourData) ? nextHourData.slice(0, shiftStart.minute) : []
|
|
2293
|
+
];
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
} else {
|
|
2297
|
+
hourData = outputHourly[actualHour.toString()] || [];
|
|
2298
|
+
if (hourIndex === hoursElapsed - 1) {
|
|
2299
|
+
const remainingMinutes = elapsedMinutes % 60;
|
|
2300
|
+
if (remainingMinutes > 0) {
|
|
2301
|
+
minutesInThisHour = remainingMinutes;
|
|
2302
|
+
hourData = Array.isArray(hourData) ? hourData.slice(0, minutesInThisHour) : [];
|
|
2203
2303
|
}
|
|
2204
2304
|
}
|
|
2205
2305
|
}
|
|
2206
|
-
const
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
});
|
|
2306
|
+
const hasXArchitecture = Array.isArray(hourData) && hourData.some((val) => val === "x");
|
|
2307
|
+
if (hasXArchitecture) {
|
|
2308
|
+
const xCount = hourData.filter((val) => val === "x").length;
|
|
2309
|
+
if (xCount <= 2) {
|
|
2310
|
+
actualMinutes += minutesInThisHour;
|
|
2311
|
+
} else {
|
|
2312
|
+
const uptimeCount = hourData.filter((val) => val !== "x").length;
|
|
2313
|
+
actualMinutes += Math.min(uptimeCount, minutesInThisHour);
|
|
2314
|
+
}
|
|
2315
|
+
} else {
|
|
2316
|
+
const arrayLength = Array.isArray(hourData) ? hourData.length : 0;
|
|
2317
|
+
if (arrayLength >= Math.min(58, minutesInThisHour - 2)) {
|
|
2318
|
+
actualMinutes += minutesInThisHour;
|
|
2319
|
+
} else {
|
|
2320
|
+
actualMinutes += Math.min(arrayLength, minutesInThisHour);
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
totalPossibleMinutes += minutesInThisHour;
|
|
2225
2324
|
}
|
|
2325
|
+
const percentage = totalPossibleMinutes > 0 ? Math.round(actualMinutes / totalPossibleMinutes * 1e3) / 10 : 100;
|
|
2326
|
+
uptimeMap.set(record.workspace_id, {
|
|
2327
|
+
expectedMinutes: totalPossibleMinutes,
|
|
2328
|
+
actualMinutes,
|
|
2329
|
+
percentage,
|
|
2330
|
+
lastCalculated: (/* @__PURE__ */ new Date()).toISOString()
|
|
2331
|
+
});
|
|
2226
2332
|
}
|
|
2227
2333
|
return uptimeMap;
|
|
2228
2334
|
} catch (error) {
|
|
@@ -5673,39 +5779,139 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
5673
5779
|
console.log("Using new output_hourly column for workspace (fallback):", recentData.workspace_name);
|
|
5674
5780
|
console.log("Raw output_hourly data (fallback):", outputHourly2);
|
|
5675
5781
|
const isNightShift = recentData.shift_id === 1;
|
|
5676
|
-
const shiftStart = recentData.shift_start || (isNightShift ? "22:00" : "06:00");
|
|
5677
|
-
const shiftEnd = recentData.shift_end || (isNightShift ? "06:00" : "14:00");
|
|
5782
|
+
const shiftStart = recentData.shift_start || (isNightShift ? shiftConfig.nightShift?.startTime || "22:00" : shiftConfig.dayShift?.startTime || "06:00");
|
|
5783
|
+
const shiftEnd = recentData.shift_end || (isNightShift ? shiftConfig.nightShift?.endTime || "06:00" : shiftConfig.dayShift?.endTime || "14:00");
|
|
5678
5784
|
const startHour = parseInt(shiftStart.split(":")[0]);
|
|
5679
5785
|
const startMinute = parseInt(shiftStart.split(":")[1] || "0");
|
|
5680
5786
|
const endHour = parseInt(shiftEnd.split(":")[0]);
|
|
5681
5787
|
const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
|
|
5682
5788
|
let shiftDuration = endHour - startHour;
|
|
5683
|
-
if (endMinute > startMinute) {
|
|
5684
|
-
shiftDuration += 1;
|
|
5685
|
-
}
|
|
5686
5789
|
if (shiftDuration <= 0) {
|
|
5687
5790
|
shiftDuration += 24;
|
|
5688
5791
|
}
|
|
5792
|
+
const hasPartialLastHour = endMinute > 0 && endMinute < 60;
|
|
5793
|
+
const hourCount = hasPartialLastHour ? Math.ceil(shiftDuration + endMinute / 60) : shiftDuration;
|
|
5689
5794
|
let expectedHours = [];
|
|
5690
|
-
for (let i = 0; i <
|
|
5795
|
+
for (let i = 0; i < hourCount; i++) {
|
|
5691
5796
|
expectedHours.push((startHour + i) % 24);
|
|
5692
5797
|
}
|
|
5693
5798
|
console.log("Expected shift hours (fallback):", expectedHours);
|
|
5694
5799
|
console.log("Available data hours (fallback):", Object.keys(outputHourly2));
|
|
5695
|
-
hourlyActionCounts2 = expectedHours.map((expectedHour) => {
|
|
5696
|
-
let
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5800
|
+
hourlyActionCounts2 = expectedHours.map((expectedHour, index) => {
|
|
5801
|
+
let hourSum = 0;
|
|
5802
|
+
const hourData = outputHourly2[expectedHour.toString()] || [];
|
|
5803
|
+
if (startMinute > 0) {
|
|
5804
|
+
if (index === 0) {
|
|
5805
|
+
if (Array.isArray(hourData)) {
|
|
5806
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
5807
|
+
const val = hourData[i];
|
|
5808
|
+
if (val !== "x" && typeof val === "number") {
|
|
5809
|
+
hourSum += val;
|
|
5810
|
+
}
|
|
5811
|
+
}
|
|
5812
|
+
}
|
|
5813
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
5814
|
+
const nextHourData = outputHourly2[nextHour.toString()] || [];
|
|
5815
|
+
if (Array.isArray(nextHourData)) {
|
|
5816
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
5817
|
+
const val = nextHourData[i];
|
|
5818
|
+
if (val !== "x" && typeof val === "number") {
|
|
5819
|
+
hourSum += val;
|
|
5820
|
+
}
|
|
5821
|
+
}
|
|
5822
|
+
}
|
|
5823
|
+
} else if (index < expectedHours.length - 1) {
|
|
5824
|
+
if (Array.isArray(hourData)) {
|
|
5825
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
5826
|
+
const val = hourData[i];
|
|
5827
|
+
if (val !== "x" && typeof val === "number") {
|
|
5828
|
+
hourSum += val;
|
|
5829
|
+
}
|
|
5830
|
+
}
|
|
5831
|
+
}
|
|
5832
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
5833
|
+
const nextHourData = outputHourly2[nextHour.toString()] || [];
|
|
5834
|
+
if (Array.isArray(nextHourData)) {
|
|
5835
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
5836
|
+
const val = nextHourData[i];
|
|
5837
|
+
if (val !== "x" && typeof val === "number") {
|
|
5838
|
+
hourSum += val;
|
|
5839
|
+
}
|
|
5840
|
+
}
|
|
5841
|
+
}
|
|
5842
|
+
} else {
|
|
5843
|
+
if (hasPartialLastHour && endMinute > 0) {
|
|
5844
|
+
if (startMinute > 0) {
|
|
5845
|
+
if (Array.isArray(hourData)) {
|
|
5846
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
5847
|
+
const val = hourData[i];
|
|
5848
|
+
if (val !== "x" && typeof val === "number") {
|
|
5849
|
+
hourSum += val;
|
|
5850
|
+
}
|
|
5851
|
+
}
|
|
5852
|
+
}
|
|
5853
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
5854
|
+
const nextHourData = outputHourly2[nextHour.toString()] || [];
|
|
5855
|
+
if (Array.isArray(nextHourData)) {
|
|
5856
|
+
for (let i = 0; i < endMinute && i < nextHourData.length; i++) {
|
|
5857
|
+
const val = nextHourData[i];
|
|
5858
|
+
if (val !== "x" && typeof val === "number") {
|
|
5859
|
+
hourSum += val;
|
|
5860
|
+
}
|
|
5861
|
+
}
|
|
5862
|
+
}
|
|
5863
|
+
} else {
|
|
5864
|
+
if (Array.isArray(hourData)) {
|
|
5865
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
5866
|
+
const val = hourData[i];
|
|
5867
|
+
if (val !== "x" && typeof val === "number") {
|
|
5868
|
+
hourSum += val;
|
|
5869
|
+
}
|
|
5870
|
+
}
|
|
5871
|
+
}
|
|
5872
|
+
}
|
|
5873
|
+
} else {
|
|
5874
|
+
if (Array.isArray(hourData)) {
|
|
5875
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
5876
|
+
const val = hourData[i];
|
|
5877
|
+
if (val !== "x" && typeof val === "number") {
|
|
5878
|
+
hourSum += val;
|
|
5879
|
+
}
|
|
5880
|
+
}
|
|
5881
|
+
}
|
|
5882
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
5883
|
+
const nextHourData = outputHourly2[nextHour.toString()] || [];
|
|
5884
|
+
if (Array.isArray(nextHourData)) {
|
|
5885
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
5886
|
+
const val = nextHourData[i];
|
|
5887
|
+
if (val !== "x" && typeof val === "number") {
|
|
5888
|
+
hourSum += val;
|
|
5889
|
+
}
|
|
5890
|
+
}
|
|
5891
|
+
}
|
|
5892
|
+
}
|
|
5893
|
+
}
|
|
5894
|
+
} else {
|
|
5895
|
+
if (Array.isArray(hourData)) {
|
|
5896
|
+
hourData.forEach((val) => {
|
|
5897
|
+
if (val !== "x" && typeof val === "number") {
|
|
5898
|
+
hourSum += val;
|
|
5899
|
+
}
|
|
5900
|
+
});
|
|
5901
|
+
}
|
|
5902
|
+
if (index === expectedHours.length - 1 && hasPartialLastHour && endMinute > 0) {
|
|
5903
|
+
hourSum = 0;
|
|
5904
|
+
if (Array.isArray(hourData)) {
|
|
5905
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
5906
|
+
const val = hourData[i];
|
|
5907
|
+
if (val !== "x" && typeof val === "number") {
|
|
5908
|
+
hourSum += val;
|
|
5909
|
+
}
|
|
5704
5910
|
}
|
|
5705
5911
|
}
|
|
5706
5912
|
}
|
|
5707
5913
|
}
|
|
5708
|
-
return
|
|
5914
|
+
return hourSum;
|
|
5709
5915
|
});
|
|
5710
5916
|
console.log("Final hourly action counts (fallback):", hourlyActionCounts2);
|
|
5711
5917
|
} else {
|
|
@@ -5732,8 +5938,8 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
5732
5938
|
date: recentData.date,
|
|
5733
5939
|
shift_id: recentData.shift_id,
|
|
5734
5940
|
action_name: recentData.action_name || "",
|
|
5735
|
-
shift_start: recentData.shift_start || "06:00",
|
|
5736
|
-
shift_end: recentData.shift_end || "14:00",
|
|
5941
|
+
shift_start: recentData.shift_start || (recentData.shift_id === 1 ? shiftConfig.nightShift?.startTime || "22:00" : shiftConfig.dayShift?.startTime || "06:00"),
|
|
5942
|
+
shift_end: recentData.shift_end || (recentData.shift_id === 1 ? shiftConfig.nightShift?.endTime || "06:00" : shiftConfig.dayShift?.endTime || "14:00"),
|
|
5737
5943
|
shift_type: recentData.shift_type || (recentData.shift_id === 0 ? "Day" : "Night"),
|
|
5738
5944
|
pph_threshold: recentData.pph_threshold || 0,
|
|
5739
5945
|
target_output: recentData.total_day_output || 0,
|
|
@@ -5789,39 +5995,139 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
5789
5995
|
console.log("\u2705 Using new output_hourly column for workspace:", data.workspace_name);
|
|
5790
5996
|
console.log("Raw output_hourly data:", JSON.stringify(outputHourly));
|
|
5791
5997
|
const isNightShift = data.shift_id === 1;
|
|
5792
|
-
const shiftStart = data.shift_start || (isNightShift ? "22:00" : "06:00");
|
|
5793
|
-
const shiftEnd = data.shift_end || (isNightShift ? "06:00" : "14:00");
|
|
5998
|
+
const shiftStart = data.shift_start || (isNightShift ? shiftConfig.nightShift?.startTime || "22:00" : shiftConfig.dayShift?.startTime || "06:00");
|
|
5999
|
+
const shiftEnd = data.shift_end || (isNightShift ? shiftConfig.nightShift?.endTime || "06:00" : shiftConfig.dayShift?.endTime || "14:00");
|
|
5794
6000
|
const startHour = parseInt(shiftStart.split(":")[0]);
|
|
5795
6001
|
const startMinute = parseInt(shiftStart.split(":")[1] || "0");
|
|
5796
6002
|
const endHour = parseInt(shiftEnd.split(":")[0]);
|
|
5797
6003
|
const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
|
|
5798
6004
|
let shiftDuration = endHour - startHour;
|
|
5799
|
-
if (endMinute > startMinute) {
|
|
5800
|
-
shiftDuration += 1;
|
|
5801
|
-
}
|
|
5802
6005
|
if (shiftDuration <= 0) {
|
|
5803
6006
|
shiftDuration += 24;
|
|
5804
6007
|
}
|
|
6008
|
+
const hasPartialLastHour = endMinute > 0 && endMinute < 60;
|
|
6009
|
+
const hourCount = hasPartialLastHour ? Math.ceil(shiftDuration + endMinute / 60) : shiftDuration;
|
|
5805
6010
|
let expectedHours = [];
|
|
5806
|
-
for (let i = 0; i <
|
|
6011
|
+
for (let i = 0; i < hourCount; i++) {
|
|
5807
6012
|
expectedHours.push((startHour + i) % 24);
|
|
5808
6013
|
}
|
|
5809
6014
|
console.log("Expected shift hours:", expectedHours);
|
|
5810
6015
|
console.log("Available data hours:", Object.keys(outputHourly));
|
|
5811
|
-
hourlyActionCounts = expectedHours.map((expectedHour) => {
|
|
5812
|
-
let
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
6016
|
+
hourlyActionCounts = expectedHours.map((expectedHour, index) => {
|
|
6017
|
+
let hourSum = 0;
|
|
6018
|
+
const hourData = outputHourly[expectedHour.toString()] || [];
|
|
6019
|
+
if (startMinute > 0) {
|
|
6020
|
+
if (index === 0) {
|
|
6021
|
+
if (Array.isArray(hourData)) {
|
|
6022
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
6023
|
+
const val = hourData[i];
|
|
6024
|
+
if (val !== "x" && typeof val === "number") {
|
|
6025
|
+
hourSum += val;
|
|
6026
|
+
}
|
|
6027
|
+
}
|
|
6028
|
+
}
|
|
6029
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
6030
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
6031
|
+
if (Array.isArray(nextHourData)) {
|
|
6032
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
6033
|
+
const val = nextHourData[i];
|
|
6034
|
+
if (val !== "x" && typeof val === "number") {
|
|
6035
|
+
hourSum += val;
|
|
6036
|
+
}
|
|
6037
|
+
}
|
|
6038
|
+
}
|
|
6039
|
+
} else if (index < expectedHours.length - 1) {
|
|
6040
|
+
if (Array.isArray(hourData)) {
|
|
6041
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
6042
|
+
const val = hourData[i];
|
|
6043
|
+
if (val !== "x" && typeof val === "number") {
|
|
6044
|
+
hourSum += val;
|
|
6045
|
+
}
|
|
6046
|
+
}
|
|
6047
|
+
}
|
|
6048
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
6049
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
6050
|
+
if (Array.isArray(nextHourData)) {
|
|
6051
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
6052
|
+
const val = nextHourData[i];
|
|
6053
|
+
if (val !== "x" && typeof val === "number") {
|
|
6054
|
+
hourSum += val;
|
|
6055
|
+
}
|
|
6056
|
+
}
|
|
6057
|
+
}
|
|
6058
|
+
} else {
|
|
6059
|
+
if (hasPartialLastHour && endMinute > 0) {
|
|
6060
|
+
if (startMinute > 0) {
|
|
6061
|
+
if (Array.isArray(hourData)) {
|
|
6062
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
6063
|
+
const val = hourData[i];
|
|
6064
|
+
if (val !== "x" && typeof val === "number") {
|
|
6065
|
+
hourSum += val;
|
|
6066
|
+
}
|
|
6067
|
+
}
|
|
6068
|
+
}
|
|
6069
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
6070
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
6071
|
+
if (Array.isArray(nextHourData)) {
|
|
6072
|
+
for (let i = 0; i < endMinute && i < nextHourData.length; i++) {
|
|
6073
|
+
const val = nextHourData[i];
|
|
6074
|
+
if (val !== "x" && typeof val === "number") {
|
|
6075
|
+
hourSum += val;
|
|
6076
|
+
}
|
|
6077
|
+
}
|
|
6078
|
+
}
|
|
6079
|
+
} else {
|
|
6080
|
+
if (Array.isArray(hourData)) {
|
|
6081
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
6082
|
+
const val = hourData[i];
|
|
6083
|
+
if (val !== "x" && typeof val === "number") {
|
|
6084
|
+
hourSum += val;
|
|
6085
|
+
}
|
|
6086
|
+
}
|
|
6087
|
+
}
|
|
6088
|
+
}
|
|
6089
|
+
} else {
|
|
6090
|
+
if (Array.isArray(hourData)) {
|
|
6091
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
6092
|
+
const val = hourData[i];
|
|
6093
|
+
if (val !== "x" && typeof val === "number") {
|
|
6094
|
+
hourSum += val;
|
|
6095
|
+
}
|
|
6096
|
+
}
|
|
6097
|
+
}
|
|
6098
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
6099
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
6100
|
+
if (Array.isArray(nextHourData)) {
|
|
6101
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
6102
|
+
const val = nextHourData[i];
|
|
6103
|
+
if (val !== "x" && typeof val === "number") {
|
|
6104
|
+
hourSum += val;
|
|
6105
|
+
}
|
|
6106
|
+
}
|
|
6107
|
+
}
|
|
6108
|
+
}
|
|
6109
|
+
}
|
|
6110
|
+
} else {
|
|
6111
|
+
if (Array.isArray(hourData)) {
|
|
6112
|
+
hourData.forEach((val) => {
|
|
6113
|
+
if (val !== "x" && typeof val === "number") {
|
|
6114
|
+
hourSum += val;
|
|
6115
|
+
}
|
|
6116
|
+
});
|
|
6117
|
+
}
|
|
6118
|
+
if (index === expectedHours.length - 1 && hasPartialLastHour && endMinute > 0) {
|
|
6119
|
+
hourSum = 0;
|
|
6120
|
+
if (Array.isArray(hourData)) {
|
|
6121
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
6122
|
+
const val = hourData[i];
|
|
6123
|
+
if (val !== "x" && typeof val === "number") {
|
|
6124
|
+
hourSum += val;
|
|
6125
|
+
}
|
|
5820
6126
|
}
|
|
5821
6127
|
}
|
|
5822
6128
|
}
|
|
5823
6129
|
}
|
|
5824
|
-
return
|
|
6130
|
+
return hourSum;
|
|
5825
6131
|
});
|
|
5826
6132
|
console.log("Final hourly action counts:", hourlyActionCounts);
|
|
5827
6133
|
} else {
|
|
@@ -5851,8 +6157,8 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
5851
6157
|
date: data.date,
|
|
5852
6158
|
shift_id: data.shift_id,
|
|
5853
6159
|
action_name: data.action_name || "",
|
|
5854
|
-
shift_start: data.shift_start || "06:00",
|
|
5855
|
-
shift_end: data.shift_end || "14:00",
|
|
6160
|
+
shift_start: data.shift_start || (data.shift_id === 1 ? shiftConfig.nightShift?.startTime || "22:00" : shiftConfig.dayShift?.startTime || "06:00"),
|
|
6161
|
+
shift_end: data.shift_end || (data.shift_id === 1 ? shiftConfig.nightShift?.endTime || "06:00" : shiftConfig.dayShift?.endTime || "14:00"),
|
|
5856
6162
|
shift_type: data.shift_type || (data.shift_id === 0 ? "Day" : "Night"),
|
|
5857
6163
|
pph_threshold: data.pph_threshold || 0,
|
|
5858
6164
|
target_output: data.total_day_output || 0,
|
|
@@ -21243,18 +21549,41 @@ var HourlyOutputChartComponent = ({
|
|
|
21243
21549
|
return { hour, minute, decimalHour };
|
|
21244
21550
|
};
|
|
21245
21551
|
const shiftStartTime = getTimeFromTimeString(shiftStart);
|
|
21246
|
-
const
|
|
21552
|
+
const { shiftDuration, shiftEndTime, hasPartialLastHour } = React19__default.useMemo(() => {
|
|
21553
|
+
console.log("[HourlyOutputChart] Calculating shift duration with:", {
|
|
21554
|
+
shiftStart,
|
|
21555
|
+
shiftEnd,
|
|
21556
|
+
shiftStartTime
|
|
21557
|
+
});
|
|
21247
21558
|
if (!shiftEnd) {
|
|
21248
|
-
|
|
21559
|
+
console.log("[HourlyOutputChart] No shiftEnd provided, using default 11 hours");
|
|
21560
|
+
return {
|
|
21561
|
+
shiftDuration: 11,
|
|
21562
|
+
shiftEndTime: null,
|
|
21563
|
+
hasPartialLastHour: false
|
|
21564
|
+
};
|
|
21249
21565
|
}
|
|
21250
21566
|
const endTime = getTimeFromTimeString(shiftEnd);
|
|
21251
21567
|
let duration = endTime.decimalHour - shiftStartTime.decimalHour;
|
|
21252
21568
|
if (duration <= 0) {
|
|
21253
21569
|
duration += 24;
|
|
21254
21570
|
}
|
|
21255
|
-
|
|
21571
|
+
const hasPartial = endTime.minute > 0 && endTime.minute < 60;
|
|
21572
|
+
const hourCount = hasPartial ? Math.ceil(duration) : Math.round(duration);
|
|
21573
|
+
console.log("[HourlyOutputChart] Shift calculation results:", {
|
|
21574
|
+
endTime,
|
|
21575
|
+
duration,
|
|
21576
|
+
hasPartial,
|
|
21577
|
+
hourCount
|
|
21578
|
+
});
|
|
21579
|
+
return {
|
|
21580
|
+
shiftDuration: hourCount,
|
|
21581
|
+
shiftEndTime: endTime,
|
|
21582
|
+
hasPartialLastHour: hasPartial
|
|
21583
|
+
};
|
|
21256
21584
|
}, [shiftEnd, shiftStartTime.decimalHour]);
|
|
21257
|
-
const SHIFT_DURATION =
|
|
21585
|
+
const SHIFT_DURATION = shiftDuration;
|
|
21586
|
+
shiftEndTime ? shiftEndTime.hour : (shiftStartTime.hour + SHIFT_DURATION) % 24;
|
|
21258
21587
|
const [animatedData, setAnimatedData] = React19__default.useState(
|
|
21259
21588
|
() => Array(SHIFT_DURATION).fill(0)
|
|
21260
21589
|
);
|
|
@@ -21365,12 +21694,19 @@ var HourlyOutputChartComponent = ({
|
|
|
21365
21694
|
};
|
|
21366
21695
|
}, []);
|
|
21367
21696
|
const formatHour = React19__default.useCallback((hourIndex) => {
|
|
21697
|
+
const isLastHour = hourIndex === SHIFT_DURATION - 1;
|
|
21368
21698
|
const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
|
|
21369
21699
|
const startHour = Math.floor(startDecimalHour) % 24;
|
|
21370
21700
|
const startMinute = Math.round(startDecimalHour % 1 * 60);
|
|
21371
|
-
|
|
21372
|
-
|
|
21373
|
-
|
|
21701
|
+
let endHour, endMinute;
|
|
21702
|
+
if (isLastHour && shiftEndTime) {
|
|
21703
|
+
endHour = shiftEndTime.hour;
|
|
21704
|
+
endMinute = shiftEndTime.minute;
|
|
21705
|
+
} else {
|
|
21706
|
+
const endDecimalHour = startDecimalHour + 1;
|
|
21707
|
+
endHour = Math.floor(endDecimalHour) % 24;
|
|
21708
|
+
endMinute = Math.round(endDecimalHour % 1 * 60);
|
|
21709
|
+
}
|
|
21374
21710
|
const formatTime3 = (h, m) => {
|
|
21375
21711
|
const period = h >= 12 ? "PM" : "AM";
|
|
21376
21712
|
const hour12 = h === 0 ? 12 : h > 12 ? h - 12 : h;
|
|
@@ -21380,26 +21716,85 @@ var HourlyOutputChartComponent = ({
|
|
|
21380
21716
|
return `${hour12}:${m.toString().padStart(2, "0")}${period}`;
|
|
21381
21717
|
};
|
|
21382
21718
|
return `${formatTime3(startHour, startMinute)}-${formatTime3(endHour, endMinute)}`;
|
|
21383
|
-
}, [shiftStartTime.decimalHour]);
|
|
21719
|
+
}, [shiftStartTime.decimalHour, SHIFT_DURATION, shiftEndTime]);
|
|
21384
21720
|
const formatTimeRange = React19__default.useCallback((hourIndex) => {
|
|
21721
|
+
const isLastHour = hourIndex === SHIFT_DURATION - 1;
|
|
21385
21722
|
const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
|
|
21386
21723
|
const startHour = Math.floor(startDecimalHour) % 24;
|
|
21387
21724
|
const startMinute = Math.round(startDecimalHour % 1 * 60);
|
|
21388
|
-
|
|
21389
|
-
|
|
21390
|
-
|
|
21725
|
+
let endHour, endMinute;
|
|
21726
|
+
if (isLastHour && shiftEndTime) {
|
|
21727
|
+
endHour = shiftEndTime.hour;
|
|
21728
|
+
endMinute = shiftEndTime.minute;
|
|
21729
|
+
} else {
|
|
21730
|
+
const endDecimalHour = startDecimalHour + 1;
|
|
21731
|
+
endHour = Math.floor(endDecimalHour) % 24;
|
|
21732
|
+
endMinute = Math.round(endDecimalHour % 1 * 60);
|
|
21733
|
+
}
|
|
21391
21734
|
const formatTime3 = (h, m) => {
|
|
21392
21735
|
const period = h >= 12 ? "PM" : "AM";
|
|
21393
21736
|
const hour12 = h === 0 ? 12 : h > 12 ? h - 12 : h;
|
|
21394
21737
|
return `${hour12}:${m.toString().padStart(2, "0")} ${period}`;
|
|
21395
21738
|
};
|
|
21396
21739
|
return `${formatTime3(startHour, startMinute)} - ${formatTime3(endHour, endMinute)}`;
|
|
21397
|
-
}, [shiftStartTime.decimalHour]);
|
|
21740
|
+
}, [shiftStartTime.decimalHour, SHIFT_DURATION, shiftEndTime]);
|
|
21398
21741
|
const chartData = React19__default.useMemo(() => {
|
|
21399
21742
|
return Array.from({ length: SHIFT_DURATION }, (_, i) => {
|
|
21400
21743
|
const actualHour = (shiftStartTime.hour + i) % 24;
|
|
21401
|
-
const
|
|
21402
|
-
|
|
21744
|
+
const startMinute = shiftStartTime.minute;
|
|
21745
|
+
let idleArray = [];
|
|
21746
|
+
let idleMinutes = 0;
|
|
21747
|
+
if (idleTimeHourly) {
|
|
21748
|
+
if (startMinute > 0) {
|
|
21749
|
+
if (i === 0) {
|
|
21750
|
+
const firstHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
21751
|
+
const nextHour = (actualHour + 1) % 24;
|
|
21752
|
+
const nextHourData = idleTimeHourly[nextHour.toString()] || [];
|
|
21753
|
+
idleArray = [
|
|
21754
|
+
...firstHourData.slice(startMinute) || [],
|
|
21755
|
+
...nextHourData.slice(0, startMinute) || []
|
|
21756
|
+
];
|
|
21757
|
+
} else if (i < SHIFT_DURATION - 1) {
|
|
21758
|
+
const currentHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
21759
|
+
const nextHour = (actualHour + 1) % 24;
|
|
21760
|
+
const nextHourData = idleTimeHourly[nextHour.toString()] || [];
|
|
21761
|
+
idleArray = [
|
|
21762
|
+
...currentHourData.slice(startMinute) || [],
|
|
21763
|
+
...nextHourData.slice(0, startMinute) || []
|
|
21764
|
+
];
|
|
21765
|
+
} else {
|
|
21766
|
+
const hasPartialLastHour2 = shiftEndTime && shiftEndTime.minute > 0 && shiftEndTime.minute < 60;
|
|
21767
|
+
if (hasPartialLastHour2) {
|
|
21768
|
+
const currentHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
21769
|
+
const nextHour = (actualHour + 1) % 24;
|
|
21770
|
+
const nextHourData = idleTimeHourly[nextHour.toString()] || [];
|
|
21771
|
+
if (startMinute > 0) {
|
|
21772
|
+
const firstPart = currentHourData.slice(startMinute) || [];
|
|
21773
|
+
const secondPart = nextHourData.slice(0, shiftEndTime.minute) || [];
|
|
21774
|
+
idleArray = [...firstPart, ...secondPart];
|
|
21775
|
+
} else {
|
|
21776
|
+
idleArray = currentHourData.slice(0, shiftEndTime.minute) || [];
|
|
21777
|
+
}
|
|
21778
|
+
} else {
|
|
21779
|
+
const currentHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
21780
|
+
const nextHour = (actualHour + 1) % 24;
|
|
21781
|
+
const nextHourData = idleTimeHourly[nextHour.toString()] || [];
|
|
21782
|
+
idleArray = [
|
|
21783
|
+
...currentHourData.slice(startMinute) || [],
|
|
21784
|
+
...nextHourData.slice(0, startMinute) || []
|
|
21785
|
+
];
|
|
21786
|
+
}
|
|
21787
|
+
}
|
|
21788
|
+
} else {
|
|
21789
|
+
const currentHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
21790
|
+
if (i === SHIFT_DURATION - 1 && shiftEndTime && shiftEndTime.minute > 0 && shiftEndTime.minute < 60) {
|
|
21791
|
+
idleArray = currentHourData.slice(0, shiftEndTime.minute) || [];
|
|
21792
|
+
} else {
|
|
21793
|
+
idleArray = currentHourData || [];
|
|
21794
|
+
}
|
|
21795
|
+
}
|
|
21796
|
+
}
|
|
21797
|
+
idleMinutes = idleArray.filter((val) => val === "1" || val === 1).length;
|
|
21403
21798
|
return {
|
|
21404
21799
|
hour: formatHour(i),
|
|
21405
21800
|
timeRange: formatTimeRange(i),
|
|
@@ -21411,7 +21806,7 @@ var HourlyOutputChartComponent = ({
|
|
|
21411
21806
|
idleArray
|
|
21412
21807
|
};
|
|
21413
21808
|
});
|
|
21414
|
-
}, [animatedData, data, pphThreshold, idleTimeHourly, shiftStartTime.hour, formatHour, formatTimeRange]);
|
|
21809
|
+
}, [animatedData, data, pphThreshold, idleTimeHourly, shiftStartTime.hour, shiftStartTime.minute, shiftEndTime, formatHour, formatTimeRange, SHIFT_DURATION]);
|
|
21415
21810
|
const IdleBar = React19__default.useMemo(() => {
|
|
21416
21811
|
if (!idleBarState.visible) return null;
|
|
21417
21812
|
return /* @__PURE__ */ jsx(
|
|
@@ -21571,13 +21966,13 @@ var HourlyOutputChartComponent = ({
|
|
|
21571
21966
|
if (showIdleTime && data2.idleArray) {
|
|
21572
21967
|
let currentRange = null;
|
|
21573
21968
|
data2.idleArray.forEach((val, idx) => {
|
|
21574
|
-
if (val === "1") {
|
|
21969
|
+
if (val === "1" || val === 1) {
|
|
21575
21970
|
if (!currentRange) {
|
|
21576
21971
|
currentRange = { start: idx, end: idx };
|
|
21577
21972
|
} else {
|
|
21578
21973
|
currentRange.end = idx;
|
|
21579
21974
|
}
|
|
21580
|
-
} else if (currentRange) {
|
|
21975
|
+
} else if (val !== "x" && currentRange) {
|
|
21581
21976
|
idleRanges.push(currentRange);
|
|
21582
21977
|
currentRange = null;
|
|
21583
21978
|
}
|
|
@@ -34119,21 +34514,135 @@ var KPIDetailView = ({
|
|
|
34119
34514
|
const shiftStart = metrics2.shift_start || (isNightShift ? "22:00" : "06:00");
|
|
34120
34515
|
const shiftEnd = metrics2.shift_end || (isNightShift ? "06:00" : "14:00");
|
|
34121
34516
|
const startHour = parseInt(shiftStart.split(":")[0]);
|
|
34517
|
+
const startMinute = parseInt(shiftStart.split(":")[1] || "0");
|
|
34122
34518
|
const endHour = parseInt(shiftEnd.split(":")[0]);
|
|
34519
|
+
const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
|
|
34123
34520
|
let shiftDuration = endHour - startHour;
|
|
34124
34521
|
if (shiftDuration <= 0) {
|
|
34125
34522
|
shiftDuration += 24;
|
|
34126
34523
|
}
|
|
34524
|
+
const hasPartialLastHour = endMinute > 0 && endMinute < 60;
|
|
34525
|
+
const hourCount = hasPartialLastHour ? Math.ceil(shiftDuration + endMinute / 60) : shiftDuration;
|
|
34127
34526
|
let expectedHours = [];
|
|
34128
|
-
for (let i = 0; i <
|
|
34527
|
+
for (let i = 0; i < hourCount; i++) {
|
|
34129
34528
|
expectedHours.push((startHour + i) % 24);
|
|
34130
34529
|
}
|
|
34131
|
-
return expectedHours.map((
|
|
34132
|
-
|
|
34133
|
-
|
|
34134
|
-
|
|
34530
|
+
return expectedHours.map((expectedHour, index) => {
|
|
34531
|
+
let hourSum = 0;
|
|
34532
|
+
const outputHourly = metrics2.output_hourly;
|
|
34533
|
+
const hourData = outputHourly[expectedHour.toString()] || [];
|
|
34534
|
+
if (startMinute > 0) {
|
|
34535
|
+
if (index === 0) {
|
|
34536
|
+
if (Array.isArray(hourData)) {
|
|
34537
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
34538
|
+
const val = hourData[i];
|
|
34539
|
+
if (val !== "x" && typeof val === "number") {
|
|
34540
|
+
hourSum += val;
|
|
34541
|
+
}
|
|
34542
|
+
}
|
|
34543
|
+
}
|
|
34544
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
34545
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
34546
|
+
if (Array.isArray(nextHourData)) {
|
|
34547
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
34548
|
+
const val = nextHourData[i];
|
|
34549
|
+
if (val !== "x" && typeof val === "number") {
|
|
34550
|
+
hourSum += val;
|
|
34551
|
+
}
|
|
34552
|
+
}
|
|
34553
|
+
}
|
|
34554
|
+
} else if (index < expectedHours.length - 1) {
|
|
34555
|
+
if (Array.isArray(hourData)) {
|
|
34556
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
34557
|
+
const val = hourData[i];
|
|
34558
|
+
if (val !== "x" && typeof val === "number") {
|
|
34559
|
+
hourSum += val;
|
|
34560
|
+
}
|
|
34561
|
+
}
|
|
34562
|
+
}
|
|
34563
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
34564
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
34565
|
+
if (Array.isArray(nextHourData)) {
|
|
34566
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
34567
|
+
const val = nextHourData[i];
|
|
34568
|
+
if (val !== "x" && typeof val === "number") {
|
|
34569
|
+
hourSum += val;
|
|
34570
|
+
}
|
|
34571
|
+
}
|
|
34572
|
+
}
|
|
34573
|
+
} else {
|
|
34574
|
+
if (hasPartialLastHour && endMinute > 0) {
|
|
34575
|
+
if (startMinute > 0) {
|
|
34576
|
+
if (Array.isArray(hourData)) {
|
|
34577
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
34578
|
+
const val = hourData[i];
|
|
34579
|
+
if (val !== "x" && typeof val === "number") {
|
|
34580
|
+
hourSum += val;
|
|
34581
|
+
}
|
|
34582
|
+
}
|
|
34583
|
+
}
|
|
34584
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
34585
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
34586
|
+
if (Array.isArray(nextHourData)) {
|
|
34587
|
+
for (let i = 0; i < endMinute && i < nextHourData.length; i++) {
|
|
34588
|
+
const val = nextHourData[i];
|
|
34589
|
+
if (val !== "x" && typeof val === "number") {
|
|
34590
|
+
hourSum += val;
|
|
34591
|
+
}
|
|
34592
|
+
}
|
|
34593
|
+
}
|
|
34594
|
+
} else {
|
|
34595
|
+
if (Array.isArray(hourData)) {
|
|
34596
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
34597
|
+
const val = hourData[i];
|
|
34598
|
+
if (val !== "x" && typeof val === "number") {
|
|
34599
|
+
hourSum += val;
|
|
34600
|
+
}
|
|
34601
|
+
}
|
|
34602
|
+
}
|
|
34603
|
+
}
|
|
34604
|
+
} else {
|
|
34605
|
+
if (Array.isArray(hourData)) {
|
|
34606
|
+
for (let i = startMinute; i < hourData.length; i++) {
|
|
34607
|
+
const val = hourData[i];
|
|
34608
|
+
if (val !== "x" && typeof val === "number") {
|
|
34609
|
+
hourSum += val;
|
|
34610
|
+
}
|
|
34611
|
+
}
|
|
34612
|
+
}
|
|
34613
|
+
const nextHour = (expectedHour + 1) % 24;
|
|
34614
|
+
const nextHourData = outputHourly[nextHour.toString()] || [];
|
|
34615
|
+
if (Array.isArray(nextHourData)) {
|
|
34616
|
+
for (let i = 0; i < startMinute && i < nextHourData.length; i++) {
|
|
34617
|
+
const val = nextHourData[i];
|
|
34618
|
+
if (val !== "x" && typeof val === "number") {
|
|
34619
|
+
hourSum += val;
|
|
34620
|
+
}
|
|
34621
|
+
}
|
|
34622
|
+
}
|
|
34623
|
+
}
|
|
34624
|
+
}
|
|
34625
|
+
} else {
|
|
34626
|
+
if (Array.isArray(hourData)) {
|
|
34627
|
+
hourData.forEach((val) => {
|
|
34628
|
+
if (val !== "x" && typeof val === "number") {
|
|
34629
|
+
hourSum += val;
|
|
34630
|
+
}
|
|
34631
|
+
});
|
|
34632
|
+
}
|
|
34633
|
+
if (index === expectedHours.length - 1 && hasPartialLastHour && endMinute > 0) {
|
|
34634
|
+
hourSum = 0;
|
|
34635
|
+
if (Array.isArray(hourData)) {
|
|
34636
|
+
for (let i = 0; i < endMinute && i < hourData.length; i++) {
|
|
34637
|
+
const val = hourData[i];
|
|
34638
|
+
if (val !== "x" && typeof val === "number") {
|
|
34639
|
+
hourSum += val;
|
|
34640
|
+
}
|
|
34641
|
+
}
|
|
34642
|
+
}
|
|
34643
|
+
}
|
|
34135
34644
|
}
|
|
34136
|
-
return
|
|
34645
|
+
return hourSum;
|
|
34137
34646
|
});
|
|
34138
34647
|
}
|
|
34139
34648
|
if (metrics2.output_array) {
|