@optifye/dashboard-core 6.11.31 → 6.11.33

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
@@ -1,5 +1,5 @@
1
- import * as React142 from 'react';
2
- import React142__default, { createContext, useRef, useCallback, useState, useMemo, useEffect, forwardRef, useImperativeHandle, useLayoutEffect, memo as memo$1, useContext, useSyncExternalStore, useId, Children, isValidElement, useInsertionEffect, startTransition, Fragment as Fragment$1, createElement, Component } from 'react';
1
+ import * as React143 from 'react';
2
+ import React143__default, { createContext, useRef, useCallback, useState, useMemo, useEffect, forwardRef, useImperativeHandle, useLayoutEffect, memo as memo$1, useContext, useSyncExternalStore, useId, Children, isValidElement, useInsertionEffect, startTransition, Fragment as Fragment$1, createElement, Component } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { useRouter } from 'next/router';
5
5
  import { toast } from 'sonner';
@@ -1938,14 +1938,14 @@ var useIdleTimeVlmConfig = () => {
1938
1938
  }
1939
1939
  return context;
1940
1940
  };
1941
- var DashboardConfigContext = React142.createContext(void 0);
1941
+ var DashboardConfigContext = React143.createContext(void 0);
1942
1942
  var DashboardProvider = ({ config: userProvidedConfig, children }) => {
1943
- const fullConfig = React142.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
1943
+ const fullConfig = React143.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
1944
1944
  _setDashboardConfigInstance(fullConfig);
1945
- React142.useEffect(() => {
1945
+ React143.useEffect(() => {
1946
1946
  _setDashboardConfigInstance(fullConfig);
1947
1947
  }, [fullConfig]);
1948
- React142.useEffect(() => {
1948
+ React143.useEffect(() => {
1949
1949
  if (!fullConfig.theme) return;
1950
1950
  const styleId = "dashboard-core-theme-vars";
1951
1951
  let styleEl = document.getElementById(styleId);
@@ -1971,7 +1971,7 @@ var DashboardProvider = ({ config: userProvidedConfig, children }) => {
1971
1971
  return /* @__PURE__ */ jsx(DashboardConfigContext.Provider, { value: fullConfig, children: /* @__PURE__ */ jsx(IdleTimeVlmConfigProvider, { children }) });
1972
1972
  };
1973
1973
  var useDashboardConfig = () => {
1974
- const ctx = React142.useContext(DashboardConfigContext);
1974
+ const ctx = React143.useContext(DashboardConfigContext);
1975
1975
  if (!ctx) throw new Error("useDashboardConfig must be used within a DashboardProvider");
1976
1976
  return ctx;
1977
1977
  };
@@ -2444,6 +2444,107 @@ var _getSupabaseInstanceOptional = () => {
2444
2444
  return supabaseInstance;
2445
2445
  };
2446
2446
 
2447
+ // src/lib/utils/sentryContext.ts
2448
+ function getSentry() {
2449
+ try {
2450
+ return __require("@sentry/nextjs");
2451
+ } catch {
2452
+ return null;
2453
+ }
2454
+ }
2455
+ function isIgnorableFrontendError(error) {
2456
+ const name = error && typeof error === "object" ? error.name || "" : "";
2457
+ const message = error instanceof Error ? error.message : String(error ?? "");
2458
+ const lowerMessage = message.toLowerCase();
2459
+ return name === "AbortError" || lowerMessage.includes("the operation was aborted") || lowerMessage.includes("signal is aborted") || lowerMessage.includes("resizeobserver loop");
2460
+ }
2461
+ function setSentryUserContext(user) {
2462
+ const sentry = getSentry();
2463
+ if (!sentry) return;
2464
+ if (user) {
2465
+ sentry.setUser({
2466
+ id: user.id,
2467
+ email: user.email
2468
+ });
2469
+ sentry.setTags({
2470
+ company_id: user.company_id || "unknown",
2471
+ role: user.role || "unknown",
2472
+ role_level: user.role_level || "unknown"
2473
+ });
2474
+ } else {
2475
+ sentry.setUser(null);
2476
+ sentry.setTags({
2477
+ company_id: void 0,
2478
+ role: void 0,
2479
+ role_level: void 0
2480
+ });
2481
+ }
2482
+ }
2483
+ function setSentryWorkspaceContext(config) {
2484
+ const sentry = getSentry();
2485
+ if (!sentry) return;
2486
+ sentry.setTags({
2487
+ workspace_company: config.companyId || "unknown",
2488
+ workspace_factory: config.factoryId || "unknown",
2489
+ factory_name: config.factoryName || "unknown"
2490
+ });
2491
+ }
2492
+ function clearSentryContext() {
2493
+ const sentry = getSentry();
2494
+ if (!sentry) return;
2495
+ sentry.setUser(null);
2496
+ sentry.setTags({
2497
+ company_id: void 0,
2498
+ role: void 0,
2499
+ role_level: void 0,
2500
+ workspace_company: void 0,
2501
+ workspace_factory: void 0,
2502
+ factory_name: void 0
2503
+ });
2504
+ }
2505
+ function applyScopeExtras(scope, extras) {
2506
+ if (!extras) return;
2507
+ if (scope.setExtras) {
2508
+ scope.setExtras(extras);
2509
+ return;
2510
+ }
2511
+ if (scope.setExtra) {
2512
+ Object.entries(extras).forEach(([key, value]) => scope.setExtra?.(key, value));
2513
+ }
2514
+ }
2515
+ function captureSentryMessage(message, level = "warning", extras) {
2516
+ const sentry = getSentry();
2517
+ if (!sentry || !sentry.captureMessage) return;
2518
+ if (sentry.withScope) {
2519
+ sentry.withScope((scope) => {
2520
+ scope.setLevel?.(level);
2521
+ applyScopeExtras(scope, extras);
2522
+ sentry.captureMessage?.(message);
2523
+ });
2524
+ return;
2525
+ }
2526
+ sentry.captureMessage(message, level);
2527
+ }
2528
+ function captureSentryException(error, extras) {
2529
+ const sentry = getSentry();
2530
+ if (!sentry || !sentry.captureException) return;
2531
+ if (sentry.withScope) {
2532
+ sentry.withScope((scope) => {
2533
+ scope.setLevel?.("error");
2534
+ applyScopeExtras(scope, extras);
2535
+ sentry.captureException?.(error);
2536
+ });
2537
+ return;
2538
+ }
2539
+ sentry.captureException(error);
2540
+ }
2541
+ function captureHandledFrontendException(error, extras) {
2542
+ if (isIgnorableFrontendError(error)) {
2543
+ return;
2544
+ }
2545
+ captureSentryException(error, extras);
2546
+ }
2547
+
2447
2548
  // src/lib/services/backendClient.ts
2448
2549
  var ACCESS_TOKEN_REFRESH_BUFFER_MS = 6e4;
2449
2550
  var cachedAccessToken = null;
@@ -2499,6 +2600,40 @@ var defaultDedupeKey = (method, url, body) => {
2499
2600
  const bodyKey = body === void 0 ? "" : typeof body === "string" ? body : JSON.stringify(body);
2500
2601
  return `${cachedUserId || "anon"}::${method.toUpperCase()}::${url}::${bodyKey}`;
2501
2602
  };
2603
+ var DEFAULT_TIMEOUT_MS = 1e4;
2604
+ var DEFAULT_RETRY_DELAY_MS = 750;
2605
+ var createAbortError = () => {
2606
+ try {
2607
+ return new DOMException("The operation was aborted.", "AbortError");
2608
+ } catch {
2609
+ const error = new Error("The operation was aborted.");
2610
+ error.name = "AbortError";
2611
+ return error;
2612
+ }
2613
+ };
2614
+ var getStatusFromError = (error) => {
2615
+ const message = error instanceof Error ? error.message : String(error ?? "");
2616
+ const statusMatch = message.match(/\((\d{3})\)/) || message.match(/http\s+(\d{3})/i);
2617
+ if (!statusMatch) {
2618
+ return null;
2619
+ }
2620
+ const status = Number.parseInt(statusMatch[1], 10);
2621
+ return Number.isFinite(status) ? status : null;
2622
+ };
2623
+ var isAbortError = (error) => {
2624
+ return error instanceof Error && error.name === "AbortError";
2625
+ };
2626
+ var isRetryableError = (error) => {
2627
+ if (isAbortError(error)) {
2628
+ return false;
2629
+ }
2630
+ const status = getStatusFromError(error);
2631
+ if (status !== null) {
2632
+ return status >= 500 || status === 408 || status === 425 || status === 429;
2633
+ }
2634
+ const message = error instanceof Error ? error.message.toLowerCase() : String(error ?? "").toLowerCase();
2635
+ return message.includes("failed to fetch") || message.includes("networkerror") || message.includes("network request failed") || message.includes("load failed") || message.includes("timed out") || message.includes("fetch failed");
2636
+ };
2502
2637
  var fetchBackendJson = async (supabase, endpoint, options = {}) => {
2503
2638
  const baseUrl = getBackendUrl();
2504
2639
  const url = endpoint.startsWith("http") ? endpoint : `${baseUrl}${endpoint.startsWith("/") ? "" : "/"}${endpoint}`;
@@ -2510,25 +2645,66 @@ var fetchBackendJson = async (supabase, endpoint, options = {}) => {
2510
2645
  return existing;
2511
2646
  }
2512
2647
  const requestPromise = (async () => {
2513
- const headers = new Headers(options.headers || {});
2514
- if (!options.skipAuth) {
2515
- const token = await getAuthToken(supabase);
2516
- headers.set("Authorization", `Bearer ${token}`);
2517
- }
2518
- if (!headers.has("Content-Type") && options.body !== void 0) {
2519
- headers.set("Content-Type", "application/json");
2520
- }
2521
- const response = await fetch(url, {
2522
- ...options,
2523
- headers
2524
- });
2525
- if (!response.ok) {
2526
- const errorText = await response.text();
2527
- throw new Error(`Backend API error (${response.status}): ${errorText}`);
2648
+ const {
2649
+ dedupeKey: _dedupeKey,
2650
+ skipAuth,
2651
+ timeoutMs = DEFAULT_TIMEOUT_MS,
2652
+ retries = 0,
2653
+ retryDelayMs = DEFAULT_RETRY_DELAY_MS,
2654
+ signal: externalSignal,
2655
+ ...fetchOptions
2656
+ } = options;
2657
+ for (let attempt = 0; attempt <= retries; attempt += 1) {
2658
+ if (externalSignal?.aborted) {
2659
+ throw createAbortError();
2660
+ }
2661
+ const headers = new Headers(fetchOptions.headers || {});
2662
+ if (!skipAuth) {
2663
+ const token = await getAuthToken(supabase);
2664
+ headers.set("Authorization", `Bearer ${token}`);
2665
+ }
2666
+ if (!headers.has("Content-Type") && fetchOptions.body !== void 0) {
2667
+ headers.set("Content-Type", "application/json");
2668
+ }
2669
+ const controller = new AbortController();
2670
+ const timeoutId = globalThis.setTimeout(() => controller.abort(), timeoutMs);
2671
+ const abortListener = () => controller.abort();
2672
+ externalSignal?.addEventListener("abort", abortListener, { once: true });
2673
+ try {
2674
+ const response = await fetch(url, {
2675
+ ...fetchOptions,
2676
+ headers,
2677
+ signal: controller.signal
2678
+ });
2679
+ if (!response.ok) {
2680
+ const errorText = await response.text();
2681
+ throw new Error(`Backend API error (${response.status}): ${errorText}`);
2682
+ }
2683
+ if (response.status === 204) {
2684
+ return void 0;
2685
+ }
2686
+ const text = await response.text();
2687
+ return text ? JSON.parse(text) : void 0;
2688
+ } catch (error) {
2689
+ const wrappedError = externalSignal?.aborted || controller.signal.aborted && !isAbortError(error) ? createAbortError() : error;
2690
+ if (attempt >= retries || !isRetryableError(wrappedError)) {
2691
+ captureHandledFrontendException(wrappedError, {
2692
+ surface: "backend_client",
2693
+ url,
2694
+ method,
2695
+ retry_attempt: attempt,
2696
+ retries,
2697
+ pathname: typeof window !== "undefined" ? window.location.pathname : "unknown"
2698
+ });
2699
+ throw wrappedError;
2700
+ }
2701
+ await new Promise((resolve) => globalThis.setTimeout(resolve, retryDelayMs));
2702
+ } finally {
2703
+ globalThis.clearTimeout(timeoutId);
2704
+ externalSignal?.removeEventListener("abort", abortListener);
2705
+ }
2528
2706
  }
2529
- if (response.status === 204) return void 0;
2530
- const text = await response.text();
2531
- return text ? JSON.parse(text) : void 0;
2707
+ return void 0;
2532
2708
  })();
2533
2709
  inFlightRequests.set(dedupeKey, requestPromise);
2534
2710
  try {
@@ -2639,9 +2815,23 @@ var ApiClient = class {
2639
2815
  continue;
2640
2816
  }
2641
2817
  if (silentErrors) {
2818
+ captureHandledFrontendException(lastError, {
2819
+ surface: "api_client",
2820
+ url,
2821
+ retries,
2822
+ silent_errors: true,
2823
+ pathname: typeof window !== "undefined" ? window.location.pathname : "unknown"
2824
+ });
2642
2825
  console.warn("[ApiClient] All retries exhausted, returning fallback data");
2643
2826
  return fallbackData;
2644
2827
  } else {
2828
+ captureHandledFrontendException(lastError, {
2829
+ surface: "api_client",
2830
+ url,
2831
+ retries,
2832
+ silent_errors: false,
2833
+ pathname: typeof window !== "undefined" ? window.location.pathname : "unknown"
2834
+ });
2645
2835
  throw lastError;
2646
2836
  }
2647
2837
  }
@@ -4919,6 +5109,13 @@ var workspaceService = {
4919
5109
  return displayNamesMap;
4920
5110
  } catch (error) {
4921
5111
  console.error("Error fetching workspace display names:", error);
5112
+ captureSentryException(error, {
5113
+ surface: "workspace_display_names",
5114
+ route: "/api/workspaces/display-names",
5115
+ company_id: companyId || null,
5116
+ line_id: lineId || null,
5117
+ pathname: typeof window !== "undefined" ? window.location.pathname : "unknown"
5118
+ });
4922
5119
  throw error;
4923
5120
  }
4924
5121
  },
@@ -6573,95 +6770,6 @@ function clearAllRateLimits2() {
6573
6770
  rateLimitMap2.clear();
6574
6771
  }
6575
6772
 
6576
- // src/lib/utils/sentryContext.ts
6577
- function getSentry() {
6578
- try {
6579
- return __require("@sentry/nextjs");
6580
- } catch {
6581
- return null;
6582
- }
6583
- }
6584
- function setSentryUserContext(user) {
6585
- const sentry = getSentry();
6586
- if (!sentry) return;
6587
- if (user) {
6588
- sentry.setUser({
6589
- id: user.id,
6590
- email: user.email
6591
- });
6592
- sentry.setTags({
6593
- company_id: user.company_id || "unknown",
6594
- role: user.role || "unknown",
6595
- role_level: user.role_level || "unknown"
6596
- });
6597
- } else {
6598
- sentry.setUser(null);
6599
- sentry.setTags({
6600
- company_id: void 0,
6601
- role: void 0,
6602
- role_level: void 0
6603
- });
6604
- }
6605
- }
6606
- function setSentryWorkspaceContext(config) {
6607
- const sentry = getSentry();
6608
- if (!sentry) return;
6609
- sentry.setTags({
6610
- workspace_company: config.companyId || "unknown",
6611
- workspace_factory: config.factoryId || "unknown",
6612
- factory_name: config.factoryName || "unknown"
6613
- });
6614
- }
6615
- function clearSentryContext() {
6616
- const sentry = getSentry();
6617
- if (!sentry) return;
6618
- sentry.setUser(null);
6619
- sentry.setTags({
6620
- company_id: void 0,
6621
- role: void 0,
6622
- role_level: void 0,
6623
- workspace_company: void 0,
6624
- workspace_factory: void 0,
6625
- factory_name: void 0
6626
- });
6627
- }
6628
- function applyScopeExtras(scope, extras) {
6629
- if (!extras) return;
6630
- if (scope.setExtras) {
6631
- scope.setExtras(extras);
6632
- return;
6633
- }
6634
- if (scope.setExtra) {
6635
- Object.entries(extras).forEach(([key, value]) => scope.setExtra?.(key, value));
6636
- }
6637
- }
6638
- function captureSentryMessage(message, level = "warning", extras) {
6639
- const sentry = getSentry();
6640
- if (!sentry || !sentry.captureMessage) return;
6641
- if (sentry.withScope) {
6642
- sentry.withScope((scope) => {
6643
- scope.setLevel?.(level);
6644
- applyScopeExtras(scope, extras);
6645
- sentry.captureMessage?.(message);
6646
- });
6647
- return;
6648
- }
6649
- sentry.captureMessage(message, level);
6650
- }
6651
- function captureSentryException(error, extras) {
6652
- const sentry = getSentry();
6653
- if (!sentry || !sentry.captureException) return;
6654
- if (sentry.withScope) {
6655
- sentry.withScope((scope) => {
6656
- scope.setLevel?.("error");
6657
- applyScopeExtras(scope, extras);
6658
- sentry.captureException?.(error);
6659
- });
6660
- return;
6661
- }
6662
- sentry.captureException(error);
6663
- }
6664
-
6665
6773
  // src/lib/services/mixpanelService.ts
6666
6774
  var ROOT_DASHBOARD_EVENT_NAMES = {
6667
6775
  operations_overview: "Operations Overview Page Clicked",
@@ -8716,6 +8824,12 @@ var LinesService = class {
8716
8824
  }));
8717
8825
  } catch (error) {
8718
8826
  console.error("Error fetching lines:", error);
8827
+ captureHandledFrontendException(error, {
8828
+ surface: "lines_service",
8829
+ operation: "getLinesByCompanyId",
8830
+ company_id: companyId,
8831
+ pathname: typeof window !== "undefined" ? window.location.pathname : "unknown"
8832
+ });
8719
8833
  throw new Error(`Failed to fetch lines: ${error.message}`);
8720
8834
  }
8721
8835
  }
@@ -8765,6 +8879,11 @@ var LinesService = class {
8765
8879
  }));
8766
8880
  } catch (error) {
8767
8881
  console.error("Error fetching all lines:", error);
8882
+ captureHandledFrontendException(error, {
8883
+ surface: "lines_service",
8884
+ operation: "getAllLines",
8885
+ pathname: typeof window !== "undefined" ? window.location.pathname : "unknown"
8886
+ });
8768
8887
  throw new Error(`Failed to fetch lines: ${error.message}`);
8769
8888
  }
8770
8889
  }
@@ -8823,6 +8942,12 @@ var LinesService = class {
8823
8942
  };
8824
8943
  } catch (error) {
8825
8944
  console.error("Error fetching line:", error);
8945
+ captureHandledFrontendException(error, {
8946
+ surface: "lines_service",
8947
+ operation: "getLineById",
8948
+ line_id: lineId,
8949
+ pathname: typeof window !== "undefined" ? window.location.pathname : "unknown"
8950
+ });
8826
8951
  throw new Error(`Failed to fetch line: ${error.message}`);
8827
8952
  }
8828
8953
  }
