@optifye/dashboard-core 6.5.2 → 6.5.3

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 CHANGED
@@ -1905,7 +1905,29 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
1905
1905
  throw error;
1906
1906
  }
1907
1907
  const processedData = (data || []).map((item) => this.processHealthStatus(item));
1908
- let filteredData = processedData;
1908
+ let uptimeMap = /* @__PURE__ */ new Map();
1909
+ if (options.companyId || data && data.length > 0) {
1910
+ const companyId = options.companyId || data[0]?.company_id;
1911
+ if (companyId) {
1912
+ try {
1913
+ uptimeMap = await this.calculateWorkspaceUptime(companyId);
1914
+ } catch (error2) {
1915
+ console.error("Error calculating uptime:", error2);
1916
+ }
1917
+ }
1918
+ }
1919
+ const dataWithUptime = processedData.map((workspace) => {
1920
+ const uptimeDetails = uptimeMap.get(workspace.workspace_id);
1921
+ if (uptimeDetails) {
1922
+ return {
1923
+ ...workspace,
1924
+ uptimePercentage: uptimeDetails.percentage,
1925
+ uptimeDetails
1926
+ };
1927
+ }
1928
+ return workspace;
1929
+ });
1930
+ let filteredData = dataWithUptime;
1909
1931
  try {
1910
1932
  const { data: enabledWorkspaces, error: workspaceError } = await supabase.from("workspaces").select("workspace_id, display_name").eq("enable", true);
1911
1933
  if (!workspaceError && enabledWorkspaces && enabledWorkspaces.length > 0) {
@@ -1981,13 +2003,31 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
1981
2003
  const healthyWorkspaces = workspaces.filter((w) => w.status === "healthy").length;
1982
2004
  const unhealthyWorkspaces = workspaces.filter((w) => w.status === "unhealthy").length;
1983
2005
  const warningWorkspaces = workspaces.filter((w) => w.status === "warning").length;
1984
- const uptimePercentage = totalWorkspaces > 0 ? healthyWorkspaces / totalWorkspaces * 100 : 0;
2006
+ let uptimePercentage = 0;
2007
+ let totalDowntimeMinutes = 0;
2008
+ if (totalWorkspaces > 0) {
2009
+ const workspacesWithUptime = workspaces.filter((w) => w.uptimePercentage !== void 0 && w.uptimeDetails !== void 0);
2010
+ if (workspacesWithUptime.length > 0) {
2011
+ const totalUptime = workspacesWithUptime.reduce((sum, w) => sum + (w.uptimePercentage || 0), 0);
2012
+ uptimePercentage = totalUptime / workspacesWithUptime.length;
2013
+ totalDowntimeMinutes = workspacesWithUptime.reduce((sum, w) => {
2014
+ if (w.uptimeDetails) {
2015
+ const downtime = Math.max(0, w.uptimeDetails.expectedMinutes - w.uptimeDetails.actualMinutes);
2016
+ return sum + downtime;
2017
+ }
2018
+ return sum;
2019
+ }, 0);
2020
+ } else {
2021
+ uptimePercentage = healthyWorkspaces / totalWorkspaces * 100;
2022
+ }
2023
+ }
1985
2024
  return {
1986
2025
  totalWorkspaces,
1987
2026
  healthyWorkspaces,
1988
2027
  unhealthyWorkspaces,
1989
2028
  warningWorkspaces,
1990
2029
  uptimePercentage,
2030
+ totalDowntimeMinutes,
1991
2031
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
1992
2032
  };
1993
2033
  }
@@ -2067,6 +2107,155 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
2067
2107
  clearCache() {
2068
2108
  this.cache.clear();
2069
2109
  }
2110
+ async calculateWorkspaceUptime(companyId) {
2111
+ const supabase = _getSupabaseInstance();
2112
+ if (!supabase) throw new Error("Supabase client not initialized");
2113
+ const dashboardConfig = _getDashboardConfigInstance();
2114
+ const timezone = dashboardConfig?.dateTimeConfig?.defaultTimezone || "UTC";
2115
+ const shiftConfig = dashboardConfig?.shiftConfig;
2116
+ const currentShiftInfo = getCurrentShift(timezone, shiftConfig);
2117
+ const currentDate = currentShiftInfo.date;
2118
+ const currentShiftId = currentShiftInfo.shiftId;
2119
+ const now2 = /* @__PURE__ */ new Date();
2120
+ const currentHour = now2.getHours();
2121
+ const currentMinute = now2.getMinutes();
2122
+ let shiftStartHour;
2123
+ let shiftEndHour;
2124
+ if (currentShiftId === 0) {
2125
+ shiftStartHour = 9;
2126
+ shiftEndHour = 18;
2127
+ } else {
2128
+ shiftStartHour = 20;
2129
+ shiftEndHour = 3;
2130
+ }
2131
+ let elapsedMinutes = 0;
2132
+ if (currentShiftId === 0) {
2133
+ if (currentHour >= shiftStartHour && currentHour < shiftEndHour) {
2134
+ elapsedMinutes = (currentHour - shiftStartHour) * 60 + currentMinute;
2135
+ } else if (currentHour >= shiftEndHour) {
2136
+ elapsedMinutes = (shiftEndHour - shiftStartHour) * 60;
2137
+ }
2138
+ } else {
2139
+ if (currentHour >= shiftStartHour) {
2140
+ elapsedMinutes = (currentHour - shiftStartHour) * 60 + currentMinute;
2141
+ } else if (currentHour < shiftEndHour) {
2142
+ elapsedMinutes = (24 - shiftStartHour + currentHour) * 60 + currentMinute;
2143
+ }
2144
+ }
2145
+ const tableName = `performance_metrics_${companyId.replace(/-/g, "_")}`;
2146
+ const query = `
2147
+ WITH workspace_uptime AS (
2148
+ SELECT
2149
+ workspace_id,
2150
+ workspace_display_name,
2151
+ idle_time_hourly,
2152
+ output_hourly,
2153
+ shift_start,
2154
+ shift_end
2155
+ FROM ${tableName}
2156
+ WHERE date = $1::date
2157
+ AND shift_id = $2
2158
+ ),
2159
+ calculated_uptime AS (
2160
+ SELECT
2161
+ workspace_id,
2162
+ workspace_display_name,
2163
+ -- Calculate actual minutes from hourly data
2164
+ (
2165
+ SELECT COALESCE(SUM(
2166
+ CASE
2167
+ WHEN jsonb_array_length(idle_time_hourly->key::text) >= 58 THEN 60
2168
+ WHEN jsonb_array_length(idle_time_hourly->key::text) > 0 THEN jsonb_array_length(idle_time_hourly->key::text)
2169
+ ELSE 0
2170
+ END
2171
+ ), 0)
2172
+ FROM jsonb_object_keys(idle_time_hourly) AS key
2173
+ WHERE key::int >= $3 AND key::int < $4
2174
+ ) +
2175
+ -- Add current hour's data if applicable
2176
+ CASE
2177
+ WHEN $4::int >= $3 AND $4::int < $5 THEN
2178
+ LEAST($6::int,
2179
+ COALESCE(jsonb_array_length(idle_time_hourly->$4::text), 0))
2180
+ ELSE 0
2181
+ END as actual_minutes
2182
+ FROM workspace_uptime
2183
+ )
2184
+ SELECT
2185
+ workspace_id,
2186
+ workspace_display_name,
2187
+ actual_minutes,
2188
+ $7::int as expected_minutes,
2189
+ ROUND(
2190
+ CASE
2191
+ WHEN $7::int > 0 THEN (actual_minutes::numeric / $7::numeric) * 100
2192
+ ELSE 100
2193
+ END, 1
2194
+ ) as uptime_percentage
2195
+ FROM calculated_uptime
2196
+ `;
2197
+ try {
2198
+ const { data, error } = await supabase.rpc("sql_query", {
2199
+ query_text: query,
2200
+ params: [
2201
+ currentDate,
2202
+ currentShiftId,
2203
+ shiftStartHour,
2204
+ currentHour,
2205
+ shiftEndHour,
2206
+ currentMinute,
2207
+ elapsedMinutes
2208
+ ]
2209
+ }).single();
2210
+ if (error) {
2211
+ 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);
2212
+ if (queryError) {
2213
+ console.error("Error fetching performance metrics:", queryError);
2214
+ return /* @__PURE__ */ new Map();
2215
+ }
2216
+ const uptimeMap2 = /* @__PURE__ */ new Map();
2217
+ for (const record of queryData || []) {
2218
+ let actualMinutes = 0;
2219
+ const idleTimeHourly = record.idle_time_hourly || {};
2220
+ if (idleTimeHourly && typeof idleTimeHourly === "object") {
2221
+ for (const [hour, dataArray] of Object.entries(idleTimeHourly)) {
2222
+ const hourNum = parseInt(hour);
2223
+ if (hourNum >= shiftStartHour && hourNum < currentHour) {
2224
+ const arrayLength = Array.isArray(dataArray) ? dataArray.length : 0;
2225
+ actualMinutes += arrayLength >= 58 ? 60 : arrayLength;
2226
+ } else if (hourNum === currentHour && currentHour >= shiftStartHour) {
2227
+ const arrayLength = Array.isArray(dataArray) ? dataArray.length : 0;
2228
+ actualMinutes += Math.min(currentMinute, arrayLength);
2229
+ }
2230
+ }
2231
+ }
2232
+ const percentage = elapsedMinutes > 0 ? Math.round(actualMinutes / elapsedMinutes * 1e3) / 10 : 100;
2233
+ uptimeMap2.set(record.workspace_id, {
2234
+ expectedMinutes: elapsedMinutes,
2235
+ actualMinutes,
2236
+ percentage,
2237
+ lastCalculated: (/* @__PURE__ */ new Date()).toISOString()
2238
+ });
2239
+ }
2240
+ return uptimeMap2;
2241
+ }
2242
+ const uptimeMap = /* @__PURE__ */ new Map();
2243
+ if (Array.isArray(data)) {
2244
+ for (const record of data) {
2245
+ uptimeMap.set(record.workspace_id, {
2246
+ expectedMinutes: record.expected_minutes,
2247
+ actualMinutes: record.actual_minutes,
2248
+ percentage: record.uptime_percentage,
2249
+ lastCalculated: (/* @__PURE__ */ new Date()).toISOString()
2250
+ });
2251
+ }
2252
+ }
2253
+ return uptimeMap;
2254
+ } catch (error) {
2255
+ console.error("Error calculating workspace uptime:", error);
2256
+ return /* @__PURE__ */ new Map();
2257
+ }
2258
+ }
2070
2259
  };
