@optifye/dashboard-core 6.12.44 → 6.12.45

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,7 +1,7 @@
1
1
  import { format, addDays, subMonths, endOfMonth, startOfMonth, endOfDay, eachDayOfInterval, getDay, isSameDay, isWithinInterval, startOfDay, parseISO, subDays, differenceInMinutes, addMinutes, addMonths, isValid, formatDistanceToNow, isToday, isFuture, isBefore } from 'date-fns';
2
2
  import { formatInTimeZone, fromZonedTime, toZonedTime } from 'date-fns-tz';
3
- import * as React147 from 'react';
4
- import React147__default, { createContext, useRef, useId, useCallback, useState, useMemo, useEffect, forwardRef, useImperativeHandle, useLayoutEffect, memo as memo$1, useContext, useSyncExternalStore, Children, isValidElement, useInsertionEffect, startTransition, Fragment as Fragment$1, createElement, Component } from 'react';
3
+ import * as React148 from 'react';
4
+ import React148__default, { createContext, useRef, useId, useCallback, useState, useMemo, useEffect, forwardRef, useImperativeHandle, useLayoutEffect, memo as memo$1, useContext, useSyncExternalStore, Children, isValidElement, useInsertionEffect, startTransition, Fragment as Fragment$1, createElement, Component } from 'react';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
  import { useRouter } from 'next/router';
7
7
  import { toast } from 'sonner';
@@ -2091,14 +2091,14 @@ var useIdleTimeVlmConfig = () => {
2091
2091
  }
2092
2092
  return context;
2093
2093
  };
