@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.mjs CHANGED
@@ -10,7 +10,7 @@ import { EventEmitter } from 'events';
10
10
  import { createClient, REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js';
11
11
  import Hls, { Events, ErrorTypes } from 'hls.js';
12
12
  import useSWR from 'swr';
13
- import { Camera, AlertTriangle, ChevronDown, ChevronUp, Check, Map as Map$1, Video, ShieldCheck, Star, Award, Filter, X, Coffee, Plus, ArrowUp, ArrowDown, ArrowRight, ArrowLeft, Clock, Calendar, Save, AlertCircle, Loader2, Minus, ChevronLeft, ChevronRight, TrendingUp, Sparkles, Pause, Play, XCircle, HelpCircle, Activity, Wrench, UserX, Package, RefreshCw, Palette, CheckCircle2, TrendingDown, FolderOpen, Folder, Tag, Sliders, Layers, Search, Edit2, CheckCircle, User, Users, Shield, Building2, Mail, Lock, Info, Share2, Trophy, Target, Download, Copy, Sun, Moon, MousePointer, UserPlus, UserCog, Trash2, Eye, MoreVertical, BarChart3, Pencil, UserCheck, LogOut, Film, MessageSquare, Menu, Send, Settings, LifeBuoy, EyeOff, Zap, Flame, Crown, Medal } from 'lucide-react';
13
+ import { Camera, AlertTriangle, ChevronDown, ChevronUp, Check, Map as Map$1, Video, ShieldCheck, Star, Award, Filter, X, Coffee, Plus, ArrowUp, ArrowDown, ArrowRight, ArrowLeft, Clock, Calendar, Save, AlertCircle, Loader2, Minus, ChevronLeft, ChevronRight, TrendingUp, Sparkles, Pause, Play, XCircle, HelpCircle, Activity, Wrench, UserX, Package, RefreshCw, Palette, CheckCircle2, TrendingDown, FolderOpen, Folder, ArrowDownWideNarrow, Tag, Sliders, Layers, Search, Edit2, CheckCircle, User, Users, Shield, Building2, Mail, Lock, Info, Share2, Trophy, Target, Download, Copy, Sun, Moon, MousePointer, UserPlus, UserCog, Trash2, Eye, MoreVertical, BarChart3, Pencil, UserCheck, LogOut, Film, MessageSquare, Menu, Send, Settings, LifeBuoy, EyeOff, Zap, Flame, Crown, Medal } from 'lucide-react';
14
14
  import { memo, noop, warning, invariant, progress, secondsToMilliseconds, millisecondsToSeconds } from 'motion-utils';
15
15
  import { BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, ReferenceLine, Tooltip, Legend, Bar, LabelList, ResponsiveContainer, LineChart as LineChart$1, Line, Customized, Cell, PieChart, Pie, ComposedChart, Area, ScatterChart, Scatter } from 'recharts';
16
16
  import { Slot } from '@radix-ui/react-slot';
@@ -4557,6 +4557,7 @@ var buildLineSkuBreakdown = (rows, skuCatalog) => {
4557
4557
  avg_efficiency: safeFloat(row.avg_efficiency),
4558
4558
  line_threshold: typeof row.line_threshold === "number" && Number.isFinite(row.line_threshold) ? row.line_threshold : null,
4559
4559
  line_threshold_recalculated: typeof row.line_threshold_recalculated === "number" && Number.isFinite(row.line_threshold_recalculated) ? row.line_threshold_recalculated : null,
4560
+ output_target_recalculated: typeof row.output_target_recalculated === "number" && Number.isFinite(row.output_target_recalculated) ? row.output_target_recalculated : null,
4560
4561
  total_workspaces: safeInt(row.total_workspaces),
4561
4562
  underperforming_workspaces: safeInt(row.underperforming_workspaces),
4562
4563
  underperforming_workspace_names: Array.isArray(row.underperforming_workspace_names) ? row.underperforming_workspace_names : [],
@@ -5207,7 +5208,7 @@ var dashboardService = {
5207
5208
  },
5208
5209
  outputProgress: {
5209
5210
  current: lineInfo.metrics.current_output,
5210
- target: lineInfo.metrics.line_threshold,
5211
+ target: lineInfo.metrics.output_target_recalculated ?? lineInfo.metrics.line_threshold,
5211
5212
  idealOutput: lineInfo.metrics.ideal_output,
5212
5213
  change: 0
5213
5214
  },
@@ -21872,6 +21873,24 @@ var getConfigurableShortWorkspaceDisplayName = (workspaceId, workspaceConfig, li
21872
21873
  return fullName;
21873
21874
  };
21874
21875
 
21876
+ // src/lib/utils/efficiencyValidity.ts
21877
+ var MIN_VALID_OUTPUT_EFFICIENCY = 5;
21878
+ var MIN_VALID_UPTIME_EFFICIENCY = 1;
21879
+ var normalizeMonitoringMode = (mode) => String(mode ?? "").trim().toLowerCase() === "uptime" ? "uptime" : "output";
21880
+ var toFiniteNumberOrNull = (value) => {
21881
+ if (typeof value === "number" && Number.isFinite(value)) return value;
21882
+ if (typeof value === "string" && value.trim() !== "") {
21883
+ const parsed = Number(value);
21884
+ return Number.isFinite(parsed) ? parsed : null;
21885
+ }
21886
+ return null;
21887
+ };
21888
+ var isValidAggregateEfficiency = (monitoringMode, efficiency) => {
21889
+ const value = toFiniteNumberOrNull(efficiency);
21890
+ if (value === null) return false;
21891
+ return normalizeMonitoringMode(monitoringMode) === "uptime" ? value >= MIN_VALID_UPTIME_EFFICIENCY : value >= MIN_VALID_OUTPUT_EFFICIENCY;
21892
+ };
21893
+
21875
21894
  // src/lib/utils/kpis.ts
21876
21895
  var toNumber = (value) => {
21877
21896
  if (typeof value === "number" && Number.isFinite(value)) return value;
@@ -21895,7 +21914,7 @@ var buildKPIsFromLineMetricsRow = (row) => {
21895
21914
  const avgEfficiency = toNumber(row.avg_efficiency);
21896
21915
  const avgCycleTime = toNumber(row.avg_cycle_time);
21897
21916
  const currentOutput = toNumber(row.current_output);
21898
- const lineThreshold = toNumber(row.line_threshold);
21917
+ const lineThreshold = row.output_target_recalculated !== void 0 && row.output_target_recalculated !== null ? toNumber(row.output_target_recalculated) : toNumber(row.line_threshold);
21899
21918
  const idealOutput = toNumber(row.ideal_output) || lineThreshold || 0;
21900
21919
  const underperformingWorkspaces = toNumber(row.underperforming_workspaces);
21901
21920
  const totalWorkspaces = toNumber(row.total_workspaces);
@@ -21927,10 +21946,15 @@ var buildKPIsFromLineMetricsRow = (row) => {
21927
21946
  };
21928
21947
  var aggregateKPIsFromLineMetricsRows = (rows) => {
21929
21948
  if (!rows || rows.length === 0) return createDefaultKPIs();
21930
- const eligibleRows = rows.filter((row) => toNumber(row?.avg_efficiency) >= 5);
21949
+ const eligibleRows = rows.filter(
21950
+ (row) => isValidAggregateEfficiency(row?.monitoring_mode ?? row?.monitoringMode, row?.avg_efficiency)
21951
+ );
21931
21952
  if (eligibleRows.length === 0) return createDefaultKPIs();
21932
21953
  const currentOutputSum = eligibleRows.reduce((sum, row) => sum + toNumber(row.current_output), 0);
21933
- const lineThresholdSum = eligibleRows.reduce((sum, row) => sum + toNumber(row.line_threshold), 0);
21954
+ const lineThresholdSum = eligibleRows.reduce(
21955
+ (sum, row) => sum + (row?.output_target_recalculated !== void 0 && row?.output_target_recalculated !== null ? toNumber(row.output_target_recalculated) : toNumber(row.line_threshold)),
21956
+ 0
21957
+ );
21934
21958
  const idealOutputSum = eligibleRows.reduce(
21935
21959
  (sum, row) => sum + (toNumber(row.ideal_output) || toNumber(row.line_threshold)),
21936
21960
  0
@@ -37252,8 +37276,8 @@ var HourlyOutputChart = React144__default.memo(
37252
37276
  HourlyOutputChart.displayName = "HourlyOutputChart";
37253
37277
 
37254
37278
  // src/components/dashboard/grid/videoGridMetricUtils.ts
37279
+ var VIDEO_GRID_LEGEND_LABEL = "Real-Time efficiency";
37255
37280
  var MAP_GRID_LEGEND_LABEL = "Efficiency";
37256
- var MIXED_VIDEO_GRID_LEGEND_LABEL = "Live Efficiency";
37257
37281
  var isFiniteNumber2 = (value) => typeof value === "number" && Number.isFinite(value);
37258
37282
  var isVideoGridRecentFlowEnabled = (workspace) => isRecentFlowVideoGridMetricMode(
37259
37283
  workspace.video_grid_metric_mode,
@@ -37265,7 +37289,7 @@ var isVideoGridWipGated = (workspace) => isWipGatedVideoGridMetricMode(
37265
37289
  );
37266
37290
  var hasVideoGridRecentFlow = (workspace) => isVideoGridRecentFlowEnabled(workspace) && isFiniteNumber2(workspace.recent_flow_percent);
37267
37291
  var isVideoGridRecentFlowUnavailable = (workspace) => isVideoGridRecentFlowEnabled(workspace) && !hasVideoGridRecentFlow(workspace);
37268
- var getVideoGridMetricValue = (workspace) => {
37292
+ var getRawVideoGridMetricValue = (workspace) => {
37269
37293
  const recentFlowPercent = workspace.recent_flow_percent;
37270
37294
  if (hasVideoGridRecentFlow(workspace) && isFiniteNumber2(recentFlowPercent)) {
37271
37295
  return recentFlowPercent;
@@ -37277,7 +37301,7 @@ var getVideoGridMetricValue = (workspace) => {
37277
37301
  };
37278
37302
  var hasIncomingWipMapping = (workspace) => Boolean(workspace.incoming_wip_buffer_name);
37279
37303
  var getVideoGridBaseColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37280
- const metricValue = getVideoGridMetricValue(workspace);
37304
+ const metricValue = getRawVideoGridMetricValue(workspace);
37281
37305
  if (!isFiniteNumber2(metricValue)) {
37282
37306
  return "neutral";
37283
37307
  }
@@ -37301,6 +37325,25 @@ var isLowWipGreenOverride = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37301
37325
  }
37302
37326
  return isFiniteNumber2(workspace.incoming_wip_current) && workspace.incoming_wip_current <= 1;
37303
37327
  };
37328
+ var isHighEfficiencyRedFlowOverride = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37329
+ if (workspace.scheduled_break_active === true) {
37330
+ return false;
37331
+ }
37332
+ if (workspace.recent_flow_forced_zero_after_shift === true) {
37333
+ return false;
37334
+ }
37335
+ if (!hasVideoGridRecentFlow(workspace) || !isVideoGridWipGated(workspace)) {
37336
+ return false;
37337
+ }
37338
+ if (isLowWipGreenOverride(workspace, legend)) {
37339
+ return false;
37340
+ }
37341
+ if (getVideoGridBaseColorState(workspace, legend) !== "red") {
37342
+ return false;
37343
+ }
37344
+ return isFiniteNumber2(workspace.efficiency) && workspace.efficiency > 100;
37345
+ };
37346
+ var getVideoGridMetricValue = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => isHighEfficiencyRedFlowOverride(workspace, legend) ? workspace.efficiency : getRawVideoGridMetricValue(workspace);
37304
37347
  var toMinuteBucket = (minuteBucket) => Number.isFinite(minuteBucket) ? Math.floor(minuteBucket) : Math.floor(Date.now() / 6e4);
37305
37348
  var getEffectiveFlowMinuteBucket = (workspace) => {
37306
37349
  const effectiveAt = workspace.recent_flow_effective_end_at;
@@ -37326,7 +37369,7 @@ var getSyntheticLowWipDisplayValue = (workspace, minuteBucket) => {
37326
37369
  const offset = (hashWorkspaceKey(workspace) % 11 + bucket % 11 + 11) % 11;
37327
37370
  return 100 + offset;
37328
37371
  };
37329
- var getVideoGridDisplayValue = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND, minuteBucket) => isLowWipGreenOverride(workspace, legend) ? getSyntheticLowWipDisplayValue(workspace, minuteBucket) : getVideoGridMetricValue(workspace);
37372
+ var getVideoGridDisplayValue = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND, minuteBucket) => isLowWipGreenOverride(workspace, legend) ? getSyntheticLowWipDisplayValue(workspace, minuteBucket) : getVideoGridMetricValue(workspace, legend);
37330
37373
  var getVideoGridColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37331
37374
  const baseColor = getVideoGridBaseColorState(workspace, legend);
37332
37375
  if (!hasVideoGridRecentFlow(workspace)) {
@@ -37338,15 +37381,18 @@ var getVideoGridColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) =>
37338
37381
  if (baseColor !== "red") {
37339
37382
  return baseColor;
37340
37383
  }
37384
+ if (isLowWipGreenOverride(workspace, legend)) {
37385
+ return "green";
37386
+ }
37387
+ if (isHighEfficiencyRedFlowOverride(workspace, legend)) {
37388
+ return getEfficiencyColor(workspace.efficiency, legend);
37389
+ }
37341
37390
  if (!hasIncomingWipMapping(workspace)) {
37342
37391
  return baseColor;
37343
37392
  }
37344
37393
  if (!isFiniteNumber2(workspace.incoming_wip_current)) {
37345
37394
  return "neutral";
37346
37395
  }
37347
- if (isLowWipGreenOverride(workspace, legend)) {
37348
- return "green";
37349
- }
37350
37396
  return baseColor;
37351
37397
  };
37352
37398
  var getVideoGridLegendLabel = (workspaces) => {
@@ -37354,21 +37400,7 @@ var getVideoGridLegendLabel = (workspaces) => {
37354
37400
  if (visibleWorkspaces.length === 0) {
37355
37401
  return MAP_GRID_LEGEND_LABEL;
37356
37402
  }
37357
- const recentFlowEnabledCount = visibleWorkspaces.filter(isVideoGridRecentFlowEnabled).length;
37358
- if (recentFlowEnabledCount === 0) {
37359
- return MAP_GRID_LEGEND_LABEL;
37360
- }
37361
- const recentFlowWindows = new Set(
37362
- visibleWorkspaces.filter(isVideoGridRecentFlowEnabled).map((workspace) => workspace.recent_flow_window_minutes ?? 7).filter((value) => typeof value === "number" && Number.isFinite(value))
37363
- );
37364
- if (recentFlowEnabledCount === visibleWorkspaces.length) {
37365
- if (recentFlowWindows.size === 1) {
37366
- const [windowMinutes] = Array.from(recentFlowWindows);
37367
- return `${windowMinutes} Minute Efficiency`;
37368
- }
37369
- return MIXED_VIDEO_GRID_LEGEND_LABEL;
37370
- }
37371
- return MIXED_VIDEO_GRID_LEGEND_LABEL;
37403
+ return visibleWorkspaces.some(isVideoGridRecentFlowEnabled) ? VIDEO_GRID_LEGEND_LABEL : MAP_GRID_LEGEND_LABEL;
37372
37404
  };
37373
37405
  function getTrendArrowAndColor(trend) {
37374
37406
  if (trend > 0) {
@@ -37411,14 +37443,15 @@ var VideoCard = React144__default.memo(({
37411
37443
  const showOffline = Boolean(isStreamStale);
37412
37444
  const lastSeenText = lastSeenLabel || "Unknown";
37413
37445
  const workspaceDisplayName = displayName || workspace.displayName || workspace.workspace_name;
37414
- const videoGridMetricValue = getVideoGridMetricValue(workspace);
37446
+ const videoGridMetricValue = getVideoGridMetricValue(workspace, effectiveLegend);
37415
37447
  const videoGridDisplayValue = getVideoGridDisplayValue(workspace, effectiveLegend, displayMinuteBucket);
37416
37448
  const videoGridColorState = getVideoGridColorState(workspace, effectiveLegend);
37417
37449
  const isRecentFlowCard = isVideoGridRecentFlowEnabled(workspace);
37450
+ const isHighEfficiencyOverride = isHighEfficiencyRedFlowOverride(workspace, effectiveLegend);
37418
37451
  const hasDisplayMetric = typeof videoGridDisplayValue === "number" && Number.isFinite(videoGridDisplayValue);
37419
37452
  const hasBarMetric = typeof videoGridMetricValue === "number" && Number.isFinite(videoGridMetricValue);
37420
37453
  const shouldRenderMetricBadge = hasDisplayMetric;
37421
- const badgeTitle = hasVideoGridRecentFlow(workspace) ? `Flow ${Math.round(videoGridDisplayValue ?? 0)}%` : isRecentFlowCard ? "Flow unavailable" : `Efficiency ${Math.round(videoGridDisplayValue ?? 0)}%`;
37454
+ const badgeTitle = isHighEfficiencyOverride ? `Efficiency ${Math.round(videoGridDisplayValue ?? 0)}%` : hasVideoGridRecentFlow(workspace) ? `Flow ${Math.round(videoGridDisplayValue ?? 0)}%` : isRecentFlowCard ? "Flow unavailable" : `Efficiency ${Math.round(videoGridDisplayValue ?? 0)}%`;
37422
37455
  const badgeLabel = `${Math.round(videoGridDisplayValue ?? 0)}%`;
37423
37456
  const efficiencyOverlayClass = videoGridColorState === "green" ? "bg-[#00D654]/25" : videoGridColorState === "yellow" ? "bg-[#FFD700]/30" : videoGridColorState === "red" ? "bg-[#FF2D0A]/30" : "bg-transparent";
37424
37457
  const efficiencyBarClass = videoGridColorState === "green" ? "bg-[#00AB45]" : videoGridColorState === "yellow" ? "bg-[#FFB020]" : videoGridColorState === "red" ? "bg-[#E34329]" : "bg-gray-500/70";
@@ -43255,6 +43288,21 @@ var parseCycleTime = (value) => {
43255
43288
  var extractCycleTimeSeconds = (clip) => {
43256
43289
  return parseCycleTime(clip?.cycleTimeSeconds) ?? parseCycleTime(clip?.cycle_time_seconds) ?? parseCycleTime(clip?.duration) ?? parseCycleTime(clip?.original_task_metadata?.cycle_time) ?? null;
43257
43290
  };
43291
+ var formatDurationLabel = (seconds) => {
43292
+ if (typeof seconds !== "number" || !Number.isFinite(seconds) || seconds <= 0) {
43293
+ return null;
43294
+ }
43295
+ const roundedSeconds = Math.round(seconds);
43296
+ if (roundedSeconds < 60) {
43297
+ return `${roundedSeconds}s`;
43298
+ }
43299
+ const minutes = Math.floor(roundedSeconds / 60);
43300
+ const remainingSeconds = roundedSeconds % 60;
43301
+ if (minutes < 10) {
43302
+ return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
43303
+ }
43304
+ return `${Math.round(roundedSeconds / 60)} min`;
43305
+ };
43258
43306
  var getSeverityIcon = (severity, categoryId, cycleTimeSeconds, targetCycleTime, clipId) => {
43259
43307
  if (categoryId === "idle_time" || categoryId === "low_value" || categoryId === "longest-idles") {
43260
43308
  return null;
@@ -43330,7 +43378,9 @@ var FileManagerFilters = ({
43330
43378
  idleTimeVlmEnabled = false,
43331
43379
  showPercentileCycleFilters = true,
43332
43380
  prefetchedClipMetadata,
43333
- activeCategoryLoading
43381
+ activeCategoryLoading,
43382
+ idleClipSort = "latest",
43383
+ onIdleClipSortChange
43334
43384
  }) => {
43335
43385
  const [expandedNodes, setExpandedNodes] = useState(/* @__PURE__ */ new Set());
43336
43386
  const [startTime, setStartTime] = useState("");
@@ -43353,6 +43403,7 @@ var FileManagerFilters = ({
43353
43403
  const [localClipClassifications, setLocalClipClassifications] = useState({});
43354
43404
  const clipMetadataRef = useRef({});
43355
43405
  const inFlightMetadataRequestsRef = useRef(/* @__PURE__ */ new Set());
43406
+ const previousIdleClipSortRef = useRef(idleClipSort);
43356
43407
  const mergedClipClassifications = useMemo(() => ({
43357
43408
  ...clipClassifications || {},
43358
43409
  ...localClipClassifications
@@ -43360,6 +43411,36 @@ var FileManagerFilters = ({
43360
43411
  useEffect(() => {
43361
43412
  clipMetadataRef.current = clipMetadata;
43362
43413
  }, [clipMetadata]);
43414
+ useEffect(() => {
43415
+ if (previousIdleClipSortRef.current === idleClipSort) {
43416
+ return;
43417
+ }
43418
+ previousIdleClipSortRef.current = idleClipSort;
43419
+ setClipMetadata((prev) => {
43420
+ if (!prev.idle_time) {
43421
+ return prev;
43422
+ }
43423
+ const next = { ...prev };
43424
+ delete next.idle_time;
43425
+ return next;
43426
+ });
43427
+ setCategoryPages((prev) => {
43428
+ if (prev.idle_time === void 0) {
43429
+ return prev;
43430
+ }
43431
+ const next = { ...prev };
43432
+ delete next.idle_time;
43433
+ return next;
43434
+ });
43435
+ setCategoryHasMore((prev) => {
43436
+ if (prev.idle_time === void 0) {
43437
+ return prev;
43438
+ }
43439
+ const next = { ...prev };
43440
+ delete next.idle_time;
43441
+ return next;
43442
+ });
43443
+ }, [idleClipSort]);
43363
43444
  const isCategoryExternallyManaged = useCallback((categoryId) => {
43364
43445
  if (!categoryId) {
43365
43446
  return false;
@@ -43518,6 +43599,7 @@ var FileManagerFilters = ({
43518
43599
  return null;
43519
43600
  }
43520
43601
  }, [supabase]);
43602
+ const getMetadataLoadingKey = useCallback((categoryId, page) => `${categoryId}-${page}-${categoryId === "idle_time" ? idleClipSort : "latest"}`, [idleClipSort]);
43521
43603
  const fetchClipMetadataPage = useCallback(async (categoryId, page = 1) => {
43522
43604
  if (!workspaceId || !date || shift === void 0) {
43523
43605
  throw new Error("Missing required params for clip metadata fetch");
@@ -43537,7 +43619,8 @@ var FileManagerFilters = ({
43537
43619
  limit: CLIP_METADATA_PAGE_SIZE,
43538
43620
  knownTotal: typeof counts?.[categoryId] === "number" ? counts[categoryId] : null,
43539
43621
  snapshotDateTime,
43540
- snapshotClipId
43622
+ snapshotClipId,
43623
+ sort: categoryId === "idle_time" ? idleClipSort : "latest"
43541
43624
  }),
43542
43625
  redirectReason: "session_expired"
43543
43626
  });
@@ -43545,7 +43628,7 @@ var FileManagerFilters = ({
43545
43628
  throw new Error(`API error: ${response.status}`);
43546
43629
  }
43547
43630
  return response.json();
43548
- }, [workspaceId, date, shift, counts, snapshotDateTime, snapshotClipId, supabase]);
43631
+ }, [workspaceId, date, shift, counts, snapshotDateTime, snapshotClipId, idleClipSort, supabase]);
43549
43632
  const seedIdleClassifications = useCallback(async (clips) => {
43550
43633
  if (!idleTimeVlmEnabled || clips.length === 0) {
43551
43634
  return;
@@ -43601,7 +43684,7 @@ var FileManagerFilters = ({
43601
43684
  console.warn("[FileManager] Missing required params for clip metadata fetch");
43602
43685
  return;
43603
43686
  }
43604
- const loadingKey = `${categoryId}-${page}`;
43687
+ const loadingKey = getMetadataLoadingKey(categoryId, page);
43605
43688
  if (inFlightMetadataRequestsRef.current.has(loadingKey)) {
43606
43689
  return;
43607
43690
  }
@@ -43629,7 +43712,7 @@ var FileManagerFilters = ({
43629
43712
  return newSet;
43630
43713
  });
43631
43714
  }
43632
- }, [workspaceId, date, shift, fetchClipMetadataPage, idleTimeVlmEnabled, seedIdleClassifications]);
43715
+ }, [workspaceId, date, shift, fetchClipMetadataPage, idleTimeVlmEnabled, seedIdleClassifications, getMetadataLoadingKey]);
43633
43716
  const ensureAllIdleTimeClipMetadataLoaded = useCallback(async () => {
43634
43717
  if (!workspaceId || !date || shift === void 0) {
43635
43718
  return;
@@ -44003,15 +44086,17 @@ var FileManagerFilters = ({
44003
44086
  const colorClasses = getColorClasses(category.color);
44004
44087
  const clipNodes = filteredClips.map((clip, index) => {
44005
44088
  const cycleTime = extractCycleTimeSeconds(clip);
44089
+ const idleDuration = category.id === "idle_time" ? clip.idle_duration_seconds ?? clip.duration : null;
44090
+ const idleDurationLabel = formatDurationLabel(idleDuration);
44006
44091
  const baseTimeLabel = formatClipExplorerTimeLabel({
44007
44092
  categoryId: category.id,
44008
44093
  clipTimestamp: clip.clip_timestamp,
44009
44094
  timezone,
44010
- durationSeconds: clip.duration,
44095
+ durationSeconds: idleDuration ?? clip.duration,
44011
44096
  idleStartTime: clip.idle_start_time,
44012
44097
  idleEndTime: clip.idle_end_time
44013
44098
  });
44014
- const displayLabel = `${baseTimeLabel}${clip.duration && category.id !== "idle_time" && category.id !== "low_value" ? ` - (${clip.duration.toFixed(1)}s)` : ""}`;
44099
+ const displayLabel = `${baseTimeLabel}${idleDurationLabel && category.id === "idle_time" ? ` - (${idleDurationLabel})` : ""}${clip.duration && category.id !== "idle_time" && category.id !== "low_value" ? ` - (${clip.duration.toFixed(1)}s)` : ""}`;
44015
44100
  return {
44016
44101
  id: clip.id,
44017
44102
  label: displayLabel,
@@ -44025,7 +44110,7 @@ var FileManagerFilters = ({
44025
44110
  clipPosition: index + 1,
44026
44111
  // Store 1-based position
44027
44112
  cycleTimeSeconds: cycleTime,
44028
- duration: clip.duration,
44113
+ duration: idleDuration ?? clip.duration,
44029
44114
  // Store duration for custom badge rendering
44030
44115
  cycleItemCount: clip.cycle_item_count ?? null
44031
44116
  };
@@ -44347,11 +44432,11 @@ var FileManagerFilters = ({
44347
44432
  /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
44348
44433
  "Loading clips..."
44349
44434
  ] }) }),
44350
- loadingCategories.has(`${node.id}-${(categoryPages[node.id] || 0) + 1}`) && /* @__PURE__ */ jsx("div", { className: "py-2 px-3 text-center", children: /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center text-sm text-slate-500", children: [
44435
+ loadingCategories.has(getMetadataLoadingKey(node.id, (categoryPages[node.id] || 0) + 1)) && /* @__PURE__ */ jsx("div", { className: "py-2 px-3 text-center", children: /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center text-sm text-slate-500", children: [
44351
44436
  /* @__PURE__ */ jsx("div", { className: "animate-spin mr-2 h-4 w-4 border-2 border-slate-300 border-t-blue-500 rounded-full" }),
44352
44437
  "Loading more clips..."
44353
44438
  ] }) }),
44354
- categoryHasMore[node.id] && !loadingCategories.has(`${node.id}-${(categoryPages[node.id] || 0) + 1}`) && /* @__PURE__ */ jsxs(
44439
+ categoryHasMore[node.id] && !loadingCategories.has(getMetadataLoadingKey(node.id, (categoryPages[node.id] || 0) + 1)) && /* @__PURE__ */ jsxs(
44355
44440
  "button",
44356
44441
  {
44357
44442
  onClick: (e) => {
@@ -44378,6 +44463,18 @@ var FileManagerFilters = ({
44378
44463
  /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx("h2", { className: "text-lg font-bold text-slate-900 tracking-tight", children: "Clips Explorer" }) })
44379
44464
  ] }),
44380
44465
  /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
44466
+ activeFilter === "idle_time" && /* @__PURE__ */ jsx(
44467
+ "button",
44468
+ {
44469
+ onClick: () => {
44470
+ onIdleClipSortChange?.(idleClipSort === "latest" ? "idle_duration_desc" : "latest");
44471
+ },
44472
+ 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"}`,
44473
+ title: idleClipSort === "idle_duration_desc" ? "Sort by newest first" : "Sort by longest idle first",
44474
+ "aria-label": idleClipSort === "idle_duration_desc" ? "Sort idle clips by newest first" : "Sort idle clips by longest idle first",
44475
+ children: /* @__PURE__ */ jsx(ArrowDownWideNarrow, { className: "h-5 w-5" })
44476
+ }
44477
+ ),
44381
44478
  activeFilter === "idle_time" && idleTimeVlmEnabled && /* @__PURE__ */ jsx(
44382
44479
  "button",
44383
44480
  {
@@ -44398,8 +44495,8 @@ var FileManagerFilters = ({
44398
44495
  )
44399
44496
  ] })
44400
44497
  ] }),
44401
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 mt-3", children: [
44402
- isTimeFilterActive && startTime && endTime && /* @__PURE__ */ 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: [
44498
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [
44499
+ isTimeFilterActive && startTime && endTime && /* @__PURE__ */ 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: [
44403
44500
  /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
44404
44501
  "Time: ",
44405
44502
  getDisplayValue(startTime),
@@ -44415,13 +44512,13 @@ var FileManagerFilters = ({
44415
44512
  setEndTime("");
44416
44513
  setIsTimeFilterActive(false);
44417
44514
  },
44418
- className: "ml-2 hover:bg-blue-100 rounded p-0.5 transition-colors",
44515
+ className: "rounded-full p-0.5 transition-colors hover:bg-blue-100",
44419
44516
  title: "Clear time filter",
44420
44517
  children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
44421
44518
  }
44422
44519
  )
44423
44520
  ] }),
44424
- idleLabelFilter && activeFilter === "idle_time" && /* @__PURE__ */ 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: [
44521
+ idleLabelFilter && activeFilter === "idle_time" && /* @__PURE__ */ 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: [
44425
44522
  /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
44426
44523
  "Reason: ",
44427
44524
  selectedIdleReasonOption?.displayName || idleLabelFilter.replace(/_/g, " ")
@@ -44433,11 +44530,27 @@ var FileManagerFilters = ({
44433
44530
  e.stopPropagation();
44434
44531
  setIdleLabelFilter(null);
44435
44532
  },
44436
- className: "ml-2 hover:bg-purple-100 rounded p-0.5 transition-colors",
44533
+ className: "rounded-full p-0.5 transition-colors hover:bg-purple-100",
44437
44534
  title: "Clear label filter",
44438
44535
  children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
44439
44536
  }
44440
44537
  )
44538
+ ] }),
44539
+ activeFilter === "idle_time" && idleClipSort === "idle_duration_desc" && /* @__PURE__ */ 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: [
44540
+ /* @__PURE__ */ jsx(ArrowDownWideNarrow, { className: "h-3.5 w-3.5" }),
44541
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Longest idle first" }),
44542
+ /* @__PURE__ */ jsx(
44543
+ "button",
44544
+ {
44545
+ onClick: (e) => {
44546
+ e.stopPropagation();
44547
+ onIdleClipSortChange?.("latest");
44548
+ },
44549
+ className: "rounded-full p-0.5 transition-colors hover:bg-orange-100",
44550
+ title: "Clear idle sort",
44551
+ children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
44552
+ }
44553
+ )
44441
44554
  ] })
44442
44555
  ] })
44443
44556
  ] }),
@@ -45201,8 +45314,10 @@ var BottlenecksContent = ({
45201
45314
  const [clipClassifications, setClipClassifications] = useState({});
45202
45315
  const [categoryMetadata, setCategoryMetadata] = useState([]);
45203
45316
  const [categoryMetadataCategoryId, setCategoryMetadataCategoryId] = useState(null);
45317
+ const [categoryMetadataSort, setCategoryMetadataSort] = useState(null);
45204
45318
  const [currentMetadataIndex, setCurrentMetadataIndex] = useState(0);
45205
45319
  const [metadataCache, setMetadataCache] = useState({});
45320
+ const [idleClipSort, setIdleClipSort] = useState("latest");
45206
45321
  const invalidateMetadataCache = useCallback((categories) => {
45207
45322
  setMetadataCache((prevCache) => {
45208
45323
  if (!prevCache || Object.keys(prevCache).length === 0) {
@@ -45233,6 +45348,7 @@ var BottlenecksContent = ({
45233
45348
  const [isFullscreen, setIsFullscreen] = useState(false);
45234
45349
  const categoryMetadataRef = useRef([]);
45235
45350
  const currentMetadataIndexRef = useRef(0);
45351
+ const previousIdleClipSortRef = useRef(idleClipSort);
45236
45352
  const clearRetryTimeout = useCallback(() => {
45237
45353
  if (retryTimeoutRef.current) {
45238
45354
  clearTimeout(retryTimeoutRef.current);
@@ -45679,9 +45795,13 @@ var BottlenecksContent = ({
45679
45795
  }
45680
45796
  return ["fast-cycles", "slow-cycles", "longest-idles"].includes(categoryId);
45681
45797
  }, [isFastSlowClipFiltersEnabled]);
45798
+ const shouldUseMetadataNavigation = useCallback((categoryId) => {
45799
+ return isPercentileCategory(categoryId) || categoryId === "idle_time" && idleClipSort === "idle_duration_desc";
45800
+ }, [idleClipSort, isPercentileCategory]);
45682
45801
  const getMetadataCacheKey = useCallback((categoryId) => {
45683
- return `${categoryId}-${effectiveDateString}-${effectiveShiftId}-${snapshotDateTime ?? "nosnap"}-${snapshotClipId ?? "nosnap"}`;
45684
- }, [effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId]);
45802
+ const sortKey = categoryId === "idle_time" ? idleClipSort : "latest";
45803
+ return `${categoryId}-${effectiveDateString}-${effectiveShiftId}-${snapshotDateTime ?? "nosnap"}-${snapshotClipId ?? "nosnap"}-${sortKey}`;
45804
+ }, [effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, idleClipSort]);
45685
45805
  const setVisibleCategoryMetadata = useCallback((categoryId, clips) => {
45686
45806
  if (activeFilterRef.current !== categoryId) {
45687
45807
  return false;
@@ -45689,8 +45809,9 @@ var BottlenecksContent = ({
45689
45809
  categoryMetadataRef.current = clips;
45690
45810
  setCategoryMetadata(clips);
45691
45811
  setCategoryMetadataCategoryId(clips.length > 0 ? categoryId : null);
45812
+ setCategoryMetadataSort(clips.length > 0 ? categoryId === "idle_time" ? idleClipSort : "latest" : null);
45692
45813
  return true;
45693
- }, []);
45814
+ }, [idleClipSort]);
45694
45815
  const applyMetadataSnapshot = useCallback((categoryId, clips, total) => {
45695
45816
  if (!clips || clips.length === 0) {
45696
45817
  return;
@@ -45701,11 +45822,11 @@ var BottlenecksContent = ({
45701
45822
  [cacheKey]: clips
45702
45823
  }));
45703
45824
  setVisibleCategoryMetadata(categoryId, clips);
45704
- if (!isPercentileCategory(categoryId) && typeof total === "number") {
45825
+ if (!shouldUseMetadataNavigation(categoryId) && typeof total === "number") {
45705
45826
  currentTotalRef.current = total;
45706
45827
  setCurrentTotal(total);
45707
45828
  }
45708
- }, [getMetadataCacheKey, isPercentileCategory, setVisibleCategoryMetadata]);
45829
+ }, [getMetadataCacheKey, shouldUseMetadataNavigation, setVisibleCategoryMetadata]);
45709
45830
  const getClipTypesForPercentileCategory = useCallback((categoryId) => {
45710
45831
  switch (categoryId) {
45711
45832
  case "fast-cycles":
@@ -45731,6 +45852,7 @@ var BottlenecksContent = ({
45731
45852
  }
45732
45853
  setCategoryMetadata([]);
45733
45854
  setCategoryMetadataCategoryId(null);
45855
+ setCategoryMetadataSort(null);
45734
45856
  categoryMetadataRef.current = [];
45735
45857
  updateActiveFilter(fallbackFilter);
45736
45858
  }, [isFastSlowClipFiltersEnabled, activeFilter, dynamicCounts, clipTypes, updateActiveFilter]);
@@ -45778,6 +45900,7 @@ var BottlenecksContent = ({
45778
45900
  if (!isFastSlowClipFiltersEnabled && (categoryId === "fast-cycles" || categoryId === "slow-cycles")) {
45779
45901
  setCategoryMetadata([]);
45780
45902
  setCategoryMetadataCategoryId(null);
45903
+ setCategoryMetadataSort(null);
45781
45904
  categoryMetadataRef.current = [];
45782
45905
  return;
45783
45906
  }
@@ -45848,7 +45971,8 @@ var BottlenecksContent = ({
45848
45971
  limit: 100,
45849
45972
  knownTotal: mergedCounts[categoryId] ?? null,
45850
45973
  snapshotDateTime,
45851
- snapshotClipId
45974
+ snapshotClipId,
45975
+ sort: categoryId === "idle_time" ? idleClipSort : "latest"
45852
45976
  }),
45853
45977
  redirectReason: "session_expired"
45854
45978
  });
@@ -45927,6 +46051,7 @@ var BottlenecksContent = ({
45927
46051
  if (activeFilterRef.current === categoryId) {
45928
46052
  setCategoryMetadata([]);
45929
46053
  setCategoryMetadataCategoryId(null);
46054
+ setCategoryMetadataSort(null);
45930
46055
  categoryMetadataRef.current = [];
45931
46056
  }
45932
46057
  }
@@ -45935,7 +46060,26 @@ var BottlenecksContent = ({
45935
46060
  } finally {
45936
46061
  setIsCategoryLoading(false);
45937
46062
  }
45938
- }, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, supabase, setVisibleCategoryMetadata]);
46063
+ }, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, idleClipSort, supabase, setVisibleCategoryMetadata]);
46064
+ useEffect(() => {
46065
+ if (previousIdleClipSortRef.current === idleClipSort) {
46066
+ return;
46067
+ }
46068
+ previousIdleClipSortRef.current = idleClipSort;
46069
+ if (activeFilterRef.current !== "idle_time") {
46070
+ return;
46071
+ }
46072
+ setCategoryMetadata([]);
46073
+ setCategoryMetadataCategoryId(null);
46074
+ setCategoryMetadataSort(null);
46075
+ categoryMetadataRef.current = [];
46076
+ setCurrentMetadataIndex(0);
46077
+ currentMetadataIndexRef.current = 0;
46078
+ setCurrentPosition(0);
46079
+ currentPositionRef.current = 0;
46080
+ setIsCategoryLoading(true);
46081
+ void loadCategoryMetadata("idle_time", true, true);
46082
+ }, [idleClipSort, loadCategoryMetadata]);
45939
46083
  useEffect(() => {
45940
46084
  if (previousFilterRef.current !== activeFilter) {
45941
46085
  console.log(`Filter changed from ${previousFilterRef.current} to ${activeFilter} - resetting to first video`);
@@ -45946,6 +46090,7 @@ var BottlenecksContent = ({
45946
46090
  loadingCategoryRef.current = null;
45947
46091
  setCategoryMetadata([]);
45948
46092
  setCategoryMetadataCategoryId(null);
46093
+ setCategoryMetadataSort(null);
45949
46094
  setCurrentMetadataIndex(0);
45950
46095
  categoryMetadataRef.current = [];
45951
46096
  currentMetadataIndexRef.current = 0;
@@ -46044,7 +46189,7 @@ var BottlenecksContent = ({
46044
46189
  }
46045
46190
  if (metadataArray.length === 0) {
46046
46191
  console.warn(`[BottlenecksContent] No metadata available for category ${categoryId} after refresh`);
46047
- if (!isPercentileCategory(categoryId)) {
46192
+ if (!shouldUseMetadataNavigation(categoryId)) {
46048
46193
  const resolvedPosition = typeof position === "number" ? position : 1;
46049
46194
  currentPositionRef.current = resolvedPosition;
46050
46195
  setCurrentPosition(resolvedPosition);
@@ -46057,7 +46202,7 @@ var BottlenecksContent = ({
46057
46202
  const clickedClipIndex = metadataArray.findIndex((clip) => clip.clipId === clipId);
46058
46203
  if (clickedClipIndex === -1) {
46059
46204
  console.warn(`[BottlenecksContent] Clip ${clipId} not found after metadata refresh`);
46060
- if (!isPercentileCategory(categoryId)) {
46205
+ if (!shouldUseMetadataNavigation(categoryId)) {
46061
46206
  const resolvedPosition = typeof position === "number" ? position : 1;
46062
46207
  currentPositionRef.current = resolvedPosition;
46063
46208
  setCurrentPosition(resolvedPosition);
@@ -46069,7 +46214,7 @@ var BottlenecksContent = ({
46069
46214
  }
46070
46215
  setCurrentMetadataIndex(clickedClipIndex);
46071
46216
  currentMetadataIndexRef.current = clickedClipIndex;
46072
- if (!isPercentileCategory(categoryId)) {
46217
+ if (!shouldUseMetadataNavigation(categoryId)) {
46073
46218
  const position2 = clickedClipIndex + 1;
46074
46219
  currentPositionRef.current = position2;
46075
46220
  setCurrentPosition(position2);
@@ -46099,7 +46244,7 @@ var BottlenecksContent = ({
46099
46244
  clearLoadingState();
46100
46245
  }
46101
46246
  }
46102
- }, [workspaceId, s3ClipsService, updateActiveFilter, clearLoadingState, clearRetryTimeout, loadCategoryMetadata, applyMetadataSnapshot, mergedCounts, isPercentileCategory]);
46247
+ }, [workspaceId, s3ClipsService, updateActiveFilter, clearLoadingState, clearRetryTimeout, loadCategoryMetadata, applyMetadataSnapshot, mergedCounts, shouldUseMetadataNavigation]);
46103
46248
  const restartCurrentClipPlayback = useCallback(() => {
46104
46249
  if (!currentClipId) {
46105
46250
  return;
@@ -46120,7 +46265,7 @@ var BottlenecksContent = ({
46120
46265
  return;
46121
46266
  }
46122
46267
  const activeCategory = activeFilterRef.current;
46123
- if (!activeCategory || activeCategory === "all" || isPercentileCategory(activeCategory)) {
46268
+ if (!activeCategory || activeCategory === "all" || shouldUseMetadataNavigation(activeCategory)) {
46124
46269
  return;
46125
46270
  }
46126
46271
  let cancelled = false;
@@ -46153,7 +46298,7 @@ var BottlenecksContent = ({
46153
46298
  }, [
46154
46299
  newClipsNotification,
46155
46300
  s3ClipsService,
46156
- isPercentileCategory,
46301
+ shouldUseMetadataNavigation,
46157
46302
  currentClipId,
46158
46303
  invalidateMetadataCache,
46159
46304
  loadAndPlayClipById,
@@ -46205,7 +46350,7 @@ var BottlenecksContent = ({
46205
46350
  }
46206
46351
  }
46207
46352
  try {
46208
- if (!isPercentileCategory(currentFilter)) {
46353
+ if (!shouldUseMetadataNavigation(currentFilter)) {
46209
46354
  if (!s3ClipsService || !workspaceId || !currentClipId) {
46210
46355
  throw new Error("S3 clips service not available");
46211
46356
  }
@@ -46305,7 +46450,7 @@ var BottlenecksContent = ({
46305
46450
  } else {
46306
46451
  const firstClipMeta = metadataArray[0];
46307
46452
  if (firstClipMeta?.clipId && firstClipMeta.clipId !== currentClipId) {
46308
- console.log(`[handleNext] Reached end of ${currentFilter}, looping back to newest percentile clip ${firstClipMeta.clipId}`);
46453
+ console.log(`[handleNext] Reached end of ${currentFilter}, looping back to first metadata clip ${firstClipMeta.clipId}`);
46309
46454
  await loadAndPlayClipById(firstClipMeta.clipId, currentFilter, 1, {
46310
46455
  clips: metadataArray,
46311
46456
  total: metadataArray.length
@@ -46331,7 +46476,7 @@ var BottlenecksContent = ({
46331
46476
  });
46332
46477
  clearLoadingState();
46333
46478
  }
46334
- }, [clearLoadingState, clearRetryTimeout, s3ClipsService, loadCategoryMetadata, loadAndPlayClipById, isPercentileCategory, workspaceId, currentClipId, effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, mergedCounts]);
46479
+ }, [clearLoadingState, clearRetryTimeout, s3ClipsService, loadCategoryMetadata, loadAndPlayClipById, shouldUseMetadataNavigation, workspaceId, currentClipId, effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, mergedCounts]);
46335
46480
  const handlePrevious = useCallback(async () => {
46336
46481
  if (!isMountedRef.current || navigationLockRef.current) return;
46337
46482
  const currentFilter = activeFilterRef.current;
@@ -46350,7 +46495,7 @@ var BottlenecksContent = ({
46350
46495
  }
46351
46496
  }
46352
46497
  try {
46353
- if (!isPercentileCategory(currentFilter)) {
46498
+ if (!shouldUseMetadataNavigation(currentFilter)) {
46354
46499
  if (!s3ClipsService || !workspaceId || !currentClipId) {
46355
46500
  throw new Error("S3 clips service not available");
46356
46501
  }
@@ -46435,7 +46580,7 @@ var BottlenecksContent = ({
46435
46580
  });
46436
46581
  clearLoadingState();
46437
46582
  }
46438
- }, [clearLoadingState, clearRetryTimeout, s3ClipsService, loadCategoryMetadata, isPercentileCategory, workspaceId, currentClipId, effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, mergedCounts]);
46583
+ }, [clearLoadingState, clearRetryTimeout, s3ClipsService, loadCategoryMetadata, shouldUseMetadataNavigation, workspaceId, currentClipId, effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, mergedCounts]);
46439
46584
  const currentVideo = useMemo(() => {
46440
46585
  if (!filteredVideos || filteredVideos.length === 0 || currentIndex >= filteredVideos.length) {
46441
46586
  return null;
@@ -46502,22 +46647,22 @@ var BottlenecksContent = ({
46502
46647
  }
46503
46648
  }, [currentVideo?.id, isShareLoading, supabase, workspaceId, workspaceName]);
46504
46649
  useMemo(() => {
46505
- if (isPercentileCategory(activeFilter)) {
46650
+ if (shouldUseMetadataNavigation(activeFilter)) {
46506
46651
  return categoryMetadata.length;
46507
46652
  }
46508
46653
  return currentTotal || mergedCounts[activeFilter] || 0;
46509
- }, [activeFilter, categoryMetadata.length, currentTotal, mergedCounts, isPercentileCategory]);
46654
+ }, [activeFilter, categoryMetadata.length, currentTotal, mergedCounts, shouldUseMetadataNavigation]);
46510
46655
  useMemo(() => {
46511
- if (isPercentileCategory(activeFilter)) {
46656
+ if (shouldUseMetadataNavigation(activeFilter)) {
46512
46657
  return categoryMetadata.length > 0 ? currentMetadataIndex + 1 : 0;
46513
46658
  }
46514
46659
  return currentPosition;
46515
- }, [activeFilter, categoryMetadata.length, currentMetadataIndex, currentPosition, isPercentileCategory]);
46516
- const prefetchedExplorerMetadata = useMemo(() => buildPrefetchedExplorerMetadata(
46660
+ }, [activeFilter, categoryMetadata.length, currentMetadataIndex, currentPosition, shouldUseMetadataNavigation]);
46661
+ const prefetchedExplorerMetadata = useMemo(() => activeFilter === "idle_time" && categoryMetadataSort !== idleClipSort ? void 0 : buildPrefetchedExplorerMetadata(
46517
46662
  activeFilter,
46518
46663
  categoryMetadataCategoryId,
46519
46664
  categoryMetadata
46520
- ), [activeFilter, categoryMetadata, categoryMetadataCategoryId]);
46665
+ ), [activeFilter, categoryMetadata, categoryMetadataCategoryId, categoryMetadataSort, idleClipSort]);
46521
46666
  const classificationClipIds = useMemo(() => {
46522
46667
  if (!idleTimeVlmEnabled) {
46523
46668
  return [];
@@ -47266,7 +47411,12 @@ var BottlenecksContent = ({
47266
47411
  showPercentileCycleFilters: isFastSlowClipFiltersEnabled,
47267
47412
  prefetchedClipMetadata: prefetchedExplorerMetadata,
47268
47413
  activeCategoryLoading: isCategoryLoading,
47414
+ idleClipSort,
47415
+ onIdleClipSortChange: setIdleClipSort,
47269
47416
  onFilterChange: (filterId) => {
47417
+ if (filterId !== "idle_time") {
47418
+ setIdleClipSort("latest");
47419
+ }
47270
47420
  updateActiveFilter(filterId);
47271
47421
  const category = categoriesToShow.find((cat) => cat.type === filterId);
47272
47422
  if (category) {
@@ -49189,6 +49339,11 @@ var LineHistoryCalendar = ({
49189
49339
  return calendar;
49190
49340
  }, [data, month, year, configuredTimezone]);
49191
49341
  const hasRealData = (shift) => {
49342
+ if (isUptimeMode) {
49343
+ if (shift.hasData === true) return true;
49344
+ const efficiency = Number(shift.avg_efficiency);
49345
+ 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;
49346
+ }
49192
49347
  if (shift.hasData !== void 0) return shift.hasData;
49193
49348
  return shift.total_workspaces > 0 || shift.avg_efficiency > 0 || shift.underperforming_workspaces > 0;
49194
49349
  };
@@ -49821,13 +49976,18 @@ var LineMonthlyHistory = ({
49821
49976
  enabled: !!lineId && idleTimeVlmEnabled
49822
49977
  });
49823
49978
  const hasRealData = (shift) => {
49979
+ if (isUptimeMode) {
49980
+ if (shift.hasData === true) return true;
49981
+ const efficiency = Number(shift.avg_efficiency);
49982
+ 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;
49983
+ }
49824
49984
  if (shift.hasData !== void 0) return shift.hasData;
49825
49985
  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;
49826
49986
  };
49827
49987
  const averages = (analysisMonthlyData || []).reduce(
49828
49988
  (acc, day) => {
49829
49989
  const shiftData = getShiftData2(day, selectedShiftId);
49830
- if (!shiftData || shiftData?.avg_efficiency < 5) {
49990
+ if (!shiftData || !isValidAggregateEfficiency(isUptimeMode ? "uptime" : "output", shiftData.avg_efficiency)) {
49831
49991
  return acc;
49832
49992
  }
49833
49993
  return {
@@ -49856,7 +50016,9 @@ var LineMonthlyHistory = ({
49856
50016
  const avgOutput = outputAverages.count > 0 ? outputAverages.output / outputAverages.count : 0;
49857
50017
  const uptimeSummary = useMemo(() => {
49858
50018
  if (!isUptimeMode) return null;
49859
- const validDays = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter((shiftData) => shiftData && hasRealData(shiftData)).map((shiftData) => ({ shiftData, totals: getUptimeTotals(shiftData) }));
50019
+ const validDays = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter(
50020
+ (shiftData) => shiftData && hasRealData(shiftData) && isValidAggregateEfficiency("uptime", shiftData.avg_efficiency)
50021
+ ).map((shiftData) => ({ shiftData, totals: getUptimeTotals(shiftData) }));
49860
50022
  if (!validDays.length) {
49861
50023
  return { avgUtilization: 0, avgIdleTime: 0, avgDailyStoppages: 0 };
49862
50024
  }
@@ -50004,7 +50166,9 @@ var LineMonthlyHistory = ({
50004
50166
  }, [chartData.yAxisMax, chartData.lastSetTarget]);
50005
50167
  const pieChartData = useMemo(() => {
50006
50168
  if (!isUptimeMode) return [];
50007
- const validShifts = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter(hasRealData);
50169
+ const validShifts = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter(
50170
+ (shift) => shift && hasRealData(shift) && isValidAggregateEfficiency("uptime", shift.avg_efficiency)
50171
+ );
50008
50172
  if (!validShifts.length) return [];
50009
50173
  const efficiencyValues = validShifts.map((shift) => Number.isFinite(shift.avg_efficiency) ? Number(shift.avg_efficiency) : null).filter((value) => value !== null);
50010
50174
  if (!efficiencyValues.length) return [];
@@ -50614,7 +50778,9 @@ var LineMonthlyPdfGenerator = ({
50614
50778
  const productiveSeconds = activeSecondsRaw > 0 ? Math.min(activeSecondsRaw, availableSeconds) : Math.max(availableSeconds - idleSeconds, 0);
50615
50779
  return { availableSeconds, productiveSeconds, idleSeconds };
50616
50780
  };
50617
- const validShifts = validDays.map((day) => getLineShiftData2(day, selectedShiftId)).filter((shift) => isUptimeMode ? hasShiftData(shift) : shift.avg_efficiency >= 5);
50781
+ const validShifts = validDays.map((day) => getLineShiftData2(day, selectedShiftId)).filter(
50782
+ (shift) => hasShiftData(shift) && isValidAggregateEfficiency(isUptimeMode ? "uptime" : "output", shift.avg_efficiency)
50783
+ );
50618
50784
  const monthlyMetrics = validShifts.length > 0 ? isUptimeMode ? (() => {
50619
50785
  let utilizationSum = 0;
50620
50786
  let idleTimeSum = 0;
@@ -52599,7 +52765,10 @@ var WorkspaceMonthlyHistory = ({
52599
52765
  return ticks.filter((v) => v >= 0 && v <= max * 1.05).sort((a, b) => a - b);
52600
52766
  }, [chartData.yAxisMax, chartData.lastSetTarget, isUptimeMode]);
52601
52767
  const pieChartData = useMemo(() => {
52602
- const validShifts = analysisMonthlyData.map((d) => getShiftData(d, selectedShiftId)).filter(hasRealData);
52768
+ const aggregateMode = isUptimeMode ? "uptime" : "output";
52769
+ const validShifts = analysisMonthlyData.map((d) => getShiftData(d, selectedShiftId)).filter(
52770
+ (shift) => shift && hasRealData(shift) && isValidAggregateEfficiency(aggregateMode, shift.efficiency)
52771
+ );
52603
52772
  if (validShifts.length === 0) return [];
52604
52773
  const efficiencyValues = validShifts.map((shift) => Number.isFinite(shift.efficiency) ? Number(shift.efficiency) : null).filter((value) => value !== null);
52605
52774
  if (!efficiencyValues.length) return [];
@@ -52610,10 +52779,10 @@ var WorkspaceMonthlyHistory = ({
52610
52779
  { name: "Productive", value: productivePercent },
52611
52780
  { name: "Idle", value: idlePercent }
52612
52781
  ];
52613
- }, [analysisMonthlyData, selectedShiftId, shiftWorkSeconds]);
52782
+ }, [analysisMonthlyData, selectedShiftId, isUptimeMode]);
52614
52783
  const metrics2 = useMemo(() => {
52615
52784
  const validShifts = analysisMonthlyData.map((d) => getShiftData(d, selectedShiftId)).filter(hasRealData);
52616
- const filteredShifts = isUptimeMode ? validShifts : validShifts.filter((shift) => (shift.efficiency ?? 0) >= 5);
52785
+ const filteredShifts = isUptimeMode ? validShifts.filter((shift) => isValidAggregateEfficiency("uptime", shift.efficiency)) : validShifts.filter((shift) => isValidAggregateEfficiency("output", shift.efficiency));
52617
52786
  if (filteredShifts.length === 0) return null;
52618
52787
  const totalEfficiency = filteredShifts.reduce((sum, shift) => sum + (shift.efficiency || 0), 0);
52619
52788
  const totalUtilization = filteredShifts.reduce(
@@ -53833,7 +54002,7 @@ var WorkspaceMonthlyPdfGenerator = ({
53833
54002
  const shift = getShiftData(dayData, selectedShiftId);
53834
54003
  return { dayData, shift };
53835
54004
  }).filter(({ shift }) => hasShiftData(shift)).sort((left, right) => getDayDateKey(right.dayData).localeCompare(getDayDateKey(left.dayData)));
53836
- const filteredShifts = isUptimeMode ? validShifts : validShifts.filter((shift) => (shift.efficiency ?? 0) >= 5);
54005
+ const filteredShifts = isUptimeMode ? validShifts.filter((shift) => isValidAggregateEfficiency("uptime", shift.efficiency)) : validShifts.filter((shift) => isValidAggregateEfficiency("output", shift.efficiency));
53837
54006
  const monthlyMetrics = filteredShifts.length > 0 ? isUptimeMode ? (() => {
53838
54007
  const totalIdleTime = filteredShifts.reduce((sum, shift) => sum + shift.idleTime, 0);
53839
54008
  const totalCycleTime = filteredShifts.reduce((sum, shift) => sum + shift.cycleTime, 0);
@@ -65187,6 +65356,7 @@ var buildLineInfoSnapshot = (lineDetails, metrics2) => {
65187
65356
  output_hourly: metrics2.output_hourly,
65188
65357
  hourly_target_output: metrics2.hourly_target_output,
65189
65358
  line_threshold: metrics2.line_threshold ?? 0,
65359
+ output_target_recalculated: metrics2.output_target_recalculated ?? null,
65190
65360
  threshold_pph: metrics2.threshold_pph ?? 0,
65191
65361
  shift_start: metrics2.shift_start || "06:00",
65192
65362
  shift_end: metrics2.shift_end || "14:00",
@@ -65274,6 +65444,7 @@ var transformLineMetrics = (lineId, detailResponse, queryDate, queryShiftId) =>
65274
65444
  output_array: [],
65275
65445
  hourly_target_output: void 0,
65276
65446
  line_threshold: 0,
65447
+ output_target_recalculated: null,
65277
65448
  threshold_pph: 0,
65278
65449
  shift_start: "06:00",
65279
65450
  shift_end: "14:00",
@@ -66111,6 +66282,7 @@ var MetricCards = memo$1(({
66111
66282
  issueResolutionSummary?.mean_resolution_seconds ?? issueResolutionSummary?.median_resolution_seconds
66112
66283
  );
66113
66284
  getIssueResolutionSecondaryText(issueResolutionSummary);
66285
+ const outputTarget = lineInfo?.metrics.output_target_recalculated ?? lineInfo?.metrics.line_threshold ?? 0;
66114
66286
  return /* @__PURE__ */ jsxs(
66115
66287
  motion.div,
66116
66288
  {
@@ -66125,7 +66297,7 @@ var MetricCards = memo$1(({
66125
66297
  OutputProgressChart,
66126
66298
  {
66127
66299
  currentOutput: lineInfo?.metrics.current_output || 0,
66128
- targetOutput: lineInfo?.metrics.line_threshold || 0,
66300
+ targetOutput: outputTarget,
66129
66301
  skuBreakdown: skuAware ? skuBreakdown : void 0,
66130
66302
  selectedSkuId,
66131
66303
  onSelectSku,
@@ -66249,7 +66421,7 @@ var MetricCards = memo$1(({
66249
66421
  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) {
66250
66422
  return false;
66251
66423
  }
66252
- 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;
66424
+ 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;
66253
66425
  });
66254
66426
  MetricCards.displayName = "MetricCards";
66255
66427
  var LineUptimeMetricCards = memo$1(({
@@ -67002,7 +67174,15 @@ var KPIDetailView = ({
67002
67174
  const fallbackTimes = resolveMonthlyShiftTimes(metric.shift_id);
67003
67175
  const resolvedShiftStart = metric.shift_start || fallbackTimes.start;
67004
67176
  const resolvedShiftEnd = metric.shift_end || fallbackTimes.end;
67005
- const hasBackendUptimeSeconds = isUptimeMode && (Number.isFinite(metric.active_time_seconds) || Number.isFinite(metric.idle_time_seconds) || Number.isFinite(metric.available_time_seconds));
67177
+ const coerceOptionalNumber2 = (value) => {
67178
+ if (value === void 0 || value === null || value === "") return null;
67179
+ const parsed = Number(value);
67180
+ return Number.isFinite(parsed) ? parsed : null;
67181
+ };
67182
+ const metricActiveTimeSeconds = coerceOptionalNumber2(metric.active_time_seconds);
67183
+ const metricIdleTimeSeconds = coerceOptionalNumber2(metric.idle_time_seconds);
67184
+ const metricAvailableTimeSeconds = coerceOptionalNumber2(metric.available_time_seconds);
67185
+ const hasBackendUptimeSeconds = isUptimeMode && (metricActiveTimeSeconds !== null || metricIdleTimeSeconds !== null || metricAvailableTimeSeconds !== null);
67006
67186
  const uptimeSeries2 = isUptimeMode && !hasBackendUptimeSeconds ? buildUptimeSeries({
67007
67187
  idleTimeHourly: metric.idle_time_hourly || {},
67008
67188
  shiftStart: resolvedShiftStart || void 0,
@@ -67010,9 +67190,13 @@ var KPIDetailView = ({
67010
67190
  shiftDate: metric.date,
67011
67191
  timezone: configuredTimezone
67012
67192
  }) : null;
67013
- const idleTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metric.idle_time_seconds || 0 : (uptimeSeries2?.idleMinutes || 0) * 60 : 0;
67014
- const activeTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metric.active_time_seconds || 0 : (uptimeSeries2?.activeMinutes || 0) * 60 : 0;
67015
- const availableTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metric.available_time_seconds || activeTimeSeconds + idleTimeSeconds : (uptimeSeries2?.availableMinutes || 0) * 60 : 0;
67193
+ const idleTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metricIdleTimeSeconds ?? 0 : (uptimeSeries2?.idleMinutes || 0) * 60 : 0;
67194
+ const activeTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metricActiveTimeSeconds ?? 0 : (uptimeSeries2?.activeMinutes || 0) * 60 : 0;
67195
+ const availableTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metricAvailableTimeSeconds ?? activeTimeSeconds + idleTimeSeconds : (uptimeSeries2?.availableMinutes || 0) * 60 : 0;
67196
+ const metricAvgEfficiency = Number(metric.avg_efficiency);
67197
+ const metricTotalWorkspaces = Number(metric.total_workspaces || 0);
67198
+ const metricCurrentOutput = Number(metric.current_output || 0);
67199
+ const hasUptimeMetricData = isUptimeMode && (availableTimeSeconds > 0 || metricTotalWorkspaces > 0 || metricCurrentOutput > 0 || Number.isFinite(metricAvgEfficiency) && metricAvgEfficiency > 0);
67016
67200
  const computedUptimeEfficiency = (() => {
67017
67201
  const availableMinutes = availableTimeSeconds / 60;
67018
67202
  if (!availableMinutes || availableMinutes <= 0) return 0;
@@ -67032,7 +67216,7 @@ var KPIDetailView = ({
67032
67216
  targetOutput: Number(metric.line_threshold ?? metric.ideal_output ?? 0),
67033
67217
  compliance_percentage: 95 + Math.random() * 5,
67034
67218
  // Mock data: random value between 95-100%
67035
- hasData: isUptimeMode ? availableTimeSeconds > 0 : true,
67219
+ hasData: isUptimeMode ? hasUptimeMetricData : true,
67036
67220
  idle_time_seconds: idleTimeSeconds,
67037
67221
  active_time_seconds: activeTimeSeconds,
67038
67222
  available_time_seconds: availableTimeSeconds,
@@ -67117,6 +67301,7 @@ var KPIDetailView = ({
67117
67301
  output_hourly: metrics2.output_hourly,
67118
67302
  hourly_target_output: metrics2.hourly_target_output,
67119
67303
  line_threshold: metrics2.line_threshold ?? 0,
67304
+ output_target_recalculated: metrics2.output_target_recalculated ?? null,
67120
67305
  threshold_pph: metrics2.threshold_pph ?? 0,
67121
67306
  shift_start: metrics2.shift_start || "06:00",
67122
67307
  shift_end: metrics2.shift_end || "14:00",
@@ -67191,15 +67376,16 @@ var KPIDetailView = ({
67191
67376
  [lineSkuBreakdown]
67192
67377
  );
67193
67378
  const outputChartSkuBreakdown = useMemo(
67194
- () => realSkuOptions.filter(
67195
- (item) => (item.current_output ?? 0) > 0 || (item.ideal_output ?? 0) > 0
67196
- ).map((item) => ({
67379
+ () => realSkuOptions.filter((item) => {
67380
+ const targetOutput = item.output_target_recalculated ?? item.line_threshold_recalculated ?? item.ideal_output ?? 0;
67381
+ return (item.current_output ?? 0) > 0 || targetOutput > 0;
67382
+ }).map((item) => ({
67197
67383
  sku_id: item.sku_id,
67198
67384
  sku_code: item.sku_code,
67199
67385
  sku_definition: "",
67200
67386
  is_dummy: false,
67201
67387
  total_output: item.current_output ?? 0,
67202
- target_output: item.ideal_output ?? 0,
67388
+ target_output: item.output_target_recalculated ?? item.line_threshold_recalculated ?? item.ideal_output ?? 0,
67203
67389
  avg_pph: 0,
67204
67390
  pph_threshold: 0,
67205
67391
  avg_cycle_time: 0,
@@ -67253,7 +67439,8 @@ var KPIDetailView = ({
67253
67439
  underperforming_workspaces: selectedSkuRow.underperforming_workspaces ?? resolvedLineInfo.metrics.underperforming_workspaces,
67254
67440
  underperforming_workspace_names: selectedSkuRow.underperforming_workspace_names ?? resolvedLineInfo.metrics.underperforming_workspace_names,
67255
67441
  underperforming_workspace_uuids: selectedSkuRow.underperforming_workspace_uuids ?? resolvedLineInfo.metrics.underperforming_workspace_uuids,
67256
- line_threshold: selectedSkuRow.line_threshold ?? resolvedLineInfo.metrics.line_threshold
67442
+ line_threshold: selectedSkuRow.line_threshold ?? resolvedLineInfo.metrics.line_threshold,
67443
+ output_target_recalculated: selectedSkuRow.output_target_recalculated ?? selectedSkuRow.line_threshold_recalculated ?? resolvedLineInfo.metrics.output_target_recalculated ?? null
67257
67444
  }
67258
67445
  };
67259
67446
  }, [resolvedLineInfo, selectedSkuRow]);