2071
2260
  var workspaceHealthService = WorkspaceHealthService.getInstance();
2072
2261
 
@@ -19725,7 +19914,7 @@ var OptifyeLogoLoader = ({
19725
19914
  className: `${sizeClasses[size]} h-auto animate-pulse select-none pointer-events-none`
19726
19915
  }
19727
19916
  ),
19728
- message && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 text-gray-600 text-sm font-medium text-center", children: message })
19917
+ message && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 text-gray-600 text-base sm:text-sm font-medium text-center", children: message })
19729
19918
  ]
19730
19919
  }
19731
19920
  );
@@ -21636,8 +21825,8 @@ var VideoCard = React19__namespace.default.memo(({
21636
21825
  ] }) }),
21637
21826
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full h-full overflow-hidden bg-black", children: [
21638
21827
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-black z-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "animate-pulse flex flex-col items-center", children: [
21639
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Camera, { className: `${compact ? "w-4 h-4" : "w-6 h-6"} text-gray-500` }),
21640
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${compact ? "text-[10px]" : "text-xs"} text-gray-500 mt-1`, children: "Loading..." })
21828
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Camera, { className: `w-5 h-5 sm:${compact ? "w-4 h-4" : "w-6 h-6"} text-gray-500` }),
21829
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-[11px] sm:${compact ? "text-[10px]" : "text-xs"} text-gray-500 mt-1`, children: "Loading..." })
21641
21830
  ] }) }),
21642
21831
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 z-10", children: [
21643
21832
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -21672,10 +21861,10 @@ var VideoCard = React19__namespace.default.memo(({
21672
21861
  }
21673
21862
  ) })
21674
21863
  ] }),
21675
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `absolute bottom-0 left-0 right-0 bg-black bg-opacity-60 ${compact ? "p-1" : "p-1.5"} flex justify-between items-center z-10`, children: [
21864
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `absolute bottom-0 left-0 right-0 bg-black bg-opacity-60 p-1.5 sm:${compact ? "p-1" : "p-1.5"} flex justify-between items-center z-10`, children: [
21676
21865
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
21677
21866
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Camera, { size: compact ? 10 : 12, className: "text-white" }),
21678
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-white ${compact ? "text-[10px]" : "text-xs"} font-medium tracking-wide`, children: displayName })
21867
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-white text-[11px] sm:${compact ? "text-[10px]" : "text-xs"} font-medium tracking-wide`, children: displayName })
21679
21868
  ] }),