@@ -10541,6 +10666,17 @@ var AuthProvider = ({ children }) => {
10541
10666
  const isRecoveringSession = authStatus === "recovering";
10542
10667
  useEffect(() => {
10543
10668
  currentUserRef.current = user;
10669
+ if (user) {
10670
+ setSentryUserContext({
10671
+ id: user.id,
10672
+ email: user.email,
10673
+ role: user.role,
10674
+ role_level: user.role_level,
10675
+ company_id: user.company_id
10676
+ });
10677
+ return;
10678
+ }
10679
+ clearSentryContext();
10544
10680
  }, [user]);
10545
10681
  const setTrackedSession = useCallback((nextSession) => {
10546
10682
  latestSessionRef.current = nextSession;
@@ -10701,6 +10837,17 @@ var AuthProvider = ({ children }) => {
10701
10837
  }
10702
10838
  if (isRetryableSessionError(err)) {
10703
10839
  console.warn("[AuthContext] Retryable session hydration error, entering recovery mode");
10840
+ if (recoveryAttemptRef.current === 0) {
10841
+ captureSentryException(err, {
10842
+ surface: "auth_session_hydration",
10843
+ phase: isReauth ? "reauth" : "initial",
10844
+ retryable: true,
10845
+ auth_status: authStatus,
10846
+ pathname: typeof window !== "undefined" ? window.location.pathname : "unknown",
10847
+ visibility_state: typeof document !== "undefined" ? document.visibilityState : "unknown",
10848
+ online_state: typeof navigator !== "undefined" ? navigator.onLine : "unknown"
10849
+ });
10850
+ }
10704
10851
  enterRecoveryMode(supabaseSession);
10705
10852
  return;
10706
10853
  }
@@ -10720,6 +10867,13 @@ var AuthProvider = ({ children }) => {
10720
10867
  }
10721
10868
  resetRecoveryState();
10722
10869
  clearAuthSnapshot();
10870
+ captureSentryException(fatalError, {
10871
+ surface: "auth_session_hydration",
10872
+ phase: isReauth ? "reauth" : "initial",
10873
+ retryable: false,
10874
+ auth_status: authStatus,
10875
+ pathname: typeof window !== "undefined" ? window.location.pathname : "unknown"
10876
+ });
10723
10877
  setError(fatalError);
10724
10878
  setAuthStatus("failed");
10725
10879
  setUser(null);
@@ -11414,7 +11568,7 @@ var useMobileMenu = () => {
11414
11568
  };
11415
11569
  var useHideMobileHeader = (shouldHide = true) => {
11416
11570
  const context = useMobileMenu();
11417
- React142__default.useEffect(() => {
11571
+ React143__default.useEffect(() => {
11418
11572
  if (context && shouldHide) {
11419
11573
  context.setHideMobileHeader(true);
11420
11574
  return () => {
@@ -13256,7 +13410,13 @@ var parseEfficiencyLegend = (legend) => {
13256
13410
  critical_threshold: coerce(legend.critical_threshold, DEFAULT_EFFICIENCY_LEGEND.critical_threshold)
13257
13411
  };
13258
13412
  };
13259
- var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, lineIds, userAccessibleLineIds }) => {
13413
+ var useDashboardMetrics = ({
13414
+ onLineMetricsUpdate,
13415
+ lineId,
13416
+ lineIds,
13417
+ userAccessibleLineIds,
13418
+ enabled = true
13419
+ }) => {
13260
13420
  const { supabaseUrl, supabaseKey } = useDashboardConfig();
13261
13421
  const entityConfig = useEntityConfig();
13262
13422
  const databaseConfig = useDatabaseConfig();
@@ -13371,7 +13531,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, lineIds, userAccessibl
13371
13531
  isTimezoneLoading,
13372
13532
  companySpecificMetricsTable
13373
13533
  });
13374
- if (!currentLineIdToUse || !supabase || shiftLoading || isTimezoneLoading || companySpecificMetricsTable.includes("unknown_company")) {
13534
+ if (!currentLineIdToUse || !supabase || !enabled || shiftLoading || isTimezoneLoading || companySpecificMetricsTable.includes("unknown_company")) {
13375
13535
  updateQueueRef.current = false;
13376
13536
  if (!metrics2?.workspaceMetrics?.length && !metrics2?.lineMetrics?.length && !shiftLoading) setIsLoading(false);
13377
13537
  if (companySpecificMetricsTable.includes("unknown_company") && !error) {
@@ -13415,19 +13575,6 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, lineIds, userAccessibl
13415
13575
  abortControllerRef.current = abortController;
13416
13576
  inFlightFetchKeyRef.current = fetchKey;
13417
13577
  try {
13418
- const { data: { session } } = await supabase.auth.getSession();
13419
- logDebug("[useDashboardMetrics] Session check:", {
13420
- hasSession: !!session,
13421
- hasToken: !!session?.access_token,
13422
- tokenPreview: session?.access_token?.substring(0, 20) + "..."
13423
- });
13424
- if (!session?.access_token) {
13425
- throw new Error("No authentication token available. Please log in.");
13426
- }
13427
- const apiUrl = process.env.NEXT_PUBLIC_BACKEND_URL;
13428
- if (!apiUrl) {
13429
- throw new Error("Backend URL is not configured. Please set NEXT_PUBLIC_BACKEND_URL in your environment.");
13430
- }
13431
13578
  if (targetLineIds.length === 0) {
13432
13579
  logDebug("[useDashboardMetrics] Skipping fetch: no target line IDs after scope filtering");
13433
13580
  setMetrics({
@@ -13446,6 +13593,10 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, lineIds, userAccessibl
13446
13593
  let idleTimeVlmByLine = {};
13447
13594
  let efficiencyLegend;
13448
13595
  const forceParam = force ? "&force_refresh=true" : "";
13596
+ const buildMetricsEndpoint = (params) => {
13597
+ const lineIdsParam = isFactory ? `line_ids=${params.groupLineIds.join(",")}` : `line_id=${params.groupLineIds[0]}`;
13598
+ return `/api/dashboard/metrics?${lineIdsParam}&date=${params.date}&shift_id=${params.shiftId}&company_id=${companyId}${forceParam}`;
13599
+ };
13449
13600
  if (usesShiftGroups) {
13450
13601
  logDebug("[useDashboardMetrics] Factory view shift groups fetch:", {
13451
13602
  groupCount: shiftGroups.length,
@@ -13462,32 +13613,23 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, lineIds, userAccessibl
13462
13613
  if (groupLineIds.length === 0) {
13463
13614
  return null;
13464
13615
  }
13465
- const lineIdsParam = `line_ids=${groupLineIds.join(",")}`;
13466
- const url = `${apiUrl}/api/dashboard/metrics?${lineIdsParam}&date=${group.date}&shift_id=${group.shiftId}&company_id=${companyId}${forceParam}`;
13616
+ const endpoint = buildMetricsEndpoint({
13617
+ groupLineIds,
13618
+ date: group.date,
13619
+ shiftId: group.shiftId
13620
+ });
13467
13621
  logDebug(`[useDashboardMetrics] \u{1F4CA} Fetching for shift ${group.shiftId} (${group.shiftName}):`, {
13468
13622
  lineIds: groupLineIds,
13469
- date: group.date
13623
+ date: group.date,
13624
+ endpoint
13470
13625
  });
13471
- const response = await fetch(url, {
13626
+ return await fetchBackendJson(supabase, endpoint, {
13472
13627
  method: "GET",
13473
- headers: {
13474
- "Authorization": `Bearer ${session.access_token}`,
13475
- "Content-Type": "application/json"
13476
- },
13477
- signal: abortController.signal
13628
+ signal: abortController.signal,
13629
+ timeoutMs: 1e4,
13630
+ retries: 1,
13631
+ dedupeKey: `dashboard-metrics::${requestLineId}::${group.date}::${group.shiftId}::${groupLineIds.join(",")}::${force ? "force" : "cached"}`
13478
13632
  });
13479
- if (!response.ok) {
13480
- const errorText = await response.text();
13481
- console.error(`[useDashboardMetrics] Backend API error for shift ${group.shiftId}:`, errorText);
13482
- throw new Error(`Backend API error (${response.status}): ${errorText}`);
13483
- }
13484
- const responseText = await response.text();
13485
- try {
13486
- return JSON.parse(responseText);
13487
- } catch (parseError) {
13488
- console.error("[useDashboardMetrics] Failed to parse response:", responseText.substring(0, 500));
13489
- throw new Error(`Invalid JSON response from backend`);
13490
- }
13491
13633
  });
13492
13634
  const results = (await Promise.all(metricsPromises)).filter((result) => !!result);
13493
13635
  hasFlowBuffers = results.some((result) => result?.metadata?.has_flow_buffers);
@@ -13522,39 +13664,23 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, lineIds, userAccessibl
13522
13664
  if (!currentShiftDetails) {
13523
13665
  throw new Error("Shift details not available for metrics fetch.");
13524
13666
  }
13525
- const operationalDate = currentShiftDetails.date;
13526
- const lineIdsParam = isFactory ? `line_ids=${targetLineIds.join(",")}` : `line_id=${targetLineIds[0]}`;
13527
- const url = `${apiUrl}/api/dashboard/metrics?${lineIdsParam}&date=${operationalDate}&shift_id=${currentShiftDetails.shiftId}&company_id=${companyId}${forceParam}`;
13667
+ const endpoint = buildMetricsEndpoint({
13668
+ groupLineIds: targetLineIds,
13669
+ date: currentShiftDetails.date,
13670
+ shiftId: currentShiftDetails.shiftId
13671
+ });
13528
13672
  logDebug("[useDashboardMetrics] Calling backend API:", {
13529
- url,
13530
- apiUrl,
13531
- lineIdsParam,
13532
- operationalDate,
13673
+ endpoint,
13533
13674
  shiftId: currentShiftDetails.shiftId,
13534
13675
  companyId
13535
13676
  });
13536
- const response = await fetch(url, {
13677
+ const backendData = await fetchBackendJson(supabase, endpoint, {
13537
13678
  method: "GET",
13538
- headers: {
13539
- "Authorization": `Bearer ${session.access_token}`,
13540
- "Content-Type": "application/json"
13541
- },
13542
- signal: abortController.signal
13679
+ signal: abortController.signal,
13680
+ timeoutMs: 1e4,
13681
+ retries: 1,
13682
+ dedupeKey: `dashboard-metrics::${requestLineId}::${currentShiftDetails.date}::${currentShiftDetails.shiftId}::${targetLineIds.join(",")}::${force ? "force" : "cached"}`
13543
13683
  });
13544
- logDebug("[useDashboardMetrics] Response status:", response.status, response.statusText);
13545
- if (!response.ok) {
13546
- const errorText = await response.text();
13547
- console.error("[useDashboardMetrics] Backend API error response:", errorText);
13548
- throw new Error(`Backend API error (${response.status}): ${errorText}`);
13549
- }
13550
- const responseText = await response.text();
13551
- let backendData;
13552
- try {
13553
- backendData = JSON.parse(responseText);
13554
- } catch (parseError) {
13555
- console.error("[useDashboardMetrics] Failed to parse response as JSON. Response text:", responseText.substring(0, 500));
13556
- throw new Error(`Invalid JSON response from backend. Received: ${responseText.substring(0, 100)}...`);
13557
- }
13558
13684
  logDebug("[useDashboardMetrics] Backend response:", {
13559
13685
  workspaceCount: backendData.workspace_metrics?.length || 0,
13560
13686
  lineCount: backendData.line_metrics?.length || 0
@@ -13609,6 +13735,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, lineIds, userAccessibl
13609
13735
  date: item.date,
13610
13736
  workspace_uuid: item.workspace_id,
13611
13737
  workspace_name: item.workspace_name,
13738
+ displayName: item.workspace_display_name || item.display_name || void 0,
13612
13739
  action_count: item.total_output || 0,
13613
13740
  pph: item.avg_pph || 0,
13614
13741
  performance_score: item.performance_score || 0,
@@ -13672,6 +13799,17 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, lineIds, userAccessibl
13672
13799
  return;
13673
13800
  }
13674
13801
  console.error("[useDashboardMetrics] Error fetching dashboard metrics:", err);
13802
+ captureSentryException(err, {
13803
+ surface: "home_live_monitor_metrics",
13804
+ route: "/api/dashboard/metrics",
13805
+ line_id: requestLineId,
13806
+ selected_line_ids: targetLineIds,
13807
+ is_factory_view: isFactory,
13808
+ reason: options.reason || "unknown",
13809
+ auth_deferred: !enabled,
13810
+ visibility_state: typeof document !== "undefined" ? document.visibilityState : "unknown",
13811
+ online_state: typeof navigator !== "undefined" ? navigator.onLine : "unknown"
13812
+ });
13675
13813
  setError({ message: err.message, code: err.code || "FETCH_ERROR" });
13676
13814
  } finally {
13677
13815
  if (requestId === activeRequestIdRef.current) {
@@ -13685,6 +13823,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, lineIds, userAccessibl
13685
13823
  }, [
13686
13824
  supabase,
13687
13825
  companySpecificMetricsTable,
13826
+ enabled,
13688
13827
  companyId,
13689
13828
  factoryViewId,
13690
13829
  defaultTimezone,
@@ -13721,24 +13860,24 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, lineIds, userAccessibl
13721
13860
  logDebug("[useDashboardMetrics] queueUpdate triggered from realtime");
13722
13861
  updateQueueRef.current = true;
13723
13862
  fetchAllMetricsRef.current({ force: true, reason: "subscription" });
13724
- }, [supabase]);
13863
+ }, [supabase, enabled]);
13725
13864
  useEffect(() => {
13726
- if (lineId && supabase && !shiftLoading && !isTimezoneLoading) {
13865
+ if (enabled && lineId && supabase && !shiftLoading && !isTimezoneLoading) {
13727
13866
  fetchAllMetrics({ reason: "line-change" });
13728
13867
  }
13729
- }, [lineId, supabase, fetchAllMetrics, shiftLoading, isTimezoneLoading]);
13868
+ }, [enabled, lineId, supabase, fetchAllMetrics, shiftLoading, isTimezoneLoading]);
13730
13869
  useEffect(() => {
13731
- if (isFactoryView || !operationalShiftKey) return;
13870
+ if (!enabled || isFactoryView || !operationalShiftKey) return;
13732
13871
  if (!supabase || shiftLoading || isTimezoneLoading) return;
13733
13872
  fetchAllMetrics({ force: true, reason: "shift-change" });
13734
- }, [isFactoryView, operationalShiftKey, supabase, shiftLoading, isTimezoneLoading, fetchAllMetrics]);
13873
+ }, [enabled, isFactoryView, operationalShiftKey, supabase, shiftLoading, isTimezoneLoading, fetchAllMetrics]);
13735
13874
  useEffect(() => {
13736
- if (!isFactoryView || !shiftGroupsKey) return;
13875
+ if (!enabled || !isFactoryView || !shiftGroupsKey) return;
13737
13876
  if (!supabase || shiftLoading || isTimezoneLoading) return;
13738
13877
  fetchAllMetrics({ force: true, reason: "shift-change" });
13739
- }, [isFactoryView, shiftGroupsKey, supabase, shiftLoading, isTimezoneLoading, fetchAllMetrics]);
13878
+ }, [enabled, isFactoryView, shiftGroupsKey, supabase, shiftLoading, isTimezoneLoading, fetchAllMetrics]);
13740
13879
  useEffect(() => {
13741
- if (!lineId || !supabase || shiftLoading || isTimezoneLoading) {
13880
+ if (!enabled || !lineId || !supabase || shiftLoading || isTimezoneLoading) {
13742
13881
  return;
13743
13882
  }
13744
13883
  let intervalId = null;
@@ -13764,15 +13903,16 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, lineIds, userAccessibl
13764
13903
  window.clearInterval(intervalId);
13765
13904
  }
13766
13905
  };
13767
- }, [lineId, supabase, shiftLoading, isTimezoneLoading]);
13906
+ }, [enabled, lineId, supabase, shiftLoading, isTimezoneLoading]);
13768
13907
  const subscriptionKey = useMemo(() => {
13769
- if (!supabase || !entityConfig?.companyId) return null;
13908
+ if (!enabled || !supabase || !entityConfig?.companyId) return null;
13770
13909
  if (shiftLoading || isTimezoneLoading) return null;
13771
13910
  const isFactory = lineId === (entityConfig.factoryViewId || "factory");
13772
13911
  if (isFactory && shiftGroups.length === 0) return null;
13773
13912
  const shiftGroupsKeyPart = isFactory ? shiftGroups.map((g) => `${g.date}-${g.shiftId}-${g.lineIds.join("_")}`).join("|") : operationalShiftKey;
13774
13913
  return `${lineId}|${entityConfig.companyId}|${shiftGroupsKeyPart}`;
13775
13914
  }, [
13915
+ enabled,
13776
13916
  supabase,
13777
13917
  entityConfig?.companyId,
13778
13918
  entityConfig?.factoryViewId,
@@ -14098,9 +14238,14 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, lineIds, userAccessibl
14098
14238
  lineMetrics: safeMetrics?.lineMetrics || [],
14099
14239
  efficiencyLegend: safeMetrics?.efficiencyLegend || DEFAULT_EFFICIENCY_LEGEND,
14100
14240
  metadata: safeMetrics?.metadata,
14101
- isLoading: isLoading || !isMetricsForActiveLine,
14241
+ isLoading: enabled ? isLoading || !isMetricsForActiveLine : false,
14102
14242
  error,
14103
- refetch: () => fetchAllMetrics({ force: true, reason: "manual" })
14243
+ refetch: () => {
14244
+ if (!enabled) {
14245
+ return;
14246
+ }
14247
+ fetchAllMetrics({ force: true, reason: "manual" });
14248
+ }
14104
14249
  };
14105
14250
  };
14106
14251
  var useLineKPIs = ({ lineId, enabled }) => {
@@ -20256,11 +20401,21 @@ var apiUtils = {
20256
20401
  const token = sessionResponse.data.session?.access_token;
20257
20402
  if (!token) {
20258
20403
  console.error("API Util: No authentication token available.");
20404
+ captureHandledFrontendException(new Error("Authentication required."), {
20405
+ surface: "api_utils",
20406
+ endpoint: relativeEndpoint,
20407
+ reason: "missing_auth_token"
20408
+ });
20259
20409
  throw new Error("Authentication required.");
20260
20410
  }
20261
20411
  const baseUrl = config.apiBaseUrl;
20262
20412
  if (!baseUrl) {
20263
20413
  console.error("API Util: apiBaseUrl is not configured.");
20414
+ captureHandledFrontendException(new Error("API base URL is not configured."), {
20415
+ surface: "api_utils",
20416
+ endpoint: relativeEndpoint,
20417
+ reason: "missing_api_base_url"
20418
+ });
20264
20419
  throw new Error("API base URL is not configured.");
20265
20420
  }
20266
20421
  const endpoint = `${baseUrl.replace(/\/$/, "")}/${relativeEndpoint.replace(/^\//, "")}`;
@@ -20289,6 +20444,12 @@ var apiUtils = {
20289
20444
  return await response.json();
20290
20445
  } catch (error) {
20291
20446
  console.error(`Network or fetch error calling ${endpoint}:`, error);
20447
+ captureHandledFrontendException(error, {
20448
+ surface: "api_utils",
20449
+ endpoint,
20450
+ method: options.method || "GET",
20451
+ pathname: typeof window !== "undefined" ? window.location.pathname : "unknown"
20452
+ });
20292
20453
  if (error instanceof Error) {
20293
20454
  throw error;
20294
20455
  } else {
@@ -23472,7 +23633,7 @@ var MotionConfigContext = createContext({
23472
23633
  });
23473
23634
 
23474
23635
  // ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PopChild.mjs
23475
- var PopChildMeasure = class extends React142.Component {
23636
+ var PopChildMeasure = class extends React143.Component {
23476
23637
  getSnapshotBeforeUpdate(prevProps) {
23477
23638
  const element = this.props.childRef.current;
23478
23639
  if (element && prevProps.isPresent && !this.props.isPresent) {
@@ -23527,7 +23688,7 @@ function PopChild({ children, isPresent }) {
23527
23688
  document.head.removeChild(style);
23528
23689
  };
23529
23690
  }, [isPresent]);
23530
- return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React142.cloneElement(children, { ref }) });
23691
+ return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React143.cloneElement(children, { ref }) });
23531
23692
  }
23532
23693
 
23533
23694
  // ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PresenceChild.mjs
@@ -23564,7 +23725,7 @@ var PresenceChild = ({ children, initial, isPresent, onExitComplete, custom, pre
23564
23725
  useMemo(() => {
23565
23726
  presenceChildren.forEach((_, key) => presenceChildren.set(key, false));
23566
23727
  }, [isPresent]);
23567
- React142.useEffect(() => {
23728
+ React143.useEffect(() => {
23568
23729
  !isPresent && !presenceChildren.size && onExitComplete && onExitComplete();
23569
23730
  }, [isPresent]);
23570
23731
  if (mode === "popLayout") {
@@ -31349,7 +31510,7 @@ var withAuth = (WrappedComponent2, options) => {
31349
31510
  requireAuth: true,
31350
31511
  ...options
31351
31512
  };
31352
- const WithAuthComponent = React142.memo(function WithAuthComponent2(props) {
31513
+ const WithAuthComponent = React143.memo(function WithAuthComponent2(props) {
31353
31514
  const {
31354
31515
  session,
31355
31516
  user,
@@ -31360,9 +31521,9 @@ var withAuth = (WrappedComponent2, options) => {
31360
31521
  retrySessionHydration
31361
31522
  } = useAuth();
31362
31523
  const router = useRouter();
31363
- const [localLoading, setLocalLoading] = React142.useState(loading);
31364
- const [loadingTimeoutReached, setLoadingTimeoutReached] = React142.useState(false);
31365
- React142.useEffect(() => {
31524
+ const [localLoading, setLocalLoading] = React143.useState(loading);
31525
+ const [loadingTimeoutReached, setLoadingTimeoutReached] = React143.useState(false);
31526
+ React143.useEffect(() => {
31366
31527
  if (process.env.NODE_ENV === "development" && process.env.DEBUG_AUTH === "true") {
31367
31528
  console.log("withAuth state:", {
31368
31529
  loading,
@@ -31374,7 +31535,7 @@ var withAuth = (WrappedComponent2, options) => {
31374
31535
  });
31375
31536
  }
31376
31537
  }, [authStatus, error, loading, session, user]);
31377
- const handleLoadingTimeout = React142.useCallback(() => {
31538
+ const handleLoadingTimeout = React143.useCallback(() => {
31378
31539
  console.warn("[withAuth] Loading timeout reached");
31379
31540
  setLoadingTimeoutReached(true);
31380
31541
  if (hasStoredSupabaseSession()) {
@@ -31386,13 +31547,13 @@ var withAuth = (WrappedComponent2, options) => {
31386
31547
  router.replace(defaultOptions.redirectTo);
31387
31548
  }
31388
31549
  }, [retrySessionHydration, router]);
31389
- React142.useEffect(() => {
31550
+ React143.useEffect(() => {
31390
31551
  if (!loading && authStatus !== "recovering" && defaultOptions.requireAuth && !session && !error) {
31391
31552
  console.log("[withAuth] No session found, redirecting to login");
31392
31553
  router.replace(defaultOptions.redirectTo);
31393
31554
  }
31394
31555
  }, [authStatus, defaultOptions.requireAuth, error, loading, router, session]);
31395
- React142.useEffect(() => {
31556
+ React143.useEffect(() => {
31396
31557
  setLocalLoading(loading);
31397
31558
  }, [loading]);
31398
31559
  if (loading || localLoading) {
@@ -32391,11 +32552,11 @@ var BarChartComponent = ({
32391
32552
  aspect = 2,
32392
32553
  ...restOfChartProps
32393
32554
  }) => {
32394
- const containerRef = React142__default.useRef(null);
32395
- const [containerReady, setContainerReady] = React142__default.useState(false);
32555
+ const containerRef = React143__default.useRef(null);
32556
+ const [containerReady, setContainerReady] = React143__default.useState(false);
32396
32557
  const themeConfig = useThemeConfig();
32397
32558
  const { formatNumber } = useFormatNumber();
32398
- React142__default.useEffect(() => {
32559
+ React143__default.useEffect(() => {
32399
32560
  const checkContainerDimensions = () => {
32400
32561
  if (containerRef.current) {
32401
32562
  const rect = containerRef.current.getBoundingClientRect();
@@ -32509,7 +32670,7 @@ var BarChartComponent = ({
32509
32670
  }
32510
32671
  return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: chartContent });
32511
32672
  };
32512
- var BarChart = React142__default.memo(BarChartComponent, (prevProps, nextProps) => {
32673
+ var BarChart = React143__default.memo(BarChartComponent, (prevProps, nextProps) => {
32513
32674
  if (prevProps.xAxisDataKey !== nextProps.xAxisDataKey || prevProps.xAxisLabel !== nextProps.xAxisLabel || prevProps.yAxisLabel !== nextProps.yAxisLabel || prevProps.yAxisUnit !== nextProps.yAxisUnit || JSON.stringify(prevProps.referenceLines || []) !== JSON.stringify(nextProps.referenceLines || []) || prevProps.layout !== nextProps.layout || prevProps.className !== nextProps.className || prevProps.showGrid !== nextProps.showGrid || prevProps.showLegend !== nextProps.showLegend || prevProps.showTooltip !== nextProps.showTooltip || prevProps.responsive !== nextProps.responsive || prevProps.aspect !== nextProps.aspect) {
32514
32675
  return false;
32515
32676
  }
@@ -32560,10 +32721,10 @@ var LineChartComponent = ({
32560
32721
  fillContainer = false,
32561
32722
  ...restOfChartProps
32562
32723
  }) => {
32563
- const containerRef = React142__default.useRef(null);
32564
- const [dimensions, setDimensions] = React142__default.useState({ width: 0, height: 0 });
32565
- const [hasValidData, setHasValidData] = React142__default.useState(false);
32566
- React142__default.useEffect(() => {
32724
+ const containerRef = React143__default.useRef(null);
32725
+ const [dimensions, setDimensions] = React143__default.useState({ width: 0, height: 0 });
32726
+ const [hasValidData, setHasValidData] = React143__default.useState(false);
32727
+ React143__default.useEffect(() => {
32567
32728
  const currentHasValidData = data && lines && lines.length > 0 && data.some(
32568
32729
  (item) => lines.some((line) => {
32569
32730
  const val = item[line.dataKey];
@@ -32574,7 +32735,7 @@ var LineChartComponent = ({
32574
32735
  setHasValidData(true);
32575
32736
  }
32576
32737
  }, [data, lines, hasValidData]);
32577
- React142__default.useEffect(() => {
32738
+ React143__default.useEffect(() => {
32578
32739
  if (!containerRef.current) return;
32579
32740
  const observer = new ResizeObserver((entries) => {
32580
32741
  const entry = entries[0];
@@ -32699,7 +32860,7 @@ var LineChartComponent = ({
32699
32860
  }
32700
32861
  return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: renderChartContent(restOfChartProps.width, restOfChartProps.height) });
32701
32862
  };
32702
- var LineChart = React142__default.memo(LineChartComponent, (prevProps, nextProps) => {
32863
+ var LineChart = React143__default.memo(LineChartComponent, (prevProps, nextProps) => {
32703
32864
  if (prevProps.xAxisDataKey !== nextProps.xAxisDataKey || prevProps.xAxisLabel !== nextProps.xAxisLabel || prevProps.yAxisLabel !== nextProps.yAxisLabel || prevProps.yAxisUnit !== nextProps.yAxisUnit || prevProps.className !== nextProps.className || prevProps.showGrid !== nextProps.showGrid || prevProps.showLegend !== nextProps.showLegend || prevProps.showTooltip !== nextProps.showTooltip || prevProps.responsive !== nextProps.responsive || prevProps.aspect !== nextProps.aspect || JSON.stringify(prevProps.yAxisDomain) !== JSON.stringify(nextProps.yAxisDomain)) {
32704
32865
  return false;
32705
32866
  }
@@ -32793,7 +32954,7 @@ var OutputProgressChartComponent = ({
32793
32954
  ] }) })
32794
32955
  ] }) });
32795
32956
  };
32796
- var OutputProgressChart = React142__default.memo(OutputProgressChartComponent);
32957
+ var OutputProgressChart = React143__default.memo(OutputProgressChartComponent);
32797
32958
  OutputProgressChart.displayName = "OutputProgressChart";
32798
32959
  var LargeOutputProgressChart = ({
32799
32960
  currentOutput,
@@ -32933,7 +33094,7 @@ var CycleTimeChartComponent = ({
32933
33094
  }
32934
33095
  ) }) });
32935
33096
  };
32936
- var CycleTimeChart = React142__default.memo(CycleTimeChartComponent, (prevProps, nextProps) => {
33097
+ var CycleTimeChart = React143__default.memo(CycleTimeChartComponent, (prevProps, nextProps) => {
32937
33098
  if (prevProps.className !== nextProps.className) {
32938
33099
  return false;
32939
33100
  }
@@ -33171,16 +33332,16 @@ var CycleTimeOverTimeChart = ({
33171
33332
  idleTimeSlots = []
33172
33333
  }) => {
33173
33334
  const MAX_DATA_POINTS = 40;
33174
- const containerRef = React142__default.useRef(null);
33175
- const [dimensions, setDimensions] = React142__default.useState({ width: 0, height: 0 });
33176
- const [hasValidData, setHasValidData] = React142__default.useState(false);
33177
- React142__default.useEffect(() => {
33335
+ const containerRef = React143__default.useRef(null);
33336
+ const [dimensions, setDimensions] = React143__default.useState({ width: 0, height: 0 });
33337
+ const [hasValidData, setHasValidData] = React143__default.useState(false);
33338
+ React143__default.useEffect(() => {
33178
33339
  const currentHasValidData = data && data.some((val) => val !== null && val > 0);
33179
33340
  if (currentHasValidData && !hasValidData) {
33180
33341
  setHasValidData(true);
33181
33342
  }
33182
33343
  }, [data, hasValidData]);
33183
- React142__default.useEffect(() => {
33344
+ React143__default.useEffect(() => {
33184
33345
  if (!containerRef.current) return;
33185
33346
  const observer = new ResizeObserver((entries) => {
33186
33347
  const entry = entries[0];
@@ -33212,7 +33373,7 @@ var CycleTimeOverTimeChart = ({
33212
33373
  const endLabel = shiftEnd && slotIndex === DURATION - 1 ? formatHourLabel(slotIndex + 1) : formatHourLabel(slotIndex + 1);
33213
33374
  return `${startLabel} - ${endLabel}`;
33214
33375
  };
33215
- const getDisplayData = React142__default.useCallback((rawData) => {
33376
+ const getDisplayData = React143__default.useCallback((rawData) => {
33216
33377
  if (xAxisMode === "hourly") return rawData;
33217
33378
  return rawData.slice(Math.max(0, rawData.length - MAX_DATA_POINTS));
33218
33379
  }, [xAxisMode]);
@@ -33220,7 +33381,7 @@ var CycleTimeOverTimeChart = ({
33220
33381
  const DURATION = displayData.length;
33221
33382
  const effectiveDatasetKey = datasetKey || `cycle-time:${xAxisMode}`;
33222
33383
  const finalData = displayData;
33223
- const labelInterval = React142__default.useMemo(() => {
33384
+ const labelInterval = React143__default.useMemo(() => {
33224
33385
  if (xAxisMode === "hourly") {
33225
33386
  return Math.max(1, Math.ceil(DURATION / 8));
33226
33387
  }
@@ -33261,8 +33422,8 @@ var CycleTimeOverTimeChart = ({
33261
33422
  return `${minutes} minutes ${seconds} seconds ago`;
33262
33423
  }
33263
33424
  };
33264
- const getNumericValue = React142__default.useCallback((value) => typeof value === "number" && Number.isFinite(value) ? value : null, []);
33265
- const renderChartTooltip = React142__default.useCallback((tooltipProps) => {
33425
+ const getNumericValue = React143__default.useCallback((value) => typeof value === "number" && Number.isFinite(value) ? value : null, []);
33426
+ const renderChartTooltip = React143__default.useCallback((tooltipProps) => {
33266
33427
  const { active, payload } = tooltipProps;
33267
33428
  if (!active || !Array.isArray(payload) || payload.length === 0) {
33268
33429
  return null;
@@ -33325,7 +33486,7 @@ var CycleTimeOverTimeChart = ({
33325
33486
  ] })
33326
33487
  ] });
33327
33488
  }, [getNumericValue, shiftStart, showIdleTime]);
33328
- const renderCycleDot = React142__default.useCallback((props) => {
33489
+ const renderCycleDot = React143__default.useCallback((props) => {
33329
33490
  const { cx: cx2, cy, payload } = props;
33330
33491
  const cycleTime = getNumericValue(payload?.cycleTime);
33331
33492
  if (cycleTime === null) {
@@ -33358,7 +33519,7 @@ var CycleTimeOverTimeChart = ({
33358
33519
  }
33359
33520
  );
33360
33521
  }, [getNumericValue, idealCycleTime]);
33361
- const renderCycleActiveDot = React142__default.useCallback((props) => {
33522
+ const renderCycleActiveDot = React143__default.useCallback((props) => {
33362
33523
  const { cx: cx2, cy, payload } = props;
33363
33524
  const cycleTime = getNumericValue(payload?.cycleTime);
33364
33525
  if (cycleTime === null) {
@@ -33379,7 +33540,7 @@ var CycleTimeOverTimeChart = ({
33379
33540
  }
33380
33541
  );
33381
33542
  }, [getNumericValue, idealCycleTime]);
33382
- const renderIdleDot = React142__default.useCallback((props) => {
33543
+ const renderIdleDot = React143__default.useCallback((props) => {
33383
33544
  const { cx: cx2, cy, payload } = props;
33384
33545
  const idleMinutes = getNumericValue(payload?.idleMinutes);
33385
33546
  if (idleMinutes === null) {
@@ -33401,7 +33562,7 @@ var CycleTimeOverTimeChart = ({
33401
33562
  }
33402
33563
  );
33403
33564
  }, [getNumericValue, showIdleTime]);
33404
- const renderIdleActiveDot = React142__default.useCallback((props) => {
33565
+ const renderIdleActiveDot = React143__default.useCallback((props) => {
33405
33566
  const { cx: cx2, cy, payload } = props;
33406
33567
  const idleMinutes = getNumericValue(payload?.idleMinutes);
33407
33568
  if (idleMinutes === null || !showIdleTime) {
@@ -33419,7 +33580,7 @@ var CycleTimeOverTimeChart = ({
33419
33580
  }
33420
33581
  );
33421
33582
  }, [getNumericValue, showIdleTime]);
33422
- const chartData = React142__default.useMemo(() => Array.from({ length: DURATION }, (_, i) => {
33583
+ const chartData = React143__default.useMemo(() => Array.from({ length: DURATION }, (_, i) => {
33423
33584
  const cycleTime = getNumericValue(finalData[i]);
33424
33585
  const useIdleSlots = idleTimeSlots.length > 0;
33425
33586
  const idleSlot = useIdleSlots ? idleTimeSlots[i] ?? null : null;
@@ -33616,7 +33777,7 @@ var CycleTimeOverTimeChart = ({
33616
33777
  }
33617
33778
  );
33618
33779
  };
33619
- var Card = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33780
+ var Card = React143.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33620
33781
  "div",
33621
33782
  {
33622
33783
  ref,
@@ -33628,7 +33789,7 @@ var Card = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
33628
33789
  }
33629
33790
  ));
33630
33791
  Card.displayName = "Card";
33631
- var CardHeader = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33792
+ var CardHeader = React143.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33632
33793
  "div",
33633
33794
  {
33634
33795
  ref,
@@ -33637,7 +33798,7 @@ var CardHeader = React142.forwardRef(({ className, ...props }, ref) => /* @__PUR
33637
33798
  }
33638
33799
  ));
33639
33800
  CardHeader.displayName = "CardHeader";
33640
- var CardTitle = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33801
+ var CardTitle = React143.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33641
33802
  "h3",
33642
33803
  {
33643
33804
  ref,
@@ -33649,7 +33810,7 @@ var CardTitle = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE
33649
33810
  }
33650
33811
  ));
33651
33812
  CardTitle.displayName = "CardTitle";
33652
- var CardDescription = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33813
+ var CardDescription = React143.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33653
33814
  "p",
33654
33815
  {
33655
33816
  ref,
@@ -33658,9 +33819,9 @@ var CardDescription = React142.forwardRef(({ className, ...props }, ref) => /* @
33658
33819
  }
33659
33820
  ));
33660
33821
  CardDescription.displayName = "CardDescription";
33661
- var CardContent = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
33822
+ var CardContent = React143.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
33662
33823
  CardContent.displayName = "CardContent";
33663
- var CardFooter = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33824
+ var CardFooter = React143.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33664
33825
  "div",
33665
33826
  {
33666
33827
  ref,
@@ -33736,7 +33897,7 @@ var buttonVariants = cva(
33736
33897
  }
33737
33898
  }
33738
33899
  );
33739
- var Button = React142.forwardRef(
33900
+ var Button = React143.forwardRef(
33740
33901
  ({ className, variant, size, asChild = false, ...props }, ref) => {
33741
33902
  const Comp = asChild ? Slot : "button";
33742
33903
  return /* @__PURE__ */ jsx(
@@ -33759,10 +33920,10 @@ var HourlyOutputChartComponent = ({
33759
33920
  idleTimeHourly,
33760
33921
  className = ""
33761
33922
  }) => {
33762
- const containerRef = React142__default.useRef(null);
33763
- const [containerReady, setContainerReady] = React142__default.useState(false);
33764
- const [containerWidth, setContainerWidth] = React142__default.useState(0);
33765
- const idleSlots = React142__default.useMemo(
33923
+ const containerRef = React143__default.useRef(null);
33924
+ const [containerReady, setContainerReady] = React143__default.useState(false);
33925
+ const [containerWidth, setContainerWidth] = React143__default.useState(0);
33926
+ const idleSlots = React143__default.useMemo(
33766
33927
  () => buildHourlyIdleSlots({
33767
33928
  idleTimeHourly,
33768
33929
  shiftStart,
@@ -33771,12 +33932,12 @@ var HourlyOutputChartComponent = ({
33771
33932
  [idleTimeHourly, shiftStart, shiftEnd]
33772
33933
  );
33773
33934
  const SHIFT_DURATION = idleSlots.length;
33774
- const [animatedData, setAnimatedData] = React142__default.useState(
33935
+ const [animatedData, setAnimatedData] = React143__default.useState(
33775
33936
  () => Array(SHIFT_DURATION).fill(0)
33776
33937
  );
33777
- const prevDataRef = React142__default.useRef(Array(SHIFT_DURATION).fill(0));
33778
- const animationFrameRef = React142__default.useRef(null);
33779
- React142__default.useEffect(() => {
33938
+ const prevDataRef = React143__default.useRef(Array(SHIFT_DURATION).fill(0));
33939
+ const animationFrameRef = React143__default.useRef(null);
33940
+ React143__default.useEffect(() => {
33780
33941
  setAnimatedData((prev) => {
33781
33942
  if (prev.length !== SHIFT_DURATION) {
33782
33943
  return Array(SHIFT_DURATION).fill(0);
@@ -33785,14 +33946,14 @@ var HourlyOutputChartComponent = ({
33785
33946
  });
33786
33947
  prevDataRef.current = Array(SHIFT_DURATION).fill(0);
33787
33948
  }, [SHIFT_DURATION]);
33788
- const [idleBarState, setIdleBarState] = React142__default.useState({
33949
+ const [idleBarState, setIdleBarState] = React143__default.useState({
33789
33950
  visible: showIdleTime,
33790
33951
  key: 0,
33791
33952
  shouldAnimate: false
33792
33953
  });
33793
- const prevShowIdleTimeRef = React142__default.useRef(showIdleTime);
33794
- const stateUpdateTimeoutRef = React142__default.useRef(null);
33795
- React142__default.useEffect(() => {
33954
+ const prevShowIdleTimeRef = React143__default.useRef(showIdleTime);
33955
+ const stateUpdateTimeoutRef = React143__default.useRef(null);
33956
+ React143__default.useEffect(() => {
33796
33957
  if (stateUpdateTimeoutRef.current) {
33797
33958
  clearTimeout(stateUpdateTimeoutRef.current);
33798
33959
  }
@@ -33817,7 +33978,7 @@ var HourlyOutputChartComponent = ({
33817
33978
  }
33818
33979
  };
33819
33980
  }, [showIdleTime]);
33820
- const animateToNewData = React142__default.useCallback((targetData) => {
33981
+ const animateToNewData = React143__default.useCallback((targetData) => {
33821
33982
  const startData = [...prevDataRef.current];
33822
33983
  const startTime = performance.now();
33823
33984
  const duration = 1200;
@@ -33847,7 +34008,7 @@ var HourlyOutputChartComponent = ({
33847
34008
  }
33848
34009
  animationFrameRef.current = requestAnimationFrame(animate);
33849
34010
  }, []);
33850
- React142__default.useEffect(() => {
34011
+ React143__default.useEffect(() => {
33851
34012
  if (JSON.stringify(data) !== JSON.stringify(prevDataRef.current)) {
33852
34013
  const shiftData = data.slice(0, SHIFT_DURATION);
33853
34014
  animateToNewData(shiftData);
@@ -33858,7 +34019,7 @@ var HourlyOutputChartComponent = ({
33858
34019
  }
33859
34020
  };
33860
34021
  }, [data, animateToNewData]);
33861
- React142__default.useEffect(() => {
34022
+ React143__default.useEffect(() => {
33862
34023
  const checkContainerDimensions = () => {
33863
34024
  if (containerRef.current) {
33864
34025
  const rect = containerRef.current.getBoundingClientRect();
@@ -33884,7 +34045,7 @@ var HourlyOutputChartComponent = ({
33884
34045
  clearTimeout(fallbackTimeout);
33885
34046
  };
33886
34047
  }, []);
33887
- const xAxisConfig = React142__default.useMemo(() => {
34048
+ const xAxisConfig = React143__default.useMemo(() => {
33888
34049
  if (containerWidth >= 960) {
33889
34050
  return { interval: 0, angle: -45, height: 92, tickFont: 10, tickMargin: 12 };
33890
34051
  }
@@ -33893,7 +34054,7 @@ var HourlyOutputChartComponent = ({
33893
34054
  }
33894
34055
  return { interval: 0, angle: -30, height: 64, tickFont: 9, tickMargin: 6 };
33895
34056
  }, [containerWidth]);
33896
- const chartData = React142__default.useMemo(() => {
34057
+ const chartData = React143__default.useMemo(() => {
33897
34058
  return Array.from({ length: SHIFT_DURATION }, (_, i) => {
33898
34059
  const idleSlot = idleSlots[i];
33899
34060
  return {
@@ -33909,7 +34070,7 @@ var HourlyOutputChartComponent = ({
33909
34070
  };
33910
34071
  });
33911
34072
  }, [animatedData, data, pphThreshold, idleSlots, SHIFT_DURATION]);
33912
- const IdleBar = React142__default.useMemo(() => {
34073
+ const IdleBar = React143__default.useMemo(() => {
33913
34074
  if (!idleBarState.visible) return null;
33914
34075
  return /* @__PURE__ */ jsx(
33915
34076
  Bar,
@@ -34207,7 +34368,7 @@ var HourlyOutputChartComponent = ({
34207
34368
  }
34208
34369
  );
34209
34370
  };
34210
- var HourlyOutputChart = React142__default.memo(HourlyOutputChartComponent, (prevProps, nextProps) => {
34371
+ var HourlyOutputChart = React143__default.memo(HourlyOutputChartComponent, (prevProps, nextProps) => {
34211
34372
  if (prevProps.pphThreshold !== nextProps.pphThreshold || prevProps.shiftStart !== nextProps.shiftStart || prevProps.shiftEnd !== nextProps.shiftEnd || prevProps.shiftDate !== nextProps.shiftDate || prevProps.timezone !== nextProps.timezone || prevProps.showIdleTime !== nextProps.showIdleTime || prevProps.className !== nextProps.className) {
34212
34373
  return false;
34213
34374
  }
@@ -34387,7 +34548,7 @@ function getTrendArrowAndColor(trend) {
34387
34548
  return { arrow: "\u2192", color: "text-gray-400" };
34388
34549
  }
34389
34550
  }
34390
- var VideoCard = React142__default.memo(({
34551
+ var VideoCard = React143__default.memo(({
34391
34552
  workspace,
34392
34553
  hlsUrl,
34393
34554
  shouldPlay,
@@ -34585,7 +34746,7 @@ var logDebug2 = (...args) => {
34585
34746
  if (!DEBUG_DASHBOARD_LOGS2) return;
34586
34747
  console.log(...args);
34587
34748
  };
34588
- var VideoGridView = React142__default.memo(({
34749
+ var VideoGridView = React143__default.memo(({
34589
34750
  workspaces,
34590
34751
  selectedLine,
34591
34752
  lineNames = {},
@@ -34861,7 +35022,7 @@ var VideoGridView = React142__default.memo(({
34861
35022
  efficiency: workspace.efficiency,
34862
35023
  action_count: workspace.action_count
34863
35024
  });
34864
- const displayName = getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
35025
+ const displayName = workspace.displayName || displayNames[`${workspace.line_id}_${workspace.workspace_name}`] || getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
34865
35026
  const currentPath = (router.asPath || "/").split("#")[0];
34866
35027
  const navParams = getWorkspaceNavigationParams(workspaceId, displayName, workspace.line_id, currentPath);
34867
35028
  router.push(`/workspace/${workspaceId}${navParams}`);
@@ -35019,7 +35180,7 @@ var VideoGridView = React142__default.memo(({
35019
35180
  ) });
35020
35181
  });
35021
35182
  VideoGridView.displayName = "VideoGridView";
35022
- var MapGridView = React142__default.memo(({
35183
+ var MapGridView = React143__default.memo(({
35023
35184
  workspaces,
35024
35185
  className = "",
35025
35186
  displayNames = {},
@@ -35858,7 +36019,7 @@ var UptimeLineChartComponent = ({ points, className = "" }) => {
35858
36019
  )
35859
36020
  ] }) }) });
35860
36021
  };
35861
- var UptimeLineChart = React142__default.memo(UptimeLineChartComponent);
36022
+ var UptimeLineChart = React143__default.memo(UptimeLineChartComponent);
35862
36023
  var padTime = (value) => value.toString().padStart(2, "0");
35863
36024
  var parseTime = (timeValue) => {
35864
36025
  if (!timeValue) return null;
@@ -36098,10 +36259,10 @@ var HourlyUptimeChartComponent = ({
36098
36259
  elapsedMinutes,
36099
36260
  className = ""
36100
36261
  }) => {
36101
- const containerRef = React142__default.useRef(null);
36102
- const [containerReady, setContainerReady] = React142__default.useState(false);
36103
- const [containerWidth, setContainerWidth] = React142__default.useState(0);
36104
- const uptimeSeries = React142__default.useMemo(() => buildUptimeSeries({
36262
+ const containerRef = React143__default.useRef(null);
36263
+ const [containerReady, setContainerReady] = React143__default.useState(false);
36264
+ const [containerWidth, setContainerWidth] = React143__default.useState(0);
36265
+ const uptimeSeries = React143__default.useMemo(() => buildUptimeSeries({
36105
36266
  idleTimeHourly,
36106
36267
  shiftStart,
36107
36268
  shiftEnd,
@@ -36110,11 +36271,11 @@ var HourlyUptimeChartComponent = ({
36110
36271
  elapsedMinutes
36111
36272
  }), [idleTimeHourly, shiftStart, shiftEnd, shiftDate, timezone, elapsedMinutes]);
36112
36273
  const hasAggregateData = Boolean(hourlyAggregates && hourlyAggregates.length > 0);
36113
- const shiftStartTime = React142__default.useMemo(
36274
+ const shiftStartTime = React143__default.useMemo(
36114
36275
  () => getTimeFromTimeString(shiftStart),
36115
36276
  [shiftStart]
36116
36277
  );
36117
- const { shiftDuration, shiftEndTime } = React142__default.useMemo(() => {
36278
+ const { shiftDuration, shiftEndTime } = React143__default.useMemo(() => {
36118
36279
  if (!shiftEnd) {
36119
36280
  const fallbackHours = uptimeSeries.shiftMinutes > 0 ? Math.ceil(uptimeSeries.shiftMinutes / 60) : 0;
36120
36281
  return { shiftDuration: fallbackHours, shiftEndTime: null };
@@ -36128,7 +36289,7 @@ var HourlyUptimeChartComponent = ({
36128
36289
  const hourCount = hasPartial ? Math.ceil(duration) : Math.round(duration);
36129
36290
  return { shiftDuration: hourCount, shiftEndTime: endTime };
36130
36291
  }, [shiftEnd, shiftStartTime.decimalHour, uptimeSeries.shiftMinutes]);
36131
- const formatHour = React142__default.useCallback((hourIndex) => {
36292
+ const formatHour = React143__default.useCallback((hourIndex) => {
36132
36293
  const isLastHour = hourIndex === shiftDuration - 1;
36133
36294
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
36134
36295
  const startHour = Math.floor(startDecimalHour) % 24;
@@ -36153,7 +36314,7 @@ var HourlyUptimeChartComponent = ({
36153
36314
  };
36154
36315
  return `${formatTime5(startHour, startMinute)}-${formatTime5(endHour, endMinute)}`;
36155
36316
  }, [shiftDuration, shiftStartTime.decimalHour, shiftEndTime]);
36156
- const formatTimeRange2 = React142__default.useCallback((hourIndex) => {
36317
+ const formatTimeRange2 = React143__default.useCallback((hourIndex) => {
36157
36318
  const isLastHour = hourIndex === shiftDuration - 1;
36158
36319
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
36159
36320
  const startHour = Math.floor(startDecimalHour) % 24;
@@ -36175,7 +36336,7 @@ var HourlyUptimeChartComponent = ({
36175
36336
  };
36176
36337
  return `${formatTime5(startHour, startMinute)} - ${formatTime5(endHour, endMinute)}`;
36177
36338
  }, [shiftDuration, shiftStartTime.decimalHour, shiftEndTime]);
36178
- const chartData = React142__default.useMemo(() => {
36339
+ const chartData = React143__default.useMemo(() => {
36179
36340
  if (shiftDuration <= 0) return [];
36180
36341
  if (hasAggregateData) {
36181
36342
  return hourlyAggregates.map((entry, hourIndex) => ({
@@ -36217,7 +36378,7 @@ var HourlyUptimeChartComponent = ({
36217
36378
  }, [hasAggregateData, hourlyAggregates, uptimeSeries.points, uptimeSeries.elapsedMinutes, uptimeSeries.shiftMinutes, shiftDuration, formatHour, formatTimeRange2]);
36218
36379
  const maxYValue = 100;
36219
36380
  const yAxisTicks = [0, 25, 50, 75, 100];
36220
- React142__default.useEffect(() => {
36381
+ React143__default.useEffect(() => {
36221
36382
  const checkContainerDimensions = () => {
36222
36383
  if (containerRef.current) {
36223
36384
  const rect = containerRef.current.getBoundingClientRect();
@@ -36243,7 +36404,7 @@ var HourlyUptimeChartComponent = ({
36243
36404
  clearTimeout(fallbackTimeout);
36244
36405
  };
36245
36406
  }, []);
36246
- const xAxisConfig = React142__default.useMemo(() => {
36407
+ const xAxisConfig = React143__default.useMemo(() => {
36247
36408
  if (containerWidth >= 960) {
36248
36409
  return { interval: 0, angle: -45, height: 92, tickFont: 10, tickMargin: 12, labelMode: "full" };
36249
36410
  }
@@ -36252,7 +36413,7 @@ var HourlyUptimeChartComponent = ({
36252
36413
  }
36253
36414
  return { interval: 0, angle: -30, height: 64, tickFont: 9, tickMargin: 6, labelMode: "start" };
36254
36415
  }, [containerWidth]);
36255
- const formatXAxisTick = React142__default.useCallback((raw) => {
36416
+ const formatXAxisTick = React143__default.useCallback((raw) => {
36256
36417
  const label = typeof raw === "string" ? raw : String(raw);
36257
36418
  if (xAxisConfig.labelMode === "full") return label;
36258
36419
  const parts = label.split("-");
@@ -36458,7 +36619,7 @@ var HourlyUptimeChartComponent = ({
36458
36619
  }
36459
36620
  );
36460
36621
  };
36461
- var HourlyUptimeChart = React142__default.memo(HourlyUptimeChartComponent);
36622
+ var HourlyUptimeChart = React143__default.memo(HourlyUptimeChartComponent);
36462
36623
  var DEFAULT_COLORS2 = ["#00AB45", "#ef4444"];
36463
36624
  var UptimeDonutChartComponent = ({
36464
36625
  data,
@@ -36528,7 +36689,7 @@ var UptimeDonutChartComponent = ({
36528
36689
  ] }) })
36529
36690
  ] }) });
36530
36691
  };
36531
- var UptimeDonutChart = React142__default.memo(UptimeDonutChartComponent);
36692
+ var UptimeDonutChart = React143__default.memo(UptimeDonutChartComponent);
36532
36693
  UptimeDonutChart.displayName = "UptimeDonutChart";
36533
36694
  var TrendIcon = ({ trend }) => {
36534
36695
  if (trend === "up") {
@@ -36647,7 +36808,7 @@ var EmptyStateMessage = ({
36647
36808
  iconClassName
36648
36809
  }) => {
36649
36810
  let IconContent = null;
36650
- if (React142__default.isValidElement(iconType)) {
36811
+ if (React143__default.isValidElement(iconType)) {
36651
36812
  IconContent = iconType;
36652
36813
  } else if (typeof iconType === "string") {
36653
36814
  const MappedIcon = IconMap[iconType];
@@ -38930,7 +39091,7 @@ function Skeleton({ className, ...props }) {
38930
39091
  var Select = SelectPrimitive.Root;
38931
39092
  var SelectGroup = SelectPrimitive.Group;
38932
39093
  var SelectValue = SelectPrimitive.Value;
38933
- var SelectTrigger = React142.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
39094
+ var SelectTrigger = React143.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
38934
39095
  SelectPrimitive.Trigger,
38935
39096
  {
38936
39097
  ref,
@@ -38946,7 +39107,7 @@ var SelectTrigger = React142.forwardRef(({ className, children, ...props }, ref)
38946
39107
  }
38947
39108
  ));
38948
39109
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
38949
- var SelectScrollUpButton = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
39110
+ var SelectScrollUpButton = React143.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
38950
39111
  SelectPrimitive.ScrollUpButton,
38951
39112
  {
38952
39113
  ref,
@@ -38956,7 +39117,7 @@ var SelectScrollUpButton = React142.forwardRef(({ className, ...props }, ref) =>
38956
39117
  }
38957
39118
  ));
38958
39119
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
38959
- var SelectScrollDownButton = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
39120
+ var SelectScrollDownButton = React143.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
38960
39121
  SelectPrimitive.ScrollDownButton,
38961
39122
  {
38962
39123
  ref,
@@ -38966,7 +39127,7 @@ var SelectScrollDownButton = React142.forwardRef(({ className, ...props }, ref)
38966
39127
  }
38967
39128
  ));
38968
39129
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
38969
- var SelectContent = React142.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
39130
+ var SelectContent = React143.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
38970
39131
  SelectPrimitive.Content,
38971
39132
  {
38972
39133
  ref,
@@ -38994,7 +39155,7 @@ var SelectContent = React142.forwardRef(({ className, children, position = "popp
38994
39155
  }
38995
39156
  ) }));
38996
39157
  SelectContent.displayName = SelectPrimitive.Content.displayName;
38997
- var SelectLabel = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
39158
+ var SelectLabel = React143.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
38998
39159
  SelectPrimitive.Label,
38999
39160
  {
39000
39161
  ref,
@@ -39003,7 +39164,7 @@ var SelectLabel = React142.forwardRef(({ className, ...props }, ref) => /* @__PU
39003
39164
  }
39004
39165
  ));
39005
39166
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
39006
- var SelectItem = React142.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
39167
+ var SelectItem = React143.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
39007
39168
  SelectPrimitive.Item,
39008
39169
  {
39009
39170
  ref,
@@ -39019,7 +39180,7 @@ var SelectItem = React142.forwardRef(({ className, children, ...props }, ref) =>
39019
39180
  }
39020
39181
  ));
39021
39182
  SelectItem.displayName = SelectPrimitive.Item.displayName;
39022
- var SelectSeparator = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
39183
+ var SelectSeparator = React143.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
39023
39184
  SelectPrimitive.Separator,
39024
39185
  {
39025
39186
  ref,
@@ -39553,13 +39714,8 @@ var TimePickerDropdown = ({
39553
39714
  }, [disabled, hasValue, onChange]);
39554
39715
  const handleContainerClick = useCallback(() => {
39555
39716
  if (disabled) return;
39556
- if (!activeSegment) {
39557
- setActiveSegment("hour");
39558
- if (!hasValue) {
39559
- onChange(to24h(12, 0, "AM"));
39560
- }
39561
- }
39562
- }, [disabled, activeSegment, hasValue, onChange]);
39717
+ togglePopover();
39718
+ }, [disabled, togglePopover]);
39563
39719
  return /* @__PURE__ */ jsxs("div", { className: `relative ${className}`, ref: containerRef, children: [
39564
39720
  /* @__PURE__ */ jsxs(
39565
39721
  "div",
@@ -39646,7 +39802,7 @@ var TimePickerDropdown = ({
39646
39802
  )
39647
39803
  ] });
39648
39804
  };
39649
- var SilentErrorBoundary = class extends React142__default.Component {
39805
+ var SilentErrorBoundary = class extends React143__default.Component {
39650
39806
  constructor(props) {
39651
39807
  super(props);
39652
39808
  this.handleClearAndReload = () => {
@@ -39679,6 +39835,12 @@ var SilentErrorBoundary = class extends React142__default.Component {
39679
39835
  componentStack: errorInfo.componentStack,
39680
39836
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
39681
39837
  });
39838
+ captureSentryException(error, {
39839
+ surface: "react_error_boundary",
39840
+ component_stack: errorInfo.componentStack,
39841
+ error_count: this.state.errorCount + 1,
39842
+ pathname: typeof window !== "undefined" ? window.location.pathname : "unknown"
39843
+ });
39682
39844
  this.setState((prev) => ({
39683
39845
  errorCount: prev.errorCount + 1,
39684
39846
  lastError: error,
@@ -46515,8 +46677,8 @@ var IdleTimeReasonChartComponent = ({
46515
46677
  updateAnimation = "replay",
46516
46678
  variant = "pie"
46517
46679
  }) => {
46518
- const [activeData, setActiveData] = React142__default.useState([]);
46519
- React142__default.useEffect(() => {
46680
+ const [activeData, setActiveData] = React143__default.useState([]);
46681
+ React143__default.useEffect(() => {
46520
46682
  if (updateAnimation === "smooth") {
46521
46683
  setActiveData(data && data.length > 0 ? data : []);
46522
46684
  return;
@@ -46535,7 +46697,7 @@ var IdleTimeReasonChartComponent = ({
46535
46697
  setActiveData([]);
46536
46698
  }
46537
46699
  }, [data, updateAnimation]);
46538
- React142__default.useEffect(() => {
46700
+ React143__default.useEffect(() => {
46539
46701
  if (!data || data.length === 0) return;
46540
46702
  data.forEach((entry, index) => {
46541
46703
  if (entry.name.toLowerCase().includes("other")) {
@@ -46543,7 +46705,7 @@ var IdleTimeReasonChartComponent = ({
46543
46705
  }
46544
46706
  });
46545
46707
  }, [data]);
46546
- const pieKey = React142__default.useMemo(() => {
46708
+ const pieKey = React143__default.useMemo(() => {
46547
46709
  if (updateAnimation === "smooth") {
46548
46710
  return "smooth";
46549
46711
  }
@@ -46713,7 +46875,7 @@ var IdleTimeReasonChartComponent = ({
46713
46875
  )
46714
46876
  ] });
46715
46877
  };
46716
- var IdleTimeReasonChart = React142__default.memo(IdleTimeReasonChartComponent);
46878
+ var IdleTimeReasonChart = React143__default.memo(IdleTimeReasonChartComponent);
46717
46879
  IdleTimeReasonChart.displayName = "IdleTimeReasonChart";
46718
46880
  var IdleTimeReasonChart_default = IdleTimeReasonChart;
46719
46881
  var DEFAULT_PERFORMANCE_DATA = {
@@ -51080,7 +51242,7 @@ var arePropsEqual = (prevProps, nextProps) => {
51080
51242
  return prevProps.data.efficiency === nextProps.data.efficiency && prevProps.data.trend_score === nextProps.data.trend_score && prevProps.data.workspace_id === nextProps.data.workspace_id && prevProps.data.workspace_name === nextProps.data.workspace_name && prevProps.isBottleneck === nextProps.isBottleneck && prevProps.isLowEfficiency === nextProps.isLowEfficiency && prevProps.isVeryLowEfficiency === nextProps.isVeryLowEfficiency && prevLegend.green_min === nextLegend.green_min && prevLegend.green_max === nextLegend.green_max && prevLegend.yellow_min === nextLegend.yellow_min && prevLegend.yellow_max === nextLegend.yellow_max && prevLegend.red_min === nextLegend.red_min && prevLegend.red_max === nextLegend.red_max && prevLegend.critical_threshold === nextLegend.critical_threshold && // Position doesn't need deep equality check as it's generally static
51081
51243
  prevProps.position.id === nextProps.position.id;
51082
51244
  };
51083
- var WorkspaceGridItem = React142__default.memo(({
51245
+ var WorkspaceGridItem = React143__default.memo(({
51084
51246
  data,
51085
51247
  position,
51086
51248
  isBottleneck = false,
@@ -51108,7 +51270,7 @@ var WorkspaceGridItem = React142__default.memo(({
51108
51270
  const handleClick = useCallback((e) => {
51109
51271
  e.preventDefault();
51110
51272
  if (isInactive) return;
51111
- const displayName = getWorkspaceDisplayName(data.workspace_name, data.line_id);
51273
+ const displayName = data.displayName || getWorkspaceDisplayName(data.workspace_name, data.line_id);
51112
51274
  const currentPath = typeof window !== "undefined" ? `${window.location.pathname}${window.location.search}` : "/";
51113
51275
  const navParams = getWorkspaceNavigationParams(data.workspace_id, displayName, data.line_id, currentPath);
51114
51276
  navigate(`/workspace/${data.workspace_id}${navParams}`, {
@@ -51157,7 +51319,7 @@ var WorkspaceGridItem = React142__default.memo(({
51157
51319
  onClick: handleClick,
51158
51320
  className: `${styles2} ${colorClass} ${isBottleneck ? "ring-2 ring-red-500/70" : ""} ${isVeryLowEfficiency ? "ring-2 ring-red-500/50" : ""} ${isInactive ? "bg-gray-200" : ""} shadow-lg touch-manipulation active:scale-[0.98] transition-transform`,
51159
51321
  "aria-label": isInactive ? `Inactive workspace ${workspaceNumber}` : `View details for workspace ${workspaceNumber}`,
51160
- title: isInactive ? `Inactive: ${getWorkspaceDisplayName(data.workspace_name, data.line_id)}` : getWorkspaceDisplayName(data.workspace_name, data.line_id),
51322
+ title: isInactive ? `Inactive: ${data.displayName || getWorkspaceDisplayName(data.workspace_name, data.line_id)}` : data.displayName || getWorkspaceDisplayName(data.workspace_name, data.line_id),
51161
51323
  children: /* @__PURE__ */ jsx("div", { className: `font-semibold tracking-wide text-lg sm:text-xl md:text-[min(4vw,2rem)] uppercase ${isInactive ? "text-gray-400" : "text-white"} drop-shadow-sm`, children: workspaceNumber })
51162
51324
  }
51163
51325
  ),
@@ -51175,7 +51337,7 @@ var WorkspaceGridItem = React142__default.memo(({
51175
51337
  );
51176
51338
  }, arePropsEqual);
51177
51339
  WorkspaceGridItem.displayName = "WorkspaceGridItem";
51178
- var WorkspaceGrid = React142__default.memo(({
51340
+ var WorkspaceGrid = React143__default.memo(({
51179
51341
  workspaces,
51180
51342
  isPdfMode = false,
51181
51343
  customWorkspacePositions,
@@ -51439,7 +51601,7 @@ var KPICard = ({
51439
51601
  }) => {
51440
51602
  useThemeConfig();
51441
51603
  const { formatNumber } = useFormatNumber();
51442
- const trendInfo = React142__default.useMemo(() => {
51604
+ const trendInfo = React143__default.useMemo(() => {
51443
51605
  let trendValue = trend || "neutral";
51444
51606
  if (change !== void 0 && trend === void 0) {
51445
51607
  trendValue = change > 0 ? "up" : change < 0 ? "down" : "neutral";
@@ -51466,7 +51628,7 @@ var KPICard = ({
51466
51628
  const shouldShowTrend = !(change === 0 && trend === void 0);
51467
51629
  return { trendValue, Icon: Icon2, colorClass, bgClass, shouldShowTrend };
51468
51630
  }, [trend, change]);
51469
- const formattedValue = React142__default.useMemo(() => {
51631
+ const formattedValue = React143__default.useMemo(() => {
51470
51632
  if (title === "Quality Compliance" && typeof value === "number") {
51471
51633
  return value.toFixed(1);
51472
51634
  }
@@ -51480,7 +51642,7 @@ var KPICard = ({
51480
51642
  }
51481
51643
  return value;
51482
51644
  }, [value, title]);
51483
- const formattedChange = React142__default.useMemo(() => {
51645
+ const formattedChange = React143__default.useMemo(() => {
51484
51646
  if (change === void 0 || change === 0 && !showZeroChange) return null;
51485
51647
  const absChange = Math.abs(change);
51486
51648
  return formatNumber(absChange, { minimumFractionDigits: 0, maximumFractionDigits: 1 });
@@ -52987,7 +53149,7 @@ var Breadcrumbs = ({ items }) => {
52987
53149
  }
52988
53150
  }
52989
53151
  };
52990
- return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "mb-1 flex items-center space-x-1 text-xs font-medium text-gray-500 dark:text-gray-400", children: items.map((item, index) => /* @__PURE__ */ jsxs(React142__default.Fragment, { children: [
53152
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "mb-1 flex items-center space-x-1 text-xs font-medium text-gray-500 dark:text-gray-400", children: items.map((item, index) => /* @__PURE__ */ jsxs(React143__default.Fragment, { children: [
52991
53153
  index > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "h-3 w-3 text-gray-400 dark:text-gray-500" }),
52992
53154
  /* @__PURE__ */ jsxs(
52993
53155
  "span",
@@ -54463,7 +54625,7 @@ var AwardBadge = ({
54463
54625
  }) => {
54464
54626
  const styles2 = getBadgeStyles(type);
54465
54627
  const Icon2 = CustomIcon || getDefaultIcon(type);
54466
- const randomDelay = React142__default.useMemo(() => Math.random() * 2, []);
54628
+ const randomDelay = React143__default.useMemo(() => Math.random() * 2, []);
54467
54629
  const floatingAnimation = {
54468
54630
  animate: {
54469
54631
  y: [0, -10, 0],
@@ -59967,67 +60129,77 @@ var NotificationService = class {
59967
60129
  this.supabaseClient = supabaseClient || null;
59968
60130
  }
59969
60131
  async fetchWithAuth(url, options = {}) {
59970
- if (!this.supabaseClient) {
59971
- throw new Error("Supabase client not initialized. Please provide a Supabase client to NotificationService.");
59972
- }
59973
- const { data: { session }, error: sessionError } = await this.supabaseClient.auth.getSession();
59974
- if (sessionError) {
59975
- console.error("Session error:", sessionError);
59976
- throw new Error("Failed to get authentication session. Please log in.");
59977
- }
59978
- if (!session) {
59979
- console.error("No session found. User must be logged in.");
59980
- throw new Error("User not authenticated. Please log in.");
59981
- }
59982
- if (!session.access_token) {
59983
- console.error("Session exists but no access_token found");
59984
- throw new Error("Invalid session. Please log in again.");
59985
- }
59986
- const token = session.access_token;
59987
- if (process.env.NODE_ENV === "development") {
59988
- console.log("[NotificationService] Using JWT token for notifications API");
59989
- }
59990
- const headers = {
59991
- "Content-Type": "application/json",
59992
- ...options.headers,
59993
- "Authorization": `Bearer ${token}`
59994
- };
59995
- const response = await fetch(url, {
59996
- ...options,
59997
- headers
59998
- });
59999
- if (response.status === 401) {
60000
- console.error("401 Unauthorized - Token expired or invalid");
60001
- throw new Error("Authentication failed. Please log in again.");
60002
- }
60003
- if (response.status === 403) {
60004
- console.error("403 Forbidden - User does not have permission");
60005
- throw new Error("Access denied. You do not have permission to access this resource.");
60006
- }
60007
- if (response.status === 500) {
60008
- console.error("500 Internal Server Error - Backend error");
60009
- let errorDetail = "Internal server error occurred.";
60010
- try {
60011
- const errorData = await response.text();
60012
- console.error("Backend error details:", errorData);
60013
- errorDetail = errorData || errorDetail;
60014
- } catch (e) {
60132
+ try {
60133
+ if (!this.supabaseClient) {
60134
+ throw new Error("Supabase client not initialized. Please provide a Supabase client to NotificationService.");
60015
60135
  }
60016
- throw new Error(`Backend error: ${errorDetail}`);
60017
- }
60018
- if (!response.ok) {
60019
- console.error(`HTTP ${response.status} - ${response.statusText}`);
60020
- let errorDetail = response.statusText;
60021
- try {
60022
- const errorData = await response.json();
60023
- if (errorData.detail) {
60024
- errorDetail = errorData.detail;
60136
+ const { data: { session }, error: sessionError } = await this.supabaseClient.auth.getSession();
60137
+ if (sessionError) {
60138
+ console.error("Session error:", sessionError);
60139
+ throw new Error("Failed to get authentication session. Please log in.");
60140
+ }
60141
+ if (!session) {
60142
+ console.error("No session found. User must be logged in.");
60143
+ throw new Error("User not authenticated. Please log in.");
60144
+ }
60145
+ if (!session.access_token) {
60146
+ console.error("Session exists but no access_token found");
60147
+ throw new Error("Invalid session. Please log in again.");
60148
+ }
60149
+ const token = session.access_token;
60150
+ if (process.env.NODE_ENV === "development") {
60151
+ console.log("[NotificationService] Using JWT token for notifications API");
60152
+ }
60153
+ const headers = {
60154
+ "Content-Type": "application/json",
60155
+ ...options.headers,
60156
+ "Authorization": `Bearer ${token}`
60157
+ };
60158
+ const response = await fetch(url, {
60159
+ ...options,
60160
+ headers
60161
+ });
60162
+ if (response.status === 401) {
60163
+ console.error("401 Unauthorized - Token expired or invalid");
60164
+ throw new Error("Authentication failed. Please log in again.");
60165
+ }
60166
+ if (response.status === 403) {
60167
+ console.error("403 Forbidden - User does not have permission");
60168
+ throw new Error("Access denied. You do not have permission to access this resource.");
60169
+ }
60170
+ if (response.status === 500) {
60171
+ console.error("500 Internal Server Error - Backend error");
60172
+ let errorDetail = "Internal server error occurred.";
60173
+ try {
60174
+ const errorData = await response.text();
60175
+ console.error("Backend error details:", errorData);
60176
+ errorDetail = errorData || errorDetail;
60177
+ } catch (e) {
60025
60178
  }
60026
- } catch (e) {
60179
+ throw new Error(`Backend error: ${errorDetail}`);
60180
+ }
60181
+ if (!response.ok) {
60182
+ console.error(`HTTP ${response.status} - ${response.statusText}`);
60183
+ let errorDetail = response.statusText;
60184
+ try {
60185
+ const errorData = await response.json();
60186
+ if (errorData.detail) {
60187
+ errorDetail = errorData.detail;
60188
+ }
60189
+ } catch (e) {
60190
+ }
60191
+ throw new Error(`Request failed (${response.status}): ${errorDetail}`);
60027
60192
  }
60028
- throw new Error(`Request failed (${response.status}): ${errorDetail}`);
60193
+ return response;
60194
+ } catch (error) {
60195
+ captureHandledFrontendException(error, {
60196
+ surface: "notification_service",
60197
+ url,
60198
+ method: options.method || "GET",
60199
+ pathname: typeof window !== "undefined" ? window.location.pathname : "unknown"
60200
+ });
60201
+ throw error;
60029
60202
  }
60030
- return response;
60031
60203
  }
60032
60204
  /**
60033
60205
  * Get bottleneck notifications
@@ -60101,8 +60273,6 @@ function HomeView({
60101
60273
  }) {
60102
60274
  const [isHydrated, setIsHydrated] = useState(false);
60103
60275
  const [isChangingFilter, setIsChangingFilter] = useState(false);
60104
- const [errorMessage, setErrorMessage] = useState(null);
60105
- const [displayNamesInitialized, setDisplayNamesInitialized] = useState(false);
60106
60276
  const [hasInitialDataLoaded, setHasInitialDataLoaded] = useState(false);
60107
60277
  const [showDataLoading, setShowDataLoading] = useState(false);
60108
60278
  const loadingStartRef = useRef(null);
@@ -60111,7 +60281,7 @@ function HomeView({
60111
60281
  const dashboardConfig = useDashboardConfig();
60112
60282
  const entityConfig = useEntityConfig();
60113
60283
  const supabaseClient = useSupabaseClient();
60114
- const { user } = useAuth();
60284
+ const { user, authStatus, isRecoveringSession, retrySessionHydration } = useAuth();
60115
60285
  const { lines: dbLines } = useLines();
60116
60286
  const mergedLineNames = useMemo(() => {
60117
60287
  const merged = { ...lineNames };
@@ -60245,26 +60415,7 @@ function HomeView({
60245
60415
  visibleLineIds,
60246
60416
  dashboardConfig?.shiftConfig
60247
60417
  );
60248
- useEffect(() => {
60249
- const initDisplayNames = async () => {
60250
- try {
60251
- for (const lineId of selectedLineIds) {
60252
- await preInitializeWorkspaceDisplayNames(lineId);
60253
- }
60254
- setDisplayNamesInitialized(true);
60255
- } catch (error) {
60256
- console.error("Failed to pre-initialize workspace display names:", error);
60257
- setDisplayNamesInitialized(true);
60258
- }
60259
- };
60260
- initDisplayNames();
60261
- }, [selectedLineIdsKey]);
60262
- const displayNameLineId = isMultiLineSelection ? void 0 : primarySelectedLineId;
60263
- const {
60264
- displayNames: workspaceDisplayNames,
60265
- loading: displayNamesLoading,
60266
- error: displayNamesError
60267
- } = useWorkspaceDisplayNames(displayNameLineId, void 0);
60418
+ const shouldEnableMetricsFetch = authStatus === "ready";
60268
60419
  const handleLineMetricsUpdate = useCallback(() => {
60269
60420
  if (trendRefreshTimerRef.current) {
60270
60421
  window.clearTimeout(trendRefreshTimerRef.current);
@@ -60291,9 +60442,32 @@ function HomeView({
60291
60442
  lineId: metricsScopeLineId,
60292
60443
  lineIds: selectedLineIds,
60293
60444
  onLineMetricsUpdate: handleLineMetricsUpdate,
60294
- userAccessibleLineIds: visibleLineIds
60445
+ userAccessibleLineIds: visibleLineIds,
60295
60446
  // Pass user's accessible lines for supervisor filtering
60447
+ enabled: shouldEnableMetricsFetch
60296
60448
  });
60449
+ const metricsDisplayNames = useMemo(() => {
60450
+ const nextDisplayNames = {};
60451
+ workspaceMetrics.forEach((workspace) => {
60452
+ if (!workspace.displayName) {
60453
+ return;
60454
+ }
60455
+ nextDisplayNames[`${workspace.line_id}_${workspace.workspace_name}`] = workspace.displayName;
60456
+ });
60457
+ return nextDisplayNames;
60458
+ }, [workspaceMetrics]);
60459
+ useEffect(() => {
60460
+ workspaceMetrics.forEach((workspace) => {
60461
+ if (!workspace.displayName) {
60462
+ return;
60463
+ }
60464
+ upsertWorkspaceDisplayNameInCache({
60465
+ lineId: workspace.line_id,
60466
+ workspaceId: workspace.workspace_name,
60467
+ displayName: workspace.displayName
60468
+ });
60469
+ });
60470
+ }, [workspaceMetrics]);
60297
60471
  const trendGroups = useMemo(() => {
60298
60472
  const lineMetricsRows = lineMetrics || [];
60299
60473
  if (!lineMetricsRows.length) return null;
@@ -60734,13 +60908,13 @@ function HomeView({
60734
60908
  dashboard_surface: "monitor"
60735
60909
  });
60736
60910
  }, []);
60737
- useEffect(() => {
60738
- if (metricsError) {
60739
- setErrorMessage(metricsError.message);
60740
- } else {
60741
- setErrorMessage(null);
60911
+ const metricsErrorMessage = metricsError?.message || null;
60912
+ const handleRetryDashboardData = useCallback(async () => {
60913
+ if (isRecoveringSession) {
60914
+ await retrySessionHydration();
60742
60915
  }
60743
- }, [metricsError]);
60916
+ refetchMetrics();
60917
+ }, [isRecoveringSession, refetchMetrics, retrySessionHydration]);
60744
60918
  const getTrackedLineScope = useCallback((lineIdsForScope) => {
60745
60919
  if (isAllLinesSelection(lineIdsForScope)) {
60746
60920
  return factoryViewId;
@@ -60798,7 +60972,7 @@ function HomeView({
60798
60972
  }
60799
60973
  }, [metricsLoading, isChangingFilter]);
60800
60974
  useEffect(() => {
60801
- if (!metricsLoading && !hasInitialDataLoaded) {
60975
+ if (shouldEnableMetricsFetch && !metricsLoading && !metricsError && !hasInitialDataLoaded) {
60802
60976
  setHasInitialDataLoaded(true);
60803
60977
  trackCoreEvent("monitor page loaded", {
60804
60978
  default_line_id: defaultLineId,
@@ -60807,7 +60981,7 @@ function HomeView({
60807
60981
  dashboard_surface: "monitor"
60808
60982
  });
60809
60983
  }
60810
- }, [metricsLoading, hasInitialDataLoaded, defaultLineId, factoryViewId, isSupervisor]);
60984
+ }, [shouldEnableMetricsFetch, metricsLoading, metricsError, hasInitialDataLoaded, defaultLineId, factoryViewId, isSupervisor]);
60811
60985
  const lineTitle = useMemo(() => {
60812
60986
  return factoryName;
60813
60987
  }, [factoryName]);
@@ -60957,8 +61131,9 @@ function HomeView({
60957
61131
  }, [isLoading, minDuration]);
60958
61132
  return showLoading;
60959
61133
  };
60960
- const isInitialLoading = !isHydrated || !hasInitialDataLoaded && (displayNamesLoading || !displayNamesInitialized);
60961
- const isDataLoading = metricsLoading || displayNamesLoading && workspaceMetrics.length === 0;
61134
+ const isAuthBootstrapping = authStatus === "loading";
61135
+ const isInitialLoading = !isHydrated || !hasInitialDataLoaded && (isAuthBootstrapping || shouldEnableMetricsFetch && metricsLoading);
61136
+ const isDataLoading = metricsLoading;
60962
61137
  const hasKpiDataReady = useMemo(() => {
60963
61138
  const lineMetricsRows = lineMetrics || [];
60964
61139
  if (selectedLineIds.length > 1) {
@@ -60967,6 +61142,10 @@ function HomeView({
60967
61142
  return lineMetricsRows.some((row) => row?.line_id === primarySelectedLineId);
60968
61143
  }, [lineMetrics, primarySelectedLineId, selectedLineIdSet, selectedLineIds.length]);
60969
61144
  const isKpiLoading = !hasKpiDataReady;
61145
+ const shouldShowReconnectScreen = !hasInitialDataLoaded && (isRecoveringSession || !shouldEnableMetricsFetch && authStatus !== "failed" || !!metricsErrorMessage && authStatus !== "failed");
61146
+ const shouldShowFatalLoadFailure = !hasInitialDataLoaded && !!metricsErrorMessage && authStatus === "failed";
61147
+ const shouldShowRecoveryBanner = hasInitialDataLoaded && (isRecoveringSession || !!metricsErrorMessage);
61148
+ const recoveryBannerMessage = isRecoveringSession ? "Reconnecting to the dashboard. Showing the last good data while auth recovers." : metricsErrorMessage ? "Live data refresh failed. Showing the last good dashboard snapshot." : null;
60970
61149
  useEffect(() => {
60971
61150
  const minLoadingDurationMs = 250;
60972
61151
  if (isDataLoading) {
@@ -61006,14 +61185,41 @@ function HomeView({
61006
61185
  if (isInitialLoading) {
61007
61186
  return /* @__PURE__ */ jsx(LoadingPageCmp, { message: "Loading Dashboard..." });
61008
61187
  }
61009
- if (errorMessage || displayNamesError) {
61010
- return /* @__PURE__ */ jsx("div", { className: "flex h-screen items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg bg-white p-6 shadow-lg", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3 text-red-500", children: [
61011
- /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
61012
- /* @__PURE__ */ jsxs("span", { className: "text-base sm:text-lg font-medium", children: [
61013
- "Error: ",
61014
- errorMessage || displayNamesError?.message
61015
- ] })
61016
- ] }) }) });
61188
+ if (shouldShowReconnectScreen) {
61189
+ return /* @__PURE__ */ jsx("div", { className: "flex h-screen items-center justify-center bg-slate-50 px-6", children: /* @__PURE__ */ jsxs("div", { className: "max-w-md rounded-2xl border border-slate-200 bg-white p-8 text-center shadow-sm", children: [
61190
+ /* @__PURE__ */ jsx("div", { className: "mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-amber-50 text-amber-600", children: /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 4v5h.582m14.836 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-14.837-2m14.837 2H15" }) }) }),
61191
+ /* @__PURE__ */ jsx("h2", { className: "mt-4 text-lg font-semibold text-slate-900", children: "Reconnecting to Optifye" }),
61192
+ /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-slate-600", children: metricsErrorMessage || "Your session is recovering after the tab resumed. We will retry automatically." }),
61193
+ /* @__PURE__ */ jsx(
61194
+ "button",
61195
+ {
61196
+ type: "button",
61197
+ onClick: () => {
61198
+ void handleRetryDashboardData();
61199
+ },
61200
+ className: "mt-5 inline-flex items-center justify-center rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-slate-800",
61201
+ children: "Retry Now"
61202
+ }
61203
+ )
61204
+ ] }) });
61205
+ }
61206
+ if (shouldShowFatalLoadFailure) {
61207
+ return /* @__PURE__ */ jsx("div", { className: "flex h-screen items-center justify-center bg-slate-50 px-6", children: /* @__PURE__ */ jsxs("div", { className: "max-w-md rounded-2xl border border-red-200 bg-white p-8 text-center shadow-sm", children: [
61208
+ /* @__PURE__ */ jsx("div", { className: "mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-50 text-red-600", children: /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }) }),
61209
+ /* @__PURE__ */ jsx("h2", { className: "mt-4 text-lg font-semibold text-slate-900", children: "Unable to load the dashboard" }),
61210
+ /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-slate-600", children: metricsErrorMessage }),
61211
+ /* @__PURE__ */ jsx(
61212
+ "button",
61213
+ {
61214
+ type: "button",
61215
+ onClick: () => {
61216
+ void handleRetryDashboardData();
61217
+ },
61218
+ className: "mt-5 inline-flex items-center justify-center rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-slate-800",
61219
+ children: "Retry Now"
61220
+ }
61221
+ )
61222
+ ] }) });
61017
61223
  }
61018
61224
  return /* @__PURE__ */ jsx(
61019
61225
  motion.div,
@@ -61032,6 +61238,20 @@ function HomeView({
61032
61238
  headerControls: kpiSectionControl
61033
61239
  }
61034
61240
  ) }) }),
61241
+ shouldShowRecoveryBanner && recoveryBannerMessage ? /* @__PURE__ */ jsx("div", { className: "border-b border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between", children: [
61242
+ /* @__PURE__ */ jsx("span", { children: recoveryBannerMessage }),
61243
+ /* @__PURE__ */ jsx(
61244
+ "button",
61245
+ {
61246
+ type: "button",
61247
+ onClick: () => {
61248
+ void handleRetryDashboardData();
61249
+ },
61250
+ className: "inline-flex items-center justify-center rounded-md border border-amber-300 bg-white px-3 py-1.5 text-xs font-medium text-amber-900 transition-colors hover:bg-amber-100",
61251
+ children: "Retry"
61252
+ }
61253
+ )
61254
+ ] }) }) : null,
61035
61255
  /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto sm:overflow-hidden relative flex flex-col", children: /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-[calc(100vh-100px)] sm:min-h-0", children: workspaceMetricsWithBreakState.length > 0 ? /* @__PURE__ */ jsx(
61036
61256
  motion.div,
61037
61257
  {
@@ -61039,7 +61259,7 @@ function HomeView({
61039
61259
  animate: { opacity: 1, scale: 1 },
61040
61260
  transition: { duration: 0.3 },
61041
61261
  className: "h-full",
61042
- children: React142__default.createElement(WorkspaceGrid, {
61262
+ children: React143__default.createElement(WorkspaceGrid, {
61043
61263
  workspaces: workspaceMetricsWithBreakState,
61044
61264
  lineNames: mergedLineNames,
61045
61265
  lineOrder: selectedLineIds,
@@ -61048,7 +61268,7 @@ function HomeView({
61048
61268
  videoSources,
61049
61269
  videoStreamsByWorkspaceId,
61050
61270
  videoStreamsLoading,
61051
- displayNames: workspaceDisplayNames,
61271
+ displayNames: metricsDisplayNames,
61052
61272
  hasFlowBuffers,
61053
61273
  className: "h-full",
61054
61274
  toolbarRightContent: lineSelectorComponent,
@@ -61072,7 +61292,7 @@ function HomeView({
61072
61292
  animate: { opacity: 1, scale: 1 },
61073
61293
  transition: { duration: 0.3 },
61074
61294
  className: "h-full",
61075
- children: React142__default.createElement(WorkspaceGrid, {
61295
+ children: React143__default.createElement(WorkspaceGrid, {
61076
61296
  workspaces: [],
61077
61297
  // Show empty grid while loading
61078
61298
  lineNames: mergedLineNames,
@@ -61082,7 +61302,7 @@ function HomeView({
61082
61302
  videoSources,
61083
61303
  videoStreamsByWorkspaceId,
61084
61304
  videoStreamsLoading,
61085
- displayNames: workspaceDisplayNames,
61305
+ displayNames: metricsDisplayNames,
61086
61306
  hasFlowBuffers,
61087
61307
  className: "h-full",
61088
61308
  toolbarRightContent: lineSelectorComponent,
@@ -61140,7 +61360,7 @@ function HomeView({
61140
61360
  }
61141
61361
  );
61142
61362
  }
61143
- var AuthenticatedHomeView = withAuth(React142__default.memo(HomeView));
61363
+ var AuthenticatedHomeView = withAuth(React143__default.memo(HomeView));
61144
61364
  var HomeView_default = HomeView;
61145
61365
  function withWorkspaceDisplayNames(Component3, options = {}) {
61146
61366
  const {
@@ -61338,6 +61558,7 @@ var buildLineInfoSnapshot = (lineDetails, metrics2) => {
61338
61558
  shift_id: metrics2.shift_id ?? 0,
61339
61559
  date: metrics2.date || "",
61340
61560
  monitoring_mode: lineDetails.monitoring_mode ?? void 0,
61561
+ assembly: lineDetails.assembly ?? null,
61341
61562
  metrics: {
61342
61563
  avg_efficiency: metrics2.avg_efficiency ?? 0,
61343
61564
  avg_cycle_time: metrics2.avg_cycle_time ?? 0,
@@ -61370,6 +61591,7 @@ var transformWorkspaceMetrics = (workspaceData, lineId, companyId, queryDate, qu
61370
61591
  pph: item.avg_pph || 0,
61371
61592
  performance_score: item.performance_score || 0,
61372
61593
  avg_cycle_time: item.avg_cycle_time || 0,
61594
+ ideal_cycle_time: item.ideal_cycle_time ?? void 0,
61373
61595
  trend: item.trend_score === 1 ? 2 : 0,
61374
61596
  predicted_output: item.ideal_output || 0,
61375
61597
  efficiency: item.efficiency || 0,
@@ -61405,7 +61627,8 @@ var transformLineDetails = (lineId, detailResponse) => {
61405
61627
  id: detailResponse.line_details.factory_id || "",
61406
61628
  factory_name: detailResponse.line_details.factory_name || ""
61407
61629
  },
61408
- monitoring_mode: detailResponse.line_details.monitoring_mode ?? void 0
61630
+ monitoring_mode: detailResponse.line_details.monitoring_mode ?? void 0,
61631
+ assembly: detailResponse.line_details.assembly ?? null
61409
61632
  };
61410
61633
  };
61411
61634
  var transformLineMetrics = (lineId, detailResponse, queryDate, queryShiftId) => {
@@ -61806,6 +62029,56 @@ function useEfficiencyLegend(companyId) {
61806
62029
  refetch: fetchLegend
61807
62030
  };
61808
62031
  }
62032
+
62033
+ // src/lib/utils/cycleTime.ts
62034
+ var toFiniteNumber = (value) => {
62035
+ if (typeof value === "number" && Number.isFinite(value)) return value;
62036
+ if (typeof value === "string" && value.trim() !== "") {
62037
+ const parsed = Number(value);
62038
+ return Number.isFinite(parsed) ? parsed : null;
62039
+ }
62040
+ return null;
62041
+ };
62042
+ var getCycleRatio = (workspace) => {
62043
+ const idealCycleTime = toFiniteNumber(workspace.ideal_cycle_time);
62044
+ const avgCycleTime = toFiniteNumber(workspace.avg_cycle_time);
62045
+ if (idealCycleTime === null || avgCycleTime === null || idealCycleTime <= 0 || avgCycleTime <= 0) {
62046
+ return null;
62047
+ }
62048
+ return idealCycleTime / avgCycleTime;
62049
+ };
62050
+ var formatCycleTimeValue = (value) => {
62051
+ const numericValue = toFiniteNumber(value);
62052
+ if (numericValue === null || numericValue <= 0) return "--";
62053
+ return `${numericValue.toFixed(1)}s`;
62054
+ };
62055
+ var CycleTimeComparison = memo$1(({
62056
+ workspace
62057
+ }) => {
62058
+ const averageValue = formatCycleTimeValue(workspace.avg_cycle_time);
62059
+ const standardValue = formatCycleTimeValue(workspace.ideal_cycle_time);
62060
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 tabular-nums", children: [
62061
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-gray-900", children: averageValue }),
62062
+ /* @__PURE__ */ jsx("span", { className: "text-gray-400 font-normal", children: "/" }),
62063
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-500", children: standardValue })
62064
+ ] });
62065
+ }, (prevProps, nextProps) => prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.ideal_cycle_time === nextProps.workspace.ideal_cycle_time);
62066
+ CycleTimeComparison.displayName = "CycleTimeComparison";
62067
+
62068
+ // src/lib/utils/kpiPoorestPerformers.ts
62069
+ var getWorstAssemblyCycleTimeWorkspaces = (workspaces, limit = 5) => {
62070
+ return workspaces.map((workspace, index) => ({
62071
+ workspace,
62072
+ index,
62073
+ cycleRatio: getCycleRatio(workspace)
62074
+ })).sort((a, b) => {
62075
+ if (a.cycleRatio === null && b.cycleRatio === null) return a.index - b.index;
62076
+ if (a.cycleRatio === null) return 1;
62077
+ if (b.cycleRatio === null) return -1;
62078
+ if (a.cycleRatio !== b.cycleRatio) return a.cycleRatio - b.cycleRatio;
62079
+ return a.index - b.index;
62080
+ }).slice(0, limit).map(({ workspace }) => workspace);
62081
+ };
61809
62082
  var WEEKDAYS4 = ["S", "M", "T", "W", "T", "F", "S"];
61810
62083
  var MonthlyRangeFilter = ({
61811
62084
  month,
@@ -62405,7 +62678,13 @@ var BottomSection = memo$1(({
62405
62678
  }) => {
62406
62679
  const navigation = useNavigation();
62407
62680
  const handleNavigate = navigate || navigation.navigate;
62681
+ const isAssemblyLine = (lineInfo.assembly === true || workspaceData.some((workspace) => workspace.assembly_enabled)) && lineInfo.monitoring_mode !== "uptime";
62682
+ const assemblyRows = useMemo(
62683
+ () => isAssemblyLine ? getWorstAssemblyCycleTimeWorkspaces(workspaceData) : [],
62684
+ [isAssemblyLine, workspaceData]
62685
+ );
62408
62686
  const handleWorkspaceClick = useCallback((ws, index) => {
62687
+ const cycleRatio = getCycleRatio(ws);
62409
62688
  trackCoreEvent("Workspace from KPI Clicked", {
62410
62689
  workspace_name: ws.workspace_name,
62411
62690
  workspace_id: ws.workspace_uuid,
@@ -62414,9 +62693,13 @@ var BottomSection = memo$1(({
62414
62693
  efficiency: ws.efficiency,
62415
62694
  action_count: ws.action_count,
62416
62695
  action_threshold: ws.action_threshold,
62696
+ avg_cycle_time: ws.avg_cycle_time ?? null,
62697
+ ideal_cycle_time: ws.ideal_cycle_time ?? null,
62698
+ cycle_ratio: cycleRatio,
62699
+ ranking_metric: isAssemblyLine ? "cycle_time" : "efficiency",
62417
62700
  section: "Poorest Performing Workspaces"
62418
62701
  });
62419
- }, [workspaceData.length]);
62702
+ }, [isAssemblyLine, workspaceData.length]);
62420
62703
  return /* @__PURE__ */ jsxs(
62421
62704
  motion.div,
62422
62705
  {
@@ -62438,14 +62721,42 @@ var BottomSection = memo$1(({
62438
62721
  )
62439
62722
  ] }),
62440
62723
  /* @__PURE__ */ jsxs("div", { className: "divide-y overflow-auto flex-1 pr-1 sm:pr-2", children: [
62441
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pb-2", children: [
62724
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between pb-2", children: isAssemblyLine ? /* @__PURE__ */ jsxs(Fragment, { children: [
62725
+ /* @__PURE__ */ jsx("div", { className: "font-medium text-gray-500 min-w-[80px] sm:min-w-[100px] md:min-w-[120px] text-xs sm:text-sm md:text-base", children: "Workspace" }),
62726
+ /* @__PURE__ */ jsx("div", { className: "text-xs md:text-sm font-medium text-gray-500 pr-1 sm:pr-2", children: "Cycle Time" })
62727
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
62442
62728
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 sm:gap-3 md:gap-6", children: [
62443
62729
  /* @__PURE__ */ jsx("div", { className: "font-medium text-gray-500 min-w-[80px] sm:min-w-[100px] md:min-w-[120px] text-xs sm:text-sm md:text-base", children: "Workspace" }),
62444
62730
  /* @__PURE__ */ jsx("div", { className: "text-xs md:text-sm font-medium text-gray-500", children: "Current/Ideal" })
62445
62731
  ] }),
62446
62732
  /* @__PURE__ */ jsx("div", { className: "text-xs md:text-sm font-medium text-gray-500 pr-1 sm:pr-2", children: "Efficiency" })
62447
- ] }),
62448
- lineInfo.metrics.poorest_performing_workspaces && lineInfo.metrics.poorest_performing_workspaces.length > 0 ? lineInfo.metrics.poorest_performing_workspaces.map((ws, index) => {
62733
+ ] }) }),
62734
+ isAssemblyLine ? assemblyRows.map((ws, index) => {
62735
+ if (!ws.workspace_uuid) {
62736
+ return null;
62737
+ }
62738
+ const clickHandler = () => handleWorkspaceClick(ws, index);
62739
+ const displayName = workspaceDisplayNames && workspaceDisplayNames[ws.workspace_name] || getWorkspaceDisplayName(ws.workspace_name, lineId);
62740
+ const navParams = getWorkspaceNavigationParams(ws.workspace_uuid, displayName, lineId);
62741
+ const dateShiftParams = urlDate ? `&date=${urlDate}&shift=${urlShift || "0"}` : "";
62742
+ const returnToParam = `&returnTo=${encodeURIComponent(`/kpis/${lineInfo?.line_id}`)}`;
62743
+ const fullUrl = `/workspace/${ws.workspace_uuid}${navParams}${dateShiftParams}${returnToParam}`;
62744
+ return /* @__PURE__ */ jsx(
62745
+ "div",
62746
+ {
62747
+ onClick: () => {
62748
+ clickHandler();
62749
+ handleNavigate && handleNavigate(fullUrl);
62750
+ },
62751
+ className: "block py-2 sm:py-3 hover:bg-gray-50 transition-colors rounded-lg cursor-pointer",
62752
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
62753
+ /* @__PURE__ */ jsx("div", { className: "min-w-[80px] sm:min-w-[100px] md:min-w-[120px]", children: /* @__PURE__ */ jsx("div", { className: "font-medium text-gray-900 text-xs sm:text-sm md:text-base truncate", children: displayName }) }),
62754
+ /* @__PURE__ */ jsx("div", { className: "shrink-0 text-xs md:text-sm", children: /* @__PURE__ */ jsx(CycleTimeComparison, { workspace: ws }) })
62755
+ ] })
62756
+ },
62757
+ ws.workspace_uuid
62758
+ );
62759
+ }) : lineInfo.metrics.poorest_performing_workspaces && lineInfo.metrics.poorest_performing_workspaces.length > 0 ? lineInfo.metrics.poorest_performing_workspaces.map((ws, index) => {
62449
62760
  const wsMetrics = workspaceData.find((w) => w.workspace_name === ws.workspace_name);
62450
62761
  const wsUuid = wsMetrics?.workspace_uuid;
62451
62762
  if (!wsUuid) {
@@ -62541,10 +62852,63 @@ var BottomSection = memo$1(({
62541
62852
  const prevPoorest = prevProps.lineInfo.metrics.poorest_performing_workspaces || [];
62542
62853
  const nextPoorest = nextProps.lineInfo.metrics.poorest_performing_workspaces || [];
62543
62854
  if (prevPoorest.length !== nextPoorest.length) return false;
62855
+ const prevPoorestSignature = JSON.stringify(prevPoorest);
62856
+ const nextPoorestSignature = JSON.stringify(nextPoorest);
62857
+ if (prevPoorestSignature !== nextPoorestSignature) return false;
62858
+ if (prevProps.lineInfo.assembly !== nextProps.lineInfo.assembly) return false;
62859
+ if (prevProps.lineInfo.monitoring_mode !== nextProps.lineInfo.monitoring_mode) return false;
62544
62860
  if (prevProps.hourlyOutputData.length !== nextProps.hourlyOutputData.length) return false;
62545
62861
  const hourlyDataChanged = prevProps.hourlyOutputData.some((value, index) => value !== nextProps.hourlyOutputData[index]);
62546
62862
  if (hourlyDataChanged) return false;
62547
62863
  if (prevProps.sortedByEfficiency.length !== nextProps.sortedByEfficiency.length) return false;
62864
+ const prevSortedSignature = JSON.stringify(
62865
+ prevProps.sortedByEfficiency.map((workspace) => ({
62866
+ workspace_uuid: workspace.workspace_uuid,
62867
+ workspace_name: workspace.workspace_name,
62868
+ efficiency: workspace.efficiency,
62869
+ action_count: workspace.action_count,
62870
+ predicted_output: workspace.predicted_output,
62871
+ avg_cycle_time: workspace.avg_cycle_time,
62872
+ ideal_cycle_time: workspace.ideal_cycle_time ?? null
62873
+ }))
62874
+ );
62875
+ const nextSortedSignature = JSON.stringify(
62876
+ nextProps.sortedByEfficiency.map((workspace) => ({
62877
+ workspace_uuid: workspace.workspace_uuid,
62878
+ workspace_name: workspace.workspace_name,
62879
+ efficiency: workspace.efficiency,
62880
+ action_count: workspace.action_count,
62881
+ predicted_output: workspace.predicted_output,
62882
+ avg_cycle_time: workspace.avg_cycle_time,
62883
+ ideal_cycle_time: workspace.ideal_cycle_time ?? null
62884
+ }))
62885
+ );
62886
+ if (prevSortedSignature !== nextSortedSignature) return false;
62887
+ const prevWorkspaceSignature = JSON.stringify(
62888
+ prevProps.workspaceData.map((workspace) => ({
62889
+ workspace_uuid: workspace.workspace_uuid,
62890
+ workspace_name: workspace.workspace_name,
62891
+ efficiency: workspace.efficiency,
62892
+ action_count: workspace.action_count,
62893
+ action_threshold: workspace.action_threshold,
62894
+ predicted_output: workspace.predicted_output,
62895
+ avg_cycle_time: workspace.avg_cycle_time,
62896
+ ideal_cycle_time: workspace.ideal_cycle_time ?? null
62897
+ }))
62898
+ );
62899
+ const nextWorkspaceSignature = JSON.stringify(
62900
+ nextProps.workspaceData.map((workspace) => ({
62901
+ workspace_uuid: workspace.workspace_uuid,
62902
+ workspace_name: workspace.workspace_name,
62903
+ efficiency: workspace.efficiency,
62904
+ action_count: workspace.action_count,
62905
+ action_threshold: workspace.action_threshold,
62906
+ predicted_output: workspace.predicted_output,
62907
+ avg_cycle_time: workspace.avg_cycle_time,
62908
+ ideal_cycle_time: workspace.ideal_cycle_time ?? null
62909
+ }))
62910
+ );
62911
+ if (prevWorkspaceSignature !== nextWorkspaceSignature) return false;
62548
62912
  if (prevProps.lineInfo.metrics.shift_start !== nextProps.lineInfo.metrics.shift_start) return false;
62549
62913
  if (prevProps.hourlyThreshold !== nextProps.hourlyThreshold) return false;
62550
62914
  if (prevProps.urlDate !== nextProps.urlDate || prevProps.urlShift !== nextProps.urlShift) return false;
@@ -63019,6 +63383,7 @@ var KPIDetailView = ({
63019
63383
  shift_id: metrics2.shift_id ?? 0,
63020
63384
  date: metrics2.date || getOperationalDate(timezone || "UTC"),
63021
63385
  monitoring_mode: lineDetails.monitoring_mode ?? void 0,
63386
+ assembly: lineDetails.assembly ?? null,
63022
63387
  metrics: {
63023
63388
  avg_efficiency: metrics2.avg_efficiency ?? 0,
63024
63389
  avg_cycle_time: metrics2.avg_cycle_time ?? 0,
@@ -64110,18 +64475,18 @@ var LinesLeaderboard = ({
64110
64475
  isHistoricalDaily
64111
64476
  }) => {
64112
64477
  const formatEfficiency = (value) => typeof value === "number" && Number.isFinite(value) ? `${value.toFixed(1)}%` : "--";
64113
- const assignedLineIdSet = React142__default.useMemo(
64478
+ const assignedLineIdSet = React143__default.useMemo(
64114
64479
  () => new Set(assignedLineIds || []),
64115
64480
  [assignedLineIds]
64116
64481
  );
64117
- const canClickLine = React142__default.useCallback(
64482
+ const canClickLine = React143__default.useCallback(
64118
64483
  (lineId) => {
64119
64484
  if (!assignedLineIds) return true;
64120
64485
  return assignedLineIdSet.has(lineId);
64121
64486
  },
64122
64487
  [assignedLineIds, assignedLineIdSet]
64123
64488
  );
64124
- const handleTimeRangeChange = React142__default.useCallback((newRange) => {
64489
+ const handleTimeRangeChange = React143__default.useCallback((newRange) => {
64125
64490
  if (newRange === timeRange) return;
64126
64491
  trackCoreEvent("Leaderboard Time Range Changed", {
64127
64492
  from_range: timeRange,
@@ -64132,7 +64497,7 @@ var LinesLeaderboard = ({
64132
64497
  });
64133
64498
  setTimeRange(newRange);
64134
64499
  }, [timeRange, lines.length, monthlyEfficiencyByLineId, setTimeRange]);
64135
- const handleLeaderboardLineClick = React142__default.useCallback((item, clickSource) => {
64500
+ const handleLeaderboardLineClick = React143__default.useCallback((item, clickSource) => {
64136
64501
  if (!canClickLine(item.line.id)) return;
64137
64502
  trackCoreEvent("Leaderboard Line Clicked", {
64138
64503
  line_id: item.line.id,
@@ -64146,8 +64511,8 @@ var LinesLeaderboard = ({
64146
64511
  });
64147
64512
  onLineClick(item.line);
64148
64513
  }, [canClickLine, onLineClick, timeRange]);
64149
- const viewLoadedTrackedRef = React142__default.useRef(null);
64150
- const leaderboardData = React142__default.useMemo(() => {
64514
+ const viewLoadedTrackedRef = React143__default.useRef(null);
64515
+ const leaderboardData = React143__default.useMemo(() => {
64151
64516
  const loading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
64152
64517
  const efficiencyMap = timeRange === "today" ? todayEfficiencyByLineId : monthlyEfficiencyByLineId;
64153
64518
  return lines.map((line) => {
@@ -64178,7 +64543,7 @@ var LinesLeaderboard = ({
64178
64543
  isLoadingToday,
64179
64544
  isLoadingMonthly
64180
64545
  ]);
64181
- React142__default.useEffect(() => {
64546
+ React143__default.useEffect(() => {
64182
64547
  const isLoading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
64183
64548
  const trackingKey = `${timeRange}-${leaderboardData.length}`;
64184
64549
  if (leaderboardData.length > 0 && !isLoading && viewLoadedTrackedRef.current !== trackingKey) {
@@ -64204,7 +64569,7 @@ var LinesLeaderboard = ({
64204
64569
  const countdownFormat = timeRange === "monthly" ? "days" : "clock";
64205
64570
  const countdownFinishedLabel = timeRange === "monthly" ? "Finished" : "Shift Ended";
64206
64571
  const showCountdown = timeRange === "monthly" || !isHistoricalDaily;
64207
- const handleCountdownFinished = React142__default.useCallback(() => {
64572
+ const handleCountdownFinished = React143__default.useCallback(() => {
64208
64573
  trackCoreEvent("Leaderboard Countdown Finished", {
64209
64574
  countdown_type: timeRange === "monthly" ? "month_end" : "shift_end",
64210
64575
  time_range: timeRange,
@@ -64231,7 +64596,7 @@ var LinesLeaderboard = ({
64231
64596
  return "bg-white border-gray-100";
64232
64597
  }
64233
64598
  };
64234
- React142__default.useEffect(() => {
64599
+ React143__default.useEffect(() => {
64235
64600
  const style = document.createElement("style");
64236
64601
  style.innerHTML = `
64237
64602
  @keyframes float {
@@ -64418,7 +64783,7 @@ var LineCard = ({
64418
64783
  supervisors
64419
64784
  }) => {
64420
64785
  const isUptimeLine = (line.monitoring_mode ?? "output") === "uptime";
64421
- const isOnTrack = React142__default.useMemo(() => {
64786
+ const isOnTrack = React143__default.useMemo(() => {
64422
64787
  if (!kpis) return null;
64423
64788
  return isEfficiencyOnTrack(kpis.efficiency.value);
64424
64789
  }, [kpis]);
@@ -64616,46 +64981,46 @@ var KPIsOverviewView = ({
64616
64981
  const configuredTimezone = dbTimezone || dateTimeConfig.defaultTimezone || "UTC";
64617
64982
  const { startDate: monthStartDate, endDate: monthEndDateKey, monthEndDate } = getMonthDateInfo(configuredTimezone);
64618
64983
  const isSuperAdmin = user?.scope_mode === "SUPER_ADMIN" || !!user?.access_scope?.is_super_admin;
64619
- const scopedLineIds = React142__default.useMemo(
64984
+ const scopedLineIds = React143__default.useMemo(
64620
64985
  () => Array.isArray(user?.access_scope?.line_ids) ? user.access_scope.line_ids.filter((lineId) => typeof lineId === "string" && lineId.length > 0) : [],
64621
64986
  [user?.access_scope?.line_ids]
64622
64987
  );
64623
64988
  const hasCanonicalScope = !!user?.scope_mode || !!user?.access_scope;
64624
64989
  const scopeRole = (user?.role_level || user?.role || "").toLowerCase();
64625
64990
  const isStrictLineScopedRole = scopeRole === "supervisor" || isFactoryScopedRole(scopeRole);
64626
- const resolvedAssignedLineIds = React142__default.useMemo(() => {
64991
+ const resolvedAssignedLineIds = React143__default.useMemo(() => {
64627
64992
  if (isSuperAdmin) return [];
64628
64993
  if (scopedLineIds.length > 0) return scopedLineIds;
64629
64994
  if (lineIds && lineIds.length > 0) return lineIds;
64630
64995
  if (isStrictLineScopedRole && hasCanonicalScope) return [];
64631
64996
  return [];
64632
64997
  }, [isSuperAdmin, scopedLineIds, lineIds, isStrictLineScopedRole, hasCanonicalScope]);
64633
- const assignedLineIdSet = React142__default.useMemo(
64998
+ const assignedLineIdSet = React143__default.useMemo(
64634
64999
  () => new Set(resolvedAssignedLineIds),
64635
65000
  [resolvedAssignedLineIds]
64636
65001
  );
64637
- const metricsLineIds = React142__default.useMemo(() => {
65002
+ const metricsLineIds = React143__default.useMemo(() => {
64638
65003
  if (isSuperAdmin) {
64639
65004
  return lineIds ?? [];
64640
65005
  }
64641
65006
  return resolvedAssignedLineIds;
64642
65007
  }, [isSuperAdmin, lineIds, resolvedAssignedLineIds]);
64643
65008
  const assignedLineIdsForLeaderboard = isSuperAdmin ? void 0 : resolvedAssignedLineIds;
64644
- const leaderboardLinesForView = React142__default.useMemo(() => {
65009
+ const leaderboardLinesForView = React143__default.useMemo(() => {
64645
65010
  const targetMode = viewType === "machine" ? "uptime" : "output";
64646
65011
  return leaderboardLines.filter((line) => (line.monitoring_mode ?? "output") === targetMode);
64647
65012
  }, [leaderboardLines, viewType]);
64648
- const linesForView = React142__default.useMemo(() => {
65013
+ const linesForView = React143__default.useMemo(() => {
64649
65014
  const targetMode = viewType === "machine" ? "uptime" : "output";
64650
65015
  return lines.filter((line) => (line.monitoring_mode ?? "output") === targetMode);
64651
65016
  }, [lines, viewType]);
64652
- const relevantLinesForMode = React142__default.useMemo(() => {
65017
+ const relevantLinesForMode = React143__default.useMemo(() => {
64653
65018
  if (activeTab === "leaderboard") {
64654
65019
  return leaderboardLines.length > 0 ? leaderboardLines : lines;
64655
65020
  }
64656
65021
  return lines;
64657
65022
  }, [activeTab, leaderboardLines, lines]);
64658
- const { hasUptime, hasOutput } = React142__default.useMemo(() => {
65023
+ const { hasUptime, hasOutput } = React143__default.useMemo(() => {
64659
65024
  let uptime = false;
64660
65025
  let output = false;
64661
65026
  for (const line of relevantLinesForMode) {
@@ -64680,14 +65045,14 @@ var KPIsOverviewView = ({
64680
65045
  const currentShiftDetails = getCurrentShift(configuredTimezone, shiftConfig);
64681
65046
  const currentShiftDate = currentShiftDetails.date;
64682
65047
  const currentShiftId = currentShiftDetails.shiftId;
64683
- const activeFiltersCount = React142__default.useMemo(() => {
65048
+ const activeFiltersCount = React143__default.useMemo(() => {
64684
65049
  let count = 0;
64685
65050
  if (selectedLeaderboardShiftId !== currentShiftId) {
64686
65051
  count++;
64687
65052
  }
64688
65053
  return count;
64689
65054
  }, [selectedLeaderboardShiftId, currentShiftId]);
64690
- const clearFilters = React142__default.useCallback(() => {
65055
+ const clearFilters = React143__default.useCallback(() => {
64691
65056
  setSelectedLeaderboardShiftId(currentShiftId);
64692
65057
  }, [currentShiftId]);
64693
65058
  useEffect(() => {
@@ -64701,11 +65066,11 @@ var KPIsOverviewView = ({
64701
65066
  document.addEventListener("mousedown", handleClickOutside);
64702
65067
  return () => document.removeEventListener("mousedown", handleClickOutside);
64703
65068
  }, []);
64704
- const shiftEndDate = React142__default.useMemo(
65069
+ const shiftEndDate = React143__default.useMemo(
64705
65070
  () => getShiftEndDate(currentShiftDetails, configuredTimezone),
64706
65071
  [currentShiftDetails, configuredTimezone]
64707
65072
  );
64708
- const leaderboardShiftOptions = React142__default.useMemo(() => {
65073
+ const leaderboardShiftOptions = React143__default.useMemo(() => {
64709
65074
  if (shiftConfig?.shifts && shiftConfig.shifts.length > 0) {
64710
65075
  return shiftConfig.shifts.map((shift) => ({
64711
65076
  id: shift.shiftId,
@@ -64785,15 +65150,15 @@ var KPIsOverviewView = ({
64785
65150
  lineId: factoryViewId,
64786
65151
  userAccessibleLineIds: metricsLineIds
64787
65152
  });
64788
- const defaultKPIs = React142__default.useMemo(() => createDefaultKPIs(), []);
64789
- const kpisByLineId = React142__default.useMemo(() => {
65153
+ const defaultKPIs = React143__default.useMemo(() => createDefaultKPIs(), []);
65154
+ const kpisByLineId = React143__default.useMemo(() => {
64790
65155
  const map = /* @__PURE__ */ new Map();
64791
65156
  lineMetrics.forEach((row) => {
64792
65157
  if (row?.line_id) map.set(row.line_id, buildKPIsFromLineMetricsRow(row));
64793
65158
  });
64794
65159
  return map;
64795
65160
  }, [lineMetrics]);
64796
- const supervisorLineIds = React142__default.useMemo(
65161
+ const supervisorLineIds = React143__default.useMemo(
64797
65162
  () => (leaderboardLines.length > 0 ? leaderboardLines : lines).map((l) => l.id),
64798
65163
  [leaderboardLines, lines]
64799
65164
  );
@@ -65633,39 +65998,6 @@ var KPIsOverviewView = ({
65633
65998
  ] });
65634
65999
  };
65635
66000
  var KPIsOverviewView_default = KPIsOverviewView;
65636
- var toFiniteNumber = (value) => {
65637
- if (typeof value === "number" && Number.isFinite(value)) return value;
65638
- if (typeof value === "string" && value.trim() !== "") {
65639
- const parsed = Number(value);
65640
- return Number.isFinite(parsed) ? parsed : null;
65641
- }
65642
- return null;
65643
- };
65644
- var getCycleRatio = (workspace) => {
65645
- const idealCycleTime = toFiniteNumber(workspace.ideal_cycle_time);
65646
- const avgCycleTime = toFiniteNumber(workspace.avg_cycle_time);
65647
- if (idealCycleTime === null || avgCycleTime === null || idealCycleTime <= 0 || avgCycleTime <= 0) {
65648
- return null;
65649
- }
65650
- return idealCycleTime / avgCycleTime;
65651
- };
65652
- var formatCycleTimeValue = (value) => {
65653
- const numericValue = toFiniteNumber(value);
65654
- if (numericValue === null || numericValue <= 0) return "--";
65655
- return `${numericValue.toFixed(1)}s`;
65656
- };
65657
- var CycleTimeComparison = memo$1(({
65658
- workspace
65659
- }) => {
65660
- const averageValue = formatCycleTimeValue(workspace.avg_cycle_time);
65661
- const standardValue = formatCycleTimeValue(workspace.ideal_cycle_time);
65662
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 tabular-nums", children: [
65663
- /* @__PURE__ */ jsx("span", { className: "font-semibold text-gray-900", children: averageValue }),
65664
- /* @__PURE__ */ jsx("span", { className: "text-gray-400 font-normal", children: "/" }),
65665
- /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-500", children: standardValue })
65666
- ] });
65667
- }, (prevProps, nextProps) => prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.ideal_cycle_time === nextProps.workspace.ideal_cycle_time);
65668
- CycleTimeComparison.displayName = "CycleTimeComparison";
65669
66001
  var IsolatedTimer = memo$1(() => {
65670
66002
  return /* @__PURE__ */ jsx(ISTTimer_default, {});
65671
66003
  });
@@ -65917,7 +66249,7 @@ var LeaderboardDetailView = memo$1(({
65917
66249
  return () => document.removeEventListener("mousedown", handleClickOutside);
65918
66250
  }, []);
65919
66251
  const [isMobile, setIsMobile] = useState(false);
65920
- React142__default.useEffect(() => {
66252
+ React143__default.useEffect(() => {
65921
66253
  const checkMobile = () => setIsMobile(window.innerWidth < 640);
65922
66254
  checkMobile();
65923
66255
  window.addEventListener("resize", checkMobile);
@@ -66207,10 +66539,25 @@ var LeaderboardDetailView = memo$1(({
66207
66539
  setTodayLoading(true);
66208
66540
  setTodayError(null);
66209
66541
  try {
66210
- const entries = await fetchLeaderboardEntries({
66542
+ if (!supabase) {
66543
+ throw new Error("Supabase client not initialized");
66544
+ }
66545
+ if (!entityConfig.companyId) {
66546
+ throw new Error("Company ID is not configured");
66547
+ }
66548
+ const searchParams = new URLSearchParams({
66549
+ company_id: entityConfig.companyId,
66211
66550
  date: todayDate,
66212
- shiftId: todayShiftId
66551
+ shift_id: todayShiftId.toString()
66213
66552
  });
66553
+ if (configuredLineIds.length > 0) {
66554
+ searchParams.set("line_ids", configuredLineIds.join(","));
66555
+ }
66556
+ const metricsData = await fetchBackendJson(
66557
+ supabase,
66558
+ `/api/dashboard/metrics?${searchParams.toString()}`
66559
+ );
66560
+ const entries = metricsData.workspace_metrics || [];
66214
66561
  if (todayRequestKeyRef.current !== requestKey) {
66215
66562
  return;
66216
66563
  }
@@ -66227,7 +66574,15 @@ var LeaderboardDetailView = memo$1(({
66227
66574
  setTodayLoading(false);
66228
66575
  }
66229
66576
  }
66230
- }, [fetchLeaderboardEntries, mapEntriesToWorkspaces, todayDate, todayShiftId, lineKey]);
66577
+ }, [
66578
+ configuredLineIds,
66579
+ entityConfig.companyId,
66580
+ mapEntriesToWorkspaces,
66581
+ supabase,
66582
+ todayDate,
66583
+ todayShiftId,
66584
+ lineKey
66585
+ ]);
66231
66586
  const queueTodayLeaderboardRefresh = useCallback(() => {
66232
66587
  if (leaderboardUpdateQueuedRef.current) return;
66233
66588
  leaderboardUpdateQueuedRef.current = true;
@@ -68313,7 +68668,7 @@ var ShiftsView = ({
68313
68668
  ] })
68314
68669
  ] });
68315
68670
  };
68316
- var AuthenticatedShiftsView = withAuth(React142__default.memo(ShiftsView));
68671
+ var AuthenticatedShiftsView = withAuth(React143__default.memo(ShiftsView));
68317
68672
  var ShiftsView_default = ShiftsView;
68318
68673
 
68319
68674
  // src/views/TargetsView.utils.ts
@@ -70015,7 +70370,7 @@ var TargetsView = ({
70015
70370
  };
70016
70371
  var TargetsViewWithDisplayNames = withAllWorkspaceDisplayNames(TargetsView);
70017
70372
  var TargetsView_default = TargetsViewWithDisplayNames;
70018
- var AuthenticatedTargetsView = withAuth(React142__default.memo(TargetsViewWithDisplayNames));
70373
+ var AuthenticatedTargetsView = withAuth(React143__default.memo(TargetsViewWithDisplayNames));
70019
70374
  function useTimezone(options = {}) {
70020
70375
  const dashboardConfig = useDashboardConfig();
70021
70376
  const workspaceConfig = useWorkspaceConfig();
@@ -73434,7 +73789,7 @@ function BottleneckClipsView({
73434
73789
  ) })
73435
73790
  ] }) });
73436
73791
  }
73437
- var AuthenticatedBottleneckClipsView = withAuth(React142__default.memo(BottleneckClipsView));
73792
+ var AuthenticatedBottleneckClipsView = withAuth(React143__default.memo(BottleneckClipsView));
73438
73793
  var BottleneckClipsView_default = BottleneckClipsView;
73439
73794
 
73440
73795
  // src/lib/services/ticketService.ts
@@ -73464,8 +73819,8 @@ var TicketService = class {
73464
73819
  return response;
73465
73820
  } catch (error) {
73466
73821
  lastError = error instanceof Error ? error : new Error(String(error));
73467
- const isRetryableError = lastError.message.includes("network") || lastError.message.includes("Failed to fetch") || lastError.message.includes("fetch failed") || lastError.message.includes("aborted") || lastError.message.includes("ENOTFOUND") || lastError.message.includes("ECONNREFUSED") || lastError.message.includes("503");
73468
- if (!isRetryableError || attempt === retries) {
73822
+ const isRetryableError2 = lastError.message.includes("network") || lastError.message.includes("Failed to fetch") || lastError.message.includes("fetch failed") || lastError.message.includes("aborted") || lastError.message.includes("ENOTFOUND") || lastError.message.includes("ECONNREFUSED") || lastError.message.includes("503");
73823
+ if (!isRetryableError2 || attempt === retries) {
73469
73824
  throw lastError;
73470
73825
  }
73471
73826
  const delay2 = 1e3 * Math.pow(2, attempt);
@@ -73480,69 +73835,78 @@ var TicketService = class {
73480
73835
  * Uses the user's JWT access token from Supabase session (NOT the anon key)
73481
73836
  */
73482
73837
  async fetchWithAuth(url, options = {}) {
73483
- if (!this.supabaseClient) {
73484
- throw new Error("Supabase client not initialized. Please provide a Supabase client to TicketService.");
73485
- }
73486
- const { data: { session }, error: sessionError } = await this.supabaseClient.auth.getSession();
73487
- if (sessionError) {
73488
- console.error("Session error:", sessionError);
73489
- throw new Error("Failed to get authentication session. Please log in.");
73490
- }
73491
- if (!session) {
73492
- console.error("No session found. User must be logged in.");
73493
- throw new Error("User not authenticated. Please log in.");
73494
- }
73495
- if (!session.access_token) {
73496
- console.error("Session exists but no access_token found");
73497
- throw new Error("Invalid session. Please log in again.");
73498
- }
73499
- const token = session.access_token;
73500
- if (process.env.NODE_ENV === "development") {
73501
- console.log("[TicketService] Using JWT token (first 20 chars):", token.substring(0, 20) + "...");
73502
- console.log("[TicketService] Token is NOT the anon key - it is the user JWT from session.access_token");
73503
- }
73504
- const headers = {
73505
- "Content-Type": "application/json",
73506
- ...options.headers,
73507
- "Authorization": `Bearer ${token}`
73508
- // This is the USER's JWT, not the anon key
73509
- };
73510
- const response = await this.fetchWithRetry(url, {
73511
- ...options,
73512
- headers
73513
- });
73514
- if (response.status === 401) {
73515
- console.error("401 Unauthorized - Token expired or invalid");
73516
- throw new Error("Authentication failed. Token expired or invalid. Please log in again.");
73517
- }
73518
- if (response.status === 403) {
73519
- console.error("403 Forbidden - User does not have permission");
73520
- throw new Error("Access denied. You do not have permission to access this resource.");
73521
- }
73522
- if (response.status === 500) {
73523
- console.error("500 Internal Server Error - Backend error");
73524
- let errorDetail = "Internal server error occurred.";
73525
- try {
73526
- const errorData = await response.text();
73527
- console.error("Backend error details:", errorData);
73528
- errorDetail = errorData || errorDetail;
73529
- } catch (e) {
73838
+ try {
73839
+ if (!this.supabaseClient) {
73840
+ throw new Error("Supabase client not initialized. Please provide a Supabase client to TicketService.");
73530
73841
  }
73531
- throw new Error(`Backend error: ${errorDetail}`);
73532
- }
73533
- if (!response.ok) {
73534
- console.error(`HTTP ${response.status} - ${response.statusText}`);
73535
- let errorDetail = response.statusText;
73536
- try {
73537
- const errorData = await response.json();
73538
- if (errorData.detail) {
73539
- errorDetail = errorData.detail;
73842
+ const { data: { session }, error: sessionError } = await this.supabaseClient.auth.getSession();
73843
+ if (sessionError) {
73844
+ console.error("Session error:", sessionError);
73845
+ throw new Error("Failed to get authentication session. Please log in.");
73846
+ }
73847
+ if (!session) {
73848
+ console.error("No session found. User must be logged in.");
73849
+ throw new Error("User not authenticated. Please log in.");
73850
+ }
73851
+ if (!session.access_token) {
73852
+ console.error("Session exists but no access_token found");
73853
+ throw new Error("Invalid session. Please log in again.");
73854
+ }
73855
+ const token = session.access_token;
73856
+ if (process.env.NODE_ENV === "development") {
73857
+ console.log("[TicketService] Using JWT token (first 20 chars):", token.substring(0, 20) + "...");
73858
+ console.log("[TicketService] Token is NOT the anon key - it is the user JWT from session.access_token");
73859
+ }
73860
+ const headers = {
73861
+ "Content-Type": "application/json",
73862
+ ...options.headers,
73863
+ "Authorization": `Bearer ${token}`
73864
+ };
73865
+ const response = await this.fetchWithRetry(url, {
73866
+ ...options,
73867
+ headers
73868
+ });
73869
+ if (response.status === 401) {
73870
+ console.error("401 Unauthorized - Token expired or invalid");
73871
+ throw new Error("Authentication failed. Token expired or invalid. Please log in again.");
73872
+ }
73873
+ if (response.status === 403) {
73874
+ console.error("403 Forbidden - User does not have permission");
73875
+ throw new Error("Access denied. You do not have permission to access this resource.");
73876
+ }
73877
+ if (response.status === 500) {
73878
+ console.error("500 Internal Server Error - Backend error");
73879
+ let errorDetail = "Internal server error occurred.";
73880
+ try {
73881
+ const errorData = await response.text();
73882
+ console.error("Backend error details:", errorData);
73883
+ errorDetail = errorData || errorDetail;
73884
+ } catch (e) {
73540
73885
  }
73541
- } catch (e) {
73886
+ throw new Error(`Backend error: ${errorDetail}`);
73887
+ }
73888
+ if (!response.ok) {
73889
+ console.error(`HTTP ${response.status} - ${response.statusText}`);
73890
+ let errorDetail = response.statusText;
73891
+ try {
73892
+ const errorData = await response.json();
73893
+ if (errorData.detail) {
73894
+ errorDetail = errorData.detail;
73895
+ }
73896
+ } catch (e) {
73897
+ }
73898
+ throw new Error(`Request failed (${response.status}): ${errorDetail}`);
73542
73899
  }
73543
- throw new Error(`Request failed (${response.status}): ${errorDetail}`);
73900
+ return response;
73901
+ } catch (error) {
73902
+ captureHandledFrontendException(error, {
73903
+ surface: "ticket_service",
73904
+ url,
73905
+ method: options.method || "GET",
73906
+ pathname: typeof window !== "undefined" ? window.location.pathname : "unknown"
73907
+ });
73908
+ throw error;
73544
73909
  }
73545
- return response;
73546
73910
  }
73547
73911
  /**
73548
73912
  * Get tickets with filters and pagination
@@ -74265,7 +74629,7 @@ Please ensure:
74265
74629
  )
74266
74630
  ] });
74267
74631
  }
74268
- var AuthenticatedTicketsView = withAuth(React142__default.memo(TicketsView));
74632
+ var AuthenticatedTicketsView = withAuth(React143__default.memo(TicketsView));
74269
74633
  var TicketsView_default = TicketsView;
74270
74634
 
74271
74635
  // src/lib/utils/improvementDisplay.ts
@@ -75236,7 +75600,7 @@ var ImprovementCenterView = () => {
75236
75600
  setSelectedMemberId("all");
75237
75601
  }
75238
75602
  }, [memberOptions, selectedMemberId]);
75239
- const getRecommendationDisplayMetadata = React142__default.useCallback((rec) => {
75603
+ const getRecommendationDisplayMetadata = React143__default.useCallback((rec) => {
75240
75604
  const supervisors = rec.line_id ? supervisorsByLineId.get(rec.line_id) || [] : [];
75241
75605
  return getImprovementDisplayMetadata({
75242
75606
  location: rec.location,
@@ -75710,7 +76074,7 @@ var ThreadSidebar = ({
75710
76074
  ] }) })
75711
76075
  ] });
75712
76076
  };
75713
- var ProfilePicture = React142__default.memo(({
76077
+ var ProfilePicture = React143__default.memo(({
75714
76078
  alt = "Axel",
75715
76079
  className = "",
75716
76080
  size = "md",
@@ -78235,7 +78599,7 @@ var OverviewImprovementsSkeleton = () => /* @__PURE__ */ jsx("div", { className:
78235
78599
  ] }),
78236
78600
  /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end flex-shrink-0 ml-4", children: /* @__PURE__ */ jsx(SectionPulse, { className: "h-6 w-20 rounded-full" }) })
78237
78601
  ] }, index)) });
78238
- var OperationsOverviewHeader = React142__default.memo(({
78602
+ var OperationsOverviewHeader = React143__default.memo(({
78239
78603
  dateRange,
78240
78604
  displayDateRange,
78241
78605
  trendMode,
@@ -78255,65 +78619,65 @@ var OperationsOverviewHeader = React142__default.memo(({
78255
78619
  bumpRenderCounter();
78256
78620
  const subtitleRange = displayDateRange || dateRange;
78257
78621
  const showLiveShiftMeta = isLiveScope && trendMode !== "all";
78258
- const liveShiftLabel = React142__default.useMemo(
78622
+ const liveShiftLabel = React143__default.useMemo(
78259
78623
  () => normalizeShiftLabel(liveShiftName, trendMode),
78260
78624
  [liveShiftName, trendMode]
78261
78625
  );
78262
- const liveShiftIcon = React142__default.useMemo(
78626
+ const liveShiftIcon = React143__default.useMemo(
78263
78627
  () => getShiftIcon(liveShiftName, trendMode),
78264
78628
  [liveShiftName, trendMode]
78265
78629
  );
78266
- const [isFilterOpen, setIsFilterOpen] = React142__default.useState(false);
78267
- const [isLinesDropdownOpen, setIsLinesDropdownOpen] = React142__default.useState(false);
78268
- const filterRef = React142__default.useRef(null);
78269
- const filterButtonRef = React142__default.useRef(null);
78270
- const mobileFilterButtonRef = React142__default.useRef(null);
78271
- const linesDropdownRef = React142__default.useRef(null);
78272
- const mobileSubtitle = React142__default.useMemo(() => {
78630
+ const [isFilterOpen, setIsFilterOpen] = React143__default.useState(false);
78631
+ const [isLinesDropdownOpen, setIsLinesDropdownOpen] = React143__default.useState(false);
78632
+ const filterRef = React143__default.useRef(null);
78633
+ const filterButtonRef = React143__default.useRef(null);
78634
+ const mobileFilterButtonRef = React143__default.useRef(null);
78635
+ const linesDropdownRef = React143__default.useRef(null);
78636
+ const mobileSubtitle = React143__default.useMemo(() => {
78273
78637
  if (subtitleRange.startKey === subtitleRange.endKey) {
78274
78638
  return format(parseDateKeyToDate(subtitleRange.startKey), "do MMM, yyyy");
78275
78639
  }
78276
78640
  return `${format(parseDateKeyToDate(subtitleRange.startKey), "do MMM")} - ${format(parseDateKeyToDate(subtitleRange.endKey), "do MMM, yyyy")}`;
78277
78641
  }, [subtitleRange.endKey, subtitleRange.startKey]);
78278
- const desktopSubtitle = React142__default.useMemo(() => {
78642
+ const desktopSubtitle = React143__default.useMemo(() => {
78279
78643
  if (subtitleRange.startKey === subtitleRange.endKey) {
78280
78644
  return format(parseDateKeyToDate(subtitleRange.startKey), "do MMMM, yyyy");
78281
78645
  }
78282
78646
  return `${format(parseDateKeyToDate(subtitleRange.startKey), "do MMMM, yyyy")} - ${format(parseDateKeyToDate(subtitleRange.endKey), "do MMMM, yyyy")}`;
78283
78647
  }, [subtitleRange.endKey, subtitleRange.startKey]);
78284
- const availableLineIds = React142__default.useMemo(
78648
+ const availableLineIds = React143__default.useMemo(
78285
78649
  () => lineOptions.map((line) => line.id),
78286
78650
  [lineOptions]
78287
78651
  );
78288
- const selectedLineIdSet = React142__default.useMemo(
78652
+ const selectedLineIdSet = React143__default.useMemo(
78289
78653
  () => new Set(selectedLineIds),
78290
78654
  [selectedLineIds]
78291
78655
  );
78292
- const isAllLinesSelected = React142__default.useMemo(() => {
78656
+ const isAllLinesSelected = React143__default.useMemo(() => {
78293
78657
  if (availableLineIds.length === 0) return true;
78294
78658
  return availableLineIds.every((lineId) => selectedLineIdSet.has(lineId));
78295
78659
  }, [availableLineIds, selectedLineIdSet]);
78296
- const activeFilterCount = React142__default.useMemo(() => {
78660
+ const activeFilterCount = React143__default.useMemo(() => {
78297
78661
  let count = 0;
78298
78662
  if (trendMode !== "all") count += 1;
78299
78663
  if (selectedSupervisorId !== "all") count += 1;
78300
78664
  if (!isAllLinesSelected) count += 1;
78301
78665
  return count;
78302
78666
  }, [isAllLinesSelected, selectedSupervisorId, trendMode]);
78303
- const handleFilterToggle = React142__default.useCallback(() => {
78667
+ const handleFilterToggle = React143__default.useCallback(() => {
78304
78668
  trackCoreEvent("Operations Overview Filter Toggled", {
78305
78669
  action: !isFilterOpen ? "open" : "close"
78306
78670
  });
78307
78671
  setIsFilterOpen((previous) => !previous);
78308
78672
  }, [isFilterOpen]);
78309
- const handleTrendModeChange = React142__default.useCallback((event) => {
78673
+ const handleTrendModeChange = React143__default.useCallback((event) => {
78310
78674
  const nextMode = event.target.value;
78311
78675
  trackCoreEvent("Operations Overview Shift Filter Changed", {
78312
78676
  shift_mode: nextMode
78313
78677
  });
78314
78678
  onTrendModeChange(nextMode);
78315
78679
  }, [onTrendModeChange]);
78316
- const handleAllLinesToggle = React142__default.useCallback(() => {
78680
+ const handleAllLinesToggle = React143__default.useCallback(() => {
78317
78681
  trackCoreEvent("Operations Overview Line Filter Changed", {
78318
78682
  selected_line_ids: availableLineIds,
78319
78683
  selected_line_count: availableLineIds.length,
@@ -78321,7 +78685,7 @@ var OperationsOverviewHeader = React142__default.memo(({
78321
78685
  });
78322
78686
  onSelectedLineIdsChange(availableLineIds);
78323
78687
  }, [availableLineIds, onSelectedLineIdsChange]);
78324
- const handleSupervisorChange = React142__default.useCallback((event) => {
78688
+ const handleSupervisorChange = React143__default.useCallback((event) => {
78325
78689
  const supervisorId = event.target.value;
78326
78690
  const selectedSupervisor = supervisorOptions.find((option) => option.id === supervisorId);
78327
78691
  trackCoreEvent("Operations Overview Supervisor Filter Changed", {
@@ -78332,7 +78696,7 @@ var OperationsOverviewHeader = React142__default.memo(({
78332
78696
  });
78333
78697
  onSelectedSupervisorIdChange(supervisorId);
78334
78698
  }, [availableLineIds, onSelectedSupervisorIdChange, supervisorOptions]);
78335
- const handleLineToggle = React142__default.useCallback((lineId) => {
78699
+ const handleLineToggle = React143__default.useCallback((lineId) => {
78336
78700
  const current = new Set(selectedLineIds);
78337
78701
  if (current.has(lineId)) {
78338
78702
  if (current.size <= 1) return;
@@ -78348,13 +78712,13 @@ var OperationsOverviewHeader = React142__default.memo(({
78348
78712
  });
78349
78713
  onSelectedLineIdsChange(next);
78350
78714
  }, [availableLineIds, onSelectedLineIdsChange, selectedLineIds]);
78351
- const handleClearAllFilters = React142__default.useCallback(() => {
78715
+ const handleClearAllFilters = React143__default.useCallback(() => {
78352
78716
  onTrendModeChange("all");
78353
78717
  onSelectedSupervisorIdChange("all");
78354
78718
  onSelectedLineIdsChange(availableLineIds);
78355
78719
  setIsFilterOpen(false);
78356
78720
  }, [availableLineIds, onSelectedLineIdsChange, onSelectedSupervisorIdChange, onTrendModeChange]);
78357
- React142__default.useEffect(() => {
78721
+ React143__default.useEffect(() => {
78358
78722
  const handleClickOutside = (event) => {
78359
78723
  const target = event.target;
78360
78724
  if (filterRef.current && !filterRef.current.contains(target) && filterButtonRef.current && !filterButtonRef.current.contains(target) && mobileFilterButtonRef.current && !mobileFilterButtonRef.current.contains(target)) {
@@ -78593,12 +78957,12 @@ var OperationsOverviewHeader = React142__default.memo(({
78593
78957
  ] }) });
78594
78958
  });
78595
78959
  OperationsOverviewHeader.displayName = "OperationsOverviewHeader";
78596
- var OverviewSummaryCards = React142__default.memo(({ store }) => {
78960
+ var OverviewSummaryCards = React143__default.memo(({ store }) => {
78597
78961
  bumpRenderCounter();
78598
78962
  const scope = useOperationsOverviewScope(store);
78599
78963
  const snapshot = useOperationsOverviewSnapshot(store);
78600
78964
  const showSnapshotSkeleton = snapshot.loading && !snapshot.hasLoadedOnce;
78601
- const comparisonLabel = React142__default.useMemo(() => {
78965
+ const comparisonLabel = React143__default.useMemo(() => {
78602
78966
  return formatComparisonWindow({
78603
78967
  currentDayCount: scope.current_range?.day_count ?? null,
78604
78968
  previousDayCount: scope.previous_range?.day_count ?? null,
@@ -78611,27 +78975,27 @@ var OverviewSummaryCards = React142__default.memo(({ store }) => {
78611
78975
  scope.previous_range?.day_count,
78612
78976
  scope.shift_mode
78613
78977
  ]);
78614
- const [isIdleContributorsOpen, setIsIdleContributorsOpen] = React142__default.useState(false);
78615
- const [isIdleContributorsPinned, setIsIdleContributorsPinned] = React142__default.useState(false);
78616
- const idleContributorsRef = React142__default.useRef(null);
78617
- const plantEfficiencyBadge = React142__default.useMemo(() => {
78978
+ const [isIdleContributorsOpen, setIsIdleContributorsOpen] = React143__default.useState(false);
78979
+ const [isIdleContributorsPinned, setIsIdleContributorsPinned] = React143__default.useState(false);
78980
+ const idleContributorsRef = React143__default.useRef(null);
78981
+ const plantEfficiencyBadge = React143__default.useMemo(() => {
78618
78982
  return buildDeltaBadge(snapshot.data.summary.plant_efficiency?.delta_pp, {
78619
78983
  positiveIsGood: true,
78620
78984
  formatter: (value) => `${value >= 0 ? "+" : ""}${roundOne(value)}%`,
78621
78985
  comparisonLabel
78622
78986
  });
78623
78987
  }, [comparisonLabel, snapshot.data.summary.plant_efficiency?.delta_pp]);
78624
- const idleBadge = React142__default.useMemo(() => {
78988
+ const idleBadge = React143__default.useMemo(() => {
78625
78989
  return buildDeltaBadge(snapshot.data.summary.avg_idle_per_workstation?.delta_seconds, {
78626
78990
  positiveIsGood: false,
78627
78991
  formatter: (value) => formatSignedIdleDuration(value),
78628
78992
  comparisonLabel
78629
78993
  });
78630
78994
  }, [comparisonLabel, snapshot.data.summary.avg_idle_per_workstation?.delta_seconds]);
78631
- const canInspectIdleContributors = React142__default.useMemo(() => {
78995
+ const canInspectIdleContributors = React143__default.useMemo(() => {
78632
78996
  return !showSnapshotSkeleton && snapshot.data.summary.avg_idle_per_workstation?.current_seconds !== null && snapshot.data.summary.avg_idle_per_workstation?.current_seconds !== void 0;
78633
78997
  }, [showSnapshotSkeleton, snapshot.data.summary.avg_idle_per_workstation?.current_seconds]);
78634
- const idleTopContributors = React142__default.useMemo(() => {
78998
+ const idleTopContributors = React143__default.useMemo(() => {
78635
78999
  return (snapshot.data.summary.avg_idle_per_workstation?.top_contributors || []).map((item) => ({
78636
79000
  workspaceId: item.workspace_id || "",
78637
79001
  workspaceName: item.workspace_name?.trim() || item.workspace_id || "Unknown",
@@ -78639,14 +79003,14 @@ var OverviewSummaryCards = React142__default.memo(({ store }) => {
78639
79003
  avgIdleSeconds: toNumber3(item.avg_idle_seconds)
78640
79004
  })).slice(0, 5);
78641
79005
  }, [snapshot.data.summary.avg_idle_per_workstation?.top_contributors]);
78642
- const showIdleContributorLineNames = React142__default.useMemo(() => {
79006
+ const showIdleContributorLineNames = React143__default.useMemo(() => {
78643
79007
  return (scope.line_count ?? 0) > 1;
78644
79008
  }, [scope.line_count]);
78645
- const closeIdleContributors = React142__default.useCallback(() => {
79009
+ const closeIdleContributors = React143__default.useCallback(() => {
78646
79010
  setIsIdleContributorsOpen(false);
78647
79011
  setIsIdleContributorsPinned(false);
78648
79012
  }, []);
78649
- const handleIdleContributorsToggle = React142__default.useCallback(() => {
79013
+ const handleIdleContributorsToggle = React143__default.useCallback(() => {
78650
79014
  if (!canInspectIdleContributors) return;
78651
79015
  setIsIdleContributorsPinned((previous) => {
78652
79016
  const next = !previous;
@@ -78654,7 +79018,7 @@ var OverviewSummaryCards = React142__default.memo(({ store }) => {
78654
79018
  return next;
78655
79019
  });
78656
79020
  }, [canInspectIdleContributors]);
78657
- const handleIdleContributorsKeyDown = React142__default.useCallback((event) => {
79021
+ const handleIdleContributorsKeyDown = React143__default.useCallback((event) => {
78658
79022
  if (!canInspectIdleContributors) return;
78659
79023
  if (event.key === "Enter" || event.key === " ") {
78660
79024
  event.preventDefault();
@@ -78666,11 +79030,11 @@ var OverviewSummaryCards = React142__default.memo(({ store }) => {
78666
79030
  closeIdleContributors();
78667
79031
  }
78668
79032
  }, [canInspectIdleContributors, closeIdleContributors, handleIdleContributorsToggle]);
78669
- React142__default.useEffect(() => {
79033
+ React143__default.useEffect(() => {
78670
79034
  setIsIdleContributorsOpen(false);
78671
79035
  setIsIdleContributorsPinned(false);
78672
79036
  }, [scope.comparison_strategy, scope.current_range?.start_date, scope.current_range?.end_date, scope.line_count, scope.shift_mode]);
78673
- React142__default.useEffect(() => {
79037
+ React143__default.useEffect(() => {
78674
79038
  if (!isIdleContributorsOpen) return void 0;
78675
79039
  const handleClickOutside = (event) => {
78676
79040
  if (!isIdleContributorsPinned) return;
@@ -78808,7 +79172,7 @@ var OverviewSummaryCards = React142__default.memo(({ store }) => {
78808
79172
  ] });
78809
79173
  });
78810
79174
  OverviewSummaryCards.displayName = "OverviewSummaryCards";
78811
- var PoorestPerformersCard = React142__default.memo(({
79175
+ var PoorestPerformersCard = React143__default.memo(({
78812
79176
  store,
78813
79177
  supervisorsByLineId,
78814
79178
  onViewAll,
@@ -78817,9 +79181,9 @@ var PoorestPerformersCard = React142__default.memo(({
78817
79181
  bumpRenderCounter();
78818
79182
  const scope = useOperationsOverviewScope(store);
78819
79183
  const snapshot = useOperationsOverviewSnapshot(store);
78820
- const [poorestLineMode, setPoorestLineMode] = React142__default.useState("output");
79184
+ const [poorestLineMode, setPoorestLineMode] = React143__default.useState("output");
78821
79185
  const availableLineModes = scope.available_line_modes;
78822
- React142__default.useEffect(() => {
79186
+ React143__default.useEffect(() => {
78823
79187
  const hasOutput = !!availableLineModes?.has_output;
78824
79188
  const hasUptime = !!availableLineModes?.has_uptime;
78825
79189
  if (hasOutput && !hasUptime && poorestLineMode !== "output") {
@@ -78828,7 +79192,7 @@ var PoorestPerformersCard = React142__default.memo(({
78828
79192
  setPoorestLineMode("uptime");
78829
79193
  }
78830
79194
  }, [availableLineModes?.has_output, availableLineModes?.has_uptime, poorestLineMode]);
78831
- const comparisonLabel = React142__default.useMemo(() => {
79195
+ const comparisonLabel = React143__default.useMemo(() => {
78832
79196
  return formatComparisonWindow({
78833
79197
  currentDayCount: scope.current_range?.day_count ?? null,
78834
79198
  previousDayCount: scope.previous_range?.day_count ?? null,
@@ -78842,7 +79206,7 @@ var PoorestPerformersCard = React142__default.memo(({
78842
79206
  scope.shift_mode
78843
79207
  ]);
78844
79208
  const showSnapshotSkeleton = snapshot.loading && !snapshot.hasLoadedOnce;
78845
- const mergedPoorestLines = React142__default.useMemo(() => {
79209
+ const mergedPoorestLines = React143__default.useMemo(() => {
78846
79210
  const rows = snapshot.data.poorest_lines?.[poorestLineMode] || [];
78847
79211
  return rows.slice(0, 3).map((line) => {
78848
79212
  const lineId = line.line_id || "";
@@ -78861,7 +79225,7 @@ var PoorestPerformersCard = React142__default.memo(({
78861
79225
  }, [poorestLineMode, snapshot.data.poorest_lines, supervisorsByLineId]);
78862
79226
  const showPoorestModeToggle = !!availableLineModes?.has_output && !!availableLineModes?.has_uptime;
78863
79227
  const poorestMetricLabel = poorestLineMode === "uptime" ? "Uptime" : "Efficiency";
78864
- const handlePoorestLineModeChange = React142__default.useCallback((mode) => {
79228
+ const handlePoorestLineModeChange = React143__default.useCallback((mode) => {
78865
79229
  trackCoreEvent("Operations Overview Poorest Line Mode Changed", { mode });
78866
79230
  setPoorestLineMode(mode);
78867
79231
  }, []);
@@ -78947,14 +79311,14 @@ var PoorestPerformersCard = React142__default.memo(({
78947
79311
  ] });
78948
79312
  });
78949
79313
  PoorestPerformersCard.displayName = "PoorestPerformersCard";
78950
- var IdleBreakdownCard = React142__default.memo(({
79314
+ var IdleBreakdownCard = React143__default.memo(({
78951
79315
  store,
78952
79316
  scopedLineCount
78953
79317
  }) => {
78954
79318
  bumpRenderCounter();
78955
79319
  const idle = useOperationsOverviewIdle(store);
78956
79320
  const showInitialSkeleton = idle.loading && idle.lastUpdated === null;
78957
- const idleBreakdown = React142__default.useMemo(() => {
79321
+ const idleBreakdown = React143__default.useMemo(() => {
78958
79322
  return idle.data.map((item) => ({
78959
79323
  name: item.display_name?.trim() || item.reason?.trim() || "Unknown",
78960
79324
  reasonKey: item.reason_key?.trim() || item.reason?.trim() || "unknown",
@@ -78973,7 +79337,7 @@ var IdleBreakdownCard = React142__default.memo(({
78973
79337
  }))
78974
79338
  })).filter((item) => item.value > 0);
78975
79339
  }, [idle.data]);
78976
- const showIdleModuleNotEnabledState = React142__default.useMemo(() => {
79340
+ const showIdleModuleNotEnabledState = React143__default.useMemo(() => {
78977
79341
  const enabledLineCount = idle.scope.idle_time_vlm_enabled_line_count;
78978
79342
  return !showInitialSkeleton && scopedLineCount > 0 && typeof enabledLineCount === "number" && enabledLineCount === 0;
78979
79343
  }, [idle.scope.idle_time_vlm_enabled_line_count, scopedLineCount, showInitialSkeleton]);
@@ -78994,7 +79358,7 @@ var IdleBreakdownCard = React142__default.memo(({
78994
79358
  ] });
78995
79359
  });
78996
79360
  IdleBreakdownCard.displayName = "IdleBreakdownCard";
78997
- var EfficiencyTrendCard = React142__default.memo(({
79361
+ var EfficiencyTrendCard = React143__default.memo(({
78998
79362
  store,
78999
79363
  dateRange,
79000
79364
  appTimezone,
@@ -79002,14 +79366,14 @@ var EfficiencyTrendCard = React142__default.memo(({
79002
79366
  }) => {
79003
79367
  bumpRenderCounter();
79004
79368
  const trend = useOperationsOverviewTrend(store);
79005
- const currentWeekRange = React142__default.useMemo(
79369
+ const currentWeekRange = React143__default.useMemo(
79006
79370
  () => getCurrentWeekToDateRange(appTimezone),
79007
79371
  [appTimezone]
79008
79372
  );
79009
79373
  const isCurrentWeekToDateRange = dateRange.startKey === currentWeekRange.startKey && dateRange.endKey === currentWeekRange.endKey;
79010
79374
  const showInitialSkeleton = trend.loading && trend.lastUpdated === null;
79011
79375
  const isHourlyTrend = trend.data.granularity === "hour";
79012
- const trendData = React142__default.useMemo(() => {
79376
+ const trendData = React143__default.useMemo(() => {
79013
79377
  if (isHourlyTrend) {
79014
79378
  return (trend.data.points || []).map((point, index) => ({
79015
79379
  name: (() => {
@@ -79081,13 +79445,13 @@ var EfficiencyTrendCard = React142__default.memo(({
79081
79445
  };
79082
79446
  });
79083
79447
  }, [currentWeekRange.startKey, hourlyLabelStartTime, isCurrentWeekToDateRange, isHourlyTrend, trend.data.points]);
79084
- const trendTooltipLabelFormatter = React142__default.useCallback((label, payload) => {
79448
+ const trendTooltipLabelFormatter = React143__default.useCallback((label, payload) => {
79085
79449
  if (isHourlyTrend) return label;
79086
79450
  const dayOfWeek = payload?.[0]?.payload?.dayOfWeek;
79087
79451
  if (!dayOfWeek || typeof label !== "string") return label;
79088
79452
  return `${label} (${dayOfWeek})`;
79089
79453
  }, [isHourlyTrend]);
79090
- const trendXAxisTickFormatter = React142__default.useCallback((value, index) => {
79454
+ const trendXAxisTickFormatter = React143__default.useCallback((value, index) => {
79091
79455
  if (!isHourlyTrend) {
79092
79456
  return typeof value === "string" ? value : String(value ?? "");
79093
79457
  }
@@ -79114,7 +79478,7 @@ var EfficiencyTrendCard = React142__default.memo(({
79114
79478
  ] });
79115
79479
  });
79116
79480
  EfficiencyTrendCard.displayName = "EfficiencyTrendCard";
79117
- var TopImprovementsCard = React142__default.memo(({
79481
+ var TopImprovementsCard = React143__default.memo(({
79118
79482
  store,
79119
79483
  supervisorsByLineId,
79120
79484
  onViewAll,
@@ -79123,7 +79487,7 @@ var TopImprovementsCard = React142__default.memo(({
79123
79487
  bumpRenderCounter();
79124
79488
  const improvements = useOperationsOverviewImprovements(store);
79125
79489
  const showInitialSkeleton = improvements.loading && improvements.lastUpdated === null;
79126
- const displayImprovements = React142__default.useMemo(() => {
79490
+ const displayImprovements = React143__default.useMemo(() => {
79127
79491
  return improvements.data.map((item) => {
79128
79492
  const supervisors = item.lineId ? supervisorsByLineId.get(item.lineId) || [] : [];
79129
79493
  return {
@@ -79196,7 +79560,7 @@ var debugRefreshLog = (message, payload) => {
79196
79560
  }
79197
79561
  console.log(`[OperationsOverviewRefresh] ${message}`);
79198
79562
  };
79199
- var isAbortError = (error) => {
79563
+ var isAbortError2 = (error) => {
79200
79564
  return error instanceof DOMException && error.name === "AbortError";
79201
79565
  };
79202
79566
  var toNumber4 = (value) => {
@@ -79251,33 +79615,33 @@ var useOperationsOverviewRefresh = ({
79251
79615
  isLiveScope,
79252
79616
  enabled = true
79253
79617
  }) => {
79254
- const lineIdsKey = React142__default.useMemo(() => lineIds.join(","), [lineIds]);
79255
- const scopeSignature = React142__default.useMemo(
79618
+ const lineIdsKey = React143__default.useMemo(() => lineIds.join(","), [lineIds]);
79619
+ const scopeSignature = React143__default.useMemo(
79256
79620
  () => [companyId || "", startKey, endKey, trendMode, comparisonStrategy || "", lineIdsKey].join("::"),
79257
79621
  [companyId, comparisonStrategy, endKey, lineIdsKey, startKey, trendMode]
79258
79622
  );
79259
- const controllersRef = React142__default.useRef({});
79260
- const requestIdsRef = React142__default.useRef({
79623
+ const controllersRef = React143__default.useRef({});
79624
+ const requestIdsRef = React143__default.useRef({
79261
79625
  snapshot: 0,
79262
79626
  trend: 0,
79263
79627
  idle: 0,
79264
79628
  improvements: 0
79265
79629
  });
79266
- const intervalRef = React142__default.useRef(null);
79267
- const isPageActiveRef = React142__default.useRef(true);
79268
- const lastResumeRefreshAtRef = React142__default.useRef(0);
79269
- const abortAll = React142__default.useCallback(() => {
79630
+ const intervalRef = React143__default.useRef(null);
79631
+ const isPageActiveRef = React143__default.useRef(true);
79632
+ const lastResumeRefreshAtRef = React143__default.useRef(0);
79633
+ const abortAll = React143__default.useCallback(() => {
79270
79634
  Object.values(controllersRef.current).forEach((controller) => {
79271
79635
  controller?.abort();
79272
79636
  });
79273
79637
  controllersRef.current = {};
79274
79638
  }, []);
79275
- React142__default.useEffect(() => {
79639
+ React143__default.useEffect(() => {
79276
79640
  return () => {
79277
79641
  abortAll();
79278
79642
  };
79279
79643
  }, [abortAll]);
79280
- const getIsPageActive = React142__default.useCallback(() => {
79644
+ const getIsPageActive = React143__default.useCallback(() => {
79281
79645
  if (typeof document === "undefined") {
79282
79646
  return true;
79283
79647
  }
@@ -79285,7 +79649,7 @@ var useOperationsOverviewRefresh = ({
79285
79649
  const hasFocus = typeof document.hasFocus === "function" ? document.hasFocus() : true;
79286
79650
  return isVisible && hasFocus;
79287
79651
  }, []);
79288
- const stopPolling = React142__default.useCallback((reason) => {
79652
+ const stopPolling = React143__default.useCallback((reason) => {
79289
79653
  if (intervalRef.current === null) {
79290
79654
  return;
79291
79655
  }
@@ -79293,7 +79657,7 @@ var useOperationsOverviewRefresh = ({
79293
79657
  intervalRef.current = null;
79294
79658
  debugRefreshLog("poll stopped", { reason });
79295
79659
  }, []);
79296
- const runRefresh = React142__default.useCallback(
79660
+ const runRefresh = React143__default.useCallback(
79297
79661
  async (section, begin, onSuccess, onError, request, reason) => {
79298
79662
  if (!enabled || !supabase || !companyId || lineIds.length === 0) return;
79299
79663
  const requestId = requestIdsRef.current[section] + 1;
@@ -79309,7 +79673,7 @@ var useOperationsOverviewRefresh = ({
79309
79673
  }
79310
79674
  onSuccess(response, Date.now(), reason === "live_refresh" ? "transition" : "default");
79311
79675
  } catch (error) {
79312
- if (controller.signal.aborted || requestIdsRef.current[section] !== requestId || isAbortError(error)) {
79676
+ if (controller.signal.aborted || requestIdsRef.current[section] !== requestId || isAbortError2(error)) {
79313
79677
  return;
79314
79678
  }
79315
79679
  onError(error instanceof Error ? error.message : `Failed to refresh ${section}`);
@@ -79317,7 +79681,7 @@ var useOperationsOverviewRefresh = ({
79317
79681
  },
79318
79682
  [companyId, enabled, lineIds.length, supabase]
79319
79683
  );
79320
- const refreshSnapshot = React142__default.useCallback(
79684
+ const refreshSnapshot = React143__default.useCallback(
79321
79685
  async (reason) => {
79322
79686
  await runRefresh(
79323
79687
  "snapshot",
@@ -79349,7 +79713,7 @@ var useOperationsOverviewRefresh = ({
79349
79713
  },
79350
79714
  [companyId, comparisonStrategy, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
79351
79715
  );
79352
- const refreshTrend = React142__default.useCallback(
79716
+ const refreshTrend = React143__default.useCallback(
79353
79717
  async (reason) => {
79354
79718
  await runRefresh(
79355
79719
  "trend",
@@ -79378,7 +79742,7 @@ var useOperationsOverviewRefresh = ({
79378
79742
  },
79379
79743
  [companyId, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
79380
79744
  );
79381
- const refreshIdle = React142__default.useCallback(
79745
+ const refreshIdle = React143__default.useCallback(
79382
79746
  async (reason) => {
79383
79747
  await runRefresh(
79384
79748
  "idle",
@@ -79407,7 +79771,7 @@ var useOperationsOverviewRefresh = ({
79407
79771
  },
79408
79772
  [companyId, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
79409
79773
  );
79410
- const refreshImprovements = React142__default.useCallback(
79774
+ const refreshImprovements = React143__default.useCallback(
79411
79775
  async (reason) => {
79412
79776
  await runRefresh(
79413
79777
  "improvements",
@@ -79437,7 +79801,7 @@ var useOperationsOverviewRefresh = ({
79437
79801
  },
79438
79802
  [companyId, lineIds, lineIdsKey, runRefresh, scopeSignature, store, supabase]
79439
79803
  );
79440
- const refreshAll = React142__default.useCallback(
79804
+ const refreshAll = React143__default.useCallback(
79441
79805
  async (reason) => {
79442
79806
  await Promise.allSettled([
79443
79807
  refreshSnapshot(reason),
@@ -79448,7 +79812,7 @@ var useOperationsOverviewRefresh = ({
79448
79812
  },
79449
79813
  [refreshIdle, refreshImprovements, refreshSnapshot, refreshTrend]
79450
79814
  );
79451
- const startPolling = React142__default.useCallback((reason) => {
79815
+ const startPolling = React143__default.useCallback((reason) => {
79452
79816
  if (!isLiveScope || !supabase || !companyId || lineIds.length === 0) {
79453
79817
  return;
79454
79818
  }
@@ -79469,7 +79833,7 @@ var useOperationsOverviewRefresh = ({
79469
79833
  }, LIVE_REFRESH_INTERVAL_MS);
79470
79834
  debugRefreshLog("poll started", { reason, intervalMs: LIVE_REFRESH_INTERVAL_MS });
79471
79835
  }, [companyId, isLiveScope, lineIds.length, refreshAll, stopPolling, supabase]);
79472
- const refreshFromResume = React142__default.useCallback((reason) => {
79836
+ const refreshFromResume = React143__default.useCallback((reason) => {
79473
79837
  const now4 = Date.now();
79474
79838
  if (now4 - lastResumeRefreshAtRef.current < 1e3) {
79475
79839
  debugRefreshLog("resume refresh suppressed", { reason });
@@ -79484,7 +79848,7 @@ var useOperationsOverviewRefresh = ({
79484
79848
  }
79485
79849
  });
79486
79850
  }, [refreshAll, startPolling, stopPolling]);
79487
- React142__default.useEffect(() => {
79851
+ React143__default.useEffect(() => {
79488
79852
  if (!enabled) {
79489
79853
  stopPolling("disabled");
79490
79854
  abortAll();
@@ -79499,7 +79863,7 @@ var useOperationsOverviewRefresh = ({
79499
79863
  }
79500
79864
  void refreshAll("scope_change");
79501
79865
  }, [abortAll, companyId, enabled, lineIds.length, refreshAll, scopeSignature, stopPolling, store, supabase]);
79502
- React142__default.useEffect(() => {
79866
+ React143__default.useEffect(() => {
79503
79867
  if (!enabled || !isLiveScope || !supabase || !companyId || lineIds.length === 0) {
79504
79868
  isPageActiveRef.current = false;
79505
79869
  stopPolling("live_scope_disabled");
@@ -79674,55 +80038,55 @@ var PlantHeadView = () => {
79674
80038
  const { accessibleLineIds } = useUserLineAccess();
79675
80039
  const mobileMenuContext = useMobileMenu();
79676
80040
  useHideMobileHeader(!!mobileMenuContext);
79677
- const storeRef = React142__default.useRef(createOperationsOverviewStore());
80041
+ const storeRef = React143__default.useRef(createOperationsOverviewStore());
79678
80042
  const store = storeRef.current;
79679
- const fallbackOperationalDate = React142__default.useMemo(
80043
+ const fallbackOperationalDate = React143__default.useMemo(
79680
80044
  () => getOperationalDate(appTimezone),
79681
80045
  [appTimezone]
79682
80046
  );
79683
- const [dateRange, setDateRange] = React142__default.useState(() => ({
80047
+ const [dateRange, setDateRange] = React143__default.useState(() => ({
79684
80048
  startKey: fallbackOperationalDate,
79685
80049
  endKey: fallbackOperationalDate
79686
80050
  }));
79687
- const [usesThisWeekComparison, setUsesThisWeekComparison] = React142__default.useState(false);
79688
- const [trendMode, setTrendMode] = React142__default.useState("all");
79689
- const [selectedSupervisorId, setSelectedSupervisorId] = React142__default.useState("all");
79690
- const [selectedLineIds, setSelectedLineIds] = React142__default.useState([]);
79691
- const [isInitialScopeReady, setIsInitialScopeReady] = React142__default.useState(false);
79692
- const [shiftResolutionTick, setShiftResolutionTick] = React142__default.useState(0);
79693
- const hasAutoInitializedScopeRef = React142__default.useRef(false);
79694
- const hasUserAdjustedScopeRef = React142__default.useRef(false);
79695
- React142__default.useEffect(() => {
80051
+ const [usesThisWeekComparison, setUsesThisWeekComparison] = React143__default.useState(false);
80052
+ const [trendMode, setTrendMode] = React143__default.useState("all");
80053
+ const [selectedSupervisorId, setSelectedSupervisorId] = React143__default.useState("all");
80054
+ const [selectedLineIds, setSelectedLineIds] = React143__default.useState([]);
80055
+ const [isInitialScopeReady, setIsInitialScopeReady] = React143__default.useState(false);
80056
+ const [shiftResolutionTick, setShiftResolutionTick] = React143__default.useState(0);
80057
+ const hasAutoInitializedScopeRef = React143__default.useRef(false);
80058
+ const hasUserAdjustedScopeRef = React143__default.useRef(false);
80059
+ React143__default.useEffect(() => {
79696
80060
  trackCorePageView("Operations Overview", {
79697
80061
  dashboard_surface: "operations_overview"
79698
80062
  });
79699
80063
  }, []);
79700
- const currentWeekRange = React142__default.useMemo(
80064
+ const currentWeekRange = React143__default.useMemo(
79701
80065
  () => getCurrentWeekToDateRange(appTimezone),
79702
80066
  [appTimezone]
79703
80067
  );
79704
- const currentWeekDisplayRange = React142__default.useMemo(
80068
+ const currentWeekDisplayRange = React143__default.useMemo(
79705
80069
  () => getCurrentWeekFullRange(appTimezone),
79706
80070
  [appTimezone]
79707
80071
  );
79708
80072
  const isCurrentWeekToDateRange = dateRange.startKey === currentWeekRange.startKey && dateRange.endKey === currentWeekRange.endKey;
79709
- const headerDateRange = React142__default.useMemo(() => {
80073
+ const headerDateRange = React143__default.useMemo(() => {
79710
80074
  if (usesThisWeekComparison && isCurrentWeekToDateRange) {
79711
80075
  return currentWeekDisplayRange;
79712
80076
  }
79713
80077
  return dateRange;
79714
80078
  }, [currentWeekDisplayRange, dateRange, isCurrentWeekToDateRange, usesThisWeekComparison]);
79715
- const normalizedLineIds = React142__default.useMemo(
80079
+ const normalizedLineIds = React143__default.useMemo(
79716
80080
  () => Array.from(new Set(
79717
80081
  (accessibleLineIds || []).filter(Boolean).filter((lineId) => lineId !== factoryViewId)
79718
80082
  )).sort(),
79719
80083
  [accessibleLineIds, factoryViewId]
79720
80084
  );
79721
- const lineIdsKey = React142__default.useMemo(
80085
+ const lineIdsKey = React143__default.useMemo(
79722
80086
  () => normalizedLineIds.join(","),
79723
80087
  [normalizedLineIds]
79724
80088
  );
79725
- const lineOptions = React142__default.useMemo(
80089
+ const lineOptions = React143__default.useMemo(
79726
80090
  () => normalizedLineIds.map((lineId) => ({
79727
80091
  id: lineId,
79728
80092
  name: getLineDisplayName(entityConfig, lineId)
@@ -79734,7 +80098,7 @@ var PlantHeadView = () => {
79734
80098
  companyId: entityConfig.companyId,
79735
80099
  useBackend: true
79736
80100
  });
79737
- const supervisorOptions = React142__default.useMemo(
80101
+ const supervisorOptions = React143__default.useMemo(
79738
80102
  () => {
79739
80103
  const optionsById = /* @__PURE__ */ new Map();
79740
80104
  normalizedLineIds.forEach((lineId) => {
@@ -79760,7 +80124,7 @@ var PlantHeadView = () => {
79760
80124
  },
79761
80125
  [normalizedLineIds, supervisorsByLineId]
79762
80126
  );
79763
- React142__default.useEffect(() => {
80127
+ React143__default.useEffect(() => {
79764
80128
  if (selectedSupervisorId === "all") {
79765
80129
  setSelectedLineIds((previous) => {
79766
80130
  if (normalizedLineIds.length === 0) {
@@ -79786,7 +80150,7 @@ var PlantHeadView = () => {
79786
80150
  const scopedSupervisorLineIds = normalizedLineIds.filter((lineId) => supervisorLineIdSet.has(lineId));
79787
80151
  setSelectedLineIds((previous) => previous.length === scopedSupervisorLineIds.length && previous.every((lineId, index) => lineId === scopedSupervisorLineIds[index]) ? previous : scopedSupervisorLineIds);
79788
80152
  }, [lineIdsKey, normalizedLineIds, selectedSupervisorId, supervisorOptions]);
79789
- const scopedLineIds = React142__default.useMemo(
80153
+ const scopedLineIds = React143__default.useMemo(
79790
80154
  () => selectedLineIds.length > 0 ? selectedLineIds : normalizedLineIds,
79791
80155
  [normalizedLineIds, selectedLineIds]
79792
80156
  );
@@ -79794,7 +80158,7 @@ var PlantHeadView = () => {
79794
80158
  shiftConfigMap,
79795
80159
  isLoading: isShiftConfigLoading
79796
80160
  } = useMultiLineShiftConfigs(scopedLineIds, staticShiftConfig);
79797
- React142__default.useEffect(() => {
80161
+ React143__default.useEffect(() => {
79798
80162
  if (scopedLineIds.length === 0 || isShiftConfigLoading) {
79799
80163
  return;
79800
80164
  }
@@ -79805,11 +80169,11 @@ var PlantHeadView = () => {
79805
80169
  clearInterval(intervalId);
79806
80170
  };
79807
80171
  }, [isShiftConfigLoading, scopedLineIds.length]);
79808
- const shiftResolutionNow = React142__default.useMemo(
80172
+ const shiftResolutionNow = React143__default.useMemo(
79809
80173
  () => /* @__PURE__ */ new Date(),
79810
80174
  [shiftResolutionTick]
79811
80175
  );
79812
- const earliestDayShiftStartTime = React142__default.useMemo(() => {
80176
+ const earliestDayShiftStartTime = React143__default.useMemo(() => {
79813
80177
  const candidateStarts = [];
79814
80178
  scopedLineIds.forEach((lineId) => {
79815
80179
  const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
@@ -79845,11 +80209,11 @@ var PlantHeadView = () => {
79845
80209
  const minutes = earliestMinutes % 60;
79846
80210
  return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
79847
80211
  }, [appTimezone, scopedLineIds, shiftConfigMap, staticShiftConfig]);
79848
- const resolvedOperationalToday = React142__default.useMemo(
80212
+ const resolvedOperationalToday = React143__default.useMemo(
79849
80213
  () => getOperationalDate(appTimezone, shiftResolutionNow, earliestDayShiftStartTime),
79850
80214
  [appTimezone, earliestDayShiftStartTime, shiftResolutionNow]
79851
80215
  );
79852
- const activeLineShiftStates = React142__default.useMemo(() => {
80216
+ const activeLineShiftStates = React143__default.useMemo(() => {
79853
80217
  return scopedLineIds.flatMap((lineId) => {
79854
80218
  const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
79855
80219
  const activeShift = getActiveShift(appTimezone, shiftConfig, shiftResolutionNow);
@@ -79876,16 +80240,16 @@ var PlantHeadView = () => {
79876
80240
  }];
79877
80241
  });
79878
80242
  }, [appTimezone, scopedLineIds, shiftConfigMap, shiftResolutionNow, staticShiftConfig]);
79879
- const hasActiveDayShiftLine = React142__default.useMemo(
80243
+ const hasActiveDayShiftLine = React143__default.useMemo(
79880
80244
  () => activeLineShiftStates.some((shift) => shift.trendMode === "day" && shift.date === resolvedOperationalToday),
79881
80245
  [activeLineShiftStates, resolvedOperationalToday]
79882
80246
  );
79883
- const hasActiveNightShiftLine = React142__default.useMemo(
80247
+ const hasActiveNightShiftLine = React143__default.useMemo(
79884
80248
  () => activeLineShiftStates.some((shift) => shift.trendMode === "night" && shift.date === resolvedOperationalToday),
79885
80249
  [activeLineShiftStates, resolvedOperationalToday]
79886
80250
  );
79887
80251
  const resolvedTrendMode = isInitialScopeReady ? trendMode : "all";
79888
- const hourlyWindowStartTime = React142__default.useMemo(() => {
80252
+ const hourlyWindowStartTime = React143__default.useMemo(() => {
79889
80253
  if (scopedLineIds.length === 0) {
79890
80254
  return null;
79891
80255
  }
@@ -79936,12 +80300,12 @@ var PlantHeadView = () => {
79936
80300
  const minutes = earliestMinutes % 60;
79937
80301
  return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
79938
80302
  }, [appTimezone, resolvedTrendMode, scopedLineIds, shiftConfigMap, staticShiftConfig]);
79939
- const isShiftScopeResolved = React142__default.useMemo(
80303
+ const isShiftScopeResolved = React143__default.useMemo(
79940
80304
  () => !isShiftConfigLoading,
79941
80305
  [isShiftConfigLoading]
79942
80306
  );
79943
- const initializedTimezoneRef = React142__default.useRef(appTimezone);
79944
- React142__default.useEffect(() => {
80307
+ const initializedTimezoneRef = React143__default.useRef(appTimezone);
80308
+ React143__default.useEffect(() => {
79945
80309
  if (initializedTimezoneRef.current === appTimezone) return;
79946
80310
  hasAutoInitializedScopeRef.current = false;
79947
80311
  hasUserAdjustedScopeRef.current = false;
@@ -79954,7 +80318,7 @@ var PlantHeadView = () => {
79954
80318
  setIsInitialScopeReady(false);
79955
80319
  initializedTimezoneRef.current = appTimezone;
79956
80320
  }, [appTimezone, fallbackOperationalDate]);
79957
- React142__default.useEffect(() => {
80321
+ React143__default.useEffect(() => {
79958
80322
  if (hasAutoInitializedScopeRef.current || hasUserAdjustedScopeRef.current) {
79959
80323
  return;
79960
80324
  }
@@ -79979,7 +80343,7 @@ var PlantHeadView = () => {
79979
80343
  hasAutoInitializedScopeRef.current = true;
79980
80344
  setIsInitialScopeReady(true);
79981
80345
  }, [fallbackOperationalDate, isShiftScopeResolved, resolvedOperationalToday, scopedLineIds.length]);
79982
- const handleDateRangeChange = React142__default.useCallback((range, meta) => {
80346
+ const handleDateRangeChange = React143__default.useCallback((range, meta) => {
79983
80347
  hasUserAdjustedScopeRef.current = true;
79984
80348
  setIsInitialScopeReady(true);
79985
80349
  trackCoreEvent("Operations Overview Date Range Changed", {
@@ -79997,12 +80361,12 @@ var PlantHeadView = () => {
79997
80361
  return previous;
79998
80362
  });
79999
80363
  }, []);
80000
- const handleTrendModeChange = React142__default.useCallback((mode) => {
80364
+ const handleTrendModeChange = React143__default.useCallback((mode) => {
80001
80365
  hasUserAdjustedScopeRef.current = true;
80002
80366
  setIsInitialScopeReady(true);
80003
80367
  setTrendMode(mode);
80004
80368
  }, []);
80005
- const handleSelectedLineIdsChange = React142__default.useCallback((lineIds) => {
80369
+ const handleSelectedLineIdsChange = React143__default.useCallback((lineIds) => {
80006
80370
  setSelectedSupervisorId("all");
80007
80371
  if (normalizedLineIds.length === 0) {
80008
80372
  setSelectedLineIds([]);
@@ -80013,10 +80377,10 @@ var PlantHeadView = () => {
80013
80377
  const next = normalizedLineIds.filter((lineId) => selectedSet.has(lineId));
80014
80378
  setSelectedLineIds(next.length > 0 ? next : normalizedLineIds);
80015
80379
  }, [normalizedLineIds]);
80016
- const handleSelectedSupervisorIdChange = React142__default.useCallback((supervisorId) => {
80380
+ const handleSelectedSupervisorIdChange = React143__default.useCallback((supervisorId) => {
80017
80381
  setSelectedSupervisorId(supervisorId);
80018
80382
  }, []);
80019
- const buildLineMonthlyHistoryUrl = React142__default.useCallback((lineId) => {
80383
+ const buildLineMonthlyHistoryUrl = React143__default.useCallback((lineId) => {
80020
80384
  const rangeStartDate = parseDateKeyToDate(dateRange.startKey);
80021
80385
  const params = new URLSearchParams();
80022
80386
  params.set("tab", "monthly_history");
@@ -80026,15 +80390,15 @@ var PlantHeadView = () => {
80026
80390
  params.set("rangeEnd", dateRange.endKey);
80027
80391
  return `/kpis/${lineId}?${params.toString()}`;
80028
80392
  }, [dateRange.endKey, dateRange.startKey]);
80029
- const handleViewAllPoorestPerformers = React142__default.useCallback(() => {
80393
+ const handleViewAllPoorestPerformers = React143__default.useCallback(() => {
80030
80394
  trackCoreEvent("Operations Overview View All Clicked", { section: "poorest_performers" });
80031
80395
  navigate("/kpis?tab=leaderboard");
80032
80396
  }, [navigate]);
80033
- const handleViewAllImprovements = React142__default.useCallback(() => {
80397
+ const handleViewAllImprovements = React143__default.useCallback(() => {
80034
80398
  trackCoreEvent("Operations Overview View All Clicked", { section: "improvements" });
80035
80399
  navigate("/improvement-center");
80036
80400
  }, [navigate]);
80037
- const handleOpenImprovement = React142__default.useCallback((item) => {
80401
+ const handleOpenImprovement = React143__default.useCallback((item) => {
80038
80402
  trackCoreEvent("Operations Overview Improvement Clicked", {
80039
80403
  issue_id: item.issueId,
80040
80404
  issue_number: item.issueNumber,
@@ -80045,13 +80409,13 @@ var PlantHeadView = () => {
80045
80409
  });
80046
80410
  navigate(`/improvement-center?${params.toString()}`);
80047
80411
  }, [navigate]);
80048
- const comparisonStrategy = React142__default.useMemo(() => {
80412
+ const comparisonStrategy = React143__default.useMemo(() => {
80049
80413
  if (usesThisWeekComparison && isCurrentWeekToDateRange) {
80050
80414
  return "previous_full_week";
80051
80415
  }
80052
80416
  return void 0;
80053
80417
  }, [isCurrentWeekToDateRange, usesThisWeekComparison]);
80054
- const effectiveDateRange = React142__default.useMemo(() => {
80418
+ const effectiveDateRange = React143__default.useMemo(() => {
80055
80419
  if (isInitialScopeReady) {
80056
80420
  return dateRange;
80057
80421
  }
@@ -80061,21 +80425,21 @@ var PlantHeadView = () => {
80061
80425
  endKey: nextStartKey
80062
80426
  };
80063
80427
  }, [dateRange, fallbackOperationalDate, isInitialScopeReady, resolvedOperationalToday]);
80064
- const effectiveTrendMode = React142__default.useMemo(
80428
+ const effectiveTrendMode = React143__default.useMemo(
80065
80429
  () => resolvedTrendMode,
80066
80430
  [resolvedTrendMode]
80067
80431
  );
80068
- const hourlyLabelStartTime = React142__default.useMemo(() => {
80432
+ const hourlyLabelStartTime = React143__default.useMemo(() => {
80069
80433
  if (scopedLineIds.length === 0) {
80070
80434
  return null;
80071
80435
  }
80072
80436
  return hourlyWindowStartTime;
80073
80437
  }, [hourlyWindowStartTime, scopedLineIds.length]);
80074
- const isSingleDayScope = React142__default.useMemo(
80438
+ const isSingleDayScope = React143__default.useMemo(
80075
80439
  () => effectiveDateRange.startKey === effectiveDateRange.endKey,
80076
80440
  [effectiveDateRange.endKey, effectiveDateRange.startKey]
80077
80441
  );
80078
- const isLiveScope = React142__default.useMemo(
80442
+ const isLiveScope = React143__default.useMemo(
80079
80443
  () => isSingleDayScope && effectiveDateRange.startKey === resolvedOperationalToday && (effectiveTrendMode === "all" || effectiveTrendMode === "day" && hasActiveDayShiftLine || effectiveTrendMode === "night" && hasActiveNightShiftLine),
80080
80444
  [
80081
80445
  effectiveDateRange.startKey,
@@ -80086,7 +80450,7 @@ var PlantHeadView = () => {
80086
80450
  resolvedOperationalToday
80087
80451
  ]
80088
80452
  );
80089
- const handleOpenLineDetails = React142__default.useCallback((lineId, lineName) => {
80453
+ const handleOpenLineDetails = React143__default.useCallback((lineId, lineName) => {
80090
80454
  trackCoreEvent("Operations Overview Line Clicked", {
80091
80455
  line_id: lineId,
80092
80456
  line_name: lineName,
@@ -80654,4 +81018,4 @@ var streamProxyConfig = {
80654
81018
  }
80655
81019
  };
80656
81020
 
80657
- export { ACTION_FAMILIES, ACTION_NAMES, AIAgentView_default as AIAgentView, AcceptInvite, AcceptInviteView_default as AcceptInviteView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthService, AuthenticatedBottleneckClipsView, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedTicketsView, AuthenticatedWorkspaceHealthView, AvatarUpload, AxelNotificationPopup, AxelOrb, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottleneckClipsModal, BottleneckClipsView_default as BottleneckClipsView, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ChangeRoleDialog, ClipFilterProvider, ClipsCostView_default as ClipsCostView, CompactWorkspaceHealthCard, ConfirmRemoveUserDialog, CongratulationsOverlay, CroppedHlsVideoPlayer, CroppedVideoPlayer, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_HOME_VIEW_CONFIG, DEFAULT_MAP_VIEW_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_SHIFT_DATA, 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, DetailedHealthStatus, DiagnosisVideoModal, EFFICIENCY_ON_TRACK_THRESHOLD, EmptyStateMessage, EncouragementOverlay, FactoryAssignmentDropdown, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, FittingTitle, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthDateShiftSelector, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HlsVideoPlayer, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, HourlyUptimeChart, ISTTimer_default as ISTTimer, IdleTimeVlmConfigProvider, ImprovementCenterView_default as ImprovementCenterView, InlineEditableText, InteractiveOnboardingTour, InvitationService, InvitationsTable, InviteUserDialog, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend5 as Legend, LineAssignmentDropdown, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LinesService, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, Logo, MainLayout, MapGridView, MetricCard_default as MetricCard, MinimalOnboardingPopup, MobileMenuProvider, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PlantHeadView_default as PlantHeadView, PlayPauseIndicator, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, ROOT_DASHBOARD_EVENT_NAMES, RegistryProvider, RoleBadge, S3ClipsSupabaseService as S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SessionTracker, SessionTrackingContext, SessionTrackingProvider, SettingsPopup, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SignupWithInvitation, SilentErrorBoundary, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, TeamManagementView_default as TeamManagementView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TicketsView_default as TicketsView, TimeDisplay_default as TimeDisplay, TimePickerDropdown, Timer_default as Timer, TimezoneProvider, TimezoneService, UptimeDonutChart, UptimeLineChart, UptimeMetricCards, UserAvatar, UserManagementService, UserManagementTable, UserService, UserUsageDetailModal, UserUsageStats, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceCycleTimeMetricCards, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, aggregateKPIsFromLineMetricsRows, alertsService, apiUtils, areAllLinesOnSameShift, authCoreService, authOTPService, authRateLimitService, awardsService, buildDateKey, buildKPIsFromLineMetricsRow, buildShiftGroupsKey, canRoleAccessDashboardPath, canRoleAccessTeamManagement, canRoleAssignFactories, canRoleAssignLines, canRoleChangeRole, canRoleInviteRole, canRoleManageCompany, canRoleManageTargets, canRoleManageUsers, canRoleRemoveUser, canRoleViewClipsCost, canRoleViewUsageStats, captureSentryException, captureSentryMessage, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearSentryContext, clearWorkspaceDisplayNamesCache, cn, createDefaultKPIs, createInvitationService, createLinesService, createSessionTracker, createStorageService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, fetchIdleTimeReasons, filterDataByDateKeyRange, forceRefreshWorkspaceDisplayNames, formatAwardMonth, formatDateInZone, formatDateKeyForDisplay, formatDateTimeInZone, formatDuration2 as formatDuration, formatISTDate, formatIdleTime, formatRangeLabel, formatReasonLabel, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getActionDisplayName, getActiveShift, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAllWorkspaceDisplayNamesSnapshot, getAnonClient, getAssignableRoles, getAssignmentColumnLabel, getAvailableShiftIds, getAwardBadgeType, getAwardDescription, getAwardTitle, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentShiftForLine, getCurrentTimeInZone, getCurrentWeekFullRange, getCurrentWeekToDateRange, getDashboardHeaderTimeInZone, getDateKeyFromDate, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getInitials, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getMonthKeyBounds, getMonthWeekRanges, getNextUpdateInterval, getOperationalDate, getRoleAssignmentKind, getRoleDescription, getRoleLabel, getRoleMetadata, getRoleNavPaths, getS3SignedUrl, getS3VideoSrc, getShiftData, getShiftNameById, getShiftWorkDurationSeconds, getShortShiftName, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUniformShiftGroup, getUserThreads, getUserThreadsPaginated, getVisibleRolesForCurrentUser, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, groupLinesByShift, hasAnyShiftData, identifyCoreUser, initializeCoreMixpanel, isEfficiencyOnTrack, isFactoryScopedRole, isFullMonthRange, isLegacyConfiguration, isLoopbackHostname, isPrefetchError, isRecentFlowVideoGridMetricMode, isSafari, isSupervisorRole, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWipGatedVideoGridMetricMode, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, lineLeaderboardService, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, normalizeActionFamily, normalizeDateKeyRange, normalizeRoleLevel, normalizeVideoGridMetricMode, optifyeAgentClient, parseDateKeyToDate, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, setSentryUserContext, setSentryWorkspaceContext, shouldEnableLocalDevTestLogin, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, subscribeWorkspaceDisplayNames, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, transformToChartData, updateThreadTitle, upsertWorkspaceDisplayNameInCache, useAccessControl, useActiveBreaks, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useClipsInit, useCompanyClipsCost, useCompanyFastSlowClipFiltersEnabled, useCompanyHasVlmEnabledLine, useCompanyUsersUsage, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHideMobileHeader, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useIdleTimeClipClassifications, useIdleTimeReasons, useIdleTimeVlmConfig, useKpiTrends, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useLines, useMessages, useMetrics, useMobileMenu, useMonthlyTrend, useMultiLineShiftConfigs, useNavigation, useOperationalShiftKey, useOptionalSupabase, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useSessionTracking, useSessionTrackingContext, useShiftConfig, useShiftGroups, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useSupervisorsByLineIds, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useUserUsage, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthLastSeen, useWorkspaceHealthStatus, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, useWorkspaceUptimeTimeline, useWorkspaceVideoStreams, userService, videoPrefetchManager, videoPreloader, weeklyTopPerformerService, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };
81021
+ export { ACTION_FAMILIES, ACTION_NAMES, AIAgentView_default as AIAgentView, AcceptInvite, AcceptInviteView_default as AcceptInviteView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthService, AuthenticatedBottleneckClipsView, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedTicketsView, AuthenticatedWorkspaceHealthView, AvatarUpload, AxelNotificationPopup, AxelOrb, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottleneckClipsModal, BottleneckClipsView_default as BottleneckClipsView, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ChangeRoleDialog, ClipFilterProvider, ClipsCostView_default as ClipsCostView, CompactWorkspaceHealthCard, ConfirmRemoveUserDialog, CongratulationsOverlay, CroppedHlsVideoPlayer, CroppedVideoPlayer, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_HOME_VIEW_CONFIG, DEFAULT_MAP_VIEW_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_SHIFT_DATA, 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, DetailedHealthStatus, DiagnosisVideoModal, EFFICIENCY_ON_TRACK_THRESHOLD, EmptyStateMessage, EncouragementOverlay, FactoryAssignmentDropdown, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, FittingTitle, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthDateShiftSelector, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HlsVideoPlayer, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, HourlyUptimeChart, ISTTimer_default as ISTTimer, IdleTimeVlmConfigProvider, ImprovementCenterView_default as ImprovementCenterView, InlineEditableText, InteractiveOnboardingTour, InvitationService, InvitationsTable, InviteUserDialog, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend5 as Legend, LineAssignmentDropdown, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LinesService, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, Logo, MainLayout, MapGridView, MetricCard_default as MetricCard, MinimalOnboardingPopup, MobileMenuProvider, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PlantHeadView_default as PlantHeadView, PlayPauseIndicator, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, ROOT_DASHBOARD_EVENT_NAMES, RegistryProvider, RoleBadge, S3ClipsSupabaseService as S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SessionTracker, SessionTrackingContext, SessionTrackingProvider, SettingsPopup, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SignupWithInvitation, SilentErrorBoundary, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, TeamManagementView_default as TeamManagementView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TicketsView_default as TicketsView, TimeDisplay_default as TimeDisplay, TimePickerDropdown, Timer_default as Timer, TimezoneProvider, TimezoneService, UptimeDonutChart, UptimeLineChart, UptimeMetricCards, UserAvatar, UserManagementService, UserManagementTable, UserService, UserUsageDetailModal, UserUsageStats, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceCycleTimeMetricCards, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, aggregateKPIsFromLineMetricsRows, alertsService, apiUtils, areAllLinesOnSameShift, authCoreService, authOTPService, authRateLimitService, awardsService, buildDateKey, buildKPIsFromLineMetricsRow, buildShiftGroupsKey, canRoleAccessDashboardPath, canRoleAccessTeamManagement, canRoleAssignFactories, canRoleAssignLines, canRoleChangeRole, canRoleInviteRole, canRoleManageCompany, canRoleManageTargets, canRoleManageUsers, canRoleRemoveUser, canRoleViewClipsCost, canRoleViewUsageStats, captureHandledFrontendException, captureSentryException, captureSentryMessage, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearSentryContext, clearWorkspaceDisplayNamesCache, cn, createDefaultKPIs, createInvitationService, createLinesService, createSessionTracker, createStorageService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, fetchIdleTimeReasons, filterDataByDateKeyRange, forceRefreshWorkspaceDisplayNames, formatAwardMonth, formatDateInZone, formatDateKeyForDisplay, formatDateTimeInZone, formatDuration2 as formatDuration, formatISTDate, formatIdleTime, formatRangeLabel, formatReasonLabel, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getActionDisplayName, getActiveShift, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAllWorkspaceDisplayNamesSnapshot, getAnonClient, getAssignableRoles, getAssignmentColumnLabel, getAvailableShiftIds, getAwardBadgeType, getAwardDescription, getAwardTitle, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentShiftForLine, getCurrentTimeInZone, getCurrentWeekFullRange, getCurrentWeekToDateRange, getDashboardHeaderTimeInZone, getDateKeyFromDate, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getInitials, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getMonthKeyBounds, getMonthWeekRanges, getNextUpdateInterval, getOperationalDate, getRoleAssignmentKind, getRoleDescription, getRoleLabel, getRoleMetadata, getRoleNavPaths, getS3SignedUrl, getS3VideoSrc, getShiftData, getShiftNameById, getShiftWorkDurationSeconds, getShortShiftName, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUniformShiftGroup, getUserThreads, getUserThreadsPaginated, getVisibleRolesForCurrentUser, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, groupLinesByShift, hasAnyShiftData, identifyCoreUser, initializeCoreMixpanel, isEfficiencyOnTrack, isFactoryScopedRole, isFullMonthRange, isIgnorableFrontendError, isLegacyConfiguration, isLoopbackHostname, isPrefetchError, isRecentFlowVideoGridMetricMode, isSafari, isSupervisorRole, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWipGatedVideoGridMetricMode, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, lineLeaderboardService, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, normalizeActionFamily, normalizeDateKeyRange, normalizeRoleLevel, normalizeVideoGridMetricMode, optifyeAgentClient, parseDateKeyToDate, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, setSentryUserContext, setSentryWorkspaceContext, shouldEnableLocalDevTestLogin, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, subscribeWorkspaceDisplayNames, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, transformToChartData, updateThreadTitle, upsertWorkspaceDisplayNameInCache, useAccessControl, useActiveBreaks, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useClipsInit, useCompanyClipsCost, useCompanyFastSlowClipFiltersEnabled, useCompanyHasVlmEnabledLine, useCompanyUsersUsage, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHideMobileHeader, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useIdleTimeClipClassifications, useIdleTimeReasons, useIdleTimeVlmConfig, useKpiTrends, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useLines, useMessages, useMetrics, useMobileMenu, useMonthlyTrend, useMultiLineShiftConfigs, useNavigation, useOperationalShiftKey, useOptionalSupabase, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useSessionTracking, useSessionTrackingContext, useShiftConfig, useShiftGroups, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useSupervisorsByLineIds, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useUserUsage, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthLastSeen, useWorkspaceHealthStatus, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, useWorkspaceUptimeTimeline, useWorkspaceVideoStreams, userService, videoPrefetchManager, videoPreloader, weeklyTopPerformerService, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };