@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.mjs CHANGED
@@ -878,20 +878,121 @@ var dashboardService = {
878
878
  }
879
879
  console.log("Expected shift hours:", expectedHours);
880
880
  console.log("Available data hours:", Object.keys(outputHourly));
881
- hourlyActionCounts = expectedHours.map((expectedHour) => {
882
- let hourData = outputHourly[expectedHour.toString()];
883
- if (!hourData && isNightShift) {
884
- for (const [storedHour, data2] of Object.entries(outputHourly)) {
885
- if (Array.isArray(data2) && data2.length > 0 && data2.some((val) => val > 0)) {
886
- if (storedHour === "18" && expectedHour === 1) {
887
- hourData = data2;
888
- console.log(`Mapping stored hour ${storedHour} to expected hour ${expectedHour}`);
889
- break;
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
+ }
890
991
  }
891
992
  }
892
993
  }
893
994
  }
894
- return Array.isArray(hourData) ? hourData.reduce((sum, count) => sum + (count || 0), 0) : 0;
995
+ return hourSum;
895
996
  });
896
997
  console.log("Final hourly action counts:", hourlyActionCounts);
897
998
  } else {
@@ -2092,136 +2193,142 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
2092
2193
  const now2 = /* @__PURE__ */ new Date();
2093
2194
  const currentHour = now2.getHours();
2094
2195
  const currentMinute = now2.getMinutes();
2095
- let shiftStartHour;
2096
- let shiftEndHour;
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;
2097
2205
  if (currentShiftId === 0) {
2098
- shiftStartHour = 9;
2099
- shiftEndHour = 18;
2206
+ shiftStart = parseShiftTime(dayShiftStart);
2207
+ shiftEnd = parseShiftTime(dayShiftEnd);
2100
2208
  } else {
2101
- shiftStartHour = 20;
2102
- shiftEndHour = 3;
2209
+ shiftStart = parseShiftTime(nightShiftStart);
2210
+ shiftEnd = parseShiftTime(nightShiftEnd);
2103
2211
  }
2104
2212
  let elapsedMinutes = 0;
2105
2213
  if (currentShiftId === 0) {
2106
- if (currentHour >= shiftStartHour && currentHour < shiftEndHour) {
2107
- elapsedMinutes = (currentHour - shiftStartHour) * 60 + currentMinute;
2108
- } else if (currentHour >= shiftEndHour) {
2109
- elapsedMinutes = (shiftEndHour - shiftStartHour) * 60;
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;
2110
2221
  }
2111
2222
  } else {
2112
- if (currentHour >= shiftStartHour) {
2113
- elapsedMinutes = (currentHour - shiftStartHour) * 60 + currentMinute;
2114
- } else if (currentHour < shiftEndHour) {
2115
- elapsedMinutes = (24 - shiftStartHour + currentHour) * 60 + currentMinute;
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
+ }
2116
2236
  }
2117
2237
  }
2118
2238
  const tableName = `performance_metrics_${companyId.replace(/-/g, "_")}`;