21680
21869
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center ${compact ? "gap-1" : "gap-1.5"}`, children: [
21681
21870
  trendInfo && /* @__PURE__ */ jsxRuntime.jsx(
@@ -21687,7 +21876,7 @@ var VideoCard = React19__namespace.default.memo(({
21687
21876
  }
21688
21877
  ),
21689
21878
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${compact ? "w-1 h-1" : "w-1.5 h-1.5"} rounded-full bg-green-500` }),
21690
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-white ${compact ? "text-[10px]" : "text-xs"}`, children: "Live" })
21879
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-white text-[11px] sm:${compact ? "text-[10px]" : "text-xs"}`, children: "Live" })
21691
21880
  ] })
21692
21881
  ] })
21693
21882
  ]
@@ -21897,10 +22086,10 @@ var VideoGridView = React19__namespace.default.memo(({
21897
22086
  view_type: "video_grid"
21898
22087
  });
21899
22088
  }, []);
21900
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `relative overflow-hidden h-full w-full ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: "h-full w-full p-2", children: /* @__PURE__ */ jsxRuntime.jsx(
22089
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `relative overflow-hidden h-full w-full ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: "h-full w-full p-3 sm:p-2", children: /* @__PURE__ */ jsxRuntime.jsx(
21901
22090
  "div",
21902
22091
  {
21903
- className: "grid h-full w-full gap-2",
22092
+ className: "grid h-full w-full gap-3 sm:gap-2",
21904
22093
  style: {
21905
22094
  gridTemplateColumns: `repeat(${gridCols}, 1fr)`,
21906
22095
  gridTemplateRows: `repeat(${gridRows}, 1fr)`,
@@ -22685,15 +22874,15 @@ var BreakNotificationPopup = ({
22685
22874
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 bg-amber-500 rounded-full animate-pulse flex-shrink-0 mt-2" }),
22686
22875
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
22687
22876
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1", children: [
22688
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-semibold text-sm text-gray-900", children: breakItem.remarks || "Break" }),
22689
- (activeBreaks.length > 1 || lineNames[breakItem.lineId]) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500 mt-0.5", children: lineNames[breakItem.lineId] || `Line ${breakItem.lineId.substring(0, 8)}` })
22877
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-semibold text-base sm:text-sm text-gray-900", children: breakItem.remarks || "Break" }),
22878
+ (activeBreaks.length > 1 || lineNames[breakItem.lineId]) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm sm:text-xs text-gray-500 mt-0.5", children: lineNames[breakItem.lineId] || `Line ${breakItem.lineId.substring(0, 8)}` })
22690
22879
  ] }),
22691
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-gray-600 font-medium", children: [
22880
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm sm:text-xs text-gray-600 font-medium", children: [
22692
22881
  breakItem.startTime,
22693
22882
  " - ",
22694
22883
  breakItem.endTime
22695
22884
  ] }) }),
22696
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-gray-500", children: [
22885
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm sm:text-xs text-gray-500", children: [
22697
22886
  formatTime3(breakItem.elapsedMinutes),
22698
22887
  " / ",
22699
22888
  formatTime3(breakItem.duration)
@@ -23411,7 +23600,7 @@ var TimeDisplay = ({ className, variant = "default" }) => {
23411
23600
  className: `flex items-center space-x-1.5 bg-white/60 backdrop-blur-sm px-2 py-0.5 rounded-md shadow-xs ${className || ""}`,
23412
23601
  children: [
23413
23602
  /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-3 w-3 text-[var(--primary-DEFAULT)]", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z", clipRule: "evenodd" }) }),
23414
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] font-medium text-gray-800 tabular-nums tracking-tight", children: [
23603
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs sm:text-[11px] font-medium text-gray-800 tabular-nums tracking-tight", children: [
23415
23604
  time2,
23416
23605
  " ",
23417
23606
  timeSuffix
@@ -28087,7 +28276,7 @@ var WorkspaceGridItem = React19__namespace.default.memo(({
28087
28276
  isVeryLowEfficiency && !isInactive && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -top-10 left-1/2 -translate-x-1/2 z-30", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
28088
28277
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -inset-1 bg-red-400/50 rounded-full blur-sm animate-pulse" }),
28089
28278
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -inset-0.5 bg-red-500/30 rounded-full blur-md animate-ping [animation-duration:1.5s]" }),
28090
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-[#E34329] w-9 h-9 rounded-full flex items-center justify-center text-white font-bold text-lg shadow-lg ring-2 ring-red-400/40 border border-red-400/80 animate-pulse", children: "!" })
28279
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-[#E34329] w-8 h-8 sm:w-9 sm:h-9 rounded-full flex items-center justify-center text-white font-bold text-base sm:text-lg shadow-lg ring-2 ring-red-400/40 border border-red-400/80 animate-pulse", children: "!" })
28091
28280
  ] }) }),
28092
28281
  /* @__PURE__ */ jsxRuntime.jsx(
28093
28282
  "button",
@@ -28096,14 +28285,14 @@ var WorkspaceGridItem = React19__namespace.default.memo(({
28096
28285
  className: `${styles2} ${colorClass} ${isBottleneck ? "ring-2 ring-red-500/70" : ""} ${isVeryLowEfficiency ? "ring-2 ring-red-500/50" : ""} ${isInactive ? "bg-gray-200" : ""} shadow-lg`,
28097
28286
  "aria-label": isInactive ? `Inactive workspace ${workspaceNumber}` : `View details for workspace ${workspaceNumber}`,
28098
28287
  title: isInactive ? `Inactive: ${getWorkspaceDisplayName(data.workspace_name, data.line_id)}` : getWorkspaceDisplayName(data.workspace_name, data.line_id),
28099
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `font-semibold tracking-wide text-[min(4vw,2rem)] uppercase ${isInactive ? "text-gray-400" : "text-white"} drop-shadow-sm`, children: workspaceNumber })
28288
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `font-semibold tracking-wide text-lg sm:text-xl md:text-[min(4vw,2rem)] uppercase ${isInactive ? "text-gray-400" : "text-white"} drop-shadow-sm`, children: workspaceNumber })
28100
28289
  }
28101
28290
  ),
28102
28291
  arrow && !isInactive && /* @__PURE__ */ jsxRuntime.jsx(
28103
28292
  "div",
28104
28293
  {
28105
28294
  className: `absolute left-1/2 -translate-x-1/2 ${arrowPosition}
28106
- text-[min(3.5vw,2.25rem)] font-bold tracking-tight ${arrowColor} drop-shadow-sm`,
28295
+ text-base sm:text-lg md:text-[min(3.5vw,2.25rem)] font-bold tracking-tight ${arrowColor} drop-shadow-sm`,
28107
28296
  style: { bottom: "-2.5rem", lineHeight: 1, display: "flex", alignItems: "center", justifyContent: "center" },
28108
28297
  children: arrow
28109
28298
  }
@@ -28133,11 +28322,11 @@ var WorkspaceGrid = React19__namespace.default.memo(({
28133
28322
  }, [workspaces.length]);
28134
28323
  const { VideoGridView: VideoGridViewComponent } = useRegistry();
28135
28324
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative w-full h-full overflow-hidden ${className}`, children: [
28136
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute top-0 left-2 sm:left-4 right-2 sm:right-8 z-20", children: [
28137
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-row items-center justify-between py-1 sm:py-1.5 gap-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsxRuntime.jsx(Legend6, {}) }) }),
28138
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(Legend6, {}) })
28325
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute top-0 left-4 sm:left-4 right-4 sm:right-8 z-20", children: [
28326
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-row items-center justify-between py-2 sm:py-1.5 gap-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsxRuntime.jsx(Legend6, {}) }) }),
28327
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden mt-2", children: /* @__PURE__ */ jsxRuntime.jsx(Legend6, {}) })
28139
28328
  ] }),
