@optifye/dashboard-core 6.0.8 → 6.1.0

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
@@ -12,7 +12,7 @@ import { noop, warning, invariant, progress, secondsToMilliseconds, milliseconds
12
12
  import { getValueTransition, hover, press, isPrimaryPointer, GroupPlaybackControls, setDragLock, supportsLinearEasing, attachTimeline, isGenerator, calcGeneratorDuration, isWaapiSupportedEasing, mapEasingToNativeEasing, maxGeneratorDuration, generateLinearEasing, isBezierDefinition } from 'motion-dom';
13
13
  import { BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, Tooltip, Legend, Bar, LabelList, ResponsiveContainer, LineChart as LineChart$1, Line, PieChart, Pie, Cell, ReferenceLine, ComposedChart, Area, ScatterChart, Scatter } from 'recharts';
14
14
  import { Slot } from '@radix-ui/react-slot';
15
- import { Camera, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, X, Coffee, Plus, Clock, Minus, ArrowDown, ArrowUp, Search, CheckCircle, AlertTriangle, Info, Share2, Download, User, XCircle, ChevronLeft, ChevronRight, AlertCircle, Sun, Moon, MessageSquare, Trash2, ArrowLeft, RefreshCw, Menu, Send, Copy, Edit2, UserCheck, Save, LogOut, Calendar, Package, Settings, LifeBuoy, ArrowLeftIcon as ArrowLeftIcon$1, Settings2, CheckCircle2, EyeOff, Eye, Zap, UserCircle } from 'lucide-react';
15
+ import { Camera, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, X, Coffee, Plus, Clock, Minus, ArrowDown, ArrowUp, Search, CheckCircle, AlertTriangle, Info, Share2, Download, User, XCircle, ChevronLeft, ChevronRight, AlertCircle, Sun, Moon, MessageSquare, Trash2, ArrowLeft, RefreshCw, Menu, Send, Copy, Edit2, UserCheck, Save, LogOut, Calendar, Package, Settings, LifeBuoy, EyeOff, Eye, Zap, UserCircle, ArrowLeftIcon as ArrowLeftIcon$1, Settings2, CheckCircle2 } from 'lucide-react';
16
16
  import { DayPicker, useNavigation as useNavigation$1 } from 'react-day-picker';
17
17
  import html2canvas from 'html2canvas';
18
18
  import jsPDF, { jsPDF as jsPDF$1 } from 'jspdf';
@@ -4987,34 +4987,6 @@ var useWorkspaceOperators = (workspaceId, options) => {
4987
4987
  refetch: fetchData
4988
4988
  };
4989
4989
  };
4990
-
4991
- // src/lib/utils/dashboardReload.ts
4992
- var createThrottledReload = (interval = 5e3) => {
4993
- let last = 0;
4994
- let queued = false;
4995
- const doReload = () => {
4996
- if (typeof window !== "undefined") {
4997
- window.location.reload();
4998
- }
4999
- };
5000
- return () => {
5001
- const now2 = Date.now();
5002
- if (now2 - last >= interval) {
5003
- last = now2;
5004
- doReload();
5005
- } else if (!queued) {
5006
- queued = true;
5007
- setTimeout(() => {
5008
- queued = false;
5009
- last = Date.now();
5010
- doReload();
5011
- }, interval - (now2 - last));
5012
- }
5013
- };
5014
- };
5015
- var throttledReloadDashboard = createThrottledReload(5e3);
5016
-
5017
- // src/lib/hooks/useHlsStream.ts
5018
4990
  var HLS_CONFIG = {
5019
4991
  maxBufferLength: 8,
5020
4992
  maxMaxBufferLength: 15,
@@ -5033,7 +5005,35 @@ var HLS_CONFIG = {
5033
5005
  liveSyncDurationCount: 2
5034
5006
  // Follow live edge aggressively
5035
5007
  };
5008
+ var failedUrls = /* @__PURE__ */ new Map();
5009
+ var MAX_FAILURES_PER_URL = 3;
5010
+ var FAILURE_EXPIRY_MS = 5 * 60 * 1e3;
5011
+ function resetFailedUrl(url) {
5012
+ if (failedUrls.has(url)) {
5013
+ console.log(`[HLS] Manually resetting failed URL: ${url}`);
5014
+ failedUrls.delete(url);
5015
+ }
5016
+ }
5017
+ function isUrlPermanentlyFailed(url) {
5018
+ const failure = failedUrls.get(url);
5019
+ return failure?.permanentlyFailed || false;
5020
+ }
5036
5021
  function useHlsStream(videoRef, { src, shouldPlay, onFatalError }) {
5022
+ const urlFailure = failedUrls.get(src);
5023
+ const isPermanentlyFailed = urlFailure?.permanentlyFailed || false;
5024
+ const cleanupFailedUrls = () => {
5025
+ const now2 = Date.now();
5026
+ const expiredUrls = [];
5027
+ failedUrls.forEach((failure, url) => {
5028
+ if (now2 - failure.timestamp > FAILURE_EXPIRY_MS) {
5029
+ expiredUrls.push(url);
5030
+ }
5031
+ });
5032
+ expiredUrls.forEach((url) => {
5033
+ console.log(`[HLS] Removing expired failure entry for: ${url}`);
5034
+ failedUrls.delete(url);
5035
+ });
5036
+ };
5037
5037
  const [restartKey, setRestartKey] = useState(0);
5038
5038
  const hlsRef = useRef(null);
5039
5039
  const stallCheckIntervalRef = useRef(null);
@@ -5103,14 +5103,33 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError }) {
5103
5103
  };
5104
5104
  const hardRestart = (reason) => {
5105
5105
  console.warn(`[HLS] Hard restart: ${reason}`);
5106
+ cleanupFailedUrls();
5107
+ const failure = failedUrls.get(src);
5108
+ const failureCount = failure ? failure.count : 0;
5109
+ if (failureCount >= MAX_FAILURES_PER_URL) {
5110
+ console.error(`[HLS] URL has failed ${failureCount} times. Marking as permanently failed: ${src}`);
5111
+ failedUrls.set(src, {
5112
+ count: failureCount,
5113
+ timestamp: Date.now(),
5114
+ permanentlyFailed: true
5115
+ });
5116
+ cleanup();
5117
+ if (onFatalError) {
5118
+ onFatalError();
5119
+ }
5120
+ return;
5121
+ }
5122
+ failedUrls.set(src, {
5123
+ count: failureCount + 1,
5124
+ timestamp: Date.now(),
5125
+ permanentlyFailed: false
5126
+ });
5106
5127
  cleanup();
5107
5128
  setRestartKey((k) => k + 1);
5108
5129
  softRestartCountRef.current = 0;
5109
- if (reason.includes("hard restart") || reason.includes("native video error")) {
5130
+ if (reason.includes("404 hard restart")) {
5110
5131
  if (onFatalError) {
5111
5132
  onFatalError();
5112
- } else {
5113
- throttledReloadDashboard();
5114
5133
  }
5115
5134
  }
5116
5135
  };
@@ -5164,6 +5183,13 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError }) {
5164
5183
  }, 7e3);
