@optifye/dashboard-core 6.12.5 → 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';
@@ -21873,6 +21873,24 @@ var getConfigurableShortWorkspaceDisplayName = (workspaceId, workspaceConfig, li
21873
21873
  return fullName;
21874
21874
  };
21875
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
+
21876
21894
  // src/lib/utils/kpis.ts
21877
21895
  var toNumber = (value) => {
21878
21896
  if (typeof value === "number" && Number.isFinite(value)) return value;
@@ -21928,7 +21946,9 @@ var buildKPIsFromLineMetricsRow = (row) => {
21928
21946
  };
21929
21947
  var aggregateKPIsFromLineMetricsRows = (rows) => {
21930
21948
  if (!rows || rows.length === 0) return createDefaultKPIs();
21931
- 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
+ );
21932
21952
  if (eligibleRows.length === 0) return createDefaultKPIs();
21933
21953
  const currentOutputSum = eligibleRows.reduce((sum, row) => sum + toNumber(row.current_output), 0);
21934
21954
  const lineThresholdSum = eligibleRows.reduce(
@@ -37256,8 +37276,8 @@ var HourlyOutputChart = React144__default.memo(
37256
37276
  HourlyOutputChart.displayName = "HourlyOutputChart";
37257
37277
 
37258
37278
  // src/components/dashboard/grid/videoGridMetricUtils.ts
37279
+ var VIDEO_GRID_LEGEND_LABEL = "Real-Time efficiency";
37259
37280
  var MAP_GRID_LEGEND_LABEL = "Efficiency";
37260
- var MIXED_VIDEO_GRID_LEGEND_LABEL = "Live Efficiency";
37261
37281
  var isFiniteNumber2 = (value) => typeof value === "number" && Number.isFinite(value);
37262
37282
  var isVideoGridRecentFlowEnabled = (workspace) => isRecentFlowVideoGridMetricMode(
37263
37283
  workspace.video_grid_metric_mode,
@@ -37269,7 +37289,7 @@ var isVideoGridWipGated = (workspace) => isWipGatedVideoGridMetricMode(
37269
37289
  );
37270
37290
  var hasVideoGridRecentFlow = (workspace) => isVideoGridRecentFlowEnabled(workspace) && isFiniteNumber2(workspace.recent_flow_percent);
37271
37291
  var isVideoGridRecentFlowUnavailable = (workspace) => isVideoGridRecentFlowEnabled(workspace) && !hasVideoGridRecentFlow(workspace);
37272
- var getVideoGridMetricValue = (workspace) => {
37292
+ var getRawVideoGridMetricValue = (workspace) => {
37273
37293
  const recentFlowPercent = workspace.recent_flow_percent;
37274
37294
  if (hasVideoGridRecentFlow(workspace) && isFiniteNumber2(recentFlowPercent)) {
37275
37295
  return recentFlowPercent;
@@ -37281,7 +37301,7 @@ var getVideoGridMetricValue = (workspace) => {
37281
37301
  };
37282
37302
  var hasIncomingWipMapping = (workspace) => Boolean(workspace.incoming_wip_buffer_name);
37283
37303
  var getVideoGridBaseColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37284
- const metricValue = getVideoGridMetricValue(workspace);
37304
+ const metricValue = getRawVideoGridMetricValue(workspace);
37285
37305
  if (!isFiniteNumber2(metricValue)) {
37286
37306
  return "neutral";
37287
37307
  }
@@ -37305,6 +37325,25 @@ var isLowWipGreenOverride = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37305
37325
  }
37306
37326
  return isFiniteNumber2(workspace.incoming_wip_current) && workspace.incoming_wip_current <= 1;
37307
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);
37308
37347
  var toMinuteBucket = (minuteBucket) => Number.isFinite(minuteBucket) ? Math.floor(minuteBucket) : Math.floor(Date.now() / 6e4);
37309
37348
  var getEffectiveFlowMinuteBucket = (workspace) => {
37310
37349
  const effectiveAt = workspace.recent_flow_effective_end_at;
@@ -37330,7 +37369,7 @@ var getSyntheticLowWipDisplayValue = (workspace, minuteBucket) => {
37330
37369
  const offset = (hashWorkspaceKey(workspace) % 11 + bucket % 11 + 11) % 11;
37331
37370
  return 100 + offset;
37332
37371
  };
37333
- 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);
37334
37373
  var getVideoGridColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
37335
37374
  const baseColor = getVideoGridBaseColorState(workspace, legend);
37336
37375
  if (!hasVideoGridRecentFlow(workspace)) {
@@ -37342,15 +37381,18 @@ var getVideoGridColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) =>
37342
37381
  if (baseColor !== "red") {
37343
37382
  return baseColor;
37344
37383
  }
37384
+ if (isLowWipGreenOverride(workspace, legend)) {
37385
+ return "green";
37386
+ }
37387
+ if (isHighEfficiencyRedFlowOverride(workspace, legend)) {
37388
+ return getEfficiencyColor(workspace.efficiency, legend);
37389
+ }
37345
37390
  if (!hasIncomingWipMapping(workspace)) {
37346
37391
  return baseColor;
37347
37392
  }
37348
37393
  if (!isFiniteNumber2(workspace.incoming_wip_current)) {
37349
37394
  return "neutral";
37350
37395
  }
37351
- if (isLowWipGreenOverride(workspace, legend)) {
37352
- return "green";
37353
- }
37354
37396
  return baseColor;
37355
37397
  };
37356
37398
  var getVideoGridLegendLabel = (workspaces) => {
@@ -37358,21 +37400,7 @@ var getVideoGridLegendLabel = (workspaces) => {
37358
37400
  if (visibleWorkspaces.length === 0) {
37359
37401
  return MAP_GRID_LEGEND_LABEL;
37360
37402
  }
37361
- const recentFlowEnabledCount = visibleWorkspaces.filter(isVideoGridRecentFlowEnabled).length;
37362
- if (recentFlowEnabledCount === 0) {
37363
- return MAP_GRID_LEGEND_LABEL;
37364
- }
37365
- const recentFlowWindows = new Set(
37366
- visibleWorkspaces.filter(isVideoGridRecentFlowEnabled).map((workspace) => workspace.recent_flow_window_minutes ?? 7).filter((value) => typeof value === "number" && Number.isFinite(value))
37367
- );
37368
- if (recentFlowEnabledCount === visibleWorkspaces.length) {
37369
- if (recentFlowWindows.size === 1) {
37370
- const [windowMinutes] = Array.from(recentFlowWindows);
37371
- return `${windowMinutes} Minute Efficiency`;
37372
- }
37373
- return MIXED_VIDEO_GRID_LEGEND_LABEL;
37374
- }
37375
- return MIXED_VIDEO_GRID_LEGEND_LABEL;
37403
+ return visibleWorkspaces.some(isVideoGridRecentFlowEnabled) ? VIDEO_GRID_LEGEND_LABEL : MAP_GRID_LEGEND_LABEL;
37376
37404
  };
37377
37405
  function getTrendArrowAndColor(trend) {
37378
37406
  if (trend > 0) {
@@ -37415,14 +37443,15 @@ var VideoCard = React144__default.memo(({
37415
37443
  const showOffline = Boolean(isStreamStale);
37416
37444
  const lastSeenText = lastSeenLabel || "Unknown";
37417
37445
  const workspaceDisplayName = displayName || workspace.displayName || workspace.workspace_name;
37418
- const videoGridMetricValue = getVideoGridMetricValue(workspace);
37446
+ const videoGridMetricValue = getVideoGridMetricValue(workspace, effectiveLegend);
37419
37447
  const videoGridDisplayValue = getVideoGridDisplayValue(workspace, effectiveLegend, displayMinuteBucket);
37420
37448
  const videoGridColorState = getVideoGridColorState(workspace, effectiveLegend);
37421
37449
  const isRecentFlowCard = isVideoGridRecentFlowEnabled(workspace);
37450
+ const isHighEfficiencyOverride = isHighEfficiencyRedFlowOverride(workspace, effectiveLegend);
37422
37451
  const hasDisplayMetric = typeof videoGridDisplayValue === "number" && Number.isFinite(videoGridDisplayValue);
37423
37452
  const hasBarMetric = typeof videoGridMetricValue === "number" && Number.isFinite(videoGridMetricValue);
37424
37453
  const shouldRenderMetricBadge = hasDisplayMetric;
37425
- 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)}%`;
37426
37455
  const badgeLabel = `${Math.round(videoGridDisplayValue ?? 0)}%`;
37427
37456
  const efficiencyOverlayClass = videoGridColorState === "green" ? "bg-[#00D654]/25" : videoGridColorState === "yellow" ? "bg-[#FFD700]/30" : videoGridColorState === "red" ? "bg-[#FF2D0A]/30" : "bg-transparent";
37428
37457
  const efficiencyBarClass = videoGridColorState === "green" ? "bg-[#00AB45]" : videoGridColorState === "yellow" ? "bg-[#FFB020]" : videoGridColorState === "red" ? "bg-[#E34329]" : "bg-gray-500/70";
@@ -43259,6 +43288,21 @@ var parseCycleTime = (value) => {
43259
43288
  var extractCycleTimeSeconds = (clip) => {
43260
43289
  return parseCycleTime(clip?.cycleTimeSeconds) ?? parseCycleTime(clip?.cycle_time_seconds) ?? parseCycleTime(clip?.duration) ?? parseCycleTime(clip?.original_task_metadata?.cycle_time) ?? null;
43261
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
+ };
43262
43306
  var getSeverityIcon = (severity, categoryId, cycleTimeSeconds, targetCycleTime, clipId) => {
43263
43307
  if (categoryId === "idle_time" || categoryId === "low_value" || categoryId === "longest-idles") {
43264
43308
  return null;
@@ -43334,7 +43378,9 @@ var FileManagerFilters = ({
43334
43378
  idleTimeVlmEnabled = false,
43335
43379
  showPercentileCycleFilters = true,
43336
43380
  prefetchedClipMetadata,
43337
- activeCategoryLoading
43381
+ activeCategoryLoading,
43382
+ idleClipSort = "latest",
43383
+ onIdleClipSortChange
43338
43384
  }) => {
43339
43385
  const [expandedNodes, setExpandedNodes] = useState(/* @__PURE__ */ new Set());
43340
43386
  const [startTime, setStartTime] = useState("");
@@ -43357,6 +43403,7 @@ var FileManagerFilters = ({
43357
43403
  const [localClipClassifications, setLocalClipClassifications] = useState({});
43358
43404
  const clipMetadataRef = useRef({});
43359
43405
  const inFlightMetadataRequestsRef = useRef(/* @__PURE__ */ new Set());
43406
+ const previousIdleClipSortRef = useRef(idleClipSort);
43360
43407
  const mergedClipClassifications = useMemo(() => ({
43361
43408
  ...clipClassifications || {},
43362
43409
  ...localClipClassifications
@@ -43364,6 +43411,36 @@ var FileManagerFilters = ({
43364
43411
  useEffect(() => {
43365
43412
  clipMetadataRef.current = clipMetadata;
43366
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]);
43367
43444
  const isCategoryExternallyManaged = useCallback((categoryId) => {
43368
43445
  if (!categoryId) {
43369
43446
  return false;
@@ -43522,6 +43599,7 @@ var FileManagerFilters = ({
43522
43599
  return null;
43523
43600
  }
43524
43601
  }, [supabase]);
43602
+ const getMetadataLoadingKey = useCallback((categoryId, page) => `${categoryId}-${page}-${categoryId === "idle_time" ? idleClipSort : "latest"}`, [idleClipSort]);
43525
43603
  const fetchClipMetadataPage = useCallback(async (categoryId, page = 1) => {
43526
43604
  if (!workspaceId || !date || shift === void 0) {
43527
43605
  throw new Error("Missing required params for clip metadata fetch");
@@ -43541,7 +43619,8 @@ var FileManagerFilters = ({
43541
43619
  limit: CLIP_METADATA_PAGE_SIZE,
43542
43620
  knownTotal: typeof counts?.[categoryId] === "number" ? counts[categoryId] : null,
43543
43621
  snapshotDateTime,
43544
- snapshotClipId
43622
+ snapshotClipId,
43623
+ sort: categoryId === "idle_time" ? idleClipSort : "latest"
43545
43624
  }),
43546
43625
  redirectReason: "session_expired"
43547
43626
  });
@@ -43549,7 +43628,7 @@ var FileManagerFilters = ({
43549
43628
  throw new Error(`API error: ${response.status}`);
43550
43629
  }
43551
43630
  return response.json();
43552
- }, [workspaceId, date, shift, counts, snapshotDateTime, snapshotClipId, supabase]);
43631
+ }, [workspaceId, date, shift, counts, snapshotDateTime, snapshotClipId, idleClipSort, supabase]);
43553
43632
  const seedIdleClassifications = useCallback(async (clips) => {
43554
43633
  if (!idleTimeVlmEnabled || clips.length === 0) {
43555
43634
  return;
@@ -43605,7 +43684,7 @@ var FileManagerFilters = ({
43605
43684
  console.warn("[FileManager] Missing required params for clip metadata fetch");
43606
43685
  return;
43607
43686
  }
43608
- const loadingKey = `${categoryId}-${page}`;
43687
+ const loadingKey = getMetadataLoadingKey(categoryId, page);
43609
43688
  if (inFlightMetadataRequestsRef.current.has(loadingKey)) {
43610
43689
  return;
43611
43690
  }
@@ -43633,7 +43712,7 @@ var FileManagerFilters = ({
43633
43712
  return newSet;
43634
43713
  });
43635
43714
  }
43636
- }, [workspaceId, date, shift, fetchClipMetadataPage, idleTimeVlmEnabled, seedIdleClassifications]);
43715
+ }, [workspaceId, date, shift, fetchClipMetadataPage, idleTimeVlmEnabled, seedIdleClassifications, getMetadataLoadingKey]);
43637
43716
  const ensureAllIdleTimeClipMetadataLoaded = useCallback(async () => {
43638
43717
  if (!workspaceId || !date || shift === void 0) {
43639
43718
  return;
@@ -44007,15 +44086,17 @@ var FileManagerFilters = ({
44007
44086
  const colorClasses = getColorClasses(category.color);
44008
44087
  const clipNodes = filteredClips.map((clip, index) => {
44009
44088
  const cycleTime = extractCycleTimeSeconds(clip);
44089
+ const idleDuration = category.id === "idle_time" ? clip.idle_duration_seconds ?? clip.duration : null;
44090
+ const idleDurationLabel = formatDurationLabel(idleDuration);
44010
44091
  const baseTimeLabel = formatClipExplorerTimeLabel({
44011
44092
  categoryId: category.id,
44012
44093
  clipTimestamp: clip.clip_timestamp,
44013
44094
  timezone,
44014
- durationSeconds: clip.duration,
44095
+ durationSeconds: idleDuration ?? clip.duration,
44015
44096
  idleStartTime: clip.idle_start_time,
44016
44097
  idleEndTime: clip.idle_end_time
44017
44098
  });
44018
- 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)` : ""}`;
44019
44100
  return {
44020
44101
  id: clip.id,
44021
44102
  label: displayLabel,
@@ -44029,7 +44110,7 @@ var FileManagerFilters = ({
44029
44110
  clipPosition: index + 1,
44030
44111
  // Store 1-based position
44031
44112
  cycleTimeSeconds: cycleTime,
44032
- duration: clip.duration,
44113
+ duration: idleDuration ?? clip.duration,
44033
44114
  // Store duration for custom badge rendering
44034
44115
  cycleItemCount: clip.cycle_item_count ?? null
44035
44116
  };
@@ -44351,11 +44432,11 @@ var FileManagerFilters = ({
44351
44432
  /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
44352
44433
  "Loading clips..."
44353
44434
  ] }) }),
44354
- 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: [
44355
44436
  /* @__PURE__ */ jsx("div", { className: "animate-spin mr-2 h-4 w-4 border-2 border-slate-300 border-t-blue-500 rounded-full" }),
44356
44437
  "Loading more clips..."
44357
44438
  ] }) }),
44358
- 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(
44359
44440
  "button",
44360
44441
  {
44361
44442
  onClick: (e) => {
@@ -44382,6 +44463,18 @@ var FileManagerFilters = ({
44382
44463
  /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx("h2", { className: "text-lg font-bold text-slate-900 tracking-tight", children: "Clips Explorer" }) })
44383
44464
  ] }),
44384
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
+ ),
44385
44478
  activeFilter === "idle_time" && idleTimeVlmEnabled && /* @__PURE__ */ jsx(
44386
44479
  "button",
44387
44480
  {
@@ -44402,8 +44495,8 @@ var FileManagerFilters = ({
44402
44495
  )
44403
44496
  ] })
44404
44497
  ] }),
44405
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 mt-3", children: [
44406
- 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: [
44407
44500
  /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
44408
44501
  "Time: ",
44409
44502
  getDisplayValue(startTime),
@@ -44419,13 +44512,13 @@ var FileManagerFilters = ({
44419
44512
  setEndTime("");
44420
44513
  setIsTimeFilterActive(false);
44421
44514
  },
44422
- 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",
44423
44516
  title: "Clear time filter",
44424
44517
  children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
44425
44518
  }
44426
44519
  )
44427
44520
  ] }),
44428
- 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: [
44429
44522
  /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
44430
44523
  "Reason: ",
44431
44524
  selectedIdleReasonOption?.displayName || idleLabelFilter.replace(/_/g, " ")
@@ -44437,11 +44530,27 @@ var FileManagerFilters = ({
44437
44530
  e.stopPropagation();
44438
44531
  setIdleLabelFilter(null);
44439
44532
  },
44440
- 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",
44441
44534
  title: "Clear label filter",
44442
44535
  children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
44443
44536
  }
44444
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
+ )
44445
44554
  ] })
44446
44555
  ] })
44447
44556
  ] }),
@@ -45205,8 +45314,10 @@ var BottlenecksContent = ({
45205
45314
  const [clipClassifications, setClipClassifications] = useState({});
45206
45315
  const [categoryMetadata, setCategoryMetadata] = useState([]);
45207
45316
  const [categoryMetadataCategoryId, setCategoryMetadataCategoryId] = useState(null);
45317
+ const [categoryMetadataSort, setCategoryMetadataSort] = useState(null);
45208
45318
  const [currentMetadataIndex, setCurrentMetadataIndex] = useState(0);
45209
45319
  const [metadataCache, setMetadataCache] = useState({});
45320
+ const [idleClipSort, setIdleClipSort] = useState("latest");
45210
45321
  const invalidateMetadataCache = useCallback((categories) => {
45211
45322
  setMetadataCache((prevCache) => {
45212
45323
  if (!prevCache || Object.keys(prevCache).length === 0) {
@@ -45237,6 +45348,7 @@ var BottlenecksContent = ({
45237
45348
  const [isFullscreen, setIsFullscreen] = useState(false);
45238
45349
  const categoryMetadataRef = useRef([]);
45239
45350
  const currentMetadataIndexRef = useRef(0);
45351
+ const previousIdleClipSortRef = useRef(idleClipSort);
45240
45352
  const clearRetryTimeout = useCallback(() => {
45241
45353
  if (retryTimeoutRef.current) {
45242
45354
  clearTimeout(retryTimeoutRef.current);
@@ -45683,9 +45795,13 @@ var BottlenecksContent = ({
45683
45795
  }
45684
45796
  return ["fast-cycles", "slow-cycles", "longest-idles"].includes(categoryId);
45685
45797
  }, [isFastSlowClipFiltersEnabled]);
45798
+ const shouldUseMetadataNavigation = useCallback((categoryId) => {
45799
+ return isPercentileCategory(categoryId) || categoryId === "idle_time" && idleClipSort === "idle_duration_desc";
45800
+ }, [idleClipSort, isPercentileCategory]);
45686
45801
  const getMetadataCacheKey = useCallback((categoryId) => {
45687
- return `${categoryId}-${effectiveDateString}-${effectiveShiftId}-${snapshotDateTime ?? "nosnap"}-${snapshotClipId ?? "nosnap"}`;
45688
- }, [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]);
45689
45805
  const setVisibleCategoryMetadata = useCallback((categoryId, clips) => {
45690
45806
  if (activeFilterRef.current !== categoryId) {
45691
45807
  return false;
@@ -45693,8 +45809,9 @@ var BottlenecksContent = ({
45693
45809
  categoryMetadataRef.current = clips;
45694
45810
  setCategoryMetadata(clips);
45695
45811
  setCategoryMetadataCategoryId(clips.length > 0 ? categoryId : null);
45812
+ setCategoryMetadataSort(clips.length > 0 ? categoryId === "idle_time" ? idleClipSort : "latest" : null);
45696
45813
  return true;
45697
- }, []);
45814
+ }, [idleClipSort]);
45698
45815
  const applyMetadataSnapshot = useCallback((categoryId, clips, total) => {
45699
45816
  if (!clips || clips.length === 0) {
45700
45817
  return;
@@ -45705,11 +45822,11 @@ var BottlenecksContent = ({
45705
45822
  [cacheKey]: clips
45706
45823
  }));
45707
45824
  setVisibleCategoryMetadata(categoryId, clips);
45708
- if (!isPercentileCategory(categoryId) && typeof total === "number") {
45825
+ if (!shouldUseMetadataNavigation(categoryId) && typeof total === "number") {
45709
45826
  currentTotalRef.current = total;
45710
45827
  setCurrentTotal(total);
45711
45828
  }
45712
- }, [getMetadataCacheKey, isPercentileCategory, setVisibleCategoryMetadata]);
45829
+ }, [getMetadataCacheKey, shouldUseMetadataNavigation, setVisibleCategoryMetadata]);
45713
45830
  const getClipTypesForPercentileCategory = useCallback((categoryId) => {
45714
45831
  switch (categoryId) {
45715
45832
  case "fast-cycles":
@@ -45735,6 +45852,7 @@ var BottlenecksContent = ({
45735
45852
  }
45736
45853
  setCategoryMetadata([]);
45737
45854
  setCategoryMetadataCategoryId(null);
45855
+ setCategoryMetadataSort(null);
45738
45856
  categoryMetadataRef.current = [];
45739
45857
  updateActiveFilter(fallbackFilter);
45740
45858
  }, [isFastSlowClipFiltersEnabled, activeFilter, dynamicCounts, clipTypes, updateActiveFilter]);
@@ -45782,6 +45900,7 @@ var BottlenecksContent = ({
45782
45900
  if (!isFastSlowClipFiltersEnabled && (categoryId === "fast-cycles" || categoryId === "slow-cycles")) {
45783
45901
  setCategoryMetadata([]);
45784
45902
  setCategoryMetadataCategoryId(null);
45903
+ setCategoryMetadataSort(null);
45785
45904
  categoryMetadataRef.current = [];
45786
45905
  return;
45787
45906
  }
@@ -45852,7 +45971,8 @@ var BottlenecksContent = ({
45852
45971
  limit: 100,
45853
45972
  knownTotal: mergedCounts[categoryId] ?? null,
45854
45973
  snapshotDateTime,
45855
- snapshotClipId
45974
+ snapshotClipId,
45975
+ sort: categoryId === "idle_time" ? idleClipSort : "latest"
45856
45976
  }),
45857
45977
  redirectReason: "session_expired"
45858
45978
  });
@@ -45931,6 +46051,7 @@ var BottlenecksContent = ({
45931
46051
  if (activeFilterRef.current === categoryId) {
45932
46052
  setCategoryMetadata([]);
45933
46053
  setCategoryMetadataCategoryId(null);
46054
+ setCategoryMetadataSort(null);
45934
46055
  categoryMetadataRef.current = [];
45935
46056
  }
45936
46057
  }
@@ -45939,7 +46060,26 @@ var BottlenecksContent = ({
45939
46060
  } finally {
45940
46061
  setIsCategoryLoading(false);
45941
46062
  }
45942
- }, [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]);
45943
46083
  useEffect(() => {
45944
46084
  if (previousFilterRef.current !== activeFilter) {
45945
46085
  console.log(`Filter changed from ${previousFilterRef.current} to ${activeFilter} - resetting to first video`);
@@ -45950,6 +46090,7 @@ var BottlenecksContent = ({
45950
46090
  loadingCategoryRef.current = null;
45951
46091
  setCategoryMetadata([]);
45952
46092
  setCategoryMetadataCategoryId(null);
46093
+ setCategoryMetadataSort(null);
45953
46094
  setCurrentMetadataIndex(0);
45954
46095
  categoryMetadataRef.current = [];
45955
46096
  currentMetadataIndexRef.current = 0;
@@ -46048,7 +46189,7 @@ var BottlenecksContent = ({
46048
46189
  }
46049
46190
  if (metadataArray.length === 0) {
46050
46191
  console.warn(`[BottlenecksContent] No metadata available for category ${categoryId} after refresh`);
46051
- if (!isPercentileCategory(categoryId)) {
46192
+ if (!shouldUseMetadataNavigation(categoryId)) {
46052
46193
  const resolvedPosition = typeof position === "number" ? position : 1;
46053
46194
  currentPositionRef.current = resolvedPosition;
46054
46195
  setCurrentPosition(resolvedPosition);
@@ -46061,7 +46202,7 @@ var BottlenecksContent = ({
46061
46202
  const clickedClipIndex = metadataArray.findIndex((clip) => clip.clipId === clipId);
46062
46203
  if (clickedClipIndex === -1) {
46063
46204
  console.warn(`[BottlenecksContent] Clip ${clipId} not found after metadata refresh`);
46064
- if (!isPercentileCategory(categoryId)) {
46205
+ if (!shouldUseMetadataNavigation(categoryId)) {
46065
46206
  const resolvedPosition = typeof position === "number" ? position : 1;
46066
46207
  currentPositionRef.current = resolvedPosition;
46067
46208
  setCurrentPosition(resolvedPosition);
@@ -46073,7 +46214,7 @@ var BottlenecksContent = ({
46073
46214
  }
46074
46215
  setCurrentMetadataIndex(clickedClipIndex);
46075
46216
  currentMetadataIndexRef.current = clickedClipIndex;
46076
- if (!isPercentileCategory(categoryId)) {
46217
+ if (!shouldUseMetadataNavigation(categoryId)) {
46077
46218
  const position2 = clickedClipIndex + 1;
46078
46219
  currentPositionRef.current = position2;
46079
46220
  setCurrentPosition(position2);
@@ -46103,7 +46244,7 @@ var BottlenecksContent = ({
46103
46244
  clearLoadingState();
46104
46245
  }
46105
46246
  }
46106
- }, [workspaceId, s3ClipsService, updateActiveFilter, clearLoadingState, clearRetryTimeout, loadCategoryMetadata, applyMetadataSnapshot, mergedCounts, isPercentileCategory]);
46247
+ }, [workspaceId, s3ClipsService, updateActiveFilter, clearLoadingState, clearRetryTimeout, loadCategoryMetadata, applyMetadataSnapshot, mergedCounts, shouldUseMetadataNavigation]);
46107
46248
  const restartCurrentClipPlayback = useCallback(() => {
46108
46249
  if (!currentClipId) {
46109
46250
  return;
@@ -46124,7 +46265,7 @@ var BottlenecksContent = ({
46124
46265
  return;
46125
46266
  }
46126
46267
  const activeCategory = activeFilterRef.current;
46127
- if (!activeCategory || activeCategory === "all" || isPercentileCategory(activeCategory)) {
46268
+ if (!activeCategory || activeCategory === "all" || shouldUseMetadataNavigation(activeCategory)) {
46128
46269
  return;
46129
46270
  }
46130
46271
  let cancelled = false;
@@ -46157,7 +46298,7 @@ var BottlenecksContent = ({
46157
46298
  }, [
46158
46299
  newClipsNotification,
46159
46300
  s3ClipsService,
46160
- isPercentileCategory,
46301
+ shouldUseMetadataNavigation,
46161
46302
  currentClipId,
46162
46303
  invalidateMetadataCache,
46163
46304
  loadAndPlayClipById,
@@ -46209,7 +46350,7 @@ var BottlenecksContent = ({
46209
46350
  }
46210
46351
  }
46211
46352
  try {
46212
- if (!isPercentileCategory(currentFilter)) {
46353
+ if (!shouldUseMetadataNavigation(currentFilter)) {
46213
46354
  if (!s3ClipsService || !workspaceId || !currentClipId) {
46214
46355
  throw new Error("S3 clips service not available");
46215
46356
  }
@@ -46309,7 +46450,7 @@ var BottlenecksContent = ({
46309
46450
  } else {
46310
46451
  const firstClipMeta = metadataArray[0];
46311
46452
  if (firstClipMeta?.clipId && firstClipMeta.clipId !== currentClipId) {
46312
- 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}`);
46313
46454
  await loadAndPlayClipById(firstClipMeta.clipId, currentFilter, 1, {
46314
46455
  clips: metadataArray,
46315
46456
  total: metadataArray.length
@@ -46335,7 +46476,7 @@ var BottlenecksContent = ({
46335
46476
  });
46336
46477
  clearLoadingState();
46337
46478
  }
46338
- }, [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]);
46339
46480
  const handlePrevious = useCallback(async () => {
46340
46481
  if (!isMountedRef.current || navigationLockRef.current) return;
46341
46482
  const currentFilter = activeFilterRef.current;
@@ -46354,7 +46495,7 @@ var BottlenecksContent = ({
46354
46495
  }
46355
46496
  }
46356
46497
  try {
46357
- if (!isPercentileCategory(currentFilter)) {
46498
+ if (!shouldUseMetadataNavigation(currentFilter)) {
46358
46499
  if (!s3ClipsService || !workspaceId || !currentClipId) {
46359
46500
  throw new Error("S3 clips service not available");
46360
46501
  }
@@ -46439,7 +46580,7 @@ var BottlenecksContent = ({
46439
46580
  });
46440
46581
  clearLoadingState();
46441
46582
  }
46442
- }, [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]);
46443
46584
  const currentVideo = useMemo(() => {
46444
46585
  if (!filteredVideos || filteredVideos.length === 0 || currentIndex >= filteredVideos.length) {
46445
46586
  return null;
@@ -46506,22 +46647,22 @@ var BottlenecksContent = ({
46506
46647
  }
46507
46648
  }, [currentVideo?.id, isShareLoading, supabase, workspaceId, workspaceName]);
46508
46649
  useMemo(() => {
46509
- if (isPercentileCategory(activeFilter)) {
46650
+ if (shouldUseMetadataNavigation(activeFilter)) {
46510
46651
  return categoryMetadata.length;
46511
46652
  }
46512
46653
  return currentTotal || mergedCounts[activeFilter] || 0;
46513
- }, [activeFilter, categoryMetadata.length, currentTotal, mergedCounts, isPercentileCategory]);
46654
+ }, [activeFilter, categoryMetadata.length, currentTotal, mergedCounts, shouldUseMetadataNavigation]);
46514
46655
  useMemo(() => {
46515
- if (isPercentileCategory(activeFilter)) {
46656
+ if (shouldUseMetadataNavigation(activeFilter)) {
46516
46657
  return categoryMetadata.length > 0 ? currentMetadataIndex + 1 : 0;
46517
46658
  }
46518
46659
  return currentPosition;
46519
- }, [activeFilter, categoryMetadata.length, currentMetadataIndex, currentPosition, isPercentileCategory]);
46520
- const prefetchedExplorerMetadata = useMemo(() => buildPrefetchedExplorerMetadata(
46660
+ }, [activeFilter, categoryMetadata.length, currentMetadataIndex, currentPosition, shouldUseMetadataNavigation]);
46661
+ const prefetchedExplorerMetadata = useMemo(() => activeFilter === "idle_time" && categoryMetadataSort !== idleClipSort ? void 0 : buildPrefetchedExplorerMetadata(
46521
46662
  activeFilter,
46522
46663
  categoryMetadataCategoryId,
46523
46664
  categoryMetadata
46524
- ), [activeFilter, categoryMetadata, categoryMetadataCategoryId]);
46665
+ ), [activeFilter, categoryMetadata, categoryMetadataCategoryId, categoryMetadataSort, idleClipSort]);
46525
46666
  const classificationClipIds = useMemo(() => {
46526
46667
  if (!idleTimeVlmEnabled) {
46527
46668
  return [];
@@ -47270,7 +47411,12 @@ var BottlenecksContent = ({
47270
47411
  showPercentileCycleFilters: isFastSlowClipFiltersEnabled,
47271
47412
  prefetchedClipMetadata: prefetchedExplorerMetadata,
47272
47413
  activeCategoryLoading: isCategoryLoading,
47414
+ idleClipSort,
47415
+ onIdleClipSortChange: setIdleClipSort,
47273
47416
  onFilterChange: (filterId) => {
47417
+ if (filterId !== "idle_time") {
47418
+ setIdleClipSort("latest");
47419
+ }
47274
47420
  updateActiveFilter(filterId);
47275
47421
  const category = categoriesToShow.find((cat) => cat.type === filterId);
47276
47422
  if (category) {
@@ -49193,6 +49339,11 @@ var LineHistoryCalendar = ({
49193
49339
  return calendar;
49194
49340
  }, [data, month, year, configuredTimezone]);
49195
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
+ }
49196
49347
  if (shift.hasData !== void 0) return shift.hasData;
49197
49348
  return shift.total_workspaces > 0 || shift.avg_efficiency > 0 || shift.underperforming_workspaces > 0;
49198
49349
  };
@@ -49825,13 +49976,18 @@ var LineMonthlyHistory = ({
49825
49976
  enabled: !!lineId && idleTimeVlmEnabled
49826
49977
  });
49827
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
+ }
49828
49984
  if (shift.hasData !== void 0) return shift.hasData;
49829
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;
49830
49986
  };
49831
49987
  const averages = (analysisMonthlyData || []).reduce(
49832
49988
  (acc, day) => {
49833
49989
  const shiftData = getShiftData2(day, selectedShiftId);
49834
- if (!shiftData || shiftData?.avg_efficiency < 5) {
49990
+ if (!shiftData || !isValidAggregateEfficiency(isUptimeMode ? "uptime" : "output", shiftData.avg_efficiency)) {
49835
49991
  return acc;
49836
49992
  }
49837
49993
  return {
@@ -49860,7 +50016,9 @@ var LineMonthlyHistory = ({
49860
50016
  const avgOutput = outputAverages.count > 0 ? outputAverages.output / outputAverages.count : 0;
49861
50017
  const uptimeSummary = useMemo(() => {
49862
50018
  if (!isUptimeMode) return null;
49863
- 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) }));
49864
50022
  if (!validDays.length) {
49865
50023
  return { avgUtilization: 0, avgIdleTime: 0, avgDailyStoppages: 0 };
49866
50024
  }
@@ -50008,7 +50166,9 @@ var LineMonthlyHistory = ({
50008
50166
  }, [chartData.yAxisMax, chartData.lastSetTarget]);
50009
50167
  const pieChartData = useMemo(() => {
50010
50168
  if (!isUptimeMode) return [];
50011
- 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
+ );
50012
50172
  if (!validShifts.length) return [];
50013
50173
  const efficiencyValues = validShifts.map((shift) => Number.isFinite(shift.avg_efficiency) ? Number(shift.avg_efficiency) : null).filter((value) => value !== null);
50014
50174
  if (!efficiencyValues.length) return [];
@@ -50618,7 +50778,9 @@ var LineMonthlyPdfGenerator = ({
50618
50778
  const productiveSeconds = activeSecondsRaw > 0 ? Math.min(activeSecondsRaw, availableSeconds) : Math.max(availableSeconds - idleSeconds, 0);
50619
50779
  return { availableSeconds, productiveSeconds, idleSeconds };
50620
50780
  };
50621
- 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
+ );
50622
50784
  const monthlyMetrics = validShifts.length > 0 ? isUptimeMode ? (() => {
50623
50785
  let utilizationSum = 0;
50624
50786
  let idleTimeSum = 0;
@@ -52603,7 +52765,10 @@ var WorkspaceMonthlyHistory = ({
52603
52765
  return ticks.filter((v) => v >= 0 && v <= max * 1.05).sort((a, b) => a - b);
52604
52766
  }, [chartData.yAxisMax, chartData.lastSetTarget, isUptimeMode]);
52605
52767
  const pieChartData = useMemo(() => {
52606
- 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
+ );
52607
52772
  if (validShifts.length === 0) return [];
52608
52773
  const efficiencyValues = validShifts.map((shift) => Number.isFinite(shift.efficiency) ? Number(shift.efficiency) : null).filter((value) => value !== null);
52609
52774
  if (!efficiencyValues.length) return [];
@@ -52614,10 +52779,10 @@ var WorkspaceMonthlyHistory = ({
52614
52779
  { name: "Productive", value: productivePercent },
52615
52780
  { name: "Idle", value: idlePercent }
52616
52781
  ];
52617
- }, [analysisMonthlyData, selectedShiftId, shiftWorkSeconds]);
52782
+ }, [analysisMonthlyData, selectedShiftId, isUptimeMode]);
52618
52783
  const metrics2 = useMemo(() => {
52619
52784
  const validShifts = analysisMonthlyData.map((d) => getShiftData(d, selectedShiftId)).filter(hasRealData);
52620
- 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));
52621
52786
  if (filteredShifts.length === 0) return null;
52622
52787
  const totalEfficiency = filteredShifts.reduce((sum, shift) => sum + (shift.efficiency || 0), 0);
52623
52788
  const totalUtilization = filteredShifts.reduce(
@@ -53837,7 +54002,7 @@ var WorkspaceMonthlyPdfGenerator = ({
53837
54002
  const shift = getShiftData(dayData, selectedShiftId);
53838
54003
  return { dayData, shift };
53839
54004
  }).filter(({ shift }) => hasShiftData(shift)).sort((left, right) => getDayDateKey(right.dayData).localeCompare(getDayDateKey(left.dayData)));
53840
- 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));
53841
54006
  const monthlyMetrics = filteredShifts.length > 0 ? isUptimeMode ? (() => {
53842
54007
  const totalIdleTime = filteredShifts.reduce((sum, shift) => sum + shift.idleTime, 0);
53843
54008
  const totalCycleTime = filteredShifts.reduce((sum, shift) => sum + shift.cycleTime, 0);
@@ -67009,7 +67174,15 @@ var KPIDetailView = ({
67009
67174
  const fallbackTimes = resolveMonthlyShiftTimes(metric.shift_id);
67010
67175
  const resolvedShiftStart = metric.shift_start || fallbackTimes.start;
67011
67176
  const resolvedShiftEnd = metric.shift_end || fallbackTimes.end;
67012
- 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);
67013
67186
  const uptimeSeries2 = isUptimeMode && !hasBackendUptimeSeconds ? buildUptimeSeries({
67014
67187
  idleTimeHourly: metric.idle_time_hourly || {},
67015
67188
  shiftStart: resolvedShiftStart || void 0,
@@ -67017,9 +67190,13 @@ var KPIDetailView = ({
67017
67190
  shiftDate: metric.date,
67018
67191
  timezone: configuredTimezone
67019
67192
  }) : null;
67020
- const idleTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metric.idle_time_seconds || 0 : (uptimeSeries2?.idleMinutes || 0) * 60 : 0;
67021
- const activeTimeSeconds = isUptimeMode ? hasBackendUptimeSeconds ? metric.active_time_seconds || 0 : (uptimeSeries2?.activeMinutes || 0) * 60 : 0;
67022
- 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);
67023
67200
  const computedUptimeEfficiency = (() => {
67024
67201
  const availableMinutes = availableTimeSeconds / 60;
67025
67202
  if (!availableMinutes || availableMinutes <= 0) return 0;
@@ -67039,7 +67216,7 @@ var KPIDetailView = ({
67039
67216
  targetOutput: Number(metric.line_threshold ?? metric.ideal_output ?? 0),
67040
67217
  compliance_percentage: 95 + Math.random() * 5,
67041
67218
  // Mock data: random value between 95-100%
67042
- hasData: isUptimeMode ? availableTimeSeconds > 0 : true,
67219
+ hasData: isUptimeMode ? hasUptimeMetricData : true,
67043
67220
  idle_time_seconds: idleTimeSeconds,
67044
67221
  active_time_seconds: activeTimeSeconds,
67045
67222
  available_time_seconds: availableTimeSeconds,