28140
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-10 sm:top-16 left-0 right-0 bottom-0", children: /* @__PURE__ */ jsxRuntime.jsx(
28329
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-12 sm:top-16 left-0 right-0 bottom-0", children: /* @__PURE__ */ jsxRuntime.jsx(
28141
28330
  VideoGridViewComponent,
28142
28331
  {
28143
28332
  workspaces,
@@ -28352,8 +28541,8 @@ var KPICard = ({
28352
28541
  const cardClasses = clsx(
28353
28542
  // Base classes
28354
28543
  "rounded-lg transition-all duration-200",
28355
- // Sizing based on compact mode - extra compact on mobile
28356
- "p-1.5 sm:p-3 md:p-4",
28544
+ // Sizing based on compact mode - better padding on mobile
28545
+ "p-2.5 sm:p-3 md:p-4",
28357
28546
  // Variant-specific styling
28358
28547
  {
28359
28548
  "bg-white/50 backdrop-blur-sm border border-gray-200/60 shadow-sm hover:shadow-md dark:bg-gray-800/50 dark:border-gray-700/60": style.variant === "default",
@@ -28361,8 +28550,8 @@ var KPICard = ({
28361
28550
  "bg-blue-50 border border-blue-200 dark:bg-blue-900/20 dark:border-blue-800/30": style.variant === "filled",
28362
28551
  "bg-gray-50/50 dark:bg-gray-800/30": style.variant === "subtle"
28363
28552
  },
28364
- // Width for src matching - compact on mobile, flexible on small screens
28365
- !className?.includes("w-") && "w-[120px] sm:w-[180px] md:w-[220px]",
28553
+ // Width for src matching - better mobile width, flexible on small screens
28554
+ !className?.includes("w-") && "w-[110px] sm:w-[180px] md:w-[220px]",
28366
28555
  // Interactive styling if onClick is provided
28367
28556
  onClick && "cursor-pointer hover:scale-[1.01] active:scale-[0.99]",
28368
28557
  // Loading state
@@ -28381,14 +28570,14 @@ var KPICard = ({
28381
28570
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
28382
28571
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx(
28383
28572
  "font-medium text-gray-500 dark:text-gray-400",
28384
- "text-[9px] sm:text-xs md:text-sm",
28385
- "mb-0.5 sm:mb-1 md:mb-2",
28386
- "uppercase tracking-wider"
28573
+ "text-[10px] sm:text-xs md:text-sm",
28574
+ "mb-1 sm:mb-1 md:mb-2",
28575
+ "uppercase tracking-wide sm:tracking-wider"
28387
28576
  ), children: title }),
28388
28577
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-0.5 sm:gap-2 flex-wrap", children: [
28389
28578
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx(
28390
28579
  "font-bold text-gray-900 dark:text-gray-50",
28391
- "text-sm sm:text-xl md:text-2xl"
28580
+ "text-base sm:text-xl md:text-2xl"
28392
28581
  ), children: isLoading ? "\u2014" : formattedValue }),
28393
28582
  suffix && !isLoading && /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx(
28394
28583
  "font-medium text-gray-600 dark:text-gray-300",
@@ -28563,35 +28752,46 @@ var KPISection = React19.memo(({
28563
28752
  const outputDifference = kpis.outputProgress.current - kpis.outputProgress.idealOutput;
28564
28753
  const outputIsOnTarget = outputDifference >= 0;
28565
28754
  if (useSrcLayout) {
28566
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex gap-1 sm:gap-3 overflow-x-auto sm:overflow-visible pb-1 sm:pb-0 ${className || ""}`, children: [
28567
- /* @__PURE__ */ jsxRuntime.jsx(
28568
- KPICard,
28569
- {
28570
- title: "Underperforming",
28571
- value: "2/3",
28572
- change: 0
28573
- }
28574
- ),
28575
- /* @__PURE__ */ jsxRuntime.jsx(
28576
- KPICard,
28577
- {
28578
- title: "Efficiency",
28579
- value: kpis.efficiency.value,
28580
- change: kpis.efficiency.change,
28581
- suffix: "%"
28582
- }
28583
- ),
28584
- /* @__PURE__ */ jsxRuntime.jsx(
28585
- KPICard,
28586
- {
28587
- title: "Output Progress",
28588
- value: `${kpis.outputProgress.current}/${kpis.outputProgress.target}`,
28589
- change: kpis.outputProgress.change,
28590
- outputDifference,
28591
- showOutputDetails: true
28592
- }
28593
- )
28594
- ] });
28755
+ return /* @__PURE__ */ jsxRuntime.jsxs(
28756
+ "div",
28757
+ {
28758
+ className: `flex gap-2 sm:gap-3 overflow-x-auto sm:overflow-visible pb-2 sm:pb-0 ${className || ""}`,
28759
+ style: {
28760
+ scrollbarWidth: "none",
28761
+ msOverflowStyle: "none",
28762
+ WebkitScrollbar: { display: "none" }
28763
+ },
28764
+ children: [
28765
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
28766
+ KPICard,
28767
+ {
28768
+ title: "Underperforming",
28769
+ value: "2/3",
28770
+ change: 0
28771
+ }
28772
+ ) }),
28773
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
28774
+ KPICard,
28775
+ {
28776
+ title: "Efficiency",
28777
+ value: kpis.efficiency.value,
28778
+ change: kpis.efficiency.change,
28779
+ suffix: "%"
28780
+ }
28781
+ ) }),
28782
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
28783
+ KPICard,
28784
+ {
28785
+ title: "Output Progress",
28786
+ value: `${kpis.outputProgress.current}/${kpis.outputProgress.target}`,
28787
+ change: kpis.outputProgress.change,
28788
+ outputDifference,
28789
+ showOutputDetails: true
28790
+ }
28791
+ ) })
28792
+ ]
28793
+ }
28794
+ );
28595
28795
  }
28596
28796
  const kpiCardData = [
28597
28797
  {
@@ -28724,6 +28924,19 @@ var WorkspaceHealthCard = ({
28724
28924
  const formatTimeAgo = (timeString) => {
28725
28925
  return timeString.replace("about ", "").replace(" ago", "");
28726
28926
  };
28927
+ const formatDowntime = (uptimeDetails) => {
28928
+ if (!uptimeDetails) return "";
28929
+ const downtimeMinutes = Math.max(0, uptimeDetails.expectedMinutes - uptimeDetails.actualMinutes);
28930
+ if (downtimeMinutes === 0) return "No downtime";
28931
+ if (downtimeMinutes < 1) return "< 1 min downtime";
28932
+ if (downtimeMinutes < 60) return `${downtimeMinutes} min downtime`;
28933
+ const hours = Math.floor(downtimeMinutes / 60);
28934
+ const minutes = downtimeMinutes % 60;
28935
+ if (minutes === 0) {
28936
+ return `${hours} hr downtime`;
28937
+ }
28938
+ return `${hours} hr ${minutes} min downtime`;
28939
+ };
28727
28940
  return /* @__PURE__ */ jsxRuntime.jsx(
28728
28941
  Card2,
28729
28942
  {
@@ -28757,13 +28970,32 @@ var WorkspaceHealthCard = ({
28757
28970
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: config.statusText })
28758
28971
  ] })
28759
28972
  ] }),
28760
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
28761
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "h-3.5 w-3.5 text-gray-400" }),
28762
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-gray-600 dark:text-gray-400 whitespace-nowrap", children: [
28763
- "Last seen: ",
28764
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: formatTimeAgo(workspace.timeSinceLastUpdate) })
28765
- ] })
28766
- ] }) }) })
28973
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
28974
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
28975
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "h-3.5 w-3.5 text-gray-400" }),
28976
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-gray-600 dark:text-gray-400 whitespace-nowrap", children: [
28977
+ "Last seen: ",
28978
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: formatTimeAgo(workspace.timeSinceLastUpdate) })
28979
+ ] })
28980
+ ] }),
28981
+ workspace.uptimePercentage !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
28982
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Activity, { className: "h-3.5 w-3.5 text-gray-400" }),
28983
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-gray-600 dark:text-gray-400 whitespace-nowrap", children: [
28984
+ "Uptime today: ",
28985
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: clsx(
28986
+ "font-medium",
28987
+ workspace.uptimePercentage >= 97 ? "text-green-600 dark:text-green-400" : workspace.uptimePercentage >= 90 ? "text-yellow-600 dark:text-yellow-400" : "text-red-600 dark:text-red-400"
28988
+ ), children: [
28989
+ workspace.uptimePercentage.toFixed(1),
28990
+ "%"
28991
+ ] })
28992
+ ] })
28993
+ ] }),
28994
+ workspace.uptimeDetails && workspace.uptimeDetails.expectedMinutes > workspace.uptimeDetails.actualMinutes && workspace.uptimePercentage !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx(
28995
+ "inline-flex items-center px-2 py-0.5 rounded text-xs font-medium",
28996
+ workspace.uptimePercentage >= 97 ? "bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400" : workspace.uptimePercentage >= 90 ? "bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400" : "bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400"
28997
+ ), children: formatDowntime(workspace.uptimeDetails) }) })
28998
+ ] })
28767
28999
  ] })
28768
29000
  }
28769
29001
  );
@@ -28834,6 +29066,20 @@ var CompactWorkspaceHealthCard = ({
28834
29066
  ] })
28835
29067
  ] }),
28836
29068
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
29069
+ workspace.uptimePercentage !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
29070
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: clsx(
29071
+ "text-xs font-medium",
29072
+ workspace.uptimePercentage >= 97 ? "text-green-600 dark:text-green-400" : workspace.uptimePercentage >= 90 ? "text-yellow-600 dark:text-yellow-400" : "text-red-600 dark:text-red-400"
29073
+ ), children: [
29074
+ workspace.uptimePercentage.toFixed(1),
29075
+ "%"
29076
+ ] }),
29077
+ workspace.uptimeDetails && workspace.uptimeDetails.expectedMinutes > workspace.uptimeDetails.actualMinutes && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400 dark:text-gray-400", children: "\u2022" }),
29078
+ workspace.uptimeDetails && workspace.uptimeDetails.expectedMinutes > workspace.uptimeDetails.actualMinutes && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: [
29079
+ Math.max(0, workspace.uptimeDetails.expectedMinutes - workspace.uptimeDetails.actualMinutes),
29080
+ "m down"
29081
+ ] })
29082
+ ] }),
28837
29083
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: workspace.timeSinceLastUpdate }),
28838
29084
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx("h-2 w-2 rounded-full", config.dot) })
28839
29085
  ] })
@@ -29057,18 +29303,18 @@ var DashboardHeader = React19.memo(({ lineTitle, className = "", headerControls
29057
29303
  };
29058
29304
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-row items-center justify-between w-full ${className}`, children: [
29059
29305
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
29060
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 sm:gap-2 md:gap-3", children: [
29061
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-base sm:text-xl md:text-2xl lg:text-3xl font-bold text-gray-800 tracking-tight leading-none", children: lineTitle }),
29062
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1 w-1 sm:h-1.5 sm:w-1.5 md:h-2 md:w-2 rounded-full bg-green-500 animate-pulse ring-1 sm:ring-2 ring-green-500/30 ring-offset-1" })
29306
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 sm:gap-2 md:gap-3", children: [
29307
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-lg sm:text-xl md:text-2xl lg:text-3xl font-bold text-gray-800 tracking-tight leading-none", children: lineTitle }),
29308
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1.5 w-1.5 sm:h-1.5 sm:w-1.5 md:h-2 md:w-2 rounded-full bg-green-500 animate-pulse ring-2 sm:ring-2 ring-green-500/30 ring-offset-1" })
29063
29309
  ] }),
29064
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 inline-flex items-center gap-3", children: [
29065
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm font-medium text-gray-600", children: [
29310
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 inline-flex items-center gap-2 sm:gap-3", children: [
29311
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs sm:text-sm font-medium text-gray-600", children: [
29066
29312
  /* @__PURE__ */ jsxRuntime.jsx(ISTTimer2, {}),
29067
29313
  " IST"
29068
29314
  ] }),
29069
29315
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-1", children: [
29070
29316
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-600", children: getShiftIcon() }),
29071
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-medium text-gray-600", children: [
29317
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs sm:text-sm font-medium text-gray-600", children: [
29072
29318
  getShiftName(),
29073
29319
  " Shift"
29074
29320
  ] })
@@ -29079,9 +29325,9 @@ var DashboardHeader = React19.memo(({ lineTitle, className = "", headerControls
29079
29325
  ] });
29080
29326
  });
