@optifye/dashboard-core 6.12.5 → 6.12.7

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
@@ -5257,46 +5257,83 @@ var dashboardService = {
5257
5257
  const dbConfig = config.databaseConfig ?? DEFAULT_DATABASE_CONFIG;
5258
5258
  const linesTable = getTable(dbConfig, "lines");
5259
5259
  const companyId = config.entityConfig?.companyId;
5260
+ const baseLineSelect = `
5261
+ id,
5262
+ line_name,
5263
+ factory_id,
5264
+ factories!lines_factory_id_fkey(factory_name),
5265
+ company_id,
5266
+ companies!lines_company_id_fkey(company_name:name),
5267
+ enable,
5268
+ monitoring_mode,
5269
+ assembly,
5270
+ video_grid_metric_mode,
5271
+ recent_flow_window_minutes
5272
+ `;
5273
+ const lineSelectWithArea = `
5274
+ ${baseLineSelect},
5275
+ factory_area_id,
5276
+ factory_line_areas!lines_factory_area_id_factory_id_fkey(
5277
+ area_key,
5278
+ area_name,
5279
+ sort_order,
5280
+ enabled
5281
+ )
5282
+ `;
5283
+ const shouldRetryWithoutFactoryArea = (error) => {
5284
+ const errorText = [
5285
+ error?.message,
5286
+ error?.details,
5287
+ error?.hint,
5288
+ error?.code
5289
+ ].filter(Boolean).join(" ").toLowerCase();
5290
+ return errorText.includes("factory_area_id") || errorText.includes("factory_line_areas") || errorText.includes("lines_factory_area_id_factory_id_fkey");
5291
+ };
5260
5292
  try {
5261
- let query = supabase.from(linesTable).select(`
5262
- id,
5263
- line_name,
5264
- factory_id,
5265
- factories!lines_factory_id_fkey(factory_name),
5266
- company_id,
5267
- companies!lines_company_id_fkey(company_name:name),
5268
- enable,
5269
- monitoring_mode,
5270
- assembly,
5271
- video_grid_metric_mode,
5272
- recent_flow_window_minutes
5273
- `).eq("enable", true);
5274
- if (companyId) {
5275
- query = query.eq("company_id", companyId);
5276
- }
5277
- const { data, error } = await query;
5293
+ const fetchLines = async (selectClause) => {
5294
+ let query = supabase.from(linesTable).select(selectClause).eq("enable", true);
5295
+ if (companyId) {
5296
+ query = query.eq("company_id", companyId);
5297
+ }
5298
+ return await query;
5299
+ };
5300
+ let { data, error } = await fetchLines(lineSelectWithArea);
5301
+ if (error && shouldRetryWithoutFactoryArea(error)) {
5302
+ console.warn("[dashboardService.getAllLines] Factory area metadata unavailable, falling back to line-only metadata:", error);
5303
+ const fallbackResult = await fetchLines(baseLineSelect);
5304
+ data = fallbackResult.data;
5305
+ error = fallbackResult.error;
5306
+ }
5278
5307
  if (error) {
5279
5308
  console.error("Error fetching all lines:", error);
5280
5309
  throw error;
5281
5310
  }
5282
5311
  if (!data) return [];
5283
- const transformedLines = data.map((line) => ({
5284
- id: line.id,
5285
- line_name: line.line_name,
5286
- factory_id: line.factory_id,
5287
- factory_name: line.factories?.factory_name ?? "N/A",
5288
- company_id: line.company_id,
5289
- company_name: line.companies?.company_name ?? "N/A",
5290
- enable: line.enable ?? true,
5291
- // Default to true if not specified
5292
- monitoring_mode: line.monitoring_mode ?? "output",
5293
- assembly: line.assembly ?? false,
5294
- video_grid_metric_mode: normalizeVideoGridMetricMode(
5295
- line.video_grid_metric_mode,
5296
- line.assembly ?? false
5297
- ),
5298
- recent_flow_window_minutes: line.recent_flow_window_minutes ?? 7
5299
- }));
5312
+ const transformedLines = data.map((line) => {
5313
+ const factoryArea = Array.isArray(line.factory_line_areas) ? line.factory_line_areas[0] : line.factory_line_areas;
5314
+ return {
5315
+ id: line.id,
5316
+ line_name: line.line_name,
5317
+ factory_id: line.factory_id,
5318
+ factory_name: line.factories?.factory_name ?? "N/A",
5319
+ company_id: line.company_id,
5320
+ company_name: line.companies?.company_name ?? "N/A",
5321
+ enable: line.enable ?? true,
5322
+ // Default to true if not specified
5323
+ monitoring_mode: line.monitoring_mode ?? "output",
5324
+ assembly: line.assembly ?? false,
5325
+ video_grid_metric_mode: normalizeVideoGridMetricMode(
5326
+ line.video_grid_metric_mode,
5327
+ line.assembly ?? false
5328
+ ),
5329
+ recent_flow_window_minutes: line.recent_flow_window_minutes ?? 7,
5330
+ factory_area_id: line.factory_area_id ?? null,
5331
+ factory_area_key: factoryArea?.area_key ?? null,
5332
+ factory_area_name: factoryArea?.area_name ?? null,
5333
+ factory_area_sort_order: factoryArea?.sort_order ?? null,
5334
+ factory_area_enabled: factoryArea?.enabled ?? null
5335
+ };
5336
+ });
5300
5337
  return transformedLines;
5301
5338
  } catch (err) {
5302
5339
  console.error("Exception in getAllLines:", err);
@@ -14265,7 +14302,9 @@ var useLeaderboardMetrics = (date, shiftId, limit = 10, filter2 = "all") => {
14265
14302
  `/api/dashboard/leaderboard?${params.toString()}`
14266
14303
  );
14267
14304
  let entries = (data.entries || []).slice();
14268
- entries.sort((a, b) => (b.efficiency || 0) - (a.efficiency || 0));
14305
+ entries.sort(
14306
+ (a, b) => (b.leaderboard_value ?? b.efficiency ?? 0) - (a.leaderboard_value ?? a.efficiency ?? 0)
14307
+ );
14269
14308
  if (filter2 === "top") {
14270
14309
  entries = entries.slice(0, limit);
14271
14310
  } else if (filter2 === "bottom") {
@@ -21902,6 +21941,24 @@ var getConfigurableShortWorkspaceDisplayName = (workspaceId, workspaceConfig, li
21902
21941
  return fullName;
21903
21942
  };
21904
21943
 
21944
+ // src/lib/utils/efficiencyValidity.ts
21945
+ var MIN_VALID_OUTPUT_EFFICIENCY = 5;
21946
+ var MIN_VALID_UPTIME_EFFICIENCY = 1;
21947
+ var normalizeMonitoringMode = (mode) => String(mode ?? "").trim().toLowerCase() === "uptime" ? "uptime" : "output";
21948
+ var toFiniteNumberOrNull = (value) => {
21949
+ if (typeof value === "number" && Number.isFinite(value)) return value;
21950
+ if (typeof value === "string" && value.trim() !== "") {
21951
+ const parsed = Number(value);
21952
+ return Number.isFinite(parsed) ? parsed : null;
21953
+ }
21954
+ return null;
21955
+ };
21956
+ var isValidAggregateEfficiency = (monitoringMode, efficiency) => {
21957
+ const value = toFiniteNumberOrNull(efficiency);
21958
+ if (value === null) return false;
21959
+ return normalizeMonitoringMode(monitoringMode) === "uptime" ? value >= MIN_VALID_UPTIME_EFFICIENCY : value >= MIN_VALID_OUTPUT_EFFICIENCY;
21960
+ };
21961
+
21905
21962
  // src/lib/utils/kpis.ts
21906
21963
  var toNumber = (value) => {
21907
21964
  if (typeof value === "number" && Number.isFinite(value)) return value;
@@ -21957,7 +22014,9 @@ var buildKPIsFromLineMetricsRow = (row) => {
21957
22014
  };
21958
22015
  var aggregateKPIsFromLineMetricsRows = (rows) => {
21959
22016
  if (!rows || rows.length === 0) return createDefaultKPIs();
21960
- const eligibleRows = rows.filter((row) => toNumber(row?.avg_efficiency) >= 5);
22017
+ const eligibleRows = rows.filter(
22018
+ (row) => isValidAggregateEfficiency(row?.monitoring_mode ?? row?.monitoringMode, row?.avg_efficiency)
22019
+ );
21961
22020
  if (eligibleRows.length === 0) return createDefaultKPIs();
21962
22021
  const currentOutputSum = eligibleRows.reduce((sum, row) => sum + toNumber(row.current_output), 0);
21963
22022
  const lineThresholdSum = eligibleRows.reduce(
@@ -22009,6 +22068,84 @@ var aggregateKPIsFromLineMetricsRows = (rows) => {
22009
22068
  };
22010
22069
  };
22011
22070
 
22071
+ // src/lib/utils/kpiHierarchy.ts
22072
+ var FACTORY_LEVEL_MIN_FACTORY_COUNT = 3;
22073
+ var compareText = (left, right) => left.localeCompare(right, void 0, { sensitivity: "base", numeric: true });
22074
+ var compareLinesByName = (left, right) => compareText(left.line_name || "", right.line_name || "");
22075
+ var normalizeAreaSortOrder = (value) => {
22076
+ if (typeof value === "number" && Number.isFinite(value)) return value;
22077
+ if (typeof value === "string" && value.trim() !== "") {
22078
+ const parsed = Number(value);
22079
+ return Number.isFinite(parsed) ? parsed : null;
22080
+ }
22081
+ return null;
22082
+ };
22083
+ var getEnabledAreaInfo = (line) => {
22084
+ if (!line.factory_area_id) return null;
22085
+ if (line.factory_area_enabled !== true) return null;
22086
+ if (!line.factory_area_name || line.factory_area_name.trim().length === 0) return null;
22087
+ return {
22088
+ id: line.factory_area_id,
22089
+ areaName: line.factory_area_name,
22090
+ areaKey: line.factory_area_key ?? null,
22091
+ sortOrder: normalizeAreaSortOrder(line.factory_area_sort_order)
22092
+ };
22093
+ };
22094
+ var buildKpiLineHierarchy = (lines) => {
22095
+ const factoryMap = /* @__PURE__ */ new Map();
22096
+ lines.forEach((line) => {
22097
+ const factoryId = line.factory_id || "unknown-factory";
22098
+ let factory = factoryMap.get(factoryId);
22099
+ if (!factory) {
22100
+ factory = {
22101
+ id: factoryId,
22102
+ factoryName: line.factory_name || "Factory",
22103
+ lines: [],
22104
+ areas: [],
22105
+ ungroupedLines: [],
22106
+ areaMap: /* @__PURE__ */ new Map()
22107
+ };
22108
+ factoryMap.set(factoryId, factory);
22109
+ }
22110
+ factory.lines.push(line);
22111
+ const areaInfo = getEnabledAreaInfo(line);
22112
+ if (!areaInfo) {
22113
+ factory.ungroupedLines.push(line);
22114
+ return;
22115
+ }
22116
+ let area = factory.areaMap.get(areaInfo.id);
22117
+ if (!area) {
22118
+ area = {
22119
+ id: areaInfo.id,
22120
+ areaName: areaInfo.areaName,
22121
+ areaKey: areaInfo.areaKey,
22122
+ sortOrder: areaInfo.sortOrder,
22123
+ lines: []
22124
+ };
22125
+ factory.areaMap.set(areaInfo.id, area);
22126
+ factory.areas.push(area);
22127
+ }
22128
+ area.lines.push(line);
22129
+ });
22130
+ const factories = Array.from(factoryMap.values()).map(({ areaMap: _areaMap, ...factory }) => {
22131
+ factory.lines.sort(compareLinesByName);
22132
+ factory.ungroupedLines.sort(compareLinesByName);
22133
+ factory.areas.forEach((area) => area.lines.sort(compareLinesByName));
22134
+ factory.areas.sort((left, right) => {
22135
+ const leftOrder = left.sortOrder ?? Number.POSITIVE_INFINITY;
22136
+ const rightOrder = right.sortOrder ?? Number.POSITIVE_INFINITY;
22137
+ if (leftOrder !== rightOrder) return leftOrder - rightOrder;
22138
+ return compareText(left.areaName, right.areaName);
22139
+ });
22140
+ return factory;
22141
+ });
22142
+ factories.sort((left, right) => compareText(left.factoryName, right.factoryName));
22143
+ return {
22144
+ factories,
22145
+ showFactoryLevel: factories.length >= FACTORY_LEVEL_MIN_FACTORY_COUNT
22146
+ };
22147
+ };
22148
+
22012
22149
  // src/lib/utils/awards.ts
22013
22150
  var toNumber2 = (value) => {
22014
22151
  if (typeof value === "number" && Number.isFinite(value)) return value;
@@ -37285,8 +37422,8 @@ var HourlyOutputChart = React144__namespace.default.memo(
37285
37422
  HourlyOutputChart.displayName = "HourlyOutputChart";
37286
37423
 
37287
37424
  // src/components/dashboard/grid/videoGridMetricUtils.ts
37425
+ var VIDEO_GRID_LEGEND_LABEL = "Real-Time efficiency";
37288
37426
  var MAP_GRID_LEGEND_LABEL = "Efficiency";
37289
- var MIXED_VIDEO_GRID_LEGEND_LABEL = "Live Efficiency";
37290
37427
  var isFiniteNumber2 = (value) => typeof value === "number" && Number.isFinite(value);
37291
37428
  var isVideoGridRecentFlowEnabled = (workspace) => isRecentFlowVideoGridMetricMode(
37292
37429
  workspace.video_grid_metric_mode,
@@ -37298,7 +37435,7 @@ var isVideoGridWipGated = (workspace) => isWipGatedVideoGridMetricMode(
37298
37435
  );
37299
37436
  var hasVideoGridRecentFlow = (workspace) => isVideoGridRecentFlowEnabled(workspace) && isFiniteNumber2(workspace.recent_flow_percent);
37300
37437
  var isVideoGridRecentFlowUnavailable = (workspace) => isVideoGridRecentFlowEnabled(workspace) && !hasVideoGridRecentFlow(workspace);
37301
- var getVideoGridMetricValue = (workspace) => {
37438
+ var getRawVideoGridMetricValue = (workspace) => {
37302
37439
  const recentFlowPercent = workspace.recent_flow_percent;
37303
37440
  if (hasVideoGridRecentFlow(workspace) && isFiniteNumber2(recentFlowPercent)) {
37304
37441
  return recentFlowPercent;
@@ -37310,7 +37447,7 @@ var getVideoGridMetricValue = (workspace) => {
37310
37447
  };
37311
37448
  var hasIncomingWipMapping = (workspace) => Boolean(workspace.incoming_wip_buffer_name);
37312
37449
  var getVideoGridBaseColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37313
- const metricValue = getVideoGridMetricValue(workspace);
37450
+ const metricValue = getRawVideoGridMetricValue(workspace);
37314
37451
  if (!isFiniteNumber2(metricValue)) {
37315
37452
  return "neutral";
37316
37453
  }
@@ -37334,6 +37471,25 @@ var isLowWipGreenOverride = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37334
37471
  }
37335
37472
  return isFiniteNumber2(workspace.incoming_wip_current) && workspace.incoming_wip_current <= 1;
37336
37473
  };
37474
+ var isHighEfficiencyRedFlowOverride = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37475
+ if (workspace.scheduled_break_active === true) {
37476
+ return false;
37477
+ }
37478
+ if (workspace.recent_flow_forced_zero_after_shift === true) {
37479
+ return false;
37480
+ }
37481
+ if (!hasVideoGridRecentFlow(workspace) || !isVideoGridWipGated(workspace)) {
37482
+ return false;
37483
+ }
37484
+ if (isLowWipGreenOverride(workspace, legend)) {
37485
+ return false;
37486
+ }
37487
+ if (getVideoGridBaseColorState(workspace, legend) !== "red") {
37488
+ return false;
37489
+ }
37490
+ return isFiniteNumber2(workspace.efficiency) && workspace.efficiency > 100;
37491
+ };
37492
+ var getVideoGridMetricValue = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => isHighEfficiencyRedFlowOverride(workspace, legend) ? workspace.efficiency : getRawVideoGridMetricValue(workspace);
37337
37493
  var toMinuteBucket = (minuteBucket) => Number.isFinite(minuteBucket) ? Math.floor(minuteBucket) : Math.floor(Date.now() / 6e4);
37338
37494
  var getEffectiveFlowMinuteBucket = (workspace) => {
37339
37495
  const effectiveAt = workspace.recent_flow_effective_end_at;
@@ -37359,7 +37515,7 @@ var getSyntheticLowWipDisplayValue = (workspace, minuteBucket) => {
37359
37515
  const offset = (hashWorkspaceKey(workspace) % 11 + bucket % 11 + 11) % 11;
37360
37516
  return 100 + offset;
37361
37517
  };
37362
- var getVideoGridDisplayValue = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND, minuteBucket) => isLowWipGreenOverride(workspace, legend) ? getSyntheticLowWipDisplayValue(workspace, minuteBucket) : getVideoGridMetricValue(workspace);
37518
+ var getVideoGridDisplayValue = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND, minuteBucket) => isLowWipGreenOverride(workspace, legend) ? getSyntheticLowWipDisplayValue(workspace, minuteBucket) : getVideoGridMetricValue(workspace, legend);
37363
37519
  var getVideoGridColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37364
37520
  const baseColor = getVideoGridBaseColorState(workspace, legend);
37365
37521
  if (!hasVideoGridRecentFlow(workspace)) {
@@ -37371,15 +37527,18 @@ var getVideoGridColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) =>
37371
37527
  if (baseColor !== "red") {
37372
37528
  return baseColor;
37373
37529
  }
37530
+ if (isLowWipGreenOverride(workspace, legend)) {
37531
+ return "green";
37532
+ }
37533
+ if (isHighEfficiencyRedFlowOverride(workspace, legend)) {
37534
+ return getEfficiencyColor(workspace.efficiency, legend);
37535
+ }
37374
37536
  if (!hasIncomingWipMapping(workspace)) {
37375
37537
  return baseColor;
37376
37538
  }
37377
37539
  if (!isFiniteNumber2(workspace.incoming_wip_current)) {
37378
37540
  return "neutral";
37379
37541
  }
37380
- if (isLowWipGreenOverride(workspace, legend)) {
37381
- return "green";
37382
- }
37383
37542
  return baseColor;
37384
37543
  };
37385
37544
  var getVideoGridLegendLabel = (workspaces) => {
@@ -37387,21 +37546,7 @@ var getVideoGridLegendLabel = (workspaces) => {
37387
37546
  if (visibleWorkspaces.length === 0) {
37388
37547
  return MAP_GRID_LEGEND_LABEL;
37389
37548
  }
37390
- const recentFlowEnabledCount = visibleWorkspaces.filter(isVideoGridRecentFlowEnabled).length;
37391
- if (recentFlowEnabledCount === 0) {
37392
- return MAP_GRID_LEGEND_LABEL;
37393
- }
37394
- const recentFlowWindows = new Set(
37395
- visibleWorkspaces.filter(isVideoGridRecentFlowEnabled).map((workspace) => workspace.recent_flow_window_minutes ?? 7).filter((value) => typeof value === "number" && Number.isFinite(value))
37396
- );
37397
- if (recentFlowEnabledCount === visibleWorkspaces.length) {
37398
- if (recentFlowWindows.size === 1) {
37399
- const [windowMinutes] = Array.from(recentFlowWindows);
37400
- return `${windowMinutes} Minute Efficiency`;
37401
- }
37402
- return MIXED_VIDEO_GRID_LEGEND_LABEL;
37403
- }
37404
- return MIXED_VIDEO_GRID_LEGEND_LABEL;
37549
+ return visibleWorkspaces.some(isVideoGridRecentFlowEnabled) ? VIDEO_GRID_LEGEND_LABEL : MAP_GRID_LEGEND_LABEL;
37405
37550
  };
37406
37551
  function getTrendArrowAndColor(trend) {
37407
37552
  if (trend > 0) {
@@ -37444,14 +37589,15 @@ var VideoCard = React144__namespace.default.memo(({
37444
37589
  const showOffline = Boolean(isStreamStale);
37445
37590
  const lastSeenText = lastSeenLabel || "Unknown";
37446
37591
  const workspaceDisplayName = displayName || workspace.displayName || workspace.workspace_name;
37447
- const videoGridMetricValue = getVideoGridMetricValue(workspace);
37592
+ const videoGridMetricValue = getVideoGridMetricValue(workspace, effectiveLegend);
37448
37593
  const videoGridDisplayValue = getVideoGridDisplayValue(workspace, effectiveLegend, displayMinuteBucket);
37449
37594
  const videoGridColorState = getVideoGridColorState(workspace, effectiveLegend);
37450
37595
  const isRecentFlowCard = isVideoGridRecentFlowEnabled(workspace);
37596
+ const isHighEfficiencyOverride = isHighEfficiencyRedFlowOverride(workspace, effectiveLegend);
37451
37597
  const hasDisplayMetric = typeof videoGridDisplayValue === "number" && Number.isFinite(videoGridDisplayValue);
37452
37598
  const hasBarMetric = typeof videoGridMetricValue === "number" && Number.isFinite(videoGridMetricValue);
37453
37599
  const shouldRenderMetricBadge = hasDisplayMetric;
37454
- const badgeTitle = hasVideoGridRecentFlow(workspace) ? `Flow ${Math.round(videoGridDisplayValue ?? 0)}%` : isRecentFlowCard ? "Flow unavailable" : `Efficiency ${Math.round(videoGridDisplayValue ?? 0)}%`;
37600
+ const badgeTitle = isHighEfficiencyOverride ? `Efficiency ${Math.round(videoGridDisplayValue ?? 0)}%` : hasVideoGridRecentFlow(workspace) ? `Flow ${Math.round(videoGridDisplayValue ?? 0)}%` : isRecentFlowCard ? "Flow unavailable" : `Efficiency ${Math.round(videoGridDisplayValue ?? 0)}%`;
37455
37601
  const badgeLabel = `${Math.round(videoGridDisplayValue ?? 0)}%`;
37456
37602
  const efficiencyOverlayClass = videoGridColorState === "green" ? "bg-[#00D654]/25" : videoGridColorState === "yellow" ? "bg-[#FFD700]/30" : videoGridColorState === "red" ? "bg-[#FF2D0A]/30" : "bg-transparent";
37457
37603
  const efficiencyBarClass = videoGridColorState === "green" ? "bg-[#00AB45]" : videoGridColorState === "yellow" ? "bg-[#FFB020]" : videoGridColorState === "red" ? "bg-[#E34329]" : "bg-gray-500/70";
@@ -38234,7 +38380,8 @@ var WorkspaceMetricCardsImpl = ({
38234
38380
  legend,
38235
38381
  skuAware,
38236
38382
  skuBreakdown,
38237
- activeSkuId
38383
+ activeSkuId,
38384
+ liveSkuId
38238
38385
  }) => {
38239
38386
  const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
38240
38387
  const activeSku = React144__namespace.default.useMemo(() => {
@@ -38243,6 +38390,13 @@ var WorkspaceMetricCardsImpl = ({
38243
38390
  }
38244
38391
  return null;
38245
38392
  }, [skuAware, activeSkuId, skuBreakdown]);
38393
+ const displaySku = React144__namespace.default.useMemo(() => {
38394
+ if (activeSku) return activeSku;
38395
+ if (skuAware && !activeSkuId && liveSkuId && skuBreakdown) {
38396
+ return skuBreakdown.find((s) => s.sku_id === liveSkuId) ?? null;
38397
+ }
38398
+ return null;
38399
+ }, [activeSku, skuAware, activeSkuId, liveSkuId, skuBreakdown]);
38246
38400
  const pphValue = activeSku ? activeSku.avg_pph : workspace.avg_pph;
38247
38401
  const pphThreshold = activeSku ? activeSku.pph_threshold : workspace.pph_threshold;
38248
38402
  const cycleValue = activeSku ? activeSku.avg_cycle_time : workspace.avg_cycle_time;
@@ -38277,7 +38431,7 @@ var WorkspaceMetricCardsImpl = ({
38277
38431
  /* @__PURE__ */ jsxRuntime.jsxs(Card2, { className: "flex flex-col bg-white shadow-sm h-full min-h-[150px] sm:min-h-0", children: [
38278
38432
  /* @__PURE__ */ jsxRuntime.jsxs(CardHeader2, { className: "pb-2 flex-none text-center", children: [
38279
38433
  /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg", children: "PPH" }),
38280
- activeSku && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-blue-600 mt-1 truncate px-2", title: activeSku.sku_code, children: activeSku.sku_code })
38434
+ displaySku && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-blue-600 mt-1 truncate px-2", title: displaySku.sku_code, children: displaySku.sku_code })
38281
38435
  ] }),
38282
38436
  /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6 sm:py-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
38283
38437
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-5xl font-bold ${pphValue >= pphThreshold ? "text-green-500" : "text-red-500"}`, children: pphValue.toFixed(1) }),
@@ -38290,7 +38444,7 @@ var WorkspaceMetricCardsImpl = ({
38290
38444
  /* @__PURE__ */ jsxRuntime.jsxs(Card2, { className: "flex flex-col bg-white shadow-sm h-full min-h-[150px] sm:min-h-0", children: [
38291
38445
  /* @__PURE__ */ jsxRuntime.jsxs(CardHeader2, { className: "pb-2 flex-none text-center", children: [
38292
38446
  /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg", children: "Avg. Cycle Time" }),
38293
- activeSku && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-blue-600 mt-1 truncate px-2", title: activeSku.sku_code, children: activeSku.sku_code })
38447
+ displaySku && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-blue-600 mt-1 truncate px-2", title: displaySku.sku_code, children: displaySku.sku_code })
38294
38448
  ] }),
38295
38449
  /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6 sm:py-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
38296
38450
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-5xl font-bold ${cycleValue > (cycleStandard || 0) ? "text-red-500" : "text-green-500"}`, children: cycleValue.toFixed(1) }),
@@ -43288,6 +43442,21 @@ var parseCycleTime = (value) => {
43288
43442
  var extractCycleTimeSeconds = (clip) => {
43289
43443
  return parseCycleTime(clip?.cycleTimeSeconds) ?? parseCycleTime(clip?.cycle_time_seconds) ?? parseCycleTime(clip?.duration) ?? parseCycleTime(clip?.original_task_metadata?.cycle_time) ?? null;
43290
43444
  };
43445
+ var formatDurationLabel = (seconds) => {
43446
+ if (typeof seconds !== "number" || !Number.isFinite(seconds) || seconds <= 0) {
43447
+ return null;
43448
+ }
43449
+ const roundedSeconds = Math.round(seconds);
43450
+ if (roundedSeconds < 60) {
43451
+ return `${roundedSeconds}s`;
43452
+ }
43453
+ const minutes = Math.floor(roundedSeconds / 60);
43454
+ const remainingSeconds = roundedSeconds % 60;
43455
+ if (minutes < 10) {
43456
+ return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
43457
+ }
43458
+ return `${Math.round(roundedSeconds / 60)} min`;
43459
+ };
43291
43460
  var getSeverityIcon = (severity, categoryId, cycleTimeSeconds, targetCycleTime, clipId) => {
43292
43461
  if (categoryId === "idle_time" || categoryId === "low_value" || categoryId === "longest-idles") {
43293
43462
  return null;
@@ -43363,7 +43532,9 @@ var FileManagerFilters = ({
43363
43532
  idleTimeVlmEnabled = false,
43364
43533
  showPercentileCycleFilters = true,
43365
43534
  prefetchedClipMetadata,
43366
- activeCategoryLoading
43535
+ activeCategoryLoading,
43536
+ idleClipSort = "latest",
43537
+ onIdleClipSortChange
43367
43538
  }) => {
43368
43539
  const [expandedNodes, setExpandedNodes] = React144.useState(/* @__PURE__ */ new Set());
43369
43540
  const [startTime, setStartTime] = React144.useState("");
@@ -43386,6 +43557,7 @@ var FileManagerFilters = ({
43386
43557
  const [localClipClassifications, setLocalClipClassifications] = React144.useState({});
43387
43558
  const clipMetadataRef = React144.useRef({});
43388
43559
  const inFlightMetadataRequestsRef = React144.useRef(/* @__PURE__ */ new Set());
43560
+ const previousIdleClipSortRef = React144.useRef(idleClipSort);
43389
43561
  const mergedClipClassifications = React144.useMemo(() => ({
43390
43562
  ...clipClassifications || {},
43391
43563
  ...localClipClassifications
@@ -43393,6 +43565,36 @@ var FileManagerFilters = ({
43393
43565
  React144.useEffect(() => {
43394
43566
  clipMetadataRef.current = clipMetadata;
43395
43567
  }, [clipMetadata]);
43568
+ React144.useEffect(() => {
43569
+ if (previousIdleClipSortRef.current === idleClipSort) {
43570
+ return;
43571
+ }
43572
+ previousIdleClipSortRef.current = idleClipSort;
43573
+ setClipMetadata((prev) => {
43574
+ if (!prev.idle_time) {
43575
+ return prev;
43576
+ }
43577
+ const next = { ...prev };
43578
+ delete next.idle_time;
43579
+ return next;
43580
+ });
43581
+ setCategoryPages((prev) => {
43582
+ if (prev.idle_time === void 0) {
43583
+ return prev;
43584
+ }
43585
+ const next = { ...prev };
43586
+ delete next.idle_time;
43587
+ return next;
43588
+ });
43589
+ setCategoryHasMore((prev) => {
43590
+ if (prev.idle_time === void 0) {
43591
+ return prev;
43592
+ }
43593
+ const next = { ...prev };
43594
+ delete next.idle_time;
43595
+ return next;
43596
+ });
43597
+ }, [idleClipSort]);
43396
43598
  const isCategoryExternallyManaged = React144.useCallback((categoryId) => {
43397
43599
  if (!categoryId) {
43398
43600
  return false;
@@ -43551,6 +43753,7 @@ var FileManagerFilters = ({
43551
43753
  return null;
43552
43754
  }
43553
43755
  }, [supabase]);
43756
+ const getMetadataLoadingKey = React144.useCallback((categoryId, page) => `${categoryId}-${page}-${categoryId === "idle_time" ? idleClipSort : "latest"}`, [idleClipSort]);
43554
43757
  const fetchClipMetadataPage = React144.useCallback(async (categoryId, page = 1) => {
43555
43758
  if (!workspaceId || !date || shift === void 0) {
43556
43759
  throw new Error("Missing required params for clip metadata fetch");
@@ -43570,7 +43773,8 @@ var FileManagerFilters = ({
43570
43773
  limit: CLIP_METADATA_PAGE_SIZE,
43571
43774
  knownTotal: typeof counts?.[categoryId] === "number" ? counts[categoryId] : null,
43572
43775
  snapshotDateTime,
43573
- snapshotClipId
43776
+ snapshotClipId,
43777
+ sort: categoryId === "idle_time" ? idleClipSort : "latest"
43574
43778
  }),
43575
43779
  redirectReason: "session_expired"
43576
43780
  });
@@ -43578,7 +43782,7 @@ var FileManagerFilters = ({
43578
43782
  throw new Error(`API error: ${response.status}`);
43579
43783
  }
43580
43784
  return response.json();
43581
- }, [workspaceId, date, shift, counts, snapshotDateTime, snapshotClipId, supabase]);
43785
+ }, [workspaceId, date, shift, counts, snapshotDateTime, snapshotClipId, idleClipSort, supabase]);
43582
43786
  const seedIdleClassifications = React144.useCallback(async (clips) => {
43583
43787
  if (!idleTimeVlmEnabled || clips.length === 0) {
43584
43788
  return;
@@ -43634,7 +43838,7 @@ var FileManagerFilters = ({
43634
43838
  console.warn("[FileManager] Missing required params for clip metadata fetch");
43635
43839
  return;
43636
43840
  }
43637
- const loadingKey = `${categoryId}-${page}`;
43841
+ const loadingKey = getMetadataLoadingKey(categoryId, page);
43638
43842
  if (inFlightMetadataRequestsRef.current.has(loadingKey)) {
43639
43843
  return;
43640
43844
  }
@@ -43662,7 +43866,7 @@ var FileManagerFilters = ({
43662
43866
  return newSet;
43663
43867
  });
43664
43868
  }
43665
- }, [workspaceId, date, shift, fetchClipMetadataPage, idleTimeVlmEnabled, seedIdleClassifications]);
43869
+ }, [workspaceId, date, shift, fetchClipMetadataPage, idleTimeVlmEnabled, seedIdleClassifications, getMetadataLoadingKey]);
43666
43870
  const ensureAllIdleTimeClipMetadataLoaded = React144.useCallback(async () => {
43667
43871
  if (!workspaceId || !date || shift === void 0) {
43668
43872
  return;
@@ -44036,15 +44240,17 @@ var FileManagerFilters = ({
44036
44240
  const colorClasses = getColorClasses(category.color);
44037
44241
  const clipNodes = filteredClips.map((clip, index) => {
44038
44242
  const cycleTime = extractCycleTimeSeconds(clip);
44243
+ const idleDuration = category.id === "idle_time" ? clip.idle_duration_seconds ?? clip.duration : null;
44244
+ const idleDurationLabel = formatDurationLabel(idleDuration);
44039
44245
  const baseTimeLabel = formatClipExplorerTimeLabel({
44040
44246
  categoryId: category.id,
44041
44247
  clipTimestamp: clip.clip_timestamp,
44042
44248
  timezone,
44043
- durationSeconds: clip.duration,
44249
+ durationSeconds: idleDuration ?? clip.duration,
44044
44250
  idleStartTime: clip.idle_start_time,
44045
44251
  idleEndTime: clip.idle_end_time
44046
44252
  });
44047
- const displayLabel = `${baseTimeLabel}${clip.duration && category.id !== "idle_time" && category.id !== "low_value" ? ` - (${clip.duration.toFixed(1)}s)` : ""}`;
44253
+ const displayLabel = `${baseTimeLabel}${idleDurationLabel && category.id === "idle_time" ? ` - (${idleDurationLabel})` : ""}${clip.duration && category.id !== "idle_time" && category.id !== "low_value" ? ` - (${clip.duration.toFixed(1)}s)` : ""}`;
44048
44254
  return {
44049
44255
  id: clip.id,
44050
44256
  label: displayLabel,
@@ -44058,7 +44264,7 @@ var FileManagerFilters = ({
44058
44264
  clipPosition: index + 1,
44059
44265
  // Store 1-based position
44060
44266
  cycleTimeSeconds: cycleTime,
44061
- duration: clip.duration,
44267
+ duration: idleDuration ?? clip.duration,
44062
44268
  // Store duration for custom badge rendering
44063
44269
  cycleItemCount: clip.cycle_item_count ?? null
44064
44270
  };
@@ -44380,11 +44586,11 @@ var FileManagerFilters = ({
44380
44586
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
44381
44587
  "Loading clips..."
44382
44588
  ] }) }),
44383
- loadingCategories.has(`${node.id}-${(categoryPages[node.id] || 0) + 1}`) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2 px-3 text-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center text-sm text-slate-500", children: [
44589
+ loadingCategories.has(getMetadataLoadingKey(node.id, (categoryPages[node.id] || 0) + 1)) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2 px-3 text-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center text-sm text-slate-500", children: [
44384
44590
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-spin mr-2 h-4 w-4 border-2 border-slate-300 border-t-blue-500 rounded-full" }),
44385
44591
  "Loading more clips..."
44386
44592
  ] }) }),
44387
- categoryHasMore[node.id] && !loadingCategories.has(`${node.id}-${(categoryPages[node.id] || 0) + 1}`) && /* @__PURE__ */ jsxRuntime.jsxs(
44593
+ categoryHasMore[node.id] && !loadingCategories.has(getMetadataLoadingKey(node.id, (categoryPages[node.id] || 0) + 1)) && /* @__PURE__ */ jsxRuntime.jsxs(
44388
44594
  "button",
44389
44595
  {
44390
44596
  onClick: (e) => {
@@ -44411,6 +44617,18 @@ var FileManagerFilters = ({
44411
44617
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-bold text-slate-900 tracking-tight", children: "Clips Explorer" }) })
44412
44618
  ] }),
44413
44619
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [
44620
+ activeFilter === "idle_time" && /* @__PURE__ */ jsxRuntime.jsx(
44621
+ "button",
44622
+ {
44623
+ onClick: () => {
44624
+ onIdleClipSortChange?.(idleClipSort === "latest" ? "idle_duration_desc" : "latest");
44625
+ },
44626
+ className: `p-2 rounded-xl transition-all duration-200 ${idleClipSort === "idle_duration_desc" ? "bg-orange-100 text-orange-600 hover:bg-orange-200 shadow-sm" : "bg-slate-100 text-slate-600 hover:bg-slate-200"}`,
44627
+ title: idleClipSort === "idle_duration_desc" ? "Sort by newest first" : "Sort by longest idle first",
44628
+ "aria-label": idleClipSort === "idle_duration_desc" ? "Sort idle clips by newest first" : "Sort idle clips by longest idle first",
44629
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownWideNarrow, { className: "h-5 w-5" })
44630
+ }
44631
+ ),
44414
44632
  activeFilter === "idle_time" && idleTimeVlmEnabled && /* @__PURE__ */ jsxRuntime.jsx(
44415
44633
  "button",
44416
44634
  {
@@ -44431,8 +44649,8 @@ var FileManagerFilters = ({
44431
44649
  )
44432
44650
  ] })
44433
44651
  ] }),
44434
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 mt-3", children: [
44435
- isTimeFilterActive && startTime && endTime && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 text-xs text-blue-600 bg-blue-50/60 px-3 py-1.5 rounded-lg border border-blue-100", children: [
44652
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [
44653
+ isTimeFilterActive && startTime && endTime && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex w-fit items-center gap-2 rounded-full border border-blue-100 bg-blue-50/70 px-2.5 py-1 text-xs text-blue-700 shadow-sm", children: [
44436
44654
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
44437
44655
  "Time: ",
44438
44656
  getDisplayValue(startTime),
@@ -44448,13 +44666,13 @@ var FileManagerFilters = ({
44448
44666
  setEndTime("");
44449
44667
  setIsTimeFilterActive(false);
44450
44668
  },
44451
- className: "ml-2 hover:bg-blue-100 rounded p-0.5 transition-colors",
44669
+ className: "rounded-full p-0.5 transition-colors hover:bg-blue-100",
44452
44670
  title: "Clear time filter",
44453
44671
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3.5 w-3.5" })
44454
44672
  }
44455
44673
  )
44456
44674
  ] }),
44457
- idleLabelFilter && activeFilter === "idle_time" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 text-xs text-purple-600 bg-purple-50/60 px-3 py-1.5 rounded-lg border border-purple-100", children: [
44675
+ idleLabelFilter && activeFilter === "idle_time" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex w-fit items-center gap-2 rounded-full border border-purple-100 bg-purple-50/70 px-2.5 py-1 text-xs text-purple-700 shadow-sm", children: [
44458
44676
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
44459
44677
  "Reason: ",
44460
44678
  selectedIdleReasonOption?.displayName || idleLabelFilter.replace(/_/g, " ")
@@ -44466,11 +44684,27 @@ var FileManagerFilters = ({
44466
44684
  e.stopPropagation();
44467
44685
  setIdleLabelFilter(null);
44468
44686
  },
44469
- className: "ml-2 hover:bg-purple-100 rounded p-0.5 transition-colors",
44687
+ className: "rounded-full p-0.5 transition-colors hover:bg-purple-100",
44470
44688
  title: "Clear label filter",
44471
44689
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3.5 w-3.5" })
44472
44690
  }
44473
44691
  )
44692
+ ] }),
44693
+ activeFilter === "idle_time" && idleClipSort === "idle_duration_desc" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex w-fit items-center gap-2 rounded-full border border-orange-100 bg-orange-50/70 px-2.5 py-1 text-xs text-orange-700 shadow-sm", children: [
44694
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownWideNarrow, { className: "h-3.5 w-3.5" }),
44695
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Longest idle first" }),
44696
+ /* @__PURE__ */ jsxRuntime.jsx(
44697
+ "button",
44698
+ {
44699
+ onClick: (e) => {
44700
+ e.stopPropagation();
44701
+ onIdleClipSortChange?.("latest");
44702
+ },
44703
+ className: "rounded-full p-0.5 transition-colors hover:bg-orange-100",
44704
+ title: "Clear idle sort",
44705
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3.5 w-3.5" })
44706
+ }
44707
+ )
44474
44708
  ] })
44475
44709
  ] })
44476
44710
  ] }),
@@ -45234,8 +45468,10 @@ var BottlenecksContent = ({
45234
45468
  const [clipClassifications, setClipClassifications] = React144.useState({});
45235
45469
  const [categoryMetadata, setCategoryMetadata] = React144.useState([]);
45236
45470
  const [categoryMetadataCategoryId, setCategoryMetadataCategoryId] = React144.useState(null);
45471
+ const [categoryMetadataSort, setCategoryMetadataSort] = React144.useState(null);
45237
45472
  const [currentMetadataIndex, setCurrentMetadataIndex] = React144.useState(0);
45238
45473
  const [metadataCache, setMetadataCache] = React144.useState({});
45474
+ const [idleClipSort, setIdleClipSort] = React144.useState("latest");
45239
45475
  const invalidateMetadataCache = React144.useCallback((categories) => {
45240
45476
  setMetadataCache((prevCache) => {
45241
45477
  if (!prevCache || Object.keys(prevCache).length === 0) {
@@ -45266,6 +45502,7 @@ var BottlenecksContent = ({
45266
45502
  const [isFullscreen, setIsFullscreen] = React144.useState(false);
45267
45503
  const categoryMetadataRef = React144.useRef([]);
45268
45504
  const currentMetadataIndexRef = React144.useRef(0);
45505
+ const previousIdleClipSortRef = React144.useRef(idleClipSort);
45269
45506
  const clearRetryTimeout = React144.useCallback(() => {
45270
45507
  if (retryTimeoutRef.current) {
45271
45508
  clearTimeout(retryTimeoutRef.current);
@@ -45712,9 +45949,13 @@ var BottlenecksContent = ({
45712
45949
  }
45713
45950
  return ["fast-cycles", "slow-cycles", "longest-idles"].includes(categoryId);
45714
45951
  }, [isFastSlowClipFiltersEnabled]);
45952
+ const shouldUseMetadataNavigation = React144.useCallback((categoryId) => {
45953
+ return isPercentileCategory(categoryId) || categoryId === "idle_time" && idleClipSort === "idle_duration_desc";
45954
+ }, [idleClipSort, isPercentileCategory]);
45715
45955
  const getMetadataCacheKey = React144.useCallback((categoryId) => {
45716
- return `${categoryId}-${effectiveDateString}-${effectiveShiftId}-${snapshotDateTime ?? "nosnap"}-${snapshotClipId ?? "nosnap"}`;
45717
- }, [effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId]);
45956
+ const sortKey = categoryId === "idle_time" ? idleClipSort : "latest";
45957
+ return `${categoryId}-${effectiveDateString}-${effectiveShiftId}-${snapshotDateTime ?? "nosnap"}-${snapshotClipId ?? "nosnap"}-${sortKey}`;
45958
+ }, [effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, idleClipSort]);
45718
45959
  const setVisibleCategoryMetadata = React144.useCallback((categoryId, clips) => {
45719
45960
  if (activeFilterRef.current !== categoryId) {
45720
45961
  return false;
@@ -45722,8 +45963,9 @@ var BottlenecksContent = ({
45722
45963
  categoryMetadataRef.current = clips;
45723
45964
  setCategoryMetadata(clips);
45724
45965
  setCategoryMetadataCategoryId(clips.length > 0 ? categoryId : null);
45966
+ setCategoryMetadataSort(clips.length > 0 ? categoryId === "idle_time" ? idleClipSort : "latest" : null);
45725
45967
  return true;
45726
- }, []);
45968
+ }, [idleClipSort]);
45727
45969
  const applyMetadataSnapshot = React144.useCallback((categoryId, clips, total) => {
45728
45970
  if (!clips || clips.length === 0) {
45729
45971
  return;
@@ -45734,11 +45976,11 @@ var BottlenecksContent = ({
45734
45976
  [cacheKey]: clips
45735
45977
  }));
45736
45978
  setVisibleCategoryMetadata(categoryId, clips);
45737
- if (!isPercentileCategory(categoryId) && typeof total === "number") {
45979
+ if (!shouldUseMetadataNavigation(categoryId) && typeof total === "number") {
45738
45980
  currentTotalRef.current = total;
45739
45981
  setCurrentTotal(total);
45740
45982
  }
45741
- }, [getMetadataCacheKey, isPercentileCategory, setVisibleCategoryMetadata]);
45983
+ }, [getMetadataCacheKey, shouldUseMetadataNavigation, setVisibleCategoryMetadata]);
45742
45984
  const getClipTypesForPercentileCategory = React144.useCallback((categoryId) => {
45743
45985
  switch (categoryId) {
45744
45986
  case "fast-cycles":
@@ -45764,6 +46006,7 @@ var BottlenecksContent = ({
45764
46006
  }
45765
46007
  setCategoryMetadata([]);
45766
46008
  setCategoryMetadataCategoryId(null);
46009
+ setCategoryMetadataSort(null);
45767
46010
  categoryMetadataRef.current = [];
45768
46011
  updateActiveFilter(fallbackFilter);
45769
46012
  }, [isFastSlowClipFiltersEnabled, activeFilter, dynamicCounts, clipTypes, updateActiveFilter]);
@@ -45811,6 +46054,7 @@ var BottlenecksContent = ({
45811
46054
  if (!isFastSlowClipFiltersEnabled && (categoryId === "fast-cycles" || categoryId === "slow-cycles")) {
45812
46055
  setCategoryMetadata([]);
45813
46056
  setCategoryMetadataCategoryId(null);
46057
+ setCategoryMetadataSort(null);
45814
46058
  categoryMetadataRef.current = [];
45815
46059
  return;
45816
46060
  }
@@ -45881,7 +46125,8 @@ var BottlenecksContent = ({
45881
46125
  limit: 100,
45882
46126
  knownTotal: mergedCounts[categoryId] ?? null,
45883
46127
  snapshotDateTime,
45884
- snapshotClipId
46128
+ snapshotClipId,
46129
+ sort: categoryId === "idle_time" ? idleClipSort : "latest"
45885
46130
  }),
45886
46131
  redirectReason: "session_expired"
45887
46132
  });
@@ -45960,6 +46205,7 @@ var BottlenecksContent = ({
45960
46205
  if (activeFilterRef.current === categoryId) {
45961
46206
  setCategoryMetadata([]);
45962
46207
  setCategoryMetadataCategoryId(null);
46208
+ setCategoryMetadataSort(null);
45963
46209
  categoryMetadataRef.current = [];
45964
46210
  }
45965
46211
  }
@@ -45968,7 +46214,26 @@ var BottlenecksContent = ({
45968
46214
  } finally {
45969
46215
  setIsCategoryLoading(false);
45970
46216
  }
45971
- }, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, supabase, setVisibleCategoryMetadata]);
46217
+ }, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, idleClipSort, supabase, setVisibleCategoryMetadata]);
46218
+ React144.useEffect(() => {
46219
+ if (previousIdleClipSortRef.current === idleClipSort) {
46220
+ return;
46221
+ }
46222
+ previousIdleClipSortRef.current = idleClipSort;
46223
+ if (activeFilterRef.current !== "idle_time") {
46224
+ return;
46225
+ }
46226
+ setCategoryMetadata([]);
46227
+ setCategoryMetadataCategoryId(null);
46228
+ setCategoryMetadataSort(null);
46229
+ categoryMetadataRef.current = [];
46230
+ setCurrentMetadataIndex(0);
46231
+ currentMetadataIndexRef.current = 0;
46232
+ setCurrentPosition(0);
46233
+ currentPositionRef.current = 0;
46234
+ setIsCategoryLoading(true);
46235
+ void loadCategoryMetadata("idle_time", true, true);
46236
+ }, [idleClipSort, loadCategoryMetadata]);
45972
46237
  React144.useEffect(() => {
45973
46238
  if (previousFilterRef.current !== activeFilter) {
45974
46239
  console.log(`Filter changed from ${previousFilterRef.current} to ${activeFilter} - resetting to first video`);
@@ -45979,6 +46244,7 @@ var BottlenecksContent = ({
45979
46244
  loadingCategoryRef.current = null;
45980
46245
  setCategoryMetadata([]);
45981
46246
  setCategoryMetadataCategoryId(null);
46247
+ setCategoryMetadataSort(null);
45982
46248
  setCurrentMetadataIndex(0);
45983
46249
  categoryMetadataRef.current = [];
45984
46250
  currentMetadataIndexRef.current = 0;
@@ -46077,7 +46343,7 @@ var BottlenecksContent = ({
46077
46343
  }
46078
46344
  if (metadataArray.length === 0) {
46079
46345
  console.warn(`[BottlenecksContent] No metadata available for category ${categoryId} after refresh`);
46080
- if (!isPercentileCategory(categoryId)) {
46346
+ if (!shouldUseMetadataNavigation(categoryId)) {
46081
46347
  const resolvedPosition = typeof position === "number" ? position : 1;
46082
46348
  currentPositionRef.current = resolvedPosition;
46083
46349
  setCurrentPosition(resolvedPosition);
@@ -46090,7 +46356,7 @@ var BottlenecksContent = ({
46090
46356
  const clickedClipIndex = metadataArray.findIndex((clip) => clip.clipId === clipId);
46091
46357
  if (clickedClipIndex === -1) {
46092
46358
  console.warn(`[BottlenecksContent] Clip ${clipId} not found after metadata refresh`);
46093
- if (!isPercentileCategory(categoryId)) {
46359
+ if (!shouldUseMetadataNavigation(categoryId)) {
46094
46360
  const resolvedPosition = typeof position === "number" ? position : 1;
46095
46361
  currentPositionRef.current = resolvedPosition;
46096
46362
  setCurrentPosition(resolvedPosition);
@@ -46102,7 +46368,7 @@ var BottlenecksContent = ({
46102
46368
  }
46103
46369
  setCurrentMetadataIndex(clickedClipIndex);
46104
46370
  currentMetadataIndexRef.current = clickedClipIndex;
46105
- if (!isPercentileCategory(categoryId)) {
46371
+ if (!shouldUseMetadataNavigation(categoryId)) {
46106
46372
  const position2 = clickedClipIndex + 1;
46107
46373
  currentPositionRef.current = position2;
46108
46374
  setCurrentPosition(position2);
@@ -46132,7 +46398,7 @@ var BottlenecksContent = ({
46132
46398
  clearLoadingState();
46133
46399
  }
46134
46400
  }
46135
- }, [workspaceId, s3ClipsService, updateActiveFilter, clearLoadingState, clearRetryTimeout, loadCategoryMetadata, applyMetadataSnapshot, mergedCounts, isPercentileCategory]);
46401
+ }, [workspaceId, s3ClipsService, updateActiveFilter, clearLoadingState, clearRetryTimeout, loadCategoryMetadata, applyMetadataSnapshot, mergedCounts, shouldUseMetadataNavigation]);
46136
46402
  const restartCurrentClipPlayback = React144.useCallback(() => {
46137
46403
  if (!currentClipId) {
46138
46404
  return;
@@ -46153,7 +46419,7 @@ var BottlenecksContent = ({
46153
46419
  return;
46154
46420
  }
46155
46421
  const activeCategory = activeFilterRef.current;
46156
- if (!activeCategory || activeCategory === "all" || isPercentileCategory(activeCategory)) {
46422
+ if (!activeCategory || activeCategory === "all" || shouldUseMetadataNavigation(activeCategory)) {
46157
46423
  return;
46158
46424
  }
46159
46425
  let cancelled = false;
@@ -46186,7 +46452,7 @@ var BottlenecksContent = ({
46186
46452
  }, [
46187
46453
  newClipsNotification,
46188
46454
  s3ClipsService,
46189
- isPercentileCategory,
46455
+ shouldUseMetadataNavigation,
46190
46456
  currentClipId,
46191
46457
  invalidateMetadataCache,
46192
46458
  loadAndPlayClipById,
@@ -46238,7 +46504,7 @@ var BottlenecksContent = ({
46238
46504
  }
46239
46505
  }
46240
46506
  try {
46241
- if (!isPercentileCategory(currentFilter)) {
46507
+ if (!shouldUseMetadataNavigation(currentFilter)) {
46242
46508
  if (!s3ClipsService || !workspaceId || !currentClipId) {
46243
46509
  throw new Error("S3 clips service not available");
46244
46510
  }
@@ -46338,7 +46604,7 @@ var BottlenecksContent = ({
46338
46604
  } else {
46339
46605
  const firstClipMeta = metadataArray[0];
46340
46606
  if (firstClipMeta?.clipId && firstClipMeta.clipId !== currentClipId) {
46341
- console.log(`[handleNext] Reached end of ${currentFilter}, looping back to newest percentile clip ${firstClipMeta.clipId}`);
46607
+ console.log(`[handleNext] Reached end of ${currentFilter}, looping back to first metadata clip ${firstClipMeta.clipId}`);
46342
46608
  await loadAndPlayClipById(firstClipMeta.clipId, currentFilter, 1, {
46343
46609
  clips: metadataArray,
46344
46610
  total: metadataArray.length
@@ -46364,7 +46630,7 @@ var BottlenecksContent = ({
46364
46630
  });
46365
46631
  clearLoadingState();
46366
46632
  }
46367
- }, [clearLoadingState, clearRetryTimeout, s3ClipsService, loadCategoryMetadata, loadAndPlayClipById, isPercentileCategory, workspaceId, currentClipId, effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, mergedCounts]);
46633
+ }, [clearLoadingState, clearRetryTimeout, s3ClipsService, loadCategoryMetadata, loadAndPlayClipById, shouldUseMetadataNavigation, workspaceId, currentClipId, effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, mergedCounts]);
46368
46634
  const handlePrevious = React144.useCallback(async () => {
46369
46635
  if (!isMountedRef.current || navigationLockRef.current) return;
46370
46636
  const currentFilter = activeFilterRef.current;
@@ -46383,7 +46649,7 @@ var BottlenecksContent = ({
46383
46649
  }
46384
46650
  }
46385
46651
  try {
46386
- if (!isPercentileCategory(currentFilter)) {
46652
+ if (!shouldUseMetadataNavigation(currentFilter)) {
46387
46653
  if (!s3ClipsService || !workspaceId || !currentClipId) {
46388
46654
  throw new Error("S3 clips service not available");
46389
46655
  }
@@ -46468,7 +46734,7 @@ var BottlenecksContent = ({
46468
46734
  });
46469
46735
  clearLoadingState();
46470
46736
  }
46471
- }, [clearLoadingState, clearRetryTimeout, s3ClipsService, loadCategoryMetadata, isPercentileCategory, workspaceId, currentClipId, effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, mergedCounts]);
46737
+ }, [clearLoadingState, clearRetryTimeout, s3ClipsService, loadCategoryMetadata, shouldUseMetadataNavigation, workspaceId, currentClipId, effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, mergedCounts]);
46472
46738
  const currentVideo = React144.useMemo(() => {
46473
46739
  if (!filteredVideos || filteredVideos.length === 0 || currentIndex >= filteredVideos.length) {
46474
46740
  return null;
@@ -46535,22 +46801,22 @@ var BottlenecksContent = ({
46535
46801
  }
46536
46802
  }, [currentVideo?.id, isShareLoading, supabase, workspaceId, workspaceName]);
46537
46803
  React144.useMemo(() => {
46538
- if (isPercentileCategory(activeFilter)) {
46804
+ if (shouldUseMetadataNavigation(activeFilter)) {
46539
46805
  return categoryMetadata.length;
46540
46806
  }
46541
46807
  return currentTotal || mergedCounts[activeFilter] || 0;
46542
- }, [activeFilter, categoryMetadata.length, currentTotal, mergedCounts, isPercentileCategory]);
46808
+ }, [activeFilter, categoryMetadata.length, currentTotal, mergedCounts, shouldUseMetadataNavigation]);
46543
46809
  React144.useMemo(() => {
46544
- if (isPercentileCategory(activeFilter)) {
46810
+ if (shouldUseMetadataNavigation(activeFilter)) {
46545
46811
  return categoryMetadata.length > 0 ? currentMetadataIndex + 1 : 0;
46546
46812
  }
46547
46813
  return currentPosition;
46548
- }, [activeFilter, categoryMetadata.length, currentMetadataIndex, currentPosition, isPercentileCategory]);
46549
- const prefetchedExplorerMetadata = React144.useMemo(() => buildPrefetchedExplorerMetadata(
46814
+ }, [activeFilter, categoryMetadata.length, currentMetadataIndex, currentPosition, shouldUseMetadataNavigation]);
46815
+ const prefetchedExplorerMetadata = React144.useMemo(() => activeFilter === "idle_time" && categoryMetadataSort !== idleClipSort ? void 0 : buildPrefetchedExplorerMetadata(
46550
46816
  activeFilter,
46551
46817
  categoryMetadataCategoryId,
46552
46818
  categoryMetadata
46553
- ), [activeFilter, categoryMetadata, categoryMetadataCategoryId]);
46819
+ ), [activeFilter, categoryMetadata, categoryMetadataCategoryId, categoryMetadataSort, idleClipSort]);
46554
46820
  const classificationClipIds = React144.useMemo(() => {
46555
46821
  if (!idleTimeVlmEnabled) {
46556
46822
  return [];
@@ -47299,7 +47565,12 @@ var BottlenecksContent = ({
47299
47565
  showPercentileCycleFilters: isFastSlowClipFiltersEnabled,
47300
47566
  prefetchedClipMetadata: prefetchedExplorerMetadata,
47301
47567
  activeCategoryLoading: isCategoryLoading,
47568
+ idleClipSort,
47569
+ onIdleClipSortChange: setIdleClipSort,
47302
47570
  onFilterChange: (filterId) => {
47571
+ if (filterId !== "idle_time") {
47572
+ setIdleClipSort("latest");
47573
+ }
47303
47574
  updateActiveFilter(filterId);
47304
47575
  const category = categoriesToShow.find((cat) => cat.type === filterId);
47305
47576
  if (category) {
@@ -49222,6 +49493,11 @@ var LineHistoryCalendar = ({
49222
49493
  return calendar;
49223
49494
  }, [data, month, year, configuredTimezone]);
49224
49495
  const hasRealData = (shift) => {
49496
+ if (isUptimeMode) {
49497
+ if (shift.hasData === true) return true;
49498
+ const efficiency = Number(shift.avg_efficiency);
49499
+ return shift.total_workspaces > 0 || shift.underperforming_workspaces > 0 || (shift.output || 0) > 0 || (shift.available_time_seconds || 0) > 0 || (shift.active_time_seconds || 0) > 0 || (shift.idle_time_seconds || 0) > 0 || Number.isFinite(efficiency) && efficiency > 0;
49500
+ }
49225
49501
  if (shift.hasData !== void 0) return shift.hasData;
49226
49502
  return shift.total_workspaces > 0 || shift.avg_efficiency > 0 || shift.underperforming_workspaces > 0;
49227
49503
  };
@@ -49854,13 +50130,18 @@ var LineMonthlyHistory = ({
49854
50130
  enabled: !!lineId && idleTimeVlmEnabled
49855
50131
  });
49856
50132
  const hasRealData = (shift) => {
50133
+ if (isUptimeMode) {
50134
+ if (shift.hasData === true) return true;
50135
+ const efficiency = Number(shift.avg_efficiency);
50136
+ return shift.total_workspaces > 0 || shift.underperforming_workspaces > 0 || (shift.output || 0) > 0 || (shift.idealOutput || 0) > 0 || (shift.idle_time_seconds || 0) > 0 || (shift.active_time_seconds || 0) > 0 || (shift.available_time_seconds || 0) > 0 || Number.isFinite(efficiency) && efficiency > 0;
50137
+ }
49857
50138
  if (shift.hasData !== void 0) return shift.hasData;
49858
50139
  return shift.avg_efficiency > 0 || shift.underperforming_workspaces > 0 || shift.total_workspaces > 0 || (shift.output || 0) > 0 || (shift.idealOutput || 0) > 0 || (shift.idle_time_seconds || 0) > 0 || (shift.active_time_seconds || 0) > 0 || (shift.available_time_seconds || 0) > 0;
49859
50140
  };
49860
50141
  const averages = (analysisMonthlyData || []).reduce(
49861
50142
  (acc, day) => {
49862
50143
  const shiftData = getShiftData2(day, selectedShiftId);
49863
- if (!shiftData || shiftData?.avg_efficiency < 5) {
50144
+ if (!shiftData || !isValidAggregateEfficiency(isUptimeMode ? "uptime" : "output", shiftData.avg_efficiency)) {
49864
50145
  return acc;
49865
50146
  }
49866
50147
  return {
@@ -49889,7 +50170,9 @@ var LineMonthlyHistory = ({
49889
50170
  const avgOutput = outputAverages.count > 0 ? outputAverages.output / outputAverages.count : 0;
49890
50171
  const uptimeSummary = React144.useMemo(() => {
49891
50172
  if (!isUptimeMode) return null;
49892
- const validDays = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter((shiftData) => shiftData && hasRealData(shiftData)).map((shiftData) => ({ shiftData, totals: getUptimeTotals(shiftData) }));
50173
+ const validDays = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter(
50174
+ (shiftData) => shiftData && hasRealData(shiftData) && isValidAggregateEfficiency("uptime", shiftData.avg_efficiency)
50175
+ ).map((shiftData) => ({ shiftData, totals: getUptimeTotals(shiftData) }));
49893
50176
  if (!validDays.length) {
49894
50177
  return { avgUtilization: 0, avgIdleTime: 0, avgDailyStoppages: 0 };
49895
50178
  }
@@ -50037,7 +50320,9 @@ var LineMonthlyHistory = ({
50037
50320
  }, [chartData.yAxisMax, chartData.lastSetTarget]);
50038
50321
  const pieChartData = React144.useMemo(() => {
50039
50322
  if (!isUptimeMode) return [];
50040
- const validShifts = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter(hasRealData);
50323
+ const validShifts = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter(
50324
+ (shift) => shift && hasRealData(shift) && isValidAggregateEfficiency("uptime", shift.avg_efficiency)
50325
+ );
50041
50326
  if (!validShifts.length) return [];
50042
50327
  const efficiencyValues = validShifts.map((shift) => Number.isFinite(shift.avg_efficiency) ? Number(shift.avg_efficiency) : null).filter((value) => value !== null);
50043
50328
  if (!efficiencyValues.length) return [];
@@ -50647,7 +50932,9 @@ var LineMonthlyPdfGenerator = ({
50647
50932
  const productiveSeconds = activeSecondsRaw > 0 ? Math.min(activeSecondsRaw, availableSeconds) : Math.max(availableSeconds - idleSeconds, 0);
50648
50933
  return { availableSeconds, productiveSeconds, idleSeconds };
50649
50934
  };
50650
- const validShifts = validDays.map((day) => getLineShiftData2(day, selectedShiftId)).filter((shift) => isUptimeMode ? hasShiftData(shift) : shift.avg_efficiency >= 5);
50935
+ const validShifts = validDays.map((day) => getLineShiftData2(day, selectedShiftId)).filter(
50936
+ (shift) => hasShiftData(shift) && isValidAggregateEfficiency(isUptimeMode ? "uptime" : "output", shift.avg_efficiency)
50937
+ );
50651
50938
  const monthlyMetrics = validShifts.length > 0 ? isUptimeMode ? (() => {
50652
50939
  let utilizationSum = 0;
50653
50940
  let idleTimeSum = 0;
@@ -52632,7 +52919,10 @@ var WorkspaceMonthlyHistory = ({
52632
52919
  return ticks.filter((v) => v >= 0 && v <= max * 1.05).sort((a, b) => a - b);
52633
52920
  }, [chartData.yAxisMax, chartData.lastSetTarget, isUptimeMode]);
52634
52921
  const pieChartData = React144.useMemo(() => {
52635
- const validShifts = analysisMonthlyData.map((d) => getShiftData(d, selectedShiftId)).filter(hasRealData);
52922
+ const aggregateMode = isUptimeMode ? "uptime" : "output";
52923
+ const validShifts = analysisMonthlyData.map((d) => getShiftData(d, selectedShiftId)).filter(
52924
+ (shift) => shift && hasRealData(shift) && isValidAggregateEfficiency(aggregateMode, shift.efficiency)
52925
+ );
52636
52926
  if (validShifts.length === 0) return [];
52637
52927
  const efficiencyValues = validShifts.map((shift) => Number.isFinite(shift.efficiency) ? Number(shift.efficiency) : null).filter((value) => value !== null);
52638
52928
  if (!efficiencyValues.length) return [];
@@ -52643,10 +52933,10 @@ var WorkspaceMonthlyHistory = ({
52643
52933
  { name: "Productive", value: productivePercent },
52644
52934
  { name: "Idle", value: idlePercent }
52645
52935
  ];
52646
- }, [analysisMonthlyData, selectedShiftId, shiftWorkSeconds]);
52936
+ }, [analysisMonthlyData, selectedShiftId, isUptimeMode]);
52647
52937
  const metrics2 = React144.useMemo(() => {
52648
52938
  const validShifts = analysisMonthlyData.map((d) => getShiftData(d, selectedShiftId)).filter(hasRealData);
52649
- const filteredShifts = isUptimeMode ? validShifts : validShifts.filter((shift) => (shift.efficiency ?? 0) >= 5);
52939
+ const filteredShifts = isUptimeMode ? validShifts.filter((shift) => isValidAggregateEfficiency("uptime", shift.efficiency)) : validShifts.filter((shift) => isValidAggregateEfficiency("output", shift.efficiency));
52650
52940
  if (filteredShifts.length === 0) return null;
52651
52941
  const totalEfficiency = filteredShifts.reduce((sum, shift) => sum + (shift.efficiency || 0), 0);
52652
52942
  const totalUtilization = filteredShifts.reduce(
@@ -53866,7 +54156,7 @@ var WorkspaceMonthlyPdfGenerator = ({
53866
54156
  const shift = getShiftData(dayData, selectedShiftId);
53867
54157
  return { dayData, shift };
53868
54158
  }).filter(({ shift }) => hasShiftData(shift)).sort((left, right) => getDayDateKey(right.dayData).localeCompare(getDayDateKey(left.dayData)));
53869
- const filteredShifts = isUptimeMode ? validShifts : validShifts.filter((shift) => (shift.efficiency ?? 0) >= 5);
54159
+ const filteredShifts = isUptimeMode ? validShifts.filter((shift) => isValidAggregateEfficiency("uptime", shift.efficiency)) : validShifts.filter((shift) => isValidAggregateEfficiency("output", shift.efficiency));
53870
54160
  const monthlyMetrics = filteredShifts.length > 0 ? isUptimeMode ? (() => {
53871
54161
  const totalIdleTime = filteredShifts.reduce((sum, shift) => sum + shift.idleTime, 0);
53872
54162
  const totalCycleTime = filteredShifts.reduce((sum, shift) => sum + shift.cycleTime, 0);
@@ -54136,7 +54426,8 @@ var WorkspaceCycleTimeMetricCards = ({
54136
54426
  idleTimeData,
54137
54427
  skuAware,
54138
54428
  skuBreakdown,
54139
- activeSkuId
54429
+ activeSkuId,
54430
+ liveSkuId
54140
54431
  }) => {
54141
54432
  const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
54142
54433
  const activeSku = React144__namespace.default.useMemo(() => {
@@ -54145,6 +54436,13 @@ var WorkspaceCycleTimeMetricCards = ({
54145
54436
  }
54146
54437
  return null;
54147
54438
  }, [skuAware, activeSkuId, skuBreakdown]);
54439
+ const displaySku = React144__namespace.default.useMemo(() => {
54440
+ if (activeSku) return activeSku;
54441
+ if (skuAware && !activeSkuId && liveSkuId && skuBreakdown) {
54442
+ return skuBreakdown.find((s) => s.sku_id === liveSkuId) ?? null;
54443
+ }
54444
+ return null;
54445
+ }, [activeSku, skuAware, activeSkuId, liveSkuId, skuBreakdown]);
54148
54446
  const cycleValue = activeSku ? activeSku.avg_cycle_time : workspace.avg_cycle_time;
54149
54447
  const cycleStandard = activeSku ? activeSku.ideal_cycle_time : workspace.ideal_cycle_time;
54150
54448
  const efficiencyValue = workspace.avg_efficiency || 0;
@@ -54174,7 +54472,7 @@ var WorkspaceCycleTimeMetricCards = ({
54174
54472
  /* @__PURE__ */ jsxRuntime.jsxs(Card2, { className: "flex flex-col bg-white shadow-sm border border-gray-200 h-full min-h-[150px] sm:min-h-0 rounded-xl", children: [
54175
54473
  /* @__PURE__ */ jsxRuntime.jsxs(CardHeader2, { className: "pb-1 pt-5 flex-none text-center", children: [
54176
54474
  /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-[15px] font-bold text-gray-900 tracking-wide", children: "Cycle Time (s)" }),
54177
- activeSku && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-blue-600 mt-1 truncate px-2", title: activeSku.sku_code, children: activeSku.sku_code })
54475
+ displaySku && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-blue-600 mt-1 truncate px-2", title: displaySku.sku_code, children: displaySku.sku_code })
54178
54476
  ] }),
54179
54477
  /* @__PURE__ */ jsxRuntime.jsxs(CardContent2, { className: "flex-1 flex flex-col items-center justify-center pb-6", children: [
54180
54478
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-5xl font-bold tracking-tight ${cycleValue > (cycleStandard || 0) ? "text-red-500" : "text-[#34C759]"}`, children: cycleValue.toFixed(1) }),
@@ -67038,7 +67336,15 @@ var KPIDetailView = ({
67038
67336
  const fallbackTimes = resolveMonthlyShiftTimes(metric.shift_id);
67039
67337
  const resolvedShiftStart = metric.shift_start || fallbackTimes.start;
67040
67338
  const resolvedShiftEnd = metric.shift_end || fallbackTimes.end;
67041
- const hasBackendUptimeSeconds = isUptimeMode && (Number.isFinite(metric.active_time_seconds) || Number.isFinite(metric.idle_time_seconds) || Number.isFinite(metric.available_time_seconds));
67339
+ const coerceOptionalNumber2 = (value) => {
67340
+ if (value === void 0 || value === null || value === "") return null;
67341
+ const parsed = Number(value);
67342
+ return Number.isFinite(parsed) ? parsed : null;
67343
+ };
67344
+ const metricActiveTimeSeconds = coerceOptionalNumber2(metric.active_time_seconds);
67345
+ const metricIdleTimeSeconds = coerceOptionalNumber2(metric.idle_time_seconds);
67346
+ const metricAvailableTimeSeconds = coerceOptionalNumber2(metric.available_time_seconds);
67347
+ const hasBackendUptimeSeconds = isUptimeMode && (metricActiveTimeSeconds !== null || metricIdleTimeSeconds !== null || metricAvailableTimeSeconds !== null);
67042
67348
  const uptimeSeries2 = isUptimeMode && !hasBackendUptimeSeconds ? buildUptimeSeries({
67043
67349
  idleTimeHourly: metric.idle_time_hourly || {},
67044
67350
  shiftStart: resolvedShiftStart || void 0,
@@ -67046,9 +67352,13 @@ var KPIDetailView = ({
67046
67352
  shiftDate: metric.date,
67047
67353
  timezone: configuredTimezone
67048
67354
  }) : null;
67049
- const idleTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metric.idle_time_seconds || 0 : (uptimeSeries2?.idleMinutes || 0) * 60 : 0;
67050
- const activeTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metric.active_time_seconds || 0 : (uptimeSeries2?.activeMinutes || 0) * 60 : 0;
67051
- const availableTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metric.available_time_seconds || activeTimeSeconds + idleTimeSeconds : (uptimeSeries2?.availableMinutes || 0) * 60 : 0;
67355
+ const idleTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metricIdleTimeSeconds ?? 0 : (uptimeSeries2?.idleMinutes || 0) * 60 : 0;
67356
+ const activeTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metricActiveTimeSeconds ?? 0 : (uptimeSeries2?.activeMinutes || 0) * 60 : 0;
67357
+ const availableTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metricAvailableTimeSeconds ?? activeTimeSeconds + idleTimeSeconds : (uptimeSeries2?.availableMinutes || 0) * 60 : 0;
67358
+ const metricAvgEfficiency = Number(metric.avg_efficiency);
67359
+ const metricTotalWorkspaces = Number(metric.total_workspaces || 0);
67360
+ const metricCurrentOutput = Number(metric.current_output || 0);
67361
+ const hasUptimeMetricData = isUptimeMode && (availableTimeSeconds > 0 || metricTotalWorkspaces > 0 || metricCurrentOutput > 0 || Number.isFinite(metricAvgEfficiency) && metricAvgEfficiency > 0);
67052
67362
  const computedUptimeEfficiency = (() => {
67053
67363
  const availableMinutes = availableTimeSeconds / 60;
67054
67364
  if (!availableMinutes || availableMinutes <= 0) return 0;
@@ -67068,7 +67378,7 @@ var KPIDetailView = ({
67068
67378
  targetOutput: Number(metric.line_threshold ?? metric.ideal_output ?? 0),
67069
67379
  compliance_percentage: 95 + Math.random() * 5,
67070
67380
  // Mock data: random value between 95-100%
67071
- hasData: isUptimeMode ? availableTimeSeconds > 0 : true,
67381
+ hasData: isUptimeMode ? hasUptimeMetricData : true,
67072
67382
  idle_time_seconds: idleTimeSeconds,
67073
67383
  active_time_seconds: activeTimeSeconds,
67074
67384
  available_time_seconds: availableTimeSeconds,
@@ -68252,6 +68562,9 @@ var KPIDetailView = ({
68252
68562
  var KPIDetailViewWithDisplayNames = withSelectedLineDisplayNames(KPIDetailView);
68253
68563
  var KPIDetailView_default = KPIDetailViewWithDisplayNames;
68254
68564
  var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0;
68565
+ var KPI_FACTORY_QUERY_PARAM = "factory_id";
68566
+ var KPI_FACTORY_AREA_QUERY_PARAM = "factory_area_id";
68567
+ var getSingleQueryValue = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
68255
68568
  var resolveCompanyId = (...candidates) => candidates.find(isNonEmptyString);
68256
68569
  var parseTimeToMinutes3 = (value) => {
68257
68570
  if (!value) return null;
@@ -68288,7 +68601,9 @@ var getMonthDateInfo = (timezone) => {
68288
68601
  var createKpisOverviewUrl = ({
68289
68602
  tab,
68290
68603
  date,
68291
- shift
68604
+ shift,
68605
+ factoryId,
68606
+ factoryAreaId
68292
68607
  }) => {
68293
68608
  const params = new URLSearchParams();
68294
68609
  if (tab) {
@@ -68300,6 +68615,12 @@ var createKpisOverviewUrl = ({
68300
68615
  if (typeof shift === "number" && Number.isFinite(shift)) {
68301
68616
  params.set("shift", shift.toString());
68302
68617
  }
68618
+ if (!tab && factoryId) {
68619
+ params.set(KPI_FACTORY_QUERY_PARAM, factoryId);
68620
+ }
68621
+ if (!tab && factoryId && factoryAreaId) {
68622
+ params.set(KPI_FACTORY_AREA_QUERY_PARAM, factoryAreaId);
68623
+ }
68303
68624
  const queryString = params.toString();
68304
68625
  return queryString ? `/kpis?${queryString}` : "/kpis";
68305
68626
  };
@@ -68821,6 +69142,101 @@ var LineCard = ({
68821
69142
  }
68822
69143
  );
68823
69144
  };
69145
+ var KpiGroupCard = ({
69146
+ title,
69147
+ subtitle,
69148
+ kpis,
69149
+ isLoading,
69150
+ error,
69151
+ isUptimeMode,
69152
+ onClick
69153
+ }) => {
69154
+ const isOnTrack = React144__namespace.default.useMemo(() => {
69155
+ if (!kpis) return null;
69156
+ return isEfficiencyOnTrack(kpis.efficiency.value);
69157
+ }, [kpis]);
69158
+ const outputTarget = Number(kpis?.outputProgress?.target ?? 0);
69159
+ const outputCurrent = Number(kpis?.outputProgress?.current ?? 0);
69160
+ const progressPercent = outputTarget > 0 ? Math.min(outputCurrent / outputTarget * 100, 100) : 0;
69161
+ return /* @__PURE__ */ jsxRuntime.jsxs(
69162
+ motion.div,
69163
+ {
69164
+ initial: { opacity: 0, y: 20 },
69165
+ animate: { opacity: 1, y: 0 },
69166
+ transition: { duration: 0.3 },
69167
+ onClick,
69168
+ className: "relative bg-white border border-gray-200/80 shadow-sm hover:shadow-lg \n rounded-xl p-4 sm:p-5 md:p-6 transition-all duration-200 cursor-pointer \n hover:scale-[1.01] active:scale-[0.99] group",
69169
+ children: [
69170
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4 sm:mb-5 md:mb-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-start gap-2 sm:gap-3", children: [
69171
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
69172
+ /* @__PURE__ */ jsxRuntime.jsx(
69173
+ FittingTitle,
69174
+ {
69175
+ title,
69176
+ className: "text-[10px] sm:text-xs md:text-sm"
69177
+ }
69178
+ ),
69179
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs font-medium text-gray-500", children: subtitle })
69180
+ ] }),
69181
+ !isUptimeMode && kpis && isOnTrack !== null && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center gap-1.5 px-2.5 sm:px-3 py-1 sm:py-1.5 rounded-full text-xs font-medium flex-shrink-0 ${isOnTrack ? "bg-emerald-100 text-emerald-700 border border-emerald-200" : "bg-red-100 text-red-700 border border-red-200"}`, style: { minWidth: "fit-content" }, children: [
69182
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-2 h-2 rounded-full ${isOnTrack ? "bg-emerald-500" : "bg-red-500"} animate-pulse` }),
69183
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: isOnTrack ? "On Track" : "Behind" })
69184
+ ] })
69185
+ ] }) }),
69186
+ isLoading && !kpis && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
69187
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "animate-pulse", children: [
69188
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-gray-200 rounded w-1/3 mb-2" }),
69189
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 bg-gray-200 rounded w-1/2" })
69190
+ ] }),
69191
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "animate-pulse", children: [
69192
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-gray-200 rounded w-1/3 mb-2" }),
69193
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 bg-gray-200 rounded w-3/4" })
69194
+ ] }),
69195
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "animate-pulse", children: [
69196
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-gray-200 rounded w-1/3 mb-2" }),
69197
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 bg-gray-200 rounded w-1/2" })
69198
+ ] })
69199
+ ] }),
69200
+ error && !kpis && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "Unable to load metrics" }) }),
69201
+ kpis && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 sm:space-y-5 pb-8 sm:pb-10", children: [
69202
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
69203
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-medium text-gray-500 uppercase tracking-wider mb-1.5 sm:mb-2", children: isUptimeMode ? "Utilization" : "Efficiency" }),
69204
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline justify-between", children: [
69205
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-2xl sm:text-3xl font-semibold text-gray-900", children: [
69206
+ kpis.efficiency.value.toFixed(1),
69207
+ "%"
69208
+ ] }),
69209
+ kpis.efficiency.change !== 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `text-xs sm:text-sm font-medium ${kpis.efficiency.change > 0 ? "text-emerald-600" : "text-red-600"}`, children: [
69210
+ kpis.efficiency.change > 0 ? "+" : "",
69211
+ kpis.efficiency.change.toFixed(1),
69212
+ "%"
69213
+ ] })
69214
+ ] })
69215
+ ] }),
69216
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
69217
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-medium text-gray-500 uppercase tracking-wider mb-1.5 sm:mb-2", children: isUptimeMode ? "Stoppages" : "Output Progress" }),
69218
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline justify-between mb-2 sm:mb-3", children: [
69219
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${isUptimeMode ? "text-2xl sm:text-3xl font-bold text-red-600" : "text-xl sm:text-2xl font-semibold text-gray-900"}`, children: kpis.outputProgress.current }),
69220
+ !isUptimeMode && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs sm:text-sm text-gray-500 font-medium", children: [
69221
+ "/ ",
69222
+ kpis.outputProgress.target,
69223
+ " units"
69224
+ ] })
69225
+ ] }),
69226
+ !isUptimeMode && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full bg-gray-200 rounded-full h-2 sm:h-2.5", children: /* @__PURE__ */ jsxRuntime.jsx(
69227
+ "div",
69228
+ {
69229
+ className: "bg-blue-600 h-2 sm:h-2.5 rounded-full transition-all duration-500 ease-out",
69230
+ style: { width: `${progressPercent}%` }
69231
+ }
69232
+ ) })
69233
+ ] })
69234
+ ] }),
69235
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-3 right-3 sm:bottom-4 sm:right-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 sm:p-2.5 rounded-full bg-gray-50 group-hover:bg-blue-50 transition-colors shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsx(outline.ArrowRightIcon, { className: "w-4 h-4 sm:w-5 sm:h-5 text-gray-400 group-hover:text-blue-600 transition-colors" }) }) })
69236
+ ]
69237
+ }
69238
+ );
69239
+ };
68824
69240
  var KPIsOverviewView = ({
68825
69241
  companyId,
68826
69242
  navigate,
@@ -68986,6 +69402,20 @@ var KPIsOverviewView = ({
68986
69402
  const effectiveLeaderboardDate = selectedLeaderboardDate || currentShiftDate;
68987
69403
  const effectiveLeaderboardShiftId = Number.isFinite(selectedLeaderboardShiftId) ? selectedLeaderboardShiftId : currentShiftId;
68988
69404
  const isHistoricalLeaderboardDaily = activeTab === "leaderboard" && timeRange === "today" && (effectiveLeaderboardDate !== currentShiftDate || effectiveLeaderboardShiftId !== currentShiftId);
69405
+ const selectedFactoryIdFromUrl = getSingleQueryValue(router$1.query[KPI_FACTORY_QUERY_PARAM]);
69406
+ const selectedFactoryAreaIdFromUrl = getSingleQueryValue(router$1.query[KPI_FACTORY_AREA_QUERY_PARAM]);
69407
+ const kpiLineHierarchy = React144__namespace.default.useMemo(
69408
+ () => buildKpiLineHierarchy(linesForView),
69409
+ [linesForView]
69410
+ );
69411
+ const selectedFactoryNode = React144__namespace.default.useMemo(
69412
+ () => kpiLineHierarchy.showFactoryLevel && selectedFactoryIdFromUrl ? kpiLineHierarchy.factories.find((factory) => factory.id === selectedFactoryIdFromUrl) : void 0,
69413
+ [kpiLineHierarchy, selectedFactoryIdFromUrl]
69414
+ );
69415
+ const selectedFactoryAreaNode = React144__namespace.default.useMemo(
69416
+ () => selectedFactoryNode && selectedFactoryAreaIdFromUrl ? selectedFactoryNode.areas.find((area) => area.id === selectedFactoryAreaIdFromUrl) : void 0,
69417
+ [selectedFactoryNode, selectedFactoryAreaIdFromUrl]
69418
+ );
68989
69419
  React144.useEffect(() => {
68990
69420
  if (!router$1.isReady) return;
68991
69421
  const tabQuery = router$1.query.tab;
@@ -69013,20 +69443,27 @@ var KPIsOverviewView = ({
69013
69443
  ]);
69014
69444
  React144.useEffect(() => {
69015
69445
  if (!router$1.isReady || !hasHydratedLeaderboardRouteState) return;
69446
+ if (activeTab === "today" && loading) return;
69016
69447
  const expectedTab = activeTab === "leaderboard" ? "leaderboard" : void 0;
69017
69448
  const expectedDate = activeTab === "leaderboard" && timeRange === "today" && isHistoricalLeaderboardDaily ? effectiveLeaderboardDate : void 0;
69018
69449
  const expectedShift = expectedDate !== void 0 ? effectiveLeaderboardShiftId.toString() : void 0;
69450
+ const expectedFactory = activeTab === "today" && selectedFactoryNode ? selectedFactoryNode.id : void 0;
69451
+ const expectedFactoryArea = activeTab === "today" && selectedFactoryNode && selectedFactoryAreaNode ? selectedFactoryAreaNode.id : void 0;
69019
69452
  const currentTab = typeof router$1.query.tab === "string" ? router$1.query.tab : void 0;
69020
69453
  const currentDateQuery = typeof router$1.query.date === "string" ? router$1.query.date : void 0;
69021
69454
  const currentShiftQuery = typeof router$1.query.shift === "string" ? router$1.query.shift : void 0;
69022
- if (currentTab === expectedTab && currentDateQuery === expectedDate && currentShiftQuery === expectedShift) {
69455
+ const currentFactoryQuery = getSingleQueryValue(router$1.query[KPI_FACTORY_QUERY_PARAM]);
69456
+ const currentFactoryAreaQuery = getSingleQueryValue(router$1.query[KPI_FACTORY_AREA_QUERY_PARAM]);
69457
+ if (currentTab === expectedTab && currentDateQuery === expectedDate && currentShiftQuery === expectedShift && currentFactoryQuery === expectedFactory && currentFactoryAreaQuery === expectedFactoryArea) {
69023
69458
  return;
69024
69459
  }
69025
69460
  void router$1.replace(
69026
69461
  createKpisOverviewUrl({
69027
69462
  tab: expectedTab === "leaderboard" ? "leaderboard" : void 0,
69028
69463
  date: expectedDate,
69029
- shift: expectedShift !== void 0 ? Number.parseInt(expectedShift, 10) : void 0
69464
+ shift: expectedShift !== void 0 ? Number.parseInt(expectedShift, 10) : void 0,
69465
+ factoryId: expectedFactory,
69466
+ factoryAreaId: expectedFactoryArea
69030
69467
  }),
69031
69468
  void 0,
69032
69469
  { shallow: true }
@@ -69038,7 +69475,10 @@ var KPIsOverviewView = ({
69038
69475
  effectiveLeaderboardDate,
69039
69476
  effectiveLeaderboardShiftId,
69040
69477
  hasHydratedLeaderboardRouteState,
69041
- isHistoricalLeaderboardDaily
69478
+ isHistoricalLeaderboardDaily,
69479
+ loading,
69480
+ selectedFactoryNode,
69481
+ selectedFactoryAreaNode
69042
69482
  ]);
69043
69483
  const factoryViewId = entityConfig.factoryViewId || "factory";
69044
69484
  const {
@@ -69050,13 +69490,42 @@ var KPIsOverviewView = ({
69050
69490
  userAccessibleLineIds: metricsLineIds
69051
69491
  });
69052
69492
  const defaultKPIs = React144__namespace.default.useMemo(() => createDefaultKPIs(), []);
69053
- const kpisByLineId = React144__namespace.default.useMemo(() => {
69493
+ const lineModeById = React144__namespace.default.useMemo(() => {
69494
+ const map = /* @__PURE__ */ new Map();
69495
+ linesForView.forEach((line) => {
69496
+ map.set(line.id, line.monitoring_mode ?? "output");
69497
+ });
69498
+ return map;
69499
+ }, [linesForView]);
69500
+ const lineMetricRowsByLineId = React144__namespace.default.useMemo(() => {
69054
69501
  const map = /* @__PURE__ */ new Map();
69055
69502
  lineMetrics.forEach((row) => {
69056
- if (row?.line_id) map.set(row.line_id, buildKPIsFromLineMetricsRow(row));
69503
+ if (!row?.line_id) return;
69504
+ const monitoringMode = lineModeById.get(row.line_id);
69505
+ map.set(
69506
+ row.line_id,
69507
+ monitoringMode ? { ...row, monitoring_mode: monitoringMode } : row
69508
+ );
69057
69509
  });
69058
69510
  return map;
69059
- }, [lineMetrics]);
69511
+ }, [lineMetrics, lineModeById]);
69512
+ const kpisByLineId = React144__namespace.default.useMemo(() => {
69513
+ const map = /* @__PURE__ */ new Map();
69514
+ lineMetricRowsByLineId.forEach((row, lineId) => {
69515
+ map.set(lineId, buildKPIsFromLineMetricsRow(row));
69516
+ });
69517
+ return map;
69518
+ }, [lineMetricRowsByLineId]);
69519
+ const getLineCardKpis = React144__namespace.default.useCallback((line) => {
69520
+ if (metricsError) return null;
69521
+ return kpisByLineId.get(line.id) ?? (metricsLoading ? null : defaultKPIs);
69522
+ }, [defaultKPIs, kpisByLineId, metricsError, metricsLoading]);
69523
+ const getAggregateCardKpis = React144__namespace.default.useCallback((cardLines) => {
69524
+ if (metricsError) return null;
69525
+ const rows = cardLines.map((line) => lineMetricRowsByLineId.get(line.id)).filter(Boolean);
69526
+ if (metricsLoading && rows.length === 0) return null;
69527
+ return aggregateKPIsFromLineMetricsRows(rows);
69528
+ }, [lineMetricRowsByLineId, metricsError, metricsLoading]);
69060
69529
  const supervisorLineIds = React144__namespace.default.useMemo(
69061
69530
  () => (leaderboardLines.length > 0 ? leaderboardLines : lines).map((l) => l.id),
69062
69531
  [leaderboardLines, lines]
@@ -69260,6 +69729,20 @@ var KPIsOverviewView = ({
69260
69729
  if (activeTab !== "leaderboard" || timeRange !== "today") return;
69261
69730
  fetchDailyLeaderboard();
69262
69731
  }, [activeTab, timeRange, fetchDailyLeaderboard]);
69732
+ const navigateTodayHierarchy = React144.useCallback((factoryId, factoryAreaId) => {
69733
+ void router$1.push(
69734
+ createKpisOverviewUrl({ factoryId, factoryAreaId }),
69735
+ void 0,
69736
+ { shallow: true }
69737
+ );
69738
+ }, [router$1]);
69739
+ const lineDetailReturnTo = React144__namespace.default.useMemo(() => {
69740
+ if (activeTab !== "today" || !selectedFactoryNode) return void 0;
69741
+ return createKpisOverviewUrl({
69742
+ factoryId: selectedFactoryNode.id,
69743
+ factoryAreaId: selectedFactoryAreaNode?.id
69744
+ });
69745
+ }, [activeTab, selectedFactoryNode, selectedFactoryAreaNode]);
69263
69746
  const formatTopPerformerWeek = (periodStart, periodEnd) => {
69264
69747
  const dateToUse = periodStart ? /* @__PURE__ */ new Date(`${periodStart}T00:00:00`) : /* @__PURE__ */ new Date();
69265
69748
  if (Number.isNaN(dateToUse.getTime())) {
@@ -69346,7 +69829,8 @@ var KPIsOverviewView = ({
69346
69829
  );
69347
69830
  return;
69348
69831
  }
69349
- navigation.navigate(`/kpis/${line.id}`);
69832
+ const returnToQuery = lineDetailReturnTo ? `?returnTo=${encodeURIComponent(lineDetailReturnTo)}` : "";
69833
+ navigation.navigate(`/kpis/${line.id}${returnToQuery}`);
69350
69834
  };
69351
69835
  const handleBackClick = React144.useCallback(() => {
69352
69836
  trackCoreEvent("Back Button Clicked", {
@@ -69415,6 +69899,70 @@ var KPIsOverviewView = ({
69415
69899
  }
69416
69900
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" }) });
69417
69901
  };
69902
+ const renderLineCard = (line) => /* @__PURE__ */ jsxRuntime.jsx(
69903
+ LineCard,
69904
+ {
69905
+ line,
69906
+ kpis: getLineCardKpis(line),
69907
+ isLoading: metricsLoading,
69908
+ error: metricsError,
69909
+ onClick: (kpis) => handleLineClick(line, kpis),
69910
+ supervisorEnabled,
69911
+ supervisorName: supervisorNamesByLineId.get(line.id) || null,
69912
+ supervisors: supervisorsByLineId?.get(line.id)
69913
+ },
69914
+ line.id
69915
+ );
69916
+ const renderGroupCard = ({
69917
+ key,
69918
+ title,
69919
+ subtitle,
69920
+ lines: cardLines,
69921
+ onClick
69922
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
69923
+ KpiGroupCard,
69924
+ {
69925
+ title,
69926
+ subtitle,
69927
+ kpis: getAggregateCardKpis(cardLines),
69928
+ isLoading: metricsLoading,
69929
+ error: metricsError,
69930
+ isUptimeMode: viewType === "machine",
69931
+ onClick
69932
+ },
69933
+ key
69934
+ );
69935
+ const renderTodayCards = () => {
69936
+ if (!kpiLineHierarchy.showFactoryLevel) {
69937
+ return linesForView.map(renderLineCard);
69938
+ }
69939
+ if (selectedFactoryNode && selectedFactoryAreaNode) {
69940
+ return selectedFactoryAreaNode.lines.map(renderLineCard);
69941
+ }
69942
+ if (selectedFactoryNode) {
69943
+ return [
69944
+ ...selectedFactoryNode.areas.map(
69945
+ (area) => renderGroupCard({
69946
+ key: `area-${area.id}`,
69947
+ title: area.areaName,
69948
+ subtitle: `${area.lines.length} ${area.lines.length === 1 ? "line" : "lines"}`,
69949
+ lines: area.lines,
69950
+ onClick: () => navigateTodayHierarchy(selectedFactoryNode.id, area.id)
69951
+ })
69952
+ ),
69953
+ ...selectedFactoryNode.ungroupedLines.map(renderLineCard)
69954
+ ];
69955
+ }
69956
+ return kpiLineHierarchy.factories.map(
69957
+ (factory) => renderGroupCard({
69958
+ key: `factory-${factory.id}`,
69959
+ title: factory.factoryName,
69960
+ subtitle: `${factory.lines.length} ${factory.lines.length === 1 ? "line" : "lines"}`,
69961
+ lines: factory.lines,
69962
+ onClick: () => navigateTodayHierarchy(factory.id)
69963
+ })
69964
+ );
69965
+ };
69418
69966
  if (loading || isShiftConfigLoading) {
69419
69967
  return /* @__PURE__ */ jsxRuntime.jsx(LoadingPage, { message: "Loading production lines..." });
69420
69968
  }
@@ -69847,23 +70395,34 @@ var KPIsOverviewView = ({
69847
70395
  ] })
69848
70396
  ] })
69849
70397
  ] }) }),
69850
- /* @__PURE__ */ jsxRuntime.jsx("main", { className: `flex-1 p-3 sm:p-4 md:p-6 bg-slate-50 ${activeTab === "leaderboard" ? "overflow-hidden flex flex-col" : "overflow-y-auto"}`, children: activeTab === "today" ? (
69851
- /* Line Cards Grid */
69852
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3 sm:gap-4 md:gap-6", children: linesForView.map((line) => /* @__PURE__ */ jsxRuntime.jsx(
69853
- LineCard,
69854
- {
69855
- line,
69856
- kpis: metricsError ? null : kpisByLineId.get(line.id) ?? (metricsLoading ? null : defaultKPIs),
69857
- isLoading: metricsLoading,
69858
- error: metricsError,
69859
- onClick: (kpis) => handleLineClick(line, kpis),
69860
- supervisorEnabled,
69861
- supervisorName: supervisorNamesByLineId.get(line.id) || null,
69862
- supervisors: supervisorsByLineId?.get(line.id)
69863
- },
69864
- line.id
69865
- )) })
69866
- ) : showLeaderboardLoader ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex flex-col items-center justify-center bg-white rounded-2xl border border-gray-100 shadow-sm m-2 sm:m-4", children: /* @__PURE__ */ jsxRuntime.jsx(
70398
+ /* @__PURE__ */ jsxRuntime.jsx("main", { className: `flex-1 p-3 sm:p-4 md:p-6 bg-slate-50 ${activeTab === "leaderboard" ? "overflow-hidden flex flex-col" : "overflow-y-auto"}`, children: activeTab === "today" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 sm:space-y-4", children: [
70399
+ kpiLineHierarchy.showFactoryLevel && selectedFactoryNode && /* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "flex flex-wrap items-center gap-2 text-sm", "aria-label": "KPI hierarchy", children: [
70400
+ /* @__PURE__ */ jsxRuntime.jsx(
70401
+ "button",
70402
+ {
70403
+ type: "button",
70404
+ onClick: () => navigateTodayHierarchy(),
70405
+ className: "font-medium text-gray-500 hover:text-blue-600 transition-colors",
70406
+ children: "Factories"
70407
+ }
70408
+ ),
70409
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-300", children: "/" }),
70410
+ selectedFactoryAreaNode ? /* @__PURE__ */ jsxRuntime.jsx(
70411
+ "button",
70412
+ {
70413
+ type: "button",
70414
+ onClick: () => navigateTodayHierarchy(selectedFactoryNode.id),
70415
+ className: "font-medium text-gray-500 hover:text-blue-600 transition-colors",
70416
+ children: selectedFactoryNode.factoryName
70417
+ }
70418
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-gray-900", children: selectedFactoryNode.factoryName }),
70419
+ selectedFactoryAreaNode && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
70420
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-300", children: "/" }),
70421
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-gray-900", children: selectedFactoryAreaNode.areaName })
70422
+ ] })
70423
+ ] }),
70424
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3 sm:gap-4 md:gap-6", children: renderTodayCards() })
70425
+ ] }) : showLeaderboardLoader ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex flex-col items-center justify-center bg-white rounded-2xl border border-gray-100 shadow-sm m-2 sm:m-4", children: /* @__PURE__ */ jsxRuntime.jsx(
69867
70426
  OptifyeLogoLoader_default,
69868
70427
  {
69869
70428
  size: "lg",
@@ -69910,6 +70469,27 @@ var AnimatedEfficiency = React144.memo(({ value }) => {
69910
70469
  return prevProps.value === nextProps.value;
69911
70470
  });
69912
70471
  AnimatedEfficiency.displayName = "AnimatedEfficiency";
70472
+ var getWorkspaceLeaderboardMetricValue = (workspace) => {
70473
+ if (workspace.monitoring_mode === "output") {
70474
+ return toFiniteNumber(workspace.efficiency);
70475
+ }
70476
+ if (workspace.leaderboard_metric_kind === "recent_flow_shift_average") {
70477
+ return toFiniteNumber(workspace.leaderboard_value);
70478
+ }
70479
+ return toFiniteNumber(workspace.leaderboard_value) ?? toFiniteNumber(workspace.efficiency);
70480
+ };
70481
+ var getWorkspaceDisplayedMetricValue = (workspace) => getWorkspaceLeaderboardMetricValue(workspace);
70482
+ var getWorkspaceLeaderboardMetricLabel = (workspace, defaultLabel) => workspace.monitoring_mode !== "output" && workspace.leaderboard_metric_kind === "recent_flow_shift_average" ? "Avg Flow" : defaultLabel;
70483
+ var renderWorkspaceLeaderboardMetric = (workspace, isAssemblyMode) => {
70484
+ if (isAssemblyMode) {
70485
+ return /* @__PURE__ */ jsxRuntime.jsx(CycleTimeComparison, { workspace });
70486
+ }
70487
+ const displayedMetricValue = getWorkspaceDisplayedMetricValue(workspace);
70488
+ if (displayedMetricValue === null) {
70489
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tabular-nums", children: "--" });
70490
+ }
70491
+ return /* @__PURE__ */ jsxRuntime.jsx(AnimatedEfficiency, { value: displayedMetricValue });
70492
+ };
69913
70493
  var HeaderRibbon = React144.memo(({
69914
70494
  currentDate,
69915
70495
  currentMobileDate,
@@ -69988,13 +70568,13 @@ var MobileWorkspaceCard = React144.memo(({
69988
70568
  ] })
69989
70569
  ] }),
69990
70570
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-right", children: [
69991
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-bold text-gray-900 text-lg flex justify-end", children: isAssemblyMode ? /* @__PURE__ */ jsxRuntime.jsx(CycleTimeComparison, { workspace }) : /* @__PURE__ */ jsxRuntime.jsx(AnimatedEfficiency, { value: workspace.efficiency || 0 }) }),
69992
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500", children: metricLabel })
70571
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-bold text-gray-900 text-lg flex justify-end", children: renderWorkspaceLeaderboardMetric(workspace, isAssemblyMode) }),
70572
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500", children: getWorkspaceLeaderboardMetricLabel(workspace, metricLabel) })
69993
70573
  ] })
69994
70574
  ] })
69995
70575
  }
69996
70576
  ), (prevProps, nextProps) => {
69997
- return prevProps.metricLabel === nextProps.metricLabel && prevProps.isAssemblyMode === nextProps.isAssemblyMode && prevProps.rank === nextProps.rank && prevProps.cardClass === nextProps.cardClass && prevProps.isClickable === nextProps.isClickable && prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.efficiency === nextProps.workspace.efficiency && prevProps.workspace.ideal_cycle_time === nextProps.workspace.ideal_cycle_time && prevProps.workspace.action_count === nextProps.workspace.action_count && prevProps.workspace.action_threshold === nextProps.workspace.action_threshold && prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.displayName === nextProps.workspace.displayName && prevProps.workspace.lineName === nextProps.workspace.lineName;
70577
+ return prevProps.metricLabel === nextProps.metricLabel && prevProps.isAssemblyMode === nextProps.isAssemblyMode && prevProps.rank === nextProps.rank && prevProps.cardClass === nextProps.cardClass && prevProps.isClickable === nextProps.isClickable && prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.leaderboard_value === nextProps.workspace.leaderboard_value && prevProps.workspace.leaderboard_metric_kind === nextProps.workspace.leaderboard_metric_kind && prevProps.workspace.efficiency === nextProps.workspace.efficiency && prevProps.workspace.ideal_cycle_time === nextProps.workspace.ideal_cycle_time && prevProps.workspace.action_count === nextProps.workspace.action_count && prevProps.workspace.action_threshold === nextProps.workspace.action_threshold && prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.displayName === nextProps.workspace.displayName && prevProps.workspace.lineName === nextProps.workspace.lineName;
69998
70578
  });
69999
70579
  MobileWorkspaceCard.displayName = "MobileWorkspaceCard";
70000
70580
  var DesktopWorkspaceRow = React144.memo(({
@@ -70021,11 +70601,11 @@ var DesktopWorkspaceRow = React144.memo(({
70021
70601
  ] }) }),
70022
70602
  /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: workspace.displayName }) }),
70023
70603
  /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: workspace.lineName }) }),
70024
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: `px-3 py-2.5 sm:p-4 text-sm sm:text-base font-medium ${isAssemblyMode ? "" : "whitespace-nowrap"}`, children: isAssemblyMode ? /* @__PURE__ */ jsxRuntime.jsx(CycleTimeComparison, { workspace }) : /* @__PURE__ */ jsxRuntime.jsx(AnimatedEfficiency, { value: workspace.efficiency || 0 }) })
70604
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: `px-3 py-2.5 sm:p-4 text-sm sm:text-base font-medium ${isAssemblyMode ? "" : "whitespace-nowrap"}`, children: isAssemblyMode ? renderWorkspaceLeaderboardMetric(workspace, true) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col", children: renderWorkspaceLeaderboardMetric(workspace, false) }) })
70025
70605
  ]
70026
70606
  }
70027
70607
  ), (prevProps, nextProps) => {
70028
- return prevProps.index === nextProps.index && prevProps.rowClass === nextProps.rowClass && prevProps.isClickable === nextProps.isClickable && prevProps.isAssemblyMode === nextProps.isAssemblyMode && prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.efficiency === nextProps.workspace.efficiency && prevProps.workspace.ideal_cycle_time === nextProps.workspace.ideal_cycle_time && prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.displayName === nextProps.workspace.displayName && prevProps.workspace.lineName === nextProps.workspace.lineName;
70608
+ return prevProps.index === nextProps.index && prevProps.rowClass === nextProps.rowClass && prevProps.isClickable === nextProps.isClickable && prevProps.isAssemblyMode === nextProps.isAssemblyMode && prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.leaderboard_value === nextProps.workspace.leaderboard_value && prevProps.workspace.leaderboard_metric_kind === nextProps.workspace.leaderboard_metric_kind && prevProps.workspace.efficiency === nextProps.workspace.efficiency && prevProps.workspace.ideal_cycle_time === nextProps.workspace.ideal_cycle_time && prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.displayName === nextProps.workspace.displayName && prevProps.workspace.lineName === nextProps.workspace.lineName;
70029
70609
  });
70030
70610
  DesktopWorkspaceRow.displayName = "DesktopWorkspaceRow";
70031
70611
  var LeaderboardDetailView = React144.memo(({
@@ -70124,6 +70704,8 @@ var LeaderboardDetailView = React144.memo(({
70124
70704
  const [monthlyError, setMonthlyError] = React144.useState(null);
70125
70705
  const todayRequestKeyRef = React144.useRef(null);
70126
70706
  const monthlyRequestKeyRef = React144.useRef(null);
70707
+ const monthlyLoadKeyRef = React144.useRef(null);
70708
+ const monthlyLoadPromiseRef = React144.useRef(null);
70127
70709
  const leaderboardUpdateQueuedRef = React144.useRef(false);
70128
70710
  const leaderboardUpdateTimerRef = React144.useRef(null);
70129
70711
  const leaderboardViewTrackedRef = React144.useRef(null);
@@ -70398,6 +70980,9 @@ var LeaderboardDetailView = React144.memo(({
70398
70980
  trend: 0,
70399
70981
  predicted_output: 0,
70400
70982
  efficiency: entry.efficiency || 0,
70983
+ avg_recent_flow: toFiniteNumber(entry.avg_recent_flow),
70984
+ leaderboard_value: toFiniteNumber(entry.leaderboard_value),
70985
+ leaderboard_metric_kind: entry.leaderboard_metric_kind ?? "efficiency",
70401
70986
  action_threshold: entry.total_day_output || 0,
70402
70987
  displayName: entry.workspace_display_name,
70403
70988
  monitoring_mode: entry.monitoring_mode ?? "output"
@@ -70428,7 +71013,10 @@ var LeaderboardDetailView = React144.memo(({
70428
71013
  searchParams.set("monitoring_mode", viewType === "machine" ? "uptime" : "output");
70429
71014
  const data = await fetchBackendJson(
70430
71015
  supabase,
70431
- `/api/dashboard/leaderboard?${searchParams.toString()}`
71016
+ `/api/dashboard/leaderboard?${searchParams.toString()}`,
71017
+ {
71018
+ timeoutMs: params.startDate && params.endDate ? 3e4 : void 0
71019
+ }
70432
71020
  );
70433
71021
  return data.entries || [];
70434
71022
  }, [supabase, entityConfig.companyId, configuredLineIds, viewType]);
@@ -70506,15 +71094,21 @@ var LeaderboardDetailView = React144.memo(({
70506
71094
  setMonthlyLoading(true);
70507
71095
  setMonthlyError(null);
70508
71096
  try {
70509
- const entries = await fetchLeaderboardEntries({
70510
- startDate: normalizedRange.startKey,
70511
- endDate: normalizedRange.endKey,
70512
- shiftId: monthlyShiftId
70513
- });
71097
+ const loadPromise = monthlyLoadPromiseRef.current && monthlyLoadKeyRef.current === requestKey ? monthlyLoadPromiseRef.current : (async () => {
71098
+ const entries = await fetchLeaderboardEntries({
71099
+ startDate: normalizedRange.startKey,
71100
+ endDate: normalizedRange.endKey,
71101
+ shiftId: monthlyShiftId
71102
+ });
71103
+ return mapEntriesToWorkspaces(entries, normalizedRange.endKey, monthlyShiftId);
71104
+ })();
71105
+ monthlyLoadKeyRef.current = requestKey;
71106
+ monthlyLoadPromiseRef.current = loadPromise;
71107
+ const workspaces = await loadPromise;
70514
71108
  if (monthlyRequestKeyRef.current !== requestKey) {
70515
71109
  return;
70516
71110
  }
70517
- setMonthlyEntries(mapEntriesToWorkspaces(entries, normalizedRange.endKey, monthlyShiftId));
71111
+ setMonthlyEntries(workspaces);
70518
71112
  } catch (err) {
70519
71113
  console.error("[LeaderboardDetailView] Error fetching monthly leaderboard:", err);
70520
71114
  if (monthlyRequestKeyRef.current !== requestKey) {
@@ -70523,6 +71117,9 @@ var LeaderboardDetailView = React144.memo(({
70523
71117
  setMonthlyError({ message: err.message, code: err.code || "FETCH_ERROR" });
70524
71118
  setMonthlyEntries([]);
70525
71119
  } finally {
71120
+ if (monthlyLoadKeyRef.current === requestKey && monthlyLoadPromiseRef.current) {
71121
+ monthlyLoadPromiseRef.current = null;
71122
+ }
70526
71123
  if (monthlyRequestKeyRef.current === requestKey) {
70527
71124
  setMonthlyLoading(false);
70528
71125
  }
@@ -70535,6 +71132,46 @@ var LeaderboardDetailView = React144.memo(({
70535
71132
  monthlyShiftId,
70536
71133
  lineKey
70537
71134
  ]);
71135
+ React144.useEffect(() => {
71136
+ if (activeTab !== "today") {
71137
+ return;
71138
+ }
71139
+ const requestKey = `${normalizedRange.startKey}|${normalizedRange.endKey}|${monthlyShiftId}|${lineKey}|${viewType}`;
71140
+ let cancelled = false;
71141
+ const loadPromise = monthlyLoadPromiseRef.current && monthlyLoadKeyRef.current === requestKey ? monthlyLoadPromiseRef.current : (async () => {
71142
+ const entries = await fetchLeaderboardEntries({
71143
+ startDate: normalizedRange.startKey,
71144
+ endDate: normalizedRange.endKey,
71145
+ shiftId: monthlyShiftId
71146
+ });
71147
+ return mapEntriesToWorkspaces(entries, normalizedRange.endKey, monthlyShiftId);
71148
+ })();
71149
+ monthlyLoadKeyRef.current = requestKey;
71150
+ monthlyLoadPromiseRef.current = loadPromise;
71151
+ loadPromise.then((workspaces) => {
71152
+ if (cancelled) {
71153
+ return;
71154
+ }
71155
+ setMonthlyEntries(workspaces);
71156
+ }).catch(() => {
71157
+ }).finally(() => {
71158
+ if (!cancelled && monthlyLoadKeyRef.current === requestKey && monthlyLoadPromiseRef.current === loadPromise) {
71159
+ monthlyLoadPromiseRef.current = null;
71160
+ }
71161
+ });
71162
+ return () => {
71163
+ cancelled = true;
71164
+ };
71165
+ }, [
71166
+ activeTab,
71167
+ fetchLeaderboardEntries,
71168
+ mapEntriesToWorkspaces,
71169
+ normalizedRange.endKey,
71170
+ normalizedRange.startKey,
71171
+ monthlyShiftId,
71172
+ lineKey,
71173
+ viewType
71174
+ ]);
70538
71175
  React144.useEffect(() => {
70539
71176
  if (activeTab === "today") {
70540
71177
  fetchTodayLeaderboard();
@@ -70669,6 +71306,9 @@ var LeaderboardDetailView = React144.memo(({
70669
71306
  total_workspaces: workspacesLengthRef.current,
70670
71307
  // Use ref instead of state to avoid dependency
70671
71308
  metric_context: viewType === "machine" ? "machine" : outputCategory,
71309
+ leaderboard_value: getWorkspaceLeaderboardMetricValue(workspace),
71310
+ leaderboard_metric_kind: workspace.leaderboard_metric_kind ?? "efficiency",
71311
+ avg_recent_flow: workspace.avg_recent_flow ?? null,
70672
71312
  efficiency: workspace.efficiency,
70673
71313
  action_count: workspace.action_count,
70674
71314
  action_threshold: workspace.action_threshold,
@@ -70749,9 +71389,12 @@ var LeaderboardDetailView = React144.memo(({
70749
71389
  if (ratioB === null) return -1;
70750
71390
  return sortAscending ? ratioA - ratioB : ratioB - ratioA;
70751
71391
  }
70752
- const effA = a.efficiency || 0;
70753
- const effB = b.efficiency || 0;
70754
- return sortAscending ? effA - effB : effB - effA;
71392
+ const metricA = getWorkspaceLeaderboardMetricValue(a);
71393
+ const metricB = getWorkspaceLeaderboardMetricValue(b);
71394
+ if (metricA === null && metricB === null) return 0;
71395
+ if (metricA === null) return 1;
71396
+ if (metricB === null) return -1;
71397
+ return sortAscending ? metricA - metricB : metricB - metricA;
70755
71398
  });
70756
71399
  }, [workspaceDisplayData, sortAscending, selectedLineFilter, selectedShiftFilter, activeTab, viewType, isAssemblyMode]);
70757
71400
  const loading = activeTab === "today" ? todayLoading : monthlyLoading;
@@ -70780,6 +71423,8 @@ var LeaderboardDetailView = React144.memo(({
70780
71423
  workspace_count: sortedWorkspaces.length,
70781
71424
  top_workspace_id: topWorkspace?.workspace_uuid ?? null,
70782
71425
  top_workspace_name: topWorkspace?.workspace_name ?? null,
71426
+ top_leaderboard_value: topWorkspace ? getWorkspaceLeaderboardMetricValue(topWorkspace) : null,
71427
+ top_leaderboard_metric_kind: topWorkspace?.leaderboard_metric_kind ?? null,
70783
71428
  top_efficiency: topWorkspace?.efficiency ?? null,
70784
71429
  top_avg_cycle_time: topWorkspace?.avg_cycle_time ?? null,
70785
71430
  top_ideal_cycle_time: topWorkspace?.ideal_cycle_time ?? null,
@@ -75925,7 +76570,11 @@ var WorkspaceDetailView = ({
75925
76570
  workspace,
75926
76571
  legend: efficiencyLegend,
75927
76572
  layout: "stack",
75928
- idleTimeData: idleTimeVlmEnabled ? idleTimeData : void 0
76573
+ idleTimeData: idleTimeVlmEnabled ? idleTimeData : void 0,
76574
+ skuAware: isSkuAware,
76575
+ skuBreakdown: isSkuAware ? realSkuBreakdown : void 0,
76576
+ activeSkuId,
76577
+ liveSkuId: isHistoricView ? null : liveSkuId
75929
76578
  }
75930
76579
  ) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
75931
76580
  WorkspaceMetricCards,
@@ -75935,7 +76584,8 @@ var WorkspaceDetailView = ({
75935
76584
  className: "flex-1",
75936
76585
  skuAware: isSkuAware,
75937
76586
  skuBreakdown: isSkuAware ? realSkuBreakdown : void 0,
75938
- activeSkuId
76587
+ activeSkuId,
76588
+ liveSkuId: isHistoricView ? null : liveSkuId
75939
76589
  }
75940
76590
  ) })
75941
76591
  ] }),
@@ -76078,7 +76728,11 @@ var WorkspaceDetailView = ({
76078
76728
  legend: efficiencyLegend,
76079
76729
  layout: "grid",
76080
76730
  className: desktopBottomSectionClass,
76081
- idleTimeData: idleTimeVlmEnabled ? idleTimeData : void 0
76731
+ idleTimeData: idleTimeVlmEnabled ? idleTimeData : void 0,
76732
+ skuAware: isSkuAware,
76733
+ skuBreakdown: isSkuAware ? realSkuBreakdown : void 0,
76734
+ activeSkuId,
76735
+ liveSkuId: isHistoricView ? null : liveSkuId
76082
76736
  }
76083
76737
  ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx("flex min-h-0", desktopBottomSectionClass), children: /* @__PURE__ */ jsxRuntime.jsx(
76084
76738
  WorkspaceMetricCards,
@@ -76088,7 +76742,8 @@ var WorkspaceDetailView = ({
76088
76742
  className: "flex-1",
76089
76743
  skuAware: isSkuAware,
76090
76744
  skuBreakdown: isSkuAware ? realSkuBreakdown : void 0,
76091
- activeSkuId
76745
+ activeSkuId,
76746
+ liveSkuId: isHistoricView ? null : liveSkuId
76092
76747
  }
76093
76748
  ) })
76094
76749
  ] })
@@ -85376,6 +86031,7 @@ exports.authRateLimitService = authRateLimitService;
85376
86031
  exports.awardsService = awardsService;
85377
86032
  exports.buildDateKey = buildDateKey;
85378
86033
  exports.buildKPIsFromLineMetricsRow = buildKPIsFromLineMetricsRow;
86034
+ exports.buildKpiLineHierarchy = buildKpiLineHierarchy;
85379
86035
  exports.buildLineSkuBreakdown = buildLineSkuBreakdown;
85380
86036
  exports.buildShiftGroupsKey = buildShiftGroupsKey;
85381
86037
  exports.canRoleAccessDashboardPath = canRoleAccessDashboardPath;