2119
- const query = `
2120
- WITH workspace_uptime AS (
2121
- SELECT
2122
- workspace_id,
2123
- workspace_display_name,
2124
- idle_time_hourly,
2125
- output_hourly,
2126
- shift_start,
2127
- shift_end
2128
- FROM ${tableName}
2129
- WHERE date = $1::date
2130
- AND shift_id = $2
2131
- ),
2132
- calculated_uptime AS (
2133
- SELECT
2134
- workspace_id,
2135
- workspace_display_name,
2136
- -- Calculate actual minutes from hourly data
2137
- (
2138
- SELECT COALESCE(SUM(
2139
- CASE
2140
- WHEN jsonb_array_length(idle_time_hourly->key::text) >= 58 THEN 60
2141
- WHEN jsonb_array_length(idle_time_hourly->key::text) > 0 THEN jsonb_array_length(idle_time_hourly->key::text)
2142
- ELSE 0
2143
- END
2144
- ), 0)
2145
- FROM jsonb_object_keys(idle_time_hourly) AS key
2146
- WHERE key::int >= $3 AND key::int < $4
2147
- ) +
2148
- -- Add current hour's data if applicable
2149
- CASE
2150
- WHEN $4::int >= $3 AND $4::int < $5 THEN
2151
- LEAST($6::int,
2152
- COALESCE(jsonb_array_length(idle_time_hourly->$4::text), 0))
2153
- ELSE 0
2154
- END as actual_minutes
2155
- FROM workspace_uptime
2156
- )
2157
- SELECT
2158
- workspace_id,
2159
- workspace_display_name,
2160
- actual_minutes,
2161
- $7::int as expected_minutes,
2162
- ROUND(
2163
- CASE
2164
- WHEN $7::int > 0 THEN (actual_minutes::numeric / $7::numeric) * 100
2165
- ELSE 100
2166
- END, 1
2167
- ) as uptime_percentage
2168
- FROM calculated_uptime
2169
- `;
2170
2239
  try {
2171
- const { data, error } = await supabase.rpc("sql_query", {
2172
- query_text: query,
2173
- params: [
2174
- currentDate,
2175
- currentShiftId,
2176
- shiftStartHour,
2177
- currentHour,
2178
- shiftEndHour,
2179
- currentMinute,
2180
- elapsedMinutes
2181
- ]
2182
- }).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);
2183
2241
  if (error) {
2184
- 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);
2185
- if (queryError) {
2186
- console.error("Error fetching performance metrics:", queryError);
2187
- return /* @__PURE__ */ new Map();
2188
- }
2189
- const uptimeMap2 = /* @__PURE__ */ new Map();
2190
- for (const record of queryData || []) {
2191
- let actualMinutes = 0;
2192
- const idleTimeHourly = record.idle_time_hourly || {};
2193
- if (idleTimeHourly && typeof idleTimeHourly === "object") {
2194
- for (const [hour, dataArray] of Object.entries(idleTimeHourly)) {
2195
- const hourNum = parseInt(hour);
2196
- if (hourNum >= shiftStartHour && hourNum < currentHour) {
2197
- const arrayLength = Array.isArray(dataArray) ? dataArray.length : 0;
2198
- actualMinutes += arrayLength >= 58 ? 60 : arrayLength;
2199
- } else if (hourNum === currentHour && currentHour >= shiftStartHour) {
2200
- const arrayLength = Array.isArray(dataArray) ? dataArray.length : 0;
2201
- actualMinutes += Math.min(currentMinute, arrayLength);
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) : [];
2202
2303
  }
2203
2304
  }
2204
2305
  }
2205
- const percentage = elapsedMinutes > 0 ? Math.round(actualMinutes / elapsedMinutes * 1e3) / 10 : 100;
2206
- uptimeMap2.set(record.workspace_id, {
2207
- expectedMinutes: elapsedMinutes,
2208
- actualMinutes,
2209
- percentage,
2210
- lastCalculated: (/* @__PURE__ */ new Date()).toISOString()
2211
- });
2212
- }
2213
- return uptimeMap2;
2214
- }
2215
- const uptimeMap = /* @__PURE__ */ new Map();
2216
- if (Array.isArray(data)) {
2217
- for (const record of data) {
2218
- uptimeMap.set(record.workspace_id, {
2219
- expectedMinutes: record.expected_minutes,
2220
- actualMinutes: record.actual_minutes,
2221
- percentage: record.uptime_percentage,
2222
- lastCalculated: (/* @__PURE__ */ new Date()).toISOString()
2223
- });
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;
2224
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
+ });
2225
2332
  }
2226
2333
  return uptimeMap;
2227
2334
  } catch (error) {
@@ -5690,20 +5797,121 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
5690
5797
  }
5691
5798
  console.log("Expected shift hours (fallback):", expectedHours);
5692
5799
  console.log("Available data hours (fallback):", Object.keys(outputHourly2));
5693
- hourlyActionCounts2 = expectedHours.map((expectedHour) => {
5694
- let hourData = outputHourly2[expectedHour.toString()];
5695
- if (!hourData && isNightShift) {
5696
- for (const [storedHour, data2] of Object.entries(outputHourly2)) {
5697
- if (Array.isArray(data2) && data2.length > 0 && data2.some((val) => val > 0)) {
5698
- if (storedHour === "18" && expectedHour === 1) {
5699
- hourData = data2;
5700
- console.log(`Mapping stored hour ${storedHour} to expected hour ${expectedHour} (fallback)`);
5701
- break;
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
+ }
5702
5910
  }
5703
5911
  }
5704
5912
  }
5705
5913
  }
5706
- return Array.isArray(hourData) ? hourData.reduce((sum, count) => sum + (count || 0), 0) : 0;
5914
+ return hourSum;
5707
5915
  });
5708
5916
  console.log("Final hourly action counts (fallback):", hourlyActionCounts2);
5709
5917
  } else {
@@ -5805,20 +6013,121 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
5805
6013
  }
5806
6014
  console.log("Expected shift hours:", expectedHours);
5807
6015
  console.log("Available data hours:", Object.keys(outputHourly));