29081
29327
  DashboardHeader.displayName = "DashboardHeader";
29082
- var NoWorkspaceData = React19.memo(({ message = "No workspace data available", className = "" }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-full items-center justify-center ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg bg-white p-4 shadow-md", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2 text-gray-500", children: [
29083
- /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z", clipRule: "evenodd" }) }),
29084
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: message })
29328
+ var NoWorkspaceData = React19.memo(({ message = "No workspace data available", className = "" }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-full items-center justify-center ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg bg-white p-5 sm:p-4 shadow-md", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-3 sm:space-x-2 text-gray-500", children: [
29329
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-6 w-6 sm:h-5 sm:w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z", clipRule: "evenodd" }) }),
29330
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base sm:text-sm", children: message })
29085
29331
  ] }) }) }));
29086
29332
  NoWorkspaceData.displayName = "NoWorkspaceData";
29087
29333
  var WorkspaceMonthlyDataFetcher = ({
@@ -29206,10 +29452,10 @@ var HamburgerButton = ({
29206
29452
  "button",
29207
29453
  {
29208
29454
  type: "button",
29209
- className: `md:hidden p-2 rounded-md text-gray-500 hover:text-gray-600 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 ${className}`,
29455
+ className: `md:hidden p-2.5 rounded-lg text-gray-600 hover:text-gray-900 hover:bg-gray-100 active:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors ${className}`,
29210
29456
  onClick,
29211
29457
  "aria-label": ariaLabel,
29212
- children: /* @__PURE__ */ jsxRuntime.jsx(outline.Bars3Icon, { className: "w-6 h-6" })
29458
+ children: /* @__PURE__ */ jsxRuntime.jsx(outline.Bars3Icon, { className: "w-7 h-7" })
29213
29459
  }
29214
29460
  );
29215
29461
  };
@@ -29740,28 +29986,189 @@ var SideNavBar = React19.memo(({
29740
29986
  }
29741
29987
  ) })
29742
29988
  ] });