2094
- var DashboardConfigContext = React147.createContext(void 0);
2094
+ var DashboardConfigContext = React148.createContext(void 0);
2095
2095
  var DashboardProvider = ({ config: userProvidedConfig, children }) => {
2096
- const fullConfig = React147.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
2096
+ const fullConfig = React148.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
2097
2097
  _setDashboardConfigInstance(fullConfig);
2098
- React147.useEffect(() => {
2098
+ React148.useEffect(() => {
2099
2099
  _setDashboardConfigInstance(fullConfig);
2100
2100
  }, [fullConfig]);
2101
- React147.useEffect(() => {
2101
+ React148.useEffect(() => {
2102
2102
  if (!fullConfig.theme) return;
2103
2103
  const styleId = "dashboard-core-theme-vars";
2104
2104
  let styleEl = document.getElementById(styleId);
@@ -2124,7 +2124,7 @@ var DashboardProvider = ({ config: userProvidedConfig, children }) => {
2124
2124
  return /* @__PURE__ */ jsx(DashboardConfigContext.Provider, { value: fullConfig, children: /* @__PURE__ */ jsx(IdleTimeVlmConfigProvider, { children }) });
2125
2125
  };
2126
2126
  var useDashboardConfig = () => {
2127
- const ctx = React147.useContext(DashboardConfigContext);
2127
+ const ctx = React148.useContext(DashboardConfigContext);
2128
2128
  if (!ctx) throw new Error("useDashboardConfig must be used within a DashboardProvider");
2129
2129
  return ctx;
2130
2130
  };
@@ -9290,6 +9290,7 @@ var CLIP_COUNTS_CACHE_TTL = 30 * 1e3;
9290
9290
  var CLIP_BY_ID_CACHE_TTL = 2 * 60 * 1e3;
9291
9291
  var CLIP_BY_ID_CACHE_MAX = 200;
9292
9292
  var CLIPS_INIT_CACHE_TTL = 30 * 1e3;
9293
+ var RECENT_FLOW_RED_STREAK_CLIP_TYPE = "recent_flow_red_streak";
9293
9294
  var parseFiniteNumber = (value) => {
9294
9295
  if (typeof value === "number" && Number.isFinite(value)) {
9295
9296
  return value;
@@ -9885,6 +9886,7 @@ var S3ClipsSupabaseService = class {
9885
9886
  case "long_cycle_time":
9886
9887
  case "worst_cycle_time":
9887
9888
  case "sop_deviations":
9889
+ case RECENT_FLOW_RED_STREAK_CLIP_TYPE:
9888
9890
  return "high";
9889
9891
  case "idle_time":
9890
9892
  return "medium";
@@ -9905,7 +9907,8 @@ var S3ClipsSupabaseService = class {
9905
9907
  "best_cycle_time": "Best Cycle Time Performance",
9906
9908
  "worst_cycle_time": "Worst Cycle Time Performance",
9907
9909
  "sop_deviations": "SOP Deviations",
9908
- "cycle_completion": "Cycle Completion"
9910
+ "cycle_completion": "Cycle Completion",
9911
+ [RECENT_FLOW_RED_STREAK_CLIP_TYPE]: "Moments with low efficiency"
9909
9912
  };
9910
9913
  return clipType ? descriptions[clipType] || "Analysis Clip" : "Analysis Clip";
9911
9914
  }
@@ -12827,7 +12830,7 @@ var useMobileMenu = () => {
12827
12830
  };
12828
12831
  var useHideMobileHeader = (shouldHide = true) => {
12829
12832
  const context = useMobileMenu();
12830
- React147__default.useEffect(() => {
12833
+ React148__default.useEffect(() => {
12831
12834
  if (context && shouldHide) {
12832
12835
  context.setHideMobileHeader(true);
12833
12836
  return () => {
@@ -25910,7 +25913,7 @@ var MotionConfigContext = createContext({
25910
25913
  });
25911
25914
 
25912
25915
  // ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PopChild.mjs
25913
- var PopChildMeasure = class extends React147.Component {
25916
+ var PopChildMeasure = class extends React148.Component {
25914
25917
  getSnapshotBeforeUpdate(prevProps) {
25915
25918
  const element = this.props.childRef.current;
25916
25919
  if (element && prevProps.isPresent && !this.props.isPresent) {
@@ -25965,7 +25968,7 @@ function PopChild({ children, isPresent }) {
25965
25968
  document.head.removeChild(style);
25966
25969
  };
25967
25970
  }, [isPresent]);
25968
- return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React147.cloneElement(children, { ref }) });
25971
+ return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React148.cloneElement(children, { ref }) });
25969
25972
  }
25970
25973
 
25971
25974
  // ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PresenceChild.mjs
@@ -26002,7 +26005,7 @@ var PresenceChild = ({ children, initial, isPresent, onExitComplete, custom, pre
26002
26005
  useMemo(() => {
26003
26006
  presenceChildren.forEach((_, key) => presenceChildren.set(key, false));
26004
26007
  }, [isPresent]);
26005
- React147.useEffect(() => {
26008
+ React148.useEffect(() => {
26006
26009
  !isPresent && !presenceChildren.size && onExitComplete && onExitComplete();
26007
26010
  }, [isPresent]);
26008
26011
  if (mode === "popLayout") {
@@ -33787,7 +33790,7 @@ var withAuth = (WrappedComponent2, options) => {
33787
33790
  requireAuth: true,
33788
33791
  ...options
33789
33792
  };
33790
- const WithAuthComponent = React147.memo(function WithAuthComponent2(props) {
33793
+ const WithAuthComponent = React148.memo(function WithAuthComponent2(props) {
33791
33794
  const {
33792
33795
  session,
33793
33796
  user,
@@ -33798,9 +33801,9 @@ var withAuth = (WrappedComponent2, options) => {
33798
33801
  retrySessionHydration
33799
33802
  } = useAuth();
33800
33803
  const router = useRouter();
33801
- const [localLoading, setLocalLoading] = React147.useState(loading);
33802
- const [loadingTimeoutReached, setLoadingTimeoutReached] = React147.useState(false);
33803
- React147.useEffect(() => {
33804
+ const [localLoading, setLocalLoading] = React148.useState(loading);
33805
+ const [loadingTimeoutReached, setLoadingTimeoutReached] = React148.useState(false);
33806
+ React148.useEffect(() => {
33804
33807
  if (process.env.NODE_ENV === "development" && process.env.DEBUG_AUTH === "true") {
33805
33808
  console.log("withAuth state:", {
33806
33809
  loading,
@@ -33812,7 +33815,7 @@ var withAuth = (WrappedComponent2, options) => {
33812
33815
  });
33813
33816
  }
33814
33817
  }, [authStatus, error, loading, session, user]);
33815
- const handleLoadingTimeout = React147.useCallback(() => {
33818
+ const handleLoadingTimeout = React148.useCallback(() => {
33816
33819
  console.warn("[withAuth] Loading timeout reached");
33817
33820
  setLoadingTimeoutReached(true);
33818
33821
  if (hasStoredSupabaseSession()) {
@@ -33824,13 +33827,13 @@ var withAuth = (WrappedComponent2, options) => {
33824
33827
  router.replace(defaultOptions.redirectTo);
33825
33828
  }
33826
33829
  }, [retrySessionHydration, router]);
33827
- React147.useEffect(() => {
33830
+ React148.useEffect(() => {
33828
33831
  if (!loading && authStatus !== "recovering" && defaultOptions.requireAuth && !session && !error) {
33829
33832
  console.log("[withAuth] No session found, redirecting to login");
33830
33833
  router.replace(defaultOptions.redirectTo);
33831
33834
  }
33832
33835
  }, [authStatus, defaultOptions.requireAuth, error, loading, router, session]);
33833
- React147.useEffect(() => {
33836
+ React148.useEffect(() => {
33834
33837
  setLocalLoading(loading);
33835
33838
  }, [loading]);
33836
33839
  if (loading || localLoading) {
@@ -34829,11 +34832,11 @@ var BarChartComponent = ({
34829
34832
  aspect = 2,
34830
34833
  ...restOfChartProps
34831
34834
  }) => {
34832
- const containerRef = React147__default.useRef(null);
34833
- const [containerReady, setContainerReady] = React147__default.useState(false);
34835
+ const containerRef = React148__default.useRef(null);
34836
+ const [containerReady, setContainerReady] = React148__default.useState(false);
34834
34837
  const themeConfig = useThemeConfig();
34835
34838
  const { formatNumber } = useFormatNumber();
34836
- React147__default.useEffect(() => {
34839
+ React148__default.useEffect(() => {
34837
34840
  const checkContainerDimensions = () => {
34838
34841
  if (containerRef.current) {
34839
34842
  const rect = containerRef.current.getBoundingClientRect();
@@ -34947,7 +34950,7 @@ var BarChartComponent = ({
34947
34950
  }
34948
34951
  return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: chartContent });
34949
34952
  };
34950
- var BarChart = React147__default.memo(BarChartComponent, (prevProps, nextProps) => {
34953
+ var BarChart = React148__default.memo(BarChartComponent, (prevProps, nextProps) => {
34951
34954
  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) {
34952
34955
  return false;
34953
34956
  }
@@ -34998,10 +35001,10 @@ var LineChartComponent = ({
34998
35001
  fillContainer = false,
34999
35002
  ...restOfChartProps
35000
35003
  }) => {
35001
- const containerRef = React147__default.useRef(null);
35002
- const [dimensions, setDimensions] = React147__default.useState({ width: 0, height: 0 });
35003
- const [hasValidData, setHasValidData] = React147__default.useState(false);
35004
- React147__default.useEffect(() => {
35004
+ const containerRef = React148__default.useRef(null);
35005
+ const [dimensions, setDimensions] = React148__default.useState({ width: 0, height: 0 });
35006
+ const [hasValidData, setHasValidData] = React148__default.useState(false);
35007
+ React148__default.useEffect(() => {
35005
35008
  const currentHasValidData = data && lines && lines.length > 0 && data.some(
35006
35009
  (item) => lines.some((line) => {
35007
35010
  const val = item[line.dataKey];
@@ -35012,7 +35015,7 @@ var LineChartComponent = ({
35012
35015
  setHasValidData(true);
35013
35016
  }
35014
35017
  }, [data, lines, hasValidData]);
35015
- React147__default.useEffect(() => {
35018
+ React148__default.useEffect(() => {
35016
35019
  if (!containerRef.current) return;
35017
35020
  const observer = new ResizeObserver((entries) => {
35018
35021
  const entry = entries[0];
@@ -35137,7 +35140,7 @@ var LineChartComponent = ({
35137
35140
  }
35138
35141
  return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: renderChartContent(restOfChartProps.width, restOfChartProps.height) });
35139
35142
  };
35140
- var LineChart = React147__default.memo(LineChartComponent, (prevProps, nextProps) => {
35143
+ var LineChart = React148__default.memo(LineChartComponent, (prevProps, nextProps) => {
35141
35144
  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)) {
35142
35145
  return false;
35143
35146
  }
@@ -35304,7 +35307,7 @@ var SkuRow = ({ sku, isSelected, isLive, onSelect }) => {
35304
35307
  );
35305
35308
  };
35306
35309
  var PerSkuView = ({ rows, className = "", selectedSkuId, liveSkuId, onSelectSku }) => {
35307
- const ordered = React147__default.useMemo(
35310
+ const ordered = React148__default.useMemo(
35308
35311
  () => [...rows].sort((a, b) => {
35309
35312
  const am = (b.active_minutes ?? 0) - (a.active_minutes ?? 0);
35310
35313
  if (am !== 0) return am;
@@ -35312,9 +35315,9 @@ var PerSkuView = ({ rows, className = "", selectedSkuId, liveSkuId, onSelectSku
35312
35315
  }),
35313
35316
  [rows]
35314
35317
  );
35315
- const scrollContainerRef = React147__default.useRef(null);
35316
- const [showScrollIndicatorBottom, setShowScrollIndicatorBottom] = React147__default.useState(ordered.length > 4);
35317
- const [showScrollIndicatorTop, setShowScrollIndicatorTop] = React147__default.useState(false);
35318
+ const scrollContainerRef = React148__default.useRef(null);
35319
+ const [showScrollIndicatorBottom, setShowScrollIndicatorBottom] = React148__default.useState(ordered.length > 4);
35320
+ const [showScrollIndicatorTop, setShowScrollIndicatorTop] = React148__default.useState(false);
35318
35321
  const handleScroll = (e) => {
35319
35322
  const target = e.currentTarget;
35320
35323
  if (target.scrollHeight - target.scrollTop <= target.clientHeight + 10) {
@@ -35338,7 +35341,7 @@ var PerSkuView = ({ rows, className = "", selectedSkuId, liveSkuId, onSelectSku
35338
35341
  scrollContainerRef.current.scrollBy({ top: -80, behavior: "smooth" });
35339
35342
  }
35340
35343
  };
35341
- React147__default.useEffect(() => {
35344
+ React148__default.useEffect(() => {
35342
35345
  if (scrollContainerRef.current) {
35343
35346
  const target = scrollContainerRef.current;
35344
35347
  setShowScrollIndicatorBottom(target.scrollHeight > target.clientHeight && target.scrollHeight - target.scrollTop > target.clientHeight + 10);
@@ -35411,7 +35414,7 @@ var OutputProgressChartComponent = ({
35411
35414
  liveSkuId,
35412
35415
  onSelectSku
35413
35416
  }) => {
35414
- const realSkuRows = React147__default.useMemo(
35417
+ const realSkuRows = React148__default.useMemo(
35415
35418
  () => filterRealSkuBreakdown(skuBreakdown),
35416
35419
  [skuBreakdown]
35417
35420
  );
@@ -35436,7 +35439,7 @@ var OutputProgressChartComponent = ({
35436
35439
  }
35437
35440
  );
35438
35441
  };
35439
- var OutputProgressChart = React147__default.memo(OutputProgressChartComponent);
35442
+ var OutputProgressChart = React148__default.memo(OutputProgressChartComponent);
35440
35443
  OutputProgressChart.displayName = "OutputProgressChart";
35441
35444
  var LargeOutputProgressChart = ({
35442
35445
  currentOutput,
@@ -35576,7 +35579,7 @@ var CycleTimeChartComponent = ({
35576
35579
  }
35577
35580
  ) }) });
35578
35581
  };
35579
- var CycleTimeChart = React147__default.memo(CycleTimeChartComponent, (prevProps, nextProps) => {
35582
+ var CycleTimeChart = React148__default.memo(CycleTimeChartComponent, (prevProps, nextProps) => {
35580
35583
  if (prevProps.className !== nextProps.className) {
35581
35584
  return false;
35582
35585
  }
@@ -35816,16 +35819,16 @@ var CycleTimeOverTimeChart = ({
35816
35819
  onHourClick
35817
35820
  }) => {
35818
35821
  const MAX_DATA_POINTS = 40;
35819
- const containerRef = React147__default.useRef(null);
35820
- const [dimensions, setDimensions] = React147__default.useState({ width: 0, height: 0 });
35821
- const [hasValidData, setHasValidData] = React147__default.useState(false);
35822
- React147__default.useEffect(() => {
35822
+ const containerRef = React148__default.useRef(null);
35823
+ const [dimensions, setDimensions] = React148__default.useState({ width: 0, height: 0 });
35824
+ const [hasValidData, setHasValidData] = React148__default.useState(false);
35825
+ React148__default.useEffect(() => {
35823
35826
  const currentHasValidData = data && data.some((val) => val !== null && val > 0);
35824
35827
  if (currentHasValidData && !hasValidData) {
35825
35828
  setHasValidData(true);
35826
35829
  }
35827
35830
  }, [data, hasValidData]);
35828
- React147__default.useEffect(() => {
35831
+ React148__default.useEffect(() => {
35829
35832
  if (!containerRef.current) return;
35830
35833
  const observer = new ResizeObserver((entries) => {
35831
35834
  const entry = entries[0];
@@ -35863,7 +35866,7 @@ var CycleTimeOverTimeChart = ({
35863
35866
  const endLabel = shiftEnd && slotIndex === DURATION - 1 ? formatHourLabel(slotIndex + 1) : formatHourLabel(slotIndex + 1);
35864
35867
  return `${startLabel} - ${endLabel}`;
35865
35868
  };
35866
- const getDisplayData = React147__default.useCallback((rawData) => {
35869
+ const getDisplayData = React148__default.useCallback((rawData) => {
35867
35870
  if (xAxisMode === "hourly") return rawData;
35868
35871
  return rawData.slice(Math.max(0, rawData.length - MAX_DATA_POINTS));
35869
35872
  }, [xAxisMode]);
@@ -35871,7 +35874,7 @@ var CycleTimeOverTimeChart = ({
35871
35874
  const DURATION = displayData.length;
35872
35875
  const effectiveDatasetKey = datasetKey || `cycle-time:${xAxisMode}`;
35873
35876
  const finalData = displayData;
35874
- const labelInterval = React147__default.useMemo(() => {
35877
+ const labelInterval = React148__default.useMemo(() => {
35875
35878
  if (xAxisMode === "hourly") {
35876
35879
  return Math.max(1, Math.ceil(DURATION / 8));
35877
35880
  }
@@ -35912,8 +35915,8 @@ var CycleTimeOverTimeChart = ({
35912
35915
  return `${minutes} minutes ${seconds} seconds ago`;
35913
35916
  }
35914
35917
  };
35915
- const getNumericValue = React147__default.useCallback((value) => typeof value === "number" && Number.isFinite(value) ? value : null, []);
35916
- const buildHourClickPayload = React147__default.useCallback((dataPoint) => {
35918
+ const getNumericValue = React148__default.useCallback((value) => typeof value === "number" && Number.isFinite(value) ? value : null, []);
35919
+ const buildHourClickPayload = React148__default.useCallback((dataPoint) => {
35917
35920
  if (!onHourClick || xAxisMode !== "hourly") {
35918
35921
  return null;
35919
35922
  }
@@ -35932,7 +35935,7 @@ var CycleTimeOverTimeChart = ({
35932
35935
  status: cycleTime !== null && cycleTime <= idealCycleTime ? "within_standard" : "above_standard"
35933
35936
  };
35934
35937
  }, [DURATION, getNumericValue, idealCycleTime, onHourClick, shiftEnd, shiftStart, xAxisMode]);
35935
- const renderChartTooltip = React147__default.useCallback((tooltipProps) => {
35938
+ const renderChartTooltip = React148__default.useCallback((tooltipProps) => {
35936
35939
  const { active, payload } = tooltipProps;
35937
35940
  if (!active || !Array.isArray(payload) || payload.length === 0) {
35938
35941
  return null;
@@ -35996,7 +35999,7 @@ var CycleTimeOverTimeChart = ({
35996
35999
  ] })
35997
36000
  ] });
35998
36001
  }, [getNumericValue, onHourClick, shiftStart, showIdleTime, xAxisMode]);
35999
- const renderCycleDot = React147__default.useCallback((props) => {
36002
+ const renderCycleDot = React148__default.useCallback((props) => {
36000
36003
  const { cx: cx2, cy, payload } = props;
36001
36004
  const cycleTime = getNumericValue(payload?.cycleTime);
36002
36005
  if (cycleTime === null) {
@@ -36036,7 +36039,7 @@ var CycleTimeOverTimeChart = ({
36036
36039
  }
36037
36040
  );
36038
36041
  }, [buildHourClickPayload, getNumericValue, idealCycleTime, onHourClick, selectedHourIndex]);
36039
- const renderCycleActiveDot = React147__default.useCallback((props) => {
36042
+ const renderCycleActiveDot = React148__default.useCallback((props) => {
36040
36043
  const { cx: cx2, cy, payload } = props;
36041
36044
  const cycleTime = getNumericValue(payload?.cycleTime);
36042
36045
  if (cycleTime === null) {
@@ -36065,7 +36068,7 @@ var CycleTimeOverTimeChart = ({
36065
36068
  }
36066
36069
  );
36067
36070
  }, [buildHourClickPayload, getNumericValue, idealCycleTime, onHourClick, selectedHourIndex]);
36068
- const renderIdleDot = React147__default.useCallback((props) => {
36071
+ const renderIdleDot = React148__default.useCallback((props) => {
36069
36072
  const { cx: cx2, cy, payload } = props;
36070
36073
  const idleMinutes = getNumericValue(payload?.idleMinutes);
36071
36074
  if (idleMinutes === null) {
@@ -36087,7 +36090,7 @@ var CycleTimeOverTimeChart = ({
36087
36090
  }
36088
36091
  );
36089
36092
  }, [getNumericValue, showIdleTime]);
36090
- const renderIdleActiveDot = React147__default.useCallback((props) => {
36093
+ const renderIdleActiveDot = React148__default.useCallback((props) => {
36091
36094
  const { cx: cx2, cy, payload } = props;
36092
36095
  const idleMinutes = getNumericValue(payload?.idleMinutes);
36093
36096
  if (idleMinutes === null || !showIdleTime) {
@@ -36105,7 +36108,7 @@ var CycleTimeOverTimeChart = ({
36105
36108
  }
36106
36109
  );
36107
36110
  }, [getNumericValue, showIdleTime]);
36108
- const chartData = React147__default.useMemo(() => Array.from({ length: DURATION }, (_, i) => {
36111
+ const chartData = React148__default.useMemo(() => Array.from({ length: DURATION }, (_, i) => {
36109
36112
  const cycleTime = getNumericValue(finalData[i]);
36110
36113
  const useIdleSlots = idleTimeSlots.length > 0;
36111
36114
  const idleSlot = useIdleSlots ? idleTimeSlots[i] ?? null : null;
@@ -36302,7 +36305,7 @@ var CycleTimeOverTimeChart = ({
36302
36305
  }
36303
36306
  );
36304
36307
  };
36305
- var Card = React147.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36308
+ var Card = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36306
36309
  "div",
36307
36310
  {
36308
36311
  ref,
@@ -36314,7 +36317,7 @@ var Card = React147.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
36314
36317
  }
36315
36318
  ));
36316
36319
  Card.displayName = "Card";
36317
- var CardHeader = React147.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36320
+ var CardHeader = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36318
36321
  "div",
36319
36322
  {
36320
36323
  ref,
@@ -36323,7 +36326,7 @@ var CardHeader = React147.forwardRef(({ className, ...props }, ref) => /* @__PUR
36323
36326
  }
36324
36327
  ));
36325
36328
  CardHeader.displayName = "CardHeader";
36326
- var CardTitle = React147.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36329
+ var CardTitle = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36327
36330
  "h3",
36328
36331
  {
36329
36332
  ref,
@@ -36335,7 +36338,7 @@ var CardTitle = React147.forwardRef(({ className, ...props }, ref) => /* @__PURE
36335
36338
  }
36336
36339
  ));
36337
36340
  CardTitle.displayName = "CardTitle";
36338
- var CardDescription = React147.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36341
+ var CardDescription = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36339
36342
  "p",
36340
36343
  {
36341
36344
  ref,
@@ -36344,9 +36347,9 @@ var CardDescription = React147.forwardRef(({ className, ...props }, ref) => /* @
36344
36347
  }
36345
36348
  ));
36346
36349
  CardDescription.displayName = "CardDescription";
36347
- var CardContent = React147.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
36350
+ var CardContent = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
36348
36351
  CardContent.displayName = "CardContent";
36349
- var CardFooter = React147.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36352
+ var CardFooter = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36350
36353
  "div",
36351
36354
  {
36352
36355
  ref,
@@ -36422,7 +36425,7 @@ var buttonVariants = cva(
36422
36425
  }
36423
36426
  }
36424
36427
  );
36425
- var Button = React147.forwardRef(
36428
+ var Button = React148.forwardRef(
36426
36429
  ({ className, variant, size, asChild = false, ...props }, ref) => {
36427
36430
  const Comp = asChild ? Slot : "button";
36428
36431
  return /* @__PURE__ */ jsx(
@@ -37180,14 +37183,14 @@ var HourlyOutputChartComponent = ({
37180
37183
  onAiSummaryClick,
37181
37184
  className = ""
37182
37185
  }) => {
37183
- const containerRef = React147__default.useRef(null);
37184
- const [containerReady, setContainerReady] = React147__default.useState(false);
37185
- const [containerWidth, setContainerWidth] = React147__default.useState(0);
37186
- const [hoveredSkuRailLabel, setHoveredSkuRailLabel] = React147__default.useState(null);
37187
- const [isTooltipHovered, setIsTooltipHovered] = React147__default.useState(false);
37188
- const lastTooltipDataRef = React147__default.useRef(null);
37189
- const tooltipHoverTimeoutRef = React147__default.useRef(null);
37190
- const idleSlots = React147__default.useMemo(
37186
+ const containerRef = React148__default.useRef(null);
37187
+ const [containerReady, setContainerReady] = React148__default.useState(false);
37188
+ const [containerWidth, setContainerWidth] = React148__default.useState(0);
37189
+ const [hoveredSkuRailLabel, setHoveredSkuRailLabel] = React148__default.useState(null);
37190
+ const [isTooltipHovered, setIsTooltipHovered] = React148__default.useState(false);
37191
+ const lastTooltipDataRef = React148__default.useRef(null);
37192
+ const tooltipHoverTimeoutRef = React148__default.useRef(null);
37193
+ const idleSlots = React148__default.useMemo(
37191
37194
  () => buildHourlyIdleSlots({
37192
37195
  idleTimeHourly,
37193
37196
  shiftStart,
@@ -37196,12 +37199,12 @@ var HourlyOutputChartComponent = ({
37196
37199
  [idleTimeHourly, shiftStart, shiftEnd]
37197
37200
  );
37198
37201
  const SHIFT_DURATION = idleSlots.length;
37199
- const [animatedData, setAnimatedData] = React147__default.useState(
37202
+ const [animatedData, setAnimatedData] = React148__default.useState(
37200
37203
  () => Array(SHIFT_DURATION).fill(0)
37201
37204
  );
37202
- const prevDataRef = React147__default.useRef(Array(SHIFT_DURATION).fill(0));
37203
- const animationFrameRef = React147__default.useRef(null);
37204
- React147__default.useEffect(() => {
37205
+ const prevDataRef = React148__default.useRef(Array(SHIFT_DURATION).fill(0));
37206
+ const animationFrameRef = React148__default.useRef(null);
37207
+ React148__default.useEffect(() => {
37205
37208
  setAnimatedData((prev) => {
37206
37209
  if (prev.length !== SHIFT_DURATION) {
37207
37210
  return Array(SHIFT_DURATION).fill(0);
@@ -37210,14 +37213,14 @@ var HourlyOutputChartComponent = ({
37210
37213
  });
37211
37214
  prevDataRef.current = Array(SHIFT_DURATION).fill(0);
37212
37215
  }, [SHIFT_DURATION]);
37213
- const [idleBarState, setIdleBarState] = React147__default.useState({
37216
+ const [idleBarState, setIdleBarState] = React148__default.useState({
37214
37217
  visible: showIdleTime,
37215
37218
  key: 0,
37216
37219
  shouldAnimate: false
37217
37220
  });
37218
- const prevShowIdleTimeRef = React147__default.useRef(showIdleTime);
37219
- const stateUpdateTimeoutRef = React147__default.useRef(null);
37220
- React147__default.useEffect(() => {
37221
+ const prevShowIdleTimeRef = React148__default.useRef(showIdleTime);
37222
+ const stateUpdateTimeoutRef = React148__default.useRef(null);
37223
+ React148__default.useEffect(() => {
37221
37224
  if (stateUpdateTimeoutRef.current) {
37222
37225
  clearTimeout(stateUpdateTimeoutRef.current);
37223
37226
  }
@@ -37242,7 +37245,7 @@ var HourlyOutputChartComponent = ({
37242
37245
  }
37243
37246
  };
37244
37247
  }, [showIdleTime]);
37245
- const animateToNewData = React147__default.useCallback((targetData) => {
37248
+ const animateToNewData = React148__default.useCallback((targetData) => {
37246
37249
  const startData = [...prevDataRef.current];
37247
37250
  const startTime = performance.now();
37248
37251
  const duration = 1200;
@@ -37272,7 +37275,7 @@ var HourlyOutputChartComponent = ({
37272
37275
  }
37273
37276
  animationFrameRef.current = requestAnimationFrame(animate);
37274
37277
  }, []);
37275
- React147__default.useEffect(() => {
37278
+ React148__default.useEffect(() => {
37276
37279
  if (JSON.stringify(data) !== JSON.stringify(prevDataRef.current)) {
37277
37280
  const shiftData = data.slice(0, SHIFT_DURATION);
37278
37281
  animateToNewData(shiftData);
@@ -37283,14 +37286,14 @@ var HourlyOutputChartComponent = ({
37283
37286
  }
37284
37287
  };
37285
37288
  }, [data, animateToNewData]);
37286
- React147__default.useEffect(() => {
37289
+ React148__default.useEffect(() => {
37287
37290
  return () => {
37288
37291
  if (tooltipHoverTimeoutRef.current) {
37289
37292
  clearTimeout(tooltipHoverTimeoutRef.current);
37290
37293
  }
37291
37294
  };
37292
37295
  }, []);
37293
- React147__default.useEffect(() => {
37296
+ React148__default.useEffect(() => {
37294
37297
  const checkContainerDimensions = () => {
37295
37298
  if (containerRef.current) {
37296
37299
  const rect = containerRef.current.getBoundingClientRect();
@@ -37316,7 +37319,7 @@ var HourlyOutputChartComponent = ({
37316
37319
  clearTimeout(fallbackTimeout);
37317
37320
  };
37318
37321
  }, []);
37319
- const xAxisConfig = React147__default.useMemo(() => {
37322
+ const xAxisConfig = React148__default.useMemo(() => {
37320
37323
  if (containerWidth >= 960) {
37321
37324
  return {
37322
37325
  interval: 0,
@@ -37337,13 +37340,13 @@ var HourlyOutputChartComponent = ({
37337
37340
  }
37338
37341
  return { interval: 0, angle: -30, height: 64, tickFont: 9, tickMargin: 6 };
37339
37342
  }, [containerWidth]);
37340
- const shiftWindow = React147__default.useMemo(() => resolveShiftWindow2({
37343
+ const shiftWindow = React148__default.useMemo(() => resolveShiftWindow2({
37341
37344
  shiftStart,
37342
37345
  slotCount: SHIFT_DURATION,
37343
37346
  shiftDate,
37344
37347
  timezone
37345
37348
  }), [shiftStart, shiftEnd, SHIFT_DURATION, shiftDate, timezone]);
37346
- const fallbackTimelineEndOffset = React147__default.useMemo(
37349
+ const fallbackTimelineEndOffset = React148__default.useMemo(
37347
37350
  () => resolveTimelineEndOffset({
37348
37351
  shiftStart,
37349
37352
  shiftEnd,
@@ -37353,7 +37356,7 @@ var HourlyOutputChartComponent = ({
37353
37356
  }),
37354
37357
  [shiftStart, shiftEnd, SHIFT_DURATION, shiftDate, timezone]
37355
37358
  );
37356
- const observedTimelineEndOffset = React147__default.useMemo(() => {
37359
+ const observedTimelineEndOffset = React148__default.useMemo(() => {
37357
37360
  let lastObservedMinute = -1;
37358
37361
  idleSlots.forEach((slot) => {
37359
37362
  slot.idleArray.forEach((value, minuteIndex) => {
@@ -37369,7 +37372,7 @@ var HourlyOutputChartComponent = ({
37369
37372
  return Math.min((lastObservedMinute + 1) / 60, SHIFT_DURATION);
37370
37373
  }, [idleSlots, SHIFT_DURATION]);
37371
37374
  const timelineEndOffset = observedTimelineEndOffset ?? fallbackTimelineEndOffset;
37372
- const targetLineEndOffset = React147__default.useMemo(() => {
37375
+ const targetLineEndOffset = React148__default.useMemo(() => {
37373
37376
  if (timelineEndOffset >= SHIFT_DURATION) {
37374
37377
  return SHIFT_DURATION;
37375
37378
  }
@@ -37378,7 +37381,7 @@ var HourlyOutputChartComponent = ({
37378
37381
  }
37379
37382
  return Math.min(Math.floor(timelineEndOffset) + 1, SHIFT_DURATION);
37380
37383
  }, [timelineEndOffset, SHIFT_DURATION]);
37381
- const skuTimelineSegments = React147__default.useMemo(() => {
37384
+ const skuTimelineSegments = React148__default.useMemo(() => {
37382
37385
  if (!skuSegments || skuSegments.length === 0 || !shiftWindow || timelineEndOffset <= 0) {
37383
37386
  return [];
37384
37387
  }
@@ -37412,18 +37415,18 @@ var HourlyOutputChartComponent = ({
37412
37415
  };
37413
37416
  }).filter((segment) => segment.end > segment.start);
37414
37417
  }, [skuSegments, shiftWindow, timelineEndOffset, pphThreshold]);
37415
- const targetTimelineSegments = React147__default.useMemo(() => {
37418
+ const targetTimelineSegments = React148__default.useMemo(() => {
37416
37419
  if (skuTimelineSegments.length === 0) return [];
37417
37420
  return skuTimelineSegments.map((segment, index) => ({
37418
37421
  ...segment,
37419
37422
  end: index === skuTimelineSegments.length - 1 ? Math.max(segment.start, targetLineEndOffset) : segment.end
37420
37423
  })).filter((segment) => segment.end > segment.start);
37421
37424
  }, [skuTimelineSegments, targetLineEndOffset]);
37422
- const hasExplicitHourlyTargetOutputProp = React147__default.useMemo(
37425
+ const hasExplicitHourlyTargetOutputProp = React148__default.useMemo(
37423
37426
  () => hourlyTargetOutput !== void 0,
37424
37427
  [hourlyTargetOutput]
37425
37428
  );
37426
- const fallbackHourlyTargetOutput = React147__default.useMemo(() => {
37429
+ const fallbackHourlyTargetOutput = React148__default.useMemo(() => {
37427
37430
  if (hasExplicitHourlyTargetOutputProp) return void 0;
37428
37431
  if (skuTimelineSegments.length > 0) return void 0;
37429
37432
  const plan = buildHourlyTargetPlan({
@@ -37443,19 +37446,19 @@ var HourlyOutputChartComponent = ({
37443
37446
  shiftBreaks,
37444
37447
  pphThreshold
37445
37448
  ]);
37446
- const effectiveHourlyTargetOutput = React147__default.useMemo(
37449
+ const effectiveHourlyTargetOutput = React148__default.useMemo(
37447
37450
  () => hasExplicitHourlyTargetOutputProp ? hourlyTargetOutput : fallbackHourlyTargetOutput,
37448
37451
  [hasExplicitHourlyTargetOutputProp, hourlyTargetOutput, fallbackHourlyTargetOutput]
37449
37452
  );
37450
- const hasHourlyTargetOutputProp = React147__default.useMemo(
37453
+ const hasHourlyTargetOutputProp = React148__default.useMemo(
37451
37454
  () => effectiveHourlyTargetOutput !== void 0,
37452
37455
  [effectiveHourlyTargetOutput]
37453
37456
  );
37454
- const hasExplicitHourlyTargets = React147__default.useMemo(
37457
+ const hasExplicitHourlyTargets = React148__default.useMemo(
37455
37458
  () => Array.isArray(effectiveHourlyTargetOutput) && effectiveHourlyTargetOutput.some((value) => value !== null && value !== void 0),
37456
37459
  [effectiveHourlyTargetOutput]
37457
37460
  );
37458
- const hourlyTargetSegments = React147__default.useMemo(() => {
37461
+ const hourlyTargetSegments = React148__default.useMemo(() => {
37459
37462
  if (!hasExplicitHourlyTargets) return [];
37460
37463
  const segments = [];
37461
37464
  let runStart = null;
@@ -37487,7 +37490,7 @@ var HourlyOutputChartComponent = ({
37487
37490
  flush(SHIFT_DURATION);
37488
37491
  return segments.filter((segment) => segment.end > segment.start);
37489
37492
  }, [SHIFT_DURATION, hasExplicitHourlyTargets, effectiveHourlyTargetOutput]);
37490
- const activeSkuHourIndices = React147__default.useMemo(() => {
37493
+ const activeSkuHourIndices = React148__default.useMemo(() => {
37491
37494
  const indices = /* @__PURE__ */ new Set();
37492
37495
  const targets = Array(SHIFT_DURATION).fill(pphThreshold);
37493
37496
  if (!skuSegments || !shiftWindow) return { indices, targets, hasTimeline: false };
@@ -37520,7 +37523,7 @@ var HourlyOutputChartComponent = ({
37520
37523
  }
37521
37524
  return { indices, targets, hasTimeline: true };
37522
37525
  }, [skuSegments, activeSkuId, shiftWindow, SHIFT_DURATION, pphThreshold]);
37523
- const chartData = React147__default.useMemo(() => {
37526
+ const chartData = React148__default.useMemo(() => {
37524
37527
  const { indices, targets, hasTimeline } = activeSkuHourIndices;
37525
37528
  return Array.from({ length: SHIFT_DURATION }, (_, i) => {
37526
37529
  const idleSlot = idleSlots[i];
@@ -37549,7 +37552,7 @@ var HourlyOutputChartComponent = ({
37549
37552
  };
37550
37553
  });
37551
37554
  }, [animatedData, data, pphThreshold, idleSlots, SHIFT_DURATION, activeSkuHourIndices, activeSkuId, effectiveHourlyTargetOutput, hasHourlyTargetOutputProp, selectedHourIndex]);
37552
- const renderSkuTimelineRail = React147__default.useCallback((props) => {
37555
+ const renderSkuTimelineRail = React148__default.useCallback((props) => {
37553
37556
  if (!skuTimelineSegments.length || SHIFT_DURATION <= 0) return null;
37554
37557
  const offset = props?.offset;
37555
37558
  if (!offset) return null;
@@ -37698,7 +37701,7 @@ var HourlyOutputChartComponent = ({
37698
37701
  })
37699
37702
  ] });
37700
37703
  }, [skuTimelineSegments, SHIFT_DURATION, activeSkuId]);
37701
- const IdleBar = React147__default.useMemo(() => {
37704
+ const IdleBar = React148__default.useMemo(() => {
37702
37705
  if (!idleBarState.visible) return null;
37703
37706
  return /* @__PURE__ */ jsx(
37704
37707
  Bar,
@@ -37792,7 +37795,7 @@ var HourlyOutputChartComponent = ({
37792
37795
  }
37793
37796
  return filteredTicks;
37794
37797
  };
37795
- const renderTargetLine = React147__default.useCallback((props) => {
37798
+ const renderTargetLine = React148__default.useCallback((props) => {
37796
37799
  const { offset, yAxisMap } = props;
37797
37800
  if (!offset || !yAxisMap || SHIFT_DURATION <= 0 || targetLineEndOffset <= 0) return null;
37798
37801
  const { left, width } = offset;
@@ -38293,7 +38296,7 @@ var HourlyOutputChartComponent = ({
38293
38296
  }
38294
38297
  );
38295
38298
  };
38296
- var HourlyOutputChart = React147__default.memo(
38299
+ var HourlyOutputChart = React148__default.memo(
38297
38300
  HourlyOutputChartComponent,
38298
38301
  (prevProps, nextProps) => {
38299
38302
  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.activeSkuId !== nextProps.activeSkuId || prevProps.selectedHourIndex !== nextProps.selectedHourIndex || prevProps.onHourClick !== nextProps.onHourClick || prevProps.className !== nextProps.className) {
@@ -38747,7 +38750,7 @@ function getTrendArrowAndColor(trend) {
38747
38750
  return { arrow: "\u2192", color: "text-gray-400" };
38748
38751
  }
38749
38752
  }
38750
- var VideoCard = React147__default.memo(({
38753
+ var VideoCard = React148__default.memo(({
38751
38754
  workspace,
38752
38755
  hlsUrl,
38753
38756
  shouldPlay,
@@ -39017,7 +39020,7 @@ var hasRecentHealthSignal = (lastHeartbeat) => {
39017
39020
  if (!Number.isFinite(heartbeatMs)) return false;
39018
39021
  return Date.now() - heartbeatMs <= RECENT_HEALTH_SIGNAL_MS;
39019
39022
  };
39020
- var VideoGridView = React147__default.memo(({
39023
+ var VideoGridView = React148__default.memo(({
39021
39024
  workspaces,
39022
39025
  blueComparisonWorkspaces,
39023
39026
  selectedLine,
@@ -39456,7 +39459,7 @@ var VideoGridView = React147__default.memo(({
39456
39459
  ) });
39457
39460
  });
39458
39461
  VideoGridView.displayName = "VideoGridView";
39459
- var MapGridView = React147__default.memo(({
39462
+ var MapGridView = React148__default.memo(({
39460
39463
  workspaces,
39461
39464
  className = "",
39462
39465
  displayNames = {},
@@ -39677,13 +39680,13 @@ var WorkspaceMetricCardsImpl = ({
39677
39680
  liveSkuId
39678
39681
  }) => {
39679
39682
  const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
39680
- const activeSku = React147__default.useMemo(() => {
39683
+ const activeSku = React148__default.useMemo(() => {
39681
39684
  if (skuAware && activeSkuId && skuBreakdown) {
39682
39685
  return skuBreakdown.find((s) => s.sku_id === activeSkuId);
39683
39686
  }
39684
39687
  return null;
39685
39688
  }, [skuAware, activeSkuId, skuBreakdown]);
39686
- const displaySku = React147__default.useMemo(() => {
39689
+ const displaySku = React148__default.useMemo(() => {
39687
39690
  if (activeSku) return activeSku;
39688
39691
  if (skuAware && !activeSkuId && liveSkuId && skuBreakdown) {
39689
39692
  return skuBreakdown.find((s) => s.sku_id === liveSkuId) ?? null;
@@ -40337,7 +40340,7 @@ var UptimeLineChartComponent = ({ points, className = "" }) => {
40337
40340
  )
40338
40341
  ] }) }) });
40339
40342
  };
40340
- var UptimeLineChart = React147__default.memo(UptimeLineChartComponent);
40343
+ var UptimeLineChart = React148__default.memo(UptimeLineChartComponent);
40341
40344
  var getTimeFromTimeString = (timeStr) => {
40342
40345
  if (!timeStr) {
40343
40346
  return { hour: 0, minute: 0, decimalHour: 0 };
@@ -40361,10 +40364,10 @@ var HourlyUptimeChartComponent = ({
40361
40364
  shiftBreaks,
40362
40365
  className = ""
40363
40366
  }) => {
40364
- const containerRef = React147__default.useRef(null);
40365
- const [containerReady, setContainerReady] = React147__default.useState(false);
40366
- const [containerWidth, setContainerWidth] = React147__default.useState(0);
40367
- const uptimeSeries = React147__default.useMemo(() => buildUptimeSeries({
40367
+ const containerRef = React148__default.useRef(null);
40368
+ const [containerReady, setContainerReady] = React148__default.useState(false);
40369
+ const [containerWidth, setContainerWidth] = React148__default.useState(0);
40370
+ const uptimeSeries = React148__default.useMemo(() => buildUptimeSeries({
40368
40371
  idleTimeHourly,
40369
40372
  shiftStart,
40370
40373
  shiftEnd,
@@ -40374,11 +40377,11 @@ var HourlyUptimeChartComponent = ({
40374
40377
  shiftBreaks
40375
40378
  }), [idleTimeHourly, shiftStart, shiftEnd, shiftDate, timezone, elapsedMinutes, shiftBreaks]);
40376
40379
  const hasAggregateData = Boolean(hourlyAggregates && hourlyAggregates.length > 0);
40377
- const shiftStartTime = React147__default.useMemo(
40380
+ const shiftStartTime = React148__default.useMemo(
40378
40381
  () => getTimeFromTimeString(shiftStart),
40379
40382
  [shiftStart]
40380
40383
  );
40381
- const { shiftDuration, shiftEndTime } = React147__default.useMemo(() => {
40384
+ const { shiftDuration, shiftEndTime } = React148__default.useMemo(() => {
40382
40385
  if (!shiftEnd) {
40383
40386
  const fallbackHours = uptimeSeries.shiftMinutes > 0 ? Math.ceil(uptimeSeries.shiftMinutes / 60) : 0;
40384
40387
  return { shiftDuration: fallbackHours, shiftEndTime: null };
@@ -40392,7 +40395,7 @@ var HourlyUptimeChartComponent = ({
40392
40395
  const hourCount = hasPartial ? Math.ceil(duration) : Math.round(duration);
40393
40396
  return { shiftDuration: hourCount, shiftEndTime: endTime };
40394
40397
  }, [shiftEnd, shiftStartTime.decimalHour, uptimeSeries.shiftMinutes]);
40395
- const formatHour = React147__default.useCallback((hourIndex) => {
40398
+ const formatHour = React148__default.useCallback((hourIndex) => {
40396
40399
  const isLastHour = hourIndex === shiftDuration - 1;
40397
40400
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
40398
40401
  const startHour = Math.floor(startDecimalHour) % 24;
@@ -40417,7 +40420,7 @@ var HourlyUptimeChartComponent = ({
40417
40420
  };
40418
40421
  return `${formatTime5(startHour, startMinute)}-${formatTime5(endHour, endMinute)}`;
40419
40422
  }, [shiftDuration, shiftStartTime.decimalHour, shiftEndTime]);
40420
- const formatTimeRange2 = React147__default.useCallback((hourIndex) => {
40423
+ const formatTimeRange2 = React148__default.useCallback((hourIndex) => {
40421
40424
  const isLastHour = hourIndex === shiftDuration - 1;
40422
40425
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
40423
40426
  const startHour = Math.floor(startDecimalHour) % 24;
@@ -40439,7 +40442,7 @@ var HourlyUptimeChartComponent = ({
40439
40442
  };
40440
40443
  return `${formatTime5(startHour, startMinute)} - ${formatTime5(endHour, endMinute)}`;
40441
40444
  }, [shiftDuration, shiftStartTime.decimalHour, shiftEndTime]);
40442
- const chartData = React147__default.useMemo(() => {
40445
+ const chartData = React148__default.useMemo(() => {
40443
40446
  if (shiftDuration <= 0) return [];
40444
40447
  if (hasAggregateData) {
40445
40448
  return hourlyAggregates.map((entry, hourIndex) => ({
@@ -40481,7 +40484,7 @@ var HourlyUptimeChartComponent = ({
40481
40484
  }, [hasAggregateData, hourlyAggregates, uptimeSeries.points, uptimeSeries.elapsedMinutes, uptimeSeries.shiftMinutes, shiftDuration, formatHour, formatTimeRange2]);
40482
40485
  const maxYValue = 100;
40483
40486
  const yAxisTicks = [0, 25, 50, 75, 100];
40484
- React147__default.useEffect(() => {
40487
+ React148__default.useEffect(() => {
40485
40488
  const checkContainerDimensions = () => {
40486
40489
  if (containerRef.current) {
40487
40490
  const rect = containerRef.current.getBoundingClientRect();
@@ -40507,7 +40510,7 @@ var HourlyUptimeChartComponent = ({
40507
40510
  clearTimeout(fallbackTimeout);
40508
40511
  };
40509
40512
  }, []);
40510
- const xAxisConfig = React147__default.useMemo(() => {
40513
+ const xAxisConfig = React148__default.useMemo(() => {
40511
40514
  if (containerWidth >= 960) {
40512
40515
  return { interval: 0, angle: -45, height: 92, tickFont: 10, tickMargin: 12, labelMode: "full" };
40513
40516
  }
@@ -40516,7 +40519,7 @@ var HourlyUptimeChartComponent = ({
40516
40519
  }
40517
40520
  return { interval: 0, angle: -30, height: 64, tickFont: 9, tickMargin: 6, labelMode: "start" };
40518
40521
  }, [containerWidth]);
40519
- const formatXAxisTick = React147__default.useCallback((raw) => {
40522
+ const formatXAxisTick = React148__default.useCallback((raw) => {
40520
40523
  const label = typeof raw === "string" ? raw : String(raw);
40521
40524
  if (xAxisConfig.labelMode === "full") return label;
40522
40525
  const parts = label.split("-");
@@ -40722,7 +40725,7 @@ var HourlyUptimeChartComponent = ({
40722
40725
  }
40723
40726
  );
40724
40727
  };
40725
- var HourlyUptimeChart = React147__default.memo(HourlyUptimeChartComponent);
40728
+ var HourlyUptimeChart = React148__default.memo(HourlyUptimeChartComponent);
40726
40729
  var DEFAULT_COLORS2 = ["#00AB45", "#ef4444"];
40727
40730
  var UptimeDonutChartComponent = ({
40728
40731
  data,
@@ -40792,7 +40795,7 @@ var UptimeDonutChartComponent = ({
40792
40795
  ] }) })
40793
40796
  ] }) });
40794
40797
  };
40795
- var UptimeDonutChart = React147__default.memo(UptimeDonutChartComponent);
40798
+ var UptimeDonutChart = React148__default.memo(UptimeDonutChartComponent);
40796
40799
  UptimeDonutChart.displayName = "UptimeDonutChart";
40797
40800
  var TrendIcon = ({ trend }) => {
40798
40801
  if (trend === "up") {
@@ -40913,7 +40916,7 @@ var EmptyStateMessage = ({
40913
40916
  iconClassName
40914
40917
  }) => {
40915
40918
  let IconContent = null;
40916
- if (React147__default.isValidElement(iconType)) {
40919
+ if (React148__default.isValidElement(iconType)) {
40917
40920
  IconContent = iconType;
40918
40921
  } else if (typeof iconType === "string") {
40919
40922
  const MappedIcon = IconMap[iconType];
@@ -41421,6 +41424,7 @@ var CYCLE_RANGE_CATEGORY_IDS = /* @__PURE__ */ new Set([
41421
41424
  "fast-cycles",
41422
41425
  "slow-cycles"
41423
41426
  ]);
41427
+ var EXPLICIT_INTERVAL_CATEGORY_IDS = /* @__PURE__ */ new Set(["recent_flow_red_streak"]);
41424
41428
  var roundToNearestMinute = (date) => {
41425
41429
  const rounded = new Date(date.getTime());
41426
41430
  const seconds = rounded.getSeconds();
@@ -41476,6 +41480,22 @@ var buildPrefetchedExplorerMetadata = (activeFilter, metadataCategoryId, categor
41476
41480
  };
41477
41481
  };
41478
41482
  var shouldDeferClipPlayerRender = (cropLoading, workspaceCrop) => cropLoading && workspaceCrop === null;
41483
+ var getCategoryMetadataLoadPlanForFilterChange = ({
41484
+ activeFilter,
41485
+ currentClipId,
41486
+ categoryTotal
41487
+ }) => {
41488
+ if (!activeFilter || activeFilter === "all") {
41489
+ return { shouldLoad: false, autoLoadFirstVideo: false };
41490
+ }
41491
+ if (activeFilter === "recent_flow_red_streak" && categoryTotal > 0) {
41492
+ return { shouldLoad: true, autoLoadFirstVideo: true };
41493
+ }
41494
+ return {
41495
+ shouldLoad: Boolean(currentClipId),
41496
+ autoLoadFirstVideo: false
41497
+ };
41498
+ };
41479
41499
  var getSecondsBetweenTimestamps = (startTime, endTime) => {
41480
41500
  const startDate = parseTimestamp(startTime);
41481
41501
  const endDate = parseTimestamp(endTime);
@@ -41488,8 +41508,24 @@ var formatClipExplorerTimeLabel = ({
41488
41508
  timezone,
41489
41509
  durationSeconds,
41490
41510
  idleStartTime,
41491
- idleEndTime
41511
+ idleEndTime,
41512
+ clipStartTime,
41513
+ clipEndTime
41492
41514
  }) => {
41515
+ if (EXPLICIT_INTERVAL_CATEGORY_IDS.has(categoryId)) {
41516
+ const endTimestamp = clipEndTime || clipTimestamp;
41517
+ if (clipStartTime && endTimestamp) {
41518
+ return formatTimestampRange(clipStartTime, endTimestamp, timezone);
41519
+ }
41520
+ if (typeof durationSeconds === "number" && Number.isFinite(durationSeconds) && durationSeconds > 0) {
41521
+ const endDate = parseTimestamp(endTimestamp);
41522
+ if (endDate) {
41523
+ const startDate = new Date(endDate.getTime() - durationSeconds * 1e3);
41524
+ return formatTimestampRange(startDate.toISOString(), endTimestamp, timezone);
41525
+ }
41526
+ }
41527
+ return formatClipExplorerSingleTime(endTimestamp, timezone);
41528
+ }
41493
41529
  if (IDLE_RANGE_CATEGORY_IDS.has(categoryId)) {
41494
41530
  const idleDurationSeconds = getSecondsBetweenTimestamps(idleStartTime, idleEndTime);
41495
41531
  const idleEndTimestamp = idleEndTime || clipTimestamp;
@@ -41516,6 +41552,106 @@ var formatClipExplorerTimeLabel = ({
41516
41552
  return singleTime;
41517
41553
  };
41518
41554
  var formatIdleTimeRange = (startTime, endTime, timezone) => formatTimestampRange(startTime, endTime, timezone);
41555
+
41556
+ // src/lib/utils/redFlowDisplay.ts
41557
+ var getRedFlowDriverLabel = (driver) => {
41558
+ switch (driver) {
41559
+ case "idle":
41560
+ return "Idle";
41561
+ case "micro_stoppage":
41562
+ return "Gaps";
41563
+ case "slow_cycle":
41564
+ return "Slow Cycles";
41565
+ case "low_output":
41566
+ return "Low Output";
41567
+ default:
41568
+ return "";
41569
+ }
41570
+ };
41571
+ var getRedFlowDriversFromEvidence = (evidence) => {
41572
+ const drivers = /* @__PURE__ */ new Set();
41573
+ (evidence || []).forEach((item) => {
41574
+ const normalized = item.toLowerCase();
41575
+ if (normalized.includes("idle")) {
41576
+ drivers.add("idle");
41577
+ }
41578
+ if (normalized.includes("micro") || normalized.includes("gap")) {
41579
+ drivers.add("micro_stoppage");
41580
+ }
41581
+ if (normalized.includes("slow") || normalized.includes("cycle time") || normalized.includes("shift avg")) {
41582
+ drivers.add("slow_cycle");
41583
+ }
41584
+ if (normalized.includes("output")) {
41585
+ drivers.add("low_output");
41586
+ }
41587
+ });
41588
+ return Array.from(drivers);
41589
+ };
41590
+ var getRedFlowDisplayDriverKeys = (summary) => {
41591
+ if (!summary || summary.confidence !== "medium" && summary.confidence !== "high") {
41592
+ return [];
41593
+ }
41594
+ if (summary.primary_driver === "unknown") {
41595
+ return [];
41596
+ }
41597
+ if (summary.primary_driver === "mixed") {
41598
+ const evidenceDrivers = getRedFlowDriversFromEvidence(summary.evidence).filter((driver) => Boolean(getRedFlowDriverLabel(driver)));
41599
+ return evidenceDrivers.length >= 2 ? evidenceDrivers.slice(0, 3) : [];
41600
+ }
41601
+ return getRedFlowDriverLabel(summary.primary_driver) ? [summary.primary_driver] : [];
41602
+ };
41603
+ var formatRedFlowCompactNumber = (value) => Number.isInteger(value) ? String(value) : value.toFixed(1).replace(/\.0$/, "");
41604
+ var formatRedFlowOutputCount = (value) => Number.isFinite(value) ? String(Math.round(value)) : "";
41605
+ var getRedFlowBinOutputUnits = (bin) => {
41606
+ if (typeof bin.actual_output_units === "number" && Number.isFinite(bin.actual_output_units)) {
41607
+ return bin.actual_output_units;
41608
+ }
41609
+ if (typeof bin.actual_ppm === "number" && Number.isFinite(bin.actual_ppm)) {
41610
+ const durationSeconds = typeof bin.duration_seconds === "number" && Number.isFinite(bin.duration_seconds) && bin.duration_seconds > 0 ? bin.duration_seconds : 60;
41611
+ return bin.actual_ppm * durationSeconds / 60;
41612
+ }
41613
+ return null;
41614
+ };
41615
+ var summarizeRedFlowOutput = (timeline, summary) => {
41616
+ const actualFromSummary = summary?.totals.actual_output_units;
41617
+ const expectedFromSummary = summary?.totals.baseline_output_units;
41618
+ if (typeof actualFromSummary === "number" && Number.isFinite(actualFromSummary) && typeof expectedFromSummary === "number" && Number.isFinite(expectedFromSummary)) {
41619
+ return { actual: actualFromSummary, expected: expectedFromSummary };
41620
+ }
41621
+ let actual = 0;
41622
+ let expected = 0;
41623
+ let hasActual = false;
41624
+ let hasExpected = false;
41625
+ (timeline?.minute_bins || []).forEach((bin) => {
41626
+ const output = getRedFlowBinOutputUnits(bin);
41627
+ if (output !== null) {
41628
+ actual += output;
41629
+ hasActual = true;
41630
+ }
41631
+ if (typeof bin.target_ppm === "number" && Number.isFinite(bin.target_ppm)) {
41632
+ const durationSeconds = typeof bin.duration_seconds === "number" && Number.isFinite(bin.duration_seconds) && bin.duration_seconds > 0 ? bin.duration_seconds : 60;
41633
+ expected += bin.target_ppm * durationSeconds / 60;
41634
+ hasExpected = true;
41635
+ }
41636
+ });
41637
+ return hasActual && hasExpected ? { actual, expected } : null;
41638
+ };
41639
+ var getRedFlowOutputShortfallUnits = (timeline) => {
41640
+ let actual = 0;
41641
+ let expected = 0;
41642
+ let hasComparableBin = false;
41643
+ (timeline?.minute_bins || []).forEach((bin) => {
41644
+ const output = getRedFlowBinOutputUnits(bin);
41645
+ const durationSeconds = typeof bin.duration_seconds === "number" && Number.isFinite(bin.duration_seconds) && bin.duration_seconds > 0 ? bin.duration_seconds : null;
41646
+ if (output === null || durationSeconds === null || typeof bin.target_ppm !== "number" || !Number.isFinite(bin.target_ppm)) {
41647
+ return;
41648
+ }
41649
+ actual += output;
41650
+ expected += bin.target_ppm * durationSeconds / 60;
41651
+ hasComparableBin = true;
41652
+ });
41653
+ return hasComparableBin ? expected - actual : null;
41654
+ };
41519
41655
  var formatTime2 = (seconds) => {
41520
41656
  if (!seconds || isNaN(seconds)) return "0:00";
41521
41657
  const h = Math.floor(seconds / 3600);
@@ -41526,6 +41662,33 @@ var formatTime2 = (seconds) => {
41526
41662
  }
41527
41663
  return `${m}:${s.toString().padStart(2, "0")}`;
41528
41664
  };
41665
+ var formatTimelineClockTime = (isoTime, timezone) => {
41666
+ if (!isoTime) return "";
41667
+ const date = new Date(isoTime);
41668
+ if (Number.isNaN(date.getTime())) return "";
41669
+ return date.toLocaleTimeString("en-US", {
41670
+ hour: "numeric",
41671
+ minute: "2-digit",
41672
+ hour12: true,
41673
+ timeZone: timezone
41674
+ });
41675
+ };
41676
+ var formatCompactNumber = formatRedFlowCompactNumber;
41677
+ var formatTooltipSeconds = (value) => `${Math.round(value)}s`;
41678
+ var formatEfficiencyPercent = (value) => {
41679
+ if (typeof value !== "number" || !Number.isFinite(value)) {
41680
+ return "No output data";
41681
+ }
41682
+ return `${Math.round(value)}% efficient`;
41683
+ };
41684
+ var getBinOutputUnits = getRedFlowBinOutputUnits;
41685
+ var formatOutputLabel = (bin) => {
41686
+ const actualOutput = getBinOutputUnits(bin);
41687
+ if (actualOutput === null) {
41688
+ return "";
41689
+ }
41690
+ return `Output ${formatCompactNumber(actualOutput)}`;
41691
+ };
41529
41692
  var VideoControls = ({
41530
41693
  isPlaying,
41531
41694
  currentTime,
@@ -41544,15 +41707,20 @@ var VideoControls = ({
41544
41707
  onShare,
41545
41708
  isShareLoading = false,
41546
41709
  isShareCopied = false,
41710
+ timelineAnnotations,
41711
+ timelineExplanation,
41712
+ timelineTimezone,
41547
41713
  className = ""
41548
41714
  }) => {
41549
41715
  const [isDragging2, setIsDragging] = useState(false);
41550
41716
  const [dragTime, setDragTime] = useState(0);
41551
41717
  const [isHoveringProgressBar, setIsHoveringProgressBar] = useState(false);
41718
+ const [hoveredTimelineBin, setHoveredTimelineBin] = useState(null);
41552
41719
  const [showSpeedMenu, setShowSpeedMenu] = useState(false);
41553
41720
  const speedMenuRef = useRef(null);
41554
41721
  const progressTrackRef = useRef(null);
41555
41722
  const activePointerIdRef = useRef(null);
41723
+ const markerPointerJumpHandledRef = useRef(false);
41556
41724
  const progressColor = "#4b5563";
41557
41725
  const controlsVisible = showControls || controlsPinned;
41558
41726
  const isDraggingRef = useRef(false);
@@ -41576,6 +41744,43 @@ var VideoControls = ({
41576
41744
  isDraggingRef.current = false;
41577
41745
  onSeekEnd?.();
41578
41746
  };
41747
+ const handleTimelineJump = useCallback((time2) => {
41748
+ const nextTime = Math.min(Math.max(time2, 0), duration || time2);
41749
+ const wasDragging = isDraggingRef.current;
41750
+ activePointerIdRef.current = null;
41751
+ setIsDragging(false);
41752
+ isDraggingRef.current = false;
41753
+ setDragTime(nextTime);
41754
+ if (!wasDragging) {
41755
+ onSeekStart?.();
41756
+ }
41757
+ onSeek(nextTime);
41758
+ onSeekEnd?.();
41759
+ }, [duration, onSeek, onSeekEnd, onSeekStart]);
41760
+ const handleTimelineMarkerPointerDown = useCallback((e, time2) => {
41761
+ e.preventDefault();
41762
+ e.stopPropagation();
41763
+ markerPointerJumpHandledRef.current = true;
41764
+ handleTimelineJump(time2);
41765
+ }, [handleTimelineJump]);
41766
+ const handleTimelineMarkerMouseDown = useCallback((e, time2) => {
41767
+ e.preventDefault();
41768
+ e.stopPropagation();
41769
+ if (markerPointerJumpHandledRef.current) {
41770
+ return;
41771
+ }
41772
+ markerPointerJumpHandledRef.current = true;
41773
+ handleTimelineJump(time2);
41774
+ }, [handleTimelineJump]);
41775
+ const handleTimelineMarkerClick = useCallback((e, time2) => {
41776
+ e.preventDefault();
41777
+ e.stopPropagation();
41778
+ if (markerPointerJumpHandledRef.current) {
41779
+ markerPointerJumpHandledRef.current = false;
41780
+ return;
41781
+ }
41782
+ handleTimelineJump(time2);
41783
+ }, [handleTimelineJump]);
41579
41784
  const updateTimeFromClientX = useCallback((clientX) => {
41580
41785
  if (!progressTrackRef.current) return;
41581
41786
  const rect = progressTrackRef.current.getBoundingClientRect();
@@ -41636,6 +41841,127 @@ var VideoControls = ({
41636
41841
  const displayTime = isDragging2 ? dragTime : currentTime;
41637
41842
  const progressPercent = getPercentage(displayTime, duration);
41638
41843
  const bufferedPercent = getPercentage(buffered, duration);
41844
+ const timelineBins = useMemo(() => {
41845
+ if (!timelineAnnotations?.minute_bins?.length || duration <= 0) {
41846
+ return [];
41847
+ }
41848
+ return timelineAnnotations.minute_bins.map((bin) => {
41849
+ const offset = typeof bin.offset_seconds === "number" && Number.isFinite(bin.offset_seconds) ? Math.max(0, bin.offset_seconds) : 0;
41850
+ const binDuration = typeof bin.duration_seconds === "number" && Number.isFinite(bin.duration_seconds) && bin.duration_seconds > 0 ? bin.duration_seconds : 60;
41851
+ if (offset >= duration) {
41852
+ return null;
41853
+ }
41854
+ const clampedDuration = Math.min(binDuration, Math.max(0, duration - offset));
41855
+ if (clampedDuration <= 0) {
41856
+ return null;
41857
+ }
41858
+ const clockLabel = formatTimelineClockTime(bin.start_time, timelineTimezone);
41859
+ const minuteExplanation = timelineExplanation?.minute_explanations?.find((explanation) => explanation.offset_seconds === offset || Boolean(explanation.start_time) && explanation.start_time === bin.start_time);
41860
+ const explanationLabel = minuteExplanation && minuteExplanation.confidence !== "low" ? minuteExplanation.primary_driver === "idle" ? "High Idle Detected" : minuteExplanation.primary_driver === "micro_stoppage" ? `Gap: ${Math.round(minuteExplanation.micro_stoppage_lost_seconds)}s lost` : minuteExplanation.primary_driver === "slow_cycle" ? typeof minuteExplanation.actual_cycle_time_seconds === "number" && Number.isFinite(minuteExplanation.actual_cycle_time_seconds) && typeof minuteExplanation.median_cycle_time_seconds === "number" && Number.isFinite(minuteExplanation.median_cycle_time_seconds) ? `Avg Cycle Time: ${formatTooltipSeconds(minuteExplanation.actual_cycle_time_seconds)} vs Shift Avg: ${formatTooltipSeconds(minuteExplanation.median_cycle_time_seconds)}` : `Slow cycle: ${Math.round(minuteExplanation.slow_cycle_lost_seconds)}s lost` : minuteExplanation.primary_driver === "low_output" ? "Low Output" : void 0 : void 0;
41861
+ return {
41862
+ ...bin,
41863
+ offset_seconds: offset,
41864
+ duration_seconds: clampedDuration,
41865
+ leftPercent: getPercentage(offset, duration),
41866
+ widthPercent: Math.max(getPercentage(clampedDuration, duration), 0.4),
41867
+ clockLabel,
41868
+ efficiencyLabel: formatEfficiencyPercent(bin.efficiency_percent),
41869
+ outputLabel: formatOutputLabel({ ...bin, duration_seconds: clampedDuration }),
41870
+ explanationLabel
41871
+ };
41872
+ }).filter((bin) => Boolean(bin));
41873
+ }, [duration, timelineAnnotations, timelineExplanation, timelineTimezone]);
41874
+ const hasTimelineAnnotations = timelineBins.length > 0;
41875
+ const worstMinuteMarkers = useMemo(() => {
41876
+ const efficiencySource = timelineBins.filter((bin) => typeof bin.efficiency_percent === "number" && Number.isFinite(bin.efficiency_percent)).slice().sort((a, b) => a.efficiency_percent - b.efficiency_percent || a.offset_seconds - b.offset_seconds).slice(0, 3).map((bin, index) => ({
41877
+ start_time: bin.start_time,
41878
+ offset_seconds: bin.offset_seconds,
41879
+ duration_seconds: bin.duration_seconds,
41880
+ avg_flow_percent: bin.avg_flow_percent,
41881
+ rank: index + 1
41882
+ }));
41883
+ const source = efficiencySource.length ? efficiencySource : timelineAnnotations?.worst_minutes?.length ? timelineAnnotations.worst_minutes : timelineBins.filter((bin) => typeof bin.avg_flow_percent === "number" && Number.isFinite(bin.avg_flow_percent)).sort((a, b) => a.avg_flow_percent - b.avg_flow_percent).slice(0, 3);
41884
+ return source.filter((marker) => typeof marker.offset_seconds === "number" && Number.isFinite(marker.offset_seconds)).slice(0, 3).map((marker, index) => {
41885
+ const offset = Math.max(0, Math.min(duration, marker.offset_seconds));
41886
+ const matchingBin = timelineBins.find((bin) => bin.offset_seconds === marker.offset_seconds || Boolean(marker.start_time) && bin.start_time === marker.start_time);
41887
+ const markerDuration = "duration_seconds" in marker ? Number(marker.duration_seconds || 0) : 0;
41888
+ const width = markerDuration > 0 ? markerDuration : Number(matchingBin?.duration_seconds || 0);
41889
+ const centerOffset = Math.min(duration, offset + Math.max(0, width) / 2);
41890
+ return {
41891
+ ...marker,
41892
+ rank: "rank" in marker ? marker.rank : index + 1,
41893
+ leftPercent: getPercentage(centerOffset, duration)
41894
+ };
41895
+ });
41896
+ }, [duration, timelineAnnotations, timelineBins]);
41897
+ const transitionMarkers = useMemo(() => {
41898
+ if (timelineBins.length < 2 || duration <= 0) {
41899
+ return [];
41900
+ }
41901
+ const orderedBins = timelineBins.slice().sort((left, right) => left.offset_seconds - right.offset_seconds);
41902
+ return orderedBins.slice(1).map((bin, index) => {
41903
+ const previousBin = orderedBins[index];
41904
+ const fromOutputUnits = getBinOutputUnits(previousBin);
41905
+ const toOutputUnits = getBinOutputUnits(bin);
41906
+ const hasOutputValues = fromOutputUnits !== null && toOutputUnits !== null && fromOutputUnits > 0;
41907
+ const fromEfficiency = previousBin.efficiency_percent;
41908
+ const toEfficiency = bin.efficiency_percent;
41909
+ const hasEfficiencyValues = typeof fromEfficiency === "number" && typeof toEfficiency === "number" && Number.isFinite(fromEfficiency) && Number.isFinite(toEfficiency) && fromEfficiency > 0;
41910
+ if (!hasOutputValues && !hasEfficiencyValues) {
41911
+ return null;
41912
+ }
41913
+ const fromValue = hasOutputValues ? fromOutputUnits : fromEfficiency;
41914
+ const toValue2 = hasOutputValues ? toOutputUnits : toEfficiency;
41915
+ const relativeDrop = (fromValue - toValue2) / fromValue;
41916
+ if (relativeDrop <= 0.5) {
41917
+ return null;
41918
+ }
41919
+ const transitionOffset = Math.min(Math.max(bin.offset_seconds, 0), duration);
41920
+ return {
41921
+ offsetSeconds: transitionOffset,
41922
+ leftPercent: getPercentage(transitionOffset, duration),
41923
+ fromValue,
41924
+ toValue: toValue2,
41925
+ relativeDrop,
41926
+ fromOutputUnits,
41927
+ toOutputUnits,
41928
+ source: hasOutputValues ? "output" : "efficiency",
41929
+ absoluteDrop: fromValue - toValue2
41930
+ };
41931
+ }).filter((marker) => Boolean(marker)).sort((left, right) => {
41932
+ const relativeDiff = right.relativeDrop - left.relativeDrop;
41933
+ if (relativeDiff !== 0) {
41934
+ return relativeDiff;
41935
+ }
41936
+ const outputDiff = right.absoluteDrop - left.absoluteDrop;
41937
+ if (outputDiff !== 0) {
41938
+ return outputDiff;
41939
+ }
41940
+ return left.offsetSeconds - right.offsetSeconds;
41941
+ }).slice(0, 3).map((marker, index) => ({
41942
+ ...marker,
41943
+ rank: index + 1
41944
+ }));
41945
+ }, [duration, timelineBins]);
41946
+ worstMinuteMarkers[0] || null;
41947
+ const updateHoveredTimelineBin = useCallback((clientX) => {
41948
+ if (!hasTimelineAnnotations || !progressTrackRef.current || duration <= 0) {
41949
+ setHoveredTimelineBin(null);
41950
+ return;
41951
+ }
41952
+ const rect = progressTrackRef.current.getBoundingClientRect();
41953
+ if (!rect.width) {
41954
+ setHoveredTimelineBin(null);
41955
+ return;
41956
+ }
41957
+ const pct = Math.min(Math.max((clientX - rect.left) / rect.width, 0), 1);
41958
+ const hoverTime = pct * duration;
41959
+ const nextBin = timelineBins.find((bin) => hoverTime >= bin.offset_seconds && hoverTime <= bin.offset_seconds + bin.duration_seconds) || null;
41960
+ setHoveredTimelineBin(nextBin);
41961
+ }, [duration, hasTimelineAnnotations, timelineBins]);
41962
+ const handleProgressMouseMove = useCallback((e) => {
41963
+ updateHoveredTimelineBin(e.clientX);
41964
+ }, [updateHoveredTimelineBin]);
41639
41965
  return /* @__PURE__ */ jsxs(
41640
41966
  "div",
41641
41967
  {
@@ -41647,12 +41973,16 @@ var VideoControls = ({
41647
41973
  "div",
41648
41974
  {
41649
41975
  ref: progressTrackRef,
41650
- className: "relative h-1 mb-4 group cursor-pointer",
41976
+ className: "relative z-10 h-1 mb-4 group cursor-pointer",
41651
41977
  onMouseEnter: () => setIsHoveringProgressBar(true),
41652
- onMouseLeave: () => setIsHoveringProgressBar(false),
41978
+ onMouseMove: handleProgressMouseMove,
41979
+ onMouseLeave: () => {
41980
+ setIsHoveringProgressBar(false);
41981
+ setHoveredTimelineBin(null);
41982
+ },
41653
41983
  onPointerDown: handlePointerDown,
41654
41984
  children: [
41655
- /* @__PURE__ */ jsx("div", { className: "absolute -top-4 -bottom-4 left-0 right-0 z-20" }),
41985
+ /* @__PURE__ */ jsx("div", { className: "absolute -top-4 bottom-0 left-0 right-0 z-20" }),
41656
41986
  /* @__PURE__ */ jsx("div", { className: "absolute top-0 left-0 right-0 bottom-0 bg-white/20 rounded-full overflow-hidden z-0", children: /* @__PURE__ */ jsx(
41657
41987
  "div",
41658
41988
  {
@@ -41686,17 +42016,47 @@ var VideoControls = ({
41686
42016
  onInput: handleSeekChange,
41687
42017
  onMouseDown: handleSeekStart,
41688
42018
  onMouseUp: handleSeekEnd,
42019
+ onMouseMove: handleProgressMouseMove,
41689
42020
  onTouchStart: handleSeekStart,
41690
42021
  onTouchEnd: handleSeekEnd,
41691
42022
  onPointerDown: handlePointerDown,
41692
- className: "absolute left-0 right-0 top-[-12px] bottom-[-12px] w-full h-auto opacity-0 cursor-pointer z-30 margin-0 padding-0"
42023
+ className: "absolute left-0 right-0 top-[-12px] bottom-0 w-full h-auto opacity-0 cursor-pointer z-30 margin-0 padding-0"
42024
+ }
42025
+ ),
42026
+ hasTimelineAnnotations && transitionMarkers.map((marker) => /* @__PURE__ */ jsx(
42027
+ "button",
42028
+ {
42029
+ type: "button",
42030
+ "aria-label": marker.source === "output" ? `Output drop marker ${marker.rank}: output ${formatCompactNumber(marker.fromValue)} to ${formatCompactNumber(marker.toValue)} (${Math.round(marker.relativeDrop * 100)}% drop)` : `Output drop marker ${marker.rank}: efficiency ${Math.round(marker.fromValue)}% to ${Math.round(marker.toValue)}% (${Math.round(marker.relativeDrop * 100)}% drop)`,
42031
+ title: marker.source === "output" ? `Output drop: ${formatCompactNumber(marker.fromValue)} to ${formatCompactNumber(marker.toValue)}` : `Output drop: ${Math.round(marker.fromValue)}% to ${Math.round(marker.toValue)}%`,
42032
+ onPointerDownCapture: (e) => handleTimelineMarkerPointerDown(e, marker.offsetSeconds),
42033
+ onMouseDownCapture: (e) => handleTimelineMarkerMouseDown(e, marker.offsetSeconds),
42034
+ onClickCapture: (e) => handleTimelineMarkerClick(e, marker.offsetSeconds),
42035
+ className: "absolute top-1/2 -translate-y-1/2 z-[70] flex h-5 w-5 cursor-pointer items-center justify-center rounded-full border border-white bg-sky-500 p-0 text-center text-[9px] font-bold leading-none text-white shadow hover:bg-sky-400 focus:outline-none focus:ring-2 focus:ring-sky-200",
42036
+ style: { left: `calc(${marker.leftPercent}% - 10px)`, zIndex: 70, pointerEvents: "auto" },
42037
+ children: marker.rank
42038
+ },
42039
+ `${marker.rank}-${marker.offsetSeconds}`
42040
+ )),
42041
+ hasTimelineAnnotations && hoveredTimelineBin && /* @__PURE__ */ jsxs(
42042
+ "div",
42043
+ {
42044
+ className: "absolute bottom-full z-50 mb-2 -translate-x-1/2 rounded bg-slate-900 px-2 py-1 text-[11px] font-semibold text-white shadow-lg",
42045
+ style: { left: `${hoveredTimelineBin.leftPercent + hoveredTimelineBin.widthPercent / 2}%` },
42046
+ children: [
42047
+ hoveredTimelineBin.clockLabel || formatTime2(hoveredTimelineBin.offset_seconds),
42048
+ " | ",
42049
+ hoveredTimelineBin.efficiencyLabel,
42050
+ hoveredTimelineBin.outputLabel ? ` | ${hoveredTimelineBin.outputLabel}` : "",
42051
+ hoveredTimelineBin.explanationLabel ? ` | ${hoveredTimelineBin.explanationLabel}` : ""
42052
+ ]
41693
42053
  }
41694
42054
  )
41695
42055
  ]
41696
42056
  }
41697
42057
  ),
41698
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-white", children: [
41699
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
42058
+ /* @__PURE__ */ jsxs("div", { className: "relative z-40 flex items-center justify-between text-white", children: [
42059
+ /* @__PURE__ */ jsxs("div", { className: "relative z-50 flex items-center gap-4", children: [
41700
42060
  /* @__PURE__ */ jsx(
41701
42061
  "button",
41702
42062
  {
@@ -41977,7 +42337,10 @@ var HlsVideoPlayer = forwardRef(({
41977
42337
  onClick,
41978
42338
  onShare,
41979
42339
  isShareLoading,
41980
- isShareCopied
42340
+ isShareCopied,
42341
+ timelineAnnotations,
42342
+ timelineExplanation,
42343
+ timelineTimezone
41981
42344
  }, ref) => {
41982
42345
  const supabase = useSupabase();
41983
42346
  const videoContainerRef = useRef(null);
@@ -42639,6 +43002,7 @@ var HlsVideoPlayer = forwardRef(({
42639
43002
  const handleSeek = useCallback((time2) => {
42640
43003
  if (videoRef.current) {
42641
43004
  videoRef.current.currentTime = time2;
43005
+ setCurrentTime(time2);
42642
43006
  }
42643
43007
  }, []);
42644
43008
  const handleSeekStart = useCallback(() => {
@@ -42745,7 +43109,10 @@ var HlsVideoPlayer = forwardRef(({
42745
43109
  onToggleFullscreen: handleToggleFullscreen,
42746
43110
  onShare,
42747
43111
  isShareLoading,
42748
- isShareCopied
43112
+ isShareCopied,
43113
+ timelineAnnotations,
43114
+ timelineExplanation,
43115
+ timelineTimezone
42749
43116
  }
42750
43117
  )
42751
43118
  ]
@@ -43066,6 +43433,7 @@ var CroppedHlsVideoPlayer = forwardRef(({
43066
43433
  const handleSeek = useCallback((time2) => {
43067
43434
  if (hiddenVideoRef.current) {
43068
43435
  hiddenVideoRef.current.currentTime(time2);
43436
+ setCurrentTime(time2);
43069
43437
  setTimeout(() => renderFrameToCanvas(), 50);
43070
43438
  userSeekingRef.current = true;
43071
43439
  }
@@ -43211,7 +43579,10 @@ var CroppedHlsVideoPlayer = forwardRef(({
43211
43579
  onToggleFullscreen: handleToggleFullscreen,
43212
43580
  onShare: videoProps.onShare,
43213
43581
  isShareLoading: videoProps.isShareLoading,
43214
- isShareCopied: videoProps.isShareCopied
43582
+ isShareCopied: videoProps.isShareCopied,
43583
+ timelineAnnotations: videoProps.timelineAnnotations,
43584
+ timelineExplanation: videoProps.timelineExplanation,
43585
+ timelineTimezone: videoProps.timelineTimezone
43215
43586
  }
43216
43587
  )
43217
43588
  ]
@@ -43220,6 +43591,100 @@ var CroppedHlsVideoPlayer = forwardRef(({
43220
43591
  });
43221
43592
  CroppedHlsVideoPlayer.displayName = "CroppedHlsVideoPlayer";
43222
43593
  var CroppedVideoPlayer = CroppedHlsVideoPlayer;
43594
+ var formatSeconds = (value) => {
43595
+ const seconds = Math.max(0, Math.round(value));
43596
+ if (seconds < 60) {
43597
+ return `${seconds}s`;
43598
+ }
43599
+ const minutes = Math.floor(seconds / 60);
43600
+ const remainingSeconds = seconds % 60;
43601
+ return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
43602
+ };
43603
+ var buildLostChip = (explanation) => {
43604
+ const totals = explanation.summary.totals;
43605
+ const explicitTotalLostSeconds = Number(totals.total_lost_seconds);
43606
+ const lostSeconds = Number.isFinite(explicitTotalLostSeconds) ? explicitTotalLostSeconds : Math.max(
43607
+ Number(totals.idle_overlap_seconds) || 0,
43608
+ Number(totals.micro_stoppage_lost_seconds) || 0,
43609
+ Number(totals.slow_cycle_lost_seconds) || 0
43610
+ );
43611
+ if (lostSeconds > 0) {
43612
+ return `${formatSeconds(lostSeconds)} lost`;
43613
+ }
43614
+ if (Number(totals.idle_overlap_percent) > 0) {
43615
+ return `${Math.round(totals.idle_overlap_percent)}% idle`;
43616
+ }
43617
+ return null;
43618
+ };
43619
+ var RedFlowDiagnosticOverlay = ({
43620
+ timeline,
43621
+ explanation,
43622
+ aiSummary,
43623
+ aiSummaryLoading = false,
43624
+ aiSummaryError = null,
43625
+ className = ""
43626
+ }) => {
43627
+ const summary = explanation?.summary || null;
43628
+ const driverKeys = useMemo(() => getRedFlowDisplayDriverKeys(summary), [summary]);
43629
+ const outputSummary = useMemo(() => summarizeRedFlowOutput(timeline, summary), [summary, timeline]);
43630
+ const hasOutputIssue = Boolean(
43631
+ outputSummary && Number.isFinite(outputSummary.expected) && Number.isFinite(outputSummary.actual) && outputSummary.expected > outputSummary.actual
43632
+ );
43633
+ if (driverKeys.length === 0 && !hasOutputIssue) {
43634
+ return null;
43635
+ }
43636
+ const driverLabel = driverKeys.length > 0 ? driverKeys.map(getRedFlowDriverLabel).filter(Boolean).join(" + ") : "Low Output";
43637
+ if (!driverLabel) {
43638
+ return null;
43639
+ }
43640
+ const shouldShowLostChip = driverKeys.some((driver) => driver !== "low_output");
43641
+ const chips = explanation && shouldShowLostChip ? [buildLostChip(explanation)].filter((chip) => Boolean(chip)) : [];
43642
+ const shouldShowHeadline = Boolean(summary && driverKeys.length > 0 && summary.primary_driver !== "unknown");
43643
+ const aiSummaryBullets = Array.isArray(aiSummary?.bullets) ? aiSummary.bullets.map((bullet) => String(bullet || "").trim()).filter(Boolean).slice(0, 3) : [];
43644
+ const shouldShowAiSummary = !aiSummaryError && aiSummaryBullets.length === 3;
43645
+ return /* @__PURE__ */ jsxs(
43646
+ "div",
43647
+ {
43648
+ className: `pointer-events-none absolute z-20 w-[240px] max-w-[calc(100%-2rem)] rounded-xl border border-white/10 bg-black/60 p-5 text-white shadow-xl backdrop-blur-md ${className}`,
43649
+ children: [
43650
+ outputSummary ? /* @__PURE__ */ jsxs("div", { className: "mb-5 space-y-4", children: [
43651
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
43652
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-white/50", children: "Output:" }),
43653
+ /* @__PURE__ */ jsxs("span", { className: "text-sm font-bold text-white", children: [
43654
+ /* @__PURE__ */ jsx("span", { className: "text-red-400", children: formatRedFlowOutputCount(outputSummary.actual) }),
43655
+ /* @__PURE__ */ jsx("span", { className: "px-1 text-white/30", children: "/" }),
43656
+ formatRedFlowOutputCount(outputSummary.expected)
43657
+ ] })
43658
+ ] }),
43659
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
43660
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-white/50", children: "Reason:" }),
43661
+ /* @__PURE__ */ jsx("span", { className: "rounded bg-red-500/10 px-2 py-1 text-[10px] font-semibold tracking-wide text-red-400 ring-1 ring-inset ring-red-500/20", children: "Low output" })
43662
+ ] })
43663
+ ] }) : /* @__PURE__ */ jsx("div", { className: "mb-4 flex items-center gap-2", children: /* @__PURE__ */ jsx("span", { className: "rounded bg-red-500/10 px-2 py-1 text-[10px] font-semibold tracking-wide text-red-400 ring-1 ring-inset ring-red-500/20", children: driverLabel }) }),
43664
+ (shouldShowAiSummary || aiSummaryLoading || chips.length > 0 || shouldShowHeadline) && /* @__PURE__ */ jsx("div", { className: "mb-4 h-px w-full bg-white/10" }),
43665
+ !shouldShowAiSummary && !aiSummaryLoading && shouldShowHeadline && summary?.headline ? /* @__PURE__ */ jsx("div", { className: "mb-3 text-[13px] font-medium leading-relaxed text-white/90", children: summary.headline }) : null,
43666
+ !shouldShowAiSummary && !aiSummaryLoading && chips.length > 0 ? /* @__PURE__ */ jsx("div", { className: "mb-3 flex flex-wrap gap-2", children: chips.slice(0, 3).map((chip) => /* @__PURE__ */ jsx(
43667
+ "span",
43668
+ {
43669
+ className: "rounded border border-white/10 bg-white/5 px-2 py-0.5 text-[11px] font-medium text-white/70",
43670
+ children: chip
43671
+ },
43672
+ chip
43673
+ )) }) : null,
43674
+ shouldShowAiSummary ? /* @__PURE__ */ jsxs("div", { className: "mt-1", children: [
43675
+ /* @__PURE__ */ jsx("div", { className: "mb-3 text-[10px] font-bold uppercase tracking-[0.15em] text-white/40", children: "AI summary" }),
43676
+ /* @__PURE__ */ jsx("ol", { className: "space-y-3 text-[12px] leading-relaxed text-white/80", children: aiSummaryBullets.map((bullet, index) => /* @__PURE__ */ jsxs("li", { className: "flex gap-2", children: [
43677
+ /* @__PURE__ */ jsxs("span", { className: "font-semibold text-white/40", children: [
43678
+ index + 1,
43679
+ "."
43680
+ ] }),
43681
+ /* @__PURE__ */ jsx("span", { children: bullet })
43682
+ ] }, `${index}-${bullet}`)) })
43683
+ ] }) : aiSummaryLoading ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-[13px] font-medium text-white/60", children: "Generating summary..." }) : null
43684
+ ]
43685
+ }
43686
+ );
43687
+ };
43223
43688
  function useWorkspaceCrop(workspaceId) {
43224
43689
  const supabase = useSupabase();
43225
43690
  const [crop, setCrop] = useState(null);
@@ -43269,7 +43734,7 @@ function Skeleton({ className, ...props }) {
43269
43734
  var Select = SelectPrimitive.Root;
43270
43735
  var SelectGroup = SelectPrimitive.Group;
43271
43736
  var SelectValue = SelectPrimitive.Value;
43272
- var SelectTrigger = React147.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
43737
+ var SelectTrigger = React148.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
43273
43738
  SelectPrimitive.Trigger,
43274
43739
  {
43275
43740
  ref,
@@ -43285,7 +43750,7 @@ var SelectTrigger = React147.forwardRef(({ className, children, ...props }, ref)
43285
43750
  }
43286
43751
  ));
43287
43752
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
43288
- var SelectScrollUpButton = React147.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
43753
+ var SelectScrollUpButton = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
43289
43754
  SelectPrimitive.ScrollUpButton,
43290
43755
  {
43291
43756
  ref,
@@ -43295,7 +43760,7 @@ var SelectScrollUpButton = React147.forwardRef(({ className, ...props }, ref) =>
43295
43760
  }
43296
43761
  ));
43297
43762
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
43298
- var SelectScrollDownButton = React147.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
43763
+ var SelectScrollDownButton = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
43299
43764
  SelectPrimitive.ScrollDownButton,
43300
43765
  {
43301
43766
  ref,
@@ -43305,7 +43770,7 @@ var SelectScrollDownButton = React147.forwardRef(({ className, ...props }, ref)
43305
43770
  }
43306
43771
  ));
43307
43772
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
43308
- var SelectContent = React147.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
43773
+ var SelectContent = React148.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
43309
43774
  SelectPrimitive.Content,
43310
43775
  {
43311
43776
  ref,
@@ -43333,7 +43798,7 @@ var SelectContent = React147.forwardRef(({ className, children, position = "popp
43333
43798
  }
43334
43799
  ) }));
43335
43800
  SelectContent.displayName = SelectPrimitive.Content.displayName;
43336
- var SelectLabel = React147.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
43801
+ var SelectLabel = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
43337
43802
  SelectPrimitive.Label,
43338
43803
  {
43339
43804
  ref,
@@ -43342,7 +43807,7 @@ var SelectLabel = React147.forwardRef(({ className, ...props }, ref) => /* @__PU
43342
43807
  }
43343
43808
  ));
43344
43809
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
43345
- var SelectItem = React147.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
43810
+ var SelectItem = React148.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
43346
43811
  SelectPrimitive.Item,
43347
43812
  {
43348
43813
  ref,
@@ -43358,7 +43823,7 @@ var SelectItem = React147.forwardRef(({ className, children, ...props }, ref) =>
43358
43823
  }
43359
43824
  ));
43360
43825
  SelectItem.displayName = SelectPrimitive.Item.displayName;
43361
- var SelectSeparator = React147.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
43826
+ var SelectSeparator = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
43362
43827
  SelectPrimitive.Separator,
43363
43828
  {
43364
43829
  ref,
@@ -43984,7 +44449,7 @@ var TimePickerDropdown = ({
43984
44449
  )
43985
44450
  ] });
43986
44451
  };
43987
- var SilentErrorBoundary = class extends React147__default.Component {
44452
+ var SilentErrorBoundary = class extends React148__default.Component {
43988
44453
  constructor(props) {
43989
44454
  super(props);
43990
44455
  this.handleClearAndReload = () => {
@@ -44729,6 +45194,9 @@ var AvatarUpload = ({
44729
45194
  ] });
44730
45195
  };
44731
45196
  var CLIP_METADATA_PAGE_SIZE = 50;
45197
+ var RECENT_FLOW_RED_STREAK_CLIP_TYPE2 = "recent_flow_red_streak";
45198
+ var RECENT_FLOW_RED_STREAK_DISPLAY_LABEL = "Low moments";
45199
+ var RECENT_FLOW_RED_STREAK_DISPLAY_SUBTITLE = "Moments of low efficiency";
44732
45200
  var parseCycleTime = (value) => {
44733
45201
  if (typeof value === "number" && Number.isFinite(value)) {
44734
45202
  return value;
@@ -44757,10 +45225,37 @@ var formatDurationLabel = (seconds) => {
44757
45225
  }
44758
45226
  return `${Math.round(roundedSeconds / 60)} min`;
44759
45227
  };
45228
+ var sortRedFlowMetadata = (clips) => {
45229
+ return clips.slice().sort((left, right) => {
45230
+ const getOutputShortfall = (clip) => {
45231
+ const directShortfall = parseCycleTime(clip.red_flow_output_shortfall_units);
45232
+ if (directShortfall !== null) {
45233
+ return directShortfall;
45234
+ }
45235
+ return getRedFlowOutputShortfallUnits(clip.red_flow_timeline);
45236
+ };
45237
+ const leftScore = getOutputShortfall(left);
45238
+ const rightScore = getOutputShortfall(right);
45239
+ const leftNull = leftScore === null;
45240
+ const rightNull = rightScore === null;
45241
+ if (leftNull !== rightNull) {
45242
+ return leftNull ? 1 : -1;
45243
+ }
45244
+ if (leftScore !== null && rightScore !== null && leftScore !== rightScore) {
45245
+ return rightScore - leftScore;
45246
+ }
45247
+ const leftTime = new Date(left.clip_timestamp).getTime();
45248
+ const rightTime = new Date(right.clip_timestamp).getTime();
45249
+ return (Number.isFinite(rightTime) ? rightTime : 0) - (Number.isFinite(leftTime) ? leftTime : 0);
45250
+ });
45251
+ };
44760
45252
  var getSeverityIcon = (severity, categoryId, cycleTimeSeconds, targetCycleTime, clipId) => {
44761
45253
  if (categoryId === "idle_time" || categoryId === "low_value" || categoryId === "longest-idles") {
44762
45254
  return null;
44763
45255
  }
45256
+ if (categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2) {
45257
+ return /* @__PURE__ */ jsx(AlertTriangle, { className: "h-3 w-3 text-red-500" });
45258
+ }
44764
45259
  if (categoryId === "cycle_completion" && targetCycleTime && targetCycleTime > 0 && cycleTimeSeconds !== null && cycleTimeSeconds !== void 0) {
44765
45260
  if (cycleTimeSeconds <= targetCycleTime) {
44766
45261
  return /* @__PURE__ */ jsx(CheckCircle, { className: "h-3 w-3 text-green-500" });
@@ -44832,6 +45327,7 @@ var FileManagerFilters = ({
44832
45327
  idleTimeVlmEnabled = false,
44833
45328
  showPercentileCycleFilters = true,
44834
45329
  prefetchedClipMetadata,
45330
+ externallyManagedLoadingCategories,
44835
45331
  activeCategoryLoading,
44836
45332
  idleClipSort = "latest",
44837
45333
  onIdleClipSortChange,
@@ -44916,11 +45412,11 @@ var FileManagerFilters = ({
44916
45412
  if (prefetchedClipMetadata && Array.isArray(prefetchedClipMetadata[categoryId]) && prefetchedClipMetadata[categoryId].length > 0) {
44917
45413
  return true;
44918
45414
  }
44919
- if (activeCategoryLoading !== void 0 && categoryId === activeFilter) {
45415
+ if (externallyManagedLoadingCategories?.[categoryId]) {
44920
45416
  return true;
44921
45417
  }
44922
45418
  return false;
44923
- }, [prefetchedClipMetadata, activeCategoryLoading, activeFilter]);
45419
+ }, [prefetchedClipMetadata, externallyManagedLoadingCategories]);
44924
45420
  useEffect(() => {
44925
45421
  if (!prefetchedClipMetadata) {
44926
45422
  return;
@@ -45041,6 +45537,9 @@ var FileManagerFilters = ({
45041
45537
  [idleReasonOptions, idleLabelFilter]
45042
45538
  );
45043
45539
  const getClipBadge = useCallback((node) => {
45540
+ if (node.categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2) {
45541
+ return null;
45542
+ }
45044
45543
  if (node.categoryId === "idle_time" || node.categoryId === "low_value") {
45045
45544
  return { text: "Idle", className: "bg-red-100 text-red-700" };
45046
45545
  }
@@ -45059,6 +45558,23 @@ var FileManagerFilters = ({
45059
45558
  }
45060
45559
  return { text: "Fast", className: "bg-green-100 text-green-700" };
45061
45560
  }, [resolvedTargetCycleTime]);
45561
+ const getRedFlowDriverBadges = useCallback((node) => {
45562
+ if (node.categoryId !== RECENT_FLOW_RED_STREAK_CLIP_TYPE2) {
45563
+ return [];
45564
+ }
45565
+ const summary = node.redFlowExplanationSummary || null;
45566
+ const drivers = getRedFlowDisplayDriverKeys(summary);
45567
+ if (drivers.length === 0) {
45568
+ return [{
45569
+ text: "Low Output",
45570
+ className: "bg-slate-50 text-slate-600 border border-slate-200"
45571
+ }];
45572
+ }
45573
+ return drivers.slice(0, 3).map((driver) => ({
45574
+ text: getRedFlowDriverLabel(driver),
45575
+ className: "bg-rose-50 text-rose-700 border border-rose-200"
45576
+ }));
45577
+ }, []);
45062
45578
  const getAuthToken4 = useCallback(async () => {
45063
45579
  try {
45064
45580
  return await getAccessTokenOrRedirect(supabase, { redirectReason: "session_expired" });
@@ -45067,7 +45583,7 @@ var FileManagerFilters = ({
45067
45583
  return null;
45068
45584
  }
45069
45585
  }, [supabase]);
45070
- const getMetadataLoadingKey = useCallback((categoryId, page) => `${categoryId}-${page}-${categoryId === "idle_time" ? idleClipSort : "latest"}`, [idleClipSort]);
45586
+ const getMetadataLoadingKey = useCallback((categoryId, page) => `${categoryId}-${page}-${categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest"}`, [idleClipSort]);
45071
45587
  const fetchClipMetadataPage = useCallback(async (categoryId, page = 1) => {
45072
45588
  if (!workspaceId || !date || shift === void 0) {
45073
45589
  throw new Error("Missing required params for clip metadata fetch");
@@ -45088,7 +45604,7 @@ var FileManagerFilters = ({
45088
45604
  knownTotal: typeof counts?.[categoryId] === "number" ? counts[categoryId] : null,
45089
45605
  snapshotDateTime,
45090
45606
  snapshotClipId,
45091
- sort: categoryId === "idle_time" ? idleClipSort : "latest"
45607
+ sort: categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest"
45092
45608
  }),
45093
45609
  redirectReason: "session_expired"
45094
45610
  });
@@ -45459,7 +45975,7 @@ var FileManagerFilters = ({
45459
45975
  fetchClipMetadata(activeFilter, 1);
45460
45976
  }
45461
45977
  }
45462
- }, [activeFilter, isCategoryExternallyManaged]);
45978
+ }, [activeFilter]);
45463
45979
  useEffect(() => {
45464
45980
  const handleEscape = (e) => {
45465
45981
  if (e.key === "Escape") {
@@ -45542,6 +46058,9 @@ var FileManagerFilters = ({
45542
46058
  const categoryCount = counts?.[category.id] || 0;
45543
46059
  const categoryClips = clipMetadata[category.id] || [];
45544
46060
  let filteredClips = categoryClips.filter((clip) => isClipInTimeRange(clip.clip_timestamp));
46061
+ if (category.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2) {
46062
+ filteredClips = sortRedFlowMetadata(filteredClips);
46063
+ }
45545
46064
  if (category.id === "idle_time" && idleLabelFilter) {
45546
46065
  filteredClips = filteredClips.filter((clip) => {
45547
46066
  const classification = getIdleTimeClassification(clip.clipId || clip.id);
@@ -45556,15 +46075,18 @@ var FileManagerFilters = ({
45556
46075
  const cycleTime = extractCycleTimeSeconds(clip);
45557
46076
  const idleDuration = category.id === "idle_time" ? clip.idle_duration_seconds ?? clip.duration : null;
45558
46077
  const idleDurationLabel = formatDurationLabel(idleDuration);
46078
+ const redFlowDurationLabel = category.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? formatDurationLabel(clip.duration) : null;
45559
46079
  const baseTimeLabel = formatClipExplorerTimeLabel({
45560
46080
  categoryId: category.id,
45561
46081
  clipTimestamp: clip.clip_timestamp,
45562
46082
  timezone,
45563
46083
  durationSeconds: idleDuration ?? clip.duration,
45564
46084
  idleStartTime: clip.idle_start_time,
45565
- idleEndTime: clip.idle_end_time
46085
+ idleEndTime: clip.idle_end_time,
46086
+ clipStartTime: clip.clip_start_time,
46087
+ clipEndTime: clip.clip_end_time
45566
46088
  });
45567
- const displayLabel = `${baseTimeLabel}${idleDurationLabel && category.id === "idle_time" ? ` - (${idleDurationLabel})` : ""}${clip.duration && category.id !== "idle_time" && category.id !== "low_value" ? ` - (${clip.duration.toFixed(1)}s)` : ""}`;
46089
+ const displayLabel = `${baseTimeLabel}${idleDurationLabel && category.id === "idle_time" ? ` - (${idleDurationLabel})` : ""}${redFlowDurationLabel ? ` - (${redFlowDurationLabel})` : ""}${clip.duration && category.id !== "idle_time" && category.id !== "low_value" && category.id !== RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? ` - (${clip.duration.toFixed(1)}s)` : ""}`;
45568
46090
  return {
45569
46091
  id: clip.id,
45570
46092
  label: displayLabel,
@@ -45580,14 +46102,18 @@ var FileManagerFilters = ({
45580
46102
  cycleTimeSeconds: cycleTime,
45581
46103
  duration: idleDuration ?? clip.duration,
45582
46104
  // Store duration for custom badge rendering
45583
- cycleItemCount: clip.cycle_item_count ?? null
46105
+ cycleItemCount: clip.cycle_item_count ?? null,
46106
+ redFlowSeverityScore: clip.red_flow_severity_score ?? null,
46107
+ redFlowExplanationSummary: clip.red_flow_explanation_summary ?? clip.red_flow_explanation?.summary ?? null
45584
46108
  };
45585
46109
  });
46110
+ const categoryLabel = category.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? RECENT_FLOW_RED_STREAK_DISPLAY_LABEL : category.label;
46111
+ const categorySubtitle = category.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? RECENT_FLOW_RED_STREAK_DISPLAY_SUBTITLE : category.subtitle || category.description;
45586
46112
  regularCategoryNodes.push({
45587
46113
  id: category.id,
45588
- label: category.label,
45589
- subtitle: category.subtitle || category.description,
45590
- description: category.description,
46114
+ label: categoryLabel,
46115
+ subtitle: categorySubtitle,
46116
+ description: category.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? RECENT_FLOW_RED_STREAK_DISPLAY_SUBTITLE : category.description,
45591
46117
  type: "category",
45592
46118
  count: displayCount,
45593
46119
  // Use filtered count when time filter is active
@@ -45699,7 +46225,7 @@ var FileManagerFilters = ({
45699
46225
  })
45700
46226
  } */
45701
46227
  ] : [];
45702
- const orderedIds = ["cycle_completion", "fast-cycles", "slow-cycles", "idle_time"];
46228
+ const orderedIds = [RECENT_FLOW_RED_STREAK_CLIP_TYPE2, "cycle_completion", "fast-cycles", "slow-cycles", "idle_time"];
45703
46229
  orderedIds.forEach((orderedId) => {
45704
46230
  const percentileCategory = percentileCategories.find((cat) => cat.id === orderedId);
45705
46231
  const shouldIncludePercentile = percentileCategory ? typeof percentileCategory.count === "number" && percentileCategory.count > 0 : false;
@@ -45812,8 +46338,15 @@ var FileManagerFilters = ({
45812
46338
  const isCurrentVideo = currentVideoId === node.id;
45813
46339
  const isCountUnknown = node.type === "percentile-category" && node.count === null;
45814
46340
  const hasChildren = isCountUnknown || (node.count || 0) > 0;
45815
- const showExternalLoadingState = Boolean(
45816
- activeCategoryLoading && isExpanded && node.id === activeFilter && (node.type === "category" || node.type === "percentile-category")
46341
+ const hasLoadedChildren = (clipMetadata[node.id]?.length || percentileClips[node.id]?.length || 0) > 0;
46342
+ const loadedPage = categoryPages[node.id] || 0;
46343
+ const pageOneLoadingKey = getMetadataLoadingKey(node.id, 1);
46344
+ const nextMetadataPage = loadedPage + 1;
46345
+ const nextLoadMorePage = (categoryPages[node.id] || 1) + 1;
46346
+ const isPageOneLoading = loadingCategories.has(pageOneLoadingKey);
46347
+ const isLoadMoreLoading = loadedPage > 0 && loadingCategories.has(getMetadataLoadingKey(node.id, nextMetadataPage));
46348
+ const showInitialLoadingState = Boolean(
46349
+ isExpanded && !hasLoadedChildren && (node.type === "category" || node.type === "percentile-category") && (isPageOneLoading || activeCategoryLoading && node.id === activeFilter)
45817
46350
  );
45818
46351
  const colorClasses = node.color ? getColorClasses(node.color) : null;
45819
46352
  return /* @__PURE__ */ jsxs("div", { className: "select-none animate-in", children: [
@@ -45855,9 +46388,9 @@ var FileManagerFilters = ({
45855
46388
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 flex items-center justify-between", children: [
45856
46389
  /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
45857
46390
  /* @__PURE__ */ jsx("div", { className: `font-semibold tracking-tight ${node.type === "category" || node.type === "percentile-category" ? "text-slate-800 text-sm" : "text-slate-700 text-xs"} ${isCurrentVideo ? "text-blue-700 font-bold" : ""} group-hover:text-slate-900 transition-colors duration-200`, children: node.label }),
45858
- node.type === "category" && categories.find((c) => c.id === node.id)?.description && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: categories.find((c) => c.id === node.id)?.description }),
46391
+ node.type === "category" && (node.subtitle || categories.find((c) => c.id === node.id)?.description) && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: node.subtitle || categories.find((c) => c.id === node.id)?.description }),
45859
46392
  node.type === "percentile-category" && node.subtitle && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: node.subtitle }),
45860
- node.type === "video" && (node.severity || node.categoryId === "cycle_completion" || node.categoryId === "idle_time" || node.categoryId === "low_value") && /* @__PURE__ */ jsx("div", { className: "text-xs mt-0.5 font-medium", children: node.categoryId === "idle_time" ? (
46393
+ node.type === "video" && (node.severity || node.categoryId === "cycle_completion" || node.categoryId === "idle_time" || node.categoryId === "low_value" || node.categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2) && /* @__PURE__ */ jsx("div", { className: "text-xs mt-0.5 font-medium", children: node.categoryId === "idle_time" ? (
45861
46394
  // Show root cause label for idle time clips (text only, icon is on the left)
45862
46395
  (() => {
45863
46396
  if (!idleTimeVlmEnabled) {
@@ -45879,8 +46412,10 @@ var FileManagerFilters = ({
45879
46412
  // Show badge for other clips
45880
46413
  (() => {
45881
46414
  const badge = getClipBadge(node);
46415
+ const redFlowDriverBadges = getRedFlowDriverBadges(node);
45882
46416
  return /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-1.5", children: [
45883
- /* @__PURE__ */ jsx("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-medium ${badge.className}`, children: badge.text }),
46417
+ badge ? /* @__PURE__ */ jsx("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-medium ${badge.className}`, children: badge.text }) : null,
46418
+ redFlowDriverBadges.map((redFlowDriverBadge) => /* @__PURE__ */ jsx("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-medium ${redFlowDriverBadge.className}`, children: redFlowDriverBadge.text }, redFlowDriverBadge.text)),
45884
46419
  node.categoryId === "cycle_completion" && node.cycleItemCount && node.cycleItemCount > 1 ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-semibold bg-blue-100 text-blue-700 border border-blue-200", children: [
45885
46420
  "x",
45886
46421
  node.cycleItemCount
@@ -45896,21 +46431,20 @@ var FileManagerFilters = ({
45896
46431
  ),
45897
46432
  hasChildren && isExpanded && (node.type === "category" || node.type === "percentile-category") && /* @__PURE__ */ jsx("div", { className: "mt-2 ml-3 animate-in border-l-2 border-slate-100 pl-3", children: /* @__PURE__ */ jsxs("div", { className: "max-h-64 overflow-y-auto space-y-1 scrollbar-thin scrollbar-track-slate-100 scrollbar-thumb-slate-300", children: [
45898
46433
  node.children.map((child) => renderNode(child, depth + 1)),
45899
- showExternalLoadingState && /* @__PURE__ */ jsx("div", { className: "py-2 px-3 text-center", children: /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center text-sm text-slate-500", children: [
46434
+ showInitialLoadingState && /* @__PURE__ */ jsx("div", { className: "py-2 px-3 text-center", children: /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center text-sm text-slate-500", children: [
45900
46435
  /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
45901
46436
  "Loading clips..."
45902
46437
  ] }) }),
45903
- loadingCategories.has(getMetadataLoadingKey(node.id, (categoryPages[node.id] || 0) + 1)) && /* @__PURE__ */ jsx("div", { className: "py-2 px-3 text-center", children: /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center text-sm text-slate-500", children: [
46438
+ isLoadMoreLoading && /* @__PURE__ */ jsx("div", { className: "py-2 px-3 text-center", children: /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center text-sm text-slate-500", children: [
45904
46439
  /* @__PURE__ */ jsx("div", { className: "animate-spin mr-2 h-4 w-4 border-2 border-slate-300 border-t-blue-500 rounded-full" }),
45905
46440
  "Loading more clips..."
45906
46441
  ] }) }),
45907
- categoryHasMore[node.id] && !loadingCategories.has(getMetadataLoadingKey(node.id, (categoryPages[node.id] || 0) + 1)) && /* @__PURE__ */ jsxs(
46442
+ categoryHasMore[node.id] && !isLoadMoreLoading && /* @__PURE__ */ jsxs(
45908
46443
  "button",
45909
46444
  {
45910
46445
  onClick: (e) => {
45911
46446
  e.stopPropagation();
45912
- const nextPage = (categoryPages[node.id] || 1) + 1;
45913
- fetchClipMetadata(node.id, nextPage);
46447
+ fetchClipMetadata(node.id, nextLoadMorePage);
45914
46448
  },
45915
46449
  className: "w-full py-2 px-3 text-sm text-blue-600 hover:bg-blue-50 rounded-lg transition-colors duration-200 text-center",
45916
46450
  children: [
@@ -46673,6 +47207,7 @@ var BottlenecksContent = ({
46673
47207
  triageMode = false,
46674
47208
  ticketId,
46675
47209
  prefetchedPercentileCounts,
47210
+ lowMomentsPrefetch,
46676
47211
  initialTimeFilter
46677
47212
  }) => {
46678
47213
  console.log("\u{1F3AB} [BottlenecksContent] Rendered with ticketId:", ticketId || "NONE", "workspaceId:", workspaceId, "date:", date, "shift:", shift);
@@ -46765,6 +47300,10 @@ var BottlenecksContent = ({
46765
47300
  const [isShareLoading, setIsShareLoading] = useState(false);
46766
47301
  const [isShareCopied, setIsShareCopied] = useState(false);
46767
47302
  const shareCopiedTimeoutRef = useRef(null);
47303
+ const [lowEfficiencyAiSummaryByClipId, setLowEfficiencyAiSummaryByClipId] = useState({});
47304
+ const [lowEfficiencyAiSummaryLoadingByClipId, setLowEfficiencyAiSummaryLoadingByClipId] = useState({});
47305
+ const [lowEfficiencyAiSummaryErrorByClipId, setLowEfficiencyAiSummaryErrorByClipId] = useState({});
47306
+ const lowEfficiencyAiSummaryRequestStatusRef = useRef({});
46768
47307
  useEffect(() => {
46769
47308
  return () => {
46770
47309
  if (shareCopiedTimeoutRef.current) {
@@ -46773,6 +47312,7 @@ var BottlenecksContent = ({
46773
47312
  };
46774
47313
  }, []);
46775
47314
  const loadingTimeoutRef = useRef(null);
47315
+ const metadataLoadingKeyRef = useRef(null);
46776
47316
  const [activeFilter, setActiveFilter] = useState(initialFilter);
46777
47317
  const previousFilterRef = useRef("");
46778
47318
  const [allVideos, setAllVideos] = useState([]);
@@ -46929,60 +47469,33 @@ var BottlenecksContent = ({
46929
47469
  if (initialFilter) {
46930
47470
  return;
46931
47471
  }
47472
+ const redStreakType = "recent_flow_red_streak";
47473
+ if (dynamicCounts[redStreakType] > 0) {
47474
+ setInitialFilter(redStreakType);
47475
+ setActiveFilter(redStreakType);
47476
+ activeFilterRef.current = redStreakType;
47477
+ return;
47478
+ }
46932
47479
  if (defaultCategory) {
46933
47480
  setInitialFilter(defaultCategory);
46934
47481
  setActiveFilter(defaultCategory);
46935
47482
  activeFilterRef.current = defaultCategory;
46936
47483
  return;
46937
47484
  }
46938
- if (clipTypes.length > 0) {
46939
- let selectedType = null;
46940
- if (clipTypes.length === 1) {
46941
- selectedType = clipTypes[0];
46942
- } else {
46943
- const priorityOrder = ["cycle_completion", "fast-cycles", "slow-cycles", "idle_time"];
46944
- for (const priorityType of priorityOrder) {
46945
- const type = clipTypes.find((t) => t.type === priorityType && (dynamicCounts[t.type] || 0) > 0);
46946
- if (type) {
46947
- selectedType = type;
46948
- break;
46949
- }
46950
- }
46951
- if (!selectedType) {
46952
- selectedType = clipTypes.find((type) => (dynamicCounts[type.type] || 0) > 0);
46953
- }
46954
- if (!selectedType) {
46955
- selectedType = clipTypes[0];
46956
- }
46957
- }
46958
- if (selectedType) {
46959
- console.log(`[BottlenecksContent] Auto-selecting filter: ${selectedType.type} (count: ${dynamicCounts[selectedType.type] || 0})`);
46960
- setInitialFilter(selectedType.type);
46961
- setActiveFilter(selectedType.type);
46962
- activeFilterRef.current = selectedType.type;
46963
- }
46964
- }
46965
47485
  }, [clipTypes, dynamicCounts, defaultCategory, initialFilter]);
46966
47486
  const mergedCounts = useMemo(() => {
46967
47487
  return { ...dynamicCounts };
46968
47488
  }, [dynamicCounts]);
46969
47489
  useEffect(() => {
46970
- if (!firstClip || allVideos.length > 0 || !isMountedRef.current) {
47490
+ if (allVideos.length > 0 || !isMountedRef.current) {
46971
47491
  return;
46972
47492
  }
46973
- if (activeFilterRef.current && firstClip.type !== activeFilterRef.current) {
47493
+ if (!activeFilterRef.current) {
47494
+ setHasInitialLoad(true);
47495
+ setIsCategoryLoading(false);
46974
47496
  return;
46975
47497
  }
46976
- setCurrentClipId(firstClip.id || null);
46977
- setAllVideos([firstClip]);
46978
- setCurrentPosition(1);
46979
- currentPositionRef.current = 1;
46980
- const total = mergedCounts[firstClip.type] || 0;
46981
- currentTotalRef.current = total;
46982
- setCurrentTotal(total);
46983
- setHasInitialLoad(true);
46984
- setIsCategoryLoading(false);
46985
- }, [firstClip, allVideos.length, mergedCounts]);
47498
+ }, [firstClips, allVideos.length, mergedCounts]);
46986
47499
  useEffect(() => {
46987
47500
  if (!firstClips || typeof document === "undefined") {
46988
47501
  return;
@@ -47018,25 +47531,6 @@ var BottlenecksContent = ({
47018
47531
  const loadFirstVideoForCategory = useCallback(async (category) => {
47019
47532
  if (!workspaceId || !s3ClipsService || !isMountedRef.current || !isEffectiveShiftReady) return;
47020
47533
  const targetCategory = category || activeFilterRef.current;
47021
- const initClip = targetCategory ? firstClips?.[targetCategory] : null;
47022
- if (initClip) {
47023
- setCurrentClipId(initClip.id || null);
47024
- setAllVideos((prev) => {
47025
- const exists = prev.some((v) => v.id === initClip.id);
47026
- if (!exists) {
47027
- return [...prev, initClip];
47028
- }
47029
- return prev;
47030
- });
47031
- setCurrentPosition(1);
47032
- currentPositionRef.current = 1;
47033
- const total = mergedCounts[targetCategory] || 0;
47034
- currentTotalRef.current = total;
47035
- setCurrentTotal(total);
47036
- setHasInitialLoad(true);
47037
- setIsCategoryLoading(false);
47038
- return;
47039
- }
47040
47534
  const operationKey = `loadFirstVideo:${targetCategory}:${effectiveDateString}:${effectiveShiftId}`;
47041
47535
  if (loadingCategoryRef.current === targetCategory || fetchInProgressRef.current.has(operationKey)) {
47042
47536
  console.log(`[BottlenecksContent] Load first video already in progress for ${targetCategory}`);
@@ -47052,12 +47546,25 @@ var BottlenecksContent = ({
47052
47546
  const shiftStr = effectiveShiftId;
47053
47547
  console.log(`[BottlenecksContent] Loading first video for category: ${targetCategory}`);
47054
47548
  try {
47055
- const firstVideo = await s3ClipsService.getFirstClipForCategory(
47056
- workspaceId,
47057
- operationalDate,
47058
- shiftStr,
47059
- targetCategory
47060
- );
47549
+ let firstVideo = null;
47550
+ const totalCategoryClips = mergedCounts[targetCategory] || 0;
47551
+ if (totalCategoryClips > 0) {
47552
+ firstVideo = await s3ClipsService.getClipByIndex(
47553
+ workspaceId,
47554
+ operationalDate,
47555
+ shiftStr,
47556
+ targetCategory,
47557
+ 0
47558
+ );
47559
+ }
47560
+ if (!firstVideo) {
47561
+ firstVideo = await s3ClipsService.getFirstClipForCategory(
47562
+ workspaceId,
47563
+ operationalDate,
47564
+ shiftStr,
47565
+ targetCategory
47566
+ );
47567
+ }
47061
47568
  if (firstVideo) {
47062
47569
  console.log(`[BottlenecksContent] Successfully loaded first video, ID: ${firstVideo.id}`);
47063
47570
  setCurrentClipId(firstVideo.id || null);
@@ -47068,8 +47575,8 @@ var BottlenecksContent = ({
47068
47575
  }
47069
47576
  return prev;
47070
47577
  });
47071
- setCurrentPosition(1);
47072
- currentPositionRef.current = 1;
47578
+ setCurrentPosition(totalCategoryClips > 0 ? 1 : 0);
47579
+ currentPositionRef.current = totalCategoryClips > 0 ? 1 : 0;
47073
47580
  const total = mergedCounts[targetCategory] || 0;
47074
47581
  currentTotalRef.current = total;
47075
47582
  setCurrentTotal(total);
@@ -47083,13 +47590,13 @@ var BottlenecksContent = ({
47083
47590
  }
47084
47591
  if (mergedCounts[targetCategory] > 0) {
47085
47592
  try {
47593
+ const fallbackIndex = 0;
47086
47594
  const firstVideo = await s3ClipsService.getClipByIndex(
47087
47595
  workspaceId,
47088
47596
  operationalDate,
47089
47597
  shiftStr,
47090
47598
  targetCategory,
47091
- 0
47092
- // First video (index 0)
47599
+ fallbackIndex
47093
47600
  );
47094
47601
  if (firstVideo && isMountedRef.current) {
47095
47602
  console.log(`[BottlenecksContent] Successfully loaded first video via index`);
@@ -47192,11 +47699,12 @@ var BottlenecksContent = ({
47192
47699
  categoryId
47193
47700
  }));
47194
47701
  };
47195
- const [cycleClips, idleClips] = await Promise.all([
47702
+ const [cycleClips, redFlowClips, idleClips] = await Promise.all([
47196
47703
  fetchCategoryMetadata("cycle_completion"),
47704
+ fetchCategoryMetadata("recent_flow_red_streak"),
47197
47705
  fetchCategoryMetadata("idle_time")
47198
47706
  ]);
47199
- const allClips = [...cycleClips, ...idleClips].sort(
47707
+ const allClips = [...cycleClips, ...redFlowClips, ...idleClips].sort(
47200
47708
  (a, b) => new Date(b.clip_timestamp).getTime() - new Date(a.clip_timestamp).getTime()
47201
47709
  );
47202
47710
  setTriageClips(allClips);
@@ -47245,6 +47753,9 @@ var BottlenecksContent = ({
47245
47753
  }, [idleTimeVlmEnabled, triageClips, triageMode, getAuthToken4]);
47246
47754
  useEffect(() => {
47247
47755
  if (s3ClipsService && (mergedCounts[activeFilter] || 0) > 0) {
47756
+ if (activeFilter === "recent_flow_red_streak") {
47757
+ return;
47758
+ }
47248
47759
  if (firstClip && firstClip.type === activeFilter) {
47249
47760
  return;
47250
47761
  }
@@ -47265,10 +47776,10 @@ var BottlenecksContent = ({
47265
47776
  return ["fast-cycles", "slow-cycles", "longest-idles"].includes(categoryId);
47266
47777
  }, [isFastSlowClipFiltersEnabled]);
47267
47778
  const shouldUseMetadataNavigation = useCallback((categoryId) => {
47268
- return isPercentileCategory(categoryId) || categoryId === "idle_time" && idleClipSort === "idle_duration_desc";
47779
+ return isPercentileCategory(categoryId) || categoryId === "recent_flow_red_streak" || categoryId === "idle_time" && idleClipSort === "idle_duration_desc";
47269
47780
  }, [idleClipSort, isPercentileCategory]);
47270
47781
  const getMetadataCacheKey = useCallback((categoryId) => {
47271
- const sortKey = categoryId === "idle_time" ? idleClipSort : "latest";
47782
+ const sortKey = categoryId === "recent_flow_red_streak" ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest";
47272
47783
  return `${categoryId}-${effectiveDateString}-${effectiveShiftId}-${snapshotDateTime ?? "nosnap"}-${snapshotClipId ?? "nosnap"}-${sortKey}`;
47273
47784
  }, [effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, idleClipSort]);
47274
47785
  const setVisibleCategoryMetadata = useCallback((categoryId, clips) => {
@@ -47278,7 +47789,7 @@ var BottlenecksContent = ({
47278
47789
  categoryMetadataRef.current = clips;
47279
47790
  setCategoryMetadata(clips);
47280
47791
  setCategoryMetadataCategoryId(clips.length > 0 ? categoryId : null);
47281
- setCategoryMetadataSort(clips.length > 0 ? categoryId === "idle_time" ? idleClipSort : "latest" : null);
47792
+ setCategoryMetadataSort(clips.length > 0 ? categoryId === "recent_flow_red_streak" ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest" : null);
47282
47793
  return true;
47283
47794
  }, [idleClipSort]);
47284
47795
  const applyMetadataSnapshot = useCallback((categoryId, clips, total) => {
@@ -47296,6 +47807,22 @@ var BottlenecksContent = ({
47296
47807
  setCurrentTotal(total);
47297
47808
  }
47298
47809
  }, [getMetadataCacheKey, shouldUseMetadataNavigation, setVisibleCategoryMetadata]);
47810
+ const applyPrefetchedFirstVideo = useCallback((video) => {
47811
+ if (!video || !isMountedRef.current) {
47812
+ return false;
47813
+ }
47814
+ if (currentClipIdRef.current === video.id) {
47815
+ return true;
47816
+ }
47817
+ setCurrentClipId(video.id);
47818
+ setAllVideos([video]);
47819
+ setCurrentIndex(0);
47820
+ setCurrentMetadataIndex(0);
47821
+ currentMetadataIndexRef.current = 0;
47822
+ setCurrentPosition(1);
47823
+ currentPositionRef.current = 1;
47824
+ return true;
47825
+ }, []);
47299
47826
  const getClipTypesForPercentileCategory = useCallback((categoryId) => {
47300
47827
  switch (categoryId) {
47301
47828
  case "fast-cycles":
@@ -47315,7 +47842,7 @@ var BottlenecksContent = ({
47315
47842
  if (activeFilter !== "fast-cycles" && activeFilter !== "slow-cycles") {
47316
47843
  return;
47317
47844
  }
47318
- const fallbackFilter = ["cycle_completion", "idle_time"].find((type) => (dynamicCounts[type] || 0) > 0) || clipTypes.find((type) => (dynamicCounts[type.type] || 0) > 0)?.type || clipTypes[0]?.type;
47845
+ const fallbackFilter = ["cycle_completion", "recent_flow_red_streak", "idle_time"].find((type) => (dynamicCounts[type] || 0) > 0) || clipTypes.find((type) => (dynamicCounts[type.type] || 0) > 0)?.type || clipTypes[0]?.type;
47319
47846
  if (!fallbackFilter || fallbackFilter === activeFilter) {
47320
47847
  return;
47321
47848
  }
@@ -47371,30 +47898,70 @@ var BottlenecksContent = ({
47371
47898
  setCategoryMetadataCategoryId(null);
47372
47899
  setCategoryMetadataSort(null);
47373
47900
  categoryMetadataRef.current = [];
47901
+ if (activeFilterRef.current === categoryId) {
47902
+ setIsCategoryLoading(false);
47903
+ }
47374
47904
  return;
47375
47905
  }
47376
47906
  if (!isEffectiveShiftReady) {
47377
47907
  console.log("[BottlenecksContent] Skipping metadata load - shift/date not ready");
47908
+ if (activeFilterRef.current === categoryId) {
47909
+ setIsCategoryLoading(false);
47910
+ }
47378
47911
  return;
47379
47912
  }
47380
47913
  const resolvedDate = effectiveDateString;
47381
47914
  const cacheKey = getMetadataCacheKey(categoryId);
47382
- const cachedMetadata = !forceRefresh ? metadataCache[cacheKey] : void 0;
47915
+ const candidateLowMomentsPrefetch = lowMomentsPrefetch ?? null;
47916
+ const lowMomentsPrefetchMatchesScope = Boolean(
47917
+ candidateLowMomentsPrefetch?.key?.startsWith(`recent_flow_red_streak-${effectiveDateString}-${effectiveShiftId}-`)
47918
+ );
47919
+ const matchingLowMomentsPrefetch = !forceRefresh && categoryId === "recent_flow_red_streak" && candidateLowMomentsPrefetch && (candidateLowMomentsPrefetch.key === cacheKey || lowMomentsPrefetchMatchesScope) && !candidateLowMomentsPrefetch.loading && Array.isArray(candidateLowMomentsPrefetch.metadata) && candidateLowMomentsPrefetch.metadata.length > 0 ? candidateLowMomentsPrefetch : null;
47920
+ const lowMomentsPrefetchInFlight = !forceRefresh && categoryId === "recent_flow_red_streak" && candidateLowMomentsPrefetch && (candidateLowMomentsPrefetch.key === cacheKey || lowMomentsPrefetchMatchesScope) && candidateLowMomentsPrefetch.loading;
47921
+ if (lowMomentsPrefetchInFlight) {
47922
+ if (autoLoadFirstVideo && candidateLowMomentsPrefetch?.firstVideo) {
47923
+ applyPrefetchedFirstVideo(candidateLowMomentsPrefetch.firstVideo);
47924
+ }
47925
+ if (Array.isArray(candidateLowMomentsPrefetch?.metadata) && candidateLowMomentsPrefetch.metadata.length > 0) {
47926
+ applyMetadataSnapshot(categoryId, candidateLowMomentsPrefetch.metadata, candidateLowMomentsPrefetch.total);
47927
+ }
47928
+ if (activeFilterRef.current === categoryId) {
47929
+ setIsCategoryLoading(true);
47930
+ }
47931
+ return;
47932
+ }
47933
+ const cachedMetadata = matchingLowMomentsPrefetch?.metadata ?? (!forceRefresh ? metadataCache[cacheKey] : void 0);
47934
+ const requestKey = cacheKey;
47935
+ if (metadataLoadingKeyRef.current === requestKey) {
47936
+ console.log(`[BottlenecksContent] Metadata load already in progress for ${categoryId}`);
47937
+ return;
47938
+ }
47939
+ metadataLoadingKeyRef.current = requestKey;
47383
47940
  try {
47384
47941
  if (cachedMetadata) {
47385
47942
  console.log(`[BottlenecksContent] Using cached metadata for ${categoryId}`);
47943
+ if (matchingLowMomentsPrefetch) {
47944
+ setMetadataCache((prev) => prev[cacheKey] ? prev : {
47945
+ ...prev,
47946
+ [cacheKey]: matchingLowMomentsPrefetch.metadata
47947
+ });
47948
+ }
47386
47949
  setVisibleCategoryMetadata(categoryId, cachedMetadata);
47387
47950
  if (autoLoadFirstVideo && cachedMetadata.length > 0 && s3ClipsService) {
47388
47951
  const firstClipMeta = cachedMetadata[0];
47952
+ const firstClipId = firstClipMeta.clipId || firstClipMeta.id;
47953
+ const prefetchedFirstVideo = matchingLowMomentsPrefetch?.firstVideo ?? null;
47389
47954
  try {
47390
- const video = await s3ClipsService.getClipById(firstClipMeta.clipId);
47391
- if (video && isMountedRef.current) {
47392
- setCurrentClipId(firstClipMeta.clipId);
47393
- setAllVideos([video]);
47394
- setCurrentIndex(0);
47395
- setCurrentMetadataIndex(0);
47396
- currentMetadataIndexRef.current = 0;
47397
- console.log(`[BottlenecksContent] Auto-loaded first video from cache: ${video.id} (1/${cachedMetadata.length})`);
47955
+ let loadedVideo = null;
47956
+ if (prefetchedFirstVideo?.id === firstClipId) {
47957
+ loadedVideo = prefetchedFirstVideo;
47958
+ applyPrefetchedFirstVideo(prefetchedFirstVideo);
47959
+ } else {
47960
+ loadedVideo = await s3ClipsService.getClipById(firstClipId);
47961
+ applyPrefetchedFirstVideo(loadedVideo);
47962
+ }
47963
+ if (loadedVideo && isMountedRef.current) {
47964
+ console.log(`[BottlenecksContent] Auto-loaded first video from cache: ${loadedVideo.id} (1/${cachedMetadata.length})`);
47398
47965
  }
47399
47966
  } catch (error2) {
47400
47967
  console.error(`[BottlenecksContent] Error loading first video from cache:`, error2);
@@ -47441,7 +48008,7 @@ var BottlenecksContent = ({
47441
48008
  knownTotal: mergedCounts[categoryId] ?? null,
47442
48009
  snapshotDateTime,
47443
48010
  snapshotClipId,
47444
- sort: categoryId === "idle_time" ? idleClipSort : "latest"
48011
+ sort: categoryId === "recent_flow_red_streak" ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest"
47445
48012
  }),
47446
48013
  redirectReason: "session_expired"
47447
48014
  });
@@ -47502,10 +48069,11 @@ var BottlenecksContent = ({
47502
48069
  console.log(`[BottlenecksContent] Loaded metadata for ${categoryId}: ${metadataClips.length} clips`);
47503
48070
  if (autoLoadFirstVideo && metadataClips.length > 0 && s3ClipsService) {
47504
48071
  const firstClipMeta = metadataClips[0];
48072
+ const firstClipId = firstClipMeta.clipId || firstClipMeta.id;
47505
48073
  try {
47506
- const video = await s3ClipsService.getClipById(firstClipMeta.clipId);
48074
+ const video = await s3ClipsService.getClipById(firstClipId);
47507
48075
  if (video && isMountedRef.current) {
47508
- setCurrentClipId(firstClipMeta.clipId);
48076
+ setCurrentClipId(firstClipId);
47509
48077
  setAllVideos([video]);
47510
48078
  setCurrentIndex(0);
47511
48079
  setCurrentMetadataIndex(0);
@@ -47527,9 +48095,43 @@ var BottlenecksContent = ({
47527
48095
  } catch (error2) {
47528
48096
  console.error(`[BottlenecksContent] Error loading category metadata:`, error2);
47529
48097
  } finally {
47530
- setIsCategoryLoading(false);
48098
+ if (metadataLoadingKeyRef.current === requestKey) {
48099
+ metadataLoadingKeyRef.current = null;
48100
+ }
48101
+ if (activeFilterRef.current === categoryId) {
48102
+ setIsCategoryLoading(false);
48103
+ }
48104
+ }
48105
+ }, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, idleClipSort, supabase, setVisibleCategoryMetadata, lowMomentsPrefetch, applyPrefetchedFirstVideo, applyMetadataSnapshot]);
48106
+ useEffect(() => {
48107
+ if (activeFilter !== "recent_flow_red_streak") {
48108
+ return;
48109
+ }
48110
+ if (!lowMomentsPrefetch?.key?.startsWith(`recent_flow_red_streak-${effectiveDateString}-${effectiveShiftId}-`)) {
48111
+ return;
48112
+ }
48113
+ if (lowMomentsPrefetch.firstVideo && !allVideos.some((video) => video.type === "recent_flow_red_streak")) {
48114
+ applyPrefetchedFirstVideo(lowMomentsPrefetch.firstVideo);
48115
+ }
48116
+ if (lowMomentsPrefetch.metadata.length > 0) {
48117
+ applyMetadataSnapshot("recent_flow_red_streak", lowMomentsPrefetch.metadata, lowMomentsPrefetch.total);
48118
+ if (isMountedRef.current) {
48119
+ setIsCategoryLoading(false);
48120
+ }
48121
+ return;
48122
+ }
48123
+ if (isMountedRef.current) {
48124
+ setIsCategoryLoading(lowMomentsPrefetch.loading);
47531
48125
  }
47532
- }, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, idleClipSort, supabase, setVisibleCategoryMetadata]);
48126
+ }, [
48127
+ activeFilter,
48128
+ lowMomentsPrefetch,
48129
+ effectiveDateString,
48130
+ effectiveShiftId,
48131
+ allVideos,
48132
+ applyPrefetchedFirstVideo,
48133
+ applyMetadataSnapshot
48134
+ ]);
47533
48135
  useEffect(() => {
47534
48136
  if (previousIdleClipSortRef.current === idleClipSort) {
47535
48137
  return;
@@ -47569,8 +48171,13 @@ var BottlenecksContent = ({
47569
48171
  currentTotalRef.current = total;
47570
48172
  setCurrentTotal(total);
47571
48173
  previousFilterRef.current = activeFilter;
47572
- if (activeFilter !== "all" && currentClipId) {
47573
- loadCategoryMetadata(activeFilter, false);
48174
+ const metadataLoadPlan = getCategoryMetadataLoadPlanForFilterChange({
48175
+ activeFilter,
48176
+ currentClipId,
48177
+ categoryTotal: total
48178
+ });
48179
+ if (metadataLoadPlan.shouldLoad) {
48180
+ loadCategoryMetadata(activeFilter, metadataLoadPlan.autoLoadFirstVideo);
47574
48181
  }
47575
48182
  const filtered = allVideos.filter((video) => {
47576
48183
  if (activeFilter === "all") return true;
@@ -47593,11 +48200,11 @@ var BottlenecksContent = ({
47593
48200
  if (!currentClipId || activeFilter === "all") {
47594
48201
  return;
47595
48202
  }
47596
- if (categoryMetadataRef.current.length > 0 || isCategoryLoading) {
48203
+ if (categoryMetadataRef.current.length > 0) {
47597
48204
  return;
47598
48205
  }
47599
48206
  loadCategoryMetadata(activeFilter, false);
47600
- }, [currentClipId, activeFilter, isCategoryLoading, loadCategoryMetadata]);
48207
+ }, [currentClipId, activeFilter, loadCategoryMetadata]);
47601
48208
  const loadAndPlayClipById = useCallback(async (clipId, categoryId, position, metadataContext) => {
47602
48209
  if (!workspaceId || !s3ClipsService || !isMountedRef.current) return;
47603
48210
  console.log(`[BottlenecksContent] Loading clip by ID: ${clipId}, category=${categoryId}, position=${position}`);
@@ -48056,6 +48663,98 @@ var BottlenecksContent = ({
48056
48663
  }
48057
48664
  return filteredVideos[currentIndex];
48058
48665
  }, [filteredVideos, currentIndex]);
48666
+ const currentLowEfficiencyClipId = currentVideo?.id || currentClipId || null;
48667
+ const isCurrentLowEfficiencyClip = Boolean(
48668
+ currentVideo?.type === "recent_flow_red_streak" || currentVideo?.red_flow_timeline
48669
+ );
48670
+ const currentLowEfficiencyAiSummary = currentLowEfficiencyClipId ? lowEfficiencyAiSummaryByClipId[currentLowEfficiencyClipId] || currentVideo?.low_efficiency_ai_summary || null : null;
48671
+ const isCurrentLowEfficiencyAiSummaryLoading = Boolean(
48672
+ currentLowEfficiencyClipId && lowEfficiencyAiSummaryLoadingByClipId[currentLowEfficiencyClipId]
48673
+ );
48674
+ const currentLowEfficiencyAiSummaryError = currentLowEfficiencyClipId ? lowEfficiencyAiSummaryErrorByClipId[currentLowEfficiencyClipId] || null : null;
48675
+ useEffect(() => {
48676
+ const clipId = currentLowEfficiencyClipId;
48677
+ if (!clipId || !isCurrentLowEfficiencyClip || !workspaceId) {
48678
+ return;
48679
+ }
48680
+ if (currentVideo?.low_efficiency_ai_summary || lowEfficiencyAiSummaryRequestStatusRef.current[clipId]) {
48681
+ return;
48682
+ }
48683
+ let cancelled = false;
48684
+ let timedOut = false;
48685
+ const controller = new AbortController();
48686
+ lowEfficiencyAiSummaryRequestStatusRef.current[clipId] = "loading";
48687
+ const timeout = setTimeout(() => {
48688
+ timedOut = true;
48689
+ controller.abort();
48690
+ }, 3e4);
48691
+ setLowEfficiencyAiSummaryLoadingByClipId((prev) => ({ ...prev, [clipId]: true }));
48692
+ setLowEfficiencyAiSummaryErrorByClipId((prev) => ({ ...prev, [clipId]: null }));
48693
+ void (async () => {
48694
+ try {
48695
+ const response = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
48696
+ method: "POST",
48697
+ headers: {
48698
+ "Content-Type": "application/json"
48699
+ },
48700
+ signal: controller.signal,
48701
+ body: JSON.stringify({
48702
+ action: "ai-summary",
48703
+ workspaceId,
48704
+ clipId,
48705
+ workspaceName
48706
+ }),
48707
+ redirectReason: "session_expired"
48708
+ });
48709
+ if (!response.ok) {
48710
+ throw new Error(`AI summary API error: ${response.status}`);
48711
+ }
48712
+ const payload = await response.json();
48713
+ const summary = payload?.summary;
48714
+ if (!summary || !Array.isArray(summary.bullets) || summary.bullets.filter((bullet) => String(bullet || "").trim()).length < 3) {
48715
+ throw new Error("AI summary response was empty");
48716
+ }
48717
+ if (!cancelled) {
48718
+ lowEfficiencyAiSummaryRequestStatusRef.current[clipId] = "success";
48719
+ setLowEfficiencyAiSummaryByClipId((prev) => ({ ...prev, [clipId]: summary }));
48720
+ }
48721
+ } catch (error2) {
48722
+ if (cancelled) {
48723
+ return;
48724
+ }
48725
+ lowEfficiencyAiSummaryRequestStatusRef.current[clipId] = "error";
48726
+ const message = timedOut ? "AI summary timed out" : error2 instanceof Error ? error2.message : "AI summary unavailable";
48727
+ console.warn("[BottlenecksContent] Failed to generate Low Efficiency AI summary:", error2);
48728
+ setLowEfficiencyAiSummaryErrorByClipId((prev) => ({
48729
+ ...prev,
48730
+ [clipId]: message
48731
+ }));
48732
+ } finally {
48733
+ clearTimeout(timeout);
48734
+ if (isMountedRef.current) {
48735
+ setLowEfficiencyAiSummaryLoadingByClipId((prev) => ({ ...prev, [clipId]: false }));
48736
+ }
48737
+ }
48738
+ })();
48739
+ return () => {
48740
+ cancelled = true;
48741
+ clearTimeout(timeout);
48742
+ if (lowEfficiencyAiSummaryRequestStatusRef.current[clipId] === "loading") {
48743
+ delete lowEfficiencyAiSummaryRequestStatusRef.current[clipId];
48744
+ }
48745
+ if (isMountedRef.current) {
48746
+ setLowEfficiencyAiSummaryLoadingByClipId((prev) => ({ ...prev, [clipId]: false }));
48747
+ }
48748
+ controller.abort();
48749
+ };
48750
+ }, [
48751
+ currentLowEfficiencyClipId,
48752
+ currentVideo?.low_efficiency_ai_summary,
48753
+ isCurrentLowEfficiencyClip,
48754
+ supabase,
48755
+ workspaceId,
48756
+ workspaceName
48757
+ ]);
48059
48758
  const handleShareClip = useCallback(async () => {
48060
48759
  if (!currentVideo?.id || isShareLoading) {
48061
48760
  if (!currentVideo?.id) {
@@ -48127,11 +48826,11 @@ var BottlenecksContent = ({
48127
48826
  }
48128
48827
  return currentPosition;
48129
48828
  }, [activeFilter, categoryMetadata.length, currentMetadataIndex, currentPosition, shouldUseMetadataNavigation]);
48130
- const prefetchedExplorerMetadata = useMemo(() => activeFilter === "idle_time" && categoryMetadataSort !== idleClipSort ? void 0 : buildPrefetchedExplorerMetadata(
48829
+ const prefetchedExplorerMetadata = useMemo(() => activeFilter === "recent_flow_red_streak" && lowMomentsPrefetch?.key?.startsWith(`recent_flow_red_streak-${effectiveDateString}-${effectiveShiftId}-`) && !lowMomentsPrefetch.loading && lowMomentsPrefetch.metadata.length > 0 ? { recent_flow_red_streak: lowMomentsPrefetch.metadata } : activeFilter === "idle_time" && categoryMetadataSort !== idleClipSort ? void 0 : buildPrefetchedExplorerMetadata(
48131
48830
  activeFilter,
48132
48831
  categoryMetadataCategoryId,
48133
48832
  categoryMetadata
48134
- ), [activeFilter, categoryMetadata, categoryMetadataCategoryId, categoryMetadataSort, idleClipSort]);
48833
+ ), [activeFilter, categoryMetadata, categoryMetadataCategoryId, categoryMetadataSort, idleClipSort, lowMomentsPrefetch, effectiveDateString, effectiveShiftId]);
48135
48834
  const classificationClipIds = useMemo(() => {
48136
48835
  if (!idleTimeVlmEnabled) {
48137
48836
  return [];
@@ -48523,6 +49222,8 @@ var BottlenecksContent = ({
48523
49222
  return "Cycle Completion";
48524
49223
  case "idle_time":
48525
49224
  return "Idle Time";
49225
+ case "recent_flow_red_streak":
49226
+ return "Low efficiency videos";
48526
49227
  case "running_cycle":
48527
49228
  return "Running Cycle";
48528
49229
  case "setup_state":
@@ -48602,12 +49303,26 @@ var BottlenecksContent = ({
48602
49303
  onShare: handleShareClip,
48603
49304
  isShareLoading,
48604
49305
  isShareCopied,
49306
+ timelineAnnotations: currentVideo.red_flow_timeline,
49307
+ timelineExplanation: currentVideo.red_flow_explanation,
49308
+ timelineTimezone: timezone,
48605
49309
  options: videoPlayerOptions
48606
49310
  },
48607
49311
  `${currentVideo.id}-${playerInstanceNonce}-inline`
48608
49312
  )
48609
49313
  }
48610
49314
  ),
49315
+ currentVideo.type === "recent_flow_red_streak" && !shouldDeferPlayerRenderForCrop ? /* @__PURE__ */ jsx(
49316
+ RedFlowDiagnosticOverlay,
49317
+ {
49318
+ timeline: currentVideo.red_flow_timeline,
49319
+ explanation: currentVideo.red_flow_explanation,
49320
+ aiSummary: currentLowEfficiencyAiSummary,
49321
+ aiSummaryLoading: isCurrentLowEfficiencyAiSummaryLoading,
49322
+ aiSummaryError: currentLowEfficiencyAiSummaryError,
49323
+ className: "right-4 top-4"
49324
+ }
49325
+ ) : null,
48611
49326
  showBlockingVideoLoader && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
48612
49327
  !shouldDeferPlayerRenderForCrop && !isTransitioning && isVideoBuffering && !isInitialLoading && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
48613
49328
  error && error.type === "retrying" && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-40 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
@@ -48707,10 +49422,10 @@ var BottlenecksContent = ({
48707
49422
  ] }) })
48708
49423
  ] });
48709
49424
  })()
48710
- ) : /* @__PURE__ */ jsx("div", { className: "absolute top-3 right-3 z-10 bg-black/60 backdrop-blur-sm px-3 py-1.5 rounded-lg text-white shadow-lg text-xs", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
49425
+ ) : /* @__PURE__ */ jsx("div", { className: `absolute top-3 z-10 bg-black/60 backdrop-blur-sm px-3 py-1.5 rounded-lg text-white shadow-lg text-xs ${currentVideo.type === "recent_flow_red_streak" ? "left-3" : "right-3"}`, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
48711
49426
  /* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${getSeverityColor(currentVideo.severity)} mr-2 animate-pulse` }),
48712
49427
  /* @__PURE__ */ jsx("span", { className: "font-medium mr-2", children: getClipTypeLabel(currentVideo) }),
48713
- /* @__PURE__ */ jsx("span", { className: "opacity-80 hidden sm:inline", children: currentVideo.description })
49428
+ currentVideo.type !== "recent_flow_red_streak" && /* @__PURE__ */ jsx("span", { className: "opacity-80 hidden sm:inline", children: currentVideo.description })
48714
49429
  ] }) })
48715
49430
  )
48716
49431
  ] }) }) }) : (
@@ -48720,14 +49435,21 @@ var BottlenecksContent = ({
48720
49435
  /* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Clips Found" }),
48721
49436
  /* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "There were no video clips found for this workspace today." })
48722
49437
  ] }) }) : (
48723
- /* Priority 6: Show "no matching clips" only if we have data loaded and specifically no clips for this filter */
48724
- hasInitialLoad && (mergedCounts[activeFilter] || 0) === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[220px] sm:min-h-[320px] lg:h-full", children: /* @__PURE__ */ jsxs("div", { className: "text-center p-8", children: [
49438
+ /* Priority 5.5: Show "no folder selected" if activeFilter is empty */
49439
+ hasInitialLoad && !activeFilter ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[220px] sm:min-h-[320px] lg:h-full", children: /* @__PURE__ */ jsxs("div", { className: "text-center p-8", children: [
48725
49440
  /* @__PURE__ */ jsx("svg", { className: "w-16 h-16 text-gray-300 mx-auto mb-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" }) }),
48726
- /* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Matching Clips" }),
48727
- /* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "There are no clips matching the selected filter." })
49441
+ /* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Folder Selected" }),
49442
+ /* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "Please select a folder to view clips." })
48728
49443
  ] }) }) : (
48729
- /* Priority 7: Default loading state for any other case */
48730
- /* @__PURE__ */ jsx("div", { className: "p-4 lg:h-full", children: /* @__PURE__ */ jsx("div", { className: "relative lg:h-full", children: /* @__PURE__ */ jsx("div", { className: "relative w-full min-h-[220px] sm:min-h-[320px] lg:min-h-0 lg:h-full overflow-hidden rounded-md shadow-inner bg-gray-900 flex items-center justify-center", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading..." }) }) }) })
49444
+ /* Priority 6: Show "no matching clips" only if we have data loaded and specifically no clips for this filter */
49445
+ hasInitialLoad && (mergedCounts[activeFilter] || 0) === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[220px] sm:min-h-[320px] lg:h-full", children: /* @__PURE__ */ jsxs("div", { className: "text-center p-8", children: [
49446
+ /* @__PURE__ */ jsx("svg", { className: "w-16 h-16 text-gray-300 mx-auto mb-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" }) }),
49447
+ /* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Matching Clips" }),
49448
+ /* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "There are no clips matching the selected filter." })
49449
+ ] }) }) : (
49450
+ /* Priority 7: Default loading state for any other case */
49451
+ /* @__PURE__ */ jsx("div", { className: "p-4 lg:h-full", children: /* @__PURE__ */ jsx("div", { className: "relative lg:h-full", children: /* @__PURE__ */ jsx("div", { className: "relative w-full min-h-[220px] sm:min-h-[320px] lg:min-h-0 lg:h-full overflow-hidden rounded-md shadow-inner bg-gray-900 flex items-center justify-center", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading..." }) }) }) })
49452
+ )
48731
49453
  )
48732
49454
  )
48733
49455
  ) }) }),
@@ -48879,6 +49601,11 @@ var BottlenecksContent = ({
48879
49601
  idleTimeVlmEnabled,
48880
49602
  showPercentileCycleFilters: isFastSlowClipFiltersEnabled,
48881
49603
  prefetchedClipMetadata: prefetchedExplorerMetadata,
49604
+ externallyManagedLoadingCategories: {
49605
+ recent_flow_red_streak: Boolean(
49606
+ activeFilter === "recent_flow_red_streak" && lowMomentsPrefetch?.key?.startsWith(`recent_flow_red_streak-${effectiveDateString}-${effectiveShiftId}-`) && lowMomentsPrefetch.loading
49607
+ )
49608
+ },
48882
49609
  activeCategoryLoading: isCategoryLoading,
48883
49610
  idleClipSort,
48884
49611
  onIdleClipSortChange: setIdleClipSort,
@@ -48994,10 +49721,10 @@ var BottlenecksContent = ({
48994
49721
  ] }) })
48995
49722
  ] });
48996
49723
  })()
48997
- ) : /* @__PURE__ */ jsx("div", { className: "absolute top-4 right-20 z-50 bg-black/60 backdrop-blur-sm px-4 py-2 rounded-lg text-white shadow-lg", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
49724
+ ) : /* @__PURE__ */ jsx("div", { className: `absolute top-4 z-50 bg-black/60 backdrop-blur-sm px-4 py-2 rounded-lg text-white shadow-lg ${currentVideo.type === "recent_flow_red_streak" ? "left-4" : "right-20"}`, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
48998
49725
  /* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-3 w-3 rounded-full ${getSeverityColor(currentVideo.severity)} mr-2 animate-pulse` }),
48999
49726
  /* @__PURE__ */ jsx("span", { className: "font-medium mr-2", children: getClipTypeLabel(currentVideo) }),
49000
- /* @__PURE__ */ jsx("span", { className: "opacity-80", children: currentVideo.description })
49727
+ currentVideo.type !== "recent_flow_red_streak" && /* @__PURE__ */ jsx("span", { className: "opacity-80", children: currentVideo.description })
49001
49728
  ] }) }),
49002
49729
  /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center p-8", children: /* @__PURE__ */ jsxs("div", { className: "relative w-full h-full max-w-7xl group", children: [
49003
49730
  /* @__PURE__ */ jsx(
@@ -49033,12 +49760,26 @@ var BottlenecksContent = ({
49033
49760
  onShare: handleShareClip,
49034
49761
  isShareLoading,
49035
49762
  isShareCopied,
49763
+ timelineAnnotations: currentVideo.red_flow_timeline,
49764
+ timelineExplanation: currentVideo.red_flow_explanation,
49765
+ timelineTimezone: timezone,
49036
49766
  options: videoPlayerOptions
49037
49767
  },
49038
49768
  `${currentVideo.id}-${playerInstanceNonce}-fullscreen`
49039
49769
  )
49040
49770
  }
49041
49771
  ),
49772
+ currentVideo.type === "recent_flow_red_streak" && !shouldDeferPlayerRenderForCrop ? /* @__PURE__ */ jsx(
49773
+ RedFlowDiagnosticOverlay,
49774
+ {
49775
+ timeline: currentVideo.red_flow_timeline,
49776
+ explanation: currentVideo.red_flow_explanation,
49777
+ aiSummary: currentLowEfficiencyAiSummary,
49778
+ aiSummaryLoading: isCurrentLowEfficiencyAiSummaryLoading,
49779
+ aiSummaryError: currentLowEfficiencyAiSummaryError,
49780
+ className: "right-8 top-8"
49781
+ }
49782
+ ) : null,
49042
49783
  showBlockingVideoLoader && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
49043
49784
  !shouldDeferPlayerRenderForCrop && !isTransitioning && isVideoBuffering && !isInitialLoading && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
49044
49785
  /* @__PURE__ */ jsx("div", { className: "absolute bottom-0 left-0 right-0 p-4 bg-gradient-to-t from-black/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 z-10", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-white", children: [
@@ -51061,8 +51802,8 @@ var IdleTimeReasonChartComponent = ({
51061
51802
  updateAnimation = "replay",
51062
51803
  variant = "pie"
51063
51804
  }) => {
51064
- const [activeData, setActiveData] = React147__default.useState([]);
51065
- React147__default.useEffect(() => {
51805
+ const [activeData, setActiveData] = React148__default.useState([]);
51806
+ React148__default.useEffect(() => {
51066
51807
  if (updateAnimation === "smooth") {
51067
51808
  setActiveData(data && data.length > 0 ? data : []);
51068
51809
  return;
@@ -51081,7 +51822,7 @@ var IdleTimeReasonChartComponent = ({
51081
51822
  setActiveData([]);
51082
51823
  }
51083
51824
  }, [data, updateAnimation]);
51084
- React147__default.useEffect(() => {
51825
+ React148__default.useEffect(() => {
51085
51826
  if (!data || data.length === 0) return;
51086
51827
  data.forEach((entry, index) => {
51087
51828
  if (entry.name.toLowerCase().includes("other")) {
@@ -51089,7 +51830,7 @@ var IdleTimeReasonChartComponent = ({
51089
51830
  }
51090
51831
  });
51091
51832
  }, [data]);
51092
- const pieKey = React147__default.useMemo(() => {
51833
+ const pieKey = React148__default.useMemo(() => {
51093
51834
  if (updateAnimation === "smooth") {
51094
51835
  return "smooth";
51095
51836
  }
@@ -51259,7 +52000,7 @@ var IdleTimeReasonChartComponent = ({
51259
52000
  )
51260
52001
  ] });
51261
52002
  };
51262
- var IdleTimeReasonChart = React147__default.memo(IdleTimeReasonChartComponent);
52003
+ var IdleTimeReasonChart = React148__default.memo(IdleTimeReasonChartComponent);
51263
52004
  IdleTimeReasonChart.displayName = "IdleTimeReasonChart";
51264
52005
  var IdleTimeReasonChart_default = IdleTimeReasonChart;
51265
52006
 
@@ -53483,7 +54224,7 @@ var StatusIndicator = ({ status }) => {
53483
54224
  case "bottleneck":
53484
54225
  return /* @__PURE__ */ jsx(Zap, { className: "h-5 w-5 text-orange-400", "aria-label": "Bottleneck" });
53485
54226
  case "lowEfficiency":
53486
- return /* @__PURE__ */ jsx(AlertTriangle, { className: "h-5 w-5 text-red-400", "aria-label": "Low Efficiency" });
54227
+ return /* @__PURE__ */ jsx(AlertTriangle, { className: "h-5 w-5 text-red-400", "aria-label": "Low moments" });
53487
54228
  case "inactive":
53488
54229
  return /* @__PURE__ */ jsx("div", { className: "h-3 w-3 bg-gray-400 rounded-full", title: "Inactive", "aria-label": "Inactive Workspace" });
53489
54230
  default:
@@ -55786,13 +56527,13 @@ var WorkspaceCycleTimeMetricCards = ({
55786
56527
  liveSkuId
55787
56528
  }) => {
55788
56529
  const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
55789
- const activeSku = React147__default.useMemo(() => {
56530
+ const activeSku = React148__default.useMemo(() => {
55790
56531
  if (skuAware && activeSkuId && skuBreakdown) {
55791
56532
  return skuBreakdown.find((s) => s.sku_id === activeSkuId);
55792
56533
  }
55793
56534
  return null;
55794
56535
  }, [skuAware, activeSkuId, skuBreakdown]);
55795
- const displaySku = React147__default.useMemo(() => {
56536
+ const displaySku = React148__default.useMemo(() => {
55796
56537
  if (activeSku) return activeSku;
55797
56538
  if (skuAware && !activeSkuId && liveSkuId && skuBreakdown) {
55798
56539
  return skuBreakdown.find((s) => s.sku_id === liveSkuId) ?? null;
@@ -56037,7 +56778,7 @@ var arePropsEqual = (prevProps, nextProps) => {
56037
56778
  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
56038
56779
  prevProps.position.id === nextProps.position.id;
56039
56780
  };
56040
- var WorkspaceGridItem = React147__default.memo(({
56781
+ var WorkspaceGridItem = React148__default.memo(({
56041
56782
  data,
56042
56783
  position,
56043
56784
  isBottleneck = false,
@@ -56132,7 +56873,7 @@ var WorkspaceGridItem = React147__default.memo(({
56132
56873
  );
56133
56874
  }, arePropsEqual);
56134
56875
  WorkspaceGridItem.displayName = "WorkspaceGridItem";
56135
- var WorkspaceGrid = React147__default.memo(({
56876
+ var WorkspaceGrid = React148__default.memo(({
56136
56877
  workspaces,
56137
56878
  blueComparisonWorkspaces,
56138
56879
  isPdfMode = false,
@@ -56385,7 +57126,7 @@ var KPICard = ({
56385
57126
  }) => {
56386
57127
  useThemeConfig();
56387
57128
  const { formatNumber } = useFormatNumber();
56388
- const trendInfo = React147__default.useMemo(() => {
57129
+ const trendInfo = React148__default.useMemo(() => {
56389
57130
  let trendValue = trend || "neutral";
56390
57131
  if (change !== void 0 && trend === void 0) {
56391
57132
  trendValue = change > 0 ? "up" : change < 0 ? "down" : "neutral";
@@ -56412,7 +57153,7 @@ var KPICard = ({
56412
57153
  const shouldShowTrend = !(change === 0 && trend === void 0);
56413
57154
  return { trendValue, Icon: Icon2, colorClass, bgClass, shouldShowTrend };
56414
57155
  }, [trend, change]);
56415
- const formattedValue = React147__default.useMemo(() => {
57156
+ const formattedValue = React148__default.useMemo(() => {
56416
57157
  if (title === "Quality Compliance" && typeof value === "number") {
56417
57158
  return value.toFixed(1);
56418
57159
  }
@@ -56426,7 +57167,7 @@ var KPICard = ({
56426
57167
  }
56427
57168
  return value;
56428
57169
  }, [value, title]);
56429
- const formattedChange = React147__default.useMemo(() => {
57170
+ const formattedChange = React148__default.useMemo(() => {
56430
57171
  if (change === void 0 || change === 0 && !showZeroChange) return null;
56431
57172
  const absChange = Math.abs(change);
56432
57173
  return formatNumber(absChange, { minimumFractionDigits: 0, maximumFractionDigits: 1 });
@@ -57933,7 +58674,7 @@ var Breadcrumbs = ({ items }) => {
57933
58674
  }
57934
58675
  }
57935
58676
  };
57936
- 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(React147__default.Fragment, { children: [
58677
+ 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(React148__default.Fragment, { children: [
57937
58678
  index > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "h-3 w-3 text-gray-400 dark:text-gray-500" }),
57938
58679
  /* @__PURE__ */ jsxs(
57939
58680
  "span",
@@ -59457,7 +60198,7 @@ var AwardBadge = ({
59457
60198
  }) => {
59458
60199
  const styles2 = getBadgeStyles(type);
59459
60200
  const Icon2 = CustomIcon || getDefaultIcon(type);
59460
- const randomDelay = React147__default.useMemo(() => Math.random() * 2, []);
60201
+ const randomDelay = React148__default.useMemo(() => Math.random() * 2, []);
59461
60202
  const floatingAnimation = {
59462
60203
  animate: {
59463
60204
  y: [0, -10, 0],
@@ -67826,7 +68567,7 @@ function HomeView({
67826
68567
  animate: { opacity: 1, scale: 1 },
67827
68568
  transition: { duration: 0.3 },
67828
68569
  className: "h-full",
67829
- children: React147__default.createElement(WorkspaceGrid, {
68570
+ children: React148__default.createElement(WorkspaceGrid, {
67830
68571
  workspaces: workspaceMetricsWithBreakState,
67831
68572
  blueComparisonWorkspaces: currentBlueComparisonWorkspaceMetrics || workspaceMetricsWithBreakState,
67832
68573
  lineNames: mergedLineNames,
@@ -67859,7 +68600,7 @@ function HomeView({
67859
68600
  animate: { opacity: 1, scale: 1 },
67860
68601
  transition: { duration: 0.3 },
67861
68602
  className: "h-full",
67862
- children: React147__default.createElement(WorkspaceGrid, {
68603
+ children: React148__default.createElement(WorkspaceGrid, {
67863
68604
  workspaces: [],
67864
68605
  // Show empty grid while loading
67865
68606
  blueComparisonWorkspaces: [],
@@ -67906,7 +68647,7 @@ function HomeView({
67906
68647
  contentVariant: "plain"
67907
68648
  }
67908
68649
  ),
67909
- /* @__PURE__ */ jsx(AnimatePresence, { children: showAllGreenCelebration ? /* @__PURE__ */ jsxs(React147__default.Fragment, { children: [
68650
+ /* @__PURE__ */ jsx(AnimatePresence, { children: showAllGreenCelebration ? /* @__PURE__ */ jsxs(React148__default.Fragment, { children: [
67910
68651
  /* @__PURE__ */ jsx(
67911
68652
  motion.div,
67912
68653
  {
@@ -67985,7 +68726,7 @@ function HomeView({
67985
68726
  "all-green-center-toast"
67986
68727
  )
67987
68728
  ] }, "all-green-celebration") : null }),
67988
- /* @__PURE__ */ jsx(AnimatePresence, { children: greenStreakMilestoneBanner ? /* @__PURE__ */ jsxs(React147__default.Fragment, { children: [
68729
+ /* @__PURE__ */ jsx(AnimatePresence, { children: greenStreakMilestoneBanner ? /* @__PURE__ */ jsxs(React148__default.Fragment, { children: [
67989
68730
  /* @__PURE__ */ jsx(
67990
68731
  motion.div,
67991
68732
  {
@@ -68079,7 +68820,7 @@ function HomeView({
68079
68820
  }
68080
68821
  );
68081
68822
  }
68082
- var AuthenticatedHomeView = withAuth(React147__default.memo(HomeView));
68823
+ var AuthenticatedHomeView = withAuth(React148__default.memo(HomeView));
68083
68824
  var HomeView_default = HomeView;
68084
68825
  function withWorkspaceDisplayNames(Component3, options = {}) {
68085
68826
  const {
@@ -71428,7 +72169,14 @@ var formatSupervisorFirstNames = (supervisors, fallbackSupervisorNames) => {
71428
72169
  return fallbackFirstNames.length > 0 ? Array.from(new Set(fallbackFirstNames)).join(", ") : "Unassigned";
71429
72170
  };
71430
72171
  var LeaderboardCountdown = ({ targetDate, format: format10, finishedLabel = "Finished", placeholder = "--", onFinished }) => {
71431
- const [time2, setTime] = useState("");
72172
+ const [time2, setTime] = useState(() => {
72173
+ if (!targetDate) return "";
72174
+ return targetDate.getTime() <= Date.now() ? finishedLabel : "";
72175
+ });
72176
+ const [showEndsInPrefix, setShowEndsInPrefix] = useState(() => {
72177
+ if (!targetDate) return true;
72178
+ return targetDate.getTime() > Date.now();
72179
+ });
71432
72180
  const hasFinishedRef = useRef(false);
71433
72181
  useEffect(() => {
71434
72182
  hasFinishedRef.current = false;
@@ -71436,12 +72184,14 @@ var LeaderboardCountdown = ({ targetDate, format: format10, finishedLabel = "Fin
71436
72184
  useEffect(() => {
71437
72185
  if (!targetDate) {
71438
72186
  setTime(placeholder);
72187
+ setShowEndsInPrefix(true);
71439
72188
  return;
71440
72189
  }
71441
72190
  const tick = () => {
71442
72191
  const now4 = /* @__PURE__ */ new Date();
71443
72192
  const diff = targetDate.getTime() - now4.getTime();
71444
72193
  if (diff <= 0) {
72194
+ setShowEndsInPrefix(false);
71445
72195
  setTime(finishedLabel);
71446
72196
  if (!hasFinishedRef.current && onFinished) {
71447
72197
  hasFinishedRef.current = true;
@@ -71449,6 +72199,7 @@ var LeaderboardCountdown = ({ targetDate, format: format10, finishedLabel = "Fin
71449
72199
  }
71450
72200
  return;
71451
72201
  }
72202
+ setShowEndsInPrefix(true);
71452
72203
  if (format10 === "days") {
71453
72204
  const days = Math.floor(diff / (1e3 * 60 * 60 * 24));
71454
72205
  const hours = Math.floor(diff % (1e3 * 60 * 60 * 24) / (1e3 * 60 * 60));
@@ -71465,7 +72216,10 @@ var LeaderboardCountdown = ({ targetDate, format: format10, finishedLabel = "Fin
71465
72216
  const interval = setInterval(tick, 1e3);
71466
72217
  return () => clearInterval(interval);
71467
72218
  }, [targetDate, format10, finishedLabel, placeholder, onFinished]);
71468
- return /* @__PURE__ */ jsx(Fragment, { children: time2 });
72219
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
72220
+ showEndsInPrefix && /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider", children: "Ends in" }),
72221
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-bold text-gray-900 tabular-nums tracking-tight font-mono", children: time2 })
72222
+ ] });
71469
72223
  };
71470
72224
  var LinesLeaderboard = ({
71471
72225
  lines,
@@ -71488,18 +72242,18 @@ var LinesLeaderboard = ({
71488
72242
  isHistoricalDaily
71489
72243
  }) => {
71490
72244
  const formatEfficiency = (value) => typeof value === "number" && Number.isFinite(value) ? `${value.toFixed(1)}%` : "--";
71491
- const assignedLineIdSet = React147__default.useMemo(
72245
+ const assignedLineIdSet = React148__default.useMemo(
71492
72246
  () => new Set(assignedLineIds || []),
71493
72247
  [assignedLineIds]
71494
72248
  );
71495
- const canClickLine = React147__default.useCallback(
72249
+ const canClickLine = React148__default.useCallback(
71496
72250
  (lineId) => {
71497
72251
  if (!assignedLineIds) return true;
71498
72252
  return assignedLineIdSet.has(lineId);
71499
72253
  },
71500
72254
  [assignedLineIds, assignedLineIdSet]
71501
72255
  );
71502
- const handleTimeRangeChange = React147__default.useCallback((newRange) => {
72256
+ const handleTimeRangeChange = React148__default.useCallback((newRange) => {
71503
72257
  if (newRange === timeRange) return;
71504
72258
  trackCoreEvent("Leaderboard Time Range Changed", {
71505
72259
  from_range: timeRange,
@@ -71510,11 +72264,11 @@ var LinesLeaderboard = ({
71510
72264
  });
71511
72265
  setTimeRange(newRange);
71512
72266
  }, [timeRange, lines.length, monthlyEfficiencyByLineId, setTimeRange]);
71513
- const canClickLeaderboardRow = React147__default.useCallback(
72267
+ const canClickLeaderboardRow = React148__default.useCallback(
71514
72268
  (item) => item.rowType === "line" && !!item.line && canClickLine(item.line.id),
71515
72269
  [canClickLine]
71516
72270
  );
71517
- const handleLeaderboardLineClick = React147__default.useCallback((item, clickSource) => {
72271
+ const handleLeaderboardLineClick = React148__default.useCallback((item, clickSource) => {
71518
72272
  if (!canClickLeaderboardRow(item) || !item.line) return;
71519
72273
  trackCoreEvent("Leaderboard Line Clicked", {
71520
72274
  line_id: item.line.id,
@@ -71528,8 +72282,8 @@ var LinesLeaderboard = ({
71528
72282
  });
71529
72283
  onLineClick(item.line);
71530
72284
  }, [canClickLeaderboardRow, onLineClick, timeRange]);
71531
- const viewLoadedTrackedRef = React147__default.useRef(null);
71532
- const leaderboardData = React147__default.useMemo(() => {
72285
+ const viewLoadedTrackedRef = React148__default.useRef(null);
72286
+ const leaderboardData = React148__default.useMemo(() => {
71533
72287
  const loading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
71534
72288
  const efficiencyMap = timeRange === "today" ? todayEfficiencyByLineId : monthlyEfficiencyByLineId;
71535
72289
  const fallbackEfficiencyMap = timeRange === "today" ? dailyFallbackEfficiencyByLineId : void 0;
@@ -71573,7 +72327,7 @@ var LinesLeaderboard = ({
71573
72327
  isLoadingToday,
71574
72328
  isLoadingMonthly
71575
72329
  ]);
71576
- React147__default.useEffect(() => {
72330
+ React148__default.useEffect(() => {
71577
72331
  const isLoading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
71578
72332
  const trackingKey = `${timeRange}-${leaderboardData.length}`;
71579
72333
  if (leaderboardData.length > 0 && !isLoading && viewLoadedTrackedRef.current !== trackingKey) {
@@ -71597,9 +72351,9 @@ var LinesLeaderboard = ({
71597
72351
  const topThree = leaderboardData.slice(0, 3);
71598
72352
  const countdownTarget = timeRange === "monthly" ? monthEndDate : shiftEndDate;
71599
72353
  const countdownFormat = timeRange === "monthly" ? "days" : "clock";
71600
- const countdownFinishedLabel = timeRange === "monthly" ? "Finished" : "Shift Ended";
72354
+ const countdownFinishedLabel = timeRange === "monthly" ? "Finished" : "Shift ended";
71601
72355
  const showCountdown = timeRange === "monthly" || !isHistoricalDaily;
71602
- const handleCountdownFinished = React147__default.useCallback(() => {
72356
+ const handleCountdownFinished = React148__default.useCallback(() => {
71603
72357
  trackCoreEvent("Leaderboard Countdown Finished", {
71604
72358
  countdown_type: timeRange === "monthly" ? "month_end" : "shift_end",
71605
72359
  time_range: timeRange,
@@ -71626,7 +72380,7 @@ var LinesLeaderboard = ({
71626
72380
  return "bg-white border-gray-100";
71627
72381
  }
71628
72382
  };
71629
- React147__default.useEffect(() => {
72383
+ React148__default.useEffect(() => {
71630
72384
  const style = document.createElement("style");
71631
72385
  style.innerHTML = `
71632
72386
  @keyframes float {
@@ -71674,19 +72428,16 @@ var LinesLeaderboard = ({
71674
72428
  ] }),
71675
72429
  /* @__PURE__ */ jsx("div", { className: "md:absolute md:right-0 md:top-1/2 md:-translate-y-1/2 flex flex-wrap items-center justify-center md:justify-end gap-2", children: showCountdown && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 px-4 py-2 bg-white rounded-full shadow-sm border border-gray-100", children: [
71676
72430
  /* @__PURE__ */ jsx(Clock, { className: "w-4 h-4 text-orange-500" }),
71677
- /* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-2", children: [
71678
- /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider", children: "Ends in" }),
71679
- /* @__PURE__ */ jsx("span", { className: "text-sm font-bold text-gray-900 tabular-nums tracking-tight font-mono", children: /* @__PURE__ */ jsx(
71680
- LeaderboardCountdown,
71681
- {
71682
- targetDate: countdownTarget,
71683
- format: countdownFormat,
71684
- finishedLabel: countdownFinishedLabel,
71685
- placeholder: timeRange === "monthly" ? "--" : "--:--:--",
71686
- onFinished: handleCountdownFinished
71687
- }
71688
- ) })
71689
- ] })
72431
+ /* @__PURE__ */ jsx("div", { className: "flex items-baseline gap-2", children: /* @__PURE__ */ jsx(
72432
+ LeaderboardCountdown,
72433
+ {
72434
+ targetDate: countdownTarget,
72435
+ format: countdownFormat,
72436
+ finishedLabel: countdownFinishedLabel,
72437
+ placeholder: timeRange === "monthly" ? "--" : "--:--:--",
72438
+ onFinished: handleCountdownFinished
72439
+ }
72440
+ ) })
71690
72441
  ] }) })
71691
72442
  ] }),
71692
72443
  /* @__PURE__ */ jsx("div", { className: "flex-1 hidden sm:flex justify-center items-end gap-2 md:gap-4 lg:gap-6 xl:gap-10 pb-4 pt-4 min-h-0", children: podiumOrder.map((item, index) => {
@@ -72128,36 +72879,36 @@ var KPIsOverviewView = ({
72128
72879
  const configuredTimezone = dbTimezone || dateTimeConfig.defaultTimezone || "UTC";
72129
72880
  const { startDate: monthStartDate, endDate: monthEndDateKey, monthEndDate } = getMonthDateInfo(configuredTimezone);
72130
72881
  const isSuperAdmin = user?.scope_mode === "SUPER_ADMIN" || !!user?.access_scope?.is_super_admin;
72131
- const scopedLineIds = React147__default.useMemo(
72882
+ const scopedLineIds = React148__default.useMemo(
72132
72883
  () => Array.isArray(user?.access_scope?.line_ids) ? user.access_scope.line_ids.filter((lineId) => typeof lineId === "string" && lineId.length > 0) : [],
72133
72884
  [user?.access_scope?.line_ids]
72134
72885
  );
72135
72886
  const hasCanonicalScope = !!user?.scope_mode || !!user?.access_scope;
72136
72887
  const scopeRole = (user?.role_level || user?.role || "").toLowerCase();
72137
72888
  const isStrictLineScopedRole = scopeRole === "supervisor" || isFactoryScopedRole(scopeRole);
72138
- const resolvedAssignedLineIds = React147__default.useMemo(() => {
72889
+ const resolvedAssignedLineIds = React148__default.useMemo(() => {
72139
72890
  if (isSuperAdmin) return [];
72140
72891
  if (scopedLineIds.length > 0) return scopedLineIds;
72141
72892
  if (lineIds && lineIds.length > 0) return lineIds;
72142
72893
  if (isStrictLineScopedRole && hasCanonicalScope) return [];
72143
72894
  return [];
72144
72895
  }, [isSuperAdmin, scopedLineIds, lineIds, isStrictLineScopedRole, hasCanonicalScope]);
72145
- const assignedLineIdSet = React147__default.useMemo(
72896
+ const assignedLineIdSet = React148__default.useMemo(
72146
72897
  () => new Set(resolvedAssignedLineIds),
72147
72898
  [resolvedAssignedLineIds]
72148
72899
  );
72149
- const loadedLineIds = React147__default.useMemo(
72900
+ const loadedLineIds = React148__default.useMemo(
72150
72901
  () => lines.map((line) => line.id).filter(Boolean),
72151
72902
  [lines]
72152
72903
  );
72153
- const metricsLineIds = React147__default.useMemo(() => {
72904
+ const metricsLineIds = React148__default.useMemo(() => {
72154
72905
  if (isSuperAdmin) {
72155
72906
  return loadedLineIds.length > 0 ? loadedLineIds : lineIds ?? [];
72156
72907
  }
72157
72908
  return resolvedAssignedLineIds;
72158
72909
  }, [isSuperAdmin, loadedLineIds, lineIds, resolvedAssignedLineIds]);
72159
72910
  const assignedLineIdsForLeaderboard = isSuperAdmin ? void 0 : resolvedAssignedLineIds;
72160
- const leaderboardLinesForView = React147__default.useMemo(() => {
72911
+ const leaderboardLinesForView = React148__default.useMemo(() => {
72161
72912
  const targetMode = viewType === "machine" ? "uptime" : "output";
72162
72913
  const metadataByLineId = new Map(lines.map((line) => [line.id, line]));
72163
72914
  return leaderboardLines.map((line) => {
@@ -72176,17 +72927,17 @@ var KPIsOverviewView = ({
72176
72927
  } : line;
72177
72928
  }).filter((line) => (line.monitoring_mode ?? "output") === targetMode);
72178
72929
  }, [leaderboardLines, lines, viewType]);
72179
- const linesForView = React147__default.useMemo(() => {
72930
+ const linesForView = React148__default.useMemo(() => {
72180
72931
  const targetMode = viewType === "machine" ? "uptime" : "output";
72181
72932
  return lines.filter((line) => (line.monitoring_mode ?? "output") === targetMode);
72182
72933
  }, [lines, viewType]);
72183
- const relevantLinesForMode = React147__default.useMemo(() => {
72934
+ const relevantLinesForMode = React148__default.useMemo(() => {
72184
72935
  if (activeTab === "leaderboard") {
72185
72936
  return leaderboardLines.length > 0 ? leaderboardLines : lines;
72186
72937
  }
72187
72938
  return lines;
72188
72939
  }, [activeTab, leaderboardLines, lines]);
72189
- const { hasUptime, hasOutput } = React147__default.useMemo(() => {
72940
+ const { hasUptime, hasOutput } = React148__default.useMemo(() => {
72190
72941
  let uptime = false;
72191
72942
  let output = false;
72192
72943
  for (const line of relevantLinesForMode) {
@@ -72211,14 +72962,14 @@ var KPIsOverviewView = ({
72211
72962
  const currentShiftDetails = getCurrentShift(configuredTimezone, shiftConfig);
72212
72963
  const currentShiftDate = currentShiftDetails.date;
72213
72964
  const currentShiftId = currentShiftDetails.shiftId;
72214
- const activeFiltersCount = React147__default.useMemo(() => {
72965
+ const activeFiltersCount = React148__default.useMemo(() => {
72215
72966
  let count = 0;
72216
72967
  if (leaderboardDailyScopeMode === "historical" && selectedLeaderboardShiftId !== currentShiftId) {
72217
72968
  count++;
72218
72969
  }
72219
72970
  return count;
72220
72971
  }, [leaderboardDailyScopeMode, selectedLeaderboardShiftId, currentShiftId]);
72221
- const clearFilters = React147__default.useCallback(() => {
72972
+ const clearFilters = React148__default.useCallback(() => {
72222
72973
  setSelectedLeaderboardShiftId(currentShiftId);
72223
72974
  setSelectedLeaderboardDate(currentShiftDate);
72224
72975
  setLeaderboardDailyScopeMode("live");
@@ -72234,11 +72985,11 @@ var KPIsOverviewView = ({
72234
72985
  document.addEventListener("mousedown", handleClickOutside);
72235
72986
  return () => document.removeEventListener("mousedown", handleClickOutside);
72236
72987
  }, []);
72237
- const shiftEndDate = React147__default.useMemo(
72988
+ const shiftEndDate = React148__default.useMemo(
72238
72989
  () => getShiftEndDate(currentShiftDetails, configuredTimezone),
72239
72990
  [currentShiftDetails, configuredTimezone]
72240
72991
  );
72241
- const leaderboardShiftOptions = React147__default.useMemo(() => {
72992
+ const leaderboardShiftOptions = React148__default.useMemo(() => {
72242
72993
  if (shiftConfig?.shifts && shiftConfig.shifts.length > 0) {
72243
72994
  return shiftConfig.shifts.map((shift) => ({
72244
72995
  id: shift.shiftId,
@@ -72255,34 +73006,34 @@ var KPIsOverviewView = ({
72255
73006
  const effectiveLeaderboardDate = selectedLeaderboardDate || currentShiftDate;
72256
73007
  const effectiveLeaderboardShiftId = Number.isFinite(selectedLeaderboardShiftId) ? selectedLeaderboardShiftId : currentShiftId;
72257
73008
  const isHistoricalLeaderboardDaily = activeTab === "leaderboard" && timeRange === "today" && leaderboardDailyScopeMode === "historical" && (effectiveLeaderboardDate !== currentShiftDate || effectiveLeaderboardShiftId !== currentShiftId);
72258
- const updateLeaderboardDate = React147__default.useCallback((dateKey) => {
73009
+ const updateLeaderboardDate = React148__default.useCallback((dateKey) => {
72259
73010
  setSelectedLeaderboardDate(dateKey);
72260
73011
  setLeaderboardDailyScopeMode(
72261
73012
  dateKey === currentShiftDate && effectiveLeaderboardShiftId === currentShiftId ? "live" : "historical"
72262
73013
  );
72263
73014
  }, [currentShiftDate, currentShiftId, effectiveLeaderboardShiftId]);
72264
- const updateLeaderboardShiftId = React147__default.useCallback((shiftId) => {
73015
+ const updateLeaderboardShiftId = React148__default.useCallback((shiftId) => {
72265
73016
  setSelectedLeaderboardShiftId(shiftId);
72266
73017
  setLeaderboardDailyScopeMode(
72267
73018
  effectiveLeaderboardDate === currentShiftDate && shiftId === currentShiftId ? "live" : "historical"
72268
73019
  );
72269
73020
  }, [currentShiftDate, currentShiftId, effectiveLeaderboardDate]);
72270
- const returnLeaderboardToLive = React147__default.useCallback(() => {
73021
+ const returnLeaderboardToLive = React148__default.useCallback(() => {
72271
73022
  setSelectedLeaderboardDate(currentShiftDate);
72272
73023
  setSelectedLeaderboardShiftId(currentShiftId);
72273
73024
  setLeaderboardDailyScopeMode("live");
72274
73025
  }, [currentShiftDate, currentShiftId]);
72275
73026
  const selectedFactoryIdFromUrl = getSingleQueryValue(router.query[KPI_FACTORY_QUERY_PARAM]);
72276
73027
  const selectedFactoryAreaIdFromUrl = getSingleQueryValue(router.query[KPI_FACTORY_AREA_QUERY_PARAM]);
72277
- const kpiLineHierarchy = React147__default.useMemo(
73028
+ const kpiLineHierarchy = React148__default.useMemo(
72278
73029
  () => buildKpiLineHierarchy(linesForView),
72279
73030
  [linesForView]
72280
73031
  );
72281
- const selectedFactoryNode = React147__default.useMemo(
73032
+ const selectedFactoryNode = React148__default.useMemo(
72282
73033
  () => kpiLineHierarchy.showFactoryLevel && selectedFactoryIdFromUrl ? kpiLineHierarchy.factories.find((factory) => factory.id === selectedFactoryIdFromUrl) : void 0,
72283
73034
  [kpiLineHierarchy, selectedFactoryIdFromUrl]
72284
73035
  );
72285
- const selectedFactoryAreaNode = React147__default.useMemo(
73036
+ const selectedFactoryAreaNode = React148__default.useMemo(
72286
73037
  () => selectedFactoryNode && selectedFactoryAreaIdFromUrl ? selectedFactoryNode.areas.find((area) => area.id === selectedFactoryAreaIdFromUrl) : void 0,
72287
73038
  [selectedFactoryNode, selectedFactoryAreaIdFromUrl]
72288
73039
  );
@@ -72371,15 +73122,15 @@ var KPIsOverviewView = ({
72371
73122
  lineId: factoryViewId,
72372
73123
  userAccessibleLineIds: metricsLineIds
72373
73124
  });
72374
- const defaultKPIs = React147__default.useMemo(() => createDefaultKPIs(), []);
72375
- const lineModeById = React147__default.useMemo(() => {
73125
+ const defaultKPIs = React148__default.useMemo(() => createDefaultKPIs(), []);
73126
+ const lineModeById = React148__default.useMemo(() => {
72376
73127
  const map = /* @__PURE__ */ new Map();
72377
73128
  linesForView.forEach((line) => {
72378
73129
  map.set(line.id, line.monitoring_mode ?? "output");
72379
73130
  });
72380
73131
  return map;
72381
73132
  }, [linesForView]);
72382
- const lineMetricRowsByLineId = React147__default.useMemo(() => {
73133
+ const lineMetricRowsByLineId = React148__default.useMemo(() => {
72383
73134
  const map = /* @__PURE__ */ new Map();
72384
73135
  lineMetrics.forEach((row) => {
72385
73136
  if (!row?.line_id) return;
@@ -72391,7 +73142,7 @@ var KPIsOverviewView = ({
72391
73142
  });
72392
73143
  return map;
72393
73144
  }, [lineMetrics, lineModeById]);
72394
- const liveDailyFallbackEfficiencyByLineId = React147__default.useMemo(() => {
73145
+ const liveDailyFallbackEfficiencyByLineId = React148__default.useMemo(() => {
72395
73146
  const map = /* @__PURE__ */ new Map();
72396
73147
  lineMetricRowsByLineId.forEach((row, lineId) => {
72397
73148
  const value = Number(row?.avg_efficiency);
@@ -72413,31 +73164,31 @@ var KPIsOverviewView = ({
72413
73164
  isHistoricalLeaderboardDaily,
72414
73165
  lineMetricRowsByLineId
72415
73166
  ]);
72416
- const dailyFallbackEfficiencyByLineId = React147__default.useMemo(() => {
73167
+ const dailyFallbackEfficiencyByLineId = React148__default.useMemo(() => {
72417
73168
  const map = new Map(liveDailyFallbackEfficiencyByLineId);
72418
73169
  scopedDailyFallbackEfficiencyByLineId.forEach((value, lineId) => {
72419
73170
  map.set(lineId, value);
72420
73171
  });
72421
73172
  return map;
72422
73173
  }, [liveDailyFallbackEfficiencyByLineId, scopedDailyFallbackEfficiencyByLineId]);
72423
- const kpisByLineId = React147__default.useMemo(() => {
73174
+ const kpisByLineId = React148__default.useMemo(() => {
72424
73175
  const map = /* @__PURE__ */ new Map();
72425
73176
  lineMetricRowsByLineId.forEach((row, lineId) => {
72426
73177
  map.set(lineId, buildKPIsFromLineMetricsRow(row));
72427
73178
  });
72428
73179
  return map;
72429
73180
  }, [lineMetricRowsByLineId]);
72430
- const getLineCardKpis = React147__default.useCallback((line) => {
73181
+ const getLineCardKpis = React148__default.useCallback((line) => {
72431
73182
  if (metricsError) return null;
72432
73183
  return kpisByLineId.get(line.id) ?? (metricsLoading ? null : defaultKPIs);
72433
73184
  }, [defaultKPIs, kpisByLineId, metricsError, metricsLoading]);
72434
- const getAggregateCardKpis = React147__default.useCallback((cardLines) => {
73185
+ const getAggregateCardKpis = React148__default.useCallback((cardLines) => {
72435
73186
  if (metricsError) return null;
72436
73187
  const rows = cardLines.map((line) => lineMetricRowsByLineId.get(line.id)).filter(Boolean);
72437
73188
  if (metricsLoading && rows.length === 0) return null;
72438
73189
  return aggregateKPIsFromLineMetricsRows(rows);
72439
73190
  }, [lineMetricRowsByLineId, metricsError, metricsLoading]);
72440
- const supervisorLineIds = React147__default.useMemo(
73191
+ const supervisorLineIds = React148__default.useMemo(
72441
73192
  () => (leaderboardLines.length > 0 ? leaderboardLines : lines).map((l) => l.id),
72442
73193
  [leaderboardLines, lines]
72443
73194
  );
@@ -72689,7 +73440,7 @@ var KPIsOverviewView = ({
72689
73440
  { shallow: true }
72690
73441
  );
72691
73442
  }, [router]);
72692
- const lineDetailReturnTo = React147__default.useMemo(() => {
73443
+ const lineDetailReturnTo = React148__default.useMemo(() => {
72693
73444
  if (activeTab !== "today" || !selectedFactoryNode) return void 0;
72694
73445
  return createKpisOverviewUrl({
72695
73446
  factoryId: selectedFactoryNode.id,
@@ -73489,7 +74240,7 @@ var LeaderboardDetailView = memo$1(({
73489
74240
  return () => document.removeEventListener("mousedown", handleClickOutside);
73490
74241
  }, []);
73491
74242
  const [isMobile, setIsMobile] = useState(false);
73492
- React147__default.useEffect(() => {
74243
+ React148__default.useEffect(() => {
73493
74244
  const checkMobile = () => setIsMobile(window.innerWidth < 640);
73494
74245
  checkMobile();
73495
74246
  window.addEventListener("resize", checkMobile);
@@ -77539,7 +78290,7 @@ var ShiftsView = ({
77539
78290
  ] })
77540
78291
  ] });
77541
78292
  };
77542
- var AuthenticatedShiftsView = withAuth(React147__default.memo(ShiftsView));
78293
+ var AuthenticatedShiftsView = withAuth(React148__default.memo(ShiftsView));
77543
78294
  var ShiftsView_default = ShiftsView;
77544
78295
 
77545
78296
  // src/views/TargetsView.utils.ts
@@ -79406,7 +80157,7 @@ var TargetsView = ({
79406
80157
  };
79407
80158
  var TargetsViewWithDisplayNames = withAllWorkspaceDisplayNames(TargetsView);
79408
80159
  var TargetsView_default = TargetsViewWithDisplayNames;
79409
- var AuthenticatedTargetsView = withAuth(React147__default.memo(TargetsViewWithDisplayNames));
80160
+ var AuthenticatedTargetsView = withAuth(React148__default.memo(TargetsViewWithDisplayNames));
79410
80161
  function useTimezone(options = {}) {
79411
80162
  const dashboardConfig = useDashboardConfig();
79412
80163
  const workspaceConfig = useWorkspaceConfig();
@@ -79554,7 +80305,7 @@ var formatWholeNumber = (value) => {
79554
80305
  if (typeof value !== "number" || !Number.isFinite(value)) return null;
79555
80306
  return Math.round(value).toLocaleString();
79556
80307
  };
79557
- var formatSeconds = (value) => {
80308
+ var formatSeconds2 = (value) => {
79558
80309
  if (typeof value !== "number" || !Number.isFinite(value)) return null;
79559
80310
  return `${value.toFixed(1)}s`;
79560
80311
  };
@@ -79571,13 +80322,13 @@ var WorkspaceHourSummaryPanel = ({
79571
80322
  }) => {
79572
80323
  const { data, isLoading, error, summarize, reset } = useWorkspaceHourSummary();
79573
80324
  const selectedKey = selectedHour ? `${selectedHour.source}:${selectedHour.hourIndex}:${date}:${shiftId}` : "none";
79574
- const autoSummaryKeyRef = React147__default.useRef(null);
79575
- React147__default.useEffect(() => {
80325
+ const autoSummaryKeyRef = React148__default.useRef(null);
80326
+ React148__default.useEffect(() => {
79576
80327
  reset();
79577
80328
  autoSummaryKeyRef.current = null;
79578
80329
  }, [reset, selectedKey]);
79579
80330
  const canSummarize = Boolean(workspaceId && companyId && date && shiftId !== null && shiftId !== void 0);
79580
- React147__default.useEffect(() => {
80331
+ React148__default.useEffect(() => {
79581
80332
  if (!selectedHour || !canSummarize || !companyId || !date || shiftId === null || shiftId === void 0) {
79582
80333
  return;
79583
80334
  }
@@ -79606,8 +80357,8 @@ var WorkspaceHourSummaryPanel = ({
79606
80357
  const formattedTimeRange = formatTimeRangeTo12Hour(verifiedTimeRange);
79607
80358
  const selectedMetric = selectedHour.source === "cycle" ? {
79608
80359
  label: "Cycle time",
79609
- actual: formatSeconds(selectedHour.cycleTime),
79610
- standard: formatSeconds(selectedHour.idealCycleTime)
80360
+ actual: formatSeconds2(selectedHour.cycleTime),
80361
+ standard: formatSeconds2(selectedHour.idealCycleTime)
79611
80362
  } : {
79612
80363
  label: "Hourly output",
79613
80364
  actual: formatWholeNumber(selectedHour.output),
@@ -79783,6 +80534,7 @@ var WorkspaceDetailView = ({
79783
80534
  const { legend: efficiencyLegend } = useEfficiencyLegend();
79784
80535
  const prewarmedClipsRef = useRef(/* @__PURE__ */ new Set());
79785
80536
  const prewarmInFlightRef = useRef(/* @__PURE__ */ new Set());
80537
+ const [lowMomentsPrefetch, setLowMomentsPrefetch] = useState(null);
79786
80538
  const [aiSummaryHour, setAiSummaryHour] = useState(null);
79787
80539
  const buildHourlyOutputActionTrackingProps = useCallback((payload) => ({
79788
80540
  workspace_id: workspaceId,
@@ -80295,13 +81047,108 @@ var WorkspaceDetailView = ({
80295
81047
  }
80296
81048
  prewarmInFlightRef.current.add(cacheKey);
80297
81049
  const s3Service = videoPrefetchManager.getS3Service(dashboardConfig);
80298
- s3Service.getClipsInit(workspaceId, resolvedDate, resolvedShiftId, totalOutput).then(() => {
80299
- prewarmedClipsRef.current.add(cacheKey);
80300
- }).catch((error2) => {
80301
- console.warn("[WorkspaceDetailView] Clips init prewarm failed:", error2);
80302
- }).finally(() => {
80303
- prewarmInFlightRef.current.delete(cacheKey);
80304
- });
81050
+ const controller = new AbortController();
81051
+ let cancelled = false;
81052
+ const prefetchLowMoments = async () => {
81053
+ try {
81054
+ const initData = await s3Service.getClipsInit(workspaceId, resolvedDate, resolvedShiftId, totalOutput);
81055
+ const lowMomentsCount = Number(initData?.counts?.recent_flow_red_streak || 0);
81056
+ const lowMomentsKey = [
81057
+ "recent_flow_red_streak",
81058
+ resolvedDate,
81059
+ resolvedShiftId,
81060
+ initData?.snapshotDateTime ?? "nosnap",
81061
+ initData?.snapshotClipId ?? "nosnap",
81062
+ "red_flow_output_shortfall_desc"
81063
+ ].join("-");
81064
+ if (cancelled) {
81065
+ return;
81066
+ }
81067
+ const initFirstVideo = initData?.firstClips?.recent_flow_red_streak ?? null;
81068
+ if (lowMomentsCount <= 0) {
81069
+ setLowMomentsPrefetch((prev) => prev?.key === lowMomentsKey ? {
81070
+ key: lowMomentsKey,
81071
+ metadata: [],
81072
+ firstVideo: null,
81073
+ total: 0,
81074
+ loading: false,
81075
+ error: null
81076
+ } : prev);
81077
+ prewarmedClipsRef.current.add(cacheKey);
81078
+ return;
81079
+ }
81080
+ setLowMomentsPrefetch((prev) => {
81081
+ if (prev?.key === lowMomentsKey && !prev.loading && prev.metadata.length > 0) {
81082
+ return prev;
81083
+ }
81084
+ return {
81085
+ key: lowMomentsKey,
81086
+ metadata: prev?.key === lowMomentsKey ? prev.metadata : [],
81087
+ firstVideo: prev?.key === lowMomentsKey ? prev.firstVideo || initFirstVideo : initFirstVideo,
81088
+ total: lowMomentsCount,
81089
+ loading: true,
81090
+ error: null
81091
+ };
81092
+ });
81093
+ const metadataResponse = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
81094
+ method: "POST",
81095
+ headers: {
81096
+ "Content-Type": "application/json"
81097
+ },
81098
+ body: JSON.stringify({
81099
+ action: "clip-metadata",
81100
+ workspaceId,
81101
+ date: resolvedDate,
81102
+ shift: resolvedShiftId,
81103
+ category: "recent_flow_red_streak",
81104
+ page: 1,
81105
+ limit: 100,
81106
+ knownTotal: lowMomentsCount,
81107
+ snapshotDateTime: initData?.snapshotDateTime ?? null,
81108
+ snapshotClipId: initData?.snapshotClipId ?? null,
81109
+ sort: "red_flow_output_shortfall_desc"
81110
+ }),
81111
+ signal: controller.signal,
81112
+ redirectReason: "session_expired"
81113
+ });
81114
+ if (!metadataResponse.ok) {
81115
+ throw new Error(`Low moments metadata prefetch failed: ${metadataResponse.status}`);
81116
+ }
81117
+ const metadataData = await metadataResponse.json();
81118
+ const metadata = Array.isArray(metadataData?.clips) ? metadataData.clips : [];
81119
+ const firstClipId = metadata[0]?.clipId || metadata[0]?.id || null;
81120
+ const firstVideo = initFirstVideo && (!firstClipId || initFirstVideo.id === firstClipId) ? initFirstVideo : firstClipId ? await s3Service.getClipById(firstClipId) : null;
81121
+ if (cancelled) {
81122
+ return;
81123
+ }
81124
+ setLowMomentsPrefetch({
81125
+ key: lowMomentsKey,
81126
+ metadata,
81127
+ firstVideo,
81128
+ total: typeof metadataData?.total === "number" ? metadataData.total : lowMomentsCount,
81129
+ loading: false,
81130
+ error: null
81131
+ });
81132
+ prewarmedClipsRef.current.add(cacheKey);
81133
+ } catch (error2) {
81134
+ if (error2.name === "AbortError") {
81135
+ return;
81136
+ }
81137
+ console.warn("[WorkspaceDetailView] Clips init prewarm failed:", error2);
81138
+ setLowMomentsPrefetch((prev) => prev ? {
81139
+ ...prev,
81140
+ loading: false,
81141
+ error: error2 instanceof Error ? error2.message : "Low moments prefetch failed"
81142
+ } : prev);
81143
+ } finally {
81144
+ prewarmInFlightRef.current.delete(cacheKey);
81145
+ }
81146
+ };
81147
+ void prefetchLowMoments();
81148
+ return () => {
81149
+ cancelled = true;
81150
+ controller.abort();
81151
+ };
80305
81152
  }, [
80306
81153
  isClipsEnabled,
80307
81154
  dashboardConfig,
@@ -80311,7 +81158,8 @@ var WorkspaceDetailView = ({
80311
81158
  isShiftConfigLoading,
80312
81159
  shiftConfig,
80313
81160
  timezone,
80314
- workspace
81161
+ workspace,
81162
+ supabase
80315
81163
  ]);
80316
81164
  const { supervisorName, supervisors } = useLineSupervisor(workspace?.line_id || lineId);
80317
81165
  useEffect(() => {
@@ -81530,6 +82378,7 @@ var WorkspaceDetailView = ({
81530
82378
  totalOutput: workspace?.total_actions,
81531
82379
  workspaceMetrics: detailedWorkspaceMetrics || void 0,
81532
82380
  prefetchedPercentileCounts: isFastSlowClipFiltersEnabled ? prefetchedPercentileCounts : null,
82381
+ lowMomentsPrefetch,
81533
82382
  initialTimeFilter: pendingClipHourFilter,
81534
82383
  className: "h-[calc(100vh-10rem)]"
81535
82384
  }
@@ -83168,7 +84017,7 @@ function BottleneckClipsView({
83168
84017
  ) })
83169
84018
  ] }) });
83170
84019
  }
83171
- var AuthenticatedBottleneckClipsView = withAuth(React147__default.memo(BottleneckClipsView));
84020
+ var AuthenticatedBottleneckClipsView = withAuth(React148__default.memo(BottleneckClipsView));
83172
84021
  var BottleneckClipsView_default = BottleneckClipsView;
83173
84022
 
83174
84023
  // src/lib/services/ticketService.ts
@@ -84011,7 +84860,7 @@ Please ensure:
84011
84860
  )
84012
84861
  ] });
84013
84862
  }
84014
- var AuthenticatedTicketsView = withAuth(React147__default.memo(TicketsView));
84863
+ var AuthenticatedTicketsView = withAuth(React148__default.memo(TicketsView));
84015
84864
  var TicketsView_default = TicketsView;
84016
84865
 
84017
84866
  // src/lib/utils/improvementDisplay.ts
@@ -84982,7 +85831,7 @@ var ImprovementCenterView = () => {
84982
85831
  setSelectedMemberId("all");
84983
85832
  }
84984
85833
  }, [memberOptions, selectedMemberId]);
84985
- const getRecommendationDisplayMetadata = React147__default.useCallback((rec) => {
85834
+ const getRecommendationDisplayMetadata = React148__default.useCallback((rec) => {
84986
85835
  const supervisors = rec.line_id ? supervisorsByLineId.get(rec.line_id) || [] : [];
84987
85836
  return getImprovementDisplayMetadata({
84988
85837
  location: rec.location,
@@ -85456,7 +86305,7 @@ var ThreadSidebar = ({
85456
86305
  ] }) })
85457
86306
  ] });
85458
86307
  };
85459
- var ProfilePicture = React147__default.memo(({
86308
+ var ProfilePicture = React148__default.memo(({
85460
86309
  alt = "Axel",
85461
86310
  className = "",
85462
86311
  size = "md",
@@ -88016,7 +88865,7 @@ var OverviewImprovementsSkeleton = () => /* @__PURE__ */ jsx("div", { className:
88016
88865
  ] }),
88017
88866
  /* @__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" }) })
88018
88867
  ] }, index)) });
88019
- var OperationsOverviewHeader = React147__default.memo(({
88868
+ var OperationsOverviewHeader = React148__default.memo(({
88020
88869
  dateRange,
88021
88870
  displayDateRange,
88022
88871
  trendMode,
@@ -88037,65 +88886,65 @@ var OperationsOverviewHeader = React147__default.memo(({
88037
88886
  bumpRenderCounter();
88038
88887
  const subtitleRange = displayDateRange || dateRange;
88039
88888
  const showLiveShiftMeta = isLiveScope && trendMode !== "all";
88040
- const liveShiftLabel = React147__default.useMemo(
88889
+ const liveShiftLabel = React148__default.useMemo(
88041
88890
  () => normalizeShiftLabel(liveShiftName, trendMode),
88042
88891
  [liveShiftName, trendMode]
88043
88892
  );
88044
- const liveShiftIcon = React147__default.useMemo(
88893
+ const liveShiftIcon = React148__default.useMemo(
88045
88894
  () => getShiftIcon(liveShiftName, trendMode),
88046
88895
  [liveShiftName, trendMode]
88047
88896
  );
88048
- const [isFilterOpen, setIsFilterOpen] = React147__default.useState(false);
88049
- const [isLinesDropdownOpen, setIsLinesDropdownOpen] = React147__default.useState(false);
88050
- const filterRef = React147__default.useRef(null);
88051
- const filterButtonRef = React147__default.useRef(null);
88052
- const mobileFilterButtonRef = React147__default.useRef(null);
88053
- const linesDropdownRef = React147__default.useRef(null);
88054
- const mobileSubtitle = React147__default.useMemo(() => {
88897
+ const [isFilterOpen, setIsFilterOpen] = React148__default.useState(false);
88898
+ const [isLinesDropdownOpen, setIsLinesDropdownOpen] = React148__default.useState(false);
88899
+ const filterRef = React148__default.useRef(null);
88900
+ const filterButtonRef = React148__default.useRef(null);
88901
+ const mobileFilterButtonRef = React148__default.useRef(null);
88902
+ const linesDropdownRef = React148__default.useRef(null);
88903
+ const mobileSubtitle = React148__default.useMemo(() => {
88055
88904
  if (subtitleRange.startKey === subtitleRange.endKey) {
88056
88905
  return format(parseDateKeyToDate(subtitleRange.startKey), "do MMM, yyyy");
88057
88906
  }
88058
88907
  return `${format(parseDateKeyToDate(subtitleRange.startKey), "do MMM")} - ${format(parseDateKeyToDate(subtitleRange.endKey), "do MMM, yyyy")}`;
88059
88908
  }, [subtitleRange.endKey, subtitleRange.startKey]);
88060
- const desktopSubtitle = React147__default.useMemo(() => {
88909
+ const desktopSubtitle = React148__default.useMemo(() => {
88061
88910
  if (subtitleRange.startKey === subtitleRange.endKey) {
88062
88911
  return format(parseDateKeyToDate(subtitleRange.startKey), "do MMMM, yyyy");
88063
88912
  }
88064
88913
  return `${format(parseDateKeyToDate(subtitleRange.startKey), "do MMMM, yyyy")} - ${format(parseDateKeyToDate(subtitleRange.endKey), "do MMMM, yyyy")}`;
88065
88914
  }, [subtitleRange.endKey, subtitleRange.startKey]);
88066
- const availableLineIds = React147__default.useMemo(
88915
+ const availableLineIds = React148__default.useMemo(
88067
88916
  () => lineOptions.map((line) => line.id),
88068
88917
  [lineOptions]
88069
88918
  );
88070
- const selectedLineIdSet = React147__default.useMemo(
88919
+ const selectedLineIdSet = React148__default.useMemo(
88071
88920
  () => new Set(selectedLineIds),
88072
88921
  [selectedLineIds]
88073
88922
  );
88074
- const isAllLinesSelected = React147__default.useMemo(() => {
88923
+ const isAllLinesSelected = React148__default.useMemo(() => {
88075
88924
  if (availableLineIds.length === 0) return true;
88076
88925
  return availableLineIds.every((lineId) => selectedLineIdSet.has(lineId));
88077
88926
  }, [availableLineIds, selectedLineIdSet]);
88078
- const activeFilterCount = React147__default.useMemo(() => {
88927
+ const activeFilterCount = React148__default.useMemo(() => {
88079
88928
  let count = 0;
88080
88929
  if (trendMode !== "all") count += 1;
88081
88930
  if (selectedSupervisorId !== "all") count += 1;
88082
88931
  if (!isAllLinesSelected) count += 1;
88083
88932
  return count;
88084
88933
  }, [isAllLinesSelected, selectedSupervisorId, trendMode]);
88085
- const handleFilterToggle = React147__default.useCallback(() => {
88934
+ const handleFilterToggle = React148__default.useCallback(() => {
88086
88935
  trackCoreEvent("Operations Overview Filter Toggled", {
88087
88936
  action: !isFilterOpen ? "open" : "close"
88088
88937
  });
88089
88938
  setIsFilterOpen((previous) => !previous);
88090
88939
  }, [isFilterOpen]);
88091
- const handleTrendModeChange = React147__default.useCallback((event) => {
88940
+ const handleTrendModeChange = React148__default.useCallback((event) => {
88092
88941
  const nextMode = event.target.value;
88093
88942
  trackCoreEvent("Operations Overview Shift Filter Changed", {
88094
88943
  shift_mode: nextMode
88095
88944
  });
88096
88945
  onTrendModeChange(nextMode);
88097
88946
  }, [onTrendModeChange]);
88098
- const handleAllLinesToggle = React147__default.useCallback(() => {
88947
+ const handleAllLinesToggle = React148__default.useCallback(() => {
88099
88948
  trackCoreEvent("Operations Overview Line Filter Changed", {
88100
88949
  selected_line_ids: availableLineIds,
88101
88950
  selected_line_count: availableLineIds.length,
@@ -88103,7 +88952,7 @@ var OperationsOverviewHeader = React147__default.memo(({
88103
88952
  });
88104
88953
  onSelectedLineIdsChange(availableLineIds);
88105
88954
  }, [availableLineIds, onSelectedLineIdsChange]);
88106
- const handleSupervisorChange = React147__default.useCallback((event) => {
88955
+ const handleSupervisorChange = React148__default.useCallback((event) => {
88107
88956
  const supervisorId = event.target.value;
88108
88957
  const selectedSupervisor = supervisorOptions.find((option) => option.id === supervisorId);
88109
88958
  trackCoreEvent("Operations Overview Supervisor Filter Changed", {
@@ -88114,7 +88963,7 @@ var OperationsOverviewHeader = React147__default.memo(({
88114
88963
  });
88115
88964
  onSelectedSupervisorIdChange(supervisorId);
88116
88965
  }, [availableLineIds, onSelectedSupervisorIdChange, supervisorOptions]);
88117
- const handleLineToggle = React147__default.useCallback((lineId) => {
88966
+ const handleLineToggle = React148__default.useCallback((lineId) => {
88118
88967
  const current = new Set(selectedLineIds);
88119
88968
  if (current.has(lineId)) {
88120
88969
  if (current.size <= 1) return;
@@ -88130,13 +88979,13 @@ var OperationsOverviewHeader = React147__default.memo(({
88130
88979
  });
88131
88980
  onSelectedLineIdsChange(next);
88132
88981
  }, [availableLineIds, onSelectedLineIdsChange, selectedLineIds]);
88133
- const handleClearAllFilters = React147__default.useCallback(() => {
88982
+ const handleClearAllFilters = React148__default.useCallback(() => {
88134
88983
  onTrendModeChange("all");
88135
88984
  onSelectedSupervisorIdChange("all");
88136
88985
  onSelectedLineIdsChange(availableLineIds);
88137
88986
  setIsFilterOpen(false);
88138
88987
  }, [availableLineIds, onSelectedLineIdsChange, onSelectedSupervisorIdChange, onTrendModeChange]);
88139
- React147__default.useEffect(() => {
88988
+ React148__default.useEffect(() => {
88140
88989
  const handleClickOutside = (event) => {
88141
88990
  const target = event.target;
88142
88991
  if (filterRef.current && !filterRef.current.contains(target) && filterButtonRef.current && !filterButtonRef.current.contains(target) && mobileFilterButtonRef.current && !mobileFilterButtonRef.current.contains(target)) {
@@ -88371,12 +89220,12 @@ var OperationsOverviewHeader = React147__default.memo(({
88371
89220
  ] }) });
88372
89221
  });
88373
89222
  OperationsOverviewHeader.displayName = "OperationsOverviewHeader";
88374
- var OverviewSummaryCards = React147__default.memo(({ store }) => {
89223
+ var OverviewSummaryCards = React148__default.memo(({ store }) => {
88375
89224
  bumpRenderCounter();
88376
89225
  const scope = useOperationsOverviewScope(store);
88377
89226
  const snapshot = useOperationsOverviewSnapshot(store);
88378
89227
  const showSnapshotSkeleton = snapshot.loading && !snapshot.hasLoadedOnce;
88379
- const comparisonLabel = React147__default.useMemo(() => {
89228
+ const comparisonLabel = React148__default.useMemo(() => {
88380
89229
  return formatComparisonWindow({
88381
89230
  currentDayCount: scope.current_range?.day_count ?? null,
88382
89231
  previousDayCount: scope.previous_range?.day_count ?? null,
@@ -88389,27 +89238,27 @@ var OverviewSummaryCards = React147__default.memo(({ store }) => {
88389
89238
  scope.previous_range?.day_count,
88390
89239
  scope.shift_mode
88391
89240
  ]);
88392
- const [isIdleContributorsOpen, setIsIdleContributorsOpen] = React147__default.useState(false);
88393
- const [isIdleContributorsPinned, setIsIdleContributorsPinned] = React147__default.useState(false);
88394
- const idleContributorsRef = React147__default.useRef(null);
88395
- const plantEfficiencyBadge = React147__default.useMemo(() => {
89241
+ const [isIdleContributorsOpen, setIsIdleContributorsOpen] = React148__default.useState(false);
89242
+ const [isIdleContributorsPinned, setIsIdleContributorsPinned] = React148__default.useState(false);
89243
+ const idleContributorsRef = React148__default.useRef(null);
89244
+ const plantEfficiencyBadge = React148__default.useMemo(() => {
88396
89245
  return buildDeltaBadge(snapshot.data.summary.plant_efficiency?.delta_pp, {
88397
89246
  positiveIsGood: true,
88398
89247
  formatter: (value) => `${value >= 0 ? "+" : ""}${roundOne(value)}%`,
88399
89248
  comparisonLabel
88400
89249
  });
88401
89250
  }, [comparisonLabel, snapshot.data.summary.plant_efficiency?.delta_pp]);
88402
- const idleBadge = React147__default.useMemo(() => {
89251
+ const idleBadge = React148__default.useMemo(() => {
88403
89252
  return buildDeltaBadge(snapshot.data.summary.avg_idle_per_workstation?.delta_seconds, {
88404
89253
  positiveIsGood: false,
88405
89254
  formatter: (value) => formatSignedIdleDuration(value),
88406
89255
  comparisonLabel
88407
89256
  });
88408
89257
  }, [comparisonLabel, snapshot.data.summary.avg_idle_per_workstation?.delta_seconds]);
88409
- const canInspectIdleContributors = React147__default.useMemo(() => {
89258
+ const canInspectIdleContributors = React148__default.useMemo(() => {
88410
89259
  return !showSnapshotSkeleton && snapshot.data.summary.avg_idle_per_workstation?.current_seconds !== null && snapshot.data.summary.avg_idle_per_workstation?.current_seconds !== void 0;
88411
89260
  }, [showSnapshotSkeleton, snapshot.data.summary.avg_idle_per_workstation?.current_seconds]);
88412
- const idleTopContributors = React147__default.useMemo(() => {
89261
+ const idleTopContributors = React148__default.useMemo(() => {
88413
89262
  return (snapshot.data.summary.avg_idle_per_workstation?.top_contributors || []).map((item) => ({
88414
89263
  workspaceId: item.workspace_id || "",
88415
89264
  workspaceName: item.workspace_name?.trim() || item.workspace_id || "Unknown",
@@ -88417,14 +89266,14 @@ var OverviewSummaryCards = React147__default.memo(({ store }) => {
88417
89266
  avgIdleSeconds: toNumber4(item.avg_idle_seconds)
88418
89267
  })).slice(0, 5);
88419
89268
  }, [snapshot.data.summary.avg_idle_per_workstation?.top_contributors]);
88420
- const showIdleContributorLineNames = React147__default.useMemo(() => {
89269
+ const showIdleContributorLineNames = React148__default.useMemo(() => {
88421
89270
  return (scope.line_count ?? 0) > 1;
88422
89271
  }, [scope.line_count]);
88423
- const closeIdleContributors = React147__default.useCallback(() => {
89272
+ const closeIdleContributors = React148__default.useCallback(() => {
88424
89273
  setIsIdleContributorsOpen(false);
88425
89274
  setIsIdleContributorsPinned(false);
88426
89275
  }, []);
88427
- const handleIdleContributorsToggle = React147__default.useCallback(() => {
89276
+ const handleIdleContributorsToggle = React148__default.useCallback(() => {
88428
89277
  if (!canInspectIdleContributors) return;
88429
89278
  setIsIdleContributorsPinned((previous) => {
88430
89279
  const next = !previous;
@@ -88432,7 +89281,7 @@ var OverviewSummaryCards = React147__default.memo(({ store }) => {
88432
89281
  return next;
88433
89282
  });
88434
89283
  }, [canInspectIdleContributors]);
88435
- const handleIdleContributorsKeyDown = React147__default.useCallback((event) => {
89284
+ const handleIdleContributorsKeyDown = React148__default.useCallback((event) => {
88436
89285
  if (!canInspectIdleContributors) return;
88437
89286
  if (event.key === "Enter" || event.key === " ") {
88438
89287
  event.preventDefault();
@@ -88444,11 +89293,11 @@ var OverviewSummaryCards = React147__default.memo(({ store }) => {
88444
89293
  closeIdleContributors();
88445
89294
  }
88446
89295
  }, [canInspectIdleContributors, closeIdleContributors, handleIdleContributorsToggle]);
88447
- React147__default.useEffect(() => {
89296
+ React148__default.useEffect(() => {
88448
89297
  setIsIdleContributorsOpen(false);
88449
89298
  setIsIdleContributorsPinned(false);
88450
89299
  }, [scope.comparison_strategy, scope.current_range?.start_date, scope.current_range?.end_date, scope.line_count, scope.shift_mode]);
88451
- React147__default.useEffect(() => {
89300
+ React148__default.useEffect(() => {
88452
89301
  if (!isIdleContributorsOpen) return void 0;
88453
89302
  const handleClickOutside = (event) => {
88454
89303
  if (!isIdleContributorsPinned) return;
@@ -88586,7 +89435,7 @@ var OverviewSummaryCards = React147__default.memo(({ store }) => {
88586
89435
  ] });
88587
89436
  });
88588
89437
  OverviewSummaryCards.displayName = "OverviewSummaryCards";
88589
- var PoorestPerformersCard = React147__default.memo(({
89438
+ var PoorestPerformersCard = React148__default.memo(({
88590
89439
  store,
88591
89440
  supervisorsByLineId,
88592
89441
  onViewAll,
@@ -88595,9 +89444,9 @@ var PoorestPerformersCard = React147__default.memo(({
88595
89444
  bumpRenderCounter();
88596
89445
  const scope = useOperationsOverviewScope(store);
88597
89446
  const snapshot = useOperationsOverviewSnapshot(store);
88598
- const [poorestLineMode, setPoorestLineMode] = React147__default.useState("output");
89447
+ const [poorestLineMode, setPoorestLineMode] = React148__default.useState("output");
88599
89448
  const availableLineModes = scope.available_line_modes;
88600
- React147__default.useEffect(() => {
89449
+ React148__default.useEffect(() => {
88601
89450
  const hasOutput = !!availableLineModes?.has_output;
88602
89451
  const hasUptime = !!availableLineModes?.has_uptime;
88603
89452
  if (hasOutput && !hasUptime && poorestLineMode !== "output") {
@@ -88606,7 +89455,7 @@ var PoorestPerformersCard = React147__default.memo(({
88606
89455
  setPoorestLineMode("uptime");
88607
89456
  }
88608
89457
  }, [availableLineModes?.has_output, availableLineModes?.has_uptime, poorestLineMode]);
88609
- const comparisonLabel = React147__default.useMemo(() => {
89458
+ const comparisonLabel = React148__default.useMemo(() => {
88610
89459
  return formatComparisonWindow({
88611
89460
  currentDayCount: scope.current_range?.day_count ?? null,
88612
89461
  previousDayCount: scope.previous_range?.day_count ?? null,
@@ -88620,7 +89469,7 @@ var PoorestPerformersCard = React147__default.memo(({
88620
89469
  scope.shift_mode
88621
89470
  ]);
88622
89471
  const showSnapshotSkeleton = snapshot.loading && !snapshot.hasLoadedOnce;
88623
- const mergedPoorestLines = React147__default.useMemo(() => {
89472
+ const mergedPoorestLines = React148__default.useMemo(() => {
88624
89473
  const rows = snapshot.data.poorest_lines?.[poorestLineMode] || [];
88625
89474
  const lineRows = [];
88626
89475
  const areaGroups = /* @__PURE__ */ new Map();
@@ -88700,7 +89549,7 @@ var PoorestPerformersCard = React147__default.memo(({
88700
89549
  }, [poorestLineMode, snapshot.data.poorest_lines, supervisorsByLineId]);
88701
89550
  const showPoorestModeToggle = !!availableLineModes?.has_output && !!availableLineModes?.has_uptime;
88702
89551
  const poorestMetricLabel = poorestLineMode === "uptime" ? "Uptime" : "Efficiency";
88703
- const handlePoorestLineModeChange = React147__default.useCallback((mode) => {
89552
+ const handlePoorestLineModeChange = React148__default.useCallback((mode) => {
88704
89553
  trackCoreEvent("Operations Overview Poorest Line Mode Changed", { mode });
88705
89554
  setPoorestLineMode(mode);
88706
89555
  }, []);
@@ -88786,14 +89635,14 @@ var PoorestPerformersCard = React147__default.memo(({
88786
89635
  ] });
88787
89636
  });
88788
89637
  PoorestPerformersCard.displayName = "PoorestPerformersCard";
88789
- var IdleBreakdownCard = React147__default.memo(({
89638
+ var IdleBreakdownCard = React148__default.memo(({
88790
89639
  store,
88791
89640
  scopedLineCount
88792
89641
  }) => {
88793
89642
  bumpRenderCounter();
88794
89643
  const idle = useOperationsOverviewIdle(store);
88795
89644
  const showInitialSkeleton = idle.loading && idle.lastUpdated === null;
88796
- const idleBreakdown = React147__default.useMemo(() => {
89645
+ const idleBreakdown = React148__default.useMemo(() => {
88797
89646
  return idle.data.map((item) => ({
88798
89647
  name: item.display_name?.trim() || item.reason?.trim() || "Unknown",
88799
89648
  reasonKey: item.reason_key?.trim() || item.reason?.trim() || "unknown",
@@ -88812,7 +89661,7 @@ var IdleBreakdownCard = React147__default.memo(({
88812
89661
  }))
88813
89662
  })).filter((item) => item.value > 0);
88814
89663
  }, [idle.data]);
88815
- const showIdleModuleNotEnabledState = React147__default.useMemo(() => {
89664
+ const showIdleModuleNotEnabledState = React148__default.useMemo(() => {
88816
89665
  const enabledLineCount = idle.scope.idle_time_vlm_enabled_line_count;
88817
89666
  return !showInitialSkeleton && scopedLineCount > 0 && typeof enabledLineCount === "number" && enabledLineCount === 0;
88818
89667
  }, [idle.scope.idle_time_vlm_enabled_line_count, scopedLineCount, showInitialSkeleton]);
@@ -88833,7 +89682,7 @@ var IdleBreakdownCard = React147__default.memo(({
88833
89682
  ] });
88834
89683
  });
88835
89684
  IdleBreakdownCard.displayName = "IdleBreakdownCard";
88836
- var EfficiencyTrendCard = React147__default.memo(({
89685
+ var EfficiencyTrendCard = React148__default.memo(({
88837
89686
  store,
88838
89687
  dateRange,
88839
89688
  appTimezone,
@@ -88841,14 +89690,14 @@ var EfficiencyTrendCard = React147__default.memo(({
88841
89690
  }) => {
88842
89691
  bumpRenderCounter();
88843
89692
  const trend = useOperationsOverviewTrend(store);
88844
- const currentWeekRange = React147__default.useMemo(
89693
+ const currentWeekRange = React148__default.useMemo(
88845
89694
  () => getCurrentWeekToDateRange(appTimezone),
88846
89695
  [appTimezone]
88847
89696
  );
88848
89697
  const isCurrentWeekToDateRange = dateRange.startKey === currentWeekRange.startKey && dateRange.endKey === currentWeekRange.endKey;
88849
89698
  const showInitialSkeleton = trend.loading && trend.lastUpdated === null;
88850
89699
  const isHourlyTrend = trend.data.granularity === "hour";
88851
- const trendData = React147__default.useMemo(() => {
89700
+ const trendData = React148__default.useMemo(() => {
88852
89701
  if (isHourlyTrend) {
88853
89702
  return (trend.data.points || []).map((point, index) => ({
88854
89703
  name: (() => {
@@ -88920,13 +89769,13 @@ var EfficiencyTrendCard = React147__default.memo(({
88920
89769
  };
88921
89770
  });
88922
89771
  }, [currentWeekRange.startKey, hourlyLabelStartTime, isCurrentWeekToDateRange, isHourlyTrend, trend.data.points]);
88923
- const trendTooltipLabelFormatter = React147__default.useCallback((label, payload) => {
89772
+ const trendTooltipLabelFormatter = React148__default.useCallback((label, payload) => {
88924
89773
  if (isHourlyTrend) return label;
88925
89774
  const dayOfWeek = payload?.[0]?.payload?.dayOfWeek;
88926
89775
  if (!dayOfWeek || typeof label !== "string") return label;
88927
89776
  return `${label} (${dayOfWeek})`;
88928
89777
  }, [isHourlyTrend]);
88929
- const trendXAxisTickFormatter = React147__default.useCallback((value, index) => {
89778
+ const trendXAxisTickFormatter = React148__default.useCallback((value, index) => {
88930
89779
  if (!isHourlyTrend) {
88931
89780
  return typeof value === "string" ? value : String(value ?? "");
88932
89781
  }
@@ -88953,7 +89802,7 @@ var EfficiencyTrendCard = React147__default.memo(({
88953
89802
  ] });
88954
89803
  });
88955
89804
  EfficiencyTrendCard.displayName = "EfficiencyTrendCard";
88956
- var TopImprovementsCard = React147__default.memo(({
89805
+ var TopImprovementsCard = React148__default.memo(({
88957
89806
  store,
88958
89807
  supervisorsByLineId,
88959
89808
  onViewAll,
@@ -88962,7 +89811,7 @@ var TopImprovementsCard = React147__default.memo(({
88962
89811
  bumpRenderCounter();
88963
89812
  const improvements = useOperationsOverviewImprovements(store);
88964
89813
  const showInitialSkeleton = improvements.loading && improvements.lastUpdated === null;
88965
- const displayImprovements = React147__default.useMemo(() => {
89814
+ const displayImprovements = React148__default.useMemo(() => {
88966
89815
  return improvements.data.map((item) => {
88967
89816
  const supervisors = item.lineId ? supervisorsByLineId.get(item.lineId) || [] : [];
88968
89817
  return {
@@ -89090,33 +89939,33 @@ var useOperationsOverviewRefresh = ({
89090
89939
  isLiveScope,
89091
89940
  enabled = true
89092
89941
  }) => {
89093
- const lineIdsKey = React147__default.useMemo(() => lineIds.join(","), [lineIds]);
89094
- const scopeSignature = React147__default.useMemo(
89942
+ const lineIdsKey = React148__default.useMemo(() => lineIds.join(","), [lineIds]);
89943
+ const scopeSignature = React148__default.useMemo(
89095
89944
  () => [companyId || "", startKey, endKey, trendMode, comparisonStrategy || "", lineIdsKey].join("::"),
89096
89945
  [companyId, comparisonStrategy, endKey, lineIdsKey, startKey, trendMode]
89097
89946
  );
89098
- const controllersRef = React147__default.useRef({});
89099
- const requestIdsRef = React147__default.useRef({
89947
+ const controllersRef = React148__default.useRef({});
89948
+ const requestIdsRef = React148__default.useRef({
89100
89949
  snapshot: 0,
89101
89950
  trend: 0,
89102
89951
  idle: 0,
89103
89952
  improvements: 0
89104
89953
  });
89105
- const intervalRef = React147__default.useRef(null);
89106
- const isPageActiveRef = React147__default.useRef(true);
89107
- const lastResumeRefreshAtRef = React147__default.useRef(0);
89108
- const abortAll = React147__default.useCallback(() => {
89954
+ const intervalRef = React148__default.useRef(null);
89955
+ const isPageActiveRef = React148__default.useRef(true);
89956
+ const lastResumeRefreshAtRef = React148__default.useRef(0);
89957
+ const abortAll = React148__default.useCallback(() => {
89109
89958
  Object.values(controllersRef.current).forEach((controller) => {
89110
89959
  controller?.abort();
89111
89960
  });
89112
89961
  controllersRef.current = {};
89113
89962
  }, []);
89114
- React147__default.useEffect(() => {
89963
+ React148__default.useEffect(() => {
89115
89964
  return () => {
89116
89965
  abortAll();
89117
89966
  };
89118
89967
  }, [abortAll]);
89119
- const getIsPageActive = React147__default.useCallback(() => {
89968
+ const getIsPageActive = React148__default.useCallback(() => {
89120
89969
  if (typeof document === "undefined") {
89121
89970
  return true;
89122
89971
  }
@@ -89124,7 +89973,7 @@ var useOperationsOverviewRefresh = ({
89124
89973
  const hasFocus = typeof document.hasFocus === "function" ? document.hasFocus() : true;
89125
89974
  return isVisible && hasFocus;
89126
89975
  }, []);
89127
- const stopPolling = React147__default.useCallback((reason) => {
89976
+ const stopPolling = React148__default.useCallback((reason) => {
89128
89977
  if (intervalRef.current === null) {
89129
89978
  return;
89130
89979
  }
@@ -89132,7 +89981,7 @@ var useOperationsOverviewRefresh = ({
89132
89981
  intervalRef.current = null;
89133
89982
  debugRefreshLog("poll stopped", { reason });
89134
89983
  }, []);
89135
- const runRefresh = React147__default.useCallback(
89984
+ const runRefresh = React148__default.useCallback(
89136
89985
  async (section, begin, onSuccess, onError, request, reason) => {
89137
89986
  if (!enabled || !supabase || !companyId || lineIds.length === 0) return;
89138
89987
  const requestId = requestIdsRef.current[section] + 1;
@@ -89179,7 +90028,7 @@ var useOperationsOverviewRefresh = ({
89179
90028
  },
89180
90029
  [companyId, comparisonStrategy, enabled, endKey, lineIds, startKey, supabase, trendMode]
89181
90030
  );
89182
- const refreshSnapshot = React147__default.useCallback(
90031
+ const refreshSnapshot = React148__default.useCallback(
89183
90032
  async (reason) => {
89184
90033
  await runRefresh(
89185
90034
  "snapshot",
@@ -89211,7 +90060,7 @@ var useOperationsOverviewRefresh = ({
89211
90060
  },
89212
90061
  [companyId, comparisonStrategy, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
89213
90062
  );
89214
- const refreshTrend = React147__default.useCallback(
90063
+ const refreshTrend = React148__default.useCallback(
89215
90064
  async (reason) => {
89216
90065
  await runRefresh(
89217
90066
  "trend",
@@ -89240,7 +90089,7 @@ var useOperationsOverviewRefresh = ({
89240
90089
  },
89241
90090
  [companyId, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
89242
90091
  );
89243
- const refreshIdle = React147__default.useCallback(
90092
+ const refreshIdle = React148__default.useCallback(
89244
90093
  async (reason) => {
89245
90094
  await runRefresh(
89246
90095
  "idle",
@@ -89269,7 +90118,7 @@ var useOperationsOverviewRefresh = ({
89269
90118
  },
89270
90119
  [companyId, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
89271
90120
  );
89272
- const refreshImprovements = React147__default.useCallback(
90121
+ const refreshImprovements = React148__default.useCallback(
89273
90122
  async (reason) => {
89274
90123
  await runRefresh(
89275
90124
  "improvements",
@@ -89299,7 +90148,7 @@ var useOperationsOverviewRefresh = ({
89299
90148
  },
89300
90149
  [companyId, lineIds, lineIdsKey, runRefresh, scopeSignature, store, supabase]
89301
90150
  );
89302
- const refreshAll = React147__default.useCallback(
90151
+ const refreshAll = React148__default.useCallback(
89303
90152
  async (reason) => {
89304
90153
  await Promise.allSettled([
89305
90154
  refreshSnapshot(reason),
@@ -89310,7 +90159,7 @@ var useOperationsOverviewRefresh = ({
89310
90159
  },
89311
90160
  [refreshIdle, refreshImprovements, refreshSnapshot, refreshTrend]
89312
90161
  );
89313
- const startPolling = React147__default.useCallback((reason) => {
90162
+ const startPolling = React148__default.useCallback((reason) => {
89314
90163
  if (!isLiveScope || !supabase || !companyId || lineIds.length === 0) {
89315
90164
  return;
89316
90165
  }
@@ -89331,7 +90180,7 @@ var useOperationsOverviewRefresh = ({
89331
90180
  }, LIVE_REFRESH_INTERVAL_MS);
89332
90181
  debugRefreshLog("poll started", { reason, intervalMs: LIVE_REFRESH_INTERVAL_MS });
89333
90182
  }, [companyId, isLiveScope, lineIds.length, refreshAll, stopPolling, supabase]);
89334
- const refreshFromResume = React147__default.useCallback((reason) => {
90183
+ const refreshFromResume = React148__default.useCallback((reason) => {
89335
90184
  const now4 = Date.now();
89336
90185
  if (now4 - lastResumeRefreshAtRef.current < 1e3) {
89337
90186
  debugRefreshLog("resume refresh suppressed", { reason });
@@ -89346,7 +90195,7 @@ var useOperationsOverviewRefresh = ({
89346
90195
  }
89347
90196
  });
89348
90197
  }, [refreshAll, startPolling, stopPolling]);
89349
- React147__default.useEffect(() => {
90198
+ React148__default.useEffect(() => {
89350
90199
  if (!enabled) {
89351
90200
  stopPolling("disabled");
89352
90201
  abortAll();
@@ -89361,7 +90210,7 @@ var useOperationsOverviewRefresh = ({
89361
90210
  }
89362
90211
  void refreshAll("scope_change");
89363
90212
  }, [abortAll, companyId, enabled, lineIds.length, refreshAll, scopeSignature, stopPolling, store, supabase]);
89364
- React147__default.useEffect(() => {
90213
+ React148__default.useEffect(() => {
89365
90214
  if (!enabled || !isLiveScope || !supabase || !companyId || lineIds.length === 0) {
89366
90215
  isPageActiveRef.current = false;
89367
90216
  stopPolling("live_scope_disabled");
@@ -89574,55 +90423,55 @@ var PlantHeadView = () => {
89574
90423
  const { accessibleLineIds } = useUserLineAccess();
89575
90424
  const mobileMenuContext = useMobileMenu();
89576
90425
  useHideMobileHeader(!!mobileMenuContext);
89577
- const storeRef = React147__default.useRef(createOperationsOverviewStore());
90426
+ const storeRef = React148__default.useRef(createOperationsOverviewStore());
89578
90427
  const store = storeRef.current;
89579
- const fallbackOperationalDate = React147__default.useMemo(
90428
+ const fallbackOperationalDate = React148__default.useMemo(
89580
90429
  () => getOperationalDate(appTimezone),
89581
90430
  [appTimezone]
89582
90431
  );
89583
- const [dateRange, setDateRange] = React147__default.useState(() => ({
90432
+ const [dateRange, setDateRange] = React148__default.useState(() => ({
89584
90433
  startKey: fallbackOperationalDate,
89585
90434
  endKey: fallbackOperationalDate
89586
90435
  }));
89587
- const [usesThisWeekComparison, setUsesThisWeekComparison] = React147__default.useState(false);
89588
- const [trendMode, setTrendMode] = React147__default.useState("all");
89589
- const [selectedSupervisorId, setSelectedSupervisorId] = React147__default.useState("all");
89590
- const [selectedLineIds, setSelectedLineIds] = React147__default.useState([]);
89591
- const [isInitialScopeReady, setIsInitialScopeReady] = React147__default.useState(false);
89592
- const [shiftResolutionTick, setShiftResolutionTick] = React147__default.useState(0);
89593
- const hasAutoInitializedScopeRef = React147__default.useRef(false);
89594
- const hasUserAdjustedScopeRef = React147__default.useRef(false);
89595
- React147__default.useEffect(() => {
90436
+ const [usesThisWeekComparison, setUsesThisWeekComparison] = React148__default.useState(false);
90437
+ const [trendMode, setTrendMode] = React148__default.useState("all");
90438
+ const [selectedSupervisorId, setSelectedSupervisorId] = React148__default.useState("all");
90439
+ const [selectedLineIds, setSelectedLineIds] = React148__default.useState([]);
90440
+ const [isInitialScopeReady, setIsInitialScopeReady] = React148__default.useState(false);
90441
+ const [shiftResolutionTick, setShiftResolutionTick] = React148__default.useState(0);
90442
+ const hasAutoInitializedScopeRef = React148__default.useRef(false);
90443
+ const hasUserAdjustedScopeRef = React148__default.useRef(false);
90444
+ React148__default.useEffect(() => {
89596
90445
  trackCorePageView("Operations Overview", {
89597
90446
  dashboard_surface: "operations_overview"
89598
90447
  });
89599
90448
  }, []);
89600
- const currentWeekRange = React147__default.useMemo(
90449
+ const currentWeekRange = React148__default.useMemo(
89601
90450
  () => getCurrentWeekToDateRange(appTimezone),
89602
90451
  [appTimezone]
89603
90452
  );
89604
- const currentWeekDisplayRange = React147__default.useMemo(
90453
+ const currentWeekDisplayRange = React148__default.useMemo(
89605
90454
  () => getCurrentWeekFullRange(appTimezone),
89606
90455
  [appTimezone]
89607
90456
  );
89608
90457
  const isCurrentWeekToDateRange = dateRange.startKey === currentWeekRange.startKey && dateRange.endKey === currentWeekRange.endKey;
89609
- const headerDateRange = React147__default.useMemo(() => {
90458
+ const headerDateRange = React148__default.useMemo(() => {
89610
90459
  if (usesThisWeekComparison && isCurrentWeekToDateRange) {
89611
90460
  return currentWeekDisplayRange;
89612
90461
  }
89613
90462
  return dateRange;
89614
90463
  }, [currentWeekDisplayRange, dateRange, isCurrentWeekToDateRange, usesThisWeekComparison]);
89615
- const normalizedLineIds = React147__default.useMemo(
90464
+ const normalizedLineIds = React148__default.useMemo(
89616
90465
  () => Array.from(new Set(
89617
90466
  (accessibleLineIds || []).filter(Boolean).filter((lineId) => lineId !== factoryViewId)
89618
90467
  )).sort(),
89619
90468
  [accessibleLineIds, factoryViewId]
89620
90469
  );
89621
- const lineIdsKey = React147__default.useMemo(
90470
+ const lineIdsKey = React148__default.useMemo(
89622
90471
  () => normalizedLineIds.join(","),
89623
90472
  [normalizedLineIds]
89624
90473
  );
89625
- const lineOptions = React147__default.useMemo(
90474
+ const lineOptions = React148__default.useMemo(
89626
90475
  () => normalizedLineIds.map((lineId) => ({
89627
90476
  id: lineId,
89628
90477
  name: getLineDisplayName(entityConfig, lineId)
@@ -89634,7 +90483,7 @@ var PlantHeadView = () => {
89634
90483
  companyId: entityConfig.companyId,
89635
90484
  useBackend: true
89636
90485
  });
89637
- const supervisorOptions = React147__default.useMemo(
90486
+ const supervisorOptions = React148__default.useMemo(
89638
90487
  () => {
89639
90488
  const optionsById = /* @__PURE__ */ new Map();
89640
90489
  normalizedLineIds.forEach((lineId) => {
@@ -89660,7 +90509,7 @@ var PlantHeadView = () => {
89660
90509
  },
89661
90510
  [normalizedLineIds, supervisorsByLineId]
89662
90511
  );
89663
- React147__default.useEffect(() => {
90512
+ React148__default.useEffect(() => {
89664
90513
  if (selectedSupervisorId === "all") {
89665
90514
  setSelectedLineIds((previous) => {
89666
90515
  if (normalizedLineIds.length === 0) {
@@ -89686,7 +90535,7 @@ var PlantHeadView = () => {
89686
90535
  const scopedSupervisorLineIds = normalizedLineIds.filter((lineId) => supervisorLineIdSet.has(lineId));
89687
90536
  setSelectedLineIds((previous) => previous.length === scopedSupervisorLineIds.length && previous.every((lineId, index) => lineId === scopedSupervisorLineIds[index]) ? previous : scopedSupervisorLineIds);
89688
90537
  }, [lineIdsKey, normalizedLineIds, selectedSupervisorId, supervisorOptions]);
89689
- const scopedLineIds = React147__default.useMemo(
90538
+ const scopedLineIds = React148__default.useMemo(
89690
90539
  () => selectedLineIds.length > 0 ? selectedLineIds : normalizedLineIds,
89691
90540
  [normalizedLineIds, selectedLineIds]
89692
90541
  );
@@ -89694,7 +90543,7 @@ var PlantHeadView = () => {
89694
90543
  shiftConfigMap,
89695
90544
  isLoading: isShiftConfigLoading
89696
90545
  } = useMultiLineShiftConfigs(scopedLineIds, staticShiftConfig);
89697
- const shiftFilterOptions = React147__default.useMemo(() => {
90546
+ const shiftFilterOptions = React148__default.useMemo(() => {
89698
90547
  const optionsById = /* @__PURE__ */ new Map();
89699
90548
  scopedLineIds.forEach((lineId) => {
89700
90549
  const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
@@ -89733,7 +90582,7 @@ var PlantHeadView = () => {
89733
90582
  ...dynamicOptions
89734
90583
  ];
89735
90584
  }, [appTimezone, scopedLineIds, shiftConfigMap, staticShiftConfig]);
89736
- React147__default.useEffect(() => {
90585
+ React148__default.useEffect(() => {
89737
90586
  if (scopedLineIds.length === 0 || isShiftConfigLoading) {
89738
90587
  return;
89739
90588
  }
@@ -89744,11 +90593,11 @@ var PlantHeadView = () => {
89744
90593
  clearInterval(intervalId);
89745
90594
  };
89746
90595
  }, [isShiftConfigLoading, scopedLineIds.length]);
89747
- const shiftResolutionNow = React147__default.useMemo(
90596
+ const shiftResolutionNow = React148__default.useMemo(
89748
90597
  () => /* @__PURE__ */ new Date(),
89749
90598
  [shiftResolutionTick]
89750
90599
  );
89751
- const earliestDayShiftStartTime = React147__default.useMemo(() => {
90600
+ const earliestDayShiftStartTime = React148__default.useMemo(() => {
89752
90601
  const candidateStarts = [];
89753
90602
  scopedLineIds.forEach((lineId) => {
89754
90603
  const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
@@ -89784,11 +90633,11 @@ var PlantHeadView = () => {
89784
90633
  const minutes = earliestMinutes % 60;
89785
90634
  return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
89786
90635
  }, [appTimezone, scopedLineIds, shiftConfigMap, staticShiftConfig]);
89787
- const resolvedOperationalToday = React147__default.useMemo(
90636
+ const resolvedOperationalToday = React148__default.useMemo(
89788
90637
  () => getOperationalDate(appTimezone, shiftResolutionNow, earliestDayShiftStartTime),
89789
90638
  [appTimezone, earliestDayShiftStartTime, shiftResolutionNow]
89790
90639
  );
89791
- const activeLineShiftStates = React147__default.useMemo(() => {
90640
+ const activeLineShiftStates = React148__default.useMemo(() => {
89792
90641
  return scopedLineIds.flatMap((lineId) => {
89793
90642
  const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
89794
90643
  const activeShift = getActiveShift(appTimezone, shiftConfig, shiftResolutionNow);
@@ -89818,7 +90667,7 @@ var PlantHeadView = () => {
89818
90667
  });
89819
90668
  }, [appTimezone, scopedLineIds, shiftConfigMap, shiftResolutionNow, staticShiftConfig]);
89820
90669
  const resolvedTrendMode = isInitialScopeReady ? trendMode : "all";
89821
- const hourlyWindowStartTime = React147__default.useMemo(() => {
90670
+ const hourlyWindowStartTime = React148__default.useMemo(() => {
89822
90671
  if (scopedLineIds.length === 0) {
89823
90672
  return null;
89824
90673
  }
@@ -89875,12 +90724,12 @@ var PlantHeadView = () => {
89875
90724
  const minutes = earliestMinutes % 60;
89876
90725
  return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
89877
90726
  }, [appTimezone, resolvedTrendMode, scopedLineIds, shiftConfigMap, staticShiftConfig]);
89878
- const isShiftScopeResolved = React147__default.useMemo(
90727
+ const isShiftScopeResolved = React148__default.useMemo(
89879
90728
  () => !isShiftConfigLoading,
89880
90729
  [isShiftConfigLoading]
89881
90730
  );
89882
- const initializedTimezoneRef = React147__default.useRef(appTimezone);
89883
- React147__default.useEffect(() => {
90731
+ const initializedTimezoneRef = React148__default.useRef(appTimezone);
90732
+ React148__default.useEffect(() => {
89884
90733
  if (initializedTimezoneRef.current === appTimezone) return;
89885
90734
  hasAutoInitializedScopeRef.current = false;
89886
90735
  hasUserAdjustedScopeRef.current = false;
@@ -89893,7 +90742,7 @@ var PlantHeadView = () => {
89893
90742
  setIsInitialScopeReady(false);
89894
90743
  initializedTimezoneRef.current = appTimezone;
89895
90744
  }, [appTimezone, fallbackOperationalDate]);
89896
- React147__default.useEffect(() => {
90745
+ React148__default.useEffect(() => {
89897
90746
  if (hasAutoInitializedScopeRef.current || hasUserAdjustedScopeRef.current) {
89898
90747
  return;
89899
90748
  }
@@ -89918,7 +90767,7 @@ var PlantHeadView = () => {
89918
90767
  hasAutoInitializedScopeRef.current = true;
89919
90768
  setIsInitialScopeReady(true);
89920
90769
  }, [fallbackOperationalDate, isShiftScopeResolved, resolvedOperationalToday, scopedLineIds.length]);
89921
- const handleDateRangeChange = React147__default.useCallback((range, meta) => {
90770
+ const handleDateRangeChange = React148__default.useCallback((range, meta) => {
89922
90771
  hasUserAdjustedScopeRef.current = true;
89923
90772
  setIsInitialScopeReady(true);
89924
90773
  trackCoreEvent("Operations Overview Date Range Changed", {
@@ -89936,12 +90785,12 @@ var PlantHeadView = () => {
89936
90785
  return previous;
89937
90786
  });
89938
90787
  }, []);
89939
- const handleTrendModeChange = React147__default.useCallback((mode) => {
90788
+ const handleTrendModeChange = React148__default.useCallback((mode) => {
89940
90789
  hasUserAdjustedScopeRef.current = true;
89941
90790
  setIsInitialScopeReady(true);
89942
90791
  setTrendMode(mode);
89943
90792
  }, []);
89944
- const handleSelectedLineIdsChange = React147__default.useCallback((lineIds) => {
90793
+ const handleSelectedLineIdsChange = React148__default.useCallback((lineIds) => {
89945
90794
  setSelectedSupervisorId("all");
89946
90795
  if (normalizedLineIds.length === 0) {
89947
90796
  setSelectedLineIds([]);
@@ -89952,10 +90801,10 @@ var PlantHeadView = () => {
89952
90801
  const next = normalizedLineIds.filter((lineId) => selectedSet.has(lineId));
89953
90802
  setSelectedLineIds(next.length > 0 ? next : normalizedLineIds);
89954
90803
  }, [normalizedLineIds]);
89955
- const handleSelectedSupervisorIdChange = React147__default.useCallback((supervisorId) => {
90804
+ const handleSelectedSupervisorIdChange = React148__default.useCallback((supervisorId) => {
89956
90805
  setSelectedSupervisorId(supervisorId);
89957
90806
  }, []);
89958
- const buildLineMonthlyHistoryUrl = React147__default.useCallback((lineId) => {
90807
+ const buildLineMonthlyHistoryUrl = React148__default.useCallback((lineId) => {
89959
90808
  const rangeStartDate = parseDateKeyToDate(dateRange.startKey);
89960
90809
  const params = new URLSearchParams();
89961
90810
  params.set("tab", "monthly_history");
@@ -89965,15 +90814,15 @@ var PlantHeadView = () => {
89965
90814
  params.set("rangeEnd", dateRange.endKey);
89966
90815
  return `/kpis/${lineId}?${params.toString()}`;
89967
90816
  }, [dateRange.endKey, dateRange.startKey]);
89968
- const handleViewAllPoorestPerformers = React147__default.useCallback(() => {
90817
+ const handleViewAllPoorestPerformers = React148__default.useCallback(() => {
89969
90818
  trackCoreEvent("Operations Overview View All Clicked", { section: "poorest_performers" });
89970
90819
  navigate("/kpis?tab=leaderboard");
89971
90820
  }, [navigate]);
89972
- const handleViewAllImprovements = React147__default.useCallback(() => {
90821
+ const handleViewAllImprovements = React148__default.useCallback(() => {
89973
90822
  trackCoreEvent("Operations Overview View All Clicked", { section: "improvements" });
89974
90823
  navigate("/improvement-center");
89975
90824
  }, [navigate]);
89976
- const handleOpenImprovement = React147__default.useCallback((item) => {
90825
+ const handleOpenImprovement = React148__default.useCallback((item) => {
89977
90826
  trackCoreEvent("Operations Overview Improvement Clicked", {
89978
90827
  issue_id: item.issueId,
89979
90828
  issue_number: item.issueNumber,
@@ -89984,13 +90833,13 @@ var PlantHeadView = () => {
89984
90833
  });
89985
90834
  navigate(`/improvement-center?${params.toString()}`);
89986
90835
  }, [navigate]);
89987
- const comparisonStrategy = React147__default.useMemo(() => {
90836
+ const comparisonStrategy = React148__default.useMemo(() => {
89988
90837
  if (usesThisWeekComparison && isCurrentWeekToDateRange) {
89989
90838
  return "previous_full_week";
89990
90839
  }
89991
90840
  return void 0;
89992
90841
  }, [isCurrentWeekToDateRange, usesThisWeekComparison]);
89993
- const effectiveDateRange = React147__default.useMemo(() => {
90842
+ const effectiveDateRange = React148__default.useMemo(() => {
89994
90843
  if (isInitialScopeReady) {
89995
90844
  return dateRange;
89996
90845
  }
@@ -90000,11 +90849,11 @@ var PlantHeadView = () => {
90000
90849
  endKey: nextStartKey
90001
90850
  };
90002
90851
  }, [dateRange, fallbackOperationalDate, isInitialScopeReady, resolvedOperationalToday]);
90003
- const effectiveTrendMode = React147__default.useMemo(
90852
+ const effectiveTrendMode = React148__default.useMemo(
90004
90853
  () => resolvedTrendMode,
90005
90854
  [resolvedTrendMode]
90006
90855
  );
90007
- const hasActiveSelectedShiftLine = React147__default.useMemo(
90856
+ const hasActiveSelectedShiftLine = React148__default.useMemo(
90008
90857
  () => activeLineShiftStates.some((shift) => {
90009
90858
  if (shift.date !== resolvedOperationalToday) return false;
90010
90859
  if (effectiveTrendMode === "all") return true;
@@ -90016,7 +90865,7 @@ var PlantHeadView = () => {
90016
90865
  }),
90017
90866
  [activeLineShiftStates, effectiveTrendMode, resolvedOperationalToday]
90018
90867
  );
90019
- const activeLiveShiftName = React147__default.useMemo(
90868
+ const activeLiveShiftName = React148__default.useMemo(
90020
90869
  () => {
90021
90870
  if (effectiveTrendMode === "all") return null;
90022
90871
  const matchingShift = activeLineShiftStates.find((shift) => {
@@ -90031,17 +90880,17 @@ var PlantHeadView = () => {
90031
90880
  },
90032
90881
  [activeLineShiftStates, effectiveTrendMode, resolvedOperationalToday]
90033
90882
  );
90034
- const hourlyLabelStartTime = React147__default.useMemo(() => {
90883
+ const hourlyLabelStartTime = React148__default.useMemo(() => {
90035
90884
  if (scopedLineIds.length === 0) {
90036
90885
  return null;
90037
90886
  }
90038
90887
  return hourlyWindowStartTime;
90039
90888
  }, [hourlyWindowStartTime, scopedLineIds.length]);
90040
- const isSingleDayScope = React147__default.useMemo(
90889
+ const isSingleDayScope = React148__default.useMemo(
90041
90890
  () => effectiveDateRange.startKey === effectiveDateRange.endKey,
90042
90891
  [effectiveDateRange.endKey, effectiveDateRange.startKey]
90043
90892
  );
90044
- const isLiveScope = React147__default.useMemo(
90893
+ const isLiveScope = React148__default.useMemo(
90045
90894
  () => isSingleDayScope && effectiveDateRange.startKey === resolvedOperationalToday && hasActiveSelectedShiftLine,
90046
90895
  [
90047
90896
  effectiveDateRange.startKey,
@@ -90051,7 +90900,7 @@ var PlantHeadView = () => {
90051
90900
  resolvedOperationalToday
90052
90901
  ]
90053
90902
  );
90054
- const handleOpenLineDetails = React147__default.useCallback((line) => {
90903
+ const handleOpenLineDetails = React148__default.useCallback((line) => {
90055
90904
  trackCoreEvent("Operations Overview Line Clicked", {
90056
90905
  line_id: line.rowType === "line" ? line.id : null,
90057
90906
  line_name: line.name,