@optifye/dashboard-core 6.5.9 → 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.
Files changed (3) hide show
  1. package/dist/index.js +630 -155
  2. package/dist/index.mjs +630 -155
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -908,20 +908,121 @@ var dashboardService = {
908
908
  }
909
909
  console.log("Expected shift hours:", expectedHours);
910
910
  console.log("Available data hours:", Object.keys(outputHourly));
911
- hourlyActionCounts = expectedHours.map((expectedHour) => {
912
- let hourData = outputHourly[expectedHour.toString()];
913
- if (!hourData && isNightShift) {
914
- for (const [storedHour, data2] of Object.entries(outputHourly)) {
915
- if (Array.isArray(data2) && data2.length > 0 && data2.some((val) => val > 0)) {
916
- if (storedHour === "18" && expectedHour === 1) {
917
- hourData = data2;
918
- console.log(`Mapping stored hour ${storedHour} to expected hour ${expectedHour}`);
919
- break;
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
+ }
920
1021
  }
921
1022
  }
922
1023
  }
923
1024
  }
924
- return Array.isArray(hourData) ? hourData.reduce((sum, count) => sum + (count || 0), 0) : 0;
1025
+ return hourSum;
925
1026
  });
926
1027
  console.log("Final hourly action counts:", hourlyActionCounts);
927
1028
  } else {
@@ -2122,136 +2223,142 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
2122
2223
  const now2 = /* @__PURE__ */ new Date();
2123
2224
  const currentHour = now2.getHours();
2124
2225
  const currentMinute = now2.getMinutes();
2125
- let shiftStartHour;
2126
- let shiftEndHour;
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;
2127
2235
  if (currentShiftId === 0) {
2128
- shiftStartHour = 9;
2129
- shiftEndHour = 18;
2236
+ shiftStart = parseShiftTime(dayShiftStart);
2237
+ shiftEnd = parseShiftTime(dayShiftEnd);
2130
2238
  } else {
2131
- shiftStartHour = 20;
2132
- shiftEndHour = 3;
2239
+ shiftStart = parseShiftTime(nightShiftStart);
2240
+ shiftEnd = parseShiftTime(nightShiftEnd);
2133
2241
  }
2134
2242
  let elapsedMinutes = 0;
2135
2243
  if (currentShiftId === 0) {
2136
- if (currentHour >= shiftStartHour && currentHour < shiftEndHour) {
2137
- elapsedMinutes = (currentHour - shiftStartHour) * 60 + currentMinute;
2138
- } else if (currentHour >= shiftEndHour) {
2139
- elapsedMinutes = (shiftEndHour - shiftStartHour) * 60;
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;
2140
2251
  }
2141
2252
  } else {
2142
- if (currentHour >= shiftStartHour) {
2143
- elapsedMinutes = (currentHour - shiftStartHour) * 60 + currentMinute;
2144
- } else if (currentHour < shiftEndHour) {
2145
- elapsedMinutes = (24 - shiftStartHour + currentHour) * 60 + currentMinute;
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
+ }
2146
2266
  }
2147
2267
  }
2148
2268
  const tableName = `performance_metrics_${companyId.replace(/-/g, "_")}`;
