@optifye/dashboard-core 6.11.32 → 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,
@@ -39641,7 +39802,7 @@ var TimePickerDropdown = ({
39641
39802
  )
39642
39803
  ] });
39643
39804
  };
39644
- var SilentErrorBoundary = class extends React142__default.Component {
39805
+ var SilentErrorBoundary = class extends React143__default.Component {
39645
39806
  constructor(props) {
39646
39807
  super(props);
39647
39808
  this.handleClearAndReload = () => {
@@ -39674,6 +39835,12 @@ var SilentErrorBoundary = class extends React142__default.Component {
39674
39835
  componentStack: errorInfo.componentStack,
39675
39836
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
39676
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
+ });
39677
39844
  this.setState((prev) => ({
39678
39845
  errorCount: prev.errorCount + 1,
39679
39846
  lastError: error,
@@ -46510,8 +46677,8 @@ var IdleTimeReasonChartComponent = ({
46510
46677
  updateAnimation = "replay",
46511
46678
  variant = "pie"
46512
46679
  }) => {
46513
- const [activeData, setActiveData] = React142__default.useState([]);
46514
- React142__default.useEffect(() => {
46680
+ const [activeData, setActiveData] = React143__default.useState([]);
46681
+ React143__default.useEffect(() => {
46515
46682
  if (updateAnimation === "smooth") {
46516
46683
  setActiveData(data && data.length > 0 ? data : []);
46517
46684
  return;
@@ -46530,7 +46697,7 @@ var IdleTimeReasonChartComponent = ({
46530
46697
  setActiveData([]);
46531
46698
  }
46532
46699
  }, [data, updateAnimation]);
46533
- React142__default.useEffect(() => {
46700
+ React143__default.useEffect(() => {
46534
46701
  if (!data || data.length === 0) return;
46535
46702
  data.forEach((entry, index) => {
46536
46703
  if (entry.name.toLowerCase().includes("other")) {
@@ -46538,7 +46705,7 @@ var IdleTimeReasonChartComponent = ({
46538
46705
  }
46539
46706
  });
46540
46707
  }, [data]);
46541
- const pieKey = React142__default.useMemo(() => {
46708
+ const pieKey = React143__default.useMemo(() => {
46542
46709
  if (updateAnimation === "smooth") {
46543
46710
  return "smooth";
46544
46711
  }
@@ -46708,7 +46875,7 @@ var IdleTimeReasonChartComponent = ({
46708
46875
  )
46709
46876
  ] });
46710
46877
  };
46711
- var IdleTimeReasonChart = React142__default.memo(IdleTimeReasonChartComponent);
46878
+ var IdleTimeReasonChart = React143__default.memo(IdleTimeReasonChartComponent);
46712
46879
  IdleTimeReasonChart.displayName = "IdleTimeReasonChart";
46713
46880
  var IdleTimeReasonChart_default = IdleTimeReasonChart;
46714
46881
  var DEFAULT_PERFORMANCE_DATA = {
@@ -51075,7 +51242,7 @@ var arePropsEqual = (prevProps, nextProps) => {
51075
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
51076
51243
  prevProps.position.id === nextProps.position.id;
51077
51244
  };
51078
- var WorkspaceGridItem = React142__default.memo(({
51245
+ var WorkspaceGridItem = React143__default.memo(({
51079
51246
  data,
51080
51247
  position,
51081
51248
  isBottleneck = false,
@@ -51103,7 +51270,7 @@ var WorkspaceGridItem = React142__default.memo(({
51103
51270
  const handleClick = useCallback((e) => {
51104
51271
  e.preventDefault();
51105
51272
  if (isInactive) return;
51106
- const displayName = getWorkspaceDisplayName(data.workspace_name, data.line_id);
51273
+ const displayName = data.displayName || getWorkspaceDisplayName(data.workspace_name, data.line_id);
51107
51274
  const currentPath = typeof window !== "undefined" ? `${window.location.pathname}${window.location.search}` : "/";
51108
51275
  const navParams = getWorkspaceNavigationParams(data.workspace_id, displayName, data.line_id, currentPath);
51109
51276
  navigate(`/workspace/${data.workspace_id}${navParams}`, {
@@ -51152,7 +51319,7 @@ var WorkspaceGridItem = React142__default.memo(({
51152
51319
  onClick: handleClick,
51153
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`,
51154
51321
  "aria-label": isInactive ? `Inactive workspace ${workspaceNumber}` : `View details for workspace ${workspaceNumber}`,
51155
- 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),
51156
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 })
51157
51324
  }
51158
51325
  ),
@@ -51170,7 +51337,7 @@ var WorkspaceGridItem = React142__default.memo(({
51170
51337
  );
51171
51338
  }, arePropsEqual);
51172
51339
  WorkspaceGridItem.displayName = "WorkspaceGridItem";
51173
- var WorkspaceGrid = React142__default.memo(({
51340
+ var WorkspaceGrid = React143__default.memo(({
51174
51341
  workspaces,
51175
51342
  isPdfMode = false,
51176
51343
  customWorkspacePositions,
@@ -51434,7 +51601,7 @@ var KPICard = ({
51434
51601
  }) => {
51435
51602
  useThemeConfig();
51436
51603
  const { formatNumber } = useFormatNumber();
51437
- const trendInfo = React142__default.useMemo(() => {
51604
+ const trendInfo = React143__default.useMemo(() => {
51438
51605
  let trendValue = trend || "neutral";
51439
51606
  if (change !== void 0 && trend === void 0) {
51440
51607
  trendValue = change > 0 ? "up" : change < 0 ? "down" : "neutral";
@@ -51461,7 +51628,7 @@ var KPICard = ({
51461
51628
  const shouldShowTrend = !(change === 0 && trend === void 0);
51462
51629
  return { trendValue, Icon: Icon2, colorClass, bgClass, shouldShowTrend };
51463
51630
  }, [trend, change]);
51464
- const formattedValue = React142__default.useMemo(() => {
51631
+ const formattedValue = React143__default.useMemo(() => {
51465
51632
  if (title === "Quality Compliance" && typeof value === "number") {
51466
51633
  return value.toFixed(1);
51467
51634
  }
@@ -51475,7 +51642,7 @@ var KPICard = ({
51475
51642
  }
51476
51643
  return value;
51477
51644
  }, [value, title]);
51478
- const formattedChange = React142__default.useMemo(() => {
51645
+ const formattedChange = React143__default.useMemo(() => {
51479
51646
  if (change === void 0 || change === 0 && !showZeroChange) return null;
51480
51647
  const absChange = Math.abs(change);
51481
51648
  return formatNumber(absChange, { minimumFractionDigits: 0, maximumFractionDigits: 1 });
@@ -52982,7 +53149,7 @@ var Breadcrumbs = ({ items }) => {
52982
53149
  }
52983
53150
  }
52984
53151
  };
52985
- 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: [
52986
53153
  index > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "h-3 w-3 text-gray-400 dark:text-gray-500" }),
52987
53154
  /* @__PURE__ */ jsxs(
52988
53155
  "span",
@@ -54458,7 +54625,7 @@ var AwardBadge = ({
54458
54625
  }) => {
54459
54626
  const styles2 = getBadgeStyles(type);
54460
54627
  const Icon2 = CustomIcon || getDefaultIcon(type);
54461
- const randomDelay = React142__default.useMemo(() => Math.random() * 2, []);
54628
+ const randomDelay = React143__default.useMemo(() => Math.random() * 2, []);
54462
54629
  const floatingAnimation = {
54463
54630
  animate: {
54464
54631
  y: [0, -10, 0],
@@ -59962,67 +60129,77 @@ var NotificationService = class {
59962
60129
  this.supabaseClient = supabaseClient || null;
59963
60130
  }
59964
60131
  async fetchWithAuth(url, options = {}) {
59965
- if (!this.supabaseClient) {
59966
- throw new Error("Supabase client not initialized. Please provide a Supabase client to NotificationService.");
59967
- }
59968
- const { data: { session }, error: sessionError } = await this.supabaseClient.auth.getSession();
59969
- if (sessionError) {
59970
- console.error("Session error:", sessionError);
59971
- throw new Error("Failed to get authentication session. Please log in.");
59972
- }
59973
- if (!session) {
59974
- console.error("No session found. User must be logged in.");
59975
- throw new Error("User not authenticated. Please log in.");
59976
- }
59977
- if (!session.access_token) {
59978
- console.error("Session exists but no access_token found");
59979
- throw new Error("Invalid session. Please log in again.");
59980
- }
59981
- const token = session.access_token;
59982
- if (process.env.NODE_ENV === "development") {
59983
- console.log("[NotificationService] Using JWT token for notifications API");
59984
- }
59985
- const headers = {
59986
- "Content-Type": "application/json",
59987
- ...options.headers,
59988
- "Authorization": `Bearer ${token}`
59989
- };
59990
- const response = await fetch(url, {
59991
- ...options,
59992
- headers
59993
- });
59994
- if (response.status === 401) {
59995
- console.error("401 Unauthorized - Token expired or invalid");
59996
- throw new Error("Authentication failed. Please log in again.");
59997
- }
59998
- if (response.status === 403) {
59999
- console.error("403 Forbidden - User does not have permission");
60000
- throw new Error("Access denied. You do not have permission to access this resource.");
60001
- }
60002
- if (response.status === 500) {
60003
- console.error("500 Internal Server Error - Backend error");
60004
- let errorDetail = "Internal server error occurred.";
60005
- try {
60006
- const errorData = await response.text();
60007
- console.error("Backend error details:", errorData);
60008
- errorDetail = errorData || errorDetail;
60009
- } catch (e) {
60132
+ try {
60133
+ if (!this.supabaseClient) {
60134
+ throw new Error("Supabase client not initialized. Please provide a Supabase client to NotificationService.");
60010
60135
  }
60011
- throw new Error(`Backend error: ${errorDetail}`);
60012
- }
60013
- if (!response.ok) {
60014
- console.error(`HTTP ${response.status} - ${response.statusText}`);
60015
- let errorDetail = response.statusText;
60016
- try {
60017
- const errorData = await response.json();
60018
- if (errorData.detail) {
60019
- 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) {
60020
60178
  }
60021
- } 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}`);
60022
60192
  }
60023
- 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;
60024
60202
  }
60025
- return response;
60026
60203
  }
60027
60204
  /**
60028
60205
  * Get bottleneck notifications
@@ -60096,8 +60273,6 @@ function HomeView({
60096
60273
  }) {
60097
60274
  const [isHydrated, setIsHydrated] = useState(false);
60098
60275
  const [isChangingFilter, setIsChangingFilter] = useState(false);
60099
- const [errorMessage, setErrorMessage] = useState(null);
60100
- const [displayNamesInitialized, setDisplayNamesInitialized] = useState(false);
60101
60276
  const [hasInitialDataLoaded, setHasInitialDataLoaded] = useState(false);
60102
60277
  const [showDataLoading, setShowDataLoading] = useState(false);
60103
60278
  const loadingStartRef = useRef(null);
@@ -60106,7 +60281,7 @@ function HomeView({
60106
60281
  const dashboardConfig = useDashboardConfig();
60107
60282
  const entityConfig = useEntityConfig();
60108
60283
  const supabaseClient = useSupabaseClient();
60109
- const { user } = useAuth();
60284
+ const { user, authStatus, isRecoveringSession, retrySessionHydration } = useAuth();
60110
60285
  const { lines: dbLines } = useLines();
60111
60286
  const mergedLineNames = useMemo(() => {
60112
60287
  const merged = { ...lineNames };
@@ -60240,26 +60415,7 @@ function HomeView({
60240
60415
  visibleLineIds,
60241
60416
  dashboardConfig?.shiftConfig
60242
60417
  );
60243
- useEffect(() => {
60244
- const initDisplayNames = async () => {
60245
- try {
60246
- for (const lineId of selectedLineIds) {
60247
- await preInitializeWorkspaceDisplayNames(lineId);
60248
- }
60249
- setDisplayNamesInitialized(true);
60250
- } catch (error) {
60251
- console.error("Failed to pre-initialize workspace display names:", error);
60252
- setDisplayNamesInitialized(true);
60253
- }
60254
- };
60255
- initDisplayNames();
60256
- }, [selectedLineIdsKey]);
60257
- const displayNameLineId = isMultiLineSelection ? void 0 : primarySelectedLineId;
60258
- const {
60259
- displayNames: workspaceDisplayNames,
60260
- loading: displayNamesLoading,
60261
- error: displayNamesError
60262
- } = useWorkspaceDisplayNames(displayNameLineId, void 0);
60418
+ const shouldEnableMetricsFetch = authStatus === "ready";
60263
60419
  const handleLineMetricsUpdate = useCallback(() => {
60264
60420
  if (trendRefreshTimerRef.current) {
60265
60421
  window.clearTimeout(trendRefreshTimerRef.current);
@@ -60286,9 +60442,32 @@ function HomeView({
60286
60442
  lineId: metricsScopeLineId,
60287
60443
  lineIds: selectedLineIds,
60288
60444
  onLineMetricsUpdate: handleLineMetricsUpdate,
60289
- userAccessibleLineIds: visibleLineIds
60445
+ userAccessibleLineIds: visibleLineIds,
60290
60446
  // Pass user's accessible lines for supervisor filtering
60447
+ enabled: shouldEnableMetricsFetch
60291
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]);
60292
60471
  const trendGroups = useMemo(() => {
60293
60472
  const lineMetricsRows = lineMetrics || [];
60294
60473
  if (!lineMetricsRows.length) return null;
@@ -60729,13 +60908,13 @@ function HomeView({
60729
60908
  dashboard_surface: "monitor"
60730
60909
  });
60731
60910
  }, []);
60732
- useEffect(() => {
60733
- if (metricsError) {
60734
- setErrorMessage(metricsError.message);
60735
- } else {
60736
- setErrorMessage(null);
60911
+ const metricsErrorMessage = metricsError?.message || null;
60912
+ const handleRetryDashboardData = useCallback(async () => {
60913
+ if (isRecoveringSession) {
60914
+ await retrySessionHydration();
60737
60915
  }
60738
- }, [metricsError]);
60916
+ refetchMetrics();
60917
+ }, [isRecoveringSession, refetchMetrics, retrySessionHydration]);
60739
60918
  const getTrackedLineScope = useCallback((lineIdsForScope) => {
60740
60919
  if (isAllLinesSelection(lineIdsForScope)) {
60741
60920
  return factoryViewId;
@@ -60793,7 +60972,7 @@ function HomeView({
60793
60972
  }
60794
60973
  }, [metricsLoading, isChangingFilter]);
60795
60974
  useEffect(() => {
60796
- if (!metricsLoading && !hasInitialDataLoaded) {
60975
+ if (shouldEnableMetricsFetch && !metricsLoading && !metricsError && !hasInitialDataLoaded) {
60797
60976
  setHasInitialDataLoaded(true);
60798
60977
  trackCoreEvent("monitor page loaded", {
60799
60978
  default_line_id: defaultLineId,
@@ -60802,7 +60981,7 @@ function HomeView({
60802
60981
  dashboard_surface: "monitor"
60803
60982
  });
60804
60983
  }
60805
- }, [metricsLoading, hasInitialDataLoaded, defaultLineId, factoryViewId, isSupervisor]);
60984
+ }, [shouldEnableMetricsFetch, metricsLoading, metricsError, hasInitialDataLoaded, defaultLineId, factoryViewId, isSupervisor]);
60806
60985
  const lineTitle = useMemo(() => {
60807
60986
  return factoryName;
60808
60987
  }, [factoryName]);
@@ -60952,8 +61131,9 @@ function HomeView({
60952
61131
  }, [isLoading, minDuration]);
60953
61132
  return showLoading;
60954
61133
  };
60955
- const isInitialLoading = !isHydrated || !hasInitialDataLoaded && (displayNamesLoading || !displayNamesInitialized);
60956
- const isDataLoading = metricsLoading || displayNamesLoading && workspaceMetrics.length === 0;
61134
+ const isAuthBootstrapping = authStatus === "loading";
61135
+ const isInitialLoading = !isHydrated || !hasInitialDataLoaded && (isAuthBootstrapping || shouldEnableMetricsFetch && metricsLoading);
61136
+ const isDataLoading = metricsLoading;
60957
61137
  const hasKpiDataReady = useMemo(() => {
60958
61138
  const lineMetricsRows = lineMetrics || [];
60959
61139
  if (selectedLineIds.length > 1) {
@@ -60962,6 +61142,10 @@ function HomeView({
60962
61142
  return lineMetricsRows.some((row) => row?.line_id === primarySelectedLineId);
60963
61143
  }, [lineMetrics, primarySelectedLineId, selectedLineIdSet, selectedLineIds.length]);
60964
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;
60965
61149
  useEffect(() => {
60966
61150
  const minLoadingDurationMs = 250;
60967
61151
  if (isDataLoading) {
@@ -61001,14 +61185,41 @@ function HomeView({
61001
61185
  if (isInitialLoading) {
61002
61186
  return /* @__PURE__ */ jsx(LoadingPageCmp, { message: "Loading Dashboard..." });
61003
61187
  }
61004
- if (errorMessage || displayNamesError) {
61005
- 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: [
61006
- /* @__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" }) }),
61007
- /* @__PURE__ */ jsxs("span", { className: "text-base sm:text-lg font-medium", children: [
61008
- "Error: ",
61009
- errorMessage || displayNamesError?.message
61010
- ] })
61011
- ] }) }) });
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
+ ] }) });
61012
61223
  }
61013
61224
  return /* @__PURE__ */ jsx(
61014
61225
  motion.div,
@@ -61027,6 +61238,20 @@ function HomeView({
61027
61238
  headerControls: kpiSectionControl
61028
61239
  }
61029
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,
61030
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(
61031
61256
  motion.div,
61032
61257
  {
@@ -61034,7 +61259,7 @@ function HomeView({
61034
61259
  animate: { opacity: 1, scale: 1 },
61035
61260
  transition: { duration: 0.3 },
61036
61261
  className: "h-full",
61037
- children: React142__default.createElement(WorkspaceGrid, {
61262
+ children: React143__default.createElement(WorkspaceGrid, {
61038
61263
  workspaces: workspaceMetricsWithBreakState,
61039
61264
  lineNames: mergedLineNames,
61040
61265
  lineOrder: selectedLineIds,
@@ -61043,7 +61268,7 @@ function HomeView({
61043
61268
  videoSources,
61044
61269
  videoStreamsByWorkspaceId,
61045
61270
  videoStreamsLoading,
61046
- displayNames: workspaceDisplayNames,
61271
+ displayNames: metricsDisplayNames,
61047
61272
  hasFlowBuffers,
61048
61273
  className: "h-full",
61049
61274
  toolbarRightContent: lineSelectorComponent,
@@ -61067,7 +61292,7 @@ function HomeView({
61067
61292
  animate: { opacity: 1, scale: 1 },
61068
61293
  transition: { duration: 0.3 },
61069
61294
  className: "h-full",
61070
- children: React142__default.createElement(WorkspaceGrid, {
61295
+ children: React143__default.createElement(WorkspaceGrid, {
61071
61296
  workspaces: [],
61072
61297
  // Show empty grid while loading
61073
61298
  lineNames: mergedLineNames,
@@ -61077,7 +61302,7 @@ function HomeView({
61077
61302
  videoSources,
61078
61303
  videoStreamsByWorkspaceId,
61079
61304
  videoStreamsLoading,
61080
- displayNames: workspaceDisplayNames,
61305
+ displayNames: metricsDisplayNames,
61081
61306
  hasFlowBuffers,
61082
61307
  className: "h-full",
61083
61308
  toolbarRightContent: lineSelectorComponent,
@@ -61135,7 +61360,7 @@ function HomeView({
61135
61360
  }
61136
61361
  );
61137
61362
  }
61138
- var AuthenticatedHomeView = withAuth(React142__default.memo(HomeView));
61363
+ var AuthenticatedHomeView = withAuth(React143__default.memo(HomeView));
61139
61364
  var HomeView_default = HomeView;
61140
61365
  function withWorkspaceDisplayNames(Component3, options = {}) {
61141
61366
  const {
@@ -61333,6 +61558,7 @@ var buildLineInfoSnapshot = (lineDetails, metrics2) => {
61333
61558
  shift_id: metrics2.shift_id ?? 0,
61334
61559
  date: metrics2.date || "",
61335
61560
  monitoring_mode: lineDetails.monitoring_mode ?? void 0,
61561
+ assembly: lineDetails.assembly ?? null,
61336
61562
  metrics: {
61337
61563
  avg_efficiency: metrics2.avg_efficiency ?? 0,
61338
61564
  avg_cycle_time: metrics2.avg_cycle_time ?? 0,
@@ -61365,6 +61591,7 @@ var transformWorkspaceMetrics = (workspaceData, lineId, companyId, queryDate, qu
61365
61591
  pph: item.avg_pph || 0,
61366
61592
  performance_score: item.performance_score || 0,
61367
61593
  avg_cycle_time: item.avg_cycle_time || 0,
61594
+ ideal_cycle_time: item.ideal_cycle_time ?? void 0,
61368
61595
  trend: item.trend_score === 1 ? 2 : 0,
61369
61596
  predicted_output: item.ideal_output || 0,
61370
61597
  efficiency: item.efficiency || 0,
@@ -61400,7 +61627,8 @@ var transformLineDetails = (lineId, detailResponse) => {
61400
61627
  id: detailResponse.line_details.factory_id || "",
61401
61628
  factory_name: detailResponse.line_details.factory_name || ""
61402
61629
  },
61403
- 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
61404
61632
  };
61405
61633
  };
61406
61634
  var transformLineMetrics = (lineId, detailResponse, queryDate, queryShiftId) => {
@@ -61801,6 +62029,56 @@ function useEfficiencyLegend(companyId) {
61801
62029
  refetch: fetchLegend
61802
62030
  };
61803
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
+ };
61804
62082
  var WEEKDAYS4 = ["S", "M", "T", "W", "T", "F", "S"];
61805
62083
  var MonthlyRangeFilter = ({
61806
62084
  month,
@@ -62400,7 +62678,13 @@ var BottomSection = memo$1(({
62400
62678
  }) => {
62401
62679
  const navigation = useNavigation();
62402
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
+ );
62403
62686
  const handleWorkspaceClick = useCallback((ws, index) => {
62687
+ const cycleRatio = getCycleRatio(ws);
62404
62688
  trackCoreEvent("Workspace from KPI Clicked", {
62405
62689
  workspace_name: ws.workspace_name,
62406
62690
  workspace_id: ws.workspace_uuid,
@@ -62409,9 +62693,13 @@ var BottomSection = memo$1(({
62409
62693
  efficiency: ws.efficiency,
62410
62694
  action_count: ws.action_count,
62411
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",
62412
62700
  section: "Poorest Performing Workspaces"
62413
62701
  });
62414
- }, [workspaceData.length]);
62702
+ }, [isAssemblyLine, workspaceData.length]);
62415
62703
  return /* @__PURE__ */ jsxs(
62416
62704
  motion.div,
62417
62705
  {
@@ -62433,14 +62721,42 @@ var BottomSection = memo$1(({
62433
62721
  )
62434
62722
  ] }),
62435
62723
  /* @__PURE__ */ jsxs("div", { className: "divide-y overflow-auto flex-1 pr-1 sm:pr-2", children: [
62436
- /* @__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: [
62437
62728
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 sm:gap-3 md:gap-6", children: [
62438
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" }),
62439
62730
  /* @__PURE__ */ jsx("div", { className: "text-xs md:text-sm font-medium text-gray-500", children: "Current/Ideal" })
62440
62731
  ] }),
62441
62732
  /* @__PURE__ */ jsx("div", { className: "text-xs md:text-sm font-medium text-gray-500 pr-1 sm:pr-2", children: "Efficiency" })
62442
- ] }),
62443
- 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) => {
62444
62760
  const wsMetrics = workspaceData.find((w) => w.workspace_name === ws.workspace_name);
62445
62761
  const wsUuid = wsMetrics?.workspace_uuid;
62446
62762
  if (!wsUuid) {
@@ -62536,10 +62852,63 @@ var BottomSection = memo$1(({
62536
62852
  const prevPoorest = prevProps.lineInfo.metrics.poorest_performing_workspaces || [];
62537
62853
  const nextPoorest = nextProps.lineInfo.metrics.poorest_performing_workspaces || [];
62538
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;
62539
62860
  if (prevProps.hourlyOutputData.length !== nextProps.hourlyOutputData.length) return false;
62540
62861
  const hourlyDataChanged = prevProps.hourlyOutputData.some((value, index) => value !== nextProps.hourlyOutputData[index]);
62541
62862
  if (hourlyDataChanged) return false;
62542
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;
62543
62912
  if (prevProps.lineInfo.metrics.shift_start !== nextProps.lineInfo.metrics.shift_start) return false;
62544
62913
  if (prevProps.hourlyThreshold !== nextProps.hourlyThreshold) return false;
62545
62914
  if (prevProps.urlDate !== nextProps.urlDate || prevProps.urlShift !== nextProps.urlShift) return false;
@@ -63014,6 +63383,7 @@ var KPIDetailView = ({
63014
63383
  shift_id: metrics2.shift_id ?? 0,
63015
63384
  date: metrics2.date || getOperationalDate(timezone || "UTC"),
63016
63385
  monitoring_mode: lineDetails.monitoring_mode ?? void 0,
63386
+ assembly: lineDetails.assembly ?? null,
63017
63387
  metrics: {
63018
63388
  avg_efficiency: metrics2.avg_efficiency ?? 0,
63019
63389
  avg_cycle_time: metrics2.avg_cycle_time ?? 0,
@@ -64105,18 +64475,18 @@ var LinesLeaderboard = ({
64105
64475
  isHistoricalDaily
64106
64476
  }) => {
64107
64477
  const formatEfficiency = (value) => typeof value === "number" && Number.isFinite(value) ? `${value.toFixed(1)}%` : "--";
64108
- const assignedLineIdSet = React142__default.useMemo(
64478
+ const assignedLineIdSet = React143__default.useMemo(
64109
64479
  () => new Set(assignedLineIds || []),
64110
64480
  [assignedLineIds]
64111
64481
  );
64112
- const canClickLine = React142__default.useCallback(
64482
+ const canClickLine = React143__default.useCallback(
64113
64483
  (lineId) => {
64114
64484
  if (!assignedLineIds) return true;
64115
64485
  return assignedLineIdSet.has(lineId);
64116
64486
  },
64117
64487
  [assignedLineIds, assignedLineIdSet]
64118
64488
  );
64119
- const handleTimeRangeChange = React142__default.useCallback((newRange) => {
64489
+ const handleTimeRangeChange = React143__default.useCallback((newRange) => {
64120
64490
  if (newRange === timeRange) return;
64121
64491
  trackCoreEvent("Leaderboard Time Range Changed", {
64122
64492
  from_range: timeRange,
@@ -64127,7 +64497,7 @@ var LinesLeaderboard = ({
64127
64497
  });
64128
64498
  setTimeRange(newRange);
64129
64499
  }, [timeRange, lines.length, monthlyEfficiencyByLineId, setTimeRange]);
64130
- const handleLeaderboardLineClick = React142__default.useCallback((item, clickSource) => {
64500
+ const handleLeaderboardLineClick = React143__default.useCallback((item, clickSource) => {
64131
64501
  if (!canClickLine(item.line.id)) return;
64132
64502
  trackCoreEvent("Leaderboard Line Clicked", {
64133
64503
  line_id: item.line.id,
@@ -64141,8 +64511,8 @@ var LinesLeaderboard = ({
64141
64511
  });
64142
64512
  onLineClick(item.line);
64143
64513
  }, [canClickLine, onLineClick, timeRange]);
64144
- const viewLoadedTrackedRef = React142__default.useRef(null);
64145
- const leaderboardData = React142__default.useMemo(() => {
64514
+ const viewLoadedTrackedRef = React143__default.useRef(null);
64515
+ const leaderboardData = React143__default.useMemo(() => {
64146
64516
  const loading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
64147
64517
  const efficiencyMap = timeRange === "today" ? todayEfficiencyByLineId : monthlyEfficiencyByLineId;
64148
64518
  return lines.map((line) => {
@@ -64173,7 +64543,7 @@ var LinesLeaderboard = ({
64173
64543
  isLoadingToday,
64174
64544
  isLoadingMonthly
64175
64545
  ]);
64176
- React142__default.useEffect(() => {
64546
+ React143__default.useEffect(() => {
64177
64547
  const isLoading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
64178
64548
  const trackingKey = `${timeRange}-${leaderboardData.length}`;
64179
64549
  if (leaderboardData.length > 0 && !isLoading && viewLoadedTrackedRef.current !== trackingKey) {
@@ -64199,7 +64569,7 @@ var LinesLeaderboard = ({
64199
64569
  const countdownFormat = timeRange === "monthly" ? "days" : "clock";
64200
64570
  const countdownFinishedLabel = timeRange === "monthly" ? "Finished" : "Shift Ended";
64201
64571
  const showCountdown = timeRange === "monthly" || !isHistoricalDaily;
64202
- const handleCountdownFinished = React142__default.useCallback(() => {
64572
+ const handleCountdownFinished = React143__default.useCallback(() => {
64203
64573
  trackCoreEvent("Leaderboard Countdown Finished", {
64204
64574
  countdown_type: timeRange === "monthly" ? "month_end" : "shift_end",
64205
64575
  time_range: timeRange,
@@ -64226,7 +64596,7 @@ var LinesLeaderboard = ({
64226
64596
  return "bg-white border-gray-100";
64227
64597
  }
64228
64598
  };
64229
- React142__default.useEffect(() => {
64599
+ React143__default.useEffect(() => {
64230
64600
  const style = document.createElement("style");
64231
64601
  style.innerHTML = `
64232
64602
  @keyframes float {
@@ -64413,7 +64783,7 @@ var LineCard = ({
64413
64783
  supervisors
64414
64784
  }) => {
64415
64785
  const isUptimeLine = (line.monitoring_mode ?? "output") === "uptime";
64416
- const isOnTrack = React142__default.useMemo(() => {
64786
+ const isOnTrack = React143__default.useMemo(() => {
64417
64787
  if (!kpis) return null;
64418
64788
  return isEfficiencyOnTrack(kpis.efficiency.value);
64419
64789
  }, [kpis]);
@@ -64611,46 +64981,46 @@ var KPIsOverviewView = ({
64611
64981
  const configuredTimezone = dbTimezone || dateTimeConfig.defaultTimezone || "UTC";
64612
64982
  const { startDate: monthStartDate, endDate: monthEndDateKey, monthEndDate } = getMonthDateInfo(configuredTimezone);
64613
64983
  const isSuperAdmin = user?.scope_mode === "SUPER_ADMIN" || !!user?.access_scope?.is_super_admin;
64614
- const scopedLineIds = React142__default.useMemo(
64984
+ const scopedLineIds = React143__default.useMemo(
64615
64985
  () => Array.isArray(user?.access_scope?.line_ids) ? user.access_scope.line_ids.filter((lineId) => typeof lineId === "string" && lineId.length > 0) : [],
64616
64986
  [user?.access_scope?.line_ids]
64617
64987
  );
64618
64988
  const hasCanonicalScope = !!user?.scope_mode || !!user?.access_scope;
64619
64989
  const scopeRole = (user?.role_level || user?.role || "").toLowerCase();
64620
64990
  const isStrictLineScopedRole = scopeRole === "supervisor" || isFactoryScopedRole(scopeRole);
64621
- const resolvedAssignedLineIds = React142__default.useMemo(() => {
64991
+ const resolvedAssignedLineIds = React143__default.useMemo(() => {
64622
64992
  if (isSuperAdmin) return [];
64623
64993
  if (scopedLineIds.length > 0) return scopedLineIds;
64624
64994
  if (lineIds && lineIds.length > 0) return lineIds;
64625
64995
  if (isStrictLineScopedRole && hasCanonicalScope) return [];
64626
64996
  return [];
64627
64997
  }, [isSuperAdmin, scopedLineIds, lineIds, isStrictLineScopedRole, hasCanonicalScope]);
64628
- const assignedLineIdSet = React142__default.useMemo(
64998
+ const assignedLineIdSet = React143__default.useMemo(
64629
64999
  () => new Set(resolvedAssignedLineIds),
64630
65000
  [resolvedAssignedLineIds]
64631
65001
  );
64632
- const metricsLineIds = React142__default.useMemo(() => {
65002
+ const metricsLineIds = React143__default.useMemo(() => {
64633
65003
  if (isSuperAdmin) {
64634
65004
  return lineIds ?? [];
64635
65005
  }
64636
65006
  return resolvedAssignedLineIds;
64637
65007
  }, [isSuperAdmin, lineIds, resolvedAssignedLineIds]);
64638
65008
  const assignedLineIdsForLeaderboard = isSuperAdmin ? void 0 : resolvedAssignedLineIds;
64639
- const leaderboardLinesForView = React142__default.useMemo(() => {
65009
+ const leaderboardLinesForView = React143__default.useMemo(() => {
64640
65010
  const targetMode = viewType === "machine" ? "uptime" : "output";
64641
65011
  return leaderboardLines.filter((line) => (line.monitoring_mode ?? "output") === targetMode);
64642
65012
  }, [leaderboardLines, viewType]);
64643
- const linesForView = React142__default.useMemo(() => {
65013
+ const linesForView = React143__default.useMemo(() => {
64644
65014
  const targetMode = viewType === "machine" ? "uptime" : "output";
64645
65015
  return lines.filter((line) => (line.monitoring_mode ?? "output") === targetMode);
64646
65016
  }, [lines, viewType]);
64647
- const relevantLinesForMode = React142__default.useMemo(() => {
65017
+ const relevantLinesForMode = React143__default.useMemo(() => {
64648
65018
  if (activeTab === "leaderboard") {
64649
65019
  return leaderboardLines.length > 0 ? leaderboardLines : lines;
64650
65020
  }
64651
65021
  return lines;
64652
65022
  }, [activeTab, leaderboardLines, lines]);
64653
- const { hasUptime, hasOutput } = React142__default.useMemo(() => {
65023
+ const { hasUptime, hasOutput } = React143__default.useMemo(() => {
64654
65024
  let uptime = false;
64655
65025
  let output = false;
64656
65026
  for (const line of relevantLinesForMode) {
@@ -64675,14 +65045,14 @@ var KPIsOverviewView = ({
64675
65045
  const currentShiftDetails = getCurrentShift(configuredTimezone, shiftConfig);
64676
65046
  const currentShiftDate = currentShiftDetails.date;
64677
65047
  const currentShiftId = currentShiftDetails.shiftId;
64678
- const activeFiltersCount = React142__default.useMemo(() => {
65048
+ const activeFiltersCount = React143__default.useMemo(() => {
64679
65049
  let count = 0;
64680
65050
  if (selectedLeaderboardShiftId !== currentShiftId) {
64681
65051
  count++;
64682
65052
  }
64683
65053
  return count;
64684
65054
  }, [selectedLeaderboardShiftId, currentShiftId]);
64685
- const clearFilters = React142__default.useCallback(() => {
65055
+ const clearFilters = React143__default.useCallback(() => {
64686
65056
  setSelectedLeaderboardShiftId(currentShiftId);
64687
65057
  }, [currentShiftId]);
64688
65058
  useEffect(() => {
@@ -64696,11 +65066,11 @@ var KPIsOverviewView = ({
64696
65066
  document.addEventListener("mousedown", handleClickOutside);
64697
65067
  return () => document.removeEventListener("mousedown", handleClickOutside);
64698
65068
  }, []);
64699
- const shiftEndDate = React142__default.useMemo(
65069
+ const shiftEndDate = React143__default.useMemo(
64700
65070
  () => getShiftEndDate(currentShiftDetails, configuredTimezone),
64701
65071
  [currentShiftDetails, configuredTimezone]
64702
65072
  );
64703
- const leaderboardShiftOptions = React142__default.useMemo(() => {
65073
+ const leaderboardShiftOptions = React143__default.useMemo(() => {
64704
65074
  if (shiftConfig?.shifts && shiftConfig.shifts.length > 0) {
64705
65075
  return shiftConfig.shifts.map((shift) => ({
64706
65076
  id: shift.shiftId,
@@ -64780,15 +65150,15 @@ var KPIsOverviewView = ({
64780
65150
  lineId: factoryViewId,
64781
65151
  userAccessibleLineIds: metricsLineIds
64782
65152
  });
64783
- const defaultKPIs = React142__default.useMemo(() => createDefaultKPIs(), []);
64784
- const kpisByLineId = React142__default.useMemo(() => {
65153
+ const defaultKPIs = React143__default.useMemo(() => createDefaultKPIs(), []);
65154
+ const kpisByLineId = React143__default.useMemo(() => {
64785
65155
  const map = /* @__PURE__ */ new Map();
64786
65156
  lineMetrics.forEach((row) => {
64787
65157
  if (row?.line_id) map.set(row.line_id, buildKPIsFromLineMetricsRow(row));
64788
65158
  });
64789
65159
  return map;
64790
65160
  }, [lineMetrics]);
64791
- const supervisorLineIds = React142__default.useMemo(
65161
+ const supervisorLineIds = React143__default.useMemo(
64792
65162
  () => (leaderboardLines.length > 0 ? leaderboardLines : lines).map((l) => l.id),
64793
65163
  [leaderboardLines, lines]
64794
65164
  );
@@ -65628,39 +65998,6 @@ var KPIsOverviewView = ({
65628
65998
  ] });
65629
65999
  };
65630
66000
  var KPIsOverviewView_default = KPIsOverviewView;
65631
- var toFiniteNumber = (value) => {
65632
- if (typeof value === "number" && Number.isFinite(value)) return value;
65633
- if (typeof value === "string" && value.trim() !== "") {
65634
- const parsed = Number(value);
65635
- return Number.isFinite(parsed) ? parsed : null;
65636
- }
65637
- return null;
65638
- };
65639
- var getCycleRatio = (workspace) => {
65640
- const idealCycleTime = toFiniteNumber(workspace.ideal_cycle_time);
65641
- const avgCycleTime = toFiniteNumber(workspace.avg_cycle_time);
65642
- if (idealCycleTime === null || avgCycleTime === null || idealCycleTime <= 0 || avgCycleTime <= 0) {
65643
- return null;
65644
- }
65645
- return idealCycleTime / avgCycleTime;
65646
- };
65647
- var formatCycleTimeValue = (value) => {
65648
- const numericValue = toFiniteNumber(value);
65649
- if (numericValue === null || numericValue <= 0) return "--";
65650
- return `${numericValue.toFixed(1)}s`;
65651
- };
65652
- var CycleTimeComparison = memo$1(({
65653
- workspace
65654
- }) => {
65655
- const averageValue = formatCycleTimeValue(workspace.avg_cycle_time);
65656
- const standardValue = formatCycleTimeValue(workspace.ideal_cycle_time);
65657
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 tabular-nums", children: [
65658
- /* @__PURE__ */ jsx("span", { className: "font-semibold text-gray-900", children: averageValue }),
65659
- /* @__PURE__ */ jsx("span", { className: "text-gray-400 font-normal", children: "/" }),
65660
- /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-500", children: standardValue })
65661
- ] });
65662
- }, (prevProps, nextProps) => prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.ideal_cycle_time === nextProps.workspace.ideal_cycle_time);
65663
- CycleTimeComparison.displayName = "CycleTimeComparison";
65664
66001
  var IsolatedTimer = memo$1(() => {
65665
66002
  return /* @__PURE__ */ jsx(ISTTimer_default, {});
65666
66003
  });
@@ -65912,7 +66249,7 @@ var LeaderboardDetailView = memo$1(({
65912
66249
  return () => document.removeEventListener("mousedown", handleClickOutside);
65913
66250
  }, []);
65914
66251
  const [isMobile, setIsMobile] = useState(false);
65915
- React142__default.useEffect(() => {
66252
+ React143__default.useEffect(() => {
65916
66253
  const checkMobile = () => setIsMobile(window.innerWidth < 640);
65917
66254
  checkMobile();
65918
66255
  window.addEventListener("resize", checkMobile);
@@ -66202,10 +66539,25 @@ var LeaderboardDetailView = memo$1(({
66202
66539
  setTodayLoading(true);
66203
66540
  setTodayError(null);
66204
66541
  try {
66205
- 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,
66206
66550
  date: todayDate,
66207
- shiftId: todayShiftId
66551
+ shift_id: todayShiftId.toString()
66208
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 || [];
66209
66561
  if (todayRequestKeyRef.current !== requestKey) {
66210
66562
  return;
66211
66563
  }
@@ -66222,7 +66574,15 @@ var LeaderboardDetailView = memo$1(({
66222
66574
  setTodayLoading(false);
66223
66575
  }
66224
66576
  }
66225
- }, [fetchLeaderboardEntries, mapEntriesToWorkspaces, todayDate, todayShiftId, lineKey]);
66577
+ }, [
66578
+ configuredLineIds,
66579
+ entityConfig.companyId,
66580
+ mapEntriesToWorkspaces,
66581
+ supabase,
66582
+ todayDate,
66583
+ todayShiftId,
66584
+ lineKey
66585
+ ]);
66226
66586
  const queueTodayLeaderboardRefresh = useCallback(() => {
66227
66587
  if (leaderboardUpdateQueuedRef.current) return;
66228
66588
  leaderboardUpdateQueuedRef.current = true;
@@ -68308,7 +68668,7 @@ var ShiftsView = ({
68308
68668
  ] })
68309
68669
  ] });
68310
68670
  };
68311
- var AuthenticatedShiftsView = withAuth(React142__default.memo(ShiftsView));
68671
+ var AuthenticatedShiftsView = withAuth(React143__default.memo(ShiftsView));
68312
68672
  var ShiftsView_default = ShiftsView;
68313
68673
 
68314
68674
  // src/views/TargetsView.utils.ts
@@ -70010,7 +70370,7 @@ var TargetsView = ({
70010
70370
  };
70011
70371
  var TargetsViewWithDisplayNames = withAllWorkspaceDisplayNames(TargetsView);
70012
70372
  var TargetsView_default = TargetsViewWithDisplayNames;
70013
- var AuthenticatedTargetsView = withAuth(React142__default.memo(TargetsViewWithDisplayNames));
70373
+ var AuthenticatedTargetsView = withAuth(React143__default.memo(TargetsViewWithDisplayNames));
70014
70374
  function useTimezone(options = {}) {
70015
70375
  const dashboardConfig = useDashboardConfig();
70016
70376
  const workspaceConfig = useWorkspaceConfig();
@@ -73429,7 +73789,7 @@ function BottleneckClipsView({
73429
73789
  ) })
73430
73790
  ] }) });
73431
73791
  }
73432
- var AuthenticatedBottleneckClipsView = withAuth(React142__default.memo(BottleneckClipsView));
73792
+ var AuthenticatedBottleneckClipsView = withAuth(React143__default.memo(BottleneckClipsView));
73433
73793
  var BottleneckClipsView_default = BottleneckClipsView;
73434
73794
 
73435
73795
  // src/lib/services/ticketService.ts
@@ -73459,8 +73819,8 @@ var TicketService = class {
73459
73819
  return response;
73460
73820
  } catch (error) {
73461
73821
  lastError = error instanceof Error ? error : new Error(String(error));
73462
- 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");
73463
- 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) {
73464
73824
  throw lastError;
73465
73825
  }
73466
73826
  const delay2 = 1e3 * Math.pow(2, attempt);
@@ -73475,69 +73835,78 @@ var TicketService = class {
73475
73835
  * Uses the user's JWT access token from Supabase session (NOT the anon key)
73476
73836
  */
73477
73837
  async fetchWithAuth(url, options = {}) {
73478
- if (!this.supabaseClient) {
73479
- throw new Error("Supabase client not initialized. Please provide a Supabase client to TicketService.");
73480
- }
73481
- const { data: { session }, error: sessionError } = await this.supabaseClient.auth.getSession();
73482
- if (sessionError) {
73483
- console.error("Session error:", sessionError);
73484
- throw new Error("Failed to get authentication session. Please log in.");
73485
- }
73486
- if (!session) {
73487
- console.error("No session found. User must be logged in.");
73488
- throw new Error("User not authenticated. Please log in.");
73489
- }
73490
- if (!session.access_token) {
73491
- console.error("Session exists but no access_token found");
73492
- throw new Error("Invalid session. Please log in again.");
73493
- }
73494
- const token = session.access_token;
73495
- if (process.env.NODE_ENV === "development") {
73496
- console.log("[TicketService] Using JWT token (first 20 chars):", token.substring(0, 20) + "...");
73497
- console.log("[TicketService] Token is NOT the anon key - it is the user JWT from session.access_token");
73498
- }
73499
- const headers = {
73500
- "Content-Type": "application/json",
73501
- ...options.headers,
73502
- "Authorization": `Bearer ${token}`
73503
- // This is the USER's JWT, not the anon key
73504
- };
73505
- const response = await this.fetchWithRetry(url, {
73506
- ...options,
73507
- headers
73508
- });
73509
- if (response.status === 401) {
73510
- console.error("401 Unauthorized - Token expired or invalid");
73511
- throw new Error("Authentication failed. Token expired or invalid. Please log in again.");
73512
- }
73513
- if (response.status === 403) {
73514
- console.error("403 Forbidden - User does not have permission");
73515
- throw new Error("Access denied. You do not have permission to access this resource.");
73516
- }
73517
- if (response.status === 500) {
73518
- console.error("500 Internal Server Error - Backend error");
73519
- let errorDetail = "Internal server error occurred.";
73520
- try {
73521
- const errorData = await response.text();
73522
- console.error("Backend error details:", errorData);
73523
- errorDetail = errorData || errorDetail;
73524
- } catch (e) {
73838
+ try {
73839
+ if (!this.supabaseClient) {
73840
+ throw new Error("Supabase client not initialized. Please provide a Supabase client to TicketService.");
73525
73841
  }
73526
- throw new Error(`Backend error: ${errorDetail}`);
73527
- }
73528
- if (!response.ok) {
73529
- console.error(`HTTP ${response.status} - ${response.statusText}`);
73530
- let errorDetail = response.statusText;
73531
- try {
73532
- const errorData = await response.json();
73533
- if (errorData.detail) {
73534
- 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) {
73535
73885
  }
73536
- } 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}`);
73537
73899
  }
73538
- 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;
73539
73909
  }
73540
- return response;
73541
73910
  }
73542
73911
  /**
73543
73912
  * Get tickets with filters and pagination
@@ -74260,7 +74629,7 @@ Please ensure:
74260
74629
  )
74261
74630
  ] });
74262
74631
  }
74263
- var AuthenticatedTicketsView = withAuth(React142__default.memo(TicketsView));
74632
+ var AuthenticatedTicketsView = withAuth(React143__default.memo(TicketsView));
74264
74633
  var TicketsView_default = TicketsView;
74265
74634
 
74266
74635
  // src/lib/utils/improvementDisplay.ts
@@ -75231,7 +75600,7 @@ var ImprovementCenterView = () => {
75231
75600
  setSelectedMemberId("all");
75232
75601
  }
75233
75602
  }, [memberOptions, selectedMemberId]);
75234
- const getRecommendationDisplayMetadata = React142__default.useCallback((rec) => {
75603
+ const getRecommendationDisplayMetadata = React143__default.useCallback((rec) => {
75235
75604
  const supervisors = rec.line_id ? supervisorsByLineId.get(rec.line_id) || [] : [];
75236
75605
  return getImprovementDisplayMetadata({
75237
75606
  location: rec.location,
@@ -75705,7 +76074,7 @@ var ThreadSidebar = ({
75705
76074
  ] }) })
75706
76075
  ] });
75707
76076
  };
75708
- var ProfilePicture = React142__default.memo(({
76077
+ var ProfilePicture = React143__default.memo(({
75709
76078
  alt = "Axel",
75710
76079
  className = "",
75711
76080
  size = "md",
@@ -78230,7 +78599,7 @@ var OverviewImprovementsSkeleton = () => /* @__PURE__ */ jsx("div", { className:
78230
78599
  ] }),
78231
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" }) })
78232
78601
  ] }, index)) });
78233
- var OperationsOverviewHeader = React142__default.memo(({
78602
+ var OperationsOverviewHeader = React143__default.memo(({
78234
78603
  dateRange,
78235
78604
  displayDateRange,
78236
78605
  trendMode,
@@ -78250,65 +78619,65 @@ var OperationsOverviewHeader = React142__default.memo(({
78250
78619
  bumpRenderCounter();
78251
78620
  const subtitleRange = displayDateRange || dateRange;
78252
78621
  const showLiveShiftMeta = isLiveScope && trendMode !== "all";
78253
- const liveShiftLabel = React142__default.useMemo(
78622
+ const liveShiftLabel = React143__default.useMemo(
78254
78623
  () => normalizeShiftLabel(liveShiftName, trendMode),
78255
78624
  [liveShiftName, trendMode]
78256
78625
  );
78257
- const liveShiftIcon = React142__default.useMemo(
78626
+ const liveShiftIcon = React143__default.useMemo(
78258
78627
  () => getShiftIcon(liveShiftName, trendMode),
78259
78628
  [liveShiftName, trendMode]
78260
78629
  );
78261
- const [isFilterOpen, setIsFilterOpen] = React142__default.useState(false);
78262
- const [isLinesDropdownOpen, setIsLinesDropdownOpen] = React142__default.useState(false);
78263
- const filterRef = React142__default.useRef(null);
78264
- const filterButtonRef = React142__default.useRef(null);
78265
- const mobileFilterButtonRef = React142__default.useRef(null);
78266
- const linesDropdownRef = React142__default.useRef(null);
78267
- 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(() => {
78268
78637
  if (subtitleRange.startKey === subtitleRange.endKey) {
78269
78638
  return format(parseDateKeyToDate(subtitleRange.startKey), "do MMM, yyyy");
78270
78639
  }
78271
78640
  return `${format(parseDateKeyToDate(subtitleRange.startKey), "do MMM")} - ${format(parseDateKeyToDate(subtitleRange.endKey), "do MMM, yyyy")}`;
78272
78641
  }, [subtitleRange.endKey, subtitleRange.startKey]);
78273
- const desktopSubtitle = React142__default.useMemo(() => {
78642
+ const desktopSubtitle = React143__default.useMemo(() => {
78274
78643
  if (subtitleRange.startKey === subtitleRange.endKey) {
78275
78644
  return format(parseDateKeyToDate(subtitleRange.startKey), "do MMMM, yyyy");
78276
78645
  }
78277
78646
  return `${format(parseDateKeyToDate(subtitleRange.startKey), "do MMMM, yyyy")} - ${format(parseDateKeyToDate(subtitleRange.endKey), "do MMMM, yyyy")}`;
78278
78647
  }, [subtitleRange.endKey, subtitleRange.startKey]);
78279
- const availableLineIds = React142__default.useMemo(
78648
+ const availableLineIds = React143__default.useMemo(
78280
78649
  () => lineOptions.map((line) => line.id),
78281
78650
  [lineOptions]
78282
78651
  );
78283
- const selectedLineIdSet = React142__default.useMemo(
78652
+ const selectedLineIdSet = React143__default.useMemo(
78284
78653
  () => new Set(selectedLineIds),
78285
78654
  [selectedLineIds]
78286
78655
  );
78287
- const isAllLinesSelected = React142__default.useMemo(() => {
78656
+ const isAllLinesSelected = React143__default.useMemo(() => {
78288
78657
  if (availableLineIds.length === 0) return true;
78289
78658
  return availableLineIds.every((lineId) => selectedLineIdSet.has(lineId));
78290
78659
  }, [availableLineIds, selectedLineIdSet]);
78291
- const activeFilterCount = React142__default.useMemo(() => {
78660
+ const activeFilterCount = React143__default.useMemo(() => {
78292
78661
  let count = 0;
78293
78662
  if (trendMode !== "all") count += 1;
78294
78663
  if (selectedSupervisorId !== "all") count += 1;
78295
78664
  if (!isAllLinesSelected) count += 1;
78296
78665
  return count;
78297
78666
  }, [isAllLinesSelected, selectedSupervisorId, trendMode]);
78298
- const handleFilterToggle = React142__default.useCallback(() => {
78667
+ const handleFilterToggle = React143__default.useCallback(() => {
78299
78668
  trackCoreEvent("Operations Overview Filter Toggled", {
78300
78669
  action: !isFilterOpen ? "open" : "close"
78301
78670
  });
78302
78671
  setIsFilterOpen((previous) => !previous);
78303
78672
  }, [isFilterOpen]);
78304
- const handleTrendModeChange = React142__default.useCallback((event) => {
78673
+ const handleTrendModeChange = React143__default.useCallback((event) => {
78305
78674
  const nextMode = event.target.value;
78306
78675
  trackCoreEvent("Operations Overview Shift Filter Changed", {
78307
78676
  shift_mode: nextMode
78308
78677
  });
78309
78678
  onTrendModeChange(nextMode);
78310
78679
  }, [onTrendModeChange]);
78311
- const handleAllLinesToggle = React142__default.useCallback(() => {
78680
+ const handleAllLinesToggle = React143__default.useCallback(() => {
78312
78681
  trackCoreEvent("Operations Overview Line Filter Changed", {
78313
78682
  selected_line_ids: availableLineIds,
78314
78683
  selected_line_count: availableLineIds.length,
@@ -78316,7 +78685,7 @@ var OperationsOverviewHeader = React142__default.memo(({
78316
78685
  });
78317
78686
  onSelectedLineIdsChange(availableLineIds);
78318
78687
  }, [availableLineIds, onSelectedLineIdsChange]);
78319
- const handleSupervisorChange = React142__default.useCallback((event) => {
78688
+ const handleSupervisorChange = React143__default.useCallback((event) => {
78320
78689
  const supervisorId = event.target.value;
78321
78690
  const selectedSupervisor = supervisorOptions.find((option) => option.id === supervisorId);
78322
78691
  trackCoreEvent("Operations Overview Supervisor Filter Changed", {
@@ -78327,7 +78696,7 @@ var OperationsOverviewHeader = React142__default.memo(({
78327
78696
  });
78328
78697
  onSelectedSupervisorIdChange(supervisorId);
78329
78698
  }, [availableLineIds, onSelectedSupervisorIdChange, supervisorOptions]);
78330
- const handleLineToggle = React142__default.useCallback((lineId) => {
78699
+ const handleLineToggle = React143__default.useCallback((lineId) => {
78331
78700
  const current = new Set(selectedLineIds);
78332
78701
  if (current.has(lineId)) {
78333
78702
  if (current.size <= 1) return;
@@ -78343,13 +78712,13 @@ var OperationsOverviewHeader = React142__default.memo(({
78343
78712
  });
78344
78713
  onSelectedLineIdsChange(next);
78345
78714
  }, [availableLineIds, onSelectedLineIdsChange, selectedLineIds]);
78346
- const handleClearAllFilters = React142__default.useCallback(() => {
78715
+ const handleClearAllFilters = React143__default.useCallback(() => {
78347
78716
  onTrendModeChange("all");
78348
78717
  onSelectedSupervisorIdChange("all");
78349
78718
  onSelectedLineIdsChange(availableLineIds);
78350
78719
  setIsFilterOpen(false);
78351
78720
  }, [availableLineIds, onSelectedLineIdsChange, onSelectedSupervisorIdChange, onTrendModeChange]);
78352
- React142__default.useEffect(() => {
78721
+ React143__default.useEffect(() => {
78353
78722
  const handleClickOutside = (event) => {
78354
78723
  const target = event.target;
78355
78724
  if (filterRef.current && !filterRef.current.contains(target) && filterButtonRef.current && !filterButtonRef.current.contains(target) && mobileFilterButtonRef.current && !mobileFilterButtonRef.current.contains(target)) {
@@ -78588,12 +78957,12 @@ var OperationsOverviewHeader = React142__default.memo(({
78588
78957
  ] }) });
78589
78958
  });
78590
78959
  OperationsOverviewHeader.displayName = "OperationsOverviewHeader";
78591
- var OverviewSummaryCards = React142__default.memo(({ store }) => {
78960
+ var OverviewSummaryCards = React143__default.memo(({ store }) => {
78592
78961
  bumpRenderCounter();
78593
78962
  const scope = useOperationsOverviewScope(store);
78594
78963
  const snapshot = useOperationsOverviewSnapshot(store);
78595
78964
  const showSnapshotSkeleton = snapshot.loading && !snapshot.hasLoadedOnce;
78596
- const comparisonLabel = React142__default.useMemo(() => {
78965
+ const comparisonLabel = React143__default.useMemo(() => {
78597
78966
  return formatComparisonWindow({
78598
78967
  currentDayCount: scope.current_range?.day_count ?? null,
78599
78968
  previousDayCount: scope.previous_range?.day_count ?? null,
@@ -78606,27 +78975,27 @@ var OverviewSummaryCards = React142__default.memo(({ store }) => {
78606
78975
  scope.previous_range?.day_count,
78607
78976
  scope.shift_mode
78608
78977
  ]);
78609
- const [isIdleContributorsOpen, setIsIdleContributorsOpen] = React142__default.useState(false);
78610
- const [isIdleContributorsPinned, setIsIdleContributorsPinned] = React142__default.useState(false);
78611
- const idleContributorsRef = React142__default.useRef(null);
78612
- 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(() => {
78613
78982
  return buildDeltaBadge(snapshot.data.summary.plant_efficiency?.delta_pp, {
78614
78983
  positiveIsGood: true,
78615
78984
  formatter: (value) => `${value >= 0 ? "+" : ""}${roundOne(value)}%`,
78616
78985
  comparisonLabel
78617
78986
  });
78618
78987
  }, [comparisonLabel, snapshot.data.summary.plant_efficiency?.delta_pp]);
78619
- const idleBadge = React142__default.useMemo(() => {
78988
+ const idleBadge = React143__default.useMemo(() => {
78620
78989
  return buildDeltaBadge(snapshot.data.summary.avg_idle_per_workstation?.delta_seconds, {
78621
78990
  positiveIsGood: false,
78622
78991
  formatter: (value) => formatSignedIdleDuration(value),
78623
78992
  comparisonLabel
78624
78993
  });
78625
78994
  }, [comparisonLabel, snapshot.data.summary.avg_idle_per_workstation?.delta_seconds]);
78626
- const canInspectIdleContributors = React142__default.useMemo(() => {
78995
+ const canInspectIdleContributors = React143__default.useMemo(() => {
78627
78996
  return !showSnapshotSkeleton && snapshot.data.summary.avg_idle_per_workstation?.current_seconds !== null && snapshot.data.summary.avg_idle_per_workstation?.current_seconds !== void 0;
78628
78997
  }, [showSnapshotSkeleton, snapshot.data.summary.avg_idle_per_workstation?.current_seconds]);
78629
- const idleTopContributors = React142__default.useMemo(() => {
78998
+ const idleTopContributors = React143__default.useMemo(() => {
78630
78999
  return (snapshot.data.summary.avg_idle_per_workstation?.top_contributors || []).map((item) => ({
78631
79000
  workspaceId: item.workspace_id || "",
78632
79001
  workspaceName: item.workspace_name?.trim() || item.workspace_id || "Unknown",
@@ -78634,14 +79003,14 @@ var OverviewSummaryCards = React142__default.memo(({ store }) => {
78634
79003
  avgIdleSeconds: toNumber3(item.avg_idle_seconds)
78635
79004
  })).slice(0, 5);
78636
79005
  }, [snapshot.data.summary.avg_idle_per_workstation?.top_contributors]);
78637
- const showIdleContributorLineNames = React142__default.useMemo(() => {
79006
+ const showIdleContributorLineNames = React143__default.useMemo(() => {
78638
79007
  return (scope.line_count ?? 0) > 1;
78639
79008
  }, [scope.line_count]);
78640
- const closeIdleContributors = React142__default.useCallback(() => {
79009
+ const closeIdleContributors = React143__default.useCallback(() => {
78641
79010
  setIsIdleContributorsOpen(false);
78642
79011
  setIsIdleContributorsPinned(false);
78643
79012
  }, []);
78644
- const handleIdleContributorsToggle = React142__default.useCallback(() => {
79013
+ const handleIdleContributorsToggle = React143__default.useCallback(() => {
78645
79014
  if (!canInspectIdleContributors) return;
78646
79015
  setIsIdleContributorsPinned((previous) => {
78647
79016
  const next = !previous;
@@ -78649,7 +79018,7 @@ var OverviewSummaryCards = React142__default.memo(({ store }) => {
78649
79018
  return next;
78650
79019
  });
78651
79020
  }, [canInspectIdleContributors]);
78652
- const handleIdleContributorsKeyDown = React142__default.useCallback((event) => {
79021
+ const handleIdleContributorsKeyDown = React143__default.useCallback((event) => {
78653
79022
  if (!canInspectIdleContributors) return;
78654
79023
  if (event.key === "Enter" || event.key === " ") {
78655
79024
  event.preventDefault();
@@ -78661,11 +79030,11 @@ var OverviewSummaryCards = React142__default.memo(({ store }) => {
78661
79030
  closeIdleContributors();
78662
79031
  }
78663
79032
  }, [canInspectIdleContributors, closeIdleContributors, handleIdleContributorsToggle]);
78664
- React142__default.useEffect(() => {
79033
+ React143__default.useEffect(() => {
78665
79034
  setIsIdleContributorsOpen(false);
78666
79035
  setIsIdleContributorsPinned(false);
78667
79036
  }, [scope.comparison_strategy, scope.current_range?.start_date, scope.current_range?.end_date, scope.line_count, scope.shift_mode]);
78668
- React142__default.useEffect(() => {
79037
+ React143__default.useEffect(() => {
78669
79038
  if (!isIdleContributorsOpen) return void 0;
78670
79039
  const handleClickOutside = (event) => {
78671
79040
  if (!isIdleContributorsPinned) return;
@@ -78803,7 +79172,7 @@ var OverviewSummaryCards = React142__default.memo(({ store }) => {
78803
79172
  ] });
78804
79173
  });
78805
79174
  OverviewSummaryCards.displayName = "OverviewSummaryCards";
78806
- var PoorestPerformersCard = React142__default.memo(({
79175
+ var PoorestPerformersCard = React143__default.memo(({
78807
79176
  store,
78808
79177
  supervisorsByLineId,
78809
79178
  onViewAll,
@@ -78812,9 +79181,9 @@ var PoorestPerformersCard = React142__default.memo(({
78812
79181
  bumpRenderCounter();
78813
79182
  const scope = useOperationsOverviewScope(store);
78814
79183
  const snapshot = useOperationsOverviewSnapshot(store);
78815
- const [poorestLineMode, setPoorestLineMode] = React142__default.useState("output");
79184
+ const [poorestLineMode, setPoorestLineMode] = React143__default.useState("output");
78816
79185
  const availableLineModes = scope.available_line_modes;
78817
- React142__default.useEffect(() => {
79186
+ React143__default.useEffect(() => {
78818
79187
  const hasOutput = !!availableLineModes?.has_output;
78819
79188
  const hasUptime = !!availableLineModes?.has_uptime;
78820
79189
  if (hasOutput && !hasUptime && poorestLineMode !== "output") {
@@ -78823,7 +79192,7 @@ var PoorestPerformersCard = React142__default.memo(({
78823
79192
  setPoorestLineMode("uptime");
78824
79193
  }
78825
79194
  }, [availableLineModes?.has_output, availableLineModes?.has_uptime, poorestLineMode]);
78826
- const comparisonLabel = React142__default.useMemo(() => {
79195
+ const comparisonLabel = React143__default.useMemo(() => {
78827
79196
  return formatComparisonWindow({
78828
79197
  currentDayCount: scope.current_range?.day_count ?? null,
78829
79198
  previousDayCount: scope.previous_range?.day_count ?? null,
@@ -78837,7 +79206,7 @@ var PoorestPerformersCard = React142__default.memo(({
78837
79206
  scope.shift_mode
78838
79207
  ]);
78839
79208
  const showSnapshotSkeleton = snapshot.loading && !snapshot.hasLoadedOnce;
78840
- const mergedPoorestLines = React142__default.useMemo(() => {
79209
+ const mergedPoorestLines = React143__default.useMemo(() => {
78841
79210
  const rows = snapshot.data.poorest_lines?.[poorestLineMode] || [];
78842
79211
  return rows.slice(0, 3).map((line) => {
78843
79212
  const lineId = line.line_id || "";
@@ -78856,7 +79225,7 @@ var PoorestPerformersCard = React142__default.memo(({
78856
79225
  }, [poorestLineMode, snapshot.data.poorest_lines, supervisorsByLineId]);
78857
79226
  const showPoorestModeToggle = !!availableLineModes?.has_output && !!availableLineModes?.has_uptime;
78858
79227
  const poorestMetricLabel = poorestLineMode === "uptime" ? "Uptime" : "Efficiency";
78859
- const handlePoorestLineModeChange = React142__default.useCallback((mode) => {
79228
+ const handlePoorestLineModeChange = React143__default.useCallback((mode) => {
78860
79229
  trackCoreEvent("Operations Overview Poorest Line Mode Changed", { mode });
78861
79230
  setPoorestLineMode(mode);
78862
79231
  }, []);
@@ -78942,14 +79311,14 @@ var PoorestPerformersCard = React142__default.memo(({
78942
79311
  ] });
78943
79312
  });
78944
79313
  PoorestPerformersCard.displayName = "PoorestPerformersCard";
78945
- var IdleBreakdownCard = React142__default.memo(({
79314
+ var IdleBreakdownCard = React143__default.memo(({
78946
79315
  store,
78947
79316
  scopedLineCount
78948
79317
  }) => {
78949
79318
  bumpRenderCounter();
78950
79319
  const idle = useOperationsOverviewIdle(store);
78951
79320
  const showInitialSkeleton = idle.loading && idle.lastUpdated === null;
78952
- const idleBreakdown = React142__default.useMemo(() => {
79321
+ const idleBreakdown = React143__default.useMemo(() => {
78953
79322
  return idle.data.map((item) => ({
78954
79323
  name: item.display_name?.trim() || item.reason?.trim() || "Unknown",
78955
79324
  reasonKey: item.reason_key?.trim() || item.reason?.trim() || "unknown",
@@ -78968,7 +79337,7 @@ var IdleBreakdownCard = React142__default.memo(({
78968
79337
  }))
78969
79338
  })).filter((item) => item.value > 0);
78970
79339
  }, [idle.data]);
78971
- const showIdleModuleNotEnabledState = React142__default.useMemo(() => {
79340
+ const showIdleModuleNotEnabledState = React143__default.useMemo(() => {
78972
79341
  const enabledLineCount = idle.scope.idle_time_vlm_enabled_line_count;
78973
79342
  return !showInitialSkeleton && scopedLineCount > 0 && typeof enabledLineCount === "number" && enabledLineCount === 0;
78974
79343
  }, [idle.scope.idle_time_vlm_enabled_line_count, scopedLineCount, showInitialSkeleton]);
@@ -78989,7 +79358,7 @@ var IdleBreakdownCard = React142__default.memo(({
78989
79358
  ] });
78990
79359
  });
78991
79360
  IdleBreakdownCard.displayName = "IdleBreakdownCard";
78992
- var EfficiencyTrendCard = React142__default.memo(({
79361
+ var EfficiencyTrendCard = React143__default.memo(({
78993
79362
  store,
78994
79363
  dateRange,
78995
79364
  appTimezone,
@@ -78997,14 +79366,14 @@ var EfficiencyTrendCard = React142__default.memo(({
78997
79366
  }) => {
78998
79367
  bumpRenderCounter();
78999
79368
  const trend = useOperationsOverviewTrend(store);
79000
- const currentWeekRange = React142__default.useMemo(
79369
+ const currentWeekRange = React143__default.useMemo(
79001
79370
  () => getCurrentWeekToDateRange(appTimezone),
79002
79371
  [appTimezone]
79003
79372
  );
79004
79373
  const isCurrentWeekToDateRange = dateRange.startKey === currentWeekRange.startKey && dateRange.endKey === currentWeekRange.endKey;
79005
79374
  const showInitialSkeleton = trend.loading && trend.lastUpdated === null;
79006
79375
  const isHourlyTrend = trend.data.granularity === "hour";
79007
- const trendData = React142__default.useMemo(() => {
79376
+ const trendData = React143__default.useMemo(() => {
79008
79377
  if (isHourlyTrend) {
79009
79378
  return (trend.data.points || []).map((point, index) => ({
79010
79379
  name: (() => {
@@ -79076,13 +79445,13 @@ var EfficiencyTrendCard = React142__default.memo(({
79076
79445
  };
79077
79446
  });
79078
79447
  }, [currentWeekRange.startKey, hourlyLabelStartTime, isCurrentWeekToDateRange, isHourlyTrend, trend.data.points]);
79079
- const trendTooltipLabelFormatter = React142__default.useCallback((label, payload) => {
79448
+ const trendTooltipLabelFormatter = React143__default.useCallback((label, payload) => {
79080
79449
  if (isHourlyTrend) return label;
79081
79450
  const dayOfWeek = payload?.[0]?.payload?.dayOfWeek;
79082
79451
  if (!dayOfWeek || typeof label !== "string") return label;
79083
79452
  return `${label} (${dayOfWeek})`;
79084
79453
  }, [isHourlyTrend]);
79085
- const trendXAxisTickFormatter = React142__default.useCallback((value, index) => {
79454
+ const trendXAxisTickFormatter = React143__default.useCallback((value, index) => {
79086
79455
  if (!isHourlyTrend) {
79087
79456
  return typeof value === "string" ? value : String(value ?? "");
79088
79457
  }
@@ -79109,7 +79478,7 @@ var EfficiencyTrendCard = React142__default.memo(({
79109
79478
  ] });
79110
79479
  });
79111
79480
  EfficiencyTrendCard.displayName = "EfficiencyTrendCard";
79112
- var TopImprovementsCard = React142__default.memo(({
79481
+ var TopImprovementsCard = React143__default.memo(({
79113
79482
  store,
79114
79483
  supervisorsByLineId,
79115
79484
  onViewAll,
@@ -79118,7 +79487,7 @@ var TopImprovementsCard = React142__default.memo(({
79118
79487
  bumpRenderCounter();
79119
79488
  const improvements = useOperationsOverviewImprovements(store);
79120
79489
  const showInitialSkeleton = improvements.loading && improvements.lastUpdated === null;
79121
- const displayImprovements = React142__default.useMemo(() => {
79490
+ const displayImprovements = React143__default.useMemo(() => {
79122
79491
  return improvements.data.map((item) => {
79123
79492
  const supervisors = item.lineId ? supervisorsByLineId.get(item.lineId) || [] : [];
79124
79493
  return {
@@ -79191,7 +79560,7 @@ var debugRefreshLog = (message, payload) => {
79191
79560
  }
79192
79561
  console.log(`[OperationsOverviewRefresh] ${message}`);
79193
79562
  };
79194
- var isAbortError = (error) => {
79563
+ var isAbortError2 = (error) => {
79195
79564
  return error instanceof DOMException && error.name === "AbortError";
79196
79565
  };
79197
79566
  var toNumber4 = (value) => {
@@ -79246,33 +79615,33 @@ var useOperationsOverviewRefresh = ({
79246
79615
  isLiveScope,
79247
79616
  enabled = true
79248
79617
  }) => {
79249
- const lineIdsKey = React142__default.useMemo(() => lineIds.join(","), [lineIds]);
79250
- const scopeSignature = React142__default.useMemo(
79618
+ const lineIdsKey = React143__default.useMemo(() => lineIds.join(","), [lineIds]);
79619
+ const scopeSignature = React143__default.useMemo(
79251
79620
  () => [companyId || "", startKey, endKey, trendMode, comparisonStrategy || "", lineIdsKey].join("::"),
79252
79621
  [companyId, comparisonStrategy, endKey, lineIdsKey, startKey, trendMode]
79253
79622
  );
79254
- const controllersRef = React142__default.useRef({});
79255
- const requestIdsRef = React142__default.useRef({
79623
+ const controllersRef = React143__default.useRef({});
79624
+ const requestIdsRef = React143__default.useRef({
79256
79625
  snapshot: 0,
79257
79626
  trend: 0,
79258
79627
  idle: 0,
79259
79628
  improvements: 0
79260
79629
  });
79261
- const intervalRef = React142__default.useRef(null);
79262
- const isPageActiveRef = React142__default.useRef(true);
79263
- const lastResumeRefreshAtRef = React142__default.useRef(0);
79264
- 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(() => {
79265
79634
  Object.values(controllersRef.current).forEach((controller) => {
79266
79635
  controller?.abort();
79267
79636
  });
79268
79637
  controllersRef.current = {};
79269
79638
  }, []);
79270
- React142__default.useEffect(() => {
79639
+ React143__default.useEffect(() => {
79271
79640
  return () => {
79272
79641
  abortAll();
79273
79642
  };
79274
79643
  }, [abortAll]);
79275
- const getIsPageActive = React142__default.useCallback(() => {
79644
+ const getIsPageActive = React143__default.useCallback(() => {
79276
79645
  if (typeof document === "undefined") {
79277
79646
  return true;
79278
79647
  }
@@ -79280,7 +79649,7 @@ var useOperationsOverviewRefresh = ({
79280
79649
  const hasFocus = typeof document.hasFocus === "function" ? document.hasFocus() : true;
79281
79650
  return isVisible && hasFocus;
79282
79651
  }, []);
79283
- const stopPolling = React142__default.useCallback((reason) => {
79652
+ const stopPolling = React143__default.useCallback((reason) => {
79284
79653
  if (intervalRef.current === null) {
79285
79654
  return;
79286
79655
  }
@@ -79288,7 +79657,7 @@ var useOperationsOverviewRefresh = ({
79288
79657
  intervalRef.current = null;
79289
79658
  debugRefreshLog("poll stopped", { reason });
79290
79659
  }, []);
79291
- const runRefresh = React142__default.useCallback(
79660
+ const runRefresh = React143__default.useCallback(
79292
79661
  async (section, begin, onSuccess, onError, request, reason) => {
79293
79662
  if (!enabled || !supabase || !companyId || lineIds.length === 0) return;
79294
79663
  const requestId = requestIdsRef.current[section] + 1;
@@ -79304,7 +79673,7 @@ var useOperationsOverviewRefresh = ({
79304
79673
  }
79305
79674
  onSuccess(response, Date.now(), reason === "live_refresh" ? "transition" : "default");
79306
79675
  } catch (error) {
79307
- if (controller.signal.aborted || requestIdsRef.current[section] !== requestId || isAbortError(error)) {
79676
+ if (controller.signal.aborted || requestIdsRef.current[section] !== requestId || isAbortError2(error)) {
79308
79677
  return;
79309
79678
  }
79310
79679
  onError(error instanceof Error ? error.message : `Failed to refresh ${section}`);
@@ -79312,7 +79681,7 @@ var useOperationsOverviewRefresh = ({
79312
79681
  },
79313
79682
  [companyId, enabled, lineIds.length, supabase]
79314
79683
  );
79315
- const refreshSnapshot = React142__default.useCallback(
79684
+ const refreshSnapshot = React143__default.useCallback(
79316
79685
  async (reason) => {
79317
79686
  await runRefresh(
79318
79687
  "snapshot",
@@ -79344,7 +79713,7 @@ var useOperationsOverviewRefresh = ({
79344
79713
  },
79345
79714
  [companyId, comparisonStrategy, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
79346
79715
  );
79347
- const refreshTrend = React142__default.useCallback(
79716
+ const refreshTrend = React143__default.useCallback(
79348
79717
  async (reason) => {
79349
79718
  await runRefresh(
79350
79719
  "trend",
@@ -79373,7 +79742,7 @@ var useOperationsOverviewRefresh = ({
79373
79742
  },
79374
79743
  [companyId, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
79375
79744
  );
79376
- const refreshIdle = React142__default.useCallback(
79745
+ const refreshIdle = React143__default.useCallback(
79377
79746
  async (reason) => {
79378
79747
  await runRefresh(
79379
79748
  "idle",
@@ -79402,7 +79771,7 @@ var useOperationsOverviewRefresh = ({
79402
79771
  },
79403
79772
  [companyId, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
79404
79773
  );
79405
- const refreshImprovements = React142__default.useCallback(
79774
+ const refreshImprovements = React143__default.useCallback(
79406
79775
  async (reason) => {
79407
79776
  await runRefresh(
79408
79777
  "improvements",
@@ -79432,7 +79801,7 @@ var useOperationsOverviewRefresh = ({
79432
79801
  },
79433
79802
  [companyId, lineIds, lineIdsKey, runRefresh, scopeSignature, store, supabase]
79434
79803
  );
79435
- const refreshAll = React142__default.useCallback(
79804
+ const refreshAll = React143__default.useCallback(
79436
79805
  async (reason) => {
79437
79806
  await Promise.allSettled([
79438
79807
  refreshSnapshot(reason),
@@ -79443,7 +79812,7 @@ var useOperationsOverviewRefresh = ({
79443
79812
  },
79444
79813
  [refreshIdle, refreshImprovements, refreshSnapshot, refreshTrend]
79445
79814
  );
79446
- const startPolling = React142__default.useCallback((reason) => {
79815
+ const startPolling = React143__default.useCallback((reason) => {
79447
79816
  if (!isLiveScope || !supabase || !companyId || lineIds.length === 0) {
79448
79817
  return;
79449
79818
  }
@@ -79464,7 +79833,7 @@ var useOperationsOverviewRefresh = ({
79464
79833
  }, LIVE_REFRESH_INTERVAL_MS);
79465
79834
  debugRefreshLog("poll started", { reason, intervalMs: LIVE_REFRESH_INTERVAL_MS });
79466
79835
  }, [companyId, isLiveScope, lineIds.length, refreshAll, stopPolling, supabase]);
79467
- const refreshFromResume = React142__default.useCallback((reason) => {
79836
+ const refreshFromResume = React143__default.useCallback((reason) => {
79468
79837
  const now4 = Date.now();
79469
79838
  if (now4 - lastResumeRefreshAtRef.current < 1e3) {
79470
79839
  debugRefreshLog("resume refresh suppressed", { reason });
@@ -79479,7 +79848,7 @@ var useOperationsOverviewRefresh = ({
79479
79848
  }
79480
79849
  });
79481
79850
  }, [refreshAll, startPolling, stopPolling]);
79482
- React142__default.useEffect(() => {
79851
+ React143__default.useEffect(() => {
79483
79852
  if (!enabled) {
79484
79853
  stopPolling("disabled");
79485
79854
  abortAll();
@@ -79494,7 +79863,7 @@ var useOperationsOverviewRefresh = ({
79494
79863
  }
79495
79864
  void refreshAll("scope_change");
79496
79865
  }, [abortAll, companyId, enabled, lineIds.length, refreshAll, scopeSignature, stopPolling, store, supabase]);
79497
- React142__default.useEffect(() => {
79866
+ React143__default.useEffect(() => {
79498
79867
  if (!enabled || !isLiveScope || !supabase || !companyId || lineIds.length === 0) {
79499
79868
  isPageActiveRef.current = false;
79500
79869
  stopPolling("live_scope_disabled");
@@ -79669,55 +80038,55 @@ var PlantHeadView = () => {
79669
80038
  const { accessibleLineIds } = useUserLineAccess();
79670
80039
  const mobileMenuContext = useMobileMenu();
79671
80040
  useHideMobileHeader(!!mobileMenuContext);
79672
- const storeRef = React142__default.useRef(createOperationsOverviewStore());
80041
+ const storeRef = React143__default.useRef(createOperationsOverviewStore());
79673
80042
  const store = storeRef.current;
79674
- const fallbackOperationalDate = React142__default.useMemo(
80043
+ const fallbackOperationalDate = React143__default.useMemo(
79675
80044
  () => getOperationalDate(appTimezone),
79676
80045
  [appTimezone]
79677
80046
  );
79678
- const [dateRange, setDateRange] = React142__default.useState(() => ({
80047
+ const [dateRange, setDateRange] = React143__default.useState(() => ({
79679
80048
  startKey: fallbackOperationalDate,
79680
80049
  endKey: fallbackOperationalDate
79681
80050
  }));
79682
- const [usesThisWeekComparison, setUsesThisWeekComparison] = React142__default.useState(false);
79683
- const [trendMode, setTrendMode] = React142__default.useState("all");
79684
- const [selectedSupervisorId, setSelectedSupervisorId] = React142__default.useState("all");
79685
- const [selectedLineIds, setSelectedLineIds] = React142__default.useState([]);
79686
- const [isInitialScopeReady, setIsInitialScopeReady] = React142__default.useState(false);
79687
- const [shiftResolutionTick, setShiftResolutionTick] = React142__default.useState(0);
79688
- const hasAutoInitializedScopeRef = React142__default.useRef(false);
79689
- const hasUserAdjustedScopeRef = React142__default.useRef(false);
79690
- 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(() => {
79691
80060
  trackCorePageView("Operations Overview", {
79692
80061
  dashboard_surface: "operations_overview"
79693
80062
  });
79694
80063
  }, []);
79695
- const currentWeekRange = React142__default.useMemo(
80064
+ const currentWeekRange = React143__default.useMemo(
79696
80065
  () => getCurrentWeekToDateRange(appTimezone),
79697
80066
  [appTimezone]
79698
80067
  );
79699
- const currentWeekDisplayRange = React142__default.useMemo(
80068
+ const currentWeekDisplayRange = React143__default.useMemo(
79700
80069
  () => getCurrentWeekFullRange(appTimezone),
79701
80070
  [appTimezone]
79702
80071
  );
79703
80072
  const isCurrentWeekToDateRange = dateRange.startKey === currentWeekRange.startKey && dateRange.endKey === currentWeekRange.endKey;
79704
- const headerDateRange = React142__default.useMemo(() => {
80073
+ const headerDateRange = React143__default.useMemo(() => {
79705
80074
  if (usesThisWeekComparison && isCurrentWeekToDateRange) {
79706
80075
  return currentWeekDisplayRange;
79707
80076
  }
79708
80077
  return dateRange;
79709
80078
  }, [currentWeekDisplayRange, dateRange, isCurrentWeekToDateRange, usesThisWeekComparison]);
79710
- const normalizedLineIds = React142__default.useMemo(
80079
+ const normalizedLineIds = React143__default.useMemo(
79711
80080
  () => Array.from(new Set(
79712
80081
  (accessibleLineIds || []).filter(Boolean).filter((lineId) => lineId !== factoryViewId)
79713
80082
  )).sort(),
79714
80083
  [accessibleLineIds, factoryViewId]
79715
80084
  );
79716
- const lineIdsKey = React142__default.useMemo(
80085
+ const lineIdsKey = React143__default.useMemo(
79717
80086
  () => normalizedLineIds.join(","),
79718
80087
  [normalizedLineIds]
79719
80088
  );
79720
- const lineOptions = React142__default.useMemo(
80089
+ const lineOptions = React143__default.useMemo(
79721
80090
  () => normalizedLineIds.map((lineId) => ({
79722
80091
  id: lineId,
79723
80092
  name: getLineDisplayName(entityConfig, lineId)
@@ -79729,7 +80098,7 @@ var PlantHeadView = () => {
79729
80098
  companyId: entityConfig.companyId,
79730
80099
  useBackend: true
79731
80100
  });
79732
- const supervisorOptions = React142__default.useMemo(
80101
+ const supervisorOptions = React143__default.useMemo(
79733
80102
  () => {
79734
80103
  const optionsById = /* @__PURE__ */ new Map();
79735
80104
  normalizedLineIds.forEach((lineId) => {
@@ -79755,7 +80124,7 @@ var PlantHeadView = () => {
79755
80124
  },
79756
80125
  [normalizedLineIds, supervisorsByLineId]
79757
80126
  );
79758
- React142__default.useEffect(() => {
80127
+ React143__default.useEffect(() => {
79759
80128
  if (selectedSupervisorId === "all") {
79760
80129
  setSelectedLineIds((previous) => {
79761
80130
  if (normalizedLineIds.length === 0) {
@@ -79781,7 +80150,7 @@ var PlantHeadView = () => {
79781
80150
  const scopedSupervisorLineIds = normalizedLineIds.filter((lineId) => supervisorLineIdSet.has(lineId));
79782
80151
  setSelectedLineIds((previous) => previous.length === scopedSupervisorLineIds.length && previous.every((lineId, index) => lineId === scopedSupervisorLineIds[index]) ? previous : scopedSupervisorLineIds);
79783
80152
  }, [lineIdsKey, normalizedLineIds, selectedSupervisorId, supervisorOptions]);
79784
- const scopedLineIds = React142__default.useMemo(
80153
+ const scopedLineIds = React143__default.useMemo(
79785
80154
  () => selectedLineIds.length > 0 ? selectedLineIds : normalizedLineIds,
79786
80155
  [normalizedLineIds, selectedLineIds]
79787
80156
  );
@@ -79789,7 +80158,7 @@ var PlantHeadView = () => {
79789
80158
  shiftConfigMap,
79790
80159
  isLoading: isShiftConfigLoading
79791
80160
  } = useMultiLineShiftConfigs(scopedLineIds, staticShiftConfig);
79792
- React142__default.useEffect(() => {
80161
+ React143__default.useEffect(() => {
79793
80162
  if (scopedLineIds.length === 0 || isShiftConfigLoading) {
79794
80163
  return;
79795
80164
  }
@@ -79800,11 +80169,11 @@ var PlantHeadView = () => {
79800
80169
  clearInterval(intervalId);
79801
80170
  };
79802
80171
  }, [isShiftConfigLoading, scopedLineIds.length]);
79803
- const shiftResolutionNow = React142__default.useMemo(
80172
+ const shiftResolutionNow = React143__default.useMemo(
79804
80173
  () => /* @__PURE__ */ new Date(),
79805
80174
  [shiftResolutionTick]
79806
80175
  );
79807
- const earliestDayShiftStartTime = React142__default.useMemo(() => {
80176
+ const earliestDayShiftStartTime = React143__default.useMemo(() => {
79808
80177
  const candidateStarts = [];
79809
80178
  scopedLineIds.forEach((lineId) => {
79810
80179
  const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
@@ -79840,11 +80209,11 @@ var PlantHeadView = () => {
79840
80209
  const minutes = earliestMinutes % 60;
79841
80210
  return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
79842
80211
  }, [appTimezone, scopedLineIds, shiftConfigMap, staticShiftConfig]);
79843
- const resolvedOperationalToday = React142__default.useMemo(
80212
+ const resolvedOperationalToday = React143__default.useMemo(
79844
80213
  () => getOperationalDate(appTimezone, shiftResolutionNow, earliestDayShiftStartTime),
79845
80214
  [appTimezone, earliestDayShiftStartTime, shiftResolutionNow]
79846
80215
  );
79847
- const activeLineShiftStates = React142__default.useMemo(() => {
80216
+ const activeLineShiftStates = React143__default.useMemo(() => {
79848
80217
  return scopedLineIds.flatMap((lineId) => {
79849
80218
  const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
79850
80219
  const activeShift = getActiveShift(appTimezone, shiftConfig, shiftResolutionNow);
@@ -79871,16 +80240,16 @@ var PlantHeadView = () => {
79871
80240
  }];
79872
80241
  });
79873
80242
  }, [appTimezone, scopedLineIds, shiftConfigMap, shiftResolutionNow, staticShiftConfig]);
79874
- const hasActiveDayShiftLine = React142__default.useMemo(
80243
+ const hasActiveDayShiftLine = React143__default.useMemo(
79875
80244
  () => activeLineShiftStates.some((shift) => shift.trendMode === "day" && shift.date === resolvedOperationalToday),
79876
80245
  [activeLineShiftStates, resolvedOperationalToday]
79877
80246
  );
79878
- const hasActiveNightShiftLine = React142__default.useMemo(
80247
+ const hasActiveNightShiftLine = React143__default.useMemo(
79879
80248
  () => activeLineShiftStates.some((shift) => shift.trendMode === "night" && shift.date === resolvedOperationalToday),
79880
80249
  [activeLineShiftStates, resolvedOperationalToday]
79881
80250
  );
79882
80251
  const resolvedTrendMode = isInitialScopeReady ? trendMode : "all";
79883
- const hourlyWindowStartTime = React142__default.useMemo(() => {
80252
+ const hourlyWindowStartTime = React143__default.useMemo(() => {
79884
80253
  if (scopedLineIds.length === 0) {
79885
80254
  return null;
79886
80255
  }
@@ -79931,12 +80300,12 @@ var PlantHeadView = () => {
79931
80300
  const minutes = earliestMinutes % 60;
79932
80301
  return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
79933
80302
  }, [appTimezone, resolvedTrendMode, scopedLineIds, shiftConfigMap, staticShiftConfig]);
79934
- const isShiftScopeResolved = React142__default.useMemo(
80303
+ const isShiftScopeResolved = React143__default.useMemo(
79935
80304
  () => !isShiftConfigLoading,
79936
80305
  [isShiftConfigLoading]
79937
80306
  );
79938
- const initializedTimezoneRef = React142__default.useRef(appTimezone);
79939
- React142__default.useEffect(() => {
80307
+ const initializedTimezoneRef = React143__default.useRef(appTimezone);
80308
+ React143__default.useEffect(() => {
79940
80309
  if (initializedTimezoneRef.current === appTimezone) return;
79941
80310
  hasAutoInitializedScopeRef.current = false;
79942
80311
  hasUserAdjustedScopeRef.current = false;
@@ -79949,7 +80318,7 @@ var PlantHeadView = () => {
79949
80318
  setIsInitialScopeReady(false);
79950
80319
  initializedTimezoneRef.current = appTimezone;
79951
80320
  }, [appTimezone, fallbackOperationalDate]);
79952
- React142__default.useEffect(() => {
80321
+ React143__default.useEffect(() => {
79953
80322
  if (hasAutoInitializedScopeRef.current || hasUserAdjustedScopeRef.current) {
79954
80323
  return;
79955
80324
  }
@@ -79974,7 +80343,7 @@ var PlantHeadView = () => {
79974
80343
  hasAutoInitializedScopeRef.current = true;
79975
80344
  setIsInitialScopeReady(true);
79976
80345
  }, [fallbackOperationalDate, isShiftScopeResolved, resolvedOperationalToday, scopedLineIds.length]);
79977
- const handleDateRangeChange = React142__default.useCallback((range, meta) => {
80346
+ const handleDateRangeChange = React143__default.useCallback((range, meta) => {
79978
80347
  hasUserAdjustedScopeRef.current = true;
79979
80348
  setIsInitialScopeReady(true);
79980
80349
  trackCoreEvent("Operations Overview Date Range Changed", {
@@ -79992,12 +80361,12 @@ var PlantHeadView = () => {
79992
80361
  return previous;
79993
80362
  });
79994
80363
  }, []);
79995
- const handleTrendModeChange = React142__default.useCallback((mode) => {
80364
+ const handleTrendModeChange = React143__default.useCallback((mode) => {
79996
80365
  hasUserAdjustedScopeRef.current = true;
79997
80366
  setIsInitialScopeReady(true);
79998
80367
  setTrendMode(mode);
79999
80368
  }, []);
80000
- const handleSelectedLineIdsChange = React142__default.useCallback((lineIds) => {
80369
+ const handleSelectedLineIdsChange = React143__default.useCallback((lineIds) => {
80001
80370
  setSelectedSupervisorId("all");
80002
80371
  if (normalizedLineIds.length === 0) {
80003
80372
  setSelectedLineIds([]);
@@ -80008,10 +80377,10 @@ var PlantHeadView = () => {
80008
80377
  const next = normalizedLineIds.filter((lineId) => selectedSet.has(lineId));
80009
80378
  setSelectedLineIds(next.length > 0 ? next : normalizedLineIds);
80010
80379
  }, [normalizedLineIds]);
80011
- const handleSelectedSupervisorIdChange = React142__default.useCallback((supervisorId) => {
80380
+ const handleSelectedSupervisorIdChange = React143__default.useCallback((supervisorId) => {
80012
80381
  setSelectedSupervisorId(supervisorId);
80013
80382
  }, []);
80014
- const buildLineMonthlyHistoryUrl = React142__default.useCallback((lineId) => {
80383
+ const buildLineMonthlyHistoryUrl = React143__default.useCallback((lineId) => {
80015
80384
  const rangeStartDate = parseDateKeyToDate(dateRange.startKey);
80016
80385
  const params = new URLSearchParams();
80017
80386
  params.set("tab", "monthly_history");
@@ -80021,15 +80390,15 @@ var PlantHeadView = () => {
80021
80390
  params.set("rangeEnd", dateRange.endKey);
80022
80391
  return `/kpis/${lineId}?${params.toString()}`;
80023
80392
  }, [dateRange.endKey, dateRange.startKey]);
80024
- const handleViewAllPoorestPerformers = React142__default.useCallback(() => {
80393
+ const handleViewAllPoorestPerformers = React143__default.useCallback(() => {
80025
80394
  trackCoreEvent("Operations Overview View All Clicked", { section: "poorest_performers" });
80026
80395
  navigate("/kpis?tab=leaderboard");
80027
80396
  }, [navigate]);
80028
- const handleViewAllImprovements = React142__default.useCallback(() => {
80397
+ const handleViewAllImprovements = React143__default.useCallback(() => {
80029
80398
  trackCoreEvent("Operations Overview View All Clicked", { section: "improvements" });
80030
80399
  navigate("/improvement-center");
80031
80400
  }, [navigate]);
80032
- const handleOpenImprovement = React142__default.useCallback((item) => {
80401
+ const handleOpenImprovement = React143__default.useCallback((item) => {
80033
80402
  trackCoreEvent("Operations Overview Improvement Clicked", {
80034
80403
  issue_id: item.issueId,
80035
80404
  issue_number: item.issueNumber,
@@ -80040,13 +80409,13 @@ var PlantHeadView = () => {
80040
80409
  });
80041
80410
  navigate(`/improvement-center?${params.toString()}`);
80042
80411
  }, [navigate]);
80043
- const comparisonStrategy = React142__default.useMemo(() => {
80412
+ const comparisonStrategy = React143__default.useMemo(() => {
80044
80413
  if (usesThisWeekComparison && isCurrentWeekToDateRange) {
80045
80414
  return "previous_full_week";
80046
80415
  }
80047
80416
  return void 0;
80048
80417
  }, [isCurrentWeekToDateRange, usesThisWeekComparison]);
80049
- const effectiveDateRange = React142__default.useMemo(() => {
80418
+ const effectiveDateRange = React143__default.useMemo(() => {
80050
80419
  if (isInitialScopeReady) {
80051
80420
  return dateRange;
80052
80421
  }
@@ -80056,21 +80425,21 @@ var PlantHeadView = () => {
80056
80425
  endKey: nextStartKey
80057
80426
  };
80058
80427
  }, [dateRange, fallbackOperationalDate, isInitialScopeReady, resolvedOperationalToday]);
80059
- const effectiveTrendMode = React142__default.useMemo(
80428
+ const effectiveTrendMode = React143__default.useMemo(
80060
80429
  () => resolvedTrendMode,
80061
80430
  [resolvedTrendMode]
80062
80431
  );
80063
- const hourlyLabelStartTime = React142__default.useMemo(() => {
80432
+ const hourlyLabelStartTime = React143__default.useMemo(() => {
80064
80433
  if (scopedLineIds.length === 0) {
80065
80434
  return null;
80066
80435
  }
80067
80436
  return hourlyWindowStartTime;
80068
80437
  }, [hourlyWindowStartTime, scopedLineIds.length]);
80069
- const isSingleDayScope = React142__default.useMemo(
80438
+ const isSingleDayScope = React143__default.useMemo(
80070
80439
  () => effectiveDateRange.startKey === effectiveDateRange.endKey,
80071
80440
  [effectiveDateRange.endKey, effectiveDateRange.startKey]
80072
80441
  );
80073
- const isLiveScope = React142__default.useMemo(
80442
+ const isLiveScope = React143__default.useMemo(
80074
80443
  () => isSingleDayScope && effectiveDateRange.startKey === resolvedOperationalToday && (effectiveTrendMode === "all" || effectiveTrendMode === "day" && hasActiveDayShiftLine || effectiveTrendMode === "night" && hasActiveNightShiftLine),
80075
80444
  [
80076
80445
  effectiveDateRange.startKey,
@@ -80081,7 +80450,7 @@ var PlantHeadView = () => {
80081
80450
  resolvedOperationalToday
80082
80451
  ]
80083
80452
  );
80084
- const handleOpenLineDetails = React142__default.useCallback((lineId, lineName) => {
80453
+ const handleOpenLineDetails = React143__default.useCallback((lineId, lineName) => {
80085
80454
  trackCoreEvent("Operations Overview Line Clicked", {
80086
80455
  line_id: lineId,
80087
80456
  line_name: lineName,
@@ -80649,4 +81018,4 @@ var streamProxyConfig = {
80649
81018
  }
80650
81019
  };
80651
81020
 
80652
- 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 };