29989
+ const MobileNavigationContent = () => {
29990
+ const isActive = (path) => {
29991
+ if (path === "/" && pathname === "/") return true;
29992
+ if (path !== "/" && pathname.startsWith(path)) return true;
29993
+ return false;
29994
+ };
29995
+ const getMobileButtonClass = (path) => {
29996
+ const active = isActive(path);
29997
+ return `w-full flex items-center gap-3 px-5 py-3.5 rounded-lg transition-colors active:scale-[0.98] ${active ? "bg-blue-50 text-blue-700" : "text-gray-700 hover:bg-gray-100 active:bg-gray-200"}`;
29998
+ };
29999
+ const getIconClass = (path) => {
30000
+ const active = isActive(path);
30001
+ return `w-7 h-7 ${active ? "text-blue-600" : "text-gray-600"}`;
30002
+ };
30003
+ const handleMobileNavClick = (handler) => {
30004
+ return () => {
30005
+ handler();
30006
+ onMobileMenuClose?.();
30007
+ };
30008
+ };
30009
+ return /* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "px-5 py-6", children: [
30010
+ /* @__PURE__ */ jsxRuntime.jsxs(
30011
+ "button",
30012
+ {
30013
+ onClick: handleMobileNavClick(handleHomeClick),
30014
+ className: getMobileButtonClass("/"),
30015
+ "aria-label": "Home",
30016
+ children: [
30017
+ /* @__PURE__ */ jsxRuntime.jsx(outline.HomeIcon, { className: getIconClass("/") }),
30018
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-medium", children: "Home" })
30019
+ ]
30020
+ }
30021
+ ),
30022
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 space-y-2", children: [
30023
+ /* @__PURE__ */ jsxRuntime.jsxs(
30024
+ "button",
30025
+ {
30026
+ onClick: handleMobileNavClick(handleLeaderboardClick),
30027
+ className: getMobileButtonClass("/leaderboard"),
30028
+ "aria-label": "Leaderboard",
30029
+ children: [
30030
+ /* @__PURE__ */ jsxRuntime.jsx(outline.TrophyIcon, { className: getIconClass("/leaderboard") }),
30031
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-medium", children: "Leaderboard" })
30032
+ ]
30033
+ }
30034
+ ),
30035
+ /* @__PURE__ */ jsxRuntime.jsxs(
30036
+ "button",
30037
+ {
30038
+ onClick: handleMobileNavClick(handleKPIsClick),
30039
+ className: getMobileButtonClass("/kpis"),
30040
+ "aria-label": "Lines",
30041
+ children: [
30042
+ /* @__PURE__ */ jsxRuntime.jsx(outline.ChartBarIcon, { className: getIconClass("/kpis") }),
30043
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-medium", children: "Lines" })
30044
+ ]
30045
+ }
30046
+ ),
30047
+ /* @__PURE__ */ jsxRuntime.jsxs(
30048
+ "button",
30049
+ {
30050
+ onClick: handleMobileNavClick(handleTargetsClick),
30051
+ className: getMobileButtonClass("/targets"),
30052
+ "aria-label": "Targets",
30053
+ children: [
30054
+ /* @__PURE__ */ jsxRuntime.jsx(outline.AdjustmentsHorizontalIcon, { className: getIconClass("/targets") }),
30055
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-medium", children: "Targets" })
30056
+ ]
30057
+ }
30058
+ ),
30059
+ /* @__PURE__ */ jsxRuntime.jsxs(
30060
+ "button",
30061
+ {
30062
+ onClick: handleMobileNavClick(handleShiftsClick),
30063
+ className: getMobileButtonClass("/shifts"),
30064
+ "aria-label": "Shift Management",
30065
+ children: [
30066
+ /* @__PURE__ */ jsxRuntime.jsx(outline.ClockIcon, { className: getIconClass("/shifts") }),
30067
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-medium", children: "Shifts" })
30068
+ ]
30069
+ }
30070
+ ),
30071
+ skuEnabled && /* @__PURE__ */ jsxRuntime.jsxs(
30072
+ "button",
30073
+ {
30074
+ onClick: handleMobileNavClick(handleSKUsClick),
30075
+ className: getMobileButtonClass("/skus"),
30076
+ "aria-label": "SKU Management",
30077
+ children: [
30078
+ /* @__PURE__ */ jsxRuntime.jsx(outline.CubeIcon, { className: getIconClass("/skus") }),
30079
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-medium", children: "SKUs" })
30080
+ ]
30081
+ }
30082
+ ),
30083
+ /* @__PURE__ */ jsxRuntime.jsxs(
30084
+ "button",
30085
+ {
30086
+ onClick: handleMobileNavClick(handleAIAgentClick),
30087
+ className: getMobileButtonClass("/ai-agent"),
30088
+ "aria-label": "AI Manufacturing Expert",
30089
+ children: [
30090
+ /* @__PURE__ */ jsxRuntime.jsx(outline.SparklesIcon, { className: getIconClass("/ai-agent") }),
30091
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-medium", children: "Axel AI" })
30092
+ ]
30093
+ }
30094
+ ),
30095
+ /* @__PURE__ */ jsxRuntime.jsxs(
30096
+ "button",
30097
+ {
30098
+ onClick: handleMobileNavClick(handleHelpClick),
30099
+ className: getMobileButtonClass("/help"),
30100
+ "aria-label": "Help & Support",
30101
+ children: [
30102
+ /* @__PURE__ */ jsxRuntime.jsx(outline.QuestionMarkCircleIcon, { className: getIconClass("/help") }),
30103
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-medium", children: "Help" })
30104
+ ]
30105
+ }
30106
+ ),
30107
+ /* @__PURE__ */ jsxRuntime.jsxs(
30108
+ "button",
30109
+ {
30110
+ onClick: handleMobileNavClick(handleHealthClick),
30111
+ className: getMobileButtonClass("/health"),
30112
+ "aria-label": "System Health",
30113
+ children: [
30114
+ /* @__PURE__ */ jsxRuntime.jsx(outline.HeartIcon, { className: getIconClass("/health") }),
30115
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-medium", children: "System Health" })
30116
+ ]
30117
+ }
30118
+ )
30119
+ ] }),
30120
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-8 pt-6 border-t border-gray-200", children: /* @__PURE__ */ jsxRuntime.jsxs(
30121
+ "button",
30122
+ {
30123
+ onClick: handleMobileNavClick(handleProfileClick),
30124
+ className: getMobileButtonClass("/profile"),
30125
+ "aria-label": "Profile & Settings",
30126
+ children: [
30127
+ /* @__PURE__ */ jsxRuntime.jsx(outline.UserCircleIcon, { className: getIconClass("/profile") }),
30128
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-medium", children: "Profile" })
30129
+ ]
30130
+ }
30131
+ ) })
30132
+ ] });
30133
+ };
29743
30134
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
29744
30135
  /* @__PURE__ */ jsxRuntime.jsx("aside", { className: `hidden md:flex w-20 h-screen bg-white shadow-lg border-r border-gray-100 flex-col items-center fixed ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx(NavigationContent, {}) }),
29745
- isMobileMenuOpen && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
30136
+ /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
29746
30137
  /* @__PURE__ */ jsxRuntime.jsx(
29747
30138
  "div",
29748
30139
  {
29749
- className: "md:hidden fixed inset-0 bg-black bg-opacity-50 z-40",
30140
+ className: `md:hidden fixed inset-0 bg-black/60 backdrop-blur-sm z-40 transition-opacity duration-300 ease-in-out ${isMobileMenuOpen ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"}`,
29750
30141
  onClick: onMobileMenuClose,
29751
30142
  "aria-hidden": "true"
29752
30143
  }
29753
30144
  ),
29754
- /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "md:hidden fixed inset-y-0 left-0 w-20 bg-white shadow-lg border-r border-gray-100 flex flex-col items-center z-50", children: [
29755
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-4 right-4", children: /* @__PURE__ */ jsxRuntime.jsx(
29756
- "button",
29757
- {
29758
- onClick: onMobileMenuClose,
29759
- className: "p-2 rounded-md text-gray-400 hover:text-gray-600 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500",
29760
- "aria-label": "Close menu",
29761
- children: /* @__PURE__ */ jsxRuntime.jsx(outline.XMarkIcon, { className: "w-5 h-5" })
29762
- }
29763
- ) }),
29764
- /* @__PURE__ */ jsxRuntime.jsx(NavigationContent, {})
30145
+ /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: `md:hidden fixed inset-y-0 left-0 w-72 xs:w-80 bg-white shadow-2xl flex flex-col z-50 transform transition-transform duration-300 ease-in-out ${isMobileMenuOpen ? "translate-x-0" : "-translate-x-full"}`, children: [
30146
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-5 py-4 border-b border-gray-200 bg-gradient-to-r from-blue-50 to-white", children: [
30147
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
30148
+ "img",
30149
+ {
30150
+ src: "/optifye-logo.png",
30151
+ alt: "Optifye",
30152
+ className: "w-11 h-11 object-contain",
30153
+ onError: (e) => {
30154
+ e.currentTarget.style.display = "none";
30155
+ if (e.currentTarget.parentElement) {
30156
+ e.currentTarget.parentElement.innerHTML = '<span class="text-blue-600 font-bold text-xl">Optifye</span>';
30157
+ }
30158
+ }
30159
+ }
30160
+ ) }),
30161
+ /* @__PURE__ */ jsxRuntime.jsx(
30162
+ "button",
30163
+ {
30164
+ onClick: onMobileMenuClose,
30165
+ className: "p-2.5 rounded-lg text-gray-600 hover:text-gray-900 hover:bg-gray-100 active:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all active:scale-95",
30166
+ "aria-label": "Close menu",
30167
+ children: /* @__PURE__ */ jsxRuntime.jsx(outline.XMarkIcon, { className: "w-7 h-7" })
30168
+ }
30169
+ )
30170
+ ] }),
30171
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(MobileNavigationContent, {}) })
29765
30172
  ] })