2149
- const query = `
2150
- WITH workspace_uptime AS (
2151
- SELECT
2152
- workspace_id,
2153
- workspace_display_name,
2154
- idle_time_hourly,
2155
- output_hourly,
2156
- shift_start,
2157
- shift_end
2158
- FROM ${tableName}
2159
- WHERE date = $1::date
2160
- AND shift_id = $2
2161
- ),
2162
- calculated_uptime AS (
2163
- SELECT
2164
- workspace_id,
2165
- workspace_display_name,
2166
- -- Calculate actual minutes from hourly data
2167
- (
2168
- SELECT COALESCE(SUM(
2169
- CASE
2170
- WHEN jsonb_array_length(idle_time_hourly->key::text) >= 58 THEN 60
2171
- WHEN jsonb_array_length(idle_time_hourly->key::text) > 0 THEN jsonb_array_length(idle_time_hourly->key::text)
2172
- ELSE 0
2173
- END
2174
- ), 0)
2175
- FROM jsonb_object_keys(idle_time_hourly) AS key
2176
- WHERE key::int >= $3 AND key::int < $4
2177
- ) +
2178
- -- Add current hour's data if applicable
2179
- CASE
2180
- WHEN $4::int >= $3 AND $4::int < $5 THEN
2181
- LEAST($6::int,
2182
- COALESCE(jsonb_array_length(idle_time_hourly->$4::text), 0))
2183
- ELSE 0
2184
- END as actual_minutes
2185
- FROM workspace_uptime
2186
- )
2187
- SELECT
2188
- workspace_id,
2189
- workspace_display_name,
2190
- actual_minutes,
2191
- $7::int as expected_minutes,
2192
- ROUND(
2193
- CASE
2194
- WHEN $7::int > 0 THEN (actual_minutes::numeric / $7::numeric) * 100
2195
- ELSE 100
2196
- END, 1
2197
- ) as uptime_percentage
2198
- FROM calculated_uptime
2199
- `;
2200
2269
  try {
2201
- const { data, error } = await supabase.rpc("sql_query", {
2202
- query_text: query,
2203
- params: [
2204
- currentDate,
2205
- currentShiftId,
2206
- shiftStartHour,
2207
- currentHour,
2208
- shiftEndHour,
2209
- currentMinute,
2210
- elapsedMinutes
2211
- ]
2212
- }).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);
2213
2271
  if (error) {
2214
- const { data: queryData, error: queryError } = await supabase.from(tableName).select("workspace_id, workspace_display_name, idle_time_hourly, output_hourly").eq("date", currentDate).eq("shift_id", currentShiftId);
2215
- if (queryError) {
2216
- console.error("Error fetching performance metrics:", queryError);
2217
- return /* @__PURE__ */ new Map();
2218
- }
2219
- const uptimeMap2 = /* @__PURE__ */ new Map();
2220
- for (const record of queryData || []) {
2221
- let actualMinutes = 0;
2222
- const idleTimeHourly = record.idle_time_hourly || {};
2223
- if (idleTimeHourly && typeof idleTimeHourly === "object") {
2224
- for (const [hour, dataArray] of Object.entries(idleTimeHourly)) {
2225
- const hourNum = parseInt(hour);
2226
- if (hourNum >= shiftStartHour && hourNum < currentHour) {
2227
- const arrayLength = Array.isArray(dataArray) ? dataArray.length : 0;
2228
- actualMinutes += arrayLength >= 58 ? 60 : arrayLength;
2229
- } else if (hourNum === currentHour && currentHour >= shiftStartHour) {
2230
- const arrayLength = Array.isArray(dataArray) ? dataArray.length : 0;
2231
- actualMinutes += Math.min(currentMinute, arrayLength);
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) : [];
2232
2333
  }
2233
2334
  }
2234
2335
  }
2235
- const percentage = elapsedMinutes > 0 ? Math.round(actualMinutes / elapsedMinutes * 1e3) / 10 : 100;
2236
- uptimeMap2.set(record.workspace_id, {
2237
- expectedMinutes: elapsedMinutes,
2238
- actualMinutes,
2239
- percentage,
2240
- lastCalculated: (/* @__PURE__ */ new Date()).toISOString()
2241
- });
2242
- }
2243
- return uptimeMap2;
2244
- }
2245
- const uptimeMap = /* @__PURE__ */ new Map();
2246
- if (Array.isArray(data)) {
2247
- for (const record of data) {
2248
- uptimeMap.set(record.workspace_id, {
2249
- expectedMinutes: record.expected_minutes,
2250
- actualMinutes: record.actual_minutes,
2251
- percentage: record.uptime_percentage,
2252
- lastCalculated: (/* @__PURE__ */ new Date()).toISOString()
2253
- });
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;
2254
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
+ });
2255
2362
  }
2256
2363
  return uptimeMap;
2257
2364
  } catch (error) {
@@ -5720,20 +5827,121 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
5720
5827
  }
5721
5828
  console.log("Expected shift hours (fallback):", expectedHours);
5722
5829
  console.log("Available data hours (fallback):", Object.keys(outputHourly2));
5723
- hourlyActionCounts2 = expectedHours.map((expectedHour) => {
5724
- let hourData = outputHourly2[expectedHour.toString()];
5725
- if (!hourData && isNightShift) {
5726
- for (const [storedHour, data2] of Object.entries(outputHourly2)) {
5727
- if (Array.isArray(data2) && data2.length > 0 && data2.some((val) => val > 0)) {
5728
- if (storedHour === "18" && expectedHour === 1) {
5729
- hourData = data2;
5730
- console.log(`Mapping stored hour ${storedHour} to expected hour ${expectedHour} (fallback)`);
5731
- break;
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
+ }
5732
5940
  }
5733
5941
  }
5734
5942
  }
5735
5943
  }
5736
- return Array.isArray(hourData) ? hourData.reduce((sum, count) => sum + (count || 0), 0) : 0;
5944
+ return hourSum;
5737
5945
  });
5738
5946
  console.log("Final hourly action counts (fallback):", hourlyActionCounts2);
5739
5947
  } else {
@@ -5835,20 +6043,121 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
5835
6043
  }
5836
6044
  console.log("Expected shift hours:", expectedHours);
5837
6045
  console.log("Available data hours:", Object.keys(outputHourly));
