@optifye/dashboard-core 6.12.4 → 6.12.6

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
@@ -4586,6 +4586,7 @@ var buildLineSkuBreakdown = (rows, skuCatalog) => {
4586
4586
  avg_efficiency: safeFloat(row.avg_efficiency),
4587
4587
  line_threshold: typeof row.line_threshold === "number" && Number.isFinite(row.line_threshold) ? row.line_threshold : null,
4588
4588
  line_threshold_recalculated: typeof row.line_threshold_recalculated === "number" && Number.isFinite(row.line_threshold_recalculated) ? row.line_threshold_recalculated : null,
4589
+ output_target_recalculated: typeof row.output_target_recalculated === "number" && Number.isFinite(row.output_target_recalculated) ? row.output_target_recalculated : null,
4589
4590
  total_workspaces: safeInt(row.total_workspaces),
4590
4591
  underperforming_workspaces: safeInt(row.underperforming_workspaces),
4591
4592
  underperforming_workspace_names: Array.isArray(row.underperforming_workspace_names) ? row.underperforming_workspace_names : [],
@@ -5236,7 +5237,7 @@ var dashboardService = {
5236
5237
  },
5237
5238
  outputProgress: {
5238
5239
  current: lineInfo.metrics.current_output,
5239
- target: lineInfo.metrics.line_threshold,
5240
+ target: lineInfo.metrics.output_target_recalculated ?? lineInfo.metrics.line_threshold,
5240
5241
  idealOutput: lineInfo.metrics.ideal_output,
5241
5242
  change: 0
5242
5243
  },
@@ -21901,6 +21902,24 @@ var getConfigurableShortWorkspaceDisplayName = (workspaceId, workspaceConfig, li
21901
21902
  return fullName;
21902
21903
  };
21903
21904
 
21905
+ // src/lib/utils/efficiencyValidity.ts
21906
+ var MIN_VALID_OUTPUT_EFFICIENCY = 5;
21907
+ var MIN_VALID_UPTIME_EFFICIENCY = 1;
21908
+ var normalizeMonitoringMode = (mode) => String(mode ?? "").trim().toLowerCase() === "uptime" ? "uptime" : "output";
21909
+ var toFiniteNumberOrNull = (value) => {
21910
+ if (typeof value === "number" && Number.isFinite(value)) return value;
21911
+ if (typeof value === "string" && value.trim() !== "") {
21912
+ const parsed = Number(value);
21913
+ return Number.isFinite(parsed) ? parsed : null;
21914
+ }
21915
+ return null;
21916
+ };
21917
+ var isValidAggregateEfficiency = (monitoringMode, efficiency) => {
21918
+ const value = toFiniteNumberOrNull(efficiency);
21919
+ if (value === null) return false;
21920
+ return normalizeMonitoringMode(monitoringMode) === "uptime" ? value >= MIN_VALID_UPTIME_EFFICIENCY : value >= MIN_VALID_OUTPUT_EFFICIENCY;
21921
+ };
21922
+
21904
21923
  // src/lib/utils/kpis.ts
21905
21924
  var toNumber = (value) => {
21906
21925
  if (typeof value === "number" && Number.isFinite(value)) return value;
@@ -21924,7 +21943,7 @@ var buildKPIsFromLineMetricsRow = (row) => {
21924
21943
  const avgEfficiency = toNumber(row.avg_efficiency);
21925
21944
  const avgCycleTime = toNumber(row.avg_cycle_time);
21926
21945
  const currentOutput = toNumber(row.current_output);
21927
- const lineThreshold = toNumber(row.line_threshold);
21946
+ const lineThreshold = row.output_target_recalculated !== void 0 && row.output_target_recalculated !== null ? toNumber(row.output_target_recalculated) : toNumber(row.line_threshold);
21928
21947
  const idealOutput = toNumber(row.ideal_output) || lineThreshold || 0;
21929
21948
  const underperformingWorkspaces = toNumber(row.underperforming_workspaces);
21930
21949
  const totalWorkspaces = toNumber(row.total_workspaces);
@@ -21956,10 +21975,15 @@ var buildKPIsFromLineMetricsRow = (row) => {
21956
21975
  };
21957
21976
  var aggregateKPIsFromLineMetricsRows = (rows) => {
21958
21977
  if (!rows || rows.length === 0) return createDefaultKPIs();
21959
- const eligibleRows = rows.filter((row) => toNumber(row?.avg_efficiency) >= 5);
21978
+ const eligibleRows = rows.filter(
21979
+ (row) => isValidAggregateEfficiency(row?.monitoring_mode ?? row?.monitoringMode, row?.avg_efficiency)
21980
+ );
21960
21981
  if (eligibleRows.length === 0) return createDefaultKPIs();
21961
21982
  const currentOutputSum = eligibleRows.reduce((sum, row) => sum + toNumber(row.current_output), 0);
21962
- const lineThresholdSum = eligibleRows.reduce((sum, row) => sum + toNumber(row.line_threshold), 0);
21983
+ const lineThresholdSum = eligibleRows.reduce(
21984
+ (sum, row) => sum + (row?.output_target_recalculated !== void 0 && row?.output_target_recalculated !== null ? toNumber(row.output_target_recalculated) : toNumber(row.line_threshold)),
21985
+ 0
21986
+ );
21963
21987
  const idealOutputSum = eligibleRows.reduce(
21964
21988
  (sum, row) => sum + (toNumber(row.ideal_output) || toNumber(row.line_threshold)),
21965
21989
  0
@@ -37281,8 +37305,8 @@ var HourlyOutputChart = React144__namespace.default.memo(
37281
37305
  HourlyOutputChart.displayName = "HourlyOutputChart";
37282
37306
 
37283
37307
  // src/components/dashboard/grid/videoGridMetricUtils.ts
37308
+ var VIDEO_GRID_LEGEND_LABEL = "Real-Time efficiency";
37284
37309
  var MAP_GRID_LEGEND_LABEL = "Efficiency";
37285
- var MIXED_VIDEO_GRID_LEGEND_LABEL = "Live Efficiency";
37286
37310
  var isFiniteNumber2 = (value) => typeof value === "number" && Number.isFinite(value);
37287
37311
  var isVideoGridRecentFlowEnabled = (workspace) => isRecentFlowVideoGridMetricMode(
37288
37312
  workspace.video_grid_metric_mode,
@@ -37294,7 +37318,7 @@ var isVideoGridWipGated = (workspace) => isWipGatedVideoGridMetricMode(
37294
37318
  );
37295
37319
  var hasVideoGridRecentFlow = (workspace) => isVideoGridRecentFlowEnabled(workspace) && isFiniteNumber2(workspace.recent_flow_percent);
37296
37320
  var isVideoGridRecentFlowUnavailable = (workspace) => isVideoGridRecentFlowEnabled(workspace) && !hasVideoGridRecentFlow(workspace);
37297
- var getVideoGridMetricValue = (workspace) => {
37321
+ var getRawVideoGridMetricValue = (workspace) => {
37298
37322
  const recentFlowPercent = workspace.recent_flow_percent;
37299
37323
  if (hasVideoGridRecentFlow(workspace) && isFiniteNumber2(recentFlowPercent)) {
37300
37324
  return recentFlowPercent;
@@ -37306,7 +37330,7 @@ var getVideoGridMetricValue = (workspace) => {
37306
37330
  };
37307
37331
  var hasIncomingWipMapping = (workspace) => Boolean(workspace.incoming_wip_buffer_name);
37308
37332
  var getVideoGridBaseColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37309
- const metricValue = getVideoGridMetricValue(workspace);
37333
+ const metricValue = getRawVideoGridMetricValue(workspace);
37310
37334
  if (!isFiniteNumber2(metricValue)) {
37311
37335
  return "neutral";
37312
37336
  }
@@ -37330,6 +37354,25 @@ var isLowWipGreenOverride = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37330
37354
  }
37331
37355
  return isFiniteNumber2(workspace.incoming_wip_current) && workspace.incoming_wip_current <= 1;
37332
37356
  };
37357
+ var isHighEfficiencyRedFlowOverride = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37358
+ if (workspace.scheduled_break_active === true) {
37359
+ return false;
37360
+ }
37361
+ if (workspace.recent_flow_forced_zero_after_shift === true) {
37362
+ return false;
37363
+ }
37364
+ if (!hasVideoGridRecentFlow(workspace) || !isVideoGridWipGated(workspace)) {
37365
+ return false;
37366
+ }
37367
+ if (isLowWipGreenOverride(workspace, legend)) {
37368
+ return false;
37369
+ }
37370
+ if (getVideoGridBaseColorState(workspace, legend) !== "red") {
37371
+ return false;
37372
+ }
37373
+ return isFiniteNumber2(workspace.efficiency) && workspace.efficiency > 100;
37374
+ };
37375
+ var getVideoGridMetricValue = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => isHighEfficiencyRedFlowOverride(workspace, legend) ? workspace.efficiency : getRawVideoGridMetricValue(workspace);
37333
37376
  var toMinuteBucket = (minuteBucket) => Number.isFinite(minuteBucket) ? Math.floor(minuteBucket) : Math.floor(Date.now() / 6e4);
37334
37377
  var getEffectiveFlowMinuteBucket = (workspace) => {
37335
37378
  const effectiveAt = workspace.recent_flow_effective_end_at;
@@ -37355,7 +37398,7 @@ var getSyntheticLowWipDisplayValue = (workspace, minuteBucket) => {
37355
37398
  const offset = (hashWorkspaceKey(workspace) % 11 + bucket % 11 + 11) % 11;
37356
37399
  return 100 + offset;
37357
37400
  };
37358
- var getVideoGridDisplayValue = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND, minuteBucket) => isLowWipGreenOverride(workspace, legend) ? getSyntheticLowWipDisplayValue(workspace, minuteBucket) : getVideoGridMetricValue(workspace);
37401
+ var getVideoGridDisplayValue = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND, minuteBucket) => isLowWipGreenOverride(workspace, legend) ? getSyntheticLowWipDisplayValue(workspace, minuteBucket) : getVideoGridMetricValue(workspace, legend);
37359
37402
  var getVideoGridColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37360
37403
  const baseColor = getVideoGridBaseColorState(workspace, legend);
37361
37404
  if (!hasVideoGridRecentFlow(workspace)) {
@@ -37367,15 +37410,18 @@ var getVideoGridColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) =>
37367
37410
  if (baseColor !== "red") {
37368
37411
  return baseColor;
37369
37412
  }
37413
+ if (isLowWipGreenOverride(workspace, legend)) {
37414
+ return "green";
37415
+ }
37416
+ if (isHighEfficiencyRedFlowOverride(workspace, legend)) {
37417
+ return getEfficiencyColor(workspace.efficiency, legend);
37418
+ }
37370
37419
  if (!hasIncomingWipMapping(workspace)) {
37371
37420
  return baseColor;
37372
37421
  }
37373
37422
  if (!isFiniteNumber2(workspace.incoming_wip_current)) {
37374
37423
  return "neutral";
37375
37424
  }
37376
- if (isLowWipGreenOverride(workspace, legend)) {
37377
- return "green";
37378
- }
37379
37425
  return baseColor;
37380
37426
  };
37381
37427
  var getVideoGridLegendLabel = (workspaces) => {
@@ -37383,21 +37429,7 @@ var getVideoGridLegendLabel = (workspaces) => {
37383
37429
  if (visibleWorkspaces.length === 0) {
37384
37430
  return MAP_GRID_LEGEND_LABEL;
37385
37431
  }
37386
- const recentFlowEnabledCount = visibleWorkspaces.filter(isVideoGridRecentFlowEnabled).length;
37387
- if (recentFlowEnabledCount === 0) {
37388
- return MAP_GRID_LEGEND_LABEL;
37389
- }
37390
- const recentFlowWindows = new Set(
37391
- visibleWorkspaces.filter(isVideoGridRecentFlowEnabled).map((workspace) => workspace.recent_flow_window_minutes ?? 7).filter((value) => typeof value === "number" && Number.isFinite(value))
37392
- );
37393
- if (recentFlowEnabledCount === visibleWorkspaces.length) {
37394
- if (recentFlowWindows.size === 1) {
37395
- const [windowMinutes] = Array.from(recentFlowWindows);
37396
- return `${windowMinutes} Minute Efficiency`;
37397
- }
37398
- return MIXED_VIDEO_GRID_LEGEND_LABEL;
37399
- }
37400
- return MIXED_VIDEO_GRID_LEGEND_LABEL;
37432
+ return visibleWorkspaces.some(isVideoGridRecentFlowEnabled) ? VIDEO_GRID_LEGEND_LABEL : MAP_GRID_LEGEND_LABEL;
37401
37433
  };
37402
37434
  function getTrendArrowAndColor(trend) {
37403
37435
  if (trend > 0) {
@@ -37440,14 +37472,15 @@ var VideoCard = React144__namespace.default.memo(({
37440
37472
  const showOffline = Boolean(isStreamStale);
37441
37473
  const lastSeenText = lastSeenLabel || "Unknown";
37442
37474
  const workspaceDisplayName = displayName || workspace.displayName || workspace.workspace_name;
37443
- const videoGridMetricValue = getVideoGridMetricValue(workspace);
37475
+ const videoGridMetricValue = getVideoGridMetricValue(workspace, effectiveLegend);
37444
37476
  const videoGridDisplayValue = getVideoGridDisplayValue(workspace, effectiveLegend, displayMinuteBucket);
37445
37477
  const videoGridColorState = getVideoGridColorState(workspace, effectiveLegend);
37446
37478
  const isRecentFlowCard = isVideoGridRecentFlowEnabled(workspace);
37479
+ const isHighEfficiencyOverride = isHighEfficiencyRedFlowOverride(workspace, effectiveLegend);
37447
37480
  const hasDisplayMetric = typeof videoGridDisplayValue === "number" && Number.isFinite(videoGridDisplayValue);
37448
37481
  const hasBarMetric = typeof videoGridMetricValue === "number" && Number.isFinite(videoGridMetricValue);
37449
37482
  const shouldRenderMetricBadge = hasDisplayMetric;
37450
- const badgeTitle = hasVideoGridRecentFlow(workspace) ? `Flow ${Math.round(videoGridDisplayValue ?? 0)}%` : isRecentFlowCard ? "Flow unavailable" : `Efficiency ${Math.round(videoGridDisplayValue ?? 0)}%`;
37483
+ const badgeTitle = isHighEfficiencyOverride ? `Efficiency ${Math.round(videoGridDisplayValue ?? 0)}%` : hasVideoGridRecentFlow(workspace) ? `Flow ${Math.round(videoGridDisplayValue ?? 0)}%` : isRecentFlowCard ? "Flow unavailable" : `Efficiency ${Math.round(videoGridDisplayValue ?? 0)}%`;
37451
37484
  const badgeLabel = `${Math.round(videoGridDisplayValue ?? 0)}%`;
37452
37485
  const efficiencyOverlayClass = videoGridColorState === "green" ? "bg-[#00D654]/25" : videoGridColorState === "yellow" ? "bg-[#FFD700]/30" : videoGridColorState === "red" ? "bg-[#FF2D0A]/30" : "bg-transparent";
37453
37486
  const efficiencyBarClass = videoGridColorState === "green" ? "bg-[#00AB45]" : videoGridColorState === "yellow" ? "bg-[#FFB020]" : videoGridColorState === "red" ? "bg-[#E34329]" : "bg-gray-500/70";
@@ -43284,6 +43317,21 @@ var parseCycleTime = (value) => {
43284
43317
  var extractCycleTimeSeconds = (clip) => {
43285
43318
  return parseCycleTime(clip?.cycleTimeSeconds) ?? parseCycleTime(clip?.cycle_time_seconds) ?? parseCycleTime(clip?.duration) ?? parseCycleTime(clip?.original_task_metadata?.cycle_time) ?? null;
43286
43319
  };
43320
+ var formatDurationLabel = (seconds) => {
43321
+ if (typeof seconds !== "number" || !Number.isFinite(seconds) || seconds <= 0) {
43322
+ return null;
43323
+ }
43324
+ const roundedSeconds = Math.round(seconds);
43325
+ if (roundedSeconds < 60) {
43326
+ return `${roundedSeconds}s`;
43327
+ }
43328
+ const minutes = Math.floor(roundedSeconds / 60);
43329
+ const remainingSeconds = roundedSeconds % 60;
43330
+ if (minutes < 10) {
43331
+ return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
43332
+ }
43333
+ return `${Math.round(roundedSeconds / 60)} min`;
43334
+ };
43287
43335
  var getSeverityIcon = (severity, categoryId, cycleTimeSeconds, targetCycleTime, clipId) => {
43288
43336
  if (categoryId === "idle_time" || categoryId === "low_value" || categoryId === "longest-idles") {
43289
43337
  return null;
@@ -43359,7 +43407,9 @@ var FileManagerFilters = ({
43359
43407
  idleTimeVlmEnabled = false,
43360
43408
  showPercentileCycleFilters = true,
43361
43409
  prefetchedClipMetadata,
43362
- activeCategoryLoading
43410
+ activeCategoryLoading,
43411
+ idleClipSort = "latest",
43412
+ onIdleClipSortChange
43363
43413
  }) => {
43364
43414
  const [expandedNodes, setExpandedNodes] = React144.useState(/* @__PURE__ */ new Set());
43365
43415
  const [startTime, setStartTime] = React144.useState("");
@@ -43382,6 +43432,7 @@ var FileManagerFilters = ({
43382
43432
  const [localClipClassifications, setLocalClipClassifications] = React144.useState({});
43383
43433
  const clipMetadataRef = React144.useRef({});
43384
43434
  const inFlightMetadataRequestsRef = React144.useRef(/* @__PURE__ */ new Set());
43435
+ const previousIdleClipSortRef = React144.useRef(idleClipSort);
43385
43436
  const mergedClipClassifications = React144.useMemo(() => ({
43386
43437
  ...clipClassifications || {},
43387
43438
  ...localClipClassifications
@@ -43389,6 +43440,36 @@ var FileManagerFilters = ({
43389
43440
  React144.useEffect(() => {
43390
43441
  clipMetadataRef.current = clipMetadata;
43391
43442
  }, [clipMetadata]);
43443
+ React144.useEffect(() => {
43444
+ if (previousIdleClipSortRef.current === idleClipSort) {
43445
+ return;
43446
+ }
43447
+ previousIdleClipSortRef.current = idleClipSort;
43448
+ setClipMetadata((prev) => {
43449
+ if (!prev.idle_time) {
43450
+ return prev;
43451
+ }
43452
+ const next = { ...prev };
43453
+ delete next.idle_time;
43454
+ return next;
43455
+ });
43456
+ setCategoryPages((prev) => {
43457
+ if (prev.idle_time === void 0) {
43458
+ return prev;
43459
+ }
43460
+ const next = { ...prev };
43461
+ delete next.idle_time;
43462
+ return next;
43463
+ });
43464
+ setCategoryHasMore((prev) => {
43465
+ if (prev.idle_time === void 0) {
43466
+ return prev;
43467
+ }
43468
+ const next = { ...prev };
43469
+ delete next.idle_time;
43470
+ return next;
43471
+ });
43472
+ }, [idleClipSort]);
43392
43473
  const isCategoryExternallyManaged = React144.useCallback((categoryId) => {
43393
43474
  if (!categoryId) {
43394
43475
  return false;
@@ -43547,6 +43628,7 @@ var FileManagerFilters = ({
43547
43628
  return null;
43548
43629
  }
43549
43630
  }, [supabase]);
43631
+ const getMetadataLoadingKey = React144.useCallback((categoryId, page) => `${categoryId}-${page}-${categoryId === "idle_time" ? idleClipSort : "latest"}`, [idleClipSort]);
43550
43632
  const fetchClipMetadataPage = React144.useCallback(async (categoryId, page = 1) => {
43551
43633
  if (!workspaceId || !date || shift === void 0) {
43552
43634
  throw new Error("Missing required params for clip metadata fetch");
@@ -43566,7 +43648,8 @@ var FileManagerFilters = ({
43566
43648
  limit: CLIP_METADATA_PAGE_SIZE,
43567
43649
  knownTotal: typeof counts?.[categoryId] === "number" ? counts[categoryId] : null,
43568
43650
  snapshotDateTime,
43569
- snapshotClipId
43651
+ snapshotClipId,
43652
+ sort: categoryId === "idle_time" ? idleClipSort : "latest"
43570
43653
  }),
43571
43654
  redirectReason: "session_expired"
43572
43655
  });
@@ -43574,7 +43657,7 @@ var FileManagerFilters = ({
43574
43657
  throw new Error(`API error: ${response.status}`);
43575
43658
  }
43576
43659
  return response.json();
43577
- }, [workspaceId, date, shift, counts, snapshotDateTime, snapshotClipId, supabase]);
43660
+ }, [workspaceId, date, shift, counts, snapshotDateTime, snapshotClipId, idleClipSort, supabase]);
43578
43661
  const seedIdleClassifications = React144.useCallback(async (clips) => {
43579
43662
  if (!idleTimeVlmEnabled || clips.length === 0) {
43580
43663
  return;
@@ -43630,7 +43713,7 @@ var FileManagerFilters = ({
43630
43713
  console.warn("[FileManager] Missing required params for clip metadata fetch");
43631
43714
  return;
43632
43715
  }
43633
- const loadingKey = `${categoryId}-${page}`;
43716
+ const loadingKey = getMetadataLoadingKey(categoryId, page);
43634
43717
  if (inFlightMetadataRequestsRef.current.has(loadingKey)) {
43635
43718
  return;
43636
43719
  }
@@ -43658,7 +43741,7 @@ var FileManagerFilters = ({
43658
43741
  return newSet;
43659
43742
  });
43660
43743
  }
43661
- }, [workspaceId, date, shift, fetchClipMetadataPage, idleTimeVlmEnabled, seedIdleClassifications]);
43744
+ }, [workspaceId, date, shift, fetchClipMetadataPage, idleTimeVlmEnabled, seedIdleClassifications, getMetadataLoadingKey]);
43662
43745
  const ensureAllIdleTimeClipMetadataLoaded = React144.useCallback(async () => {
43663
43746
  if (!workspaceId || !date || shift === void 0) {
43664
43747
  return;
@@ -44032,15 +44115,17 @@ var FileManagerFilters = ({
44032
44115
  const colorClasses = getColorClasses(category.color);
44033
44116
  const clipNodes = filteredClips.map((clip, index) => {
44034
44117
  const cycleTime = extractCycleTimeSeconds(clip);
44118
+ const idleDuration = category.id === "idle_time" ? clip.idle_duration_seconds ?? clip.duration : null;
44119
+ const idleDurationLabel = formatDurationLabel(idleDuration);
44035
44120
  const baseTimeLabel = formatClipExplorerTimeLabel({
44036
44121
  categoryId: category.id,
44037
44122
  clipTimestamp: clip.clip_timestamp,
44038
44123
  timezone,
44039
- durationSeconds: clip.duration,
44124
+ durationSeconds: idleDuration ?? clip.duration,
44040
44125
  idleStartTime: clip.idle_start_time,
44041
44126
  idleEndTime: clip.idle_end_time
44042
44127
  });
44043
- const displayLabel = `${baseTimeLabel}${clip.duration && category.id !== "idle_time" && category.id !== "low_value" ? ` - (${clip.duration.toFixed(1)}s)` : ""}`;
44128
+ const displayLabel = `${baseTimeLabel}${idleDurationLabel && category.id === "idle_time" ? ` - (${idleDurationLabel})` : ""}${clip.duration && category.id !== "idle_time" && category.id !== "low_value" ? ` - (${clip.duration.toFixed(1)}s)` : ""}`;
44044
44129
  return {
44045
44130
  id: clip.id,
44046
44131
  label: displayLabel,
@@ -44054,7 +44139,7 @@ var FileManagerFilters = ({
44054
44139
  clipPosition: index + 1,
44055
44140
  // Store 1-based position
44056
44141
  cycleTimeSeconds: cycleTime,
44057
- duration: clip.duration,
44142
+ duration: idleDuration ?? clip.duration,
44058
44143
  // Store duration for custom badge rendering
44059
44144
  cycleItemCount: clip.cycle_item_count ?? null
44060
44145
  };
@@ -44376,11 +44461,11 @@ var FileManagerFilters = ({
44376
44461
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
44377
44462
  "Loading clips..."
44378
44463
  ] }) }),
44379
- 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: [
44464
+ 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: [
44380
44465
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-spin mr-2 h-4 w-4 border-2 border-slate-300 border-t-blue-500 rounded-full" }),
44381
44466
  "Loading more clips..."
44382
44467
  ] }) }),
44383
- categoryHasMore[node.id] && !loadingCategories.has(`${node.id}-${(categoryPages[node.id] || 0) + 1}`) && /* @__PURE__ */ jsxRuntime.jsxs(
44468
+ categoryHasMore[node.id] && !loadingCategories.has(getMetadataLoadingKey(node.id, (categoryPages[node.id] || 0) + 1)) && /* @__PURE__ */ jsxRuntime.jsxs(
44384
44469
  "button",
44385
44470
  {
44386
44471
  onClick: (e) => {
@@ -44407,6 +44492,18 @@ var FileManagerFilters = ({
44407
44492
  /* @__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" }) })
44408
44493
  ] }),
44409
44494
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [
44495
+ activeFilter === "idle_time" && /* @__PURE__ */ jsxRuntime.jsx(
44496
+ "button",
44497
+ {
44498
+ onClick: () => {
44499
+ onIdleClipSortChange?.(idleClipSort === "latest" ? "idle_duration_desc" : "latest");
44500
+ },
44501
+ 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"}`,
44502
+ title: idleClipSort === "idle_duration_desc" ? "Sort by newest first" : "Sort by longest idle first",
44503
+ "aria-label": idleClipSort === "idle_duration_desc" ? "Sort idle clips by newest first" : "Sort idle clips by longest idle first",
44504
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownWideNarrow, { className: "h-5 w-5" })
44505
+ }
44506
+ ),
44410
44507
  activeFilter === "idle_time" && idleTimeVlmEnabled && /* @__PURE__ */ jsxRuntime.jsx(
44411
44508
  "button",
44412
44509
  {
@@ -44427,8 +44524,8 @@ var FileManagerFilters = ({
44427
44524
  )
44428
44525
  ] })
44429
44526
  ] }),
44430
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 mt-3", children: [
44431
- 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: [
44527
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [
44528
+ 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: [
44432
44529
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
44433
44530
  "Time: ",
44434
44531
  getDisplayValue(startTime),
@@ -44444,13 +44541,13 @@ var FileManagerFilters = ({
44444
44541
  setEndTime("");
44445
44542
  setIsTimeFilterActive(false);
44446
44543
  },
44447
- className: "ml-2 hover:bg-blue-100 rounded p-0.5 transition-colors",
44544
+ className: "rounded-full p-0.5 transition-colors hover:bg-blue-100",
44448
44545
  title: "Clear time filter",
44449
44546
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3.5 w-3.5" })
44450
44547
  }
44451
44548
  )
44452
44549
  ] }),
44453
- 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: [
44550
+ 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: [
44454
44551
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
44455
44552
  "Reason: ",
44456
44553
  selectedIdleReasonOption?.displayName || idleLabelFilter.replace(/_/g, " ")
@@ -44462,11 +44559,27 @@ var FileManagerFilters = ({
44462
44559
  e.stopPropagation();
44463
44560
  setIdleLabelFilter(null);
44464
44561
  },
44465
- className: "ml-2 hover:bg-purple-100 rounded p-0.5 transition-colors",
44562
+ className: "rounded-full p-0.5 transition-colors hover:bg-purple-100",
44466
44563
  title: "Clear label filter",
44467
44564
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3.5 w-3.5" })
44468
44565
  }
44469
44566
  )
44567
+ ] }),
44568
+ 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: [
44569
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownWideNarrow, { className: "h-3.5 w-3.5" }),
44570
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Longest idle first" }),
44571
+ /* @__PURE__ */ jsxRuntime.jsx(
44572
+ "button",
44573
+ {
44574
+ onClick: (e) => {
44575
+ e.stopPropagation();
44576
+ onIdleClipSortChange?.("latest");
44577
+ },
44578
+ className: "rounded-full p-0.5 transition-colors hover:bg-orange-100",
44579
+ title: "Clear idle sort",
44580
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3.5 w-3.5" })
44581
+ }
44582
+ )
44470
44583
  ] })
44471
44584
  ] })
44472
44585
  ] }),
@@ -45230,8 +45343,10 @@ var BottlenecksContent = ({
45230
45343
  const [clipClassifications, setClipClassifications] = React144.useState({});
45231
45344
  const [categoryMetadata, setCategoryMetadata] = React144.useState([]);
45232
45345
  const [categoryMetadataCategoryId, setCategoryMetadataCategoryId] = React144.useState(null);
45346
+ const [categoryMetadataSort, setCategoryMetadataSort] = React144.useState(null);
45233
45347
  const [currentMetadataIndex, setCurrentMetadataIndex] = React144.useState(0);
45234
45348
  const [metadataCache, setMetadataCache] = React144.useState({});
45349
+ const [idleClipSort, setIdleClipSort] = React144.useState("latest");
45235
45350
  const invalidateMetadataCache = React144.useCallback((categories) => {
45236
45351
  setMetadataCache((prevCache) => {
45237
45352
  if (!prevCache || Object.keys(prevCache).length === 0) {
@@ -45262,6 +45377,7 @@ var BottlenecksContent = ({
45262
45377
  const [isFullscreen, setIsFullscreen] = React144.useState(false);
45263
45378
  const categoryMetadataRef = React144.useRef([]);
45264
45379
  const currentMetadataIndexRef = React144.useRef(0);
45380
+ const previousIdleClipSortRef = React144.useRef(idleClipSort);
45265
45381
  const clearRetryTimeout = React144.useCallback(() => {
45266
45382
  if (retryTimeoutRef.current) {
45267
45383
  clearTimeout(retryTimeoutRef.current);
@@ -45708,9 +45824,13 @@ var BottlenecksContent = ({
45708
45824
  }
45709
45825
  return ["fast-cycles", "slow-cycles", "longest-idles"].includes(categoryId);
45710
45826
  }, [isFastSlowClipFiltersEnabled]);
45827
+ const shouldUseMetadataNavigation = React144.useCallback((categoryId) => {
45828
+ return isPercentileCategory(categoryId) || categoryId === "idle_time" && idleClipSort === "idle_duration_desc";
45829
+ }, [idleClipSort, isPercentileCategory]);
45711
45830
  const getMetadataCacheKey = React144.useCallback((categoryId) => {
45712
- return `${categoryId}-${effectiveDateString}-${effectiveShiftId}-${snapshotDateTime ?? "nosnap"}-${snapshotClipId ?? "nosnap"}`;
45713
- }, [effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId]);
45831
+ const sortKey = categoryId === "idle_time" ? idleClipSort : "latest";
45832
+ return `${categoryId}-${effectiveDateString}-${effectiveShiftId}-${snapshotDateTime ?? "nosnap"}-${snapshotClipId ?? "nosnap"}-${sortKey}`;
45833
+ }, [effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, idleClipSort]);
45714
45834
  const setVisibleCategoryMetadata = React144.useCallback((categoryId, clips) => {
45715
45835
  if (activeFilterRef.current !== categoryId) {
45716
45836
  return false;
@@ -45718,8 +45838,9 @@ var BottlenecksContent = ({
45718
45838
  categoryMetadataRef.current = clips;
45719
45839
  setCategoryMetadata(clips);
45720
45840
  setCategoryMetadataCategoryId(clips.length > 0 ? categoryId : null);
45841
+ setCategoryMetadataSort(clips.length > 0 ? categoryId === "idle_time" ? idleClipSort : "latest" : null);
45721
45842
  return true;
45722
- }, []);
45843
+ }, [idleClipSort]);
45723
45844
  const applyMetadataSnapshot = React144.useCallback((categoryId, clips, total) => {
45724
45845
  if (!clips || clips.length === 0) {
45725
45846
  return;
@@ -45730,11 +45851,11 @@ var BottlenecksContent = ({
45730
45851
  [cacheKey]: clips
45731
45852
  }));
45732
45853
  setVisibleCategoryMetadata(categoryId, clips);
45733
- if (!isPercentileCategory(categoryId) && typeof total === "number") {
45854
+ if (!shouldUseMetadataNavigation(categoryId) && typeof total === "number") {
45734
45855
  currentTotalRef.current = total;
45735
45856
  setCurrentTotal(total);
45736
45857
  }
45737
- }, [getMetadataCacheKey, isPercentileCategory, setVisibleCategoryMetadata]);
45858
+ }, [getMetadataCacheKey, shouldUseMetadataNavigation, setVisibleCategoryMetadata]);
45738
45859
  const getClipTypesForPercentileCategory = React144.useCallback((categoryId) => {
45739
45860
  switch (categoryId) {
45740
45861
  case "fast-cycles":
@@ -45760,6 +45881,7 @@ var BottlenecksContent = ({
45760
45881
  }
45761
45882
  setCategoryMetadata([]);
45762
45883
  setCategoryMetadataCategoryId(null);
45884
+ setCategoryMetadataSort(null);
45763
45885
  categoryMetadataRef.current = [];
45764
45886
  updateActiveFilter(fallbackFilter);
45765
45887
  }, [isFastSlowClipFiltersEnabled, activeFilter, dynamicCounts, clipTypes, updateActiveFilter]);
@@ -45807,6 +45929,7 @@ var BottlenecksContent = ({
45807
45929
  if (!isFastSlowClipFiltersEnabled && (categoryId === "fast-cycles" || categoryId === "slow-cycles")) {
45808
45930
  setCategoryMetadata([]);
45809
45931
  setCategoryMetadataCategoryId(null);
45932
+ setCategoryMetadataSort(null);
45810
45933
  categoryMetadataRef.current = [];
45811
45934
  return;
45812
45935
  }
@@ -45877,7 +46000,8 @@ var BottlenecksContent = ({
45877
46000
  limit: 100,
45878
46001
  knownTotal: mergedCounts[categoryId] ?? null,
45879
46002
  snapshotDateTime,
45880
- snapshotClipId
46003
+ snapshotClipId,
46004
+ sort: categoryId === "idle_time" ? idleClipSort : "latest"
45881
46005
  }),
45882
46006
  redirectReason: "session_expired"
45883
46007
  });
@@ -45956,6 +46080,7 @@ var BottlenecksContent = ({
45956
46080
  if (activeFilterRef.current === categoryId) {
45957
46081
  setCategoryMetadata([]);
45958
46082
  setCategoryMetadataCategoryId(null);
46083
+ setCategoryMetadataSort(null);
45959
46084
  categoryMetadataRef.current = [];
45960
46085
  }
45961
46086
  }
@@ -45964,7 +46089,26 @@ var BottlenecksContent = ({
45964
46089
  } finally {
45965
46090
  setIsCategoryLoading(false);
45966
46091
  }
45967
- }, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, supabase, setVisibleCategoryMetadata]);
46092
+ }, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, idleClipSort, supabase, setVisibleCategoryMetadata]);
46093
+ React144.useEffect(() => {
46094
+ if (previousIdleClipSortRef.current === idleClipSort) {
46095
+ return;
46096
+ }
46097
+ previousIdleClipSortRef.current = idleClipSort;
46098
+ if (activeFilterRef.current !== "idle_time") {
46099
+ return;
46100
+ }
46101
+ setCategoryMetadata([]);
46102
+ setCategoryMetadataCategoryId(null);
46103
+ setCategoryMetadataSort(null);
46104
+ categoryMetadataRef.current = [];
46105
+ setCurrentMetadataIndex(0);
46106
+ currentMetadataIndexRef.current = 0;
46107
+ setCurrentPosition(0);
46108
+ currentPositionRef.current = 0;
46109
+ setIsCategoryLoading(true);
46110
+ void loadCategoryMetadata("idle_time", true, true);
46111
+ }, [idleClipSort, loadCategoryMetadata]);
45968
46112
  React144.useEffect(() => {
45969
46113
  if (previousFilterRef.current !== activeFilter) {
45970
46114
  console.log(`Filter changed from ${previousFilterRef.current} to ${activeFilter} - resetting to first video`);
@@ -45975,6 +46119,7 @@ var BottlenecksContent = ({
45975
46119
  loadingCategoryRef.current = null;
45976
46120
  setCategoryMetadata([]);
45977
46121
  setCategoryMetadataCategoryId(null);
46122
+ setCategoryMetadataSort(null);
45978
46123
  setCurrentMetadataIndex(0);
45979
46124
  categoryMetadataRef.current = [];
45980
46125
  currentMetadataIndexRef.current = 0;
@@ -46073,7 +46218,7 @@ var BottlenecksContent = ({
46073
46218
  }
46074
46219
  if (metadataArray.length === 0) {
46075
46220
  console.warn(`[BottlenecksContent] No metadata available for category ${categoryId} after refresh`);
46076
- if (!isPercentileCategory(categoryId)) {
46221
+ if (!shouldUseMetadataNavigation(categoryId)) {
46077
46222
  const resolvedPosition = typeof position === "number" ? position : 1;
46078
46223
  currentPositionRef.current = resolvedPosition;
46079
46224
  setCurrentPosition(resolvedPosition);
@@ -46086,7 +46231,7 @@ var BottlenecksContent = ({
46086
46231
  const clickedClipIndex = metadataArray.findIndex((clip) => clip.clipId === clipId);
46087
46232
  if (clickedClipIndex === -1) {
46088
46233
  console.warn(`[BottlenecksContent] Clip ${clipId} not found after metadata refresh`);
46089
- if (!isPercentileCategory(categoryId)) {
46234
+ if (!shouldUseMetadataNavigation(categoryId)) {
46090
46235
  const resolvedPosition = typeof position === "number" ? position : 1;
46091
46236
  currentPositionRef.current = resolvedPosition;
46092
46237
  setCurrentPosition(resolvedPosition);
@@ -46098,7 +46243,7 @@ var BottlenecksContent = ({
46098
46243
  }
46099
46244
  setCurrentMetadataIndex(clickedClipIndex);
46100
46245
  currentMetadataIndexRef.current = clickedClipIndex;
46101
- if (!isPercentileCategory(categoryId)) {
46246
+ if (!shouldUseMetadataNavigation(categoryId)) {
46102
46247
  const position2 = clickedClipIndex + 1;
46103
46248
  currentPositionRef.current = position2;
46104
46249
  setCurrentPosition(position2);
@@ -46128,7 +46273,7 @@ var BottlenecksContent = ({
46128
46273
  clearLoadingState();
46129
46274
  }
46130
46275
  }
46131
- }, [workspaceId, s3ClipsService, updateActiveFilter, clearLoadingState, clearRetryTimeout, loadCategoryMetadata, applyMetadataSnapshot, mergedCounts, isPercentileCategory]);
46276
+ }, [workspaceId, s3ClipsService, updateActiveFilter, clearLoadingState, clearRetryTimeout, loadCategoryMetadata, applyMetadataSnapshot, mergedCounts, shouldUseMetadataNavigation]);
46132
46277
  const restartCurrentClipPlayback = React144.useCallback(() => {
46133
46278
  if (!currentClipId) {
46134
46279
  return;
@@ -46149,7 +46294,7 @@ var BottlenecksContent = ({
46149
46294
  return;
46150
46295
  }
46151
46296
  const activeCategory = activeFilterRef.current;
46152
- if (!activeCategory || activeCategory === "all" || isPercentileCategory(activeCategory)) {
46297
+ if (!activeCategory || activeCategory === "all" || shouldUseMetadataNavigation(activeCategory)) {
46153
46298
  return;
46154
46299
  }
46155
46300
  let cancelled = false;
@@ -46182,7 +46327,7 @@ var BottlenecksContent = ({
46182
46327
  }, [
46183
46328
  newClipsNotification,
46184
46329
  s3ClipsService,
46185
- isPercentileCategory,
46330
+ shouldUseMetadataNavigation,
46186
46331
  currentClipId,
46187
46332
  invalidateMetadataCache,
46188
46333
  loadAndPlayClipById,
@@ -46234,7 +46379,7 @@ var BottlenecksContent = ({
46234
46379
  }
46235
46380
  }
46236
46381
  try {
46237
- if (!isPercentileCategory(currentFilter)) {
46382
+ if (!shouldUseMetadataNavigation(currentFilter)) {
46238
46383
  if (!s3ClipsService || !workspaceId || !currentClipId) {
46239
46384
  throw new Error("S3 clips service not available");
46240
46385
  }
@@ -46334,7 +46479,7 @@ var BottlenecksContent = ({
46334
46479
  } else {
46335
46480
  const firstClipMeta = metadataArray[0];
46336
46481
  if (firstClipMeta?.clipId && firstClipMeta.clipId !== currentClipId) {
46337
- console.log(`[handleNext] Reached end of ${currentFilter}, looping back to newest percentile clip ${firstClipMeta.clipId}`);
46482
+ console.log(`[handleNext] Reached end of ${currentFilter}, looping back to first metadata clip ${firstClipMeta.clipId}`);
46338
46483
  await loadAndPlayClipById(firstClipMeta.clipId, currentFilter, 1, {
46339
46484
  clips: metadataArray,
46340
46485
  total: metadataArray.length
@@ -46360,7 +46505,7 @@ var BottlenecksContent = ({
46360
46505
  });
46361
46506
  clearLoadingState();
46362
46507
  }
46363
- }, [clearLoadingState, clearRetryTimeout, s3ClipsService, loadCategoryMetadata, loadAndPlayClipById, isPercentileCategory, workspaceId, currentClipId, effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, mergedCounts]);
46508
+ }, [clearLoadingState, clearRetryTimeout, s3ClipsService, loadCategoryMetadata, loadAndPlayClipById, shouldUseMetadataNavigation, workspaceId, currentClipId, effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, mergedCounts]);
46364
46509
  const handlePrevious = React144.useCallback(async () => {
46365
46510
  if (!isMountedRef.current || navigationLockRef.current) return;
46366
46511
  const currentFilter = activeFilterRef.current;
@@ -46379,7 +46524,7 @@ var BottlenecksContent = ({
46379
46524
  }
46380
46525
  }
46381
46526
  try {
46382
- if (!isPercentileCategory(currentFilter)) {
46527
+ if (!shouldUseMetadataNavigation(currentFilter)) {
46383
46528
  if (!s3ClipsService || !workspaceId || !currentClipId) {
46384
46529
  throw new Error("S3 clips service not available");
46385
46530
  }
@@ -46464,7 +46609,7 @@ var BottlenecksContent = ({
46464
46609
  });
46465
46610
  clearLoadingState();
46466
46611
  }
46467
- }, [clearLoadingState, clearRetryTimeout, s3ClipsService, loadCategoryMetadata, isPercentileCategory, workspaceId, currentClipId, effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, mergedCounts]);
46612
+ }, [clearLoadingState, clearRetryTimeout, s3ClipsService, loadCategoryMetadata, shouldUseMetadataNavigation, workspaceId, currentClipId, effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, mergedCounts]);
46468
46613
  const currentVideo = React144.useMemo(() => {
46469
46614
  if (!filteredVideos || filteredVideos.length === 0 || currentIndex >= filteredVideos.length) {
46470
46615
  return null;
@@ -46531,22 +46676,22 @@ var BottlenecksContent = ({
46531
46676
  }
46532
46677
  }, [currentVideo?.id, isShareLoading, supabase, workspaceId, workspaceName]);
46533
46678
  React144.useMemo(() => {
46534
- if (isPercentileCategory(activeFilter)) {
46679
+ if (shouldUseMetadataNavigation(activeFilter)) {
46535
46680
  return categoryMetadata.length;
46536
46681
  }
46537
46682
  return currentTotal || mergedCounts[activeFilter] || 0;
46538
- }, [activeFilter, categoryMetadata.length, currentTotal, mergedCounts, isPercentileCategory]);
46683
+ }, [activeFilter, categoryMetadata.length, currentTotal, mergedCounts, shouldUseMetadataNavigation]);
46539
46684
  React144.useMemo(() => {
46540
- if (isPercentileCategory(activeFilter)) {
46685
+ if (shouldUseMetadataNavigation(activeFilter)) {
46541
46686
  return categoryMetadata.length > 0 ? currentMetadataIndex + 1 : 0;
46542
46687
  }
46543
46688
  return currentPosition;
46544
- }, [activeFilter, categoryMetadata.length, currentMetadataIndex, currentPosition, isPercentileCategory]);
46545
- const prefetchedExplorerMetadata = React144.useMemo(() => buildPrefetchedExplorerMetadata(
46689
+ }, [activeFilter, categoryMetadata.length, currentMetadataIndex, currentPosition, shouldUseMetadataNavigation]);
46690
+ const prefetchedExplorerMetadata = React144.useMemo(() => activeFilter === "idle_time" && categoryMetadataSort !== idleClipSort ? void 0 : buildPrefetchedExplorerMetadata(
46546
46691
  activeFilter,
46547
46692
  categoryMetadataCategoryId,
46548
46693
  categoryMetadata
46549
- ), [activeFilter, categoryMetadata, categoryMetadataCategoryId]);
46694
+ ), [activeFilter, categoryMetadata, categoryMetadataCategoryId, categoryMetadataSort, idleClipSort]);
46550
46695
  const classificationClipIds = React144.useMemo(() => {
46551
46696
  if (!idleTimeVlmEnabled) {
46552
46697
  return [];
@@ -47295,7 +47440,12 @@ var BottlenecksContent = ({
47295
47440
  showPercentileCycleFilters: isFastSlowClipFiltersEnabled,
47296
47441
  prefetchedClipMetadata: prefetchedExplorerMetadata,
47297
47442
  activeCategoryLoading: isCategoryLoading,
47443
+ idleClipSort,
47444
+ onIdleClipSortChange: setIdleClipSort,
47298
47445
  onFilterChange: (filterId) => {
47446
+ if (filterId !== "idle_time") {
47447
+ setIdleClipSort("latest");
47448
+ }
47299
47449
  updateActiveFilter(filterId);
47300
47450
  const category = categoriesToShow.find((cat) => cat.type === filterId);
47301
47451
  if (category) {
@@ -49218,6 +49368,11 @@ var LineHistoryCalendar = ({
49218
49368
  return calendar;
49219
49369
  }, [data, month, year, configuredTimezone]);
49220
49370
  const hasRealData = (shift) => {
49371
+ if (isUptimeMode) {
49372
+ if (shift.hasData === true) return true;
49373
+ const efficiency = Number(shift.avg_efficiency);
49374
+ 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;
49375
+ }
49221
49376
  if (shift.hasData !== void 0) return shift.hasData;
49222
49377
  return shift.total_workspaces > 0 || shift.avg_efficiency > 0 || shift.underperforming_workspaces > 0;
49223
49378
  };
@@ -49850,13 +50005,18 @@ var LineMonthlyHistory = ({
49850
50005
  enabled: !!lineId && idleTimeVlmEnabled
49851
50006
  });
49852
50007
  const hasRealData = (shift) => {
50008
+ if (isUptimeMode) {
50009
+ if (shift.hasData === true) return true;
50010
+ const efficiency = Number(shift.avg_efficiency);
50011
+ 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;
50012
+ }
49853
50013
  if (shift.hasData !== void 0) return shift.hasData;
49854
50014
  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;
49855
50015
  };
49856
50016
  const averages = (analysisMonthlyData || []).reduce(
49857
50017
  (acc, day) => {
49858
50018
  const shiftData = getShiftData2(day, selectedShiftId);
49859
- if (!shiftData || shiftData?.avg_efficiency < 5) {
50019
+ if (!shiftData || !isValidAggregateEfficiency(isUptimeMode ? "uptime" : "output", shiftData.avg_efficiency)) {
49860
50020
  return acc;
49861
50021
  }
49862
50022
  return {
@@ -49885,7 +50045,9 @@ var LineMonthlyHistory = ({
49885
50045
  const avgOutput = outputAverages.count > 0 ? outputAverages.output / outputAverages.count : 0;
49886
50046
  const uptimeSummary = React144.useMemo(() => {
49887
50047
  if (!isUptimeMode) return null;
49888
- const validDays = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter((shiftData) => shiftData && hasRealData(shiftData)).map((shiftData) => ({ shiftData, totals: getUptimeTotals(shiftData) }));
50048
+ const validDays = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter(
50049
+ (shiftData) => shiftData && hasRealData(shiftData) && isValidAggregateEfficiency("uptime", shiftData.avg_efficiency)
50050
+ ).map((shiftData) => ({ shiftData, totals: getUptimeTotals(shiftData) }));
49889
50051
  if (!validDays.length) {
49890
50052
  return { avgUtilization: 0, avgIdleTime: 0, avgDailyStoppages: 0 };
49891
50053
  }
@@ -50033,7 +50195,9 @@ var LineMonthlyHistory = ({
50033
50195
  }, [chartData.yAxisMax, chartData.lastSetTarget]);
50034
50196
  const pieChartData = React144.useMemo(() => {
50035
50197
  if (!isUptimeMode) return [];
50036
- const validShifts = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter(hasRealData);
50198
+ const validShifts = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter(
50199
+ (shift) => shift && hasRealData(shift) && isValidAggregateEfficiency("uptime", shift.avg_efficiency)
50200
+ );
50037
50201
  if (!validShifts.length) return [];
50038
50202
  const efficiencyValues = validShifts.map((shift) => Number.isFinite(shift.avg_efficiency) ? Number(shift.avg_efficiency) : null).filter((value) => value !== null);
50039
50203
  if (!efficiencyValues.length) return [];
@@ -50643,7 +50807,9 @@ var LineMonthlyPdfGenerator = ({
50643
50807
  const productiveSeconds = activeSecondsRaw > 0 ? Math.min(activeSecondsRaw, availableSeconds) : Math.max(availableSeconds - idleSeconds, 0);
50644
50808
  return { availableSeconds, productiveSeconds, idleSeconds };
50645
50809
  };
50646
- const validShifts = validDays.map((day) => getLineShiftData2(day, selectedShiftId)).filter((shift) => isUptimeMode ? hasShiftData(shift) : shift.avg_efficiency >= 5);
50810
+ const validShifts = validDays.map((day) => getLineShiftData2(day, selectedShiftId)).filter(
50811
+ (shift) => hasShiftData(shift) && isValidAggregateEfficiency(isUptimeMode ? "uptime" : "output", shift.avg_efficiency)
50812
+ );
50647
50813
  const monthlyMetrics = validShifts.length > 0 ? isUptimeMode ? (() => {
50648
50814
  let utilizationSum = 0;
50649
50815
  let idleTimeSum = 0;
@@ -52628,7 +52794,10 @@ var WorkspaceMonthlyHistory = ({
52628
52794
  return ticks.filter((v) => v >= 0 && v <= max * 1.05).sort((a, b) => a - b);
52629
52795
  }, [chartData.yAxisMax, chartData.lastSetTarget, isUptimeMode]);
52630
52796
  const pieChartData = React144.useMemo(() => {
52631
- const validShifts = analysisMonthlyData.map((d) => getShiftData(d, selectedShiftId)).filter(hasRealData);
52797
+ const aggregateMode = isUptimeMode ? "uptime" : "output";
52798
+ const validShifts = analysisMonthlyData.map((d) => getShiftData(d, selectedShiftId)).filter(
52799
+ (shift) => shift && hasRealData(shift) && isValidAggregateEfficiency(aggregateMode, shift.efficiency)
52800
+ );
52632
52801
  if (validShifts.length === 0) return [];
52633
52802
  const efficiencyValues = validShifts.map((shift) => Number.isFinite(shift.efficiency) ? Number(shift.efficiency) : null).filter((value) => value !== null);
52634
52803
  if (!efficiencyValues.length) return [];
@@ -52639,10 +52808,10 @@ var WorkspaceMonthlyHistory = ({
52639
52808
  { name: "Productive", value: productivePercent },
52640
52809
  { name: "Idle", value: idlePercent }
52641
52810
  ];
52642
- }, [analysisMonthlyData, selectedShiftId, shiftWorkSeconds]);
52811
+ }, [analysisMonthlyData, selectedShiftId, isUptimeMode]);
52643
52812
  const metrics2 = React144.useMemo(() => {
52644
52813
  const validShifts = analysisMonthlyData.map((d) => getShiftData(d, selectedShiftId)).filter(hasRealData);
52645
- const filteredShifts = isUptimeMode ? validShifts : validShifts.filter((shift) => (shift.efficiency ?? 0) >= 5);
52814
+ const filteredShifts = isUptimeMode ? validShifts.filter((shift) => isValidAggregateEfficiency("uptime", shift.efficiency)) : validShifts.filter((shift) => isValidAggregateEfficiency("output", shift.efficiency));
52646
52815
  if (filteredShifts.length === 0) return null;
52647
52816
  const totalEfficiency = filteredShifts.reduce((sum, shift) => sum + (shift.efficiency || 0), 0);
52648
52817
  const totalUtilization = filteredShifts.reduce(
@@ -53862,7 +54031,7 @@ var WorkspaceMonthlyPdfGenerator = ({
53862
54031
  const shift = getShiftData(dayData, selectedShiftId);
53863
54032
  return { dayData, shift };
53864
54033
  }).filter(({ shift }) => hasShiftData(shift)).sort((left, right) => getDayDateKey(right.dayData).localeCompare(getDayDateKey(left.dayData)));
53865
- const filteredShifts = isUptimeMode ? validShifts : validShifts.filter((shift) => (shift.efficiency ?? 0) >= 5);
54034
+ const filteredShifts = isUptimeMode ? validShifts.filter((shift) => isValidAggregateEfficiency("uptime", shift.efficiency)) : validShifts.filter((shift) => isValidAggregateEfficiency("output", shift.efficiency));
53866
54035
  const monthlyMetrics = filteredShifts.length > 0 ? isUptimeMode ? (() => {
53867
54036
  const totalIdleTime = filteredShifts.reduce((sum, shift) => sum + shift.idleTime, 0);
53868
54037
  const totalCycleTime = filteredShifts.reduce((sum, shift) => sum + shift.cycleTime, 0);
@@ -65216,6 +65385,7 @@ var buildLineInfoSnapshot = (lineDetails, metrics2) => {
65216
65385
  output_hourly: metrics2.output_hourly,
65217
65386
  hourly_target_output: metrics2.hourly_target_output,
65218
65387
  line_threshold: metrics2.line_threshold ?? 0,
65388
+ output_target_recalculated: metrics2.output_target_recalculated ?? null,
65219
65389
  threshold_pph: metrics2.threshold_pph ?? 0,
65220
65390
  shift_start: metrics2.shift_start || "06:00",
65221
65391
  shift_end: metrics2.shift_end || "14:00",
@@ -65303,6 +65473,7 @@ var transformLineMetrics = (lineId, detailResponse, queryDate, queryShiftId) =>
65303
65473
  output_array: [],
65304
65474
  hourly_target_output: void 0,
65305
65475
  line_threshold: 0,
65476
+ output_target_recalculated: null,
65306
65477
  threshold_pph: 0,
65307
65478
  shift_start: "06:00",
65308
65479
  shift_end: "14:00",
@@ -66140,6 +66311,7 @@ var MetricCards = React144.memo(({
66140
66311
  issueResolutionSummary?.mean_resolution_seconds ?? issueResolutionSummary?.median_resolution_seconds
66141
66312
  );
66142
66313
  getIssueResolutionSecondaryText(issueResolutionSummary);
66314
+ const outputTarget = lineInfo?.metrics.output_target_recalculated ?? lineInfo?.metrics.line_threshold ?? 0;
66143
66315
  return /* @__PURE__ */ jsxRuntime.jsxs(
66144
66316
  motion.div,
66145
66317
  {
@@ -66154,7 +66326,7 @@ var MetricCards = React144.memo(({
66154
66326
  OutputProgressChart,
66155
66327
  {
66156
66328
  currentOutput: lineInfo?.metrics.current_output || 0,
66157
- targetOutput: lineInfo?.metrics.line_threshold || 0,
66329
+ targetOutput: outputTarget,
66158
66330
  skuBreakdown: skuAware ? skuBreakdown : void 0,
66159
66331
  selectedSkuId,
66160
66332
  onSelectSku,
@@ -66278,7 +66450,7 @@ var MetricCards = React144.memo(({
66278
66450
  if (prevIssueSummary?.mean_resolution_seconds !== nextIssueSummary?.mean_resolution_seconds || prevIssueSummary?.median_resolution_seconds !== nextIssueSummary?.median_resolution_seconds || prevIssueSummary?.resolved_issue_count !== nextIssueSummary?.resolved_issue_count || prevIssueSummary?.open_issue_count !== nextIssueSummary?.open_issue_count || prevIssueSummary?.oldest_open_issue_age_seconds !== nextIssueSummary?.oldest_open_issue_age_seconds || prevIssueSummary?.total_issue_seconds !== nextIssueSummary?.total_issue_seconds) {
66279
66451
  return false;
66280
66452
  }
66281
- return prevMetrics.current_output === nextMetrics.current_output && prevMetrics.line_threshold === nextMetrics.line_threshold && prevMetrics.underperforming_workspaces === nextMetrics.underperforming_workspaces && prevMetrics.total_workspaces === nextMetrics.total_workspaces && prevMetrics.avg_efficiency === nextMetrics.avg_efficiency;
66453
+ return prevMetrics.current_output === nextMetrics.current_output && prevMetrics.line_threshold === nextMetrics.line_threshold && prevMetrics.output_target_recalculated === nextMetrics.output_target_recalculated && prevMetrics.underperforming_workspaces === nextMetrics.underperforming_workspaces && prevMetrics.total_workspaces === nextMetrics.total_workspaces && prevMetrics.avg_efficiency === nextMetrics.avg_efficiency;
66282
66454
  });
66283
66455
  MetricCards.displayName = "MetricCards";
66284
66456
  var LineUptimeMetricCards = React144.memo(({
@@ -67031,7 +67203,15 @@ var KPIDetailView = ({
67031
67203
  const fallbackTimes = resolveMonthlyShiftTimes(metric.shift_id);
67032
67204
  const resolvedShiftStart = metric.shift_start || fallbackTimes.start;
67033
67205
  const resolvedShiftEnd = metric.shift_end || fallbackTimes.end;
67034
- const hasBackendUptimeSeconds = isUptimeMode && (Number.isFinite(metric.active_time_seconds) || Number.isFinite(metric.idle_time_seconds) || Number.isFinite(metric.available_time_seconds));
67206
+ const coerceOptionalNumber2 = (value) => {
67207
+ if (value === void 0 || value === null || value === "") return null;
67208
+ const parsed = Number(value);
67209
+ return Number.isFinite(parsed) ? parsed : null;
67210
+ };
67211
+ const metricActiveTimeSeconds = coerceOptionalNumber2(metric.active_time_seconds);
67212
+ const metricIdleTimeSeconds = coerceOptionalNumber2(metric.idle_time_seconds);
67213
+ const metricAvailableTimeSeconds = coerceOptionalNumber2(metric.available_time_seconds);
67214
+ const hasBackendUptimeSeconds = isUptimeMode && (metricActiveTimeSeconds !== null || metricIdleTimeSeconds !== null || metricAvailableTimeSeconds !== null);
67035
67215
  const uptimeSeries2 = isUptimeMode && !hasBackendUptimeSeconds ? buildUptimeSeries({
67036
67216
  idleTimeHourly: metric.idle_time_hourly || {},
67037
67217
  shiftStart: resolvedShiftStart || void 0,
@@ -67039,9 +67219,13 @@ var KPIDetailView = ({
67039
67219
  shiftDate: metric.date,
67040
67220
  timezone: configuredTimezone
67041
67221
  }) : null;
67042
- const idleTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metric.idle_time_seconds || 0 : (uptimeSeries2?.idleMinutes || 0) * 60 : 0;
67043
- const activeTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metric.active_time_seconds || 0 : (uptimeSeries2?.activeMinutes || 0) * 60 : 0;
67044
- const availableTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metric.available_time_seconds || activeTimeSeconds + idleTimeSeconds : (uptimeSeries2?.availableMinutes || 0) * 60 : 0;
67222
+ const idleTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metricIdleTimeSeconds ?? 0 : (uptimeSeries2?.idleMinutes || 0) * 60 : 0;
67223
+ const activeTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metricActiveTimeSeconds ?? 0 : (uptimeSeries2?.activeMinutes || 0) * 60 : 0;
67224
+ const availableTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metricAvailableTimeSeconds ?? activeTimeSeconds + idleTimeSeconds : (uptimeSeries2?.availableMinutes || 0) * 60 : 0;
67225
+ const metricAvgEfficiency = Number(metric.avg_efficiency);
67226
+ const metricTotalWorkspaces = Number(metric.total_workspaces || 0);
67227
+ const metricCurrentOutput = Number(metric.current_output || 0);
67228
+ const hasUptimeMetricData = isUptimeMode && (availableTimeSeconds > 0 || metricTotalWorkspaces > 0 || metricCurrentOutput > 0 || Number.isFinite(metricAvgEfficiency) && metricAvgEfficiency > 0);
67045
67229
  const computedUptimeEfficiency = (() => {
67046
67230
  const availableMinutes = availableTimeSeconds / 60;
67047
67231
  if (!availableMinutes || availableMinutes <= 0) return 0;
@@ -67061,7 +67245,7 @@ var KPIDetailView = ({
67061
67245
  targetOutput: Number(metric.line_threshold ?? metric.ideal_output ?? 0),
67062
67246
  compliance_percentage: 95 + Math.random() * 5,
67063
67247
  // Mock data: random value between 95-100%
67064
- hasData: isUptimeMode ? availableTimeSeconds > 0 : true,
67248
+ hasData: isUptimeMode ? hasUptimeMetricData : true,
67065
67249
  idle_time_seconds: idleTimeSeconds,
67066
67250
  active_time_seconds: activeTimeSeconds,
67067
67251
  available_time_seconds: availableTimeSeconds,
@@ -67146,6 +67330,7 @@ var KPIDetailView = ({
67146
67330
  output_hourly: metrics2.output_hourly,
67147
67331
  hourly_target_output: metrics2.hourly_target_output,
67148
67332
  line_threshold: metrics2.line_threshold ?? 0,
67333
+ output_target_recalculated: metrics2.output_target_recalculated ?? null,
67149
67334
  threshold_pph: metrics2.threshold_pph ?? 0,
67150
67335
  shift_start: metrics2.shift_start || "06:00",
67151
67336
  shift_end: metrics2.shift_end || "14:00",
@@ -67220,15 +67405,16 @@ var KPIDetailView = ({
67220
67405
  [lineSkuBreakdown]
67221
67406
  );
67222
67407
  const outputChartSkuBreakdown = React144.useMemo(
67223
- () => realSkuOptions.filter(
67224
- (item) => (item.current_output ?? 0) > 0 || (item.ideal_output ?? 0) > 0
67225
- ).map((item) => ({
67408
+ () => realSkuOptions.filter((item) => {
67409
+ const targetOutput = item.output_target_recalculated ?? item.line_threshold_recalculated ?? item.ideal_output ?? 0;
67410
+ return (item.current_output ?? 0) > 0 || targetOutput > 0;
67411
+ }).map((item) => ({
67226
67412
  sku_id: item.sku_id,
67227
67413
  sku_code: item.sku_code,
67228
67414
  sku_definition: "",
67229
67415
  is_dummy: false,
67230
67416
  total_output: item.current_output ?? 0,
67231
- target_output: item.ideal_output ?? 0,
67417
+ target_output: item.output_target_recalculated ?? item.line_threshold_recalculated ?? item.ideal_output ?? 0,
67232
67418
  avg_pph: 0,
67233
67419
  pph_threshold: 0,
67234
67420
  avg_cycle_time: 0,
@@ -67282,7 +67468,8 @@ var KPIDetailView = ({
67282
67468
  underperforming_workspaces: selectedSkuRow.underperforming_workspaces ?? resolvedLineInfo.metrics.underperforming_workspaces,
67283
67469
  underperforming_workspace_names: selectedSkuRow.underperforming_workspace_names ?? resolvedLineInfo.metrics.underperforming_workspace_names,
67284
67470
  underperforming_workspace_uuids: selectedSkuRow.underperforming_workspace_uuids ?? resolvedLineInfo.metrics.underperforming_workspace_uuids,
67285
- line_threshold: selectedSkuRow.line_threshold ?? resolvedLineInfo.metrics.line_threshold
67471
+ line_threshold: selectedSkuRow.line_threshold ?? resolvedLineInfo.metrics.line_threshold,
67472
+ output_target_recalculated: selectedSkuRow.output_target_recalculated ?? selectedSkuRow.line_threshold_recalculated ?? resolvedLineInfo.metrics.output_target_recalculated ?? null
67286
67473
  }
67287
67474
  };
67288
67475
  }, [resolvedLineInfo, selectedSkuRow]);