5165
5184
  };
5166
5185
  useEffect(() => {
5186
+ if (isPermanentlyFailed) {
5187
+ console.warn(`[HLS] URL is permanently failed, not attempting to load: ${src}`);
5188
+ if (onFatalError) {
5189
+ onFatalError();
5190
+ }
5191
+ return;
5192
+ }
5167
5193
  if (!src || !shouldPlay) {
5168
5194
  cleanup();
5169
5195
  return;
@@ -5194,6 +5220,10 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError }) {
5194
5220
  }
5195
5221
  });
5196
5222
  hls.on(Hls2.Events.MANIFEST_PARSED, () => {
5223
+ if (failedUrls.has(src)) {
5224
+ console.log(`[HLS] Stream loaded successfully, resetting failure count for: ${src}`);
5225
+ failedUrls.delete(src);
5226
+ }
5197
5227
  video.play().catch((err) => {
5198
5228
  console.error("[HLS] Play failed:", err);
5199
5229
  });
@@ -5212,7 +5242,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError }) {
5212
5242
  console.error("[HLS] HLS not supported");
5213
5243
  }
5214
5244
  return cleanup;
5215
- }, [src, shouldPlay, restartKey, onFatalError]);
5245
+ }, [src, shouldPlay, restartKey, onFatalError, isPermanentlyFailed]);
5216
5246
  return {
5217
5247
  restartKey,
5218
5248
  isNativeHls: isNativeHlsRef.current
@@ -6317,7 +6347,7 @@ function useNavigation(customNavigate) {
6317
6347
  }
6318
6348
  function useWorkspaceNavigation() {
6319
6349
  const { defaultTimezone } = useDateTimeConfig();
6320
- const getWorkspaceNavigationParams3 = useCallback(
6350
+ const getWorkspaceNavigationParams2 = useCallback(
6321
6351
  (workspaceId, options) => {
6322
6352
  let dateToUse = options?.date;
6323
6353
  if (!dateToUse && options?.useCurrentDate) {
@@ -6333,7 +6363,7 @@ function useWorkspaceNavigation() {
6333
6363
  [defaultTimezone]
6334
6364
  );
6335
6365
  return {
6336
- getWorkspaceNavigationParams: getWorkspaceNavigationParams3
6366
+ getWorkspaceNavigationParams: getWorkspaceNavigationParams2
6337
6367
  };
6338
6368
  }
6339
6369
  function useDateFormatter() {
@@ -9031,9 +9061,15 @@ var getStoredWorkspaceMappings = () => {
9031
9061
  var getDefaultTabForWorkspace = (workspaceId, displayName) => {
9032
9062
  return "overview";
9033
9063
  };
9034
- var getWorkspaceNavigationParams = (workspaceId, displayName) => {
9064
+ var getWorkspaceNavigationParams = (workspaceId, displayName, lineId) => {
9035
9065
  const defaultTab = getDefaultTabForWorkspace();
9036
- return `?displayName=${encodeURIComponent(displayName)}&defaultTab=${defaultTab}`;
9066
+ const params = new URLSearchParams();
9067
+ params.set("displayName", displayName);
9068
+ params.set("defaultTab", defaultTab);
9069
+ if (lineId) {
9070
+ params.set("lineId", lineId);
9071
+ }
9072
+ return `?${params.toString()}`;
9037
9073
  };
9038
9074
 
9039
9075
  // src/lib/utils/videoPreloader.ts
@@ -9354,6 +9390,115 @@ var clearS3VideoCache = () => {
9354
9390
  var preloadS3VideoUrl = s3VideoPreloader.preloadVideo;
9355
9391
  var preloadS3VideosUrl = s3VideoPreloader.preloadVideos;
9356
9392
 
9393
+ // src/lib/utils/dashboardReload.ts
9394
+ var reloadAttempts = [];
9395
+ var createThrottledReload = (interval = 5e3, maxReloads = 3) => {
9396
+ const circuitBreakerWindow = 1e4;
9397
+ const circuitBreakerThreshold = 5;
9398
+ let last = 0;
9399
+ let queued = false;
9400
+ let reloadCount = 0;
9401
+ let firstReloadTime = 0;
9402
+ const resetWindow = 6e4;
9403
+ const doReload = () => {
9404
+ if (typeof window !== "undefined") {
9405
+ const now2 = Date.now();
9406
+ reloadAttempts.push(now2);
9407
+ const cutoff = now2 - circuitBreakerWindow;
9408
+ const recentAttempts = reloadAttempts.filter((t) => t > cutoff);
9409
+ reloadAttempts.length = 0;
9410
+ reloadAttempts.push(...recentAttempts);
9411
+ if (recentAttempts.length >= circuitBreakerThreshold) {
9412
+ console.error(`[Dashboard Reload] Circuit breaker triggered! ${recentAttempts.length} reload attempts in ${circuitBreakerWindow}ms`);
9413
+ const errorDiv = document.createElement("div");
9414
+ errorDiv.id = "reload-circuit-breaker";
9415
+ errorDiv.style.cssText = `
9416
+ position: fixed;
9417
+ top: 20px;
9418
+ left: 50%;
9419
+ transform: translateX(-50%);
9420
+ background: #dc2626;
9421
+ color: white;
9422
+ padding: 20px 32px;
9423
+ border-radius: 12px;
9424
+ z-index: 99999;
9425
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);
9426
+ font-family: system-ui, -apple-system, sans-serif;
9427
+ `;
9428
+ errorDiv.innerHTML = `
9429
+ <div style="display: flex; align-items: center; gap: 16px;">
9430
+ <svg width="24" height="24" fill="none" stroke="currentColor" viewBox="0 0 24 24">
9431
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
9432
+ </svg>
9433
+ <div>
9434
+ <div style="font-weight: 600; font-size: 16px; margin-bottom: 4px;">Too many reload attempts detected</div>
9435
+ <div style="font-size: 14px; opacity: 0.9;">Please check your network connection and refresh manually.</div>
9436
+ </div>
9437
+ </div>
9438
+ `;
9439
+ const existing = document.getElementById("reload-circuit-breaker");
9440
+ if (existing) existing.remove();
9441
+ document.body.appendChild(errorDiv);
9442
+ return;
9443
+ }
9444
+ if (now2 - firstReloadTime > resetWindow) {
9445
+ reloadCount = 0;
9446
+ firstReloadTime = now2;
9447
+ }
9448
+ if (reloadCount === 0) {
9449
+ firstReloadTime = now2;
9450
+ }
9451
+ reloadCount++;
9452
+ if (reloadCount > maxReloads) {
9453
+ console.error(`[Dashboard Reload] Maximum reload attempts (${maxReloads}) reached. Stopping to prevent infinite loop.`);
9454
+ const errorDiv = document.createElement("div");
9455
+ errorDiv.style.cssText = `
9456
+ position: fixed;
9457
+ top: 20px;
9458
+ left: 50%;
9459
+ transform: translateX(-50%);
9460
+ background: #ef4444;
9461
+ color: white;
9462
+ padding: 16px 24px;
9463
+ border-radius: 8px;
9464
+ z-index: 9999;
9465
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
9466
+ `;
9467
+ errorDiv.innerHTML = `
9468
+ <div style="display: flex; align-items: center; gap: 12px;">
9469
+ <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
9470
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
9471
+ </svg>
9472
+ <span>Stream connection failed. Please refresh the page manually.</span>
9473
+ </div>
9474
+ `;
9475
+ document.body.appendChild(errorDiv);
9476
+ setTimeout(() => {
9477
+ document.body.removeChild(errorDiv);
9478
+ }, 1e4);
9479
+ return;
9480
+ }
9481
+ console.warn(`[Dashboard Reload] Reloading dashboard (attempt ${reloadCount}/${maxReloads})`);
9482
+ window.location.reload();
9483
+ }
9484
+ };
9485
+ return () => {
9486
+ const now2 = Date.now();
9487
+ if (now2 - last >= interval) {
9488
+ last = now2;
9489
+ doReload();
9490
+ } else if (!queued) {
9491
+ queued = true;
9492
+ setTimeout(() => {
9493
+ queued = false;
9494
+ last = Date.now();
9495
+ doReload();
9496
+ }, interval - (now2 - last));
9497
+ }
9498
+ };
9499
+ };
9500
+ var throttledReloadDashboard = createThrottledReload(5e3, 3);
9501
+
9357
9502
  // src/lib/utils/index.ts
9358
9503
  var formatIdleTime = (idleTimeInSeconds) => {
9359
9504
  if (!idleTimeInSeconds || idleTimeInSeconds <= 0) {
@@ -18637,7 +18782,10 @@ var VideoGridView = React19__default.memo(({
18637
18782
  const containerRef = useRef(null);
18638
18783
  const observerRef = useRef(null);
18639
18784
  const [gridCols, setGridCols] = useState(4);
18785
+ const [gridRows, setGridRows] = useState(1);
18640
18786
  const [visibleWorkspaces, setVisibleWorkspaces] = useState(/* @__PURE__ */ new Set());
18787
+ const [cardDimensions, setCardDimensions] = useState({ width: 0, height: 0 });
18788
+ const [failedStreams, setFailedStreams] = useState(/* @__PURE__ */ new Set());
18641
18789
  const videoConfig = useVideoConfig();
18642
18790
  const { cropping, canvasConfig, hlsUrls } = videoConfig;
18643
18791
  const mergedVideoSources = {
@@ -18698,35 +18846,51 @@ var VideoGridView = React19__default.memo(({
18698
18846
  setGridCols(1);
18699
18847
  return;
18700
18848
  }
18701
- let bestCols = 1;
18702
- let bestScore = 0;
18849
+ const optimalLayouts = {
18850
+ 1: 1,
18851
+ 2: 2,
18852
+ 3: 3,
18853
+ 4: 2,
18854
+ 5: 3,
18855
+ 6: 3,
18856
+ 7: 4,
18857
+ 8: 4,
18858
+ 9: 3,
18859
+ 10: 5,
18860
+ 11: 4,
18861
+ 12: 4,
18862
+ 13: 5,
18863
+ 14: 5,
18864
+ 15: 5,
18865
+ 16: 4,
18866
+ 17: 6,
18867
+ 18: 6,
18868
+ 19: 5,
18869
+ 20: 5,
18870
+ 21: 7,
18871
+ 22: 6,
18872
+ 23: 6,
18873
+ 24: 6
18874
+ };
18875
+ let bestCols = optimalLayouts[count] || Math.ceil(Math.sqrt(count));
18876
+ const containerAspectRatio = containerWidth / containerHeight;
18703
18877
  const targetAspectRatio = 16 / 9;
18704
18878
  const gap = 8;
18705
- const maxCols = Math.min(count, selectedLine ? 6 : 12);
18706
- for (let cols = 1; cols <= maxCols; cols++) {
18707
- const rows = Math.ceil(count / cols);
18708
- const availableWidth = containerWidth - gap * (cols - 1);
18709
- const availableHeight = containerHeight - gap * (rows - 1);
18710
- const cellWidth = availableWidth / cols;
18711
- const cellHeight = availableHeight / rows;
18712
- const minCellWidth = selectedLine ? containerWidth < 800 ? 120 : 150 : containerWidth < 800 ? 80 : 100;
18713
- const minCellHeight = selectedLine ? containerHeight < 600 ? 80 : 100 : containerHeight < 600 ? 60 : 80;
18714
- if (cellWidth < minCellWidth || cellHeight < minCellHeight) continue;
18715
- const totalUsedArea = cellWidth * cellHeight * count;
18716
- const totalAvailableArea = containerWidth * containerHeight;
18717
- const spaceUtilization = totalUsedArea / totalAvailableArea;
18718
- const actualAspectRatio = cellWidth / cellHeight;
18719
- const aspectRatioScore = 1 / (1 + Math.abs(actualAspectRatio - targetAspectRatio) * 0.3);
18720
- const score = spaceUtilization * 0.9 + aspectRatioScore * 0.1;
18721
- if (score > bestScore) {
18722
- bestScore = score;
18723
- bestCols = cols;
18724
- }
18725
- }
18726
- if (bestScore === 0) {
18727
- bestCols = Math.ceil(Math.sqrt(count));
18879
+ if (containerAspectRatio > targetAspectRatio * 1.5 && count > 6) {
18880
+ bestCols = Math.min(bestCols + 1, Math.ceil(count / 2));
18881
+ }
18882
+ const minCellWidth = selectedLine ? 150 : 100;
18883
+ const availableWidth = containerWidth - gap * (bestCols - 1);
18884
+ const cellWidth = availableWidth / bestCols;
18885
+ if (cellWidth < minCellWidth && bestCols > 1) {
18886
+ bestCols = Math.floor((containerWidth + gap) / (minCellWidth + gap));
18728
18887
  }
18888
+ const rows = Math.ceil(count / bestCols);
18729
18889
  setGridCols(bestCols);
18890
+ setGridRows(rows);
18891
+ const cardWidth = (containerWidth - gap * (bestCols - 1)) / bestCols;
18892
+ const cardHeight = (containerHeight - gap * (rows - 1)) / rows;
18893
+ setCardDimensions({ width: Math.floor(cardWidth), height: Math.floor(cardHeight) });
18730
18894
  }, [filteredWorkspaces.length, selectedLine]);
18731
18895
  useEffect(() => {
18732
18896
  calculateOptimalGrid();
@@ -18773,17 +18937,25 @@ var VideoGridView = React19__default.memo(({
18773
18937
  action_count: workspace.action_count
18774
18938
  });
18775
18939
  const displayName = getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
18776
- const navParams = getWorkspaceNavigationParams(workspaceId, displayName);
18940
+ const navParams = getWorkspaceNavigationParams(workspaceId, displayName, workspace.line_id);
18777
18941
  router.push(`/workspace/${workspaceId}${navParams}`);
18778
18942
  }, [router]);
18943
+ const handleStreamError = useCallback((workspaceId) => {
18944
+ console.error(`[VideoGridView] Stream failed for workspace: ${workspaceId}`);
18945
+ setFailedStreams((prev) => new Set(prev).add(workspaceId));
18946
+ trackCoreEvent("Video Stream Error", {
18947
+ workspace_id: workspaceId,
18948
+ view_type: "video_grid"
18949
+ });
18950
+ }, []);
18779
18951
  return /* @__PURE__ */ jsx("div", { className: `relative overflow-hidden h-full w-full ${className}`, children: /* @__PURE__ */ jsx("div", { ref: containerRef, className: "h-full w-full p-2", children: /* @__PURE__ */ jsx(
18780
18952
  "div",
18781
18953
  {
18782
18954
  className: "grid h-full w-full gap-2",
18783
18955
  style: {
18784
18956
  gridTemplateColumns: `repeat(${gridCols}, 1fr)`,
18785
- gridTemplateRows: `repeat(${Math.ceil(filteredWorkspaces.length / gridCols)}, 1fr)`,
18786
- minHeight: "100%"
18957
+ gridTemplateRows: `repeat(${gridRows}, 1fr)`,
18958
+ gridAutoFlow: "row"
18787
18959
  },
18788
18960
  children: filteredWorkspaces.sort((a, b) => {
18789
18961
  if (a.line_id !== b.line_id) {
@@ -18806,23 +18978,22 @@ var VideoGridView = React19__default.memo(({
18806
18978
  "div",
18807
18979
  {
18808
18980
  "data-workspace-id": workspaceId,
18809
- className: "workspace-card relative min-h-0 min-w-0",
18810
- style: { width: "100%", height: "100%" },
18811
- children: /* @__PURE__ */ jsx(
18981
+ className: "workspace-card relative w-full h-full",
18982
+ children: /* @__PURE__ */ jsx("div", { className: "absolute inset-0", children: /* @__PURE__ */ jsx(
18812
18983
  VideoCard,
18813
18984
  {
18814
18985
  workspace,
18815
18986
  hlsUrl: getWorkspaceHlsUrl(workspace.workspace_name, workspace.line_id),
18816
- shouldPlay: isVisible,
18987
+ shouldPlay: isVisible && !failedStreams.has(workspaceId),
18817
18988
  onClick: () => handleWorkspaceClick(workspace),
18818
- onFatalError: throttledReloadDashboard,
18989
+ onFatalError: () => handleStreamError(workspaceId),
18819
18990
  isVeryLowEfficiency,
18820
18991
  cropping: workspaceCropping,
18821
18992
  canvasFps: canvasConfig?.fps,
18822
18993
  useRAF: canvasConfig?.useRAF,
18823
18994
  compact: !selectedLine
18824
18995
  }
18825
- )
18996
+ ) })
18826
18997
  },
18827
18998
  workspaceId
18828
18999
  );
@@ -23982,7 +24153,7 @@ var WorkspaceGridItem = React19__default.memo(({
23982
24153
  e.preventDefault();
23983
24154
  if (isInactive) return;
23984
24155
  const displayName = getWorkspaceDisplayName(data.workspace_name, data.line_id);
23985
- const navParams = getWorkspaceNavigationParams(data.workspace_id, displayName);
24156
+ const navParams = getWorkspaceNavigationParams(data.workspace_id, displayName, data.line_id);
23986
24157
  navigate(`/workspace/${data.workspace_id}${navParams}`, {
23987
24158
  trackingEvent: {
23988
24159
  name: "Workspace Detail Clicked",
@@ -28723,6 +28894,73 @@ function HomeView({
28723
28894
  }
28724
28895
  var AuthenticatedHomeView = withAuth(React19__default.memo(HomeView));
28725
28896
  var HomeView_default = HomeView;
28897
+ function withWorkspaceDisplayNames(Component3, options = {}) {
28898
+ const {
28899
+ showLoading = true,
28900
+ loadingMessage = "Initializing workspace data...",
28901
+ initializeFor = "all"
28902
+ } = options;
28903
+ return function WithWorkspaceDisplayNamesWrapper(props) {
28904
+ const [isInitialized2, setIsInitialized] = useState(false);
28905
+ const [error, setError] = useState(null);
28906
+ useEffect(() => {
28907
+ setIsInitialized(false);
28908
+ setError(null);
28909
+ const initializeDisplayNames = async () => {
28910
+ try {
28911
+ const { lineIds, selectedLineId, factoryViewId } = props;
28912
+ let lineIdArray = [];
28913
+ if (Array.isArray(lineIds)) {
28914
+ lineIdArray = lineIds;
28915
+ } else if (lineIds && typeof lineIds === "object") {
28916
+ lineIdArray = Object.values(lineIds).filter((id3) => !!id3);
28917
+ }
28918
+ if (initializeFor === "specific" && selectedLineId) {
28919
+ if (selectedLineId === factoryViewId && lineIdArray.length > 0) {
28920
+ await Promise.all(
28921
+ lineIdArray.map((lineId) => preInitializeWorkspaceDisplayNames(lineId))
28922
+ );
28923
+ } else {
28924
+ await preInitializeWorkspaceDisplayNames(selectedLineId);
28925
+ }
28926
+ } else if (lineIdArray.length > 0) {
28927
+ await Promise.all(
28928
+ lineIdArray.map((lineId) => preInitializeWorkspaceDisplayNames(lineId))
28929
+ );
28930
+ } else {
28931
+ await preInitializeWorkspaceDisplayNames();
28932
+ }
28933
+ setIsInitialized(true);
28934
+ } catch (err) {
28935
+ console.error("Failed to initialize workspace display names:", err);
28936
+ setError(err);
28937
+ setIsInitialized(true);
28938
+ }
28939
+ };
28940
+ initializeDisplayNames();
28941
+ }, [
28942
+ Array.isArray(props.lineIds) ? props.lineIds.join(",") : JSON.stringify(props.lineIds),
28943
+ props.selectedLineId,
28944
+ props.factoryViewId,
28945
+ initializeFor
28946
+ ]);
28947
+ if (!isInitialized2 && showLoading) {
28948
+ return /* @__PURE__ */ jsx(LoadingPage, { message: loadingMessage });
28949
+ }
28950
+ if (error && showLoading) {
28951
+ console.warn("Workspace display names initialization failed, proceeding anyway:", error);
28952
+ }
28953
+ return /* @__PURE__ */ jsx(Component3, { ...props });
28954
+ };
28955
+ }
28956
+ var withAllWorkspaceDisplayNames = (Component3) => withWorkspaceDisplayNames(Component3, {
28957
+ initializeFor: "all",
28958
+ showLoading: true
28959
+ });
28960
+ var withSelectedLineDisplayNames = (Component3) => withWorkspaceDisplayNames(Component3, {
28961
+ initializeFor: "specific",
28962
+ showLoading: true
28963
+ });
28726
28964
 
28727
28965
  // src/views/kpi-detail-view.types.ts
28728
28966
  var pageVariants = {
@@ -28783,11 +29021,6 @@ var itemVariants = {
28783
29021
  }
28784
29022
  }
28785
29023
  };
28786
-
28787
- // src/lib/utils/navigation.ts
28788
- function getWorkspaceNavigationParams2(workspaceUuid, displayName) {
28789
- return `?name=${encodeURIComponent(displayName || "")}`;
28790
- }
28791
29024
  var formatLocalDate = (date) => {
28792
29025
  const options = {
28793
29026
  year: "numeric",
@@ -28903,7 +29136,7 @@ var BottomSection = memo(({
28903
29136
  }
28904
29137
  const clickHandler = () => handleWorkspaceClick(ws, index);
28905
29138
  const displayName = getWorkspaceDisplayName(ws.workspace_name, lineId);
28906
- const navParams = wsUuid ? getWorkspaceNavigationParams2(wsUuid, displayName) : "";
29139
+ const navParams = wsUuid ? getWorkspaceNavigationParams(wsUuid, displayName, lineId) : "";
28907
29140
  const dateShiftParams = urlDate ? `&date=${urlDate}&shift=${urlShift || "0"}` : "";
28908
29141
  const returnToParam = `&returnTo=${encodeURIComponent(`/kpis/${lineInfo?.line_id}`)}`;
28909
29142
  const fullUrl = `/workspace/${wsUuid}${navParams}${dateShiftParams}${returnToParam}`;
@@ -28937,7 +29170,7 @@ var BottomSection = memo(({
28937
29170
  sortedByEfficiency.map((ws, index) => {
28938
29171
  const clickHandler = () => handleWorkspaceClick(ws, index);
28939
29172
  const displayName = getWorkspaceDisplayName(ws.workspace_name, lineId);
28940
- const navParams = ws.workspace_uuid ? getWorkspaceNavigationParams2(ws.workspace_uuid, displayName) : "";
29173
+ const navParams = ws.workspace_uuid ? getWorkspaceNavigationParams(ws.workspace_uuid, displayName, lineId) : "";
28941
29174
  const dateShiftParams = urlDate ? `&date=${urlDate}&shift=${urlShift || "0"}` : "";
28942
29175
  const returnToParam = `&returnTo=${encodeURIComponent(`/kpis/${lineInfo?.line_id}`)}`;
28943
29176
  const fullUrl = `/workspace/${ws.workspace_uuid}${navParams}${dateShiftParams}${returnToParam}`;
@@ -29552,7 +29785,8 @@ var KPIDetailView = ({
29552
29785
  ) }) })
29553
29786
  ] });
29554
29787
  };
29555
- var KPIDetailView_default = KPIDetailView;
29788
+ var KPIDetailViewWithDisplayNames = withSelectedLineDisplayNames(KPIDetailView);
29789
+ var KPIDetailView_default = KPIDetailViewWithDisplayNames;
29556
29790
  var LineCard = ({ line, onClick }) => {
29557
29791
  const { kpis, isLoading, error } = useLineKPIs({ lineId: line.id });
29558
29792
  const isOnTrack = React19__default.useMemo(() => {
@@ -30042,7 +30276,7 @@ var LeaderboardDetailView = memo(({
30042
30276
  action_threshold: workspace.action_threshold
30043
30277
  });
30044
30278
  const displayName = getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
30045
- const navParams = workspace.workspace_uuid ? getWorkspaceNavigationParams(workspace.workspace_uuid, displayName) : "";
30279
+ const navParams = workspace.workspace_uuid ? getWorkspaceNavigationParams(workspace.workspace_uuid, displayName, workspace.line_id) : "";
30046
30280
  const returnToParam = `&returnTo=${encodeURIComponent(`/leaderboard`)}`;
30047
30281
  if (onWorkspaceClick) {
30048
30282
  onWorkspaceClick(workspace, rank);
@@ -30176,7 +30410,8 @@ var LeaderboardDetailView = memo(({
30176
30410
  return prevProps.lineId === nextProps.lineId && prevProps.date === nextProps.date && prevProps.shift === nextProps.shift && prevProps.line1Id === nextProps.line1Id && prevProps.line2Id === nextProps.line2Id && JSON.stringify(prevProps.lineNames) === JSON.stringify(nextProps.lineNames) && prevProps.className === nextProps.className && prevProps.onBackClick === nextProps.onBackClick && prevProps.onWorkspaceClick === nextProps.onWorkspaceClick;
30177
30411
  });
30178
30412
  LeaderboardDetailView.displayName = "LeaderboardDetailView";
30179
- var LeaderboardDetailView_default = LeaderboardDetailView;
30413
+ var LeaderboardDetailViewWithDisplayNames = withAllWorkspaceDisplayNames(LeaderboardDetailView);
30414
+ var LeaderboardDetailView_default = LeaderboardDetailViewWithDisplayNames;
30180
30415
  function LoginView({
30181
30416
  logoSrc = "/optifye-logo.png",
30182
30417
  logoAlt = "Optifye",
@@ -32296,7 +32531,12 @@ var TargetsView = ({
32296
32531
  }
32297
32532
  }), {});
32298
32533
  }, [lineIds]);
32299
- const [lineWorkspaces, setLineWorkspaces] = useState(initialLineWorkspaces);
32534
+ const [allShiftsData, setAllShiftsData] = useState({
32535
+ 0: initialLineWorkspaces,
32536
+ // Day shift
32537
+ 1: initialLineWorkspaces
32538
+ // Night shift (will be populated on first load)
32539
+ });
32300
32540
  const [actionIds, setActionIds] = useState(null);
32301
32541
  const [savingLines, setSavingLines] = useState(
32302
32542
  () => lineIds.reduce((acc, id3) => ({ ...acc, [id3]: false }), {})
@@ -32308,6 +32548,13 @@ var TargetsView = ({
32308
32548
  const [isBulkConfigureOpen, setIsBulkConfigureOpen] = useState(false);
32309
32549
  const [selectedWorkspaces, setSelectedWorkspaces] = useState([]);
32310
32550
  const [selectedShift, setSelectedShift] = useState(0);
32551
+ const lineWorkspaces = allShiftsData[selectedShift] || initialLineWorkspaces;
32552
+ const setLineWorkspaces = useCallback((updater) => {
32553
+ setAllShiftsData((prev) => ({
32554
+ ...prev,
32555
+ [selectedShift]: typeof updater === "function" ? updater(prev[selectedShift]) : updater
32556
+ }));
32557
+ }, [selectedShift]);
32311
32558
  const supabase = useSupabase();
32312
32559
  const auth = useAuth();
32313
32560
  userId || auth?.user?.id;
@@ -32378,7 +32625,7 @@ var TargetsView = ({
32378
32625
  };
32379
32626
  fetchActions();
32380
32627
  }, [supabase, companyId]);
32381
- const fetchLineThresholds = useCallback(async () => {
32628
+ useCallback(async (shiftId) => {
32382
32629
  try {
32383
32630
  if (!supabase) return;
32384
32631
  const currentDate = getOperationalDate();
@@ -32446,15 +32693,7 @@ var TargetsView = ({
32446
32693
  shiftEndTime: endTime,
32447
32694
  breaks,
32448
32695
  shiftHours: Number(shiftHours),
32449
- workspaces: (currentLineStateFromLoop?.workspaces || []).map((ws) => ({
32450
- ...ws,
32451
- targetPPH: ws.targetCycleTime !== "" ? calculatePPH(ws.targetCycleTime, breaks, Number(shiftHours)) : ws.targetPPH,
32452
- targetDayOutput: calculateDayOutput(
32453
- ws.targetCycleTime !== "" ? calculatePPH(ws.targetCycleTime, breaks, Number(shiftHours)) : ws.targetPPH,
32454
- Number(shiftHours),
32455
- breaks
32456
- )
32457
- }))
32696
+ workspaces: currentLineStateFromLoop?.workspaces || []
32458
32697
  };
32459
32698
  hasUpdates = true;
32460
32699
  }
@@ -32468,7 +32707,71 @@ var TargetsView = ({
32468
32707
  } catch (error) {
32469
32708
  console.error("Error in fetchLineThresholds outer try-catch:", error);
32470
32709
  }
32471
- }, [selectedShift, supabase, lineIds, lineWorkspaces]);
32710
+ }, [selectedShift, supabase, lineIds, lineWorkspaces, allShiftsData]);
32711
+ const fetchAllShiftsData = useCallback(async (currentWorkspaces) => {
32712
+ if (!supabase) return;
32713
+ const currentDate = getOperationalDate();
32714
+ const newAllShiftsData = {
32715
+ 0: JSON.parse(JSON.stringify(currentWorkspaces)),
32716
+ // Deep clone for day shift
32717
+ 1: JSON.parse(JSON.stringify(currentWorkspaces))
32718
+ // Deep clone for night shift
32719
+ };
32720
+ for (const shiftId of [0, 1]) {
32721
+ for (const lineId of lineIds) {
32722
+ try {
32723
+ const { data: operatingHours, error: hoursError } = await supabase.from("line_operating_hours").select("start_time, end_time, breaks").eq("line_id", lineId).eq("shift_id", shiftId).maybeSingle();
32724
+ if (hoursError) {
32725
+ console.error(`Error fetching operating hours for line ${lineId}, shift ${shiftId}:`, hoursError);
32726
+ continue;
32727
+ }
32728
+ let breaks = [];
32729
+ if (operatingHours?.breaks) {
32730
+ if (Array.isArray(operatingHours.breaks)) {
32731
+ breaks = operatingHours.breaks.map((breakItem) => ({
32732
+ startTime: breakItem.start || breakItem.startTime || "00:00",
32733
+ endTime: breakItem.end || breakItem.endTime || "00:00",
32734
+ duration: breakItem.duration || calculateShiftHours2(breakItem.start || breakItem.startTime || "00:00", breakItem.end || breakItem.endTime || "00:00", []) * 60
32735
+ }));
32736
+ }
32737
+ }
32738
+ const startTime = operatingHours?.start_time || "08:00";
32739
+ const endTime = operatingHours?.end_time || "19:00";
32740
+ const shiftHours = calculateShiftHours2(startTime, endTime, breaks);
32741
+ const actionThresholds = await workspaceService.getActionThresholds(
32742
+ lineId,
32743
+ currentDate,
32744
+ shiftId
32745
+ );
32746
+ const existingLine = newAllShiftsData[shiftId][lineId];
32747
+ if (existingLine) {
32748
+ newAllShiftsData[shiftId][lineId] = {
32749
+ ...existingLine,
32750
+ shiftStartTime: startTime,
32751
+ shiftEndTime: endTime,
32752
+ breaks,
32753
+ shiftHours: Number(shiftHours),
32754
+ workspaces: existingLine.workspaces.map((ws) => {
32755
+ const threshold = actionThresholds.find((t) => t.workspace_id === ws.id);
32756
+ if (threshold) {
32757
+ return {
32758
+ ...ws,
32759
+ targetPPH: threshold.pph_threshold,
32760
+ targetCycleTime: threshold.ideal_cycle_time,
32761
+ targetDayOutput: threshold.total_day_output
32762
+ };
32763
+ }
32764
+ return ws;
32765
+ })
32766
+ };
32767
+ }
32768
+ } catch (error) {
32769
+ console.error(`Error fetching data for line ${lineId}, shift ${shiftId}:`, error);
32770
+ }
32771
+ }
32772
+ }
32773
+ setAllShiftsData(newAllShiftsData);
32774
+ }, [supabase, lineIds]);
32472
32775
  const loadOperatingHours = useCallback(async (lineId, shiftId) => {
32473
32776
  try {
32474
32777
  if (!supabase) return null;
@@ -32573,7 +32876,7 @@ var TargetsView = ({
32573
32876
  (line) => line.workspaces && line.workspaces.length > 0
32574
32877
  );
32575
32878
  if (workspacesAlreadyLoadedForAnyLine) {
32576
- fetchLineThresholds();
32879
+ setIsLoading(false);
32577
32880
  return;
32578
32881
  }
32579
32882
  const fetchWorkspacesAndThenThresholds = async () => {
@@ -32594,7 +32897,7 @@ var TargetsView = ({
32594
32897
  }
32595
32898
  try {
32596
32899
  const fetchedLineWorkspacesData = await workspaceService.getWorkspaces(lineId);
32597
- const mappedWorkspaces = fetchedLineWorkspacesData.map((ws) => ({
32900
+ let mappedWorkspaces = fetchedLineWorkspacesData.map((ws) => ({
32598
32901
  id: ws.id,
32599
32902
  name: ws.workspace_id,
32600
32903
  targetPPH: ws.action_pph_threshold === null ? "" : ws.action_pph_threshold,
@@ -32603,6 +32906,29 @@ var TargetsView = ({
32603
32906
  actionType: ws.action_id === actionIds.assembly ? "assembly" : ws.action_id === actionIds.packaging ? "packaging" : "assembly",
32604
32907
  actionId: ws.action_id === actionIds.assembly ? actionIds.assembly : ws.action_id === actionIds.packaging ? actionIds.packaging : actionIds.assembly
32605
32908
  })).sort((a, b) => a.name.localeCompare(b.name, void 0, { numeric: true }));
32909
+ const currentDate = getOperationalDate();
32910
+ try {
32911
+ const actionThresholds = await workspaceService.getActionThresholds(
32912
+ lineId,
32913
+ currentDate,
32914
+ selectedShift
32915
+ );
32916
+ mappedWorkspaces = mappedWorkspaces.map((ws) => {
32917
+ const threshold = actionThresholds.find((t) => t.workspace_id === ws.id);
32918
+ if (threshold) {
32919
+ return {
32920
+ ...ws,
32921
+ targetPPH: threshold.pph_threshold,
32922
+ targetCycleTime: threshold.ideal_cycle_time,
32923
+ targetDayOutput: threshold.total_day_output
32924
+ };
32925
+ }
32926
+ return ws;
32927
+ });
32928
+ console.log(`Merged action thresholds for line ${lineId}, found ${actionThresholds.length} saved thresholds`);
32929
+ } catch (error) {
32930
+ console.error(`Error fetching action thresholds for line ${lineId}:`, error);
32931
+ }
32606
32932
  if (JSON.stringify(mappedWorkspaces) !== JSON.stringify(newUpdatedLineWorkspaces[lineId].workspaces)) {
32607
32933
  newUpdatedLineWorkspaces[lineId] = {
32608
32934
  ...newUpdatedLineWorkspaces[lineId],
@@ -32617,7 +32943,7 @@ var TargetsView = ({
32617
32943
  if (workspacesHaveBeenUpdated) {
32618
32944
  setLineWorkspaces(newUpdatedLineWorkspaces);
32619
32945
  }
32620
- await fetchLineThresholds();
32946
+ await fetchAllShiftsData(newUpdatedLineWorkspaces);
32621
32947
  } catch (error) {
32622
32948
  console.error("Error in fetchWorkspacesAndThenThresholds:", error);
32623
32949
  toast.error("Failed to load workspace data");
@@ -32626,37 +32952,7 @@ var TargetsView = ({
32626
32952
  }
32627
32953
  };
32628
32954
  fetchWorkspacesAndThenThresholds();
32629
- }, [actionIds, supabase, lineIds, lineWorkspaces, fetchLineThresholds]);
32630
- useEffect(() => {
32631
- if (Object.keys(lineWorkspaces).length > 0) {
32632
- const updatedLineWorkspaces = { ...lineWorkspaces };
32633
- let hasChanges = false;
32634
- Object.keys(updatedLineWorkspaces).forEach((lineId) => {
32635
- const line = updatedLineWorkspaces[lineId];
32636
- const shiftHours = calculateShiftHours2(line.shiftStartTime, line.shiftEndTime, line.breaks);
32637
- if (shiftHours !== line.shiftHours) {
32638
- hasChanges = true;
32639
- updatedLineWorkspaces[lineId] = {
32640
- ...line,
32641
- shiftHours,
32642
- workspaces: line.workspaces.map((ws) => {
32643
- const targetDayOutput = calculateDayOutput(ws.targetPPH, shiftHours, line.breaks);
32644
- if (targetDayOutput !== ws.targetDayOutput) {
32645
- return {
32646
- ...ws,
32647
- targetDayOutput
32648
- };
32649
- }
32650
- return ws;
32651
- })
32652
- };
32653
- }
32654
- });
32655
- if (hasChanges) {
32656
- setLineWorkspaces(updatedLineWorkspaces);
32657
- }
32658
- }
32659
- }, [selectedShift]);
32955
+ }, [actionIds, supabase, lineIds]);
32660
32956
  const toggleLineDropdown = useCallback((lineId) => {
32661
32957
  setLineWorkspaces((prev) => {
32662
32958
  const newIsOpen = !prev[lineId].isOpen;
@@ -32740,6 +33036,16 @@ var TargetsView = ({
32740
33036
  updates.targetDayOutput = calculateDayOutput(value, shiftHours, prev[lineId].breaks);
32741
33037
  } else if (field === "targetDayOutput") {
32742
33038
  updates.targetDayOutput = value;
33039
+ if (value !== "") {
33040
+ const breaks = prev[lineId].breaks;
33041
+ const totalBreakMinutes = breaks.reduce((total, b) => total + b.duration, 0);
33042
+ const totalBreakHours = totalBreakMinutes / 60;
33043
+ const realWorkHours = shiftHours - totalBreakHours;
33044
+ const calculatedPPH = Math.round(value / realWorkHours);
33045
+ updates.targetPPH = calculatedPPH;
33046
+ } else {
33047
+ updates.targetPPH = "";
33048
+ }
32743
33049
  }
32744
33050
  updates[field] = value;
32745
33051
  return updates;
@@ -33001,8 +33307,9 @@ var TargetsView = ({
33001
33307
  }
33002
33308
  );
33003
33309
  };
33004
- var TargetsView_default = TargetsView;
33005
- var AuthenticatedTargetsView = withAuth(TargetsView);
33310
+ var TargetsViewWithDisplayNames = withAllWorkspaceDisplayNames(TargetsView);
33311
+ var TargetsView_default = TargetsViewWithDisplayNames;
33312
+ var AuthenticatedTargetsView = withAuth(TargetsViewWithDisplayNames);
33006
33313
 
33007
33314
  // src/views/workspace-detail-view.utils.ts
33008
33315
  var formatISTDate2 = (date = /* @__PURE__ */ new Date(), options) => {
@@ -33018,8 +33325,8 @@ var formatISTDate2 = (date = /* @__PURE__ */ new Date(), options) => {
33018
33325
  });
33019
33326
  return formatter.format(date);
33020
33327
  };
33021
- var formatWorkspaceName3 = (name) => {
33022
- return getWorkspaceDisplayName(name);
33328
+ var formatWorkspaceName3 = (name, lineId) => {
33329
+ return getWorkspaceDisplayName(name, lineId);
33023
33330
  };
33024
33331
  var getDaysDifference = (date) => {
33025
33332
  const today = /* @__PURE__ */ new Date();
@@ -33056,9 +33363,11 @@ var WorkspaceDetailView = ({
33056
33363
  fromMonthly = false,
33057
33364
  sourceType,
33058
33365
  displayName,
33366
+ lineId,
33059
33367
  defaultTab,
33060
33368
  returnUrl,
33061
33369
  lineIds = { line1: "", line2: "" },
33370
+ selectedLineId,
33062
33371
  onNavigate,
33063
33372
  onTabChange,
33064
33373
  onDateSelect,
@@ -33221,7 +33530,8 @@ var WorkspaceDetailView = ({
33221
33530
  setSelectedMonth(newMonth);
33222
33531
  setSelectedYear(newYear);
33223
33532
  };
33224
- const formattedWorkspaceName = displayName || formatWorkspaceName3(workspace?.workspace_name || "");
33533
+ const effectiveLineId = lineId || selectedLineId;
33534
+ const formattedWorkspaceName = displayName || formatWorkspaceName3(workspace?.workspace_name || "", effectiveLineId);
33225
33535
  const shouldShowCycleTimeChart = showCycleTimeChart ?? formattedWorkspaceName.startsWith("FINAL ASSY");
33226
33536
  const handleBackNavigation = () => {
33227
33537
  if (returnUrl) {
@@ -33233,13 +33543,23 @@ var WorkspaceDetailView = ({
33233
33543
  if (date || shift) {
33234
33544
  setActiveTab("monthly_history");
33235
33545
  if (onNavigate) {
33236
- onNavigate(`/workspace/${workspaceId}?fromMonthly=true`);
33546
+ const params = new URLSearchParams();
33547
+ params.set("fromMonthly", "true");
33548
+ if (effectiveLineId) {
33549
+ params.set("lineId", effectiveLineId);
33550
+ }
33551
+ onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
33237
33552
  }
33238
33553
  } else {
33239
33554
  if (previousView === "line_monthly_history") {
33240
33555
  setActiveTab("monthly_history");
33241
33556
  if (onNavigate) {
33242
- onNavigate(`/workspace/${workspaceId}?fromMonthly=true`);
33557
+ const params = new URLSearchParams();
33558
+ params.set("fromMonthly", "true");
33559
+ if (effectiveLineId) {
33560
+ params.set("lineId", effectiveLineId);
33561
+ }
33562
+ onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
33243
33563
  }
33244
33564
  } else {
33245
33565
  if (onNavigate) {
@@ -33697,7 +34017,13 @@ var WorkspaceDetailView = ({
33697
34017
  if (onDateSelect) {
33698
34018
  onDateSelect(selectedDate, selectedShift);
33699
34019
  } else if (onNavigate) {
33700
- onNavigate(`/workspace/${workspaceId}?date=${selectedDate}&shift=${selectedShift === "day" ? "0" : "1"}`);
34020
+ const params = new URLSearchParams();
34021
+ params.set("date", selectedDate);
34022
+ params.set("shift", selectedShift === "day" ? "0" : "1");
34023
+ if (effectiveLineId) {
34024
+ params.set("lineId", effectiveLineId);
34025
+ }
34026
+ onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
33701
34027
  }
33702
34028
  },
33703
34029
  onMonthNavigate: (newMonth, newYear) => {
@@ -33724,7 +34050,12 @@ var WorkspaceDetailView = ({
33724
34050
  }
33725
34051
  );
33726
34052
  };
33727
- var WrappedComponent = withAuth(WorkspaceDetailView);
34053
+ var WorkspaceDetailViewWithDisplayNames = withSelectedLineDisplayNames(WorkspaceDetailView);
34054
+ var WorkspaceDetailViewFinal = (props) => {
34055
+ const componentKey = `${props.date || "live"}_${props.shift || "current"}`;
34056
+ return /* @__PURE__ */ jsx(WorkspaceDetailViewWithDisplayNames, { ...props }, componentKey);
34057
+ };
34058
+ var WrappedComponent = withAuth(WorkspaceDetailViewFinal);
33728
34059
  var WorkspaceDetailView_default = WrappedComponent;
33729
34060
  var SKUManagementView = () => {
33730
34061
  const config = useDashboardConfig();
@@ -34102,4 +34433,4 @@ var S3Service = class {
34102
34433
  }
34103
34434
  };
34104
34435
 
34105
- export { ACTION_NAMES, AIAgentView_default as AIAgentView, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedTargetsView, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_THEME_CONFIG, DEFAULT_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, EmptyStateMessage, FactoryView_default as FactoryView, GaugeChart, GridComponentsPlaceholder, Header, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend6 as Legend, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, NoWorkspaceData, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, ProfileView_default as ProfileView, RegistryProvider, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SingleVideoStream_default as SingleVideoStream, Skeleton, SlackAPI, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TimeDisplay_default as TimeDisplay, TimePickerDropdown, VideoCard, VideoGridView, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, cacheService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createStreamProxyHandler, createSupabaseClient, createThrottledReload, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isLegacyConfiguration, isTransitionPeriod, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, mergeWithDefaultConfig, migrateLegacyConfiguration, optifyeAgentClient, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetSubscriptionManager, s3VideoPreloader, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useActiveBreaks, useAllWorkspaceMetrics, useAnalyticsConfig, useAuth, useAuthConfig, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, useRealtimeLineMetrics, useRegistry, useSKUs, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, videoPreloader, whatsappService, withAuth, withRegistry, workspaceService };
34436
+ export { ACTION_NAMES, AIAgentView_default as AIAgentView, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedTargetsView, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_THEME_CONFIG, DEFAULT_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, EmptyStateMessage, FactoryView_default as FactoryView, GaugeChart, GridComponentsPlaceholder, Header, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend6 as Legend, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, NoWorkspaceData, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, ProfileView_default as ProfileView, RegistryProvider, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SingleVideoStream_default as SingleVideoStream, Skeleton, SlackAPI, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TimeDisplay_default as TimeDisplay, TimePickerDropdown, VideoCard, VideoGridView, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, cacheService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createStreamProxyHandler, createSupabaseClient, createThrottledReload, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isLegacyConfiguration, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, mergeWithDefaultConfig, migrateLegacyConfiguration, optifyeAgentClient, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useActiveBreaks, useAllWorkspaceMetrics, useAnalyticsConfig, useAuth, useAuthConfig, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, useRealtimeLineMetrics, useRegistry, useSKUs, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, videoPreloader, whatsappService, withAuth, withRegistry, workspaceService };