5838
- hourlyActionCounts = expectedHours.map((expectedHour) => {
5839
- let hourData = outputHourly[expectedHour.toString()];
5840
- if (!hourData && isNightShift) {
5841
- for (const [storedHour, data2] of Object.entries(outputHourly)) {
5842
- if (Array.isArray(data2) && data2.length > 0 && data2.some((val) => val > 0)) {
5843
- if (storedHour === "18" && expectedHour === 1) {
5844
- hourData = data2;
5845
- console.log(`Mapping stored hour ${storedHour} to expected hour ${expectedHour}`);
5846
- break;
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
+ }
5847
6156
  }
5848
6157
  }
5849
6158
  }
5850
6159
  }
5851
- return Array.isArray(hourData) ? hourData.reduce((sum, count) => sum + (count || 0), 0) : 0;
6160
+ return hourSum;
5852
6161
  });
5853
6162
  console.log("Final hourly action counts:", hourlyActionCounts);
5854
6163
  } else {
@@ -21462,8 +21771,60 @@ var HourlyOutputChartComponent = ({
21462
21771
  const chartData = React19__namespace.default.useMemo(() => {
21463
21772
  return Array.from({ length: SHIFT_DURATION }, (_, i) => {
21464
21773
  const actualHour = (shiftStartTime.hour + i) % 24;
21465
- const idleArray = idleTimeHourly?.[actualHour.toString()] || [];
21466
- const idleMinutes = idleArray.filter((val) => val === "1").length;
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;
21467
21828
  return {
21468
21829
  hour: formatHour(i),
21469
21830
  timeRange: formatTimeRange(i),
@@ -21475,7 +21836,7 @@ var HourlyOutputChartComponent = ({
21475
21836
  idleArray
21476
21837
  };
21477
21838
  });
21478
- }, [animatedData, data, pphThreshold, idleTimeHourly, shiftStartTime.hour, formatHour, formatTimeRange]);
21839
+ }, [animatedData, data, pphThreshold, idleTimeHourly, shiftStartTime.hour, shiftStartTime.minute, shiftEndTime, formatHour, formatTimeRange, SHIFT_DURATION]);
21479
21840
  const IdleBar = React19__namespace.default.useMemo(() => {
21480
21841
  if (!idleBarState.visible) return null;
21481
21842
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -21635,13 +21996,13 @@ var HourlyOutputChartComponent = ({
21635
21996
  if (showIdleTime && data2.idleArray) {
21636
21997
  let currentRange = null;
21637
21998
  data2.idleArray.forEach((val, idx) => {
21638
- if (val === "1") {
21999
+ if (val === "1" || val === 1) {
21639
22000
  if (!currentRange) {
21640
22001
  currentRange = { start: idx, end: idx };
21641
22002
  } else {
21642
22003
  currentRange.end = idx;
21643
22004
  }
21644
- } else if (currentRange) {
22005
+ } else if (val !== "x" && currentRange) {
21645
22006
  idleRanges.push(currentRange);
21646
22007
  currentRange = null;
21647
22008
  }
@@ -34183,21 +34544,135 @@ var KPIDetailView = ({
34183
34544
  const shiftStart = metrics2.shift_start || (isNightShift ? "22:00" : "06:00");
34184
34545
  const shiftEnd = metrics2.shift_end || (isNightShift ? "06:00" : "14:00");
34185
34546
  const startHour = parseInt(shiftStart.split(":")[0]);
34547
+ const startMinute = parseInt(shiftStart.split(":")[1] || "0");
34186
34548
  const endHour = parseInt(shiftEnd.split(":")[0]);
34549
+ const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
34187
34550
  let shiftDuration = endHour - startHour;
34188
34551
  if (shiftDuration <= 0) {
34189
34552
  shiftDuration += 24;
34190
34553
  }
34554
+ const hasPartialLastHour = endMinute > 0 && endMinute < 60;
34555
+ const hourCount = hasPartialLastHour ? Math.ceil(shiftDuration + endMinute / 60) : shiftDuration;
34191
34556
  let expectedHours = [];
34192
- for (let i = 0; i < shiftDuration; i++) {
34557
+ for (let i = 0; i < hourCount; i++) {
34193
34558
  expectedHours.push((startHour + i) % 24);
34194
34559
  }
34195
- return expectedHours.map((hour) => {
34196
- const hourData = metrics2.output_hourly[hour.toString()];
34197
- if (hourData && Array.isArray(hourData)) {
34198
- return hourData.reduce((sum, val) => sum + (val || 0), 0);
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
+ }
34199
34674
  }
34200
- return 0;
34675
+ return hourSum;
34201
34676
  });
34202
34677
  }
34203
34678
  if (metrics2.output_array) {