29766
30173
  ] })
29767
30174
  ] });
@@ -29853,17 +30260,39 @@ var MainLayout = ({
29853
30260
  logo
29854
30261
  }) => {
29855
30262
  const router$1 = router.useRouter();
30263
+ const [isMobileMenuOpen, setIsMobileMenuOpen] = React19.useState(false);
30264
+ const handleMobileMenuOpen = () => setIsMobileMenuOpen(true);
30265
+ const handleMobileMenuClose = () => setIsMobileMenuOpen(false);
29856
30266
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `min-h-screen ${className}`, children: [
30267
+ /* @__PURE__ */ jsxRuntime.jsx("header", { className: "md:hidden bg-white border-b border-gray-200 shadow-sm px-5 py-3.5 flex items-center justify-between sticky top-0 z-40", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
30268
+ /* @__PURE__ */ jsxRuntime.jsx(HamburgerButton, { onClick: handleMobileMenuOpen }),
30269
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(
30270
+ "img",
30271
+ {
30272
+ src: "/optifye-logo.png",
30273
+ alt: "Optifye",
30274
+ className: "h-9 w-9 object-contain",
30275
+ onError: (e) => {
30276
+ e.currentTarget.style.display = "none";
30277
+ if (e.currentTarget.parentElement) {
30278
+ e.currentTarget.parentElement.innerHTML = '<span class="text-blue-600 font-bold text-lg">Optifye</span>';
30279
+ }
30280
+ }
30281
+ }
30282
+ ) })
30283
+ ] }) }),
29857
30284
  /* @__PURE__ */ jsxRuntime.jsx(
29858
30285
  SideNavBar,
29859
30286
  {
29860
30287
  navItems,
29861
30288
  currentPathname: router$1.pathname,
29862
30289
  currentQuery: router$1.query,
29863
- logo
30290
+ logo,
30291
+ isMobileMenuOpen,
30292
+ onMobileMenuClose: handleMobileMenuClose
29864
30293
  }
29865
30294
  ),