5808
- hourlyActionCounts = expectedHours.map((expectedHour) => {
5809
- let hourData = outputHourly[expectedHour.toString()];
5810
- if (!hourData && isNightShift) {
5811
- for (const [storedHour, data2] of Object.entries(outputHourly)) {
5812
- if (Array.isArray(data2) && data2.length > 0 && data2.some((val) => val > 0)) {
5813
- if (storedHour === "18" && expectedHour === 1) {
5814
- hourData = data2;
5815
- console.log(`Mapping stored hour ${storedHour} to expected hour ${expectedHour}`);
5816
- break;
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
+ }
5817
6126
  }
5818
6127
  }
5819
6128
  }
5820
6129
  }
5821
- return Array.isArray(hourData) ? hourData.reduce((sum, count) => sum + (count || 0), 0) : 0;
6130
+ return hourSum;
5822
6131
  });
5823
6132
  console.log("Final hourly action counts:", hourlyActionCounts);
5824
6133
  } else {
@@ -21432,8 +21741,60 @@ var HourlyOutputChartComponent = ({
21432
21741
  const chartData = React19__default.useMemo(() => {
21433
21742
  return Array.from({ length: SHIFT_DURATION }, (_, i) => {
21434
21743
  const actualHour = (shiftStartTime.hour + i) % 24;
21435
- const idleArray = idleTimeHourly?.[actualHour.toString()] || [];
21436
- const idleMinutes = idleArray.filter((val) => val === "1").length;
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;
21437
21798
  return {
21438
21799
  hour: formatHour(i),
21439
21800
  timeRange: formatTimeRange(i),
@@ -21445,7 +21806,7 @@ var HourlyOutputChartComponent = ({
21445
21806
  idleArray
21446
21807
  };
21447
21808
  });
21448
- }, [animatedData, data, pphThreshold, idleTimeHourly, shiftStartTime.hour, formatHour, formatTimeRange]);
21809
+ }, [animatedData, data, pphThreshold, idleTimeHourly, shiftStartTime.hour, shiftStartTime.minute, shiftEndTime, formatHour, formatTimeRange, SHIFT_DURATION]);
21449
21810
  const IdleBar = React19__default.useMemo(() => {
21450
21811
  if (!idleBarState.visible) return null;
21451
21812
  return /* @__PURE__ */ jsx(
@@ -21605,13 +21966,13 @@ var HourlyOutputChartComponent = ({
21605
21966
  if (showIdleTime && data2.idleArray) {
21606
21967
  let currentRange = null;
21607
21968
  data2.idleArray.forEach((val, idx) => {
21608
- if (val === "1") {
21969
+ if (val === "1" || val === 1) {
21609
21970
  if (!currentRange) {
21610
21971
  currentRange = { start: idx, end: idx };
21611
21972
  } else {
21612
21973
  currentRange.end = idx;
21613
21974
  }
21614
- } else if (currentRange) {
21975
+ } else if (val !== "x" && currentRange) {
21615
21976
  idleRanges.push(currentRange);
21616
21977
  currentRange = null;
21617
21978
  }
@@ -34153,21 +34514,135 @@ var KPIDetailView = ({
34153
34514
  const shiftStart = metrics2.shift_start || (isNightShift ? "22:00" : "06:00");
34154
34515
  const shiftEnd = metrics2.shift_end || (isNightShift ? "06:00" : "14:00");
34155
34516
  const startHour = parseInt(shiftStart.split(":")[0]);
34517
+ const startMinute = parseInt(shiftStart.split(":")[1] || "0");
34156
34518
  const endHour = parseInt(shiftEnd.split(":")[0]);
34519
+ const endMinute = parseInt(shiftEnd.split(":")[1] || "0");
34157
34520
  let shiftDuration = endHour - startHour;
34158
34521
  if (shiftDuration <= 0) {
34159
34522
  shiftDuration += 24;
34160
34523
  }
34524
+ const hasPartialLastHour = endMinute > 0 && endMinute < 60;
34525
+ const hourCount = hasPartialLastHour ? Math.ceil(shiftDuration + endMinute / 60) : shiftDuration;
34161
34526
  let expectedHours = [];
34162
- for (let i = 0; i < shiftDuration; i++) {
34527
+ for (let i = 0; i < hourCount; i++) {
34163
34528
  expectedHours.push((startHour + i) % 24);
34164
34529
  }
34165
- return expectedHours.map((hour) => {
34166
- const hourData = metrics2.output_hourly[hour.toString()];
34167
- if (hourData && Array.isArray(hourData)) {
34168
- return hourData.reduce((sum, val) => sum + (val || 0), 0);
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
+ }
34169
34644
  }
34170
- return 0;
34645
+ return hourSum;
34171
34646
  });
34172
34647
  }
34173
34648
  if (metrics2.output_array) {