29866
- /* @__PURE__ */ jsxRuntime.jsx("main", { className: "ml-20 bg-gray-50 min-h-screen", children })
30295
+ /* @__PURE__ */ jsxRuntime.jsx("main", { className: "md:ml-20 bg-gray-50 min-h-screen transition-all duration-300", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full", children }) })
29867
30296
  ] });
29868
30297
  };
29869
30298
  var Header = ({
@@ -32873,7 +33302,7 @@ function HomeView({
32873
33302
  return null;
32874
33303
  }
32875
33304
  return /* @__PURE__ */ jsxRuntime.jsxs(Select, { onValueChange: handleLineChange, defaultValue: selectedLineId, children: [
32876
- /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "w-full sm:w-[200px] bg-white border border-gray-200 shadow-sm rounded-md h-9 text-sm", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select a line" }) }),
33305
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "w-full sm:w-[200px] bg-white border border-gray-200 shadow-sm rounded-md h-11 sm:h-9 text-sm", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select a line" }) }),
32877
33306
  /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { className: "z-50 bg-white shadow-lg border border-gray-200 rounded-md", children: availableLineIds.map((id3) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: id3, children: lineNames[id3] || (id3 === factoryViewId ? "All Lines" : `Line ${id3.substring(0, 4)}`) }, id3)) })
32878
33307
  ] });
32879
33308
  }, [availableLineIds, handleLineChange, selectedLineId, lineNames, factoryViewId, allLineIds.length]);
@@ -32885,7 +33314,7 @@ function HomeView({
32885
33314
  if (errorMessage || displayNamesError) {
32886
33315
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-screen items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg bg-white p-6 shadow-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-3 text-red-500", children: [
32887
33316
  /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
32888
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-lg font-medium", children: [
33317
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-base sm:text-lg font-medium", children: [
32889
33318
  "Error: ",
32890
33319
  errorMessage || displayNamesError?.message
32891
33320
  ] })
@@ -32899,7 +33328,7 @@ function HomeView({
32899
33328
  animate: { opacity: 1 },
32900
33329
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-1", children: [
32901
33330
  /* @__PURE__ */ jsxRuntime.jsxs("main", { className: "flex flex-1 flex-col", children: [
32902
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-0 z-30 sm:static bg-white shadow-sm border-b border-gray-200/80", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between px-3 sm:px-6 lg:px-8 py-1.5 sm:py-2.5", children: /* @__PURE__ */ jsxRuntime.jsx(
33331
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative sm:sticky sm:top-0 z-30 bg-white shadow-sm border-b border-gray-200/80", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between px-4 sm:px-6 lg:px-8 py-3 sm:py-2.5", children: /* @__PURE__ */ jsxRuntime.jsx(
32903
33332
  DashboardHeader,
32904
33333
  {
32905
33334
  lineTitle,
@@ -32908,8 +33337,8 @@ function HomeView({
32908
33337
  }
32909
33338
  ) }) }),
32910
33339
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto sm:overflow-hidden relative", children: [
32911
- lineSelectorComponent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-3 top-2 sm:right-6 sm:top-3 z-30", children: lineSelectorComponent }),
32912
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full sm:h-full min-h-[calc(100vh-80px)] sm:min-h-0", children: memoizedWorkspaceMetrics.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
33340
+ lineSelectorComponent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-4 top-3 sm:right-6 sm:top-3 z-30", children: lineSelectorComponent }),
33341
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full sm:h-full min-h-[calc(100vh-120px)] sm:min-h-0", children: memoizedWorkspaceMetrics.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
32913
33342
  motion.div,
32914
33343
  {
32915
33344
  initial: { opacity: 0, scale: 0.98 },
@@ -38419,8 +38848,8 @@ var WorkspaceHealthView = ({
38419
38848
  }
38420
38849
  };
38421
38850
  const getUptimeColor = (percentage) => {
38422
- if (percentage >= 99) return "text-green-600 dark:text-green-400";
38423
- if (percentage >= 95) return "text-yellow-600 dark:text-yellow-400";
38851
+ if (percentage >= 97) return "text-green-600 dark:text-green-400";
38852
+ if (percentage >= 90) return "text-yellow-600 dark:text-yellow-400";
38424
38853
  return "text-red-600 dark:text-red-400";
38425
38854
  };
38426
38855
  if (loading && !summary) {
@@ -38508,20 +38937,21 @@ var WorkspaceHealthView = ({
38508
38937
  className: "grid grid-cols-2 sm:grid-cols-2 md:grid-cols-5 gap-2 sm:gap-3 lg:gap-4",
38509
38938
  children: [
38510
38939
  /* @__PURE__ */ jsxRuntime.jsxs(Card2, { className: "col-span-2 sm:col-span-2 md:col-span-2 bg-white", children: [
38511
- /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-3", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-sm font-medium text-gray-500 dark:text-gray-400", children: "Overall System Status" }) }),
38940
+ /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-3", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-sm font-medium text-gray-500 dark:text-gray-400", children: "Overall System Uptime Today" }) }),
38512
38941
  /* @__PURE__ */ jsxRuntime.jsxs(CardContent2, { children: [
38513
38942
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2", children: [
38514
38943
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: clsx("text-3xl font-bold", getUptimeColor(summary.uptimePercentage)), children: [
38515
38944
  summary.uptimePercentage.toFixed(1),
38516
38945
  "%"
38517
38946
  ] }),
38518
- summary.uptimePercentage >= 99 ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingUp, { className: "h-5 w-5 text-green-500" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingDown, { className: "h-5 w-5 text-red-500" })
38947
+ summary.uptimePercentage >= 97 ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingUp, { className: "h-5 w-5 text-green-500" }) : summary.uptimePercentage >= 90 ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Activity, { className: "h-5 w-5 text-yellow-500" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingDown, { className: "h-5 w-5 text-red-500" })
38519
38948
  ] }),
38520
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: [
38949
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: "Average uptime across all workspaces" }),
38950
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: [
38521
38951
  summary.healthyWorkspaces,
38522
38952
  " of ",
38523
38953
  summary.totalWorkspaces,
38524
- " workspaces healthy"
38954
+ " workspaces online"
38525
38955
  ] })
38526
38956
  ] })
38527
38957
  ] }),