@optifye/dashboard-core 6.12.48 → 6.12.49

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 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';
3
+ import * as React125 from 'react';
4
+ import React125__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';
@@ -10,11 +10,11 @@ import { EventEmitter } from 'events';
10
10
  import { createClient, REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js';
11
11
  import Hls, { Events, ErrorTypes } from 'hls.js';
12
12
  import useSWR from 'swr';
13
- import { Camera, AlertTriangle, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, RefreshCw, Filter, X, Coffee, Plus, ArrowUp, ArrowDown, ArrowRight, HelpCircle, ClipboardX, Activity, Wrench, UserX, Clock, Package, Monitor, CheckCircle2, ArrowLeft, Calendar, Save, AlertCircle, Loader2, Minus, ChevronLeft, ChevronRight, TrendingUp, Sparkles, Pause, Play, XCircle, Palette, LockKeyhole, TrendingDown, FolderOpen, Folder, ArrowDownWideNarrow, Tag, Sliders, Layers, Search, Edit2, CheckCircle, User, Users, Shield, Building2, Mail, Lock, Info, Share2, Trophy, Target, Download, Video, Copy, Sun, Moon, MousePointer, UserPlus, UserCog, Trash2, Eye, MoreVertical, BarChart3, Pencil, UserCheck, LogOut, Film, MessageSquare, Menu, Send, Settings, LifeBuoy, EyeOff, Zap, ExternalLink, Flame, Crown, Medal } from 'lucide-react';
13
+ import { Camera, AlertTriangle, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, RefreshCw, ArrowUpDown, X, Coffee, Plus, Filter, ArrowUp, ArrowDown, ArrowRight, HelpCircle, ClipboardX, Activity, Wrench, UserX, Clock, Package, Monitor, CheckCircle2, ArrowLeft, Calendar, Save, AlertCircle, Loader2, Minus, ChevronLeft, ChevronRight, TrendingUp, Sparkles, Pause, Play, XCircle, Palette, LockKeyhole, TrendingDown, FolderOpen, Folder, ArrowDownWideNarrow, Tag, Sliders, Layers, Search, Edit2, CheckCircle, User, Users, Shield, Building2, Mail, Lock, Info, Share2, Trophy, Target, Download, Video, Copy, Sun, Moon, MousePointer, UserPlus, UserCog, Trash2, Eye, MoreVertical, BarChart3, Pencil, UserCheck, LogOut, Film, MessageSquare, Menu, Send, Settings, LifeBuoy, EyeOff, Zap, ExternalLink, Flame, Crown, Medal } from 'lucide-react';
14
14
  import { memo, noop, warning, invariant, progress, secondsToMilliseconds, millisecondsToSeconds } from 'motion-utils';
15
15
  import { BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, ReferenceLine, Tooltip, Legend, Bar, LabelList, ResponsiveContainer, LineChart as LineChart$1, Line, Customized, Cell, PieChart, Pie, ComposedChart, Area, ScatterChart, Scatter } from 'recharts';
16
16
  import { Slot } from '@radix-ui/react-slot';
17
- import { AdjustmentsHorizontalIcon, ClipboardDocumentCheckIcon, ClockIcon, UsersIcon, UserCircleIcon, TicketIcon, CurrencyDollarIcon, QuestionMarkCircleIcon, XMarkIcon, ArrowRightIcon, SparklesIcon, PlayCircleIcon, Bars3Icon, HomeIcon, VideoCameraIcon, TrophyIcon, ChartBarIcon, LightBulbIcon, CubeIcon, HeartIcon, Cog6ToothIcon, ChevronRightIcon, ArrowRightStartOnRectangleIcon, ExclamationCircleIcon, ExclamationTriangleIcon, CalendarIcon, ChevronDownIcon, ChevronLeftIcon, EnvelopeIcon, DocumentTextIcon, ChevronUpIcon, ArrowDownTrayIcon, CheckCircleIcon, ChatBubbleLeftRightIcon, XCircleIcon, FunnelIcon, EyeIcon, InformationCircleIcon, ArrowLeftIcon } from '@heroicons/react/24/outline';
17
+ import { LightBulbIcon, AdjustmentsHorizontalIcon, ClipboardDocumentCheckIcon, ClockIcon, UsersIcon, UserCircleIcon, TicketIcon, CurrencyDollarIcon, QuestionMarkCircleIcon, XMarkIcon, ArrowRightIcon, SparklesIcon, PlayCircleIcon, Bars3Icon, HomeIcon, VideoCameraIcon, TrophyIcon, ChartBarIcon, CubeIcon, HeartIcon, Cog6ToothIcon, ChevronRightIcon, ArrowRightStartOnRectangleIcon, ExclamationCircleIcon, ExclamationTriangleIcon, CalendarIcon, ChevronDownIcon, ChevronLeftIcon, EnvelopeIcon, DocumentTextIcon, ChevronUpIcon, ArrowDownTrayIcon, CheckCircleIcon, ChatBubbleLeftRightIcon, XCircleIcon, FunnelIcon, EyeIcon, InformationCircleIcon, ArrowLeftIcon } from '@heroicons/react/24/outline';
18
18
  import * as SelectPrimitive from '@radix-ui/react-select';
19
19
  import { DayPicker, useNavigation as useNavigation$1 } from 'react-day-picker';
20
20
  import { CheckIcon } from '@heroicons/react/24/solid';
@@ -2091,14 +2091,14 @@ var useIdleTimeVlmConfig = () => {
2091
2091
  }
2092
2092
  return context;
2093
2093
  };
2094
- var DashboardConfigContext = React148.createContext(void 0);
2094
+ var DashboardConfigContext = React125.createContext(void 0);
2095
2095
  var DashboardProvider = ({ config: userProvidedConfig, children }) => {
2096
- const fullConfig = React148.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
2096
+ const fullConfig = React125.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
2097
2097
  _setDashboardConfigInstance(fullConfig);
2098
- React148.useEffect(() => {
2098
+ React125.useEffect(() => {
2099
2099
  _setDashboardConfigInstance(fullConfig);
2100
2100
  }, [fullConfig]);
2101
- React148.useEffect(() => {
2101
+ React125.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 = React148.useContext(DashboardConfigContext);
2127
+ const ctx = React125.useContext(DashboardConfigContext);
2128
2128
  if (!ctx) throw new Error("useDashboardConfig must be used within a DashboardProvider");
2129
2129
  return ctx;
2130
2130
  };
@@ -12830,7 +12830,7 @@ var useMobileMenu = () => {
12830
12830
  };
12831
12831
  var useHideMobileHeader = (shouldHide = true) => {
12832
12832
  const context = useMobileMenu();
12833
- React148__default.useEffect(() => {
12833
+ React125__default.useEffect(() => {
12834
12834
  if (context && shouldHide) {
12835
12835
  context.setHideMobileHeader(true);
12836
12836
  return () => {
@@ -25914,7 +25914,7 @@ var MotionConfigContext = createContext({
25914
25914
  });
25915
25915
 
25916
25916
  // ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PopChild.mjs
25917
- var PopChildMeasure = class extends React148.Component {
25917
+ var PopChildMeasure = class extends React125.Component {
25918
25918
  getSnapshotBeforeUpdate(prevProps) {
25919
25919
  const element = this.props.childRef.current;
25920
25920
  if (element && prevProps.isPresent && !this.props.isPresent) {
@@ -25969,7 +25969,7 @@ function PopChild({ children, isPresent }) {
25969
25969
  document.head.removeChild(style);
25970
25970
  };
25971
25971
  }, [isPresent]);
25972
- return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React148.cloneElement(children, { ref }) });
25972
+ return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React125.cloneElement(children, { ref }) });
25973
25973
  }
25974
25974
 
25975
25975
  // ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PresenceChild.mjs
@@ -26006,7 +26006,7 @@ var PresenceChild = ({ children, initial, isPresent, onExitComplete, custom, pre
26006
26006
  useMemo(() => {
26007
26007
  presenceChildren.forEach((_, key) => presenceChildren.set(key, false));
26008
26008
  }, [isPresent]);
26009
- React148.useEffect(() => {
26009
+ React125.useEffect(() => {
26010
26010
  !isPresent && !presenceChildren.size && onExitComplete && onExitComplete();
26011
26011
  }, [isPresent]);
26012
26012
  if (mode === "popLayout") {
@@ -33791,7 +33791,7 @@ var withAuth = (WrappedComponent2, options) => {
33791
33791
  requireAuth: true,
33792
33792
  ...options
33793
33793
  };
33794
- const WithAuthComponent = React148.memo(function WithAuthComponent2(props) {
33794
+ const WithAuthComponent = React125.memo(function WithAuthComponent2(props) {
33795
33795
  const {
33796
33796
  session,
33797
33797
  user,
@@ -33802,9 +33802,9 @@ var withAuth = (WrappedComponent2, options) => {
33802
33802
  retrySessionHydration
33803
33803
  } = useAuth();
33804
33804
  const router = useRouter();
33805
- const [localLoading, setLocalLoading] = React148.useState(loading);
33806
- const [loadingTimeoutReached, setLoadingTimeoutReached] = React148.useState(false);
33807
- React148.useEffect(() => {
33805
+ const [localLoading, setLocalLoading] = React125.useState(loading);
33806
+ const [loadingTimeoutReached, setLoadingTimeoutReached] = React125.useState(false);
33807
+ React125.useEffect(() => {
33808
33808
  if (process.env.NODE_ENV === "development" && process.env.DEBUG_AUTH === "true") {
33809
33809
  console.log("withAuth state:", {
33810
33810
  loading,
@@ -33816,7 +33816,7 @@ var withAuth = (WrappedComponent2, options) => {
33816
33816
  });
33817
33817
  }
33818
33818
  }, [authStatus, error, loading, session, user]);
33819
- const handleLoadingTimeout = React148.useCallback(() => {
33819
+ const handleLoadingTimeout = React125.useCallback(() => {
33820
33820
  console.warn("[withAuth] Loading timeout reached");
33821
33821
  setLoadingTimeoutReached(true);
33822
33822
  if (hasStoredSupabaseSession()) {
@@ -33828,13 +33828,13 @@ var withAuth = (WrappedComponent2, options) => {
33828
33828
  router.replace(defaultOptions.redirectTo);
33829
33829
  }
33830
33830
  }, [retrySessionHydration, router]);
33831
- React148.useEffect(() => {
33831
+ React125.useEffect(() => {
33832
33832
  if (!loading && authStatus !== "recovering" && defaultOptions.requireAuth && !session && !error) {
33833
33833
  console.log("[withAuth] No session found, redirecting to login");
33834
33834
  router.replace(defaultOptions.redirectTo);
33835
33835
  }
33836
33836
  }, [authStatus, defaultOptions.requireAuth, error, loading, router, session]);
33837
- React148.useEffect(() => {
33837
+ React125.useEffect(() => {
33838
33838
  setLocalLoading(loading);
33839
33839
  }, [loading]);
33840
33840
  if (loading || localLoading) {
@@ -34833,11 +34833,11 @@ var BarChartComponent = ({
34833
34833
  aspect = 2,
34834
34834
  ...restOfChartProps
34835
34835
  }) => {
34836
- const containerRef = React148__default.useRef(null);
34837
- const [containerReady, setContainerReady] = React148__default.useState(false);
34836
+ const containerRef = React125__default.useRef(null);
34837
+ const [containerReady, setContainerReady] = React125__default.useState(false);
34838
34838
  const themeConfig = useThemeConfig();
34839
34839
  const { formatNumber } = useFormatNumber();
34840
- React148__default.useEffect(() => {
34840
+ React125__default.useEffect(() => {
34841
34841
  const checkContainerDimensions = () => {
34842
34842
  if (containerRef.current) {
34843
34843
  const rect = containerRef.current.getBoundingClientRect();
@@ -34951,7 +34951,7 @@ var BarChartComponent = ({
34951
34951
  }
34952
34952
  return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: chartContent });
34953
34953
  };
34954
- var BarChart = React148__default.memo(BarChartComponent, (prevProps, nextProps) => {
34954
+ var BarChart = React125__default.memo(BarChartComponent, (prevProps, nextProps) => {
34955
34955
  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) {
34956
34956
  return false;
34957
34957
  }
@@ -35002,10 +35002,10 @@ var LineChartComponent = ({
35002
35002
  fillContainer = false,
35003
35003
  ...restOfChartProps
35004
35004
  }) => {
35005
- const containerRef = React148__default.useRef(null);
35006
- const [dimensions, setDimensions] = React148__default.useState({ width: 0, height: 0 });
35007
- const [hasValidData, setHasValidData] = React148__default.useState(false);
35008
- React148__default.useEffect(() => {
35005
+ const containerRef = React125__default.useRef(null);
35006
+ const [dimensions, setDimensions] = React125__default.useState({ width: 0, height: 0 });
35007
+ const [hasValidData, setHasValidData] = React125__default.useState(false);
35008
+ React125__default.useEffect(() => {
35009
35009
  const currentHasValidData = data && lines && lines.length > 0 && data.some(
35010
35010
  (item) => lines.some((line) => {
35011
35011
  const val = item[line.dataKey];
@@ -35016,7 +35016,7 @@ var LineChartComponent = ({
35016
35016
  setHasValidData(true);
35017
35017
  }
35018
35018
  }, [data, lines, hasValidData]);
35019
- React148__default.useEffect(() => {
35019
+ React125__default.useEffect(() => {
35020
35020
  if (!containerRef.current) return;
35021
35021
  const observer = new ResizeObserver((entries) => {
35022
35022
  const entry = entries[0];
@@ -35141,7 +35141,7 @@ var LineChartComponent = ({
35141
35141
  }
35142
35142
  return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: renderChartContent(restOfChartProps.width, restOfChartProps.height) });
35143
35143
  };
35144
- var LineChart = React148__default.memo(LineChartComponent, (prevProps, nextProps) => {
35144
+ var LineChart = React125__default.memo(LineChartComponent, (prevProps, nextProps) => {
35145
35145
  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)) {
35146
35146
  return false;
35147
35147
  }
@@ -35308,7 +35308,7 @@ var SkuRow = ({ sku, isSelected, isLive, onSelect }) => {
35308
35308
  );
35309
35309
  };
35310
35310
  var PerSkuView = ({ rows, className = "", selectedSkuId, liveSkuId, onSelectSku }) => {
35311
- const ordered = React148__default.useMemo(
35311
+ const ordered = React125__default.useMemo(
35312
35312
  () => [...rows].sort((a, b) => {
35313
35313
  const am = (b.active_minutes ?? 0) - (a.active_minutes ?? 0);
35314
35314
  if (am !== 0) return am;
@@ -35316,9 +35316,9 @@ var PerSkuView = ({ rows, className = "", selectedSkuId, liveSkuId, onSelectSku
35316
35316
  }),
35317
35317
  [rows]
35318
35318
  );
35319
- const scrollContainerRef = React148__default.useRef(null);
35320
- const [showScrollIndicatorBottom, setShowScrollIndicatorBottom] = React148__default.useState(ordered.length > 4);
35321
- const [showScrollIndicatorTop, setShowScrollIndicatorTop] = React148__default.useState(false);
35319
+ const scrollContainerRef = React125__default.useRef(null);
35320
+ const [showScrollIndicatorBottom, setShowScrollIndicatorBottom] = React125__default.useState(ordered.length > 4);
35321
+ const [showScrollIndicatorTop, setShowScrollIndicatorTop] = React125__default.useState(false);
35322
35322
  const handleScroll = (e) => {
35323
35323
  const target = e.currentTarget;
35324
35324
  if (target.scrollHeight - target.scrollTop <= target.clientHeight + 10) {
@@ -35342,7 +35342,7 @@ var PerSkuView = ({ rows, className = "", selectedSkuId, liveSkuId, onSelectSku
35342
35342
  scrollContainerRef.current.scrollBy({ top: -80, behavior: "smooth" });
35343
35343
  }
35344
35344
  };
35345
- React148__default.useEffect(() => {
35345
+ React125__default.useEffect(() => {
35346
35346
  if (scrollContainerRef.current) {
35347
35347
  const target = scrollContainerRef.current;
35348
35348
  setShowScrollIndicatorBottom(target.scrollHeight > target.clientHeight && target.scrollHeight - target.scrollTop > target.clientHeight + 10);
@@ -35415,7 +35415,7 @@ var OutputProgressChartComponent = ({
35415
35415
  liveSkuId,
35416
35416
  onSelectSku
35417
35417
  }) => {
35418
- const realSkuRows = React148__default.useMemo(
35418
+ const realSkuRows = React125__default.useMemo(
35419
35419
  () => filterRealSkuBreakdown(skuBreakdown),
35420
35420
  [skuBreakdown]
35421
35421
  );
@@ -35440,7 +35440,7 @@ var OutputProgressChartComponent = ({
35440
35440
  }
35441
35441
  );
35442
35442
  };
35443
- var OutputProgressChart = React148__default.memo(OutputProgressChartComponent);
35443
+ var OutputProgressChart = React125__default.memo(OutputProgressChartComponent);
35444
35444
  OutputProgressChart.displayName = "OutputProgressChart";
35445
35445
  var LargeOutputProgressChart = ({
35446
35446
  currentOutput,
@@ -35580,7 +35580,7 @@ var CycleTimeChartComponent = ({
35580
35580
  }
35581
35581
  ) }) });
35582
35582
  };
35583
- var CycleTimeChart = React148__default.memo(CycleTimeChartComponent, (prevProps, nextProps) => {
35583
+ var CycleTimeChart = React125__default.memo(CycleTimeChartComponent, (prevProps, nextProps) => {
35584
35584
  if (prevProps.className !== nextProps.className) {
35585
35585
  return false;
35586
35586
  }
@@ -35820,16 +35820,16 @@ var CycleTimeOverTimeChart = ({
35820
35820
  onHourClick
35821
35821
  }) => {
35822
35822
  const MAX_DATA_POINTS = 40;
35823
- const containerRef = React148__default.useRef(null);
35824
- const [dimensions, setDimensions] = React148__default.useState({ width: 0, height: 0 });
35825
- const [hasValidData, setHasValidData] = React148__default.useState(false);
35826
- React148__default.useEffect(() => {
35823
+ const containerRef = React125__default.useRef(null);
35824
+ const [dimensions, setDimensions] = React125__default.useState({ width: 0, height: 0 });
35825
+ const [hasValidData, setHasValidData] = React125__default.useState(false);
35826
+ React125__default.useEffect(() => {
35827
35827
  const currentHasValidData = data && data.some((val) => val !== null && val > 0);
35828
35828
  if (currentHasValidData && !hasValidData) {
35829
35829
  setHasValidData(true);
35830
35830
  }
35831
35831
  }, [data, hasValidData]);
35832
- React148__default.useEffect(() => {
35832
+ React125__default.useEffect(() => {
35833
35833
  if (!containerRef.current) return;
35834
35834
  const observer = new ResizeObserver((entries) => {
35835
35835
  const entry = entries[0];
@@ -35867,7 +35867,7 @@ var CycleTimeOverTimeChart = ({
35867
35867
  const endLabel = shiftEnd && slotIndex === DURATION - 1 ? formatHourLabel(slotIndex + 1) : formatHourLabel(slotIndex + 1);
35868
35868
  return `${startLabel} - ${endLabel}`;
35869
35869
  };
35870
- const getDisplayData = React148__default.useCallback((rawData) => {
35870
+ const getDisplayData = React125__default.useCallback((rawData) => {
35871
35871
  if (xAxisMode === "hourly") return rawData;
35872
35872
  return rawData.slice(Math.max(0, rawData.length - MAX_DATA_POINTS));
35873
35873
  }, [xAxisMode]);
@@ -35875,7 +35875,7 @@ var CycleTimeOverTimeChart = ({
35875
35875
  const DURATION = displayData.length;
35876
35876
  const effectiveDatasetKey = datasetKey || `cycle-time:${xAxisMode}`;
35877
35877
  const finalData = displayData;
35878
- const labelInterval = React148__default.useMemo(() => {
35878
+ const labelInterval = React125__default.useMemo(() => {
35879
35879
  if (xAxisMode === "hourly") {
35880
35880
  return Math.max(1, Math.ceil(DURATION / 8));
35881
35881
  }
@@ -35916,8 +35916,8 @@ var CycleTimeOverTimeChart = ({
35916
35916
  return `${minutes} minutes ${seconds} seconds ago`;
35917
35917
  }
35918
35918
  };
35919
- const getNumericValue = React148__default.useCallback((value) => typeof value === "number" && Number.isFinite(value) ? value : null, []);
35920
- const buildHourClickPayload = React148__default.useCallback((dataPoint) => {
35919
+ const getNumericValue = React125__default.useCallback((value) => typeof value === "number" && Number.isFinite(value) ? value : null, []);
35920
+ const buildHourClickPayload = React125__default.useCallback((dataPoint) => {
35921
35921
  if (!onHourClick || xAxisMode !== "hourly") {
35922
35922
  return null;
35923
35923
  }
@@ -35936,7 +35936,7 @@ var CycleTimeOverTimeChart = ({
35936
35936
  status: cycleTime !== null && cycleTime <= idealCycleTime ? "within_standard" : "above_standard"
35937
35937
  };
35938
35938
  }, [DURATION, getNumericValue, idealCycleTime, onHourClick, shiftEnd, shiftStart, xAxisMode]);
35939
- const renderChartTooltip = React148__default.useCallback((tooltipProps) => {
35939
+ const renderChartTooltip = React125__default.useCallback((tooltipProps) => {
35940
35940
  const { active, payload } = tooltipProps;
35941
35941
  if (!active || !Array.isArray(payload) || payload.length === 0) {
35942
35942
  return null;
@@ -36000,7 +36000,7 @@ var CycleTimeOverTimeChart = ({
36000
36000
  ] })
36001
36001
  ] });
36002
36002
  }, [getNumericValue, onHourClick, shiftStart, showIdleTime, xAxisMode]);
36003
- const renderCycleDot = React148__default.useCallback((props) => {
36003
+ const renderCycleDot = React125__default.useCallback((props) => {
36004
36004
  const { cx: cx2, cy, payload } = props;
36005
36005
  const cycleTime = getNumericValue(payload?.cycleTime);
36006
36006
  if (cycleTime === null) {
@@ -36040,7 +36040,7 @@ var CycleTimeOverTimeChart = ({
36040
36040
  }
36041
36041
  );
36042
36042
  }, [buildHourClickPayload, getNumericValue, idealCycleTime, onHourClick, selectedHourIndex]);
36043
- const renderCycleActiveDot = React148__default.useCallback((props) => {
36043
+ const renderCycleActiveDot = React125__default.useCallback((props) => {
36044
36044
  const { cx: cx2, cy, payload } = props;
36045
36045
  const cycleTime = getNumericValue(payload?.cycleTime);
36046
36046
  if (cycleTime === null) {
@@ -36069,7 +36069,7 @@ var CycleTimeOverTimeChart = ({
36069
36069
  }
36070
36070
  );
36071
36071
  }, [buildHourClickPayload, getNumericValue, idealCycleTime, onHourClick, selectedHourIndex]);
36072
- const renderIdleDot = React148__default.useCallback((props) => {
36072
+ const renderIdleDot = React125__default.useCallback((props) => {
36073
36073
  const { cx: cx2, cy, payload } = props;
36074
36074
  const idleMinutes = getNumericValue(payload?.idleMinutes);
36075
36075
  if (idleMinutes === null) {
@@ -36091,7 +36091,7 @@ var CycleTimeOverTimeChart = ({
36091
36091
  }
36092
36092
  );
36093
36093
  }, [getNumericValue, showIdleTime]);
36094
- const renderIdleActiveDot = React148__default.useCallback((props) => {
36094
+ const renderIdleActiveDot = React125__default.useCallback((props) => {
36095
36095
  const { cx: cx2, cy, payload } = props;
36096
36096
  const idleMinutes = getNumericValue(payload?.idleMinutes);
36097
36097
  if (idleMinutes === null || !showIdleTime) {
@@ -36109,7 +36109,7 @@ var CycleTimeOverTimeChart = ({
36109
36109
  }
36110
36110
  );
36111
36111
  }, [getNumericValue, showIdleTime]);
36112
- const chartData = React148__default.useMemo(() => Array.from({ length: DURATION }, (_, i) => {
36112
+ const chartData = React125__default.useMemo(() => Array.from({ length: DURATION }, (_, i) => {
36113
36113
  const cycleTime = getNumericValue(finalData[i]);
36114
36114
  const useIdleSlots = idleTimeSlots.length > 0;
36115
36115
  const idleSlot = useIdleSlots ? idleTimeSlots[i] ?? null : null;
@@ -36306,7 +36306,7 @@ var CycleTimeOverTimeChart = ({
36306
36306
  }
36307
36307
  );
36308
36308
  };
36309
- var Card = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36309
+ var Card = React125.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36310
36310
  "div",
36311
36311
  {
36312
36312
  ref,
@@ -36318,7 +36318,7 @@ var Card = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
36318
36318
  }
36319
36319
  ));
36320
36320
  Card.displayName = "Card";
36321
- var CardHeader = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36321
+ var CardHeader = React125.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36322
36322
  "div",
36323
36323
  {
36324
36324
  ref,
@@ -36327,7 +36327,7 @@ var CardHeader = React148.forwardRef(({ className, ...props }, ref) => /* @__PUR
36327
36327
  }
36328
36328
  ));
36329
36329
  CardHeader.displayName = "CardHeader";
36330
- var CardTitle = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36330
+ var CardTitle = React125.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36331
36331
  "h3",
36332
36332
  {
36333
36333
  ref,
@@ -36339,7 +36339,7 @@ var CardTitle = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE
36339
36339
  }
36340
36340
  ));
36341
36341
  CardTitle.displayName = "CardTitle";
36342
- var CardDescription = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36342
+ var CardDescription = React125.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36343
36343
  "p",
36344
36344
  {
36345
36345
  ref,
@@ -36348,9 +36348,9 @@ var CardDescription = React148.forwardRef(({ className, ...props }, ref) => /* @
36348
36348
  }
36349
36349
  ));
36350
36350
  CardDescription.displayName = "CardDescription";
36351
- var CardContent = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
36351
+ var CardContent = React125.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
36352
36352
  CardContent.displayName = "CardContent";
36353
- var CardFooter = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36353
+ var CardFooter = React125.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
36354
36354
  "div",
36355
36355
  {
36356
36356
  ref,
@@ -36426,7 +36426,7 @@ var buttonVariants = cva(
36426
36426
  }
36427
36427
  }
36428
36428
  );
36429
- var Button = React148.forwardRef(
36429
+ var Button = React125.forwardRef(
36430
36430
  ({ className, variant, size, asChild = false, ...props }, ref) => {
36431
36431
  const Comp = asChild ? Slot : "button";
36432
36432
  return /* @__PURE__ */ jsx(
@@ -37182,16 +37182,38 @@ var HourlyOutputChartComponent = ({
37182
37182
  onHourClick,
37183
37183
  onWatchClipsClick,
37184
37184
  onAiSummaryClick,
37185
+ onSelectSku,
37185
37186
  className = ""
37186
37187
  }) => {
37187
- const containerRef = React148__default.useRef(null);
37188
- const [containerReady, setContainerReady] = React148__default.useState(false);
37189
- const [containerWidth, setContainerWidth] = React148__default.useState(0);
37190
- const [hoveredSkuRailLabel, setHoveredSkuRailLabel] = React148__default.useState(null);
37191
- const [isTooltipHovered, setIsTooltipHovered] = React148__default.useState(false);
37192
- const lastTooltipDataRef = React148__default.useRef(null);
37193
- const tooltipHoverTimeoutRef = React148__default.useRef(null);
37194
- const idleSlots = React148__default.useMemo(
37188
+ const containerRef = React125__default.useRef(null);
37189
+ const [containerReady, setContainerReady] = React125__default.useState(false);
37190
+ const [containerWidth, setContainerWidth] = React125__default.useState(0);
37191
+ const [hoveredSkuRailLabel, setHoveredSkuRailLabel] = React125__default.useState(null);
37192
+ const [isTooltipHovered, setIsTooltipHovered] = React125__default.useState(false);
37193
+ const [forceHideTooltip, setForceHideTooltip] = React125__default.useState(false);
37194
+ const lastTooltipDataRef = React125__default.useRef(null);
37195
+ const tooltipHoverTimeoutRef = React125__default.useRef(null);
37196
+ const clearTooltipHoverTimeout = React125__default.useCallback(() => {
37197
+ if (tooltipHoverTimeoutRef.current) {
37198
+ clearTimeout(tooltipHoverTimeoutRef.current);
37199
+ tooltipHoverTimeoutRef.current = null;
37200
+ }
37201
+ }, []);
37202
+ const hideInteractiveTooltip = React125__default.useCallback(() => {
37203
+ clearTooltipHoverTimeout();
37204
+ setIsTooltipHovered(false);
37205
+ setForceHideTooltip(true);
37206
+ lastTooltipDataRef.current = null;
37207
+ }, [clearTooltipHoverTimeout]);
37208
+ const scheduleInteractiveTooltipHide = React125__default.useCallback((delayMs = 120) => {
37209
+ clearTooltipHoverTimeout();
37210
+ tooltipHoverTimeoutRef.current = setTimeout(() => {
37211
+ setIsTooltipHovered(false);
37212
+ lastTooltipDataRef.current = null;
37213
+ tooltipHoverTimeoutRef.current = null;
37214
+ }, delayMs);
37215
+ }, [clearTooltipHoverTimeout]);
37216
+ const idleSlots = React125__default.useMemo(
37195
37217
  () => buildHourlyIdleSlots({
37196
37218
  idleTimeHourly,
37197
37219
  shiftStart,
@@ -37200,12 +37222,12 @@ var HourlyOutputChartComponent = ({
37200
37222
  [idleTimeHourly, shiftStart, shiftEnd]
37201
37223
  );
37202
37224
  const SHIFT_DURATION = idleSlots.length;
37203
- const [animatedData, setAnimatedData] = React148__default.useState(
37225
+ const [animatedData, setAnimatedData] = React125__default.useState(
37204
37226
  () => Array(SHIFT_DURATION).fill(0)
37205
37227
  );
37206
- const prevDataRef = React148__default.useRef(Array(SHIFT_DURATION).fill(0));
37207
- const animationFrameRef = React148__default.useRef(null);
37208
- React148__default.useEffect(() => {
37228
+ const prevDataRef = React125__default.useRef(Array(SHIFT_DURATION).fill(0));
37229
+ const animationFrameRef = React125__default.useRef(null);
37230
+ React125__default.useEffect(() => {
37209
37231
  setAnimatedData((prev) => {
37210
37232
  if (prev.length !== SHIFT_DURATION) {
37211
37233
  return Array(SHIFT_DURATION).fill(0);
@@ -37214,14 +37236,14 @@ var HourlyOutputChartComponent = ({
37214
37236
  });
37215
37237
  prevDataRef.current = Array(SHIFT_DURATION).fill(0);
37216
37238
  }, [SHIFT_DURATION]);
37217
- const [idleBarState, setIdleBarState] = React148__default.useState({
37239
+ const [idleBarState, setIdleBarState] = React125__default.useState({
37218
37240
  visible: showIdleTime,
37219
37241
  key: 0,
37220
37242
  shouldAnimate: false
37221
37243
  });
37222
- const prevShowIdleTimeRef = React148__default.useRef(showIdleTime);
37223
- const stateUpdateTimeoutRef = React148__default.useRef(null);
37224
- React148__default.useEffect(() => {
37244
+ const prevShowIdleTimeRef = React125__default.useRef(showIdleTime);
37245
+ const stateUpdateTimeoutRef = React125__default.useRef(null);
37246
+ React125__default.useEffect(() => {
37225
37247
  if (stateUpdateTimeoutRef.current) {
37226
37248
  clearTimeout(stateUpdateTimeoutRef.current);
37227
37249
  }
@@ -37246,7 +37268,7 @@ var HourlyOutputChartComponent = ({
37246
37268
  }
37247
37269
  };
37248
37270
  }, [showIdleTime]);
37249
- const animateToNewData = React148__default.useCallback((targetData) => {
37271
+ const animateToNewData = React125__default.useCallback((targetData) => {
37250
37272
  const startData = [...prevDataRef.current];
37251
37273
  const startTime = performance.now();
37252
37274
  const duration = 1200;
@@ -37276,7 +37298,7 @@ var HourlyOutputChartComponent = ({
37276
37298
  }
37277
37299
  animationFrameRef.current = requestAnimationFrame(animate);
37278
37300
  }, []);
37279
- React148__default.useEffect(() => {
37301
+ React125__default.useEffect(() => {
37280
37302
  if (JSON.stringify(data) !== JSON.stringify(prevDataRef.current)) {
37281
37303
  const shiftData = data.slice(0, SHIFT_DURATION);
37282
37304
  animateToNewData(shiftData);
@@ -37287,14 +37309,15 @@ var HourlyOutputChartComponent = ({
37287
37309
  }
37288
37310
  };
37289
37311
  }, [data, animateToNewData]);
37290
- React148__default.useEffect(() => {
37312
+ React125__default.useEffect(() => {
37313
+ const handleWindowBlur = () => hideInteractiveTooltip();
37314
+ window.addEventListener("blur", handleWindowBlur);
37291
37315
  return () => {
37292
- if (tooltipHoverTimeoutRef.current) {
37293
- clearTimeout(tooltipHoverTimeoutRef.current);
37294
- }
37316
+ window.removeEventListener("blur", handleWindowBlur);
37317
+ clearTooltipHoverTimeout();
37295
37318
  };
37296
- }, []);
37297
- React148__default.useEffect(() => {
37319
+ }, [clearTooltipHoverTimeout, hideInteractiveTooltip]);
37320
+ React125__default.useEffect(() => {
37298
37321
  const checkContainerDimensions = () => {
37299
37322
  if (containerRef.current) {
37300
37323
  const rect = containerRef.current.getBoundingClientRect();
@@ -37320,7 +37343,7 @@ var HourlyOutputChartComponent = ({
37320
37343
  clearTimeout(fallbackTimeout);
37321
37344
  };
37322
37345
  }, []);
37323
- const xAxisConfig = React148__default.useMemo(() => {
37346
+ const xAxisConfig = React125__default.useMemo(() => {
37324
37347
  if (containerWidth >= 960) {
37325
37348
  return {
37326
37349
  interval: 0,
@@ -37341,13 +37364,13 @@ var HourlyOutputChartComponent = ({
37341
37364
  }
37342
37365
  return { interval: 0, angle: -30, height: 64, tickFont: 9, tickMargin: 6 };
37343
37366
  }, [containerWidth]);
37344
- const shiftWindow = React148__default.useMemo(() => resolveShiftWindow2({
37367
+ const shiftWindow = React125__default.useMemo(() => resolveShiftWindow2({
37345
37368
  shiftStart,
37346
37369
  slotCount: SHIFT_DURATION,
37347
37370
  shiftDate,
37348
37371
  timezone
37349
37372
  }), [shiftStart, shiftEnd, SHIFT_DURATION, shiftDate, timezone]);
37350
- const fallbackTimelineEndOffset = React148__default.useMemo(
37373
+ const fallbackTimelineEndOffset = React125__default.useMemo(
37351
37374
  () => resolveTimelineEndOffset({
37352
37375
  shiftStart,
37353
37376
  shiftEnd,
@@ -37357,7 +37380,7 @@ var HourlyOutputChartComponent = ({
37357
37380
  }),
37358
37381
  [shiftStart, shiftEnd, SHIFT_DURATION, shiftDate, timezone]
37359
37382
  );
37360
- const observedTimelineEndOffset = React148__default.useMemo(() => {
37383
+ const observedTimelineEndOffset = React125__default.useMemo(() => {
37361
37384
  let lastObservedMinute = -1;
37362
37385
  idleSlots.forEach((slot) => {
37363
37386
  slot.idleArray.forEach((value, minuteIndex) => {
@@ -37373,7 +37396,7 @@ var HourlyOutputChartComponent = ({
37373
37396
  return Math.min((lastObservedMinute + 1) / 60, SHIFT_DURATION);
37374
37397
  }, [idleSlots, SHIFT_DURATION]);
37375
37398
  const timelineEndOffset = observedTimelineEndOffset ?? fallbackTimelineEndOffset;
37376
- const targetLineEndOffset = React148__default.useMemo(() => {
37399
+ const targetLineEndOffset = React125__default.useMemo(() => {
37377
37400
  if (timelineEndOffset >= SHIFT_DURATION) {
37378
37401
  return SHIFT_DURATION;
37379
37402
  }
@@ -37382,7 +37405,7 @@ var HourlyOutputChartComponent = ({
37382
37405
  }
37383
37406
  return Math.min(Math.floor(timelineEndOffset) + 1, SHIFT_DURATION);
37384
37407
  }, [timelineEndOffset, SHIFT_DURATION]);
37385
- const skuTimelineSegments = React148__default.useMemo(() => {
37408
+ const skuTimelineSegments = React125__default.useMemo(() => {
37386
37409
  if (!skuSegments || skuSegments.length === 0 || !shiftWindow || timelineEndOffset <= 0) {
37387
37410
  return [];
37388
37411
  }
@@ -37416,18 +37439,18 @@ var HourlyOutputChartComponent = ({
37416
37439
  };
37417
37440
  }).filter((segment) => segment.end > segment.start);
37418
37441
  }, [skuSegments, shiftWindow, timelineEndOffset, pphThreshold]);
37419
- const targetTimelineSegments = React148__default.useMemo(() => {
37442
+ const targetTimelineSegments = React125__default.useMemo(() => {
37420
37443
  if (skuTimelineSegments.length === 0) return [];
37421
37444
  return skuTimelineSegments.map((segment, index) => ({
37422
37445
  ...segment,
37423
37446
  end: index === skuTimelineSegments.length - 1 ? Math.max(segment.start, targetLineEndOffset) : segment.end
37424
37447
  })).filter((segment) => segment.end > segment.start);
37425
37448
  }, [skuTimelineSegments, targetLineEndOffset]);
37426
- const hasExplicitHourlyTargetOutputProp = React148__default.useMemo(
37449
+ const hasExplicitHourlyTargetOutputProp = React125__default.useMemo(
37427
37450
  () => hourlyTargetOutput !== void 0,
37428
37451
  [hourlyTargetOutput]
37429
37452
  );
37430
- const fallbackHourlyTargetOutput = React148__default.useMemo(() => {
37453
+ const fallbackHourlyTargetOutput = React125__default.useMemo(() => {
37431
37454
  if (hasExplicitHourlyTargetOutputProp) return void 0;
37432
37455
  if (skuTimelineSegments.length > 0) return void 0;
37433
37456
  const plan = buildHourlyTargetPlan({
@@ -37447,19 +37470,19 @@ var HourlyOutputChartComponent = ({
37447
37470
  shiftBreaks,
37448
37471
  pphThreshold
37449
37472
  ]);
37450
- const effectiveHourlyTargetOutput = React148__default.useMemo(
37473
+ const effectiveHourlyTargetOutput = React125__default.useMemo(
37451
37474
  () => hasExplicitHourlyTargetOutputProp ? hourlyTargetOutput : fallbackHourlyTargetOutput,
37452
37475
  [hasExplicitHourlyTargetOutputProp, hourlyTargetOutput, fallbackHourlyTargetOutput]
37453
37476
  );
37454
- const hasHourlyTargetOutputProp = React148__default.useMemo(
37477
+ const hasHourlyTargetOutputProp = React125__default.useMemo(
37455
37478
  () => effectiveHourlyTargetOutput !== void 0,
37456
37479
  [effectiveHourlyTargetOutput]
37457
37480
  );
37458
- const hasExplicitHourlyTargets = React148__default.useMemo(
37481
+ const hasExplicitHourlyTargets = React125__default.useMemo(
37459
37482
  () => Array.isArray(effectiveHourlyTargetOutput) && effectiveHourlyTargetOutput.some((value) => value !== null && value !== void 0),
37460
37483
  [effectiveHourlyTargetOutput]
37461
37484
  );
37462
- const hourlyTargetSegments = React148__default.useMemo(() => {
37485
+ const hourlyTargetSegments = React125__default.useMemo(() => {
37463
37486
  if (!hasExplicitHourlyTargets) return [];
37464
37487
  const segments = [];
37465
37488
  let runStart = null;
@@ -37491,7 +37514,7 @@ var HourlyOutputChartComponent = ({
37491
37514
  flush(SHIFT_DURATION);
37492
37515
  return segments.filter((segment) => segment.end > segment.start);
37493
37516
  }, [SHIFT_DURATION, hasExplicitHourlyTargets, effectiveHourlyTargetOutput]);
37494
- const activeSkuHourIndices = React148__default.useMemo(() => {
37517
+ const activeSkuHourIndices = React125__default.useMemo(() => {
37495
37518
  const indices = /* @__PURE__ */ new Set();
37496
37519
  const targets = Array(SHIFT_DURATION).fill(pphThreshold);
37497
37520
  if (!skuSegments || !shiftWindow) return { indices, targets, hasTimeline: false };
@@ -37524,7 +37547,7 @@ var HourlyOutputChartComponent = ({
37524
37547
  }
37525
37548
  return { indices, targets, hasTimeline: true };
37526
37549
  }, [skuSegments, activeSkuId, shiftWindow, SHIFT_DURATION, pphThreshold]);
37527
- const chartData = React148__default.useMemo(() => {
37550
+ const chartData = React125__default.useMemo(() => {
37528
37551
  const { indices, targets, hasTimeline } = activeSkuHourIndices;
37529
37552
  return Array.from({ length: SHIFT_DURATION }, (_, i) => {
37530
37553
  const idleSlot = idleSlots[i];
@@ -37553,7 +37576,7 @@ var HourlyOutputChartComponent = ({
37553
37576
  };
37554
37577
  });
37555
37578
  }, [animatedData, data, pphThreshold, idleSlots, SHIFT_DURATION, activeSkuHourIndices, activeSkuId, effectiveHourlyTargetOutput, hasHourlyTargetOutputProp, selectedHourIndex]);
37556
- const renderSkuTimelineRail = React148__default.useCallback((props) => {
37579
+ const renderSkuTimelineRail = React125__default.useCallback((props) => {
37557
37580
  if (!skuTimelineSegments.length || SHIFT_DURATION <= 0) return null;
37558
37581
  const offset = props?.offset;
37559
37582
  if (!offset) return null;
@@ -37617,6 +37640,8 @@ var HourlyOutputChartComponent = ({
37617
37640
  width: hoverHitWidth,
37618
37641
  height: hoverHitHeight,
37619
37642
  fill: "transparent",
37643
+ style: { cursor: onSelectSku ? "pointer" : "default" },
37644
+ onClick: () => onSelectSku?.(isActive ? null : segment.skuId),
37620
37645
  onMouseEnter: () => showHoverLabel(segment.label, xStart + segmentWidth / 2, railY),
37621
37646
  onMouseLeave: () => setHoveredSkuRailLabel((current) => current?.label === segment.label ? null : current)
37622
37647
  }
@@ -37701,8 +37726,8 @@ var HourlyOutputChartComponent = ({
37701
37726
  ] }, `sku-rail-${segment.skuId}-${segment.start}-${index}`);
37702
37727
  })
37703
37728
  ] });
37704
- }, [skuTimelineSegments, SHIFT_DURATION, activeSkuId]);
37705
- const IdleBar = React148__default.useMemo(() => {
37729
+ }, [skuTimelineSegments, SHIFT_DURATION, activeSkuId, onSelectSku]);
37730
+ const IdleBar = React125__default.useMemo(() => {
37706
37731
  if (!idleBarState.visible) return null;
37707
37732
  return /* @__PURE__ */ jsx(
37708
37733
  Bar,
@@ -37796,7 +37821,7 @@ var HourlyOutputChartComponent = ({
37796
37821
  }
37797
37822
  return filteredTicks;
37798
37823
  };
37799
- const renderTargetLine = React148__default.useCallback((props) => {
37824
+ const renderTargetLine = React125__default.useCallback((props) => {
37800
37825
  const { offset, yAxisMap } = props;
37801
37826
  if (!offset || !yAxisMap || SHIFT_DURATION <= 0 || targetLineEndOffset <= 0) return null;
37802
37827
  const { left, width } = offset;
@@ -37926,378 +37951,386 @@ var HourlyOutputChartComponent = ({
37926
37951
  className: `w-full h-full min-w-0 flex flex-col ${className}`,
37927
37952
  style: { minHeight: "200px", minWidth: 0 },
37928
37953
  children: [
37929
- containerReady ? /* @__PURE__ */ jsxs("div", { className: "flex-1 min-h-0 relative", children: [
37930
- /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
37931
- BarChart$1,
37932
- {
37933
- data: chartData,
37934
- margin: {
37935
- // Reserve headroom for the SKU timeline rail + staggered
37936
- // labels only when SKU segments are rendered. Non-SKU charts
37937
- // keep the original 10px top so recharts has enough vertical
37938
- // space to show the target (pph) tick label on the Y-axis.
37939
- top: skuTimelineSegments.length > 0 ? 40 : 10,
37940
- right: 10,
37941
- bottom: 10,
37942
- left: 6
37943
- },
37944
- barCategoryGap: "25%",
37945
- children: [
37946
- /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", vertical: false }),
37947
- /* @__PURE__ */ jsx(
37948
- XAxis,
37949
- {
37950
- xAxisId: "default",
37951
- dataKey: "hour",
37952
- tick: { fontSize: xAxisConfig.tickFont },
37953
- interval: xAxisConfig.interval,
37954
- angle: xAxisConfig.angle,
37955
- textAnchor: "end",
37956
- tickMargin: xAxisConfig.tickMargin,
37957
- height: xAxisConfig.height
37958
- }
37959
- ),
37960
- /* @__PURE__ */ jsx(
37961
- XAxis,
37962
- {
37963
- xAxisId: "sku",
37964
- type: "number",
37965
- dataKey: "skuIndex",
37966
- domain: [0, Math.max(SHIFT_DURATION, 0)],
37967
- hide: true,
37968
- allowDataOverflow: true
37969
- }
37970
- ),
37971
- /* @__PURE__ */ jsx(
37972
- YAxis,
37973
- {
37974
- yAxisId: "default",
37975
- tickMargin: 8,
37976
- width: 48,
37977
- domain: [0, maxYValue],
37978
- ticks: generateYAxisTicks(),
37979
- tickFormatter: (value) => value,
37980
- tick: (props) => {
37981
- const { x, y, payload } = props;
37982
- return /* @__PURE__ */ jsx("g", { transform: `translate(${x},${y})`, children: /* @__PURE__ */ jsx(
37983
- "text",
37984
- {
37985
- x: -2,
37986
- y: 0,
37987
- dy: 4,
37988
- textAnchor: "end",
37989
- fill: "#666",
37990
- fontSize: 12,
37991
- children: payload.value
37992
- },
37993
- `tick-${payload.value}-${x}-${y}`
37994
- ) });
37995
- }
37996
- }
37997
- ),
37998
- /* @__PURE__ */ jsx(YAxis, { yAxisId: "idle", domain: [0, 60], hide: true }),
37999
- /* @__PURE__ */ jsx(
38000
- Tooltip,
38001
- {
38002
- cursor: { fill: "#f1f5f9" },
38003
- shared: false,
38004
- offset: -5,
38005
- wrapperStyle: { pointerEvents: "auto", zIndex: 100 },
38006
- active: isTooltipHovered ? true : void 0,
38007
- isAnimationActive: false,
38008
- contentStyle: { backgroundColor: "transparent", border: "none", padding: 0 },
38009
- content: (props) => {
38010
- const activeData = props.active && props.payload && props.payload.length > 0 ? props.payload[0].payload : null;
38011
- const data2 = activeData || (isTooltipHovered ? lastTooltipDataRef.current : null);
38012
- if (!data2)
38013
- return null;
38014
- if (activeData) {
38015
- lastTooltipDataRef.current = activeData;
37954
+ containerReady ? /* @__PURE__ */ jsxs(
37955
+ "div",
37956
+ {
37957
+ "data-testid": "hourly-output-chart-viewport",
37958
+ className: "flex-1 min-h-0 relative",
37959
+ onMouseEnter: () => {
37960
+ setForceHideTooltip(false);
37961
+ clearTooltipHoverTimeout();
37962
+ },
37963
+ onMouseLeave: () => {
37964
+ setForceHideTooltip(true);
37965
+ scheduleInteractiveTooltipHide(80);
37966
+ },
37967
+ children: [
37968
+ /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
37969
+ BarChart$1,
37970
+ {
37971
+ data: chartData,
37972
+ margin: {
37973
+ // Reserve headroom for the SKU timeline rail + staggered
37974
+ // labels only when SKU segments are rendered. Non-SKU charts
37975
+ // keep the original 10px top so recharts has enough vertical
37976
+ // space to show the target (pph) tick label on the Y-axis.
37977
+ top: skuTimelineSegments.length > 0 ? 40 : 10,
37978
+ right: 10,
37979
+ bottom: 10,
37980
+ left: 6
37981
+ },
37982
+ barCategoryGap: "25%",
37983
+ children: [
37984
+ /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", vertical: false }),
37985
+ /* @__PURE__ */ jsx(
37986
+ XAxis,
37987
+ {
37988
+ xAxisId: "default",
37989
+ dataKey: "hour",
37990
+ tick: { fontSize: xAxisConfig.tickFont },
37991
+ interval: xAxisConfig.interval,
37992
+ angle: xAxisConfig.angle,
37993
+ textAnchor: "end",
37994
+ tickMargin: xAxisConfig.tickMargin,
37995
+ height: xAxisConfig.height
38016
37996
  }
38017
- const idlePeriods = showIdleTime ? getHourlyIdlePeriods({
38018
- idleArray: data2.idleArray,
38019
- shiftStart,
38020
- hourIndex: Number.isFinite(data2.hourIndex) ? data2.hourIndex : 0
38021
- }) : [];
38022
- const tooltipHourIndex = Number.isFinite(data2.hourIndex) ? data2.hourIndex : 0;
38023
- const { startTime, endTime } = buildHourClipFilterWindow({
38024
- shiftStart,
38025
- shiftEnd,
38026
- hourIndex: tooltipHourIndex,
38027
- slotCount: SHIFT_DURATION
38028
- });
38029
- const clickPayload = {
38030
- hourIndex: tooltipHourIndex,
38031
- timeRange: data2.timeRange,
38032
- startTime,
38033
- endTime,
38034
- output: Math.round(data2.originalOutput || 0),
38035
- target: data2.target,
38036
- status: data2.status
38037
- };
38038
- return /* @__PURE__ */ jsx(
38039
- "div",
38040
- {
38041
- className: "p-3 -m-3 pointer-events-auto",
38042
- style: { cursor: "default" },
38043
- onMouseEnter: () => {
38044
- if (tooltipHoverTimeoutRef.current) {
38045
- clearTimeout(tooltipHoverTimeoutRef.current);
38046
- tooltipHoverTimeoutRef.current = null;
38047
- }
38048
- setIsTooltipHovered(true);
38049
- },
38050
- onMouseLeave: () => {
38051
- if (tooltipHoverTimeoutRef.current) {
38052
- clearTimeout(tooltipHoverTimeoutRef.current);
38053
- }
38054
- tooltipHoverTimeoutRef.current = setTimeout(() => {
38055
- setIsTooltipHovered(false);
38056
- tooltipHoverTimeoutRef.current = null;
38057
- }, 120);
38058
- },
38059
- children: /* @__PURE__ */ jsxs("div", { className: "bg-white/95 backdrop-blur-md border border-slate-200/60 shadow-xl shadow-slate-200/40 rounded-xl p-4 min-w-[240px] text-slate-700 pointer-events-auto", children: [
38060
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4 pb-3 border-b border-slate-100", children: [
38061
- /* @__PURE__ */ jsx("p", { className: "font-semibold text-slate-900 text-sm tracking-tight", children: data2.timeRange }),
38062
- onAiSummaryClick && /* @__PURE__ */ jsxs(
38063
- "button",
38064
- {
38065
- onClick: (e) => {
38066
- e.stopPropagation();
38067
- onAiSummaryClick(clickPayload);
38068
- },
38069
- className: "flex items-center gap-1 px-2 py-1 -mr-1 rounded-md border border-slate-200 bg-white hover:bg-slate-50 text-[11px] font-medium text-slate-600 shadow-sm transition-colors",
38070
- children: [
38071
- /* @__PURE__ */ jsx(SparklesIcon, { className: "w-3.5 h-3.5" }),
38072
- "Ask AI"
38073
- ]
38074
- }
38075
- )
38076
- ] }),
38077
- /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
38078
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
38079
- /* @__PURE__ */ jsx("span", { className: "text-sm text-slate-500 font-medium tracking-wide", children: "Output" }),
38080
- /* @__PURE__ */ jsxs("span", { className: "font-bold text-slate-900 text-sm", children: [
38081
- Math.round(data2.output),
38082
- " ",
38083
- /* @__PURE__ */ jsx("span", { className: "text-slate-400 font-normal text-xs ml-0.5", children: "units" })
38084
- ] })
38085
- ] }),
38086
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
38087
- /* @__PURE__ */ jsx("span", { className: "text-sm text-slate-500 font-medium tracking-wide", children: "Target" }),
38088
- /* @__PURE__ */ jsxs("span", { className: "font-bold text-slate-700 text-sm", children: [
38089
- Math.round(data2.target),
38090
- " ",
38091
- /* @__PURE__ */ jsx("span", { className: "text-slate-400 font-normal text-xs ml-0.5", children: "units" })
38092
- ] })
38093
- ] }),
38094
- showIdleTime && data2.idleMinutes > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
38095
- /* @__PURE__ */ jsx("div", { className: "pt-3 mt-3 border-t border-slate-100", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
38096
- /* @__PURE__ */ jsx("span", { className: "text-sm text-slate-500 font-medium tracking-wide", children: "Idle Time" }),
38097
- /* @__PURE__ */ jsxs("span", { className: "font-bold text-orange-600 text-sm flex items-center gap-1.5", children: [
38098
- /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-orange-500 shadow-[0_0_6px_rgba(249,115,22,0.6)] animate-pulse" }),
38099
- data2.idleMinutes,
38100
- " ",
38101
- /* @__PURE__ */ jsx("span", { className: "text-orange-500/70 font-normal text-xs ml-0.5", children: "min" })
38102
- ] })
38103
- ] }) }),
38104
- idlePeriods.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-3 bg-slate-50/80 rounded-lg p-3 border border-slate-100/50", children: [
38105
- /* @__PURE__ */ jsx("p", { className: "font-semibold text-slate-400 text-[10px] mb-2.5 uppercase tracking-wider", children: "Idle Periods" }),
38106
- /* @__PURE__ */ jsx("div", { className: "space-y-2.5 max-h-32 overflow-y-auto pr-1 custom-scrollbar", children: idlePeriods.map((period, index) => {
38107
- return /* @__PURE__ */ jsxs(
38108
- "div",
38109
- {
38110
- className: "flex items-start gap-2.5 text-xs",
38111
- children: [
38112
- /* @__PURE__ */ jsx("div", { className: "mt-[5px] w-1.5 h-1.5 bg-orange-400 rounded-full flex-shrink-0 shadow-[0_0_4px_rgba(251,146,60,0.5)]" }),
38113
- /* @__PURE__ */ jsx("span", { className: "text-slate-700 font-medium tracking-tight", children: period.duration === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
38114
- period.startTime,
38115
- " ",
38116
- /* @__PURE__ */ jsxs("span", { className: "text-slate-400 font-normal ml-1", children: [
38117
- "(",
38118
- period.duration,
38119
- "m)"
38120
- ] })
38121
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
38122
- period.startTime,
38123
- " ",
38124
- /* @__PURE__ */ jsx("span", { className: "text-slate-400 mx-0.5", children: "\u2192" }),
38125
- " ",
38126
- period.endTime,
38127
- " ",
38128
- /* @__PURE__ */ jsxs("span", { className: "text-slate-400 font-normal ml-1", children: [
38129
- "(",
38130
- period.duration,
38131
- "m)"
38132
- ] })
38133
- ] }) })
38134
- ]
38135
- },
38136
- index
38137
- );
38138
- }) })
38139
- ] })
38140
- ] }),
38141
- onWatchClipsClick && /* @__PURE__ */ jsx("div", { className: "pt-3 mt-3 border-t border-slate-100 flex items-center", children: /* @__PURE__ */ jsxs(
38142
- "button",
38143
- {
38144
- onClick: (e) => {
38145
- e.stopPropagation();
38146
- onWatchClipsClick(clickPayload);
38147
- },
38148
- className: "w-full rounded-md border border-slate-200 bg-white hover:bg-slate-50 px-2 py-1.5 text-xs font-semibold text-slate-700 transition-colors flex items-center justify-center gap-1.5 shadow-sm",
38149
- children: [
38150
- /* @__PURE__ */ jsx(PlayCircleIcon, { className: "w-4 h-4 text-blue-500" }),
38151
- "Watch Clips"
38152
- ]
38153
- }
38154
- ) }),
38155
- onHourClick && !onWatchClipsClick && !onAiSummaryClick && /* @__PURE__ */ jsx("div", { className: "pt-3 mt-3 border-t border-slate-100", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-blue-100 bg-blue-50/70 px-3 py-2 text-xs font-semibold text-blue-700 text-center", children: "Click to inspect hour" }) })
38156
- ] })
38157
- ] })
37997
+ ),
37998
+ /* @__PURE__ */ jsx(
37999
+ XAxis,
38000
+ {
38001
+ xAxisId: "sku",
38002
+ type: "number",
38003
+ dataKey: "skuIndex",
38004
+ domain: [0, Math.max(SHIFT_DURATION, 0)],
38005
+ hide: true,
38006
+ allowDataOverflow: true
38007
+ }
38008
+ ),
38009
+ /* @__PURE__ */ jsx(
38010
+ YAxis,
38011
+ {
38012
+ yAxisId: "default",
38013
+ tickMargin: 8,
38014
+ width: 48,
38015
+ domain: [0, maxYValue],
38016
+ ticks: generateYAxisTicks(),
38017
+ tickFormatter: (value) => value,
38018
+ tick: (props) => {
38019
+ const { x, y, payload } = props;
38020
+ return /* @__PURE__ */ jsx("g", { transform: `translate(${x},${y})`, children: /* @__PURE__ */ jsx(
38021
+ "text",
38022
+ {
38023
+ x: -2,
38024
+ y: 0,
38025
+ dy: 4,
38026
+ textAnchor: "end",
38027
+ fill: "#666",
38028
+ fontSize: 12,
38029
+ children: payload.value
38030
+ },
38031
+ `tick-${payload.value}-${x}-${y}`
38032
+ ) });
38158
38033
  }
38159
- );
38160
- },
38161
- animationDuration: 200
38162
- }
38163
- ),
38164
- /* @__PURE__ */ jsx(Customized, { component: renderTargetLine }),
38165
- /* @__PURE__ */ jsx(Customized, { component: renderSkuTimelineRail }),
38166
- /* @__PURE__ */ jsxs(
38167
- Bar,
38168
- {
38169
- xAxisId: "default",
38170
- dataKey: "output",
38171
- yAxisId: "default",
38172
- maxBarSize: 35,
38173
- radius: [10, 10, 0, 0],
38174
- isAnimationActive: false,
38175
- children: [
38176
- chartData.map((entry, index) => /* @__PURE__ */ jsx(
38177
- Cell,
38178
- {
38179
- fill: entry.color,
38180
- stroke: entry.isSelected ? "#0f172a" : "transparent",
38181
- strokeWidth: entry.isSelected ? 2 : 0,
38182
- style: {
38183
- filter: entry.isHighlighted || entry.isSelected ? "drop-shadow(0 4px 6px rgba(0, 0, 0, 0.12)) brightness(1.05)" : "brightness(1)",
38184
- transform: entry.isHighlighted || entry.isSelected ? "translateY(-4px)" : "translateY(0)",
38185
- opacity: entry.isDimmed ? 0.4 : 1,
38186
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
38187
- cursor: onHourClick || onWatchClipsClick || onAiSummaryClick ? "pointer" : "default"
38188
- },
38189
- onMouseEnter: (e) => {
38190
- const target = e.target;
38191
- target.style.filter = "drop-shadow(0 4px 6px rgba(0, 0, 0, 0.12)) brightness(1.05)";
38192
- target.style.transform = "translateY(-4px)";
38193
- target.style.opacity = "1";
38194
- },
38195
- onMouseLeave: (e) => {
38196
- const target = e.target;
38197
- target.style.filter = entry.isHighlighted || entry.isSelected ? "drop-shadow(0 4px 6px rgba(0, 0, 0, 0.12)) brightness(1.05)" : "brightness(1)";
38198
- target.style.transform = entry.isHighlighted || entry.isSelected ? "translateY(-4px)" : "translateY(0)";
38199
- target.style.opacity = entry.isDimmed ? "0.4" : "1";
38200
- },
38201
- onClick: () => {
38202
- if (!onHourClick && !onWatchClipsClick && !onAiSummaryClick) return;
38203
- const { startTime, endTime } = buildHourClipFilterWindow({
38204
- shiftStart,
38205
- shiftEnd,
38206
- hourIndex: entry.hourIndex,
38207
- slotCount: SHIFT_DURATION
38208
- });
38209
- const payload = {
38210
- hourIndex: entry.hourIndex,
38211
- timeRange: entry.timeRange,
38212
- startTime,
38213
- endTime,
38214
- output: Math.round(entry.originalOutput || 0),
38215
- target: entry.target,
38216
- status: entry.status
38217
- };
38218
- if (onHourClick) onHourClick(payload);
38034
+ }
38035
+ ),
38036
+ /* @__PURE__ */ jsx(YAxis, { yAxisId: "idle", domain: [0, 60], hide: true }),
38037
+ /* @__PURE__ */ jsx(
38038
+ Tooltip,
38039
+ {
38040
+ cursor: { fill: "#f1f5f9" },
38041
+ shared: false,
38042
+ offset: -5,
38043
+ wrapperStyle: { pointerEvents: "auto", zIndex: 100, transition: "opacity 0.2s ease-out, transform 0.15s ease-out" },
38044
+ active: forceHideTooltip ? false : isTooltipHovered ? true : void 0,
38045
+ isAnimationActive: false,
38046
+ contentStyle: { backgroundColor: "transparent", border: "none", padding: 0 },
38047
+ content: (props) => {
38048
+ const activeData = props.active && props.payload && props.payload.length > 0 ? props.payload[0].payload : null;
38049
+ const data2 = activeData || (isTooltipHovered ? lastTooltipDataRef.current : null);
38050
+ if (!data2)
38051
+ return null;
38052
+ if (activeData) {
38053
+ lastTooltipDataRef.current = activeData;
38219
38054
  }
38055
+ const idlePeriods = showIdleTime ? getHourlyIdlePeriods({
38056
+ idleArray: data2.idleArray,
38057
+ shiftStart,
38058
+ hourIndex: Number.isFinite(data2.hourIndex) ? data2.hourIndex : 0
38059
+ }) : [];
38060
+ const tooltipHourIndex = Number.isFinite(data2.hourIndex) ? data2.hourIndex : 0;
38061
+ const { startTime, endTime } = buildHourClipFilterWindow({
38062
+ shiftStart,
38063
+ shiftEnd,
38064
+ hourIndex: tooltipHourIndex,
38065
+ slotCount: SHIFT_DURATION
38066
+ });
38067
+ const clickPayload = {
38068
+ hourIndex: tooltipHourIndex,
38069
+ timeRange: data2.timeRange,
38070
+ startTime,
38071
+ endTime,
38072
+ output: Math.round(data2.originalOutput || 0),
38073
+ target: data2.target,
38074
+ status: data2.status
38075
+ };
38076
+ return /* @__PURE__ */ jsx(
38077
+ "div",
38078
+ {
38079
+ "data-testid": "hourly-output-tooltip",
38080
+ className: "p-3 -m-3 pointer-events-auto transition-opacity duration-200",
38081
+ style: { cursor: "default", opacity: data2 ? 1 : 0 },
38082
+ onMouseEnter: () => {
38083
+ clearTooltipHoverTimeout();
38084
+ setIsTooltipHovered(true);
38085
+ setForceHideTooltip(false);
38086
+ },
38087
+ onMouseLeave: () => {
38088
+ scheduleInteractiveTooltipHide();
38089
+ },
38090
+ children: /* @__PURE__ */ jsxs("div", { className: "bg-white/95 backdrop-blur-md border border-slate-200/60 shadow-xl shadow-slate-200/40 rounded-xl p-4 min-w-[240px] text-slate-700 pointer-events-auto", children: [
38091
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4 pb-3 border-b border-slate-100", children: [
38092
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-slate-900 text-sm tracking-tight", children: data2.timeRange }),
38093
+ onAiSummaryClick && /* @__PURE__ */ jsxs(
38094
+ "button",
38095
+ {
38096
+ onClick: (e) => {
38097
+ e.stopPropagation();
38098
+ onAiSummaryClick(clickPayload);
38099
+ },
38100
+ className: "flex items-center gap-1 px-2 py-1 -mr-1 rounded-md border border-slate-200 bg-white hover:bg-slate-50 text-[11px] font-medium text-slate-600 shadow-sm transition-colors",
38101
+ children: [
38102
+ /* @__PURE__ */ jsx(SparklesIcon, { className: "w-3.5 h-3.5" }),
38103
+ "Ask AI"
38104
+ ]
38105
+ }
38106
+ )
38107
+ ] }),
38108
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
38109
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
38110
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-slate-500 font-medium tracking-wide", children: "Output" }),
38111
+ /* @__PURE__ */ jsxs("span", { className: "font-bold text-slate-900 text-sm", children: [
38112
+ Math.round(data2.output),
38113
+ " ",
38114
+ /* @__PURE__ */ jsx("span", { className: "text-slate-400 font-normal text-xs ml-0.5", children: "units" })
38115
+ ] })
38116
+ ] }),
38117
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
38118
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-slate-500 font-medium tracking-wide", children: "Target" }),
38119
+ /* @__PURE__ */ jsxs("span", { className: "font-bold text-slate-700 text-sm", children: [
38120
+ Math.round(data2.target),
38121
+ " ",
38122
+ /* @__PURE__ */ jsx("span", { className: "text-slate-400 font-normal text-xs ml-0.5", children: "units" })
38123
+ ] })
38124
+ ] }),
38125
+ showIdleTime && data2.idleMinutes > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
38126
+ /* @__PURE__ */ jsx("div", { className: "pt-3 mt-3 border-t border-slate-100", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
38127
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-slate-500 font-medium tracking-wide", children: "Idle Time" }),
38128
+ /* @__PURE__ */ jsxs("span", { className: "font-bold text-orange-600 text-sm flex items-center gap-1.5", children: [
38129
+ /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-orange-500 shadow-[0_0_6px_rgba(249,115,22,0.6)] animate-pulse" }),
38130
+ data2.idleMinutes,
38131
+ " ",
38132
+ /* @__PURE__ */ jsx("span", { className: "text-orange-500/70 font-normal text-xs ml-0.5", children: "min" })
38133
+ ] })
38134
+ ] }) }),
38135
+ idlePeriods.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-3 bg-slate-50/80 rounded-lg p-3 border border-slate-100/50", children: [
38136
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-slate-400 text-[10px] mb-2.5 uppercase tracking-wider", children: "Idle Periods" }),
38137
+ /* @__PURE__ */ jsx("div", { className: "space-y-2.5 max-h-32 overflow-y-auto pr-1 custom-scrollbar", children: idlePeriods.map((period, index) => {
38138
+ return /* @__PURE__ */ jsxs(
38139
+ "div",
38140
+ {
38141
+ className: "flex items-start gap-2.5 text-xs",
38142
+ children: [
38143
+ /* @__PURE__ */ jsx("div", { className: "mt-[5px] w-1.5 h-1.5 bg-orange-400 rounded-full flex-shrink-0 shadow-[0_0_4px_rgba(251,146,60,0.5)]" }),
38144
+ /* @__PURE__ */ jsx("span", { className: "text-slate-700 font-medium tracking-tight", children: period.duration === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
38145
+ period.startTime,
38146
+ " ",
38147
+ /* @__PURE__ */ jsxs("span", { className: "text-slate-400 font-normal ml-1", children: [
38148
+ "(",
38149
+ period.duration,
38150
+ "m)"
38151
+ ] })
38152
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
38153
+ period.startTime,
38154
+ " ",
38155
+ /* @__PURE__ */ jsx("span", { className: "text-slate-400 mx-0.5", children: "\u2192" }),
38156
+ " ",
38157
+ period.endTime,
38158
+ " ",
38159
+ /* @__PURE__ */ jsxs("span", { className: "text-slate-400 font-normal ml-1", children: [
38160
+ "(",
38161
+ period.duration,
38162
+ "m)"
38163
+ ] })
38164
+ ] }) })
38165
+ ]
38166
+ },
38167
+ index
38168
+ );
38169
+ }) })
38170
+ ] })
38171
+ ] }),
38172
+ onWatchClipsClick && /* @__PURE__ */ jsx("div", { className: "pt-3 mt-3 border-t border-slate-100 flex items-center", children: /* @__PURE__ */ jsxs(
38173
+ "button",
38174
+ {
38175
+ onClick: (e) => {
38176
+ e.stopPropagation();
38177
+ onWatchClipsClick(clickPayload);
38178
+ },
38179
+ className: "w-full rounded-md border border-slate-200 bg-white hover:bg-slate-50 px-2 py-1.5 text-xs font-semibold text-slate-700 transition-colors flex items-center justify-center gap-1.5 shadow-sm",
38180
+ children: [
38181
+ /* @__PURE__ */ jsx(PlayCircleIcon, { className: "w-4 h-4 text-blue-500" }),
38182
+ "Watch Clips"
38183
+ ]
38184
+ }
38185
+ ) }),
38186
+ onHourClick && !onWatchClipsClick && !onAiSummaryClick && /* @__PURE__ */ jsx("div", { className: "pt-3 mt-3 border-t border-slate-100", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-blue-100 bg-blue-50/70 px-3 py-2 text-xs font-semibold text-blue-700 text-center", children: "Click to inspect hour" }) })
38187
+ ] })
38188
+ ] })
38189
+ }
38190
+ );
38220
38191
  },
38221
- `cell-${index}`
38222
- )),
38223
- /* @__PURE__ */ jsx(
38224
- LabelList,
38225
- {
38226
- dataKey: "originalOutput",
38227
- position: "top",
38228
- content: (props) => {
38229
- const { x, y, width, value, payload } = props;
38230
- const actualValue = payload?.originalOutput || value;
38231
- if (!actualValue || actualValue === 0) return null;
38232
- return /* @__PURE__ */ jsx(
38233
- "text",
38234
- {
38235
- x: x + width / 2,
38236
- y: y - 8,
38237
- textAnchor: "middle",
38238
- fontSize: "12",
38239
- fontWeight: "600",
38240
- fill: "#374151",
38241
- style: {
38242
- opacity: 1,
38243
- pointerEvents: "none",
38244
- transition: "none"
38245
- },
38246
- children: Math.round(actualValue)
38192
+ animationDuration: 200
38193
+ }
38194
+ ),
38195
+ /* @__PURE__ */ jsx(Customized, { component: renderTargetLine }),
38196
+ /* @__PURE__ */ jsx(Customized, { component: renderSkuTimelineRail }),
38197
+ /* @__PURE__ */ jsxs(
38198
+ Bar,
38199
+ {
38200
+ xAxisId: "default",
38201
+ dataKey: "output",
38202
+ yAxisId: "default",
38203
+ maxBarSize: 35,
38204
+ radius: [10, 10, 0, 0],
38205
+ isAnimationActive: false,
38206
+ children: [
38207
+ chartData.map((entry, index) => /* @__PURE__ */ jsx(
38208
+ Cell,
38209
+ {
38210
+ fill: entry.color,
38211
+ stroke: entry.isSelected ? "#0f172a" : "transparent",
38212
+ strokeWidth: entry.isSelected ? 2 : 0,
38213
+ style: {
38214
+ filter: entry.isHighlighted || entry.isSelected ? "drop-shadow(0 4px 6px rgba(0, 0, 0, 0.12)) brightness(1.05)" : "brightness(1)",
38215
+ transform: entry.isHighlighted || entry.isSelected ? "translateY(-4px)" : "translateY(0)",
38216
+ opacity: entry.isDimmed ? 0.4 : 1,
38217
+ transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
38218
+ cursor: onHourClick || onWatchClipsClick || onAiSummaryClick ? "pointer" : "default"
38219
+ },
38220
+ onMouseEnter: (e) => {
38221
+ const target = e.target;
38222
+ target.style.filter = "drop-shadow(0 4px 6px rgba(0, 0, 0, 0.12)) brightness(1.05)";
38223
+ target.style.transform = "translateY(-4px)";
38224
+ target.style.opacity = "1";
38225
+ },
38226
+ onMouseLeave: (e) => {
38227
+ const target = e.target;
38228
+ target.style.filter = entry.isHighlighted || entry.isSelected ? "drop-shadow(0 4px 6px rgba(0, 0, 0, 0.12)) brightness(1.05)" : "brightness(1)";
38229
+ target.style.transform = entry.isHighlighted || entry.isSelected ? "translateY(-4px)" : "translateY(0)";
38230
+ target.style.opacity = entry.isDimmed ? "0.4" : "1";
38231
+ },
38232
+ onClick: () => {
38233
+ if (!onHourClick && !onWatchClipsClick && !onAiSummaryClick) return;
38234
+ const { startTime, endTime } = buildHourClipFilterWindow({
38235
+ shiftStart,
38236
+ shiftEnd,
38237
+ hourIndex: entry.hourIndex,
38238
+ slotCount: SHIFT_DURATION
38239
+ });
38240
+ const payload = {
38241
+ hourIndex: entry.hourIndex,
38242
+ timeRange: entry.timeRange,
38243
+ startTime,
38244
+ endTime,
38245
+ output: Math.round(entry.originalOutput || 0),
38246
+ target: entry.target,
38247
+ status: entry.status
38248
+ };
38249
+ if (onHourClick) onHourClick(payload);
38247
38250
  }
38248
- );
38249
- }
38250
- }
38251
- )
38252
- ]
38253
- }
38254
- ),
38255
- IdleBar,
38256
- /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
38257
- "pattern",
38258
- {
38259
- id: "idlePattern",
38260
- patternUnits: "userSpaceOnUse",
38261
- width: "4",
38262
- height: "4",
38263
- children: [
38264
- /* @__PURE__ */ jsx("rect", { width: "4", height: "4", fill: "#4b5563", opacity: "0.6" }),
38265
- /* @__PURE__ */ jsx(
38266
- "path",
38267
- {
38268
- d: "M 0,4 l 4,-4 M -1,1 l 2,-2 M 3,5 l 2,-2",
38269
- stroke: "#374151",
38270
- strokeWidth: "0.8",
38271
- opacity: "0.8"
38272
- }
38273
- )
38274
- ]
38275
- }
38276
- ) })
38277
- ]
38278
- }
38279
- ) }),
38280
- hoveredSkuRailLabel && /* @__PURE__ */ jsx(
38281
- "div",
38282
- {
38283
- className: "absolute z-50 pointer-events-none transform -translate-x-1/2 -translate-y-full transition-opacity duration-200",
38284
- style: {
38285
- left: hoveredSkuRailLabel.centerX,
38286
- top: hoveredSkuRailLabel.railY - 12
38287
- },
38288
- children: /* @__PURE__ */ jsxs("div", { className: "bg-white/95 backdrop-blur-md border border-slate-200/80 shadow-xl shadow-slate-200/50 rounded-lg px-3 py-2 flex flex-col min-w-[100px] max-w-[280px]", children: [
38289
- /* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold tracking-wider text-blue-500 uppercase leading-none mb-1", children: "SKU" }),
38290
- /* @__PURE__ */ jsx("span", { className: "text-[13px] font-semibold text-slate-800 whitespace-normal break-words leading-snug", children: hoveredSkuRailLabel.label })
38291
- ] })
38292
- }
38293
- )
38294
- ] }) : /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center bg-gray-50 rounded-lg", children: /* @__PURE__ */ jsx("div", { className: "text-gray-500 text-sm", children: "Loading chart..." }) }),
38251
+ },
38252
+ `cell-${index}`
38253
+ )),
38254
+ /* @__PURE__ */ jsx(
38255
+ LabelList,
38256
+ {
38257
+ dataKey: "originalOutput",
38258
+ position: "top",
38259
+ content: (props) => {
38260
+ const { x, y, width, value, payload } = props;
38261
+ const actualValue = payload?.originalOutput || value;
38262
+ if (!actualValue || actualValue === 0) return null;
38263
+ return /* @__PURE__ */ jsx(
38264
+ "text",
38265
+ {
38266
+ x: x + width / 2,
38267
+ y: y - 8,
38268
+ textAnchor: "middle",
38269
+ fontSize: "12",
38270
+ fontWeight: "600",
38271
+ fill: "#374151",
38272
+ style: {
38273
+ opacity: 1,
38274
+ pointerEvents: "none",
38275
+ transition: "none"
38276
+ },
38277
+ children: Math.round(actualValue)
38278
+ }
38279
+ );
38280
+ }
38281
+ }
38282
+ )
38283
+ ]
38284
+ }
38285
+ ),
38286
+ IdleBar,
38287
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
38288
+ "pattern",
38289
+ {
38290
+ id: "idlePattern",
38291
+ patternUnits: "userSpaceOnUse",
38292
+ width: "4",
38293
+ height: "4",
38294
+ children: [
38295
+ /* @__PURE__ */ jsx("rect", { width: "4", height: "4", fill: "#4b5563", opacity: "0.6" }),
38296
+ /* @__PURE__ */ jsx(
38297
+ "path",
38298
+ {
38299
+ d: "M 0,4 l 4,-4 M -1,1 l 2,-2 M 3,5 l 2,-2",
38300
+ stroke: "#374151",
38301
+ strokeWidth: "0.8",
38302
+ opacity: "0.8"
38303
+ }
38304
+ )
38305
+ ]
38306
+ }
38307
+ ) })
38308
+ ]
38309
+ }
38310
+ ) }),
38311
+ hoveredSkuRailLabel && /* @__PURE__ */ jsx(
38312
+ "div",
38313
+ {
38314
+ className: "absolute z-50 pointer-events-none transform -translate-x-1/2 -translate-y-full transition-opacity duration-200",
38315
+ style: {
38316
+ left: hoveredSkuRailLabel.centerX,
38317
+ top: hoveredSkuRailLabel.railY - 12
38318
+ },
38319
+ children: /* @__PURE__ */ jsxs("div", { className: "bg-white/95 backdrop-blur-md border border-slate-200/80 shadow-xl shadow-slate-200/50 rounded-lg px-3 py-2 flex flex-col min-w-[100px] max-w-[280px]", children: [
38320
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold tracking-wider text-blue-500 uppercase leading-none mb-1", children: "SKU" }),
38321
+ /* @__PURE__ */ jsx("span", { className: "text-[13px] font-semibold text-slate-800 whitespace-normal break-words leading-snug", children: hoveredSkuRailLabel.label })
38322
+ ] })
38323
+ }
38324
+ )
38325
+ ]
38326
+ }
38327
+ ) : /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center bg-gray-50 rounded-lg", children: /* @__PURE__ */ jsx("div", { className: "text-gray-500 text-sm", children: "Loading chart..." }) }),
38295
38328
  /* @__PURE__ */ jsx("div", { className: "flex-none pt-2", children: renderLegend() })
38296
38329
  ]
38297
38330
  }
38298
38331
  );
38299
38332
  };
38300
- var HourlyOutputChart = React148__default.memo(
38333
+ var HourlyOutputChart = React125__default.memo(
38301
38334
  HourlyOutputChartComponent,
38302
38335
  (prevProps, nextProps) => {
38303
38336
  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) {
@@ -38859,7 +38892,7 @@ function getTrendArrowAndColor(trend) {
38859
38892
  return { arrow: "\u2192", color: "text-gray-400" };
38860
38893
  }
38861
38894
  }
38862
- var VideoCard = React148__default.memo(({
38895
+ var VideoCard = React125__default.memo(({
38863
38896
  workspace,
38864
38897
  hlsUrl,
38865
38898
  shouldPlay,
@@ -38913,8 +38946,8 @@ var VideoCard = React148__default.memo(({
38913
38946
  const efficiencyOverlayClass = videoGridColorState === "green" ? "bg-[#00D654]/25" : videoGridColorState === "blue" ? "bg-[#0EA5E9]/30" : videoGridColorState === "yellow" ? "bg-[#FFD700]/30" : videoGridColorState === "red" ? "bg-[#FF2D0A]/30" : "bg-transparent";
38914
38947
  const efficiencyBarClass = videoGridColorState === "green" ? "bg-[#00AB45]" : videoGridColorState === "blue" ? "bg-[#0EA5E9]" : videoGridColorState === "yellow" ? "bg-[#FFB020]" : videoGridColorState === "red" ? "bg-[#E34329]" : "bg-gray-500/70";
38915
38948
  const efficiencyStatus = videoGridColorState === "green" ? "High" : videoGridColorState === "blue" ? "Best" : videoGridColorState === "yellow" ? "Medium" : videoGridColorState === "red" ? "Low" : "Neutral";
38916
- const worstMarkerClassName = compact ? "left-1.5 top-1.5 gap-1.5 px-2 py-1 text-[11px]" : "left-2 top-2 gap-2 px-3 py-1.5 text-xs";
38917
- const statusBadgesPositionClass = isWorstPerformance ? compact ? "top-8 left-1.5 gap-1" : "top-10 left-2 gap-1.5" : compact ? "top-1.5 left-1.5 gap-1" : "top-2 left-2 gap-1.5";
38949
+ const worstMarkerClassName = compact ? "left-1 top-1 sm:left-1.5 sm:top-1.5 gap-1 sm:gap-1.5 p-1 sm:px-2 sm:py-1 text-[10px] sm:text-[11px]" : "left-1.5 top-1.5 sm:left-2 sm:top-2 gap-1 sm:gap-2 px-1.5 sm:px-3 py-0.5 sm:py-1.5 text-[10px] sm:text-xs";
38950
+ const statusBadgesPositionClass = isWorstPerformance ? compact ? "top-6 sm:top-8 left-1 sm:left-1.5 gap-1" : "top-7 sm:top-10 left-1.5 sm:left-2 gap-1 sm:gap-1.5" : compact ? "top-1 sm:top-1.5 left-1 sm:left-1.5 gap-1" : "top-1.5 sm:top-2 left-1.5 sm:left-2 gap-1 sm:gap-1.5";
38918
38951
  const trendInfo = workspace.trend !== void 0 ? getTrendArrowAndColor(workspace.trend) : null;
38919
38952
  const handleClick = useCallback(() => {
38920
38953
  trackCoreEvent("Workspace Card Clicked", {
@@ -38950,8 +38983,8 @@ var VideoCard = React148__default.memo(({
38950
38983
  children: [
38951
38984
  /* @__PURE__ */ jsxs("div", { className: "relative w-full h-full overflow-hidden bg-black", children: [
38952
38985
  /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-black z-0", children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse flex flex-col items-center", children: [
38953
- /* @__PURE__ */ jsx(Camera, { className: `w-5 h-5 sm:${compact ? "w-4 h-4" : "w-6 h-6"} text-gray-500` }),
38954
- /* @__PURE__ */ jsx("span", { className: `text-[11px] sm:${compact ? "text-[10px]" : "text-xs"} text-gray-500 mt-1`, children: "Loading..." })
38986
+ /* @__PURE__ */ jsx(Camera, { className: `w-5 h-5 ${compact ? "sm:w-4 sm:h-4" : "sm:w-6 sm:h-6"} text-gray-500` }),
38987
+ /* @__PURE__ */ jsx("span", { className: `text-[11px] ${compact ? "sm:text-[10px]" : "sm:text-xs"} text-gray-500 mt-1`, children: "Loading..." })
38955
38988
  ] }) }),
38956
38989
  /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 z-10", children: [
38957
38990
  /* @__PURE__ */ jsx(
@@ -39013,7 +39046,7 @@ var VideoCard = React148__default.memo(({
39013
39046
  "data-testid": `video-card-status-badge-${badge.kind}`,
39014
39047
  "aria-label": tooltipText,
39015
39048
  "aria-describedby": tooltipId,
39016
- className: `group relative inline-flex shrink-0 items-center justify-center rounded-full bg-slate-950/70 border-2 shadow-[0_3px_10px_rgba(0,0,0,0.34),inset_0_0_0_1px_rgba(255,255,255,0.18)] ${compact ? "h-10 w-10" : "h-11 w-11"}`,
39049
+ className: `group relative inline-flex shrink-0 items-center justify-center rounded-full bg-slate-950/70 border-2 shadow-[0_3px_10px_rgba(0,0,0,0.34),inset_0_0_0_1px_rgba(255,255,255,0.18)] ${compact ? "h-7 w-7 sm:h-10 sm:w-10" : "h-8 w-8 sm:h-11 sm:w-11"}`,
39017
39050
  style: {
39018
39051
  borderColor: presentation.hex
39019
39052
  },
@@ -39022,7 +39055,7 @@ var VideoCard = React148__default.memo(({
39022
39055
  Icon2,
39023
39056
  {
39024
39057
  "aria-hidden": "true",
39025
- className: `${compact ? "h-5 w-5" : "h-6 w-6"} text-white`,
39058
+ className: `${compact ? "h-4 w-4 sm:h-5 sm:w-5" : "h-4 w-4 sm:h-6 sm:w-6"} text-white`,
39026
39059
  strokeWidth: 2.4
39027
39060
  }
39028
39061
  ),
@@ -39050,10 +39083,10 @@ var VideoCard = React148__default.memo(({
39050
39083
  "div",
39051
39084
  {
39052
39085
  "data-testid": "video-card-worst-performance-marker",
39053
- className: `pointer-events-none absolute z-[65] inline-flex items-center rounded-md bg-[#1A0B09]/95 border border-[#E34329]/60 font-semibold tracking-wide text-white shadow-xl ${worstMarkerClassName}`,
39086
+ className: `pointer-events-none absolute z-[65] inline-flex items-center rounded-sm sm:rounded-md bg-[#1A0B09]/95 border border-[#E34329]/60 font-semibold tracking-wide text-white shadow-xl max-w-[calc(100%-8px)] sm:max-w-[calc(100%-16px)] ${worstMarkerClassName}`,
39054
39087
  children: [
39055
- /* @__PURE__ */ jsx(AlertTriangle, { className: `${compact ? "h-3.5 w-3.5" : "h-4 w-4"} text-[#E34329]`, "aria-hidden": "true" }),
39056
- /* @__PURE__ */ jsx("span", { children: "Overall Underperformer" })
39088
+ /* @__PURE__ */ jsx(AlertTriangle, { className: `${compact ? "h-3 w-3 sm:h-3.5 sm:w-3.5" : "h-3.5 w-3.5 sm:h-4 sm:w-4"} shrink-0 text-[#E34329]`, "aria-hidden": "true" }),
39089
+ /* @__PURE__ */ jsx("span", { className: `truncate leading-tight min-w-0 ${compact ? "hidden sm:block" : ""}`, children: "Overall Underperformer" })
39057
39090
  ]
39058
39091
  }
39059
39092
  ),
@@ -39066,10 +39099,10 @@ var VideoCard = React148__default.memo(({
39066
39099
  }
39067
39100
  ) })
39068
39101
  ] }),
39069
- /* @__PURE__ */ jsxs("div", { className: `absolute bottom-0 left-0 right-0 bg-black bg-opacity-60 p-1.5 sm:${compact ? "p-1" : "p-1.5"} flex min-w-0 justify-between items-center gap-1 z-10`, children: [
39102
+ /* @__PURE__ */ jsxs("div", { className: `absolute bottom-0 left-0 right-0 bg-black bg-opacity-60 p-1.5 ${compact ? "sm:p-1" : "sm:p-1.5"} flex min-w-0 justify-between items-center gap-1 z-10`, children: [
39070
39103
  /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-1.5", children: [
39071
39104
  /* @__PURE__ */ jsx(Camera, { size: compact ? 10 : 12, className: "shrink-0 text-white" }),
39072
- /* @__PURE__ */ jsx("p", { className: `min-w-0 truncate text-white text-[11px] sm:${compact ? "text-[10px]" : "text-xs"} font-medium tracking-wide`, children: workspaceDisplayName })
39105
+ /* @__PURE__ */ jsx("p", { className: `min-w-0 truncate text-white text-[11px] ${compact ? "sm:text-[10px]" : "sm:text-xs"} font-medium tracking-wide`, children: workspaceDisplayName })
39073
39106
  ] }),
39074
39107
  /* @__PURE__ */ jsxs("div", { className: `flex shrink-0 items-center ${compact ? "gap-1" : "gap-1.5"}`, children: [
39075
39108
  trendInfo && /* @__PURE__ */ jsx(
@@ -39086,7 +39119,7 @@ var VideoCard = React148__default.memo(({
39086
39119
  className: `${compact ? "w-1 h-1" : "w-1.5 h-1.5"} rounded-full ${showOffline ? "bg-red-500" : "bg-green-500"}`
39087
39120
  }
39088
39121
  ),
39089
- /* @__PURE__ */ jsx("span", { className: `text-white text-[11px] sm:${compact ? "text-[10px]" : "text-xs"}`, children: showOffline ? "Offline" : "Live" })
39122
+ /* @__PURE__ */ jsx("span", { className: `text-white text-[11px] ${compact ? "sm:text-[10px]" : "sm:text-xs"}`, children: showOffline ? "Offline" : "Live" })
39090
39123
  ] })
39091
39124
  ] })
39092
39125
  ]
@@ -39147,7 +39180,7 @@ var hasRecentHealthSignal = (lastHeartbeat) => {
39147
39180
  if (!Number.isFinite(heartbeatMs)) return false;
39148
39181
  return Date.now() - heartbeatMs <= RECENT_HEALTH_SIGNAL_MS;
39149
39182
  };
39150
- var VideoGridView = React148__default.memo(({
39183
+ var VideoGridView = React125__default.memo(({
39151
39184
  workspaces,
39152
39185
  blueComparisonWorkspaces,
39153
39186
  worstPerformanceWorkspaceIds = [],
@@ -39655,7 +39688,7 @@ var VideoGridView = React148__default.memo(({
39655
39688
  ) });
39656
39689
  });
39657
39690
  VideoGridView.displayName = "VideoGridView";
39658
- var MapGridView = React148__default.memo(({
39691
+ var MapGridView = React125__default.memo(({
39659
39692
  workspaces,
39660
39693
  className = "",
39661
39694
  displayNames = {},
@@ -39876,13 +39909,13 @@ var WorkspaceMetricCardsImpl = ({
39876
39909
  liveSkuId
39877
39910
  }) => {
39878
39911
  const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
39879
- const activeSku = React148__default.useMemo(() => {
39912
+ const activeSku = React125__default.useMemo(() => {
39880
39913
  if (skuAware && activeSkuId && skuBreakdown) {
39881
39914
  return skuBreakdown.find((s) => s.sku_id === activeSkuId);
39882
39915
  }
39883
39916
  return null;
39884
39917
  }, [skuAware, activeSkuId, skuBreakdown]);
39885
- const displaySku = React148__default.useMemo(() => {
39918
+ const displaySku = React125__default.useMemo(() => {
39886
39919
  if (activeSku) return activeSku;
39887
39920
  if (skuAware && !activeSkuId && liveSkuId && skuBreakdown) {
39888
39921
  return skuBreakdown.find((s) => s.sku_id === liveSkuId) ?? null;
@@ -40536,7 +40569,7 @@ var UptimeLineChartComponent = ({ points, className = "" }) => {
40536
40569
  )
40537
40570
  ] }) }) });
40538
40571
  };
40539
- var UptimeLineChart = React148__default.memo(UptimeLineChartComponent);
40572
+ var UptimeLineChart = React125__default.memo(UptimeLineChartComponent);
40540
40573
  var getTimeFromTimeString = (timeStr) => {
40541
40574
  if (!timeStr) {
40542
40575
  return { hour: 0, minute: 0, decimalHour: 0 };
@@ -40560,10 +40593,10 @@ var HourlyUptimeChartComponent = ({
40560
40593
  shiftBreaks,
40561
40594
  className = ""
40562
40595
  }) => {
40563
- const containerRef = React148__default.useRef(null);
40564
- const [containerReady, setContainerReady] = React148__default.useState(false);
40565
- const [containerWidth, setContainerWidth] = React148__default.useState(0);
40566
- const uptimeSeries = React148__default.useMemo(() => buildUptimeSeries({
40596
+ const containerRef = React125__default.useRef(null);
40597
+ const [containerReady, setContainerReady] = React125__default.useState(false);
40598
+ const [containerWidth, setContainerWidth] = React125__default.useState(0);
40599
+ const uptimeSeries = React125__default.useMemo(() => buildUptimeSeries({
40567
40600
  idleTimeHourly,
40568
40601
  shiftStart,
40569
40602
  shiftEnd,
@@ -40573,11 +40606,11 @@ var HourlyUptimeChartComponent = ({
40573
40606
  shiftBreaks
40574
40607
  }), [idleTimeHourly, shiftStart, shiftEnd, shiftDate, timezone, elapsedMinutes, shiftBreaks]);
40575
40608
  const hasAggregateData = Boolean(hourlyAggregates && hourlyAggregates.length > 0);
40576
- const shiftStartTime = React148__default.useMemo(
40609
+ const shiftStartTime = React125__default.useMemo(
40577
40610
  () => getTimeFromTimeString(shiftStart),
40578
40611
  [shiftStart]
40579
40612
  );
40580
- const { shiftDuration, shiftEndTime } = React148__default.useMemo(() => {
40613
+ const { shiftDuration, shiftEndTime } = React125__default.useMemo(() => {
40581
40614
  if (!shiftEnd) {
40582
40615
  const fallbackHours = uptimeSeries.shiftMinutes > 0 ? Math.ceil(uptimeSeries.shiftMinutes / 60) : 0;
40583
40616
  return { shiftDuration: fallbackHours, shiftEndTime: null };
@@ -40591,7 +40624,7 @@ var HourlyUptimeChartComponent = ({
40591
40624
  const hourCount = hasPartial ? Math.ceil(duration) : Math.round(duration);
40592
40625
  return { shiftDuration: hourCount, shiftEndTime: endTime };
40593
40626
  }, [shiftEnd, shiftStartTime.decimalHour, uptimeSeries.shiftMinutes]);
40594
- const formatHour = React148__default.useCallback((hourIndex) => {
40627
+ const formatHour = React125__default.useCallback((hourIndex) => {
40595
40628
  const isLastHour = hourIndex === shiftDuration - 1;
40596
40629
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
40597
40630
  const startHour = Math.floor(startDecimalHour) % 24;
@@ -40616,7 +40649,7 @@ var HourlyUptimeChartComponent = ({
40616
40649
  };
40617
40650
  return `${formatTime5(startHour, startMinute)}-${formatTime5(endHour, endMinute)}`;
40618
40651
  }, [shiftDuration, shiftStartTime.decimalHour, shiftEndTime]);
40619
- const formatTimeRange2 = React148__default.useCallback((hourIndex) => {
40652
+ const formatTimeRange2 = React125__default.useCallback((hourIndex) => {
40620
40653
  const isLastHour = hourIndex === shiftDuration - 1;
40621
40654
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
40622
40655
  const startHour = Math.floor(startDecimalHour) % 24;
@@ -40638,7 +40671,7 @@ var HourlyUptimeChartComponent = ({
40638
40671
  };
40639
40672
  return `${formatTime5(startHour, startMinute)} - ${formatTime5(endHour, endMinute)}`;
40640
40673
  }, [shiftDuration, shiftStartTime.decimalHour, shiftEndTime]);
40641
- const chartData = React148__default.useMemo(() => {
40674
+ const chartData = React125__default.useMemo(() => {
40642
40675
  if (shiftDuration <= 0) return [];
40643
40676
  if (hasAggregateData) {
40644
40677
  return hourlyAggregates.map((entry, hourIndex) => ({
@@ -40680,7 +40713,7 @@ var HourlyUptimeChartComponent = ({
40680
40713
  }, [hasAggregateData, hourlyAggregates, uptimeSeries.points, uptimeSeries.elapsedMinutes, uptimeSeries.shiftMinutes, shiftDuration, formatHour, formatTimeRange2]);
40681
40714
  const maxYValue = 100;
40682
40715
  const yAxisTicks = [0, 25, 50, 75, 100];
40683
- React148__default.useEffect(() => {
40716
+ React125__default.useEffect(() => {
40684
40717
  const checkContainerDimensions = () => {
40685
40718
  if (containerRef.current) {
40686
40719
  const rect = containerRef.current.getBoundingClientRect();
@@ -40706,7 +40739,7 @@ var HourlyUptimeChartComponent = ({
40706
40739
  clearTimeout(fallbackTimeout);
40707
40740
  };
40708
40741
  }, []);
40709
- const xAxisConfig = React148__default.useMemo(() => {
40742
+ const xAxisConfig = React125__default.useMemo(() => {
40710
40743
  if (containerWidth >= 960) {
40711
40744
  return { interval: 0, angle: -45, height: 92, tickFont: 10, tickMargin: 12, labelMode: "full" };
40712
40745
  }
@@ -40715,7 +40748,7 @@ var HourlyUptimeChartComponent = ({
40715
40748
  }
40716
40749
  return { interval: 0, angle: -30, height: 64, tickFont: 9, tickMargin: 6, labelMode: "start" };
40717
40750
  }, [containerWidth]);
40718
- const formatXAxisTick = React148__default.useCallback((raw) => {
40751
+ const formatXAxisTick = React125__default.useCallback((raw) => {
40719
40752
  const label = typeof raw === "string" ? raw : String(raw);
40720
40753
  if (xAxisConfig.labelMode === "full") return label;
40721
40754
  const parts = label.split("-");
@@ -40921,7 +40954,7 @@ var HourlyUptimeChartComponent = ({
40921
40954
  }
40922
40955
  );
40923
40956
  };
40924
- var HourlyUptimeChart = React148__default.memo(HourlyUptimeChartComponent);
40957
+ var HourlyUptimeChart = React125__default.memo(HourlyUptimeChartComponent);
40925
40958
  var DEFAULT_COLORS2 = ["#00AB45", "#ef4444"];
40926
40959
  var UptimeDonutChartComponent = ({
40927
40960
  data,
@@ -40991,7 +41024,7 @@ var UptimeDonutChartComponent = ({
40991
41024
  ] }) })
40992
41025
  ] }) });
40993
41026
  };
40994
- var UptimeDonutChart = React148__default.memo(UptimeDonutChartComponent);
41027
+ var UptimeDonutChart = React125__default.memo(UptimeDonutChartComponent);
40995
41028
  UptimeDonutChart.displayName = "UptimeDonutChart";
40996
41029
  var TrendIcon = ({ trend }) => {
40997
41030
  if (trend === "up") {
@@ -41112,7 +41145,7 @@ var EmptyStateMessage = ({
41112
41145
  iconClassName
41113
41146
  }) => {
41114
41147
  let IconContent = null;
41115
- if (React148__default.isValidElement(iconType)) {
41148
+ if (React125__default.isValidElement(iconType)) {
41116
41149
  IconContent = iconType;
41117
41150
  } else if (typeof iconType === "string") {
41118
41151
  const MappedIcon = IconMap[iconType];
@@ -41883,7 +41916,31 @@ var formatOutputLabel = (bin) => {
41883
41916
  if (actualOutput === null) {
41884
41917
  return "";
41885
41918
  }
41886
- return `Output ${formatCompactNumber(actualOutput)}`;
41919
+ const expectedOutput = getExpectedOutputUnits(bin);
41920
+ return expectedOutput !== null ? `Output ${formatCompactNumber(actualOutput)}/${formatCompactNumber(expectedOutput)}` : `Output ${formatCompactNumber(actualOutput)}`;
41921
+ };
41922
+ var getTooltipOutputParts = (outputLabel, fallbackLabel) => {
41923
+ if (outputLabel.startsWith("Output ")) {
41924
+ const [actual, expected] = outputLabel.slice("Output ".length).split("/");
41925
+ return {
41926
+ label: "Output",
41927
+ actual: actual?.trim() || "",
41928
+ expected: expected?.trim()
41929
+ };
41930
+ }
41931
+ return {
41932
+ label: "Efficiency",
41933
+ actual: fallbackLabel,
41934
+ fallbackValue: fallbackLabel
41935
+ };
41936
+ };
41937
+ var getExpectedOutputUnits = (bin) => {
41938
+ const targetPpm = bin.target_ppm;
41939
+ const durationSeconds = bin.duration_seconds;
41940
+ if (typeof targetPpm !== "number" || !Number.isFinite(targetPpm) || typeof durationSeconds !== "number" || !Number.isFinite(durationSeconds) || durationSeconds <= 0) {
41941
+ return null;
41942
+ }
41943
+ return targetPpm * durationSeconds / 60;
41887
41944
  };
41888
41945
  var VideoControls = ({
41889
41946
  isPlaying,
@@ -41912,11 +41969,12 @@ var VideoControls = ({
41912
41969
  const [dragTime, setDragTime] = useState(0);
41913
41970
  const [isHoveringProgressBar, setIsHoveringProgressBar] = useState(false);
41914
41971
  const [hoveredTimelineBin, setHoveredTimelineBin] = useState(null);
41972
+ const [tooltipAnchorPercent, setTooltipAnchorPercent] = useState(50);
41973
+ const [tooltipPointerPercent, setTooltipPointerPercent] = useState(50);
41915
41974
  const [showSpeedMenu, setShowSpeedMenu] = useState(false);
41916
41975
  const speedMenuRef = useRef(null);
41917
41976
  const progressTrackRef = useRef(null);
41918
41977
  const activePointerIdRef = useRef(null);
41919
- const markerPointerJumpHandledRef = useRef(false);
41920
41978
  const progressColor = "#4b5563";
41921
41979
  const controlsVisible = showControls || controlsPinned;
41922
41980
  const isDraggingRef = useRef(false);
@@ -41940,43 +41998,6 @@ var VideoControls = ({
41940
41998
  isDraggingRef.current = false;
41941
41999
  onSeekEnd?.();
41942
42000
  };
41943
- const handleTimelineJump = useCallback((time2) => {
41944
- const nextTime = Math.min(Math.max(time2, 0), duration || time2);
41945
- const wasDragging = isDraggingRef.current;
41946
- activePointerIdRef.current = null;
41947
- setIsDragging(false);
41948
- isDraggingRef.current = false;
41949
- setDragTime(nextTime);
41950
- if (!wasDragging) {
41951
- onSeekStart?.();
41952
- }
41953
- onSeek(nextTime);
41954
- onSeekEnd?.();
41955
- }, [duration, onSeek, onSeekEnd, onSeekStart]);
41956
- const handleTimelineMarkerPointerDown = useCallback((e, time2) => {
41957
- e.preventDefault();
41958
- e.stopPropagation();
41959
- markerPointerJumpHandledRef.current = true;
41960
- handleTimelineJump(time2);
41961
- }, [handleTimelineJump]);
41962
- const handleTimelineMarkerMouseDown = useCallback((e, time2) => {
41963
- e.preventDefault();
41964
- e.stopPropagation();
41965
- if (markerPointerJumpHandledRef.current) {
41966
- return;
41967
- }
41968
- markerPointerJumpHandledRef.current = true;
41969
- handleTimelineJump(time2);
41970
- }, [handleTimelineJump]);
41971
- const handleTimelineMarkerClick = useCallback((e, time2) => {
41972
- e.preventDefault();
41973
- e.stopPropagation();
41974
- if (markerPointerJumpHandledRef.current) {
41975
- markerPointerJumpHandledRef.current = false;
41976
- return;
41977
- }
41978
- handleTimelineJump(time2);
41979
- }, [handleTimelineJump]);
41980
42001
  const updateTimeFromClientX = useCallback((clientX) => {
41981
42002
  if (!progressTrackRef.current) return;
41982
42003
  const rect = progressTrackRef.current.getBoundingClientRect();
@@ -42054,6 +42075,13 @@ var VideoControls = ({
42054
42075
  const clockLabel = formatTimelineClockTime(bin.start_time, timelineTimezone);
42055
42076
  const minuteExplanation = timelineExplanation?.minute_explanations?.find((explanation) => explanation.offset_seconds === offset || Boolean(explanation.start_time) && explanation.start_time === bin.start_time);
42056
42077
  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;
42078
+ const binOutputUnits = getBinOutputUnits(bin);
42079
+ const binEfficiency = typeof bin.efficiency_percent === "number" && Number.isFinite(bin.efficiency_percent) ? bin.efficiency_percent : null;
42080
+ const expectedOutputUnits = getExpectedOutputUnits({ ...bin, duration_seconds: clampedDuration });
42081
+ const isBelowExpectedOutput = binOutputUnits !== null && expectedOutputUnits !== null && expectedOutputUnits > 0 && binOutputUnits / expectedOutputUnits < 0.8;
42082
+ const fallbackTooltipReasonLabel = bin.is_idle === true && (binOutputUnits === null || binOutputUnits < 1) ? "Idle" : binOutputUnits === 0 || isBelowExpectedOutput || binOutputUnits !== null && binEfficiency !== null && binEfficiency < 80 ? "Low output" : void 0;
42083
+ const explanationTooltipReasonLabel = minuteExplanation && minuteExplanation.confidence !== "low" ? minuteExplanation.primary_driver === "idle" ? "Idle" : minuteExplanation.primary_driver === "micro_stoppage" ? "Gaps" : minuteExplanation.primary_driver === "slow_cycle" ? "Slow cycles" : minuteExplanation.primary_driver === "low_output" ? "Low output" : void 0 : void 0;
42084
+ const tooltipReasonLabel = explanationTooltipReasonLabel || fallbackTooltipReasonLabel;
42057
42085
  return {
42058
42086
  ...bin,
42059
42087
  offset_seconds: offset,
@@ -42063,97 +42091,155 @@ var VideoControls = ({
42063
42091
  clockLabel,
42064
42092
  efficiencyLabel: formatEfficiencyPercent(bin.efficiency_percent),
42065
42093
  outputLabel: formatOutputLabel({ ...bin, duration_seconds: clampedDuration }),
42066
- explanationLabel
42094
+ explanationLabel,
42095
+ tooltipReasonLabel
42067
42096
  };
42068
42097
  }).filter((bin) => Boolean(bin));
42069
42098
  }, [duration, timelineAnnotations, timelineExplanation, timelineTimezone]);
42070
42099
  const hasTimelineAnnotations = timelineBins.length > 0;
42071
- const worstMinuteMarkers = useMemo(() => {
42072
- 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) => ({
42073
- start_time: bin.start_time,
42074
- offset_seconds: bin.offset_seconds,
42075
- duration_seconds: bin.duration_seconds,
42076
- avg_flow_percent: bin.avg_flow_percent,
42077
- rank: index + 1
42078
- }));
42079
- 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);
42080
- return source.filter((marker) => typeof marker.offset_seconds === "number" && Number.isFinite(marker.offset_seconds)).slice(0, 3).map((marker, index) => {
42081
- const offset = Math.max(0, Math.min(duration, marker.offset_seconds));
42082
- const matchingBin = timelineBins.find((bin) => bin.offset_seconds === marker.offset_seconds || Boolean(marker.start_time) && bin.start_time === marker.start_time);
42083
- const markerDuration = "duration_seconds" in marker ? Number(marker.duration_seconds || 0) : 0;
42084
- const width = markerDuration > 0 ? markerDuration : Number(matchingBin?.duration_seconds || 0);
42085
- const centerOffset = Math.min(duration, offset + Math.max(0, width) / 2);
42100
+ const outputBars = useMemo(() => {
42101
+ if (!timelineBins.length || duration <= 0) {
42102
+ return [];
42103
+ }
42104
+ const binsWithOutput = timelineBins.map((bin) => {
42105
+ const outputUnits = getBinOutputUnits(bin);
42106
+ if (outputUnits === null) {
42107
+ return null;
42108
+ }
42109
+ return {
42110
+ bin,
42111
+ outputUnits,
42112
+ expectedOutputUnits: getExpectedOutputUnits(bin)
42113
+ };
42114
+ }).filter((item) => Boolean(item));
42115
+ if (!binsWithOutput.length) {
42116
+ return [];
42117
+ }
42118
+ const maxActualOutput = binsWithOutput.reduce((max, item) => Math.max(max, item.outputUnits), 0);
42119
+ return binsWithOutput.map(({ bin, outputUnits, expectedOutputUnits }) => {
42120
+ const hasExpected = expectedOutputUnits !== null && expectedOutputUnits > 0;
42121
+ const scale2 = hasExpected ? outputUnits / expectedOutputUnits : maxActualOutput > 0 ? outputUnits / maxActualOutput : 0;
42122
+ const isZeroOutput = outputUnits === 0;
42123
+ const isIdle = bin.is_idle === true && outputUnits < 1;
42124
+ const hasProductionDespiteIdle = bin.is_idle === true && outputUnits >= 1;
42125
+ const isLowOutput = hasProductionDespiteIdle || (typeof bin.efficiency_percent !== "number" || !Number.isFinite(bin.efficiency_percent)) && hasExpected && outputUnits < expectedOutputUnits || !isZeroOutput && typeof bin.efficiency_percent === "number" && Number.isFinite(bin.efficiency_percent) && bin.efficiency_percent < 80;
42086
42126
  return {
42087
- ...marker,
42088
- rank: "rank" in marker ? marker.rank : index + 1,
42089
- leftPercent: getPercentage(centerOffset, duration)
42127
+ id: `${bin.offset_seconds}-${bin.duration_seconds}`,
42128
+ leftPercent: bin.leftPercent,
42129
+ widthPercent: bin.widthPercent,
42130
+ heightPercent: isZeroOutput ? 18 : Math.max(8, Math.min(scale2, 1) * 100),
42131
+ tone: isIdle ? "idle" : isZeroOutput ? "zero" : isLowOutput ? "low" : "normal",
42132
+ outputUnits
42090
42133
  };
42091
42134
  });
42092
- }, [duration, timelineAnnotations, timelineBins]);
42093
- const transitionMarkers = useMemo(() => {
42094
- if (timelineBins.length < 2 || duration <= 0) {
42135
+ }, [duration, timelineBins]);
42136
+ const lowOutputRanges = useMemo(() => {
42137
+ if (!timelineBins.length || duration <= 0) {
42095
42138
  return [];
42096
42139
  }
42140
+ const ranges = [];
42097
42141
  const orderedBins = timelineBins.slice().sort((left, right) => left.offset_seconds - right.offset_seconds);
42098
- return orderedBins.slice(1).map((bin, index) => {
42099
- const previousBin = orderedBins[index];
42100
- const fromOutputUnits = getBinOutputUnits(previousBin);
42101
- const toOutputUnits = getBinOutputUnits(bin);
42102
- const hasOutputValues = fromOutputUnits !== null && toOutputUnits !== null && fromOutputUnits > 0;
42103
- const fromEfficiency = previousBin.efficiency_percent;
42104
- const toEfficiency = bin.efficiency_percent;
42105
- const hasEfficiencyValues = typeof fromEfficiency === "number" && typeof toEfficiency === "number" && Number.isFinite(fromEfficiency) && Number.isFinite(toEfficiency) && fromEfficiency > 0;
42106
- if (!hasOutputValues && !hasEfficiencyValues) {
42107
- return null;
42142
+ orderedBins.forEach((bin) => {
42143
+ const actualOutputUnits = getBinOutputUnits(bin);
42144
+ const isIdle = bin.is_idle === true && (actualOutputUnits === null || actualOutputUnits < 1);
42145
+ const hasProductionDespiteIdle = bin.is_idle === true && actualOutputUnits !== null && actualOutputUnits >= 1;
42146
+ const isZeroOutput = actualOutputUnits === 0;
42147
+ const expectedOutputUnits = getExpectedOutputUnits(bin);
42148
+ const isBelowExpectedOutput = (typeof bin.efficiency_percent !== "number" || !Number.isFinite(bin.efficiency_percent)) && expectedOutputUnits !== null && expectedOutputUnits > 0 && actualOutputUnits !== null && actualOutputUnits < expectedOutputUnits;
42149
+ const isLowEfficiency = hasProductionDespiteIdle || isBelowExpectedOutput || !isZeroOutput && typeof bin.efficiency_percent === "number" && Number.isFinite(bin.efficiency_percent) && bin.efficiency_percent < 80;
42150
+ if (!isIdle && !isZeroOutput && !isLowEfficiency) {
42151
+ return;
42108
42152
  }
42109
- const fromValue = hasOutputValues ? fromOutputUnits : fromEfficiency;
42110
- const toValue2 = hasOutputValues ? toOutputUnits : toEfficiency;
42111
- const relativeDrop = (fromValue - toValue2) / fromValue;
42112
- if (relativeDrop <= 0.5) {
42113
- return null;
42153
+ const rangeKind = isIdle ? "idle" : isZeroOutput ? "zero" : "low";
42154
+ const binStart = Math.max(0, bin.offset_seconds);
42155
+ const binEnd = Math.min(duration, binStart + Math.max(0, bin.duration_seconds));
42156
+ if (binEnd <= binStart) {
42157
+ return;
42114
42158
  }
42115
- const transitionOffset = Math.min(Math.max(bin.offset_seconds, 0), duration);
42159
+ const outputShortfallUnits = expectedOutputUnits !== null && actualOutputUnits !== null ? Math.max(0, expectedOutputUnits - actualOutputUnits) : 0;
42160
+ const currentRange = ranges[ranges.length - 1];
42161
+ if (currentRange && currentRange.kind === rangeKind && binStart <= currentRange.endSeconds + 1) {
42162
+ currentRange.endSeconds = Math.max(currentRange.endSeconds, binEnd);
42163
+ currentRange.binCount += 1;
42164
+ currentRange.idleBinCount += isIdle ? 1 : 0;
42165
+ currentRange.zeroBinCount += isZeroOutput ? 1 : 0;
42166
+ currentRange.durationSeconds += binEnd - binStart;
42167
+ currentRange.outputShortfallUnits += outputShortfallUnits;
42168
+ return;
42169
+ }
42170
+ ranges.push({
42171
+ startSeconds: binStart,
42172
+ endSeconds: binEnd,
42173
+ kind: rangeKind,
42174
+ binCount: 1,
42175
+ idleBinCount: isIdle ? 1 : 0,
42176
+ zeroBinCount: isZeroOutput ? 1 : 0,
42177
+ durationSeconds: binEnd - binStart,
42178
+ outputShortfallUnits
42179
+ });
42180
+ });
42181
+ const labelRangeIndexes = ranges.map((range, index) => ({ range, index })).sort((left, right) => {
42182
+ const issuePriority = (range) => range.idleBinCount === range.binCount ? 2 : range.zeroBinCount === range.binCount ? 1 : 0;
42183
+ const priorityDiff = issuePriority(right.range) - issuePriority(left.range);
42184
+ if (priorityDiff !== 0) {
42185
+ return priorityDiff;
42186
+ }
42187
+ const durationDiff = right.range.durationSeconds - left.range.durationSeconds;
42188
+ if (durationDiff !== 0) {
42189
+ return durationDiff;
42190
+ }
42191
+ const shortfallDiff = right.range.outputShortfallUnits - left.range.outputShortfallUnits;
42192
+ if (shortfallDiff !== 0) {
42193
+ return shortfallDiff;
42194
+ }
42195
+ return left.range.startSeconds - right.range.startSeconds;
42196
+ }).slice(0, 3).reduce((set, item) => {
42197
+ set.add(item.index);
42198
+ return set;
42199
+ }, /* @__PURE__ */ new Set());
42200
+ return ranges.map((range, index) => {
42201
+ const isZeroOutputRange = range.zeroBinCount === range.binCount;
42202
+ const isIdleRange = range.idleBinCount === range.binCount;
42203
+ const leftPercent = getPercentage(range.startSeconds, duration);
42204
+ const widthPercent = Math.max(getPercentage(range.endSeconds - range.startSeconds, duration), 0.5);
42116
42205
  return {
42117
- offsetSeconds: transitionOffset,
42118
- leftPercent: getPercentage(transitionOffset, duration),
42119
- fromValue,
42120
- toValue: toValue2,
42121
- relativeDrop,
42122
- fromOutputUnits,
42123
- toOutputUnits,
42124
- source: hasOutputValues ? "output" : "efficiency",
42125
- absoluteDrop: fromValue - toValue2
42206
+ id: `${range.startSeconds}-${range.endSeconds}`,
42207
+ startSeconds: range.startSeconds,
42208
+ endSeconds: range.endSeconds,
42209
+ leftPercent,
42210
+ widthPercent,
42211
+ label: isIdleRange ? "Idle" : isZeroOutputRange ? "0 units" : "Low output",
42212
+ kind: range.kind,
42213
+ isIdleRange,
42214
+ isZeroOutputRange,
42215
+ durationSeconds: range.durationSeconds,
42216
+ outputShortfallUnits: range.outputShortfallUnits,
42217
+ showLabel: labelRangeIndexes.has(index) && widthPercent >= 4 && range.durationSeconds >= 60
42126
42218
  };
42127
- }).filter((marker) => Boolean(marker)).sort((left, right) => {
42128
- const relativeDiff = right.relativeDrop - left.relativeDrop;
42129
- if (relativeDiff !== 0) {
42130
- return relativeDiff;
42131
- }
42132
- const outputDiff = right.absoluteDrop - left.absoluteDrop;
42133
- if (outputDiff !== 0) {
42134
- return outputDiff;
42135
- }
42136
- return left.offsetSeconds - right.offsetSeconds;
42137
- }).slice(0, 3).map((marker, index) => ({
42138
- ...marker,
42139
- rank: index + 1
42140
- }));
42219
+ });
42141
42220
  }, [duration, timelineBins]);
42142
- worstMinuteMarkers[0] || null;
42143
42221
  const updateHoveredTimelineBin = useCallback((clientX) => {
42144
42222
  if (!hasTimelineAnnotations || !progressTrackRef.current || duration <= 0) {
42145
42223
  setHoveredTimelineBin(null);
42224
+ setTooltipAnchorPercent(50);
42225
+ setTooltipPointerPercent(50);
42146
42226
  return;
42147
42227
  }
42148
42228
  const rect = progressTrackRef.current.getBoundingClientRect();
42149
42229
  if (!rect.width) {
42150
42230
  setHoveredTimelineBin(null);
42231
+ setTooltipAnchorPercent(50);
42232
+ setTooltipPointerPercent(50);
42151
42233
  return;
42152
42234
  }
42153
42235
  const pct = Math.min(Math.max((clientX - rect.left) / rect.width, 0), 1);
42154
42236
  const hoverTime = pct * duration;
42155
42237
  const nextBin = timelineBins.find((bin) => hoverTime >= bin.offset_seconds && hoverTime <= bin.offset_seconds + bin.duration_seconds) || null;
42156
42238
  setHoveredTimelineBin(nextBin);
42239
+ const rawAnchorPercent = nextBin ? nextBin.leftPercent + nextBin.widthPercent / 2 : pct * 100;
42240
+ const clampedAnchorPercent = Math.min(90, Math.max(10, rawAnchorPercent));
42241
+ setTooltipAnchorPercent(clampedAnchorPercent);
42242
+ setTooltipPointerPercent(Math.min(92, Math.max(8, 50 + (rawAnchorPercent - clampedAnchorPercent) * 7.5)));
42157
42243
  }, [duration, hasTimelineAnnotations, timelineBins]);
42158
42244
  const handleProgressMouseMove = useCallback((e) => {
42159
42245
  updateHoveredTimelineBin(e.clientX);
@@ -42169,7 +42255,7 @@ var VideoControls = ({
42169
42255
  "div",
42170
42256
  {
42171
42257
  ref: progressTrackRef,
42172
- className: "relative z-10 h-1 mb-4 group cursor-pointer",
42258
+ className: "relative z-10 h-7 mb-4 group cursor-pointer",
42173
42259
  onMouseEnter: () => setIsHoveringProgressBar(true),
42174
42260
  onMouseMove: handleProgressMouseMove,
42175
42261
  onMouseLeave: () => {
@@ -42178,8 +42264,60 @@ var VideoControls = ({
42178
42264
  },
42179
42265
  onPointerDown: handlePointerDown,
42180
42266
  children: [
42181
- /* @__PURE__ */ jsx("div", { className: "absolute -top-4 bottom-0 left-0 right-0 z-20" }),
42182
- /* @__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(
42267
+ /* @__PURE__ */ jsx("div", { className: "absolute -top-5 -bottom-1 left-0 right-0 z-20" }),
42268
+ outputBars.length > 0 && /* @__PURE__ */ jsx(
42269
+ "div",
42270
+ {
42271
+ "data-testid": "output-bar-layer",
42272
+ "aria-hidden": "true",
42273
+ className: "pointer-events-none absolute left-0 right-0 top-0 z-[2] h-3.5",
42274
+ children: outputBars.map((bar) => /* @__PURE__ */ jsx(
42275
+ "div",
42276
+ {
42277
+ "data-testid": "output-minute-bar",
42278
+ "data-tone": bar.tone,
42279
+ className: "absolute bottom-0 rounded-sm",
42280
+ style: {
42281
+ left: `${bar.leftPercent}%`,
42282
+ width: `${Math.max(bar.widthPercent, 0.45)}%`,
42283
+ height: `${bar.heightPercent}%`,
42284
+ backgroundColor: bar.tone === "zero" ? "rgba(239, 68, 68, 0.78)" : bar.tone === "idle" ? "rgba(168, 85, 247, 0.70)" : bar.tone === "low" ? "rgba(248, 113, 113, 0.56)" : "rgba(255, 255, 255, 0.46)"
42285
+ }
42286
+ },
42287
+ bar.id
42288
+ ))
42289
+ }
42290
+ ),
42291
+ lowOutputRanges.map((range) => /* @__PURE__ */ jsx(
42292
+ "div",
42293
+ {
42294
+ "data-testid": "low-output-range",
42295
+ "data-kind": range.kind,
42296
+ "aria-hidden": "true",
42297
+ className: "pointer-events-none absolute top-[19px] z-[1] h-3 -translate-y-1/2 rounded-full border",
42298
+ style: {
42299
+ left: `${range.leftPercent}%`,
42300
+ width: `${range.widthPercent}%`,
42301
+ backgroundColor: range.isIdleRange ? "rgba(168, 85, 247, 0.24)" : range.isZeroOutputRange ? "rgba(239, 68, 68, 0.38)" : "rgba(248, 113, 113, 0.24)",
42302
+ borderColor: range.isIdleRange ? "rgba(216, 180, 254, 0.32)" : range.isZeroOutputRange ? "rgba(252, 165, 165, 0.35)" : "rgba(254, 202, 202, 0.28)"
42303
+ }
42304
+ },
42305
+ range.id
42306
+ )),
42307
+ !hoveredTimelineBin && lowOutputRanges.filter((range) => range.showLabel).map((range) => /* @__PURE__ */ jsx(
42308
+ "div",
42309
+ {
42310
+ "data-testid": "low-output-range-label",
42311
+ "data-kind": range.kind,
42312
+ className: `pointer-events-none absolute bottom-full z-[35] mb-1 -translate-x-1/2 rounded-md border px-1.5 py-0.5 text-[10px] font-semibold leading-none shadow-sm ${range.isIdleRange ? "border-violet-200/35 bg-violet-950/75 text-violet-50" : "border-red-200/30 bg-red-950/75 text-red-50"}`,
42313
+ style: {
42314
+ left: `${Math.min(98, Math.max(2, range.leftPercent + range.widthPercent / 2))}%`
42315
+ },
42316
+ children: range.label
42317
+ },
42318
+ `${range.id}-label`
42319
+ )),
42320
+ /* @__PURE__ */ jsx("div", { className: "absolute left-0 right-0 top-[19px] h-1 -translate-y-1/2 bg-white/20 rounded-full overflow-hidden z-10", children: /* @__PURE__ */ jsx(
42183
42321
  "div",
42184
42322
  {
42185
42323
  className: "absolute top-0 left-0 bottom-0 bg-white/40 transition-all duration-200",
@@ -42189,7 +42327,7 @@ var VideoControls = ({
42189
42327
  /* @__PURE__ */ jsx(
42190
42328
  "div",
42191
42329
  {
42192
- className: "absolute top-0 left-0 bottom-0 bg-[#007bff] transition-all duration-75 z-10",
42330
+ className: "absolute left-0 top-[19px] h-1 -translate-y-1/2 bg-[#007bff] transition-all duration-75 z-20",
42193
42331
  style: { width: `${progressPercent}%`, backgroundColor: progressColor },
42194
42332
  children: /* @__PURE__ */ jsx(
42195
42333
  "div",
@@ -42216,36 +42354,48 @@ var VideoControls = ({
42216
42354
  onTouchStart: handleSeekStart,
42217
42355
  onTouchEnd: handleSeekEnd,
42218
42356
  onPointerDown: handlePointerDown,
42219
- className: "absolute left-0 right-0 top-[-12px] bottom-0 w-full h-auto opacity-0 cursor-pointer z-30 margin-0 padding-0"
42357
+ className: "absolute left-0 right-0 top-[-12px] bottom-[-4px] w-full h-auto opacity-0 cursor-pointer z-40 margin-0 padding-0"
42220
42358
  }
42221
42359
  ),
42222
- hasTimelineAnnotations && transitionMarkers.map((marker) => /* @__PURE__ */ jsx(
42223
- "button",
42224
- {
42225
- type: "button",
42226
- "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)`,
42227
- title: marker.source === "output" ? `Output drop: ${formatCompactNumber(marker.fromValue)} to ${formatCompactNumber(marker.toValue)}` : `Output drop: ${Math.round(marker.fromValue)}% to ${Math.round(marker.toValue)}%`,
42228
- onPointerDownCapture: (e) => handleTimelineMarkerPointerDown(e, marker.offsetSeconds),
42229
- onMouseDownCapture: (e) => handleTimelineMarkerMouseDown(e, marker.offsetSeconds),
42230
- onClickCapture: (e) => handleTimelineMarkerClick(e, marker.offsetSeconds),
42231
- 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",
42232
- style: { left: `calc(${marker.leftPercent}% - 10px)`, zIndex: 70, pointerEvents: "auto" },
42233
- children: marker.rank
42234
- },
42235
- `${marker.rank}-${marker.offsetSeconds}`
42236
- )),
42237
- hasTimelineAnnotations && hoveredTimelineBin && /* @__PURE__ */ jsxs(
42360
+ hasTimelineAnnotations && hoveredTimelineBin && /* @__PURE__ */ jsx(
42238
42361
  "div",
42239
42362
  {
42240
- 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",
42241
- style: { left: `${hoveredTimelineBin.leftPercent + hoveredTimelineBin.widthPercent / 2}%` },
42242
- children: [
42243
- hoveredTimelineBin.clockLabel || formatTime2(hoveredTimelineBin.offset_seconds),
42244
- " | ",
42245
- hoveredTimelineBin.efficiencyLabel,
42246
- hoveredTimelineBin.outputLabel ? ` | ${hoveredTimelineBin.outputLabel}` : "",
42247
- hoveredTimelineBin.explanationLabel ? ` | ${hoveredTimelineBin.explanationLabel}` : ""
42248
- ]
42363
+ "data-testid": "tooltip-card",
42364
+ className: "absolute bottom-full z-50 mb-5 min-w-[146px] -translate-x-1/2 whitespace-nowrap rounded-lg border border-slate-500/70 bg-[#0b101b]/95 px-3 py-2.5 text-left text-white shadow-[0_16px_36px_rgba(0,0,0,0.48)] backdrop-blur",
42365
+ style: { left: `${tooltipAnchorPercent}%` },
42366
+ children: (() => {
42367
+ const outputParts = getTooltipOutputParts(hoveredTimelineBin.outputLabel, hoveredTimelineBin.efficiencyLabel);
42368
+ const isIdleReason = hoveredTimelineBin.tooltipReasonLabel === "Idle";
42369
+ const isOutputTooltip = outputParts.label === "Output";
42370
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
42371
+ /* @__PURE__ */ jsx("div", { className: "text-[11px] font-medium leading-none text-slate-300", children: hoveredTimelineBin.clockLabel || formatTime2(hoveredTimelineBin.offset_seconds) }),
42372
+ /* @__PURE__ */ jsxs("div", { className: "mt-1.5 flex items-baseline gap-1 text-[15px] font-bold leading-none tracking-[-0.01em]", children: [
42373
+ /* @__PURE__ */ jsx("span", { className: "text-white", children: outputParts.label }),
42374
+ isOutputTooltip ? /* @__PURE__ */ jsxs(Fragment, { children: [
42375
+ /* @__PURE__ */ jsx("span", { "data-testid": "tooltip-actual-output", className: "tabular-nums text-red-400", children: outputParts.actual }),
42376
+ outputParts.expected ? /* @__PURE__ */ jsxs(Fragment, { children: [
42377
+ /* @__PURE__ */ jsx("span", { className: "text-slate-100", children: "/" }),
42378
+ /* @__PURE__ */ jsx("span", { className: "tabular-nums text-slate-100", children: outputParts.expected })
42379
+ ] }) : null
42380
+ ] }) : /* @__PURE__ */ jsx("span", { className: "tabular-nums text-slate-100", children: outputParts.fallbackValue || outputParts.actual })
42381
+ ] }),
42382
+ hoveredTimelineBin.tooltipReasonLabel ? /* @__PURE__ */ jsx("div", { className: "mt-2 flex items-center", children: /* @__PURE__ */ jsx(
42383
+ "span",
42384
+ {
42385
+ className: `rounded-md border px-2 py-1 text-[10px] font-semibold leading-none shadow-sm ${isIdleReason ? "border-violet-300/30 bg-violet-500/20 text-violet-100" : "border-red-300/35 bg-red-500/25 text-red-50"}`,
42386
+ children: hoveredTimelineBin.tooltipReasonLabel
42387
+ }
42388
+ ) }) : null,
42389
+ /* @__PURE__ */ jsx(
42390
+ "div",
42391
+ {
42392
+ "data-testid": "tooltip-pointer",
42393
+ className: "absolute top-full h-3 w-3 -translate-x-1/2 -translate-y-1/2 rotate-45 border-b border-r border-slate-500/70 bg-[#0b101b]/95",
42394
+ style: { left: `${tooltipPointerPercent}%` }
42395
+ }
42396
+ )
42397
+ ] });
42398
+ })()
42249
42399
  }
42250
42400
  )
42251
42401
  ]
@@ -43812,6 +43962,19 @@ var buildLostChip = (explanation) => {
43812
43962
  }
43813
43963
  return null;
43814
43964
  };
43965
+ var getDriverBadgeClassName = (driverKeys) => {
43966
+ if (driverKeys.length === 1) {
43967
+ switch (driverKeys[0]) {
43968
+ case "idle":
43969
+ return "border border-violet-300/30 bg-violet-500/20 text-violet-100 ring-violet-500/20";
43970
+ case "slow_cycle":
43971
+ return "border border-amber-300/30 bg-amber-500/20 text-amber-100 ring-amber-500/20";
43972
+ case "micro_stoppage":
43973
+ return "border border-red-300/25 bg-red-500/15 text-red-100 ring-red-500/20";
43974
+ }
43975
+ }
43976
+ return "border border-red-300/25 bg-red-500/15 text-red-100 ring-red-500/20";
43977
+ };
43815
43978
  var RedFlowDiagnosticOverlay = ({
43816
43979
  timeline,
43817
43980
  explanation,
@@ -43836,6 +43999,7 @@ var RedFlowDiagnosticOverlay = ({
43836
43999
  const shouldShowLostChip = driverKeys.some((driver) => driver !== "low_output");
43837
44000
  const chips = explanation && shouldShowLostChip ? [buildLostChip(explanation)].filter((chip) => Boolean(chip)) : [];
43838
44001
  const shouldShowHeadline = Boolean(summary && driverKeys.length > 0 && summary.primary_driver !== "unknown");
44002
+ const driverBadgeClassName = getDriverBadgeClassName(driverKeys);
43839
44003
  const aiSummaryBullets = Array.isArray(aiSummary?.bullets) ? aiSummary.bullets.map((bullet) => String(bullet || "").trim()).filter(Boolean).slice(0, 3) : [];
43840
44004
  const shouldShowAiSummary = !aiSummaryError && aiSummaryBullets.length === 3;
43841
44005
  return /* @__PURE__ */ jsxs(
@@ -43854,9 +44018,9 @@ var RedFlowDiagnosticOverlay = ({
43854
44018
  ] }),
43855
44019
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
43856
44020
  /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-white/50", children: "Reason:" }),
43857
- /* @__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" })
44021
+ /* @__PURE__ */ jsx("span", { className: `rounded px-2 py-1 text-[10px] font-semibold tracking-wide ring-1 ring-inset ${driverBadgeClassName}`, children: driverLabel })
43858
44022
  ] })
43859
- ] }) : /* @__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 }) }),
44023
+ ] }) : /* @__PURE__ */ jsx("div", { className: "mb-4 flex items-center gap-2", children: /* @__PURE__ */ jsx("span", { className: `rounded px-2 py-1 text-[10px] font-semibold tracking-wide ring-1 ring-inset ${driverBadgeClassName}`, children: driverLabel }) }),
43860
44024
  (shouldShowAiSummary || aiSummaryLoading || chips.length > 0 || shouldShowHeadline) && /* @__PURE__ */ jsx("div", { className: "mb-4 h-px w-full bg-white/10" }),
43861
44025
  !shouldShowAiSummary && !aiSummaryLoading && shouldShowHeadline && summary?.headline ? /* @__PURE__ */ jsx("div", { className: "mb-3 text-[13px] font-medium leading-relaxed text-white/90", children: summary.headline }) : null,
43862
44026
  !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(
@@ -43930,7 +44094,7 @@ function Skeleton({ className, ...props }) {
43930
44094
  var Select = SelectPrimitive.Root;
43931
44095
  var SelectGroup = SelectPrimitive.Group;
43932
44096
  var SelectValue = SelectPrimitive.Value;
43933
- var SelectTrigger = React148.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
44097
+ var SelectTrigger = React125.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
43934
44098
  SelectPrimitive.Trigger,
43935
44099
  {
43936
44100
  ref,
@@ -43946,7 +44110,7 @@ var SelectTrigger = React148.forwardRef(({ className, children, ...props }, ref)
43946
44110
  }
43947
44111
  ));
43948
44112
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
43949
- var SelectScrollUpButton = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
44113
+ var SelectScrollUpButton = React125.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
43950
44114
  SelectPrimitive.ScrollUpButton,
43951
44115
  {
43952
44116
  ref,
@@ -43956,7 +44120,7 @@ var SelectScrollUpButton = React148.forwardRef(({ className, ...props }, ref) =>
43956
44120
  }
43957
44121
  ));
43958
44122
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
43959
- var SelectScrollDownButton = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
44123
+ var SelectScrollDownButton = React125.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
43960
44124
  SelectPrimitive.ScrollDownButton,
43961
44125
  {
43962
44126
  ref,
@@ -43966,7 +44130,7 @@ var SelectScrollDownButton = React148.forwardRef(({ className, ...props }, ref)
43966
44130
  }
43967
44131
  ));
43968
44132
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
43969
- var SelectContent = React148.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
44133
+ var SelectContent = React125.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
43970
44134
  SelectPrimitive.Content,
43971
44135
  {
43972
44136
  ref,
@@ -43994,7 +44158,7 @@ var SelectContent = React148.forwardRef(({ className, children, position = "popp
43994
44158
  }
43995
44159
  ) }));
43996
44160
  SelectContent.displayName = SelectPrimitive.Content.displayName;
43997
- var SelectLabel = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
44161
+ var SelectLabel = React125.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
43998
44162
  SelectPrimitive.Label,
43999
44163
  {
44000
44164
  ref,
@@ -44003,7 +44167,7 @@ var SelectLabel = React148.forwardRef(({ className, ...props }, ref) => /* @__PU
44003
44167
  }
44004
44168
  ));
44005
44169
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
44006
- var SelectItem = React148.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
44170
+ var SelectItem = React125.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
44007
44171
  SelectPrimitive.Item,
44008
44172
  {
44009
44173
  ref,
@@ -44019,7 +44183,7 @@ var SelectItem = React148.forwardRef(({ className, children, ...props }, ref) =>
44019
44183
  }
44020
44184
  ));
44021
44185
  SelectItem.displayName = SelectPrimitive.Item.displayName;
44022
- var SelectSeparator = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
44186
+ var SelectSeparator = React125.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
44023
44187
  SelectPrimitive.Separator,
44024
44188
  {
44025
44189
  ref,
@@ -44645,7 +44809,7 @@ var TimePickerDropdown = ({
44645
44809
  )
44646
44810
  ] });
44647
44811
  };
44648
- var SilentErrorBoundary = class extends React148__default.Component {
44812
+ var SilentErrorBoundary = class extends React125__default.Component {
44649
44813
  constructor(props) {
44650
44814
  super(props);
44651
44815
  this.handleClearAndReload = () => {
@@ -47365,6 +47529,7 @@ function useClipsRealtimeUpdates({
47365
47529
  };
47366
47530
  }
47367
47531
  var LOW_EFFICIENCY_CATEGORY_ID = "recent_flow_red_streak";
47532
+ var LOW_EFFICIENCY_AI_SUMMARY_ENABLED = process.env.NEXT_PUBLIC_LOW_EFFICIENCY_AI_SUMMARY_ENABLED === "true";
47368
47533
  var parseFiniteNumber2 = (value) => {
47369
47534
  if (typeof value === "number" && Number.isFinite(value)) {
47370
47535
  return value;
@@ -48903,12 +49068,15 @@ var BottlenecksContent = ({
48903
49068
  const isCurrentLowEfficiencyClip = Boolean(
48904
49069
  currentVideo?.type === "recent_flow_red_streak" || currentVideo?.red_flow_timeline
48905
49070
  );
48906
- const currentLowEfficiencyAiSummary = currentLowEfficiencyClipId ? lowEfficiencyAiSummaryByClipId[currentLowEfficiencyClipId] || currentVideo?.low_efficiency_ai_summary || null : null;
49071
+ const currentLowEfficiencyAiSummary = currentLowEfficiencyClipId ? LOW_EFFICIENCY_AI_SUMMARY_ENABLED ? lowEfficiencyAiSummaryByClipId[currentLowEfficiencyClipId] || currentVideo?.low_efficiency_ai_summary || null : null : null;
48907
49072
  const isCurrentLowEfficiencyAiSummaryLoading = Boolean(
48908
- currentLowEfficiencyClipId && lowEfficiencyAiSummaryLoadingByClipId[currentLowEfficiencyClipId]
49073
+ LOW_EFFICIENCY_AI_SUMMARY_ENABLED && currentLowEfficiencyClipId && lowEfficiencyAiSummaryLoadingByClipId[currentLowEfficiencyClipId]
48909
49074
  );
48910
- const currentLowEfficiencyAiSummaryError = currentLowEfficiencyClipId ? lowEfficiencyAiSummaryErrorByClipId[currentLowEfficiencyClipId] || null : null;
49075
+ const currentLowEfficiencyAiSummaryError = currentLowEfficiencyClipId ? LOW_EFFICIENCY_AI_SUMMARY_ENABLED ? lowEfficiencyAiSummaryErrorByClipId[currentLowEfficiencyClipId] || null : null : null;
48911
49076
  useEffect(() => {
49077
+ if (!LOW_EFFICIENCY_AI_SUMMARY_ENABLED) {
49078
+ return;
49079
+ }
48912
49080
  const clipId = currentLowEfficiencyClipId;
48913
49081
  if (!clipId || !isCurrentLowEfficiencyClip || !workspaceId) {
48914
49082
  return;
@@ -52038,8 +52206,8 @@ var IdleTimeReasonChartComponent = ({
52038
52206
  updateAnimation = "replay",
52039
52207
  variant = "pie"
52040
52208
  }) => {
52041
- const [activeData, setActiveData] = React148__default.useState([]);
52042
- React148__default.useEffect(() => {
52209
+ const [activeData, setActiveData] = React125__default.useState([]);
52210
+ React125__default.useEffect(() => {
52043
52211
  if (updateAnimation === "smooth") {
52044
52212
  setActiveData(data && data.length > 0 ? data : []);
52045
52213
  return;
@@ -52058,7 +52226,7 @@ var IdleTimeReasonChartComponent = ({
52058
52226
  setActiveData([]);
52059
52227
  }
52060
52228
  }, [data, updateAnimation]);
52061
- React148__default.useEffect(() => {
52229
+ React125__default.useEffect(() => {
52062
52230
  if (!data || data.length === 0) return;
52063
52231
  data.forEach((entry, index) => {
52064
52232
  if (entry.name.toLowerCase().includes("other")) {
@@ -52066,7 +52234,7 @@ var IdleTimeReasonChartComponent = ({
52066
52234
  }
52067
52235
  });
52068
52236
  }, [data]);
52069
- const pieKey = React148__default.useMemo(() => {
52237
+ const pieKey = React125__default.useMemo(() => {
52070
52238
  if (updateAnimation === "smooth") {
52071
52239
  return "smooth";
52072
52240
  }
@@ -52236,7 +52404,7 @@ var IdleTimeReasonChartComponent = ({
52236
52404
  )
52237
52405
  ] });
52238
52406
  };
52239
- var IdleTimeReasonChart = React148__default.memo(IdleTimeReasonChartComponent);
52407
+ var IdleTimeReasonChart = React125__default.memo(IdleTimeReasonChartComponent);
52240
52408
  IdleTimeReasonChart.displayName = "IdleTimeReasonChart";
52241
52409
  var IdleTimeReasonChart_default = IdleTimeReasonChart;
52242
52410
 
@@ -56763,13 +56931,13 @@ var WorkspaceCycleTimeMetricCards = ({
56763
56931
  liveSkuId
56764
56932
  }) => {
56765
56933
  const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
56766
- const activeSku = React148__default.useMemo(() => {
56934
+ const activeSku = React125__default.useMemo(() => {
56767
56935
  if (skuAware && activeSkuId && skuBreakdown) {
56768
56936
  return skuBreakdown.find((s) => s.sku_id === activeSkuId);
56769
56937
  }
56770
56938
  return null;
56771
56939
  }, [skuAware, activeSkuId, skuBreakdown]);
56772
- const displaySku = React148__default.useMemo(() => {
56940
+ const displaySku = React125__default.useMemo(() => {
56773
56941
  if (activeSku) return activeSku;
56774
56942
  if (skuAware && !activeSkuId && liveSkuId && skuBreakdown) {
56775
56943
  return skuBreakdown.find((s) => s.sku_id === liveSkuId) ?? null;
@@ -57014,7 +57182,7 @@ var arePropsEqual = (prevProps, nextProps) => {
57014
57182
  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
57015
57183
  prevProps.position.id === nextProps.position.id;
57016
57184
  };
57017
- var WorkspaceGridItem = React148__default.memo(({
57185
+ var WorkspaceGridItem = React125__default.memo(({
57018
57186
  data,
57019
57187
  position,
57020
57188
  isBottleneck = false,
@@ -57109,7 +57277,7 @@ var WorkspaceGridItem = React148__default.memo(({
57109
57277
  );
57110
57278
  }, arePropsEqual);
57111
57279
  WorkspaceGridItem.displayName = "WorkspaceGridItem";
57112
- var WorkspaceGrid = React148__default.memo(({
57280
+ var WorkspaceGrid = React125__default.memo(({
57113
57281
  workspaces,
57114
57282
  blueComparisonWorkspaces,
57115
57283
  worstPerformanceWorkspaceIds = [],
@@ -57368,7 +57536,7 @@ var KPICard = ({
57368
57536
  }) => {
57369
57537
  useThemeConfig();
57370
57538
  const { formatNumber } = useFormatNumber();
57371
- const trendInfo = React148__default.useMemo(() => {
57539
+ const trendInfo = React125__default.useMemo(() => {
57372
57540
  let trendValue = trend || "neutral";
57373
57541
  if (change !== void 0 && trend === void 0) {
57374
57542
  trendValue = change > 0 ? "up" : change < 0 ? "down" : "neutral";
@@ -57395,7 +57563,7 @@ var KPICard = ({
57395
57563
  const shouldShowTrend = !(change === 0 && trend === void 0);
57396
57564
  return { trendValue, Icon: Icon2, colorClass, bgClass, shouldShowTrend };
57397
57565
  }, [trend, change]);
57398
- const formattedValue = React148__default.useMemo(() => {
57566
+ const formattedValue = React125__default.useMemo(() => {
57399
57567
  if (title === "Quality Compliance" && typeof value === "number") {
57400
57568
  return value.toFixed(1);
57401
57569
  }
@@ -57409,7 +57577,7 @@ var KPICard = ({
57409
57577
  }
57410
57578
  return value;
57411
57579
  }, [value, title]);
57412
- const formattedChange = React148__default.useMemo(() => {
57580
+ const formattedChange = React125__default.useMemo(() => {
57413
57581
  if (change === void 0 || change === 0 && !showZeroChange) return null;
57414
57582
  const absChange = Math.abs(change);
57415
57583
  return formatNumber(absChange, { minimumFractionDigits: 0, maximumFractionDigits: 1 });
@@ -57661,11 +57829,6 @@ var KPISection = memo$1(({
57661
57829
  }) => {
57662
57830
  const showSkeleton = isLoading || !kpis;
57663
57831
  const isUptimeMode = mode === "uptime";
57664
- const efficiencyOnTrack = !isUptimeMode && isEfficiencyOnTrack(kpis?.efficiency.value);
57665
- const outputStatus = !showSkeleton && !isUptimeMode ? {
57666
- tooltipText: efficiencyOnTrack ? "On Track" : "Behind",
57667
- positive: efficiencyOnTrack
57668
- } : void 0;
57669
57832
  if (useSrcLayout) {
57670
57833
  const effChange = showSkeleton ? 0 : kpis.efficiency.change ?? 0;
57671
57834
  const effTrend = effChange > 0 ? "up" : effChange < 0 ? "down" : "neutral";
@@ -57701,7 +57864,6 @@ var KPISection = memo$1(({
57701
57864
  {
57702
57865
  title: secondaryTitle,
57703
57866
  value: secondaryValue,
57704
- status: outputStatus,
57705
57867
  isLoading: showSkeleton
57706
57868
  }
57707
57869
  ) })
@@ -57732,7 +57894,7 @@ var KPISection = memo$1(({
57732
57894
  value: showSkeleton ? "" : `${kpis.outputProgress.current}/${kpis.outputProgress.target}`,
57733
57895
  change: showSkeleton ? 0 : kpis.outputProgress.change,
57734
57896
  suffix: void 0,
57735
- status: outputStatus
57897
+ status: void 0
57736
57898
  }
57737
57899
  ];
57738
57900
  return /* @__PURE__ */ jsx(
@@ -57765,7 +57927,6 @@ var KPISection = memo$1(({
57765
57927
  if (!prevKpis && !nextKpis) return true;
57766
57928
  if (!prevKpis || !nextKpis) return false;
57767
57929
  if (prevKpis === nextKpis) return true;
57768
- if (isEfficiencyOnTrack(prevKpis.efficiency.value) !== isEfficiencyOnTrack(nextKpis.efficiency.value)) return false;
57769
57930
  if (Math.abs(prevKpis.efficiency.value - nextKpis.efficiency.value) >= 0.5) return false;
57770
57931
  if (prevKpis.efficiency.change !== nextKpis.efficiency.change) return false;
57771
57932
  if (prevKpis.underperformingWorkers.current !== nextKpis.underperformingWorkers.current || prevKpis.underperformingWorkers.total !== nextKpis.underperformingWorkers.total) return false;
@@ -58916,7 +59077,7 @@ var Breadcrumbs = ({ items }) => {
58916
59077
  }
58917
59078
  }
58918
59079
  };
58919
- 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: [
59080
+ 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(React125__default.Fragment, { children: [
58920
59081
  index > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "h-3 w-3 text-gray-400 dark:text-gray-500" }),
58921
59082
  /* @__PURE__ */ jsxs(
58922
59083
  "span",
@@ -59746,6 +59907,16 @@ var SideNavBar = memo$1(({
59746
59907
  }, [refreshAlertsSummary, showAlertsButton]);
59747
59908
  const settingsItems = useMemo(() => {
59748
59909
  const items = [
59910
+ ...canAccessPath("/improvement-center") ? [{
59911
+ key: "improvement-center",
59912
+ label: "Improve",
59913
+ icon: LightBulbIcon,
59914
+ onClick: () => {
59915
+ handleImprovementClick();
59916
+ setIsSettingsOpen(false);
59917
+ },
59918
+ isActive: pathname === "/improvement-center" || pathname.startsWith("/improvement-center/")
59919
+ }] : [],
59749
59920
  ...canAccessPath("/targets") ? [{
59750
59921
  key: "targets",
59751
59922
  label: "Targets",
@@ -59834,7 +60005,7 @@ var SideNavBar = memo$1(({
59834
60005
  });
59835
60006
  }
59836
60007
  return items;
59837
- }, [handleTargetsClick, handleProductionPlanClick, handleShiftsClick, handleTeamManagementClick, handleProfileClick, handleTicketsClick, handleClipsCostClick, handleHelpClick, pathname, ticketsEnabled, showBillingLink, canAccessPath]);
60008
+ }, [handleImprovementClick, handleTargetsClick, handleProductionPlanClick, handleShiftsClick, handleTeamManagementClick, handleProfileClick, handleTicketsClick, handleClipsCostClick, handleHelpClick, pathname, ticketsEnabled, showBillingLink, canAccessPath]);
59838
60009
  const handleLogout = useCallback(async () => {
59839
60010
  setIsSettingsOpen(false);
59840
60011
  try {
@@ -59853,7 +60024,6 @@ var SideNavBar = memo$1(({
59853
60024
  const liveButtonClasses = useMemo(() => getButtonClasses("/live-monitor"), [getButtonClasses]);
59854
60025
  const leaderboardButtonClasses = useMemo(() => getButtonClasses("/leaderboard"), [getButtonClasses]);
59855
60026
  const kpisButtonClasses = useMemo(() => getButtonClasses("/kpis"), [getButtonClasses]);
59856
- const improvementButtonClasses = useMemo(() => getButtonClasses("/improvement-center"), [getButtonClasses]);
59857
60027
  useMemo(() => getButtonClasses("/supervisor-management"), [getButtonClasses]);
59858
60028
  const skusButtonClasses = useMemo(() => getButtonClasses("/skus"), [getButtonClasses]);
59859
60029
  const healthButtonClasses = useMemo(() => getButtonClasses("/health"), [getButtonClasses]);
@@ -59941,21 +60111,6 @@ var SideNavBar = memo$1(({
59941
60111
  ]
59942
60112
  }
59943
60113
  ),
59944
- canAccessPath("/improvement-center") && /* @__PURE__ */ jsxs(
59945
- "button",
59946
- {
59947
- onClick: handleImprovementClick,
59948
- className: improvementButtonClasses,
59949
- "aria-label": "Improvement Center",
59950
- tabIndex: 0,
59951
- role: "tab",
59952
- "aria-selected": isPathActive("/improvement-center"),
59953
- children: [
59954
- /* @__PURE__ */ jsx(LightBulbIcon, { className: "w-5 h-5 mb-1" }),
59955
- /* @__PURE__ */ jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight text-center", children: "Improve" })
59956
- ]
59957
- }
59958
- ),
59959
60114
  showSupervisorManagement,
59960
60115
  skuEnabled && canAccessPath("/skus") && /* @__PURE__ */ jsxs(
59961
60116
  "button",
@@ -60073,18 +60228,6 @@ var SideNavBar = memo$1(({
60073
60228
  ]
60074
60229
  }
60075
60230
  ),
60076
- canAccessPath("/improvement-center") && /* @__PURE__ */ jsxs(
60077
- "button",
60078
- {
60079
- onClick: handleMobileNavClick(handleImprovementClick),
60080
- className: getMobileButtonClass("/improvement-center"),
60081
- "aria-label": "Improvement Center",
60082
- children: [
60083
- /* @__PURE__ */ jsx(LightBulbIcon, { className: getIconClass("/improvement-center") }),
60084
- /* @__PURE__ */ jsx("span", { className: "text-base font-medium", children: "Improve" })
60085
- ]
60086
- }
60087
- ),
60088
60231
  showSupervisorManagement,
60089
60232
  skuEnabled && canAccessPath("/skus") && /* @__PURE__ */ jsxs(
60090
60233
  "button",
@@ -60114,6 +60257,18 @@ var SideNavBar = memo$1(({
60114
60257
  /* @__PURE__ */ jsxs("div", { className: "mt-8 pt-6 border-t border-gray-100", children: [
60115
60258
  /* @__PURE__ */ jsx("h3", { className: "px-5 mb-3 text-[10px] font-bold text-gray-400 uppercase tracking-widest", children: "Settings & Support" }),
60116
60259
  /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
60260
+ canAccessPath("/improvement-center") && /* @__PURE__ */ jsxs(
60261
+ "button",
60262
+ {
60263
+ onClick: handleMobileNavClick(handleImprovementClick),
60264
+ className: getMobileButtonClass("/improvement-center"),
60265
+ "aria-label": "Improvement Center",
60266
+ children: [
60267
+ /* @__PURE__ */ jsx(LightBulbIcon, { className: getIconClass("/improvement-center") }),
60268
+ /* @__PURE__ */ jsx("span", { className: "text-base font-medium", children: "Improve" })
60269
+ ]
60270
+ }
60271
+ ),
60117
60272
  canAccessPath("/targets") && /* @__PURE__ */ jsxs(
60118
60273
  "button",
60119
60274
  {
@@ -60232,12 +60387,12 @@ var SideNavBar = memo$1(({
60232
60387
  /* @__PURE__ */ jsx(
60233
60388
  "div",
60234
60389
  {
60235
- className: `md:hidden fixed inset-0 bg-black/60 backdrop-blur-sm z-40 transition-opacity duration-300 ease-in-out ${isMobileMenuOpen ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"}`,
60390
+ className: `md:hidden fixed inset-0 bg-black/60 backdrop-blur-sm z-[190] transition-opacity duration-300 ease-in-out ${isMobileMenuOpen ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"}`,
60236
60391
  onClick: onMobileMenuClose,
60237
60392
  "aria-hidden": "true"
60238
60393
  }
60239
60394
  ),
60240
- /* @__PURE__ */ jsxs("aside", { className: `md:hidden fixed inset-y-0 left-0 w-72 xs:w-80 bg-white shadow-2xl flex flex-col z-50 transform transition-transform duration-300 ease-in-out ${isMobileMenuOpen ? "translate-x-0" : "-translate-x-full"}`, children: [
60395
+ /* @__PURE__ */ jsxs("aside", { className: `md:hidden fixed inset-y-0 left-0 w-72 xs:w-80 bg-white shadow-2xl flex flex-col z-[200] transform transition-transform duration-300 ease-in-out ${isMobileMenuOpen ? "translate-x-0" : "-translate-x-full"}`, children: [
60241
60396
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-4 border-b border-gray-200 bg-gradient-to-r from-blue-50 to-white", children: [
60242
60397
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(Logo, { className: "w-11 h-11 object-contain" }) }),
60243
60398
  /* @__PURE__ */ jsx(
@@ -60440,7 +60595,7 @@ var AwardBadge = ({
60440
60595
  }) => {
60441
60596
  const styles2 = getBadgeStyles(type);
60442
60597
  const Icon2 = CustomIcon || getDefaultIcon(type);
60443
- const randomDelay = React148__default.useMemo(() => Math.random() * 2, []);
60598
+ const randomDelay = React125__default.useMemo(() => Math.random() * 2, []);
60444
60599
  const floatingAnimation = {
60445
60600
  animate: {
60446
60601
  y: [0, -10, 0],
@@ -67356,7 +67511,7 @@ var HOME_DISPLAY_MODE_OPTIONS = [
67356
67511
  {
67357
67512
  id: "worst_workstations",
67358
67513
  label: "Overall Underperformers",
67359
- description: "Lowest performers based on full day efficiency"
67514
+ description: "Highlights the poorest performers of the day"
67360
67515
  }
67361
67516
  ];
67362
67517
  var getHomeDisplayModeLabel = (displayMode) => HOME_DISPLAY_MODE_OPTIONS.find((option) => option.id === displayMode)?.label || "Default";
@@ -68624,10 +68779,6 @@ function HomeView({
68624
68779
  selection_mode: isAllLinesSelection(normalizedLineIds) ? "all" : normalizedLineIds.length === 1 ? "single" : "custom",
68625
68780
  line_name: getLineSelectionLabel(normalizedLineIds)
68626
68781
  });
68627
- trackCoreEvent("Dashboard Filter Selected", {
68628
- filter_type: "Line Filter",
68629
- filter_value: getLineSelectionLabel(normalizedLineIds)
68630
- });
68631
68782
  }, [factoryViewId, getLineSelectionLabel, getTrackedLineScope, selectedLineIds, selectedLineIdsKey, visibleLineIds]);
68632
68783
  useCallback(() => {
68633
68784
  updateSelectedLineIds(visibleLineIds);
@@ -68861,15 +69012,6 @@ function HomeView({
68861
69012
  selected_line_count: nextSelectedLineIds.length,
68862
69013
  highlighted_workspace_count: option.id === "worst_workstations" ? worstPerformanceWorkspaceIds.length : 0
68863
69014
  });
68864
- trackCoreEvent("Dashboard Filter Selected", {
68865
- filter_type: "Display Mode",
68866
- filter_value: option.label,
68867
- filter_id: option.id,
68868
- previous_filter_value: getHomeDisplayModeLabel(displayMode),
68869
- ...selectedViewProperties,
68870
- selected_line_ids: nextSelectedLineIds,
68871
- selected_line_count: nextSelectedLineIds.length
68872
- });
68873
69015
  trackCoreEvent(`Display View Selected: ${option.label}`, {
68874
69016
  mode_id: option.id,
68875
69017
  mode_label: option.label,
@@ -69090,7 +69232,7 @@ function HomeView({
69090
69232
  animate: { opacity: 1, scale: 1 },
69091
69233
  transition: { duration: 0.3 },
69092
69234
  className: "h-full",
69093
- children: React148__default.createElement(WorkspaceGrid, {
69235
+ children: React125__default.createElement(WorkspaceGrid, {
69094
69236
  workspaces: workspaceMetricsWithBreakState,
69095
69237
  blueComparisonWorkspaces: currentBlueComparisonWorkspaceMetrics || workspaceMetricsWithBreakState,
69096
69238
  worstPerformanceWorkspaceIds: activeWorstPerformanceWorkspaceIds,
@@ -69126,7 +69268,7 @@ function HomeView({
69126
69268
  animate: { opacity: 1, scale: 1 },
69127
69269
  transition: { duration: 0.3 },
69128
69270
  className: "h-full",
69129
- children: React148__default.createElement(WorkspaceGrid, {
69271
+ children: React125__default.createElement(WorkspaceGrid, {
69130
69272
  workspaces: [],
69131
69273
  // Show empty grid while loading
69132
69274
  blueComparisonWorkspaces: [],
@@ -69176,7 +69318,7 @@ function HomeView({
69176
69318
  contentVariant: "plain"
69177
69319
  }
69178
69320
  ),
69179
- /* @__PURE__ */ jsx(AnimatePresence, { children: showAllGreenCelebration ? /* @__PURE__ */ jsxs(React148__default.Fragment, { children: [
69321
+ /* @__PURE__ */ jsx(AnimatePresence, { children: showAllGreenCelebration ? /* @__PURE__ */ jsxs(React125__default.Fragment, { children: [
69180
69322
  /* @__PURE__ */ jsx(
69181
69323
  motion.div,
69182
69324
  {
@@ -69255,7 +69397,7 @@ function HomeView({
69255
69397
  "all-green-center-toast"
69256
69398
  )
69257
69399
  ] }, "all-green-celebration") : null }),
69258
- /* @__PURE__ */ jsx(AnimatePresence, { children: greenStreakMilestoneBanner ? /* @__PURE__ */ jsxs(React148__default.Fragment, { children: [
69400
+ /* @__PURE__ */ jsx(AnimatePresence, { children: greenStreakMilestoneBanner ? /* @__PURE__ */ jsxs(React125__default.Fragment, { children: [
69259
69401
  /* @__PURE__ */ jsx(
69260
69402
  motion.div,
69261
69403
  {
@@ -69349,7 +69491,7 @@ function HomeView({
69349
69491
  }
69350
69492
  );
69351
69493
  }
69352
- var AuthenticatedHomeView = withAuth(React148__default.memo(HomeView));
69494
+ var AuthenticatedHomeView = withAuth(React125__default.memo(HomeView));
69353
69495
  var HomeView_default = HomeView;
69354
69496
  function withWorkspaceDisplayNames(Component3, options = {}) {
69355
69497
  const {
@@ -72613,6 +72755,12 @@ var KPIDetailView_default = KPIDetailViewWithDisplayNames;
72613
72755
  var isNonEmptyString2 = (value) => typeof value === "string" && value.trim().length > 0;
72614
72756
  var KPI_FACTORY_QUERY_PARAM = "factory_id";
72615
72757
  var KPI_FACTORY_AREA_QUERY_PARAM = "factory_area_id";
72758
+ var LINE_STATUS_FILTER_OPTIONS = [
72759
+ { id: "attention", label: "Attention" },
72760
+ { id: "warning", label: "Warning" },
72761
+ { id: "stable", label: "Stable" }
72762
+ ];
72763
+ var DEFAULT_LINE_STATUS_FILTERS = LINE_STATUS_FILTER_OPTIONS.map((option) => option.id);
72616
72764
  var getSingleQueryValue = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
72617
72765
  var resolveCompanyId2 = (...candidates) => candidates.find(isNonEmptyString2);
72618
72766
  var parseTimeToMinutes4 = (value) => {
@@ -72770,19 +72918,36 @@ var LinesLeaderboard = ({
72770
72918
  timezone: _timezone,
72771
72919
  isHistoricalDaily
72772
72920
  }) => {
72921
+ const { user } = useAuth();
72922
+ const isSupervisor = user?.role_level === "supervisor";
72923
+ const isCurrentUserHighlightReady = timeRange === "today" ? !isLoadingToday : !isLoadingMonthly;
72924
+ const isCurrentUserRow = React125__default.useCallback((item) => {
72925
+ if (!isCurrentUserHighlightReady) return false;
72926
+ if (!isSupervisor || !user?.id) return false;
72927
+ if (!item.supervisors) return false;
72928
+ return item.supervisors.some((s) => s.userId === user.id);
72929
+ }, [isCurrentUserHighlightReady, isSupervisor, user?.id]);
72930
+ const renderCurrentUserBadge = () => /* @__PURE__ */ jsx(
72931
+ "span",
72932
+ {
72933
+ className: "inline-flex items-center rounded-full border border-blue-200 bg-blue-50 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-[0.16em] text-blue-700 shadow-sm",
72934
+ "aria-label": "Your leaderboard position",
72935
+ children: "You"
72936
+ }
72937
+ );
72773
72938
  const formatEfficiency = (value) => typeof value === "number" && Number.isFinite(value) ? `${value.toFixed(1)}%` : "--";
72774
- const assignedLineIdSet = React148__default.useMemo(
72939
+ const assignedLineIdSet = React125__default.useMemo(
72775
72940
  () => new Set(assignedLineIds || []),
72776
72941
  [assignedLineIds]
72777
72942
  );
72778
- const canClickLine = React148__default.useCallback(
72943
+ const canClickLine = React125__default.useCallback(
72779
72944
  (lineId) => {
72780
72945
  if (!assignedLineIds) return true;
72781
72946
  return assignedLineIdSet.has(lineId);
72782
72947
  },
72783
72948
  [assignedLineIds, assignedLineIdSet]
72784
72949
  );
72785
- const handleTimeRangeChange = React148__default.useCallback((newRange) => {
72950
+ const handleTimeRangeChange = React125__default.useCallback((newRange) => {
72786
72951
  if (newRange === timeRange) return;
72787
72952
  trackCoreEvent("Leaderboard Time Range Changed", {
72788
72953
  from_range: timeRange,
@@ -72793,11 +72958,11 @@ var LinesLeaderboard = ({
72793
72958
  });
72794
72959
  setTimeRange(newRange);
72795
72960
  }, [timeRange, lines.length, monthlyEfficiencyByLineId, setTimeRange]);
72796
- const canClickLeaderboardRow = React148__default.useCallback(
72961
+ const canClickLeaderboardRow = React125__default.useCallback(
72797
72962
  (item) => item.rowType === "line" && !!item.line && canClickLine(item.line.id),
72798
72963
  [canClickLine]
72799
72964
  );
72800
- const handleLeaderboardLineClick = React148__default.useCallback((item, clickSource) => {
72965
+ const handleLeaderboardLineClick = React125__default.useCallback((item, clickSource) => {
72801
72966
  if (!canClickLeaderboardRow(item) || !item.line) return;
72802
72967
  trackCoreEvent("Leaderboard Line Clicked", {
72803
72968
  line_id: item.line.id,
@@ -72811,8 +72976,8 @@ var LinesLeaderboard = ({
72811
72976
  });
72812
72977
  onLineClick(item.line);
72813
72978
  }, [canClickLeaderboardRow, onLineClick, timeRange]);
72814
- const viewLoadedTrackedRef = React148__default.useRef(null);
72815
- const leaderboardData = React148__default.useMemo(() => {
72979
+ const viewLoadedTrackedRef = React125__default.useRef(null);
72980
+ const leaderboardData = React125__default.useMemo(() => {
72816
72981
  const loading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
72817
72982
  const efficiencyMap = timeRange === "today" ? todayEfficiencyByLineId : monthlyEfficiencyByLineId;
72818
72983
  const fallbackEfficiencyMap = timeRange === "today" ? dailyFallbackEfficiencyByLineId : void 0;
@@ -72856,7 +73021,7 @@ var LinesLeaderboard = ({
72856
73021
  isLoadingToday,
72857
73022
  isLoadingMonthly
72858
73023
  ]);
72859
- React148__default.useEffect(() => {
73024
+ React125__default.useEffect(() => {
72860
73025
  const isLoading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
72861
73026
  const trackingKey = `${timeRange}-${leaderboardData.length}`;
72862
73027
  if (leaderboardData.length > 0 && !isLoading && viewLoadedTrackedRef.current !== trackingKey) {
@@ -72882,7 +73047,7 @@ var LinesLeaderboard = ({
72882
73047
  const countdownFormat = timeRange === "monthly" ? "days" : "clock";
72883
73048
  const countdownFinishedLabel = timeRange === "monthly" ? "Finished" : "Shift ended";
72884
73049
  const showCountdown = timeRange === "monthly" || !isHistoricalDaily;
72885
- const handleCountdownFinished = React148__default.useCallback(() => {
73050
+ const handleCountdownFinished = React125__default.useCallback(() => {
72886
73051
  trackCoreEvent("Leaderboard Countdown Finished", {
72887
73052
  countdown_type: timeRange === "monthly" ? "month_end" : "shift_end",
72888
73053
  time_range: timeRange,
@@ -72909,7 +73074,7 @@ var LinesLeaderboard = ({
72909
73074
  return "bg-white border-gray-100";
72910
73075
  }
72911
73076
  };
72912
- React148__default.useEffect(() => {
73077
+ React125__default.useEffect(() => {
72913
73078
  const style = document.createElement("style");
72914
73079
  style.innerHTML = `
72915
73080
  @keyframes float {
@@ -72975,6 +73140,7 @@ var LinesLeaderboard = ({
72975
73140
  const isSecond = item.rank === 2;
72976
73141
  item.rank === 3;
72977
73142
  const isClickable = canClickLeaderboardRow(item);
73143
+ const isOwnSupervisorRow = isCurrentUserRow(item);
72978
73144
  return /* @__PURE__ */ jsxs(
72979
73145
  "div",
72980
73146
  {
@@ -73011,22 +73177,25 @@ var LinesLeaderboard = ({
73011
73177
  /* @__PURE__ */ jsx("div", { className: `absolute -bottom-2 md:-bottom-3 left-1/2 -translate-x-1/2 w-6 h-6 md:w-8 md:h-8 xl:w-10 xl:h-10 rounded-full flex items-center justify-center text-[10px] md:text-xs lg:text-sm xl:text-base font-extrabold text-white shadow-lg ${isFirst ? "bg-gradient-to-br from-yellow-400 to-yellow-600 ring-2 md:ring-4 ring-yellow-50" : isSecond ? "bg-gradient-to-br from-gray-400 to-gray-600 ring-2 md:ring-4 ring-gray-50" : "bg-gradient-to-br from-orange-400 to-orange-600 ring-2 md:ring-4 ring-orange-50"}`, children: item.rank })
73012
73178
  ] })
73013
73179
  ] }),
73014
- /* @__PURE__ */ jsx(
73180
+ /* @__PURE__ */ jsxs(
73015
73181
  "div",
73016
73182
  {
73017
- className: `flex flex-col items-center w-32 md:w-40 lg:w-48 xl:w-60 px-2 md:px-3 xl:px-4 pb-3 md:pb-4 pt-8 md:pt-10 rounded-2xl border bg-gradient-to-b shadow-2xl backdrop-blur-sm ${getRankColor(item.rank)} ${isFirst ? "h-44 md:h-52 lg:h-60 xl:h-64" : isSecond ? "h-36 md:h-44 lg:h-52 xl:h-56" : "h-28 md:h-36 lg:h-44 xl:h-48"}`,
73018
- children: /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col items-center justify-center w-full", children: [
73019
- /* @__PURE__ */ jsx("h3", { className: `font-bold text-gray-900 text-center line-clamp-1 mb-1 ${isFirst ? "text-xs md:text-sm lg:text-base xl:text-lg" : "text-[10px] md:text-xs lg:text-sm xl:text-base"}`, children: item.supervisorName }),
73020
- /* @__PURE__ */ jsx("p", { className: `text-gray-600 text-center line-clamp-1 font-medium opacity-80 bg-white/50 px-2 md:px-3 py-0.5 rounded-full ${isFirst ? "text-[9px] md:text-[10px] lg:text-xs xl:text-sm mb-2 md:mb-3" : "text-[8px] md:text-[9px] lg:text-[10px] xl:text-xs mb-1 md:mb-2"}`, children: item.displayName }),
73021
- item.rowType === "area" && /* @__PURE__ */ jsxs("span", { className: "mb-1 text-[8px] md:text-[9px] lg:text-[10px] xl:text-xs font-semibold uppercase text-gray-500", children: [
73022
- item.lines.length,
73023
- " lines"
73024
- ] }),
73025
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center mt-auto", children: [
73026
- /* @__PURE__ */ jsx("span", { className: `font-bold uppercase tracking-widest mb-0.5 ${isFirst ? "text-yellow-700/70 text-[8px] md:text-[9px] lg:text-[10px] xl:text-xs" : isSecond ? "text-gray-600/70 text-[7px] md:text-[8px] lg:text-[9px] xl:text-[10px]" : "text-orange-700/70 text-[7px] md:text-[8px] lg:text-[9px] xl:text-[10px]"}`, children: viewType === "machine" ? "Utilization" : "Efficiency" }),
73027
- /* @__PURE__ */ jsx("span", { className: `font-black tracking-tight leading-none ${isFirst ? "text-lg md:text-xl lg:text-2xl xl:text-3xl text-transparent bg-clip-text bg-gradient-to-br from-yellow-600 to-yellow-800 drop-shadow-sm" : isSecond ? "text-base md:text-lg lg:text-xl xl:text-2xl text-transparent bg-clip-text bg-gradient-to-br from-gray-600 to-gray-800 drop-shadow-sm" : "text-sm md:text-base lg:text-lg xl:text-xl text-transparent bg-clip-text bg-gradient-to-br from-orange-600 to-orange-800 drop-shadow-sm"}`, children: formatEfficiency(item.efficiency) })
73183
+ className: `relative flex flex-col items-center w-32 md:w-40 lg:w-48 xl:w-60 px-2 md:px-3 xl:px-4 pb-3 md:pb-4 pt-8 md:pt-10 rounded-2xl border bg-gradient-to-b shadow-2xl backdrop-blur-sm ${getRankColor(item.rank)} ${isOwnSupervisorRow ? "!border-blue-300 ring-2 ring-blue-500/20 shadow-[0_16px_45px_rgba(37,99,235,0.16)]" : ""} ${isFirst ? "h-44 md:h-52 lg:h-60 xl:h-64" : isSecond ? "h-36 md:h-44 lg:h-52 xl:h-56" : "h-28 md:h-36 lg:h-44 xl:h-48"}`,
73184
+ children: [
73185
+ isOwnSupervisorRow && /* @__PURE__ */ jsx("div", { className: "absolute right-3 top-3", children: renderCurrentUserBadge() }),
73186
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col items-center justify-center w-full", children: [
73187
+ /* @__PURE__ */ jsx("h3", { className: `font-bold text-gray-900 text-center line-clamp-1 mb-1 ${isFirst ? "text-xs md:text-sm lg:text-base xl:text-lg" : "text-[10px] md:text-xs lg:text-sm xl:text-base"}`, children: item.supervisorName }),
73188
+ /* @__PURE__ */ jsx("p", { className: `text-gray-600 text-center line-clamp-1 font-medium opacity-80 bg-white/50 px-2 md:px-3 py-0.5 rounded-full ${isFirst ? "text-[9px] md:text-[10px] lg:text-xs xl:text-sm mb-2 md:mb-3" : "text-[8px] md:text-[9px] lg:text-[10px] xl:text-xs mb-1 md:mb-2"}`, children: item.displayName }),
73189
+ item.rowType === "area" && /* @__PURE__ */ jsxs("span", { className: "mb-1 text-[8px] md:text-[9px] lg:text-[10px] xl:text-xs font-semibold uppercase text-gray-500", children: [
73190
+ item.lines.length,
73191
+ " lines"
73192
+ ] }),
73193
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center mt-auto", children: [
73194
+ /* @__PURE__ */ jsx("span", { className: `font-bold uppercase tracking-widest mb-0.5 ${isFirst ? "text-yellow-700/70 text-[8px] md:text-[9px] lg:text-[10px] xl:text-xs" : isSecond ? "text-gray-600/70 text-[7px] md:text-[8px] lg:text-[9px] xl:text-[10px]" : "text-orange-700/70 text-[7px] md:text-[8px] lg:text-[9px] xl:text-[10px]"}`, children: viewType === "machine" ? "Utilization" : "Efficiency" }),
73195
+ /* @__PURE__ */ jsx("span", { className: `font-black tracking-tight leading-none ${isFirst ? "text-lg md:text-xl lg:text-2xl xl:text-3xl text-transparent bg-clip-text bg-gradient-to-br from-yellow-600 to-yellow-800 drop-shadow-sm" : isSecond ? "text-base md:text-lg lg:text-xl xl:text-2xl text-transparent bg-clip-text bg-gradient-to-br from-gray-600 to-gray-800 drop-shadow-sm" : "text-sm md:text-base lg:text-lg xl:text-xl text-transparent bg-clip-text bg-gradient-to-br from-orange-600 to-orange-800 drop-shadow-sm"}`, children: formatEfficiency(item.efficiency) })
73196
+ ] })
73028
73197
  ] })
73029
- ] })
73198
+ ]
73030
73199
  }
73031
73200
  )
73032
73201
  ]
@@ -73045,11 +73214,12 @@ var LinesLeaderboard = ({
73045
73214
  /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-gray-100", children: leaderboardData.map((item) => {
73046
73215
  const isTopThree = item.rank <= 3;
73047
73216
  const isClickable = canClickLeaderboardRow(item);
73217
+ const isOwnSupervisorRow = isCurrentUserRow(item);
73048
73218
  return /* @__PURE__ */ jsxs(
73049
73219
  "tr",
73050
73220
  {
73051
73221
  onClick: () => handleLeaderboardLineClick(item, isTopThree ? "podium" : "table"),
73052
- className: `transition-colors ${isTopThree ? "sm:hidden" : ""} ${isClickable ? "hover:bg-gray-50 cursor-pointer group" : "cursor-not-allowed"}`,
73222
+ className: `transition-colors ${isTopThree ? "sm:hidden" : ""} ${isOwnSupervisorRow ? "bg-blue-50/80 ring-inset ring-1 ring-blue-500/20 shadow-[inset_3px_0_0_rgba(37,99,235,0.75)]" : ""} ${isClickable ? isOwnSupervisorRow ? "hover:bg-blue-100/80 cursor-pointer group" : "hover:bg-gray-50 cursor-pointer group" : "cursor-not-allowed"}`,
73053
73223
  children: [
73054
73224
  /* @__PURE__ */ jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center w-8 h-8 rounded-full bg-gray-100 text-gray-600 font-bold text-sm", children: item.rank }) }),
73055
73225
  /* @__PURE__ */ jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
@@ -73074,7 +73244,8 @@ var LinesLeaderboard = ({
73074
73244
  item.supervisors.length - 3
73075
73245
  ] })
73076
73246
  ] }) : /* @__PURE__ */ jsx("div", { className: "w-8 h-8 rounded-full bg-gray-100 flex items-center justify-center text-gray-500 overflow-hidden border border-gray-200 flex-shrink-0", children: item.supervisorImage ? /* @__PURE__ */ jsx("img", { src: item.supervisorImage, alt: item.supervisorName, className: "w-full h-full object-cover" }) : /* @__PURE__ */ jsx("span", { className: "text-xs font-bold", children: getInitials(item.supervisorName) }) }),
73077
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-900", children: item.supervisorName })
73247
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-900", children: item.supervisorName }),
73248
+ isOwnSupervisorRow && renderCurrentUserBadge()
73078
73249
  ] }) }),
73079
73250
  /* @__PURE__ */ jsx("td", { className: "px-4 py-3 whitespace-nowrap text-sm text-gray-500", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
73080
73251
  /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-700", children: item.displayName }),
@@ -73371,14 +73542,26 @@ var KPIsOverviewView = ({
73371
73542
  const [activeTab, setActiveTab] = useState("today");
73372
73543
  const [timeRange, setTimeRange] = useState("today");
73373
73544
  const [viewType, setViewType] = useState("operator");
73545
+ const [selectedLineStatusFilters, setSelectedLineStatusFilters] = useState(DEFAULT_LINE_STATUS_FILTERS);
73546
+ const [selectedFactoryFilters, setSelectedFactoryFilters] = useState([]);
73547
+ const [hasUserEditedFactoryFilters, setHasUserEditedFactoryFilters] = useState(false);
73548
+ const [todayViewLevel, setTodayViewLevel] = useState("factory");
73549
+ const [efficiencySortDirection, setEfficiencySortDirection] = useState("desc");
73374
73550
  const [selectedLeaderboardDate, setSelectedLeaderboardDate] = useState("");
73375
73551
  const [selectedLeaderboardShiftId, setSelectedLeaderboardShiftId] = useState(0);
73376
73552
  const [leaderboardDailyScopeMode, setLeaderboardDailyScopeMode] = useState("live");
73377
73553
  const [hasHydratedLeaderboardRouteState, setHasHydratedLeaderboardRouteState] = useState(false);
73378
73554
  const [loading, setLoading] = useState(true);
73379
73555
  const [isFilterOpen, setIsFilterOpen] = useState(false);
73556
+ const [isViewsOpen, setIsViewsOpen] = useState(false);
73557
+ const [isSortOpen, setIsSortOpen] = useState(false);
73380
73558
  const filterRef = useRef(null);
73381
73559
  const filterButtonRef = useRef(null);
73560
+ const viewsRef = useRef(null);
73561
+ const viewsButtonRef = useRef(null);
73562
+ const sortRef = useRef(null);
73563
+ const sortButtonRef = useRef(null);
73564
+ const previousFactoryFilterOptionIdsRef = useRef([]);
73382
73565
  const [error, setError] = useState(null);
73383
73566
  const [todayEfficiencyByLineId, setTodayEfficiencyByLineId] = useState(/* @__PURE__ */ new Map());
73384
73567
  const [dailyLoading, setDailyLoading] = useState(false);
@@ -73408,36 +73591,36 @@ var KPIsOverviewView = ({
73408
73591
  const configuredTimezone = dbTimezone || dateTimeConfig.defaultTimezone || "UTC";
73409
73592
  const { startDate: monthStartDate, endDate: monthEndDateKey, monthEndDate } = getMonthDateInfo(configuredTimezone);
73410
73593
  const isSuperAdmin = user?.scope_mode === "SUPER_ADMIN" || !!user?.access_scope?.is_super_admin;
73411
- const scopedLineIds = React148__default.useMemo(
73594
+ const scopedLineIds = React125__default.useMemo(
73412
73595
  () => Array.isArray(user?.access_scope?.line_ids) ? user.access_scope.line_ids.filter((lineId) => typeof lineId === "string" && lineId.length > 0) : [],
73413
73596
  [user?.access_scope?.line_ids]
73414
73597
  );
73415
73598
  const hasCanonicalScope = !!user?.scope_mode || !!user?.access_scope;
73416
73599
  const scopeRole = (user?.role_level || user?.role || "").toLowerCase();
73417
73600
  const isStrictLineScopedRole = scopeRole === "supervisor" || isFactoryScopedRole(scopeRole);
73418
- const resolvedAssignedLineIds = React148__default.useMemo(() => {
73601
+ const resolvedAssignedLineIds = React125__default.useMemo(() => {
73419
73602
  if (isSuperAdmin) return [];
73420
73603
  if (scopedLineIds.length > 0) return scopedLineIds;
73421
73604
  if (lineIds && lineIds.length > 0) return lineIds;
73422
73605
  if (isStrictLineScopedRole && hasCanonicalScope) return [];
73423
73606
  return [];
73424
73607
  }, [isSuperAdmin, scopedLineIds, lineIds, isStrictLineScopedRole, hasCanonicalScope]);
73425
- const assignedLineIdSet = React148__default.useMemo(
73608
+ const assignedLineIdSet = React125__default.useMemo(
73426
73609
  () => new Set(resolvedAssignedLineIds),
73427
73610
  [resolvedAssignedLineIds]
73428
73611
  );
73429
- const loadedLineIds = React148__default.useMemo(
73612
+ const loadedLineIds = React125__default.useMemo(
73430
73613
  () => lines.map((line) => line.id).filter(Boolean),
73431
73614
  [lines]
73432
73615
  );
73433
- const metricsLineIds = React148__default.useMemo(() => {
73616
+ const metricsLineIds = React125__default.useMemo(() => {
73434
73617
  if (isSuperAdmin) {
73435
73618
  return loadedLineIds.length > 0 ? loadedLineIds : lineIds ?? [];
73436
73619
  }
73437
73620
  return resolvedAssignedLineIds;
73438
73621
  }, [isSuperAdmin, loadedLineIds, lineIds, resolvedAssignedLineIds]);
73439
73622
  const assignedLineIdsForLeaderboard = isSuperAdmin ? void 0 : resolvedAssignedLineIds;
73440
- const leaderboardLinesForView = React148__default.useMemo(() => {
73623
+ const leaderboardLinesForView = React125__default.useMemo(() => {
73441
73624
  const targetMode = viewType === "machine" ? "uptime" : "output";
73442
73625
  const metadataByLineId = new Map(lines.map((line) => [line.id, line]));
73443
73626
  return leaderboardLines.map((line) => {
@@ -73456,17 +73639,57 @@ var KPIsOverviewView = ({
73456
73639
  } : line;
73457
73640
  }).filter((line) => (line.monitoring_mode ?? "output") === targetMode);
73458
73641
  }, [leaderboardLines, lines, viewType]);
73459
- const linesForView = React148__default.useMemo(() => {
73642
+ const linesForView = React125__default.useMemo(() => {
73460
73643
  const targetMode = viewType === "machine" ? "uptime" : "output";
73461
73644
  return lines.filter((line) => (line.monitoring_mode ?? "output") === targetMode);
73462
73645
  }, [lines, viewType]);
73463
- const relevantLinesForMode = React148__default.useMemo(() => {
73646
+ const factoryFilterOptions = React125__default.useMemo(() => {
73647
+ const factories = /* @__PURE__ */ new Map();
73648
+ linesForView.forEach((line) => {
73649
+ const factoryId = line.factory_id || "unknown-factory";
73650
+ if (!factories.has(factoryId)) {
73651
+ factories.set(factoryId, line.factory_name || "Factory");
73652
+ }
73653
+ });
73654
+ return Array.from(factories.entries()).map(([id3, label]) => ({ id: id3, label })).sort((left, right) => left.label.localeCompare(right.label, void 0, { sensitivity: "base", numeric: true }));
73655
+ }, [linesForView]);
73656
+ const factoryFilterOptionIds = React125__default.useMemo(
73657
+ () => factoryFilterOptions.map((option) => option.id),
73658
+ [factoryFilterOptions]
73659
+ );
73660
+ const effectiveSelectedFactoryFilters = React125__default.useMemo(
73661
+ () => hasUserEditedFactoryFilters ? selectedFactoryFilters : factoryFilterOptionIds,
73662
+ [factoryFilterOptionIds, hasUserEditedFactoryFilters, selectedFactoryFilters]
73663
+ );
73664
+ useEffect(() => {
73665
+ const previousFactoryFilterOptionIds = previousFactoryFilterOptionIdsRef.current;
73666
+ if (factoryFilterOptionIds.length === 0) {
73667
+ setHasUserEditedFactoryFilters(false);
73668
+ }
73669
+ setSelectedFactoryFilters((previousFilters) => {
73670
+ if (factoryFilterOptionIds.length === 0) {
73671
+ return previousFilters.length === 0 ? previousFilters : [];
73672
+ }
73673
+ if (!hasUserEditedFactoryFilters) {
73674
+ return factoryFilterOptionIds;
73675
+ }
73676
+ const validFactoryIds = new Set(factoryFilterOptionIds);
73677
+ const previousFactoryIds = new Set(previousFactoryFilterOptionIds);
73678
+ const nextFilters = [
73679
+ ...previousFilters.filter((factoryId) => validFactoryIds.has(factoryId)),
73680
+ ...factoryFilterOptionIds.filter((factoryId) => !previousFactoryIds.has(factoryId))
73681
+ ];
73682
+ return nextFilters.length === previousFilters.length ? previousFilters : nextFilters;
73683
+ });
73684
+ previousFactoryFilterOptionIdsRef.current = factoryFilterOptionIds;
73685
+ }, [factoryFilterOptionIds, hasUserEditedFactoryFilters]);
73686
+ const relevantLinesForMode = React125__default.useMemo(() => {
73464
73687
  if (activeTab === "leaderboard") {
73465
73688
  return leaderboardLines.length > 0 ? leaderboardLines : lines;
73466
73689
  }
73467
73690
  return lines;
73468
73691
  }, [activeTab, leaderboardLines, lines]);
73469
- const { hasUptime, hasOutput } = React148__default.useMemo(() => {
73692
+ const { hasUptime, hasOutput } = React125__default.useMemo(() => {
73470
73693
  let uptime = false;
73471
73694
  let output = false;
73472
73695
  for (const line of relevantLinesForMode) {
@@ -73491,18 +73714,42 @@ var KPIsOverviewView = ({
73491
73714
  const currentShiftDetails = getCurrentShift(configuredTimezone, shiftConfig);
73492
73715
  const currentShiftDate = currentShiftDetails.date;
73493
73716
  const currentShiftId = currentShiftDetails.shiftId;
73494
- const activeFiltersCount = React148__default.useMemo(() => {
73717
+ const activeFiltersCount = React125__default.useMemo(() => {
73495
73718
  let count = 0;
73496
- if (leaderboardDailyScopeMode === "historical" && selectedLeaderboardShiftId !== currentShiftId) {
73719
+ if (activeTab === "today" && selectedLineStatusFilters.length !== LINE_STATUS_FILTER_OPTIONS.length) {
73720
+ count++;
73721
+ }
73722
+ if (activeTab === "today" && factoryFilterOptions.length > 0 && effectiveSelectedFactoryFilters.length !== factoryFilterOptions.length) {
73723
+ count++;
73724
+ }
73725
+ if (activeTab === "leaderboard" && leaderboardDailyScopeMode === "historical" && selectedLeaderboardShiftId !== currentShiftId) {
73497
73726
  count++;
73498
73727
  }
73499
73728
  return count;
73500
- }, [leaderboardDailyScopeMode, selectedLeaderboardShiftId, currentShiftId]);
73501
- const clearFilters = React148__default.useCallback(() => {
73729
+ }, [activeTab, selectedLineStatusFilters.length, factoryFilterOptions.length, effectiveSelectedFactoryFilters.length, leaderboardDailyScopeMode, selectedLeaderboardShiftId, currentShiftId]);
73730
+ const activeSortCount = React125__default.useMemo(() => activeTab === "today" && efficiencySortDirection !== "desc" ? 1 : 0, [activeTab, efficiencySortDirection]);
73731
+ const clearFilters = React125__default.useCallback(() => {
73732
+ trackCoreEvent("Lines Overview Filters Cleared", {
73733
+ surface: "lines_overview",
73734
+ action: "clear_filters",
73735
+ control_clicked: "filters",
73736
+ option_clicked: "clear_all",
73737
+ option_label: "Clear all",
73738
+ source: "filters_dropdown",
73739
+ active_tab: activeTab,
73740
+ previous_status_filters: selectedLineStatusFilters,
73741
+ previous_factory_filters: effectiveSelectedFactoryFilters,
73742
+ selected_shift_id: selectedLeaderboardShiftId,
73743
+ selected_view_level: todayViewLevel,
73744
+ selected_sort_direction: efficiencySortDirection
73745
+ });
73746
+ setSelectedLineStatusFilters(DEFAULT_LINE_STATUS_FILTERS);
73747
+ setHasUserEditedFactoryFilters(false);
73748
+ setSelectedFactoryFilters(factoryFilterOptionIds);
73502
73749
  setSelectedLeaderboardShiftId(currentShiftId);
73503
73750
  setSelectedLeaderboardDate(currentShiftDate);
73504
73751
  setLeaderboardDailyScopeMode("live");
73505
- }, [currentShiftDate, currentShiftId]);
73752
+ }, [activeTab, currentShiftDate, currentShiftId, effectiveSelectedFactoryFilters, efficiencySortDirection, factoryFilterOptionIds, selectedLineStatusFilters, selectedLeaderboardShiftId, todayViewLevel]);
73506
73753
  useEffect(() => {
73507
73754
  const handleClickOutside = (event) => {
73508
73755
  const target = event.target;
@@ -73510,15 +73757,23 @@ var KPIsOverviewView = ({
73510
73757
  if (filterRef.current && !filterRef.current.contains(target)) {
73511
73758
  setIsFilterOpen(false);
73512
73759
  }
73760
+ if (viewsButtonRef.current?.contains(target)) return;
73761
+ if (viewsRef.current && !viewsRef.current.contains(target)) {
73762
+ setIsViewsOpen(false);
73763
+ }
73764
+ if (sortButtonRef.current?.contains(target)) return;
73765
+ if (sortRef.current && !sortRef.current.contains(target)) {
73766
+ setIsSortOpen(false);
73767
+ }
73513
73768
  };
73514
73769
  document.addEventListener("mousedown", handleClickOutside);
73515
73770
  return () => document.removeEventListener("mousedown", handleClickOutside);
73516
73771
  }, []);
73517
- const shiftEndDate = React148__default.useMemo(
73772
+ const shiftEndDate = React125__default.useMemo(
73518
73773
  () => getShiftEndDate(currentShiftDetails, configuredTimezone),
73519
73774
  [currentShiftDetails, configuredTimezone]
73520
73775
  );
73521
- const leaderboardShiftOptions = React148__default.useMemo(() => {
73776
+ const leaderboardShiftOptions = React125__default.useMemo(() => {
73522
73777
  if (shiftConfig?.shifts && shiftConfig.shifts.length > 0) {
73523
73778
  return shiftConfig.shifts.map((shift) => ({
73524
73779
  id: shift.shiftId,
@@ -73535,37 +73790,42 @@ var KPIsOverviewView = ({
73535
73790
  const effectiveLeaderboardDate = selectedLeaderboardDate || currentShiftDate;
73536
73791
  const effectiveLeaderboardShiftId = Number.isFinite(selectedLeaderboardShiftId) ? selectedLeaderboardShiftId : currentShiftId;
73537
73792
  const isHistoricalLeaderboardDaily = activeTab === "leaderboard" && timeRange === "today" && leaderboardDailyScopeMode === "historical" && (effectiveLeaderboardDate !== currentShiftDate || effectiveLeaderboardShiftId !== currentShiftId);
73538
- const updateLeaderboardDate = React148__default.useCallback((dateKey) => {
73793
+ const updateLeaderboardDate = React125__default.useCallback((dateKey) => {
73539
73794
  setSelectedLeaderboardDate(dateKey);
73540
73795
  setLeaderboardDailyScopeMode(
73541
73796
  dateKey === currentShiftDate && effectiveLeaderboardShiftId === currentShiftId ? "live" : "historical"
73542
73797
  );
73543
73798
  }, [currentShiftDate, currentShiftId, effectiveLeaderboardShiftId]);
73544
- const updateLeaderboardShiftId = React148__default.useCallback((shiftId) => {
73799
+ const updateLeaderboardShiftId = React125__default.useCallback((shiftId) => {
73545
73800
  setSelectedLeaderboardShiftId(shiftId);
73546
73801
  setLeaderboardDailyScopeMode(
73547
73802
  effectiveLeaderboardDate === currentShiftDate && shiftId === currentShiftId ? "live" : "historical"
73548
73803
  );
73549
73804
  }, [currentShiftDate, currentShiftId, effectiveLeaderboardDate]);
73550
- const returnLeaderboardToLive = React148__default.useCallback(() => {
73805
+ const returnLeaderboardToLive = React125__default.useCallback(() => {
73551
73806
  setSelectedLeaderboardDate(currentShiftDate);
73552
73807
  setSelectedLeaderboardShiftId(currentShiftId);
73553
73808
  setLeaderboardDailyScopeMode("live");
73554
73809
  }, [currentShiftDate, currentShiftId]);
73555
73810
  const selectedFactoryIdFromUrl = getSingleQueryValue(router.query[KPI_FACTORY_QUERY_PARAM]);
73556
73811
  const selectedFactoryAreaIdFromUrl = getSingleQueryValue(router.query[KPI_FACTORY_AREA_QUERY_PARAM]);
73557
- const kpiLineHierarchy = React148__default.useMemo(
73812
+ const kpiLineHierarchy = React125__default.useMemo(
73558
73813
  () => buildKpiLineHierarchy(linesForView),
73559
73814
  [linesForView]
73560
73815
  );
73561
- const selectedFactoryNode = React148__default.useMemo(
73816
+ const selectedFactoryNode = React125__default.useMemo(
73562
73817
  () => kpiLineHierarchy.showFactoryLevel && selectedFactoryIdFromUrl ? kpiLineHierarchy.factories.find((factory) => factory.id === selectedFactoryIdFromUrl) : void 0,
73563
73818
  [kpiLineHierarchy, selectedFactoryIdFromUrl]
73564
73819
  );
73565
- const selectedFactoryAreaNode = React148__default.useMemo(
73820
+ const selectedFactoryAreaNode = React125__default.useMemo(
73566
73821
  () => selectedFactoryNode && selectedFactoryAreaIdFromUrl ? selectedFactoryNode.areas.find((area) => area.id === selectedFactoryAreaIdFromUrl) : void 0,
73567
73822
  [selectedFactoryNode, selectedFactoryAreaIdFromUrl]
73568
73823
  );
73824
+ useEffect(() => {
73825
+ if (!kpiLineHierarchy.showFactoryLevel && todayViewLevel !== "factory") {
73826
+ setTodayViewLevel("factory");
73827
+ }
73828
+ }, [kpiLineHierarchy.showFactoryLevel, todayViewLevel]);
73569
73829
  useEffect(() => {
73570
73830
  if (!router.isReady) return;
73571
73831
  const tabQuery = router.query.tab;
@@ -73651,15 +73911,15 @@ var KPIsOverviewView = ({
73651
73911
  lineId: factoryViewId,
73652
73912
  userAccessibleLineIds: metricsLineIds
73653
73913
  });
73654
- const defaultKPIs = React148__default.useMemo(() => createDefaultKPIs(), []);
73655
- const lineModeById = React148__default.useMemo(() => {
73914
+ const defaultKPIs = React125__default.useMemo(() => createDefaultKPIs(), []);
73915
+ const lineModeById = React125__default.useMemo(() => {
73656
73916
  const map = /* @__PURE__ */ new Map();
73657
73917
  linesForView.forEach((line) => {
73658
73918
  map.set(line.id, line.monitoring_mode ?? "output");
73659
73919
  });
73660
73920
  return map;
73661
73921
  }, [linesForView]);
73662
- const lineMetricRowsByLineId = React148__default.useMemo(() => {
73922
+ const lineMetricRowsByLineId = React125__default.useMemo(() => {
73663
73923
  const map = /* @__PURE__ */ new Map();
73664
73924
  lineMetrics.forEach((row) => {
73665
73925
  if (!row?.line_id) return;
@@ -73671,7 +73931,7 @@ var KPIsOverviewView = ({
73671
73931
  });
73672
73932
  return map;
73673
73933
  }, [lineMetrics, lineModeById]);
73674
- const liveDailyFallbackEfficiencyByLineId = React148__default.useMemo(() => {
73934
+ const liveDailyFallbackEfficiencyByLineId = React125__default.useMemo(() => {
73675
73935
  const map = /* @__PURE__ */ new Map();
73676
73936
  lineMetricRowsByLineId.forEach((row, lineId) => {
73677
73937
  const value = Number(row?.avg_efficiency);
@@ -73693,31 +73953,31 @@ var KPIsOverviewView = ({
73693
73953
  isHistoricalLeaderboardDaily,
73694
73954
  lineMetricRowsByLineId
73695
73955
  ]);
73696
- const dailyFallbackEfficiencyByLineId = React148__default.useMemo(() => {
73956
+ const dailyFallbackEfficiencyByLineId = React125__default.useMemo(() => {
73697
73957
  const map = new Map(liveDailyFallbackEfficiencyByLineId);
73698
73958
  scopedDailyFallbackEfficiencyByLineId.forEach((value, lineId) => {
73699
73959
  map.set(lineId, value);
73700
73960
  });
73701
73961
  return map;
73702
73962
  }, [liveDailyFallbackEfficiencyByLineId, scopedDailyFallbackEfficiencyByLineId]);
73703
- const kpisByLineId = React148__default.useMemo(() => {
73963
+ const kpisByLineId = React125__default.useMemo(() => {
73704
73964
  const map = /* @__PURE__ */ new Map();
73705
73965
  lineMetricRowsByLineId.forEach((row, lineId) => {
73706
73966
  map.set(lineId, buildKPIsFromLineMetricsRow(row));
73707
73967
  });
73708
73968
  return map;
73709
73969
  }, [lineMetricRowsByLineId]);
73710
- const getLineCardKpis = React148__default.useCallback((line) => {
73970
+ const getLineCardKpis = React125__default.useCallback((line) => {
73711
73971
  if (metricsError) return null;
73712
73972
  return kpisByLineId.get(line.id) ?? (metricsLoading ? null : defaultKPIs);
73713
73973
  }, [defaultKPIs, kpisByLineId, metricsError, metricsLoading]);
73714
- const getAggregateCardKpis = React148__default.useCallback((cardLines) => {
73974
+ const getAggregateCardKpis = React125__default.useCallback((cardLines) => {
73715
73975
  if (metricsError) return null;
73716
73976
  const rows = cardLines.map((line) => lineMetricRowsByLineId.get(line.id)).filter(Boolean);
73717
73977
  if (metricsLoading && rows.length === 0) return null;
73718
73978
  return aggregateKPIsFromLineMetricsRows(rows);
73719
73979
  }, [lineMetricRowsByLineId, metricsError, metricsLoading]);
73720
- const supervisorLineIds = React148__default.useMemo(
73980
+ const supervisorLineIds = React125__default.useMemo(
73721
73981
  () => (leaderboardLines.length > 0 ? leaderboardLines : lines).map((l) => l.id),
73722
73982
  [leaderboardLines, lines]
73723
73983
  );
@@ -73969,7 +74229,135 @@ var KPIsOverviewView = ({
73969
74229
  { shallow: true }
73970
74230
  );
73971
74231
  }, [router]);
73972
- const lineDetailReturnTo = React148__default.useMemo(() => {
74232
+ const handleLineStatusFilterToggle = useCallback((status) => {
74233
+ setSelectedLineStatusFilters((previousStatuses) => {
74234
+ const optionLabel = LINE_STATUS_FILTER_OPTIONS.find((option) => option.id === status)?.label ?? status;
74235
+ const wasSelected = previousStatuses.includes(status);
74236
+ const nextStatuses = previousStatuses.includes(status) ? previousStatuses.filter((item) => item !== status) : [...previousStatuses, status];
74237
+ trackCoreEvent("Lines Overview Filter Changed", {
74238
+ surface: "lines_overview",
74239
+ action: "toggle_status_filter",
74240
+ control_clicked: "filters",
74241
+ source: "filters_dropdown",
74242
+ filter_group: "status",
74243
+ option_clicked: status,
74244
+ option_label: optionLabel,
74245
+ option_selected: !wasSelected,
74246
+ toggled_status: status,
74247
+ previous_status_filters: previousStatuses,
74248
+ selected_status_filters: nextStatuses,
74249
+ selected_factory_filters: effectiveSelectedFactoryFilters,
74250
+ selected_view_level: todayViewLevel,
74251
+ selected_sort_direction: efficiencySortDirection
74252
+ });
74253
+ return nextStatuses;
74254
+ });
74255
+ }, [effectiveSelectedFactoryFilters, efficiencySortDirection, todayViewLevel]);
74256
+ const handleFactoryFilterToggle = useCallback((factoryId) => {
74257
+ setHasUserEditedFactoryFilters(true);
74258
+ setSelectedFactoryFilters((previousFactoryFilters) => {
74259
+ const baseFactoryFilters = hasUserEditedFactoryFilters ? previousFactoryFilters : factoryFilterOptionIds;
74260
+ const optionLabel = factoryFilterOptions.find((option) => option.id === factoryId)?.label ?? factoryId;
74261
+ const wasSelected = baseFactoryFilters.includes(factoryId);
74262
+ const nextFactoryFilters = baseFactoryFilters.includes(factoryId) ? baseFactoryFilters.filter((item) => item !== factoryId) : [...baseFactoryFilters, factoryId];
74263
+ trackCoreEvent("Lines Overview Filter Changed", {
74264
+ surface: "lines_overview",
74265
+ action: "toggle_factory",
74266
+ control_clicked: "filters",
74267
+ source: "filters_dropdown",
74268
+ filter_group: "factory",
74269
+ option_clicked: factoryId,
74270
+ option_label: optionLabel,
74271
+ option_selected: !wasSelected,
74272
+ toggled_factory_id: factoryId,
74273
+ toggled_factory_name: optionLabel,
74274
+ previous_factory_filters: baseFactoryFilters,
74275
+ selected_factory_filters: nextFactoryFilters,
74276
+ selected_status_filters: selectedLineStatusFilters,
74277
+ selected_view_level: todayViewLevel,
74278
+ selected_sort_direction: efficiencySortDirection
74279
+ });
74280
+ return nextFactoryFilters;
74281
+ });
74282
+ }, [efficiencySortDirection, factoryFilterOptionIds, factoryFilterOptions, hasUserEditedFactoryFilters, selectedLineStatusFilters, todayViewLevel]);
74283
+ const handleTodayViewLevelChange = useCallback((nextViewLevel) => {
74284
+ const viewLevelLabels = {
74285
+ factory: "Factory level",
74286
+ units: "Area level"
74287
+ };
74288
+ trackCoreEvent("Lines Overview View Option Clicked", {
74289
+ surface: "lines_overview",
74290
+ action: "click_view_option",
74291
+ control_clicked: "views",
74292
+ source: "views_dropdown",
74293
+ option_clicked: nextViewLevel,
74294
+ option_label: viewLevelLabels[nextViewLevel],
74295
+ previous_view_level: todayViewLevel,
74296
+ selected_view_level: nextViewLevel,
74297
+ option_selected: nextViewLevel !== todayViewLevel,
74298
+ selected_factory_filters: effectiveSelectedFactoryFilters,
74299
+ selected_status_filters: selectedLineStatusFilters,
74300
+ selected_sort_direction: efficiencySortDirection
74301
+ });
74302
+ if (nextViewLevel === todayViewLevel) {
74303
+ return;
74304
+ }
74305
+ trackCoreEvent("Lines Overview View Changed", {
74306
+ surface: "lines_overview",
74307
+ action: "select_view_level",
74308
+ control_clicked: "views",
74309
+ source: "views_dropdown",
74310
+ option_clicked: nextViewLevel,
74311
+ option_label: viewLevelLabels[nextViewLevel],
74312
+ previous_view_level: todayViewLevel,
74313
+ selected_view_level: nextViewLevel,
74314
+ selected_factory_filters: effectiveSelectedFactoryFilters,
74315
+ selected_status_filters: selectedLineStatusFilters,
74316
+ selected_sort_direction: efficiencySortDirection
74317
+ });
74318
+ setTodayViewLevel(nextViewLevel);
74319
+ navigateTodayHierarchy();
74320
+ }, [effectiveSelectedFactoryFilters, efficiencySortDirection, navigateTodayHierarchy, selectedLineStatusFilters, todayViewLevel]);
74321
+ const handleEfficiencySortChange = useCallback((nextSortDirection) => {
74322
+ const sortLabels = {
74323
+ desc: "Highest to lowest",
74324
+ asc: "Lowest to highest"
74325
+ };
74326
+ trackCoreEvent("Lines Overview Sort Option Clicked", {
74327
+ surface: "lines_overview",
74328
+ action: "click_sort_option",
74329
+ control_clicked: "sort",
74330
+ source: "sort_dropdown",
74331
+ sort_metric: "efficiency",
74332
+ option_clicked: nextSortDirection,
74333
+ option_label: sortLabels[nextSortDirection],
74334
+ previous_sort_direction: efficiencySortDirection,
74335
+ selected_sort_direction: nextSortDirection,
74336
+ option_selected: nextSortDirection !== efficiencySortDirection,
74337
+ selected_factory_filters: effectiveSelectedFactoryFilters,
74338
+ selected_status_filters: selectedLineStatusFilters,
74339
+ selected_view_level: todayViewLevel
74340
+ });
74341
+ if (nextSortDirection === efficiencySortDirection) {
74342
+ return;
74343
+ }
74344
+ trackCoreEvent("Lines Overview Sort Changed", {
74345
+ surface: "lines_overview",
74346
+ action: "select_efficiency_sort",
74347
+ control_clicked: "sort",
74348
+ source: "sort_dropdown",
74349
+ sort_metric: "efficiency",
74350
+ option_clicked: nextSortDirection,
74351
+ option_label: sortLabels[nextSortDirection],
74352
+ previous_sort_direction: efficiencySortDirection,
74353
+ selected_sort_direction: nextSortDirection,
74354
+ selected_factory_filters: effectiveSelectedFactoryFilters,
74355
+ selected_status_filters: selectedLineStatusFilters,
74356
+ selected_view_level: todayViewLevel
74357
+ });
74358
+ setEfficiencySortDirection(nextSortDirection);
74359
+ }, [effectiveSelectedFactoryFilters, efficiencySortDirection, selectedLineStatusFilters, todayViewLevel]);
74360
+ const lineDetailReturnTo = React125__default.useMemo(() => {
73973
74361
  if (activeTab !== "today" || !selectedFactoryNode) return void 0;
73974
74362
  return createKpisOverviewUrl({
73975
74363
  factoryId: selectedFactoryNode.id,
@@ -74059,6 +74447,19 @@ var KPIsOverviewView = ({
74059
74447
  const headerShiftId = showHistoricalLeaderboardHeader ? effectiveLeaderboardShiftId : currentShiftDetails.shiftId;
74060
74448
  const headerShiftName = getShiftNameById(headerShiftId, configuredTimezone, shiftConfig).replace(/ Shift$/i, "");
74061
74449
  const headerDateLabel = isMonthlyMode ? getMonthRange() : formatLocalDate2(headerDateKey);
74450
+ const isDefaultStatusFilter = selectedLineStatusFilters.length === LINE_STATUS_FILTER_OPTIONS.length;
74451
+ const selectedLineStatusSet = React125__default.useMemo(
74452
+ () => new Set(selectedLineStatusFilters),
74453
+ [selectedLineStatusFilters]
74454
+ );
74455
+ const selectedFactoryFilterSet = React125__default.useMemo(
74456
+ () => new Set(effectiveSelectedFactoryFilters),
74457
+ [effectiveSelectedFactoryFilters]
74458
+ );
74459
+ const isDefaultFactoryFilter = React125__default.useMemo(
74460
+ () => factoryFilterOptions.length === 0 || effectiveSelectedFactoryFilters.length === factoryFilterOptions.length && factoryFilterOptions.every((option) => selectedFactoryFilterSet.has(option.id)),
74461
+ [effectiveSelectedFactoryFilters.length, factoryFilterOptions, selectedFactoryFilterSet]
74462
+ );
74062
74463
  const getShiftIcon2 = (shiftId) => {
74063
74464
  const shiftNameLower = getShiftNameById(shiftId, configuredTimezone, shiftConfig).toLowerCase();
74064
74465
  if (shiftNameLower.includes("day") || shiftNameLower.includes("morning") || shiftId === 0) {
@@ -74107,16 +74508,77 @@ var KPIsOverviewView = ({
74107
74508
  },
74108
74509
  key
74109
74510
  );
74511
+ const statusMatchesFilters = React125__default.useCallback((status) => {
74512
+ if (isDefaultStatusFilter) return true;
74513
+ if (!status) return false;
74514
+ return selectedLineStatusSet.has(status);
74515
+ }, [isDefaultStatusFilter, selectedLineStatusSet]);
74516
+ const factoryMatchesFilters = React125__default.useCallback((line) => {
74517
+ if (isDefaultFactoryFilter) return true;
74518
+ return selectedFactoryFilterSet.has(line.factory_id || "unknown-factory");
74519
+ }, [isDefaultFactoryFilter, selectedFactoryFilterSet]);
74520
+ const getLineStatus = React125__default.useCallback((line) => {
74521
+ const kpis = getLineCardKpis(line);
74522
+ return getKpiSignalStatus(kpis?.lineSignal, efficiencyLegend);
74523
+ }, [efficiencyLegend, getLineCardKpis]);
74524
+ const getGroupStatus = React125__default.useCallback((cardLines) => {
74525
+ const kpis = getAggregateCardKpis(cardLines);
74526
+ return getKpiSignalStatus(kpis?.lineSignal, efficiencyLegend);
74527
+ }, [efficiencyLegend, getAggregateCardKpis]);
74528
+ const getLineSortEfficiency = React125__default.useCallback((line) => {
74529
+ const value = getLineCardKpis(line)?.efficiency?.value;
74530
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
74531
+ }, [getLineCardKpis]);
74532
+ const getGroupSortEfficiency = React125__default.useCallback((cardLines) => {
74533
+ const value = getAggregateCardKpis(cardLines)?.efficiency?.value;
74534
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
74535
+ }, [getAggregateCardKpis]);
74536
+ const compareEfficiencyValues = React125__default.useCallback((leftValue, rightValue) => {
74537
+ if (leftValue === null && rightValue === null) return 0;
74538
+ if (leftValue === null) return 1;
74539
+ if (rightValue === null) return -1;
74540
+ return efficiencySortDirection === "asc" ? leftValue - rightValue : rightValue - leftValue;
74541
+ }, [efficiencySortDirection]);
74542
+ const sortLineCollection = React125__default.useCallback(
74543
+ (cardLines) => [...cardLines].sort((left, right) => {
74544
+ const efficiencyComparison = compareEfficiencyValues(getLineSortEfficiency(left), getLineSortEfficiency(right));
74545
+ if (efficiencyComparison !== 0) return efficiencyComparison;
74546
+ return (left.line_name || "").localeCompare(right.line_name || "", void 0, { sensitivity: "base", numeric: true });
74547
+ }),
74548
+ [compareEfficiencyValues, getLineSortEfficiency]
74549
+ );
74550
+ const sortGroupCollection = React125__default.useCallback(
74551
+ (groups) => [...groups].sort((left, right) => {
74552
+ const leftLines = left.lines.filter(factoryMatchesFilters);
74553
+ const rightLines = right.lines.filter(factoryMatchesFilters);
74554
+ const efficiencyComparison = compareEfficiencyValues(getGroupSortEfficiency(leftLines), getGroupSortEfficiency(rightLines));
74555
+ if (efficiencyComparison !== 0) return efficiencyComparison;
74556
+ return (left.factoryName || left.areaName || "").localeCompare(right.factoryName || right.areaName || "", void 0, { sensitivity: "base", numeric: true });
74557
+ }),
74558
+ [compareEfficiencyValues, factoryMatchesFilters, getGroupSortEfficiency]
74559
+ );
74560
+ const filterLineCollection = React125__default.useCallback(
74561
+ (cardLines) => sortLineCollection(cardLines.filter((line) => factoryMatchesFilters(line) && statusMatchesFilters(getLineStatus(line)))),
74562
+ [factoryMatchesFilters, getLineStatus, sortLineCollection, statusMatchesFilters]
74563
+ );
74564
+ const filterGroupCollection = React125__default.useCallback(
74565
+ (groups) => sortGroupCollection(groups.filter((group) => {
74566
+ const factoryFilteredLines = group.lines.filter(factoryMatchesFilters);
74567
+ if (factoryFilteredLines.length === 0) return false;
74568
+ return statusMatchesFilters(getGroupStatus(factoryFilteredLines));
74569
+ })),
74570
+ [factoryMatchesFilters, getGroupStatus, sortGroupCollection, statusMatchesFilters]
74571
+ );
74110
74572
  const renderTodayCards = () => {
74111
74573
  if (!kpiLineHierarchy.showFactoryLevel) {
74112
- return linesForView.map(renderLineCard);
74574
+ return filterLineCollection(linesForView).map(renderLineCard);
74113
74575
  }
74114
74576
  if (selectedFactoryNode && selectedFactoryAreaNode) {
74115
- return selectedFactoryAreaNode.lines.map(renderLineCard);
74577
+ return filterLineCollection(selectedFactoryAreaNode.lines).map(renderLineCard);
74116
74578
  }
74117
74579
  if (selectedFactoryNode) {
74118
74580
  return [
74119
- ...selectedFactoryNode.areas.map(
74581
+ ...filterGroupCollection(selectedFactoryNode.areas).map(
74120
74582
  (area) => renderGroupCard({
74121
74583
  key: `area-${area.id}`,
74122
74584
  title: area.areaName,
@@ -74125,10 +74587,10 @@ var KPIsOverviewView = ({
74125
74587
  onClick: () => navigateTodayHierarchy(selectedFactoryNode.id, area.id)
74126
74588
  })
74127
74589
  ),
74128
- ...selectedFactoryNode.ungroupedLines.map(renderLineCard)
74590
+ ...filterLineCollection(selectedFactoryNode.ungroupedLines).map(renderLineCard)
74129
74591
  ];
74130
74592
  }
74131
- return kpiLineHierarchy.factories.map(
74593
+ return filterGroupCollection(kpiLineHierarchy.factories).map(
74132
74594
  (factory) => renderGroupCard({
74133
74595
  key: `factory-${factory.id}`,
74134
74596
  title: factory.factoryName,
@@ -74138,6 +74600,18 @@ var KPIsOverviewView = ({
74138
74600
  })
74139
74601
  );
74140
74602
  };
74603
+ const renderTodayUnitsByFactory = () => kpiLineHierarchy.factories.flatMap((factory) => [
74604
+ ...filterGroupCollection(factory.areas).map(
74605
+ (area) => renderGroupCard({
74606
+ key: `unit-area-${factory.id}-${area.id}`,
74607
+ title: area.areaName,
74608
+ subtitle: `${area.lines.length} ${area.lines.length === 1 ? "line" : "lines"}`,
74609
+ lines: area.lines,
74610
+ onClick: () => navigateTodayHierarchy(factory.id, area.id)
74611
+ })
74612
+ ),
74613
+ ...filterLineCollection(factory.ungroupedLines).map(renderLineCard)
74614
+ ]);
74141
74615
  if (loading || isShiftConfigLoading) {
74142
74616
  return /* @__PURE__ */ jsx(LoadingPage, { message: "Loading production lines..." });
74143
74617
  }
@@ -74351,65 +74825,237 @@ var KPIsOverviewView = ({
74351
74825
  )
74352
74826
  ] }),
74353
74827
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
74354
- activeTab === "leaderboard" && timeRange === "today" && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
74355
- /* @__PURE__ */ jsx(
74356
- MonthlyRangeFilter_default,
74828
+ activeTab === "leaderboard" && timeRange === "today" && /* @__PURE__ */ jsx(
74829
+ MonthlyRangeFilter_default,
74830
+ {
74831
+ month: parseDateKeyToDate(effectiveLeaderboardDate).getMonth(),
74832
+ year: parseDateKeyToDate(effectiveLeaderboardDate).getFullYear(),
74833
+ timezone: configuredTimezone,
74834
+ value: {
74835
+ startKey: effectiveLeaderboardDate,
74836
+ endKey: effectiveLeaderboardDate
74837
+ },
74838
+ onChange: (range) => {
74839
+ updateLeaderboardDate(range.startKey);
74840
+ },
74841
+ showLabel: false,
74842
+ singleDateOnly: true
74843
+ }
74844
+ ),
74845
+ (activeTab === "today" || activeTab === "leaderboard" && timeRange === "today") && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
74846
+ /* @__PURE__ */ jsxs(
74847
+ "button",
74357
74848
  {
74358
- month: parseDateKeyToDate(effectiveLeaderboardDate).getMonth(),
74359
- year: parseDateKeyToDate(effectiveLeaderboardDate).getFullYear(),
74360
- timezone: configuredTimezone,
74361
- value: {
74362
- startKey: effectiveLeaderboardDate,
74363
- endKey: effectiveLeaderboardDate
74849
+ ref: filterButtonRef,
74850
+ type: "button",
74851
+ onClick: () => {
74852
+ const nextOpen = !isFilterOpen;
74853
+ if (nextOpen) {
74854
+ trackCoreEvent("Lines Overview Filter Menu Opened", {
74855
+ surface: "lines_overview",
74856
+ action: "open_filter_menu",
74857
+ control_clicked: "filters",
74858
+ source: "top_right_controls",
74859
+ active_tab: activeTab,
74860
+ selected_status_filters: selectedLineStatusFilters,
74861
+ selected_factory_filters: effectiveSelectedFactoryFilters,
74862
+ selected_view_level: todayViewLevel,
74863
+ selected_sort_direction: efficiencySortDirection
74864
+ });
74865
+ }
74866
+ setIsFilterOpen(nextOpen);
74867
+ setIsViewsOpen(false);
74868
+ setIsSortOpen(false);
74869
+ },
74870
+ className: `flex items-center gap-2 px-3 py-1.5 rounded-lg border text-sm font-medium transition-all shadow-sm ${isFilterOpen || activeFiltersCount > 0 ? "bg-blue-50 border-blue-200 text-blue-700" : "bg-white border-gray-200 text-gray-700 hover:bg-gray-50"}`,
74871
+ children: [
74872
+ /* @__PURE__ */ jsx(Filter, { className: "w-4 h-4" }),
74873
+ /* @__PURE__ */ jsx("span", { children: "Filters" }),
74874
+ activeFiltersCount > 0 && /* @__PURE__ */ jsx("span", { className: "flex items-center justify-center w-5 h-5 bg-blue-100 text-blue-700 text-xs rounded-full font-bold ml-1", children: activeFiltersCount }),
74875
+ /* @__PURE__ */ jsx(ChevronDown, { className: `w-3 h-3 ml-1 transition-transform ${isFilterOpen ? "rotate-180" : ""}` })
74876
+ ]
74877
+ }
74878
+ ),
74879
+ isFilterOpen && /* @__PURE__ */ jsxs("div", { ref: filterRef, className: "absolute right-0 top-full mt-2 w-72 max-h-[calc(100vh-12rem)] overflow-y-auto bg-white rounded-xl shadow-xl border border-gray-100 p-4 z-50", children: [
74880
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
74881
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Filters" }),
74882
+ activeFiltersCount > 0 && /* @__PURE__ */ jsx(
74883
+ "button",
74884
+ {
74885
+ type: "button",
74886
+ onClick: clearFilters,
74887
+ className: "text-xs text-red-600 hover:text-red-700 font-medium",
74888
+ children: "Clear all"
74889
+ }
74890
+ )
74891
+ ] }),
74892
+ activeTab === "today" ? /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
74893
+ factoryFilterOptions.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
74894
+ /* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide ml-1", children: "Filter by factory" }),
74895
+ /* @__PURE__ */ jsx("div", { className: "space-y-1", children: factoryFilterOptions.map((option) => {
74896
+ const isSelected = selectedFactoryFilterSet.has(option.id);
74897
+ return /* @__PURE__ */ jsxs(
74898
+ "button",
74899
+ {
74900
+ type: "button",
74901
+ onClick: () => handleFactoryFilterToggle(option.id),
74902
+ className: `flex w-full items-center gap-3 rounded-lg px-3 py-2 text-left text-sm transition-colors ${isSelected ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-50"}`,
74903
+ children: [
74904
+ /* @__PURE__ */ jsx("span", { className: `flex h-4 w-4 flex-shrink-0 items-center justify-center rounded border ${isSelected ? "border-blue-500 bg-blue-500 text-white" : "border-gray-300 bg-white"}`, children: isSelected && /* @__PURE__ */ jsx(Check, { className: "h-3 w-3" }) }),
74905
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: option.label })
74906
+ ]
74907
+ },
74908
+ option.id
74909
+ );
74910
+ }) })
74911
+ ] }),
74912
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
74913
+ /* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide ml-1", children: "Filter by status" }),
74914
+ /* @__PURE__ */ jsx("div", { className: "space-y-1", children: LINE_STATUS_FILTER_OPTIONS.map((option) => {
74915
+ const isSelected = selectedLineStatusSet.has(option.id);
74916
+ return /* @__PURE__ */ jsxs(
74917
+ "button",
74918
+ {
74919
+ type: "button",
74920
+ onClick: () => handleLineStatusFilterToggle(option.id),
74921
+ className: `flex w-full items-center gap-3 rounded-lg px-3 py-2 text-left text-sm transition-colors ${isSelected ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-50"}`,
74922
+ children: [
74923
+ /* @__PURE__ */ jsx("span", { className: `flex h-4 w-4 items-center justify-center rounded border ${isSelected ? "border-blue-500 bg-blue-500 text-white" : "border-gray-300 bg-white"}`, children: isSelected && /* @__PURE__ */ jsx(Check, { className: "h-3 w-3" }) }),
74924
+ option.label
74925
+ ]
74926
+ },
74927
+ option.id
74928
+ );
74929
+ }) })
74930
+ ] })
74931
+ ] }) : /* @__PURE__ */ jsx("div", { className: "space-y-3", children: /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
74932
+ /* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide ml-1", children: "Shift" }),
74933
+ /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(
74934
+ "select",
74935
+ {
74936
+ "aria-label": "Leaderboard shift",
74937
+ value: effectiveLeaderboardShiftId,
74938
+ onChange: (e) => updateLeaderboardShiftId(Number(e.target.value)),
74939
+ className: "w-full appearance-none pl-3 pr-8 py-2 text-sm bg-gray-50 border border-gray-200 hover:border-gray-300 rounded-lg text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:bg-white transition-all cursor-pointer",
74940
+ style: { backgroundImage: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e")`, backgroundPosition: `right 0.75rem center`, backgroundRepeat: `no-repeat`, backgroundSize: `1.2em 1.2em` },
74941
+ children: leaderboardShiftOptions.map((shiftOption) => /* @__PURE__ */ jsx("option", { value: shiftOption.id, children: shiftOption.label }, shiftOption.id))
74942
+ }
74943
+ ) })
74944
+ ] }) })
74945
+ ] })
74946
+ ] }),
74947
+ activeTab === "today" && kpiLineHierarchy.showFactoryLevel && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
74948
+ /* @__PURE__ */ jsxs(
74949
+ "button",
74950
+ {
74951
+ ref: viewsButtonRef,
74952
+ type: "button",
74953
+ onClick: () => {
74954
+ const nextOpen = !isViewsOpen;
74955
+ if (nextOpen) {
74956
+ trackCoreEvent("Lines Overview Views Menu Opened", {
74957
+ surface: "lines_overview",
74958
+ action: "open_views_menu",
74959
+ control_clicked: "views",
74960
+ source: "top_right_controls",
74961
+ selected_view_level: todayViewLevel,
74962
+ selected_factory_filters: effectiveSelectedFactoryFilters,
74963
+ selected_status_filters: selectedLineStatusFilters,
74964
+ selected_sort_direction: efficiencySortDirection
74965
+ });
74966
+ }
74967
+ setIsViewsOpen(nextOpen);
74968
+ setIsFilterOpen(false);
74969
+ setIsSortOpen(false);
74364
74970
  },
74365
- onChange: (range) => {
74366
- updateLeaderboardDate(range.startKey);
74971
+ className: `flex items-center gap-2 px-3 py-1.5 rounded-lg border text-sm font-medium transition-all shadow-sm ${isViewsOpen ? "bg-blue-50 border-blue-200 text-blue-700" : "bg-white border-gray-200 text-gray-700 hover:bg-gray-50"}`,
74972
+ children: [
74973
+ /* @__PURE__ */ jsx(Layers, { className: "w-4 h-4" }),
74974
+ /* @__PURE__ */ jsx("span", { children: "Views" }),
74975
+ /* @__PURE__ */ jsx(ChevronDown, { className: `w-3 h-3 ml-1 transition-transform ${isViewsOpen ? "rotate-180" : ""}` })
74976
+ ]
74977
+ }
74978
+ ),
74979
+ isViewsOpen && /* @__PURE__ */ jsxs("div", { ref: viewsRef, className: "absolute right-0 top-full mt-2 w-72 bg-white rounded-xl shadow-xl border border-gray-100 p-4 z-50", children: [
74980
+ /* @__PURE__ */ jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Views" }) }),
74981
+ /* @__PURE__ */ jsx("div", { className: "space-y-1", children: [
74982
+ { id: "factory", label: "Factory level" },
74983
+ { id: "units", label: "Area level" }
74984
+ ].map((option) => {
74985
+ const isSelected = todayViewLevel === option.id;
74986
+ return /* @__PURE__ */ jsxs(
74987
+ "button",
74988
+ {
74989
+ type: "button",
74990
+ onClick: () => handleTodayViewLevelChange(option.id),
74991
+ className: `flex w-full items-center gap-3 rounded-lg px-3 py-2 text-left text-sm transition-colors ${isSelected ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-50"}`,
74992
+ children: [
74993
+ /* @__PURE__ */ jsx("span", { className: `flex h-4 w-4 items-center justify-center rounded border ${isSelected ? "border-blue-500 bg-blue-500 text-white" : "border-gray-300 bg-white"}`, children: isSelected && /* @__PURE__ */ jsx(Check, { className: "h-3 w-3" }) }),
74994
+ option.label
74995
+ ]
74996
+ },
74997
+ option.id
74998
+ );
74999
+ }) })
75000
+ ] })
75001
+ ] }),
75002
+ activeTab === "today" && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
75003
+ /* @__PURE__ */ jsxs(
75004
+ "button",
75005
+ {
75006
+ ref: sortButtonRef,
75007
+ type: "button",
75008
+ onClick: () => {
75009
+ const nextOpen = !isSortOpen;
75010
+ if (nextOpen) {
75011
+ trackCoreEvent("Lines Overview Sort Menu Opened", {
75012
+ surface: "lines_overview",
75013
+ action: "open_sort_menu",
75014
+ control_clicked: "sort",
75015
+ source: "top_right_controls",
75016
+ sort_metric: "efficiency",
75017
+ selected_sort_direction: efficiencySortDirection,
75018
+ selected_factory_filters: effectiveSelectedFactoryFilters,
75019
+ selected_status_filters: selectedLineStatusFilters,
75020
+ selected_view_level: todayViewLevel
75021
+ });
75022
+ }
75023
+ setIsSortOpen(nextOpen);
75024
+ setIsFilterOpen(false);
75025
+ setIsViewsOpen(false);
74367
75026
  },
74368
- showLabel: false,
74369
- singleDateOnly: true
75027
+ className: `flex items-center gap-2 px-3 py-1.5 rounded-lg border text-sm font-medium transition-all shadow-sm ${isSortOpen || activeSortCount > 0 ? "bg-blue-50 border-blue-200 text-blue-700" : "bg-white border-gray-200 text-gray-700 hover:bg-gray-50"}`,
75028
+ children: [
75029
+ /* @__PURE__ */ jsx(ArrowUpDown, { className: "w-4 h-4" }),
75030
+ /* @__PURE__ */ jsx("span", { children: "Sort" }),
75031
+ activeSortCount > 0 && /* @__PURE__ */ jsx("span", { className: "flex items-center justify-center w-5 h-5 bg-blue-100 text-blue-700 text-xs rounded-full font-bold ml-1", children: activeSortCount }),
75032
+ /* @__PURE__ */ jsx(ChevronDown, { className: `w-3 h-3 ml-1 transition-transform ${isSortOpen ? "rotate-180" : ""}` })
75033
+ ]
74370
75034
  }
74371
75035
  ),
74372
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
74373
- /* @__PURE__ */ jsxs(
74374
- "button",
74375
- {
74376
- ref: filterButtonRef,
74377
- onClick: () => setIsFilterOpen(!isFilterOpen),
74378
- className: `flex items-center gap-2 px-3 py-1.5 rounded-lg border text-sm font-medium transition-all shadow-sm ${isFilterOpen || activeFiltersCount > 0 ? "bg-blue-50 border-blue-200 text-blue-700" : "bg-white border-gray-200 text-gray-700 hover:bg-gray-50"}`,
74379
- children: [
74380
- /* @__PURE__ */ jsx(Filter, { className: "w-4 h-4" }),
74381
- /* @__PURE__ */ jsx("span", { children: "Filters" }),
74382
- activeFiltersCount > 0 && /* @__PURE__ */ jsx("span", { className: "flex items-center justify-center w-5 h-5 bg-blue-100 text-blue-700 text-xs rounded-full font-bold ml-1", children: activeFiltersCount }),
74383
- /* @__PURE__ */ jsx(ChevronDown, { className: `w-3 h-3 ml-1 transition-transform ${isFilterOpen ? "rotate-180" : ""}` })
74384
- ]
74385
- }
74386
- ),
74387
- isFilterOpen && /* @__PURE__ */ jsxs("div", { ref: filterRef, className: "absolute right-0 top-full mt-2 w-72 bg-white rounded-xl shadow-xl border border-gray-100 p-4 z-50", children: [
74388
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
74389
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Filter View" }),
74390
- activeFiltersCount > 0 && /* @__PURE__ */ jsx(
75036
+ isSortOpen && /* @__PURE__ */ jsxs("div", { ref: sortRef, className: "absolute right-0 top-full mt-2 w-72 bg-white rounded-xl shadow-xl border border-gray-100 p-4 z-50", children: [
75037
+ /* @__PURE__ */ jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Sort" }) }),
75038
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
75039
+ /* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide ml-1", children: "Efficiency" }),
75040
+ /* @__PURE__ */ jsx("div", { className: "space-y-1", children: [
75041
+ { id: "desc", label: "Highest to lowest" },
75042
+ { id: "asc", label: "Lowest to highest" }
75043
+ ].map((option) => {
75044
+ const isSelected = efficiencySortDirection === option.id;
75045
+ return /* @__PURE__ */ jsxs(
74391
75046
  "button",
74392
75047
  {
74393
- onClick: clearFilters,
74394
- className: "text-xs text-red-600 hover:text-red-700 font-medium",
74395
- children: "Clear all"
74396
- }
74397
- )
74398
- ] }),
74399
- /* @__PURE__ */ jsx("div", { className: "space-y-3", children: /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
74400
- /* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide ml-1", children: "Shift" }),
74401
- /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(
74402
- "select",
74403
- {
74404
- "aria-label": "Leaderboard shift",
74405
- value: effectiveLeaderboardShiftId,
74406
- onChange: (e) => updateLeaderboardShiftId(Number(e.target.value)),
74407
- className: "w-full appearance-none pl-3 pr-8 py-2 text-sm bg-gray-50 border border-gray-200 hover:border-gray-300 rounded-lg text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:bg-white transition-all cursor-pointer",
74408
- style: { backgroundImage: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e")`, backgroundPosition: `right 0.75rem center`, backgroundRepeat: `no-repeat`, backgroundSize: `1.2em 1.2em` },
74409
- children: leaderboardShiftOptions.map((shiftOption) => /* @__PURE__ */ jsx("option", { value: shiftOption.id, children: shiftOption.label }, shiftOption.id))
74410
- }
74411
- ) })
74412
- ] }) })
75048
+ type: "button",
75049
+ onClick: () => handleEfficiencySortChange(option.id),
75050
+ className: `flex w-full items-center gap-3 rounded-lg px-3 py-2 text-left text-sm transition-colors ${isSelected ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-50"}`,
75051
+ children: [
75052
+ /* @__PURE__ */ jsx("span", { className: `flex h-4 w-4 items-center justify-center rounded border ${isSelected ? "border-blue-500 bg-blue-500 text-white" : "border-gray-300 bg-white"}`, children: isSelected && /* @__PURE__ */ jsx(Check, { className: "h-3 w-3" }) }),
75053
+ option.label
75054
+ ]
75055
+ },
75056
+ option.id
75057
+ );
75058
+ }) })
74413
75059
  ] })
74414
75060
  ] })
74415
75061
  ] }),
@@ -74430,7 +75076,7 @@ var KPIsOverviewView = ({
74430
75076
  ] })
74431
75077
  ] })
74432
75078
  ] }) }),
74433
- /* @__PURE__ */ jsx("main", { className: `flex-1 p-3 sm:p-4 md:p-6 bg-slate-50 ${activeTab === "leaderboard" ? "overflow-hidden flex flex-col" : "overflow-y-auto"}`, children: activeTab === "today" ? /* @__PURE__ */ jsxs("div", { className: "space-y-3 sm:space-y-4", children: [
75079
+ /* @__PURE__ */ jsx("main", { className: `flex-1 p-3 sm:p-4 md:p-6 bg-slate-50 ${activeTab === "leaderboard" ? "overflow-hidden flex flex-col" : "overflow-y-auto"}`, children: activeTab === "today" ? /* @__PURE__ */ jsx("div", { className: "space-y-3 sm:space-y-4", children: todayViewLevel === "units" && kpiLineHierarchy.showFactoryLevel ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3 sm:gap-4 md:gap-6", children: renderTodayUnitsByFactory() }) : /* @__PURE__ */ jsxs(Fragment, { children: [
74434
75080
  kpiLineHierarchy.showFactoryLevel && selectedFactoryNode && /* @__PURE__ */ jsxs("nav", { className: "flex flex-wrap items-center gap-2 text-sm", "aria-label": "KPI hierarchy", children: [
74435
75081
  /* @__PURE__ */ jsx(
74436
75082
  "button",
@@ -74457,7 +75103,7 @@ var KPIsOverviewView = ({
74457
75103
  ] })
74458
75104
  ] }),
74459
75105
  /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3 sm:gap-4 md:gap-6", children: renderTodayCards() })
74460
- ] }) : showLeaderboardLoader ? /* @__PURE__ */ jsx("div", { className: "flex-1 flex flex-col items-center justify-center bg-white rounded-2xl border border-gray-100 shadow-sm m-2 sm:m-4", children: /* @__PURE__ */ jsx(
75106
+ ] }) }) : showLeaderboardLoader ? /* @__PURE__ */ jsx("div", { className: "flex-1 flex flex-col items-center justify-center bg-white rounded-2xl border border-gray-100 shadow-sm m-2 sm:m-4", children: /* @__PURE__ */ jsx(
74461
75107
  OptifyeLogoLoader_default,
74462
75108
  {
74463
75109
  size: "lg",
@@ -74769,7 +75415,7 @@ var LeaderboardDetailView = memo$1(({
74769
75415
  return () => document.removeEventListener("mousedown", handleClickOutside);
74770
75416
  }, []);
74771
75417
  const [isMobile, setIsMobile] = useState(false);
74772
- React148__default.useEffect(() => {
75418
+ React125__default.useEffect(() => {
74773
75419
  const checkMobile = () => setIsMobile(window.innerWidth < 640);
74774
75420
  checkMobile();
74775
75421
  window.addEventListener("resize", checkMobile);
@@ -75594,7 +76240,7 @@ var LeaderboardDetailView = memo$1(({
75594
76240
  ] }) }),
75595
76241
  isFilterOpen && /* @__PURE__ */ jsxs("div", { ref: filterRef, className: "absolute right-3 sm:right-4 md:right-5 lg:right-6 top-full mt-2 w-72 bg-white rounded-xl shadow-xl border border-gray-100 p-4 z-50", children: [
75596
76242
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
75597
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Filter View" }),
76243
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Sort" }),
75598
76244
  activeFiltersCount > 0 && /* @__PURE__ */ jsx(
75599
76245
  "button",
75600
76246
  {
@@ -75719,9 +76365,9 @@ var LeaderboardDetailView = memo$1(({
75719
76365
  ref: mobileFilterButtonRef,
75720
76366
  onClick: () => setIsFilterOpen(!isFilterOpen),
75721
76367
  className: `p-2 rounded-full transition-colors relative ${isFilterOpen || activeFiltersCount > 0 ? "bg-blue-50" : "active:bg-gray-100"}`,
75722
- "aria-label": "Open filters",
76368
+ "aria-label": "Open sort",
75723
76369
  children: [
75724
- /* @__PURE__ */ jsx(Filter, { className: `w-5 h-5 ${activeFiltersCount > 0 ? "text-blue-600" : "text-gray-700"}` }),
76370
+ /* @__PURE__ */ jsx(ArrowUpDown, { className: `w-5 h-5 ${activeFiltersCount > 0 ? "text-blue-600" : "text-gray-700"}` }),
75725
76371
  activeFiltersCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute -top-1 -right-1 flex items-center justify-center w-4 h-4 bg-blue-600 text-white text-[10px] rounded-full font-bold", children: activeFiltersCount })
75726
76372
  ]
75727
76373
  }
@@ -75794,8 +76440,8 @@ var LeaderboardDetailView = memo$1(({
75794
76440
  onClick: () => setIsFilterOpen(!isFilterOpen),
75795
76441
  className: `flex items-center gap-2 px-3 py-1.5 rounded-lg border text-sm font-medium transition-all shadow-sm ${isFilterOpen || activeFiltersCount > 0 ? "bg-blue-50 border-blue-200 text-blue-700" : "bg-white border-gray-200 text-gray-700 hover:bg-gray-50"}`,
75796
76442
  children: [
75797
- /* @__PURE__ */ jsx(Filter, { className: "w-4 h-4" }),
75798
- /* @__PURE__ */ jsx("span", { children: "Filters" }),
76443
+ /* @__PURE__ */ jsx(ArrowUpDown, { className: "w-4 h-4" }),
76444
+ /* @__PURE__ */ jsx("span", { children: "Sort" }),
75799
76445
  activeFiltersCount > 0 && /* @__PURE__ */ jsx("span", { className: "flex items-center justify-center w-5 h-5 bg-blue-100 text-blue-700 text-xs rounded-full font-bold ml-1", children: activeFiltersCount }),
75800
76446
  /* @__PURE__ */ jsx(ChevronDown, { className: `w-3 h-3 ml-1 transition-transform ${isFilterOpen ? "rotate-180" : ""}` })
75801
76447
  ]
@@ -78819,7 +79465,7 @@ var ShiftsView = ({
78819
79465
  ] })
78820
79466
  ] });
78821
79467
  };
78822
- var AuthenticatedShiftsView = withAuth(React148__default.memo(ShiftsView));
79468
+ var AuthenticatedShiftsView = withAuth(React125__default.memo(ShiftsView));
78823
79469
  var ShiftsView_default = ShiftsView;
78824
79470
 
78825
79471
  // src/views/TargetsView.utils.ts
@@ -80686,7 +81332,7 @@ var TargetsView = ({
80686
81332
  };
80687
81333
  var TargetsViewWithDisplayNames = withAllWorkspaceDisplayNames(TargetsView);
80688
81334
  var TargetsView_default = TargetsViewWithDisplayNames;
80689
- var AuthenticatedTargetsView = withAuth(React148__default.memo(TargetsViewWithDisplayNames));
81335
+ var AuthenticatedTargetsView = withAuth(React125__default.memo(TargetsViewWithDisplayNames));
80690
81336
  function useTimezone(options = {}) {
80691
81337
  const dashboardConfig = useDashboardConfig();
80692
81338
  const workspaceConfig = useWorkspaceConfig();
@@ -80851,13 +81497,13 @@ var WorkspaceHourSummaryPanel = ({
80851
81497
  }) => {
80852
81498
  const { data, isLoading, error, summarize, reset } = useWorkspaceHourSummary();
80853
81499
  const selectedKey = selectedHour ? `${selectedHour.source}:${selectedHour.hourIndex}:${date}:${shiftId}` : "none";
80854
- const autoSummaryKeyRef = React148__default.useRef(null);
80855
- React148__default.useEffect(() => {
81500
+ const autoSummaryKeyRef = React125__default.useRef(null);
81501
+ React125__default.useEffect(() => {
80856
81502
  reset();
80857
81503
  autoSummaryKeyRef.current = null;
80858
81504
  }, [reset, selectedKey]);
80859
81505
  const canSummarize = Boolean(workspaceId && companyId && date && shiftId !== null && shiftId !== void 0);
80860
- React148__default.useEffect(() => {
81506
+ React125__default.useEffect(() => {
80861
81507
  if (!selectedHour || !canSummarize || !companyId || !date || shiftId === null || shiftId === void 0) {
80862
81508
  return;
80863
81509
  }
@@ -82588,7 +83234,8 @@ var WorkspaceDetailView = ({
82588
83234
  selectedHourIndex: isWorkspaceHourAiSummaryEnabled ? selectedHour?.source === "output" ? selectedHour.hourIndex : aiSummaryHour?.hourIndex ?? null : null,
82589
83235
  onHourClick: isWorkspaceHourAiSummaryEnabled ? handleOutputHourSelect : void 0,
82590
83236
  onWatchClipsClick: handleWatchClipsFromChart,
82591
- onAiSummaryClick: isWorkspaceHourAiSummaryEnabled ? handleAiSummaryClick : void 0
83237
+ onAiSummaryClick: isWorkspaceHourAiSummaryEnabled ? handleAiSummaryClick : void 0,
83238
+ onSelectSku: setSelectedSkuId
82592
83239
  }
82593
83240
  )
82594
83241
  }
@@ -82761,7 +83408,8 @@ var WorkspaceDetailView = ({
82761
83408
  selectedHourIndex: isWorkspaceHourAiSummaryEnabled ? selectedHour?.source === "output" ? selectedHour.hourIndex : aiSummaryHour?.hourIndex ?? null : null,
82762
83409
  onHourClick: isWorkspaceHourAiSummaryEnabled ? handleOutputHourSelect : void 0,
82763
83410
  onWatchClipsClick: handleWatchClipsFromChart,
82764
- onAiSummaryClick: isWorkspaceHourAiSummaryEnabled ? handleAiSummaryClick : void 0
83411
+ onAiSummaryClick: isWorkspaceHourAiSummaryEnabled ? handleAiSummaryClick : void 0,
83412
+ onSelectSku: setSelectedSkuId
82765
83413
  }
82766
83414
  ) })
82767
83415
  ]
@@ -84548,7 +85196,7 @@ function BottleneckClipsView({
84548
85196
  ) })
84549
85197
  ] }) });
84550
85198
  }
84551
- var AuthenticatedBottleneckClipsView = withAuth(React148__default.memo(BottleneckClipsView));
85199
+ var AuthenticatedBottleneckClipsView = withAuth(React125__default.memo(BottleneckClipsView));
84552
85200
  var BottleneckClipsView_default = BottleneckClipsView;
84553
85201
 
84554
85202
  // src/lib/services/ticketService.ts
@@ -85391,7 +86039,7 @@ Please ensure:
85391
86039
  )
85392
86040
  ] });
85393
86041
  }
85394
- var AuthenticatedTicketsView = withAuth(React148__default.memo(TicketsView));
86042
+ var AuthenticatedTicketsView = withAuth(React125__default.memo(TicketsView));
85395
86043
  var TicketsView_default = TicketsView;
85396
86044
 
85397
86045
  // src/lib/utils/improvementDisplay.ts
@@ -86362,7 +87010,7 @@ var ImprovementCenterView = () => {
86362
87010
  setSelectedMemberId("all");
86363
87011
  }
86364
87012
  }, [memberOptions, selectedMemberId]);
86365
- const getRecommendationDisplayMetadata = React148__default.useCallback((rec) => {
87013
+ const getRecommendationDisplayMetadata = React125__default.useCallback((rec) => {
86366
87014
  const supervisors = rec.line_id ? supervisorsByLineId.get(rec.line_id) || [] : [];
86367
87015
  return getImprovementDisplayMetadata({
86368
87016
  location: rec.location,
@@ -86836,7 +87484,7 @@ var ThreadSidebar = ({
86836
87484
  ] }) })
86837
87485
  ] });
86838
87486
  };
86839
- var ProfilePicture = React148__default.memo(({
87487
+ var ProfilePicture = React125__default.memo(({
86840
87488
  alt = "Axel",
86841
87489
  className = "",
86842
87490
  size = "md",
@@ -89396,7 +90044,7 @@ var OverviewImprovementsSkeleton = () => /* @__PURE__ */ jsx("div", { className:
89396
90044
  ] }),
89397
90045
  /* @__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" }) })
89398
90046
  ] }, index)) });
89399
- var OperationsOverviewHeader = React148__default.memo(({
90047
+ var OperationsOverviewHeader = React125__default.memo(({
89400
90048
  dateRange,
89401
90049
  displayDateRange,
89402
90050
  trendMode,
@@ -89417,65 +90065,65 @@ var OperationsOverviewHeader = React148__default.memo(({
89417
90065
  bumpRenderCounter();
89418
90066
  const subtitleRange = displayDateRange || dateRange;
89419
90067
  const showLiveShiftMeta = isLiveScope && trendMode !== "all";
89420
- const liveShiftLabel = React148__default.useMemo(
90068
+ const liveShiftLabel = React125__default.useMemo(
89421
90069
  () => normalizeShiftLabel(liveShiftName, trendMode),
89422
90070
  [liveShiftName, trendMode]
89423
90071
  );
89424
- const liveShiftIcon = React148__default.useMemo(
90072
+ const liveShiftIcon = React125__default.useMemo(
89425
90073
  () => getShiftIcon(liveShiftName, trendMode),
89426
90074
  [liveShiftName, trendMode]
89427
90075
  );
89428
- const [isFilterOpen, setIsFilterOpen] = React148__default.useState(false);
89429
- const [isLinesDropdownOpen, setIsLinesDropdownOpen] = React148__default.useState(false);
89430
- const filterRef = React148__default.useRef(null);
89431
- const filterButtonRef = React148__default.useRef(null);
89432
- const mobileFilterButtonRef = React148__default.useRef(null);
89433
- const linesDropdownRef = React148__default.useRef(null);
89434
- const mobileSubtitle = React148__default.useMemo(() => {
90076
+ const [isFilterOpen, setIsFilterOpen] = React125__default.useState(false);
90077
+ const [isLinesDropdownOpen, setIsLinesDropdownOpen] = React125__default.useState(false);
90078
+ const filterRef = React125__default.useRef(null);
90079
+ const filterButtonRef = React125__default.useRef(null);
90080
+ const mobileFilterButtonRef = React125__default.useRef(null);
90081
+ const linesDropdownRef = React125__default.useRef(null);
90082
+ const mobileSubtitle = React125__default.useMemo(() => {
89435
90083
  if (subtitleRange.startKey === subtitleRange.endKey) {
89436
90084
  return format(parseDateKeyToDate(subtitleRange.startKey), "do MMM, yyyy");
89437
90085
  }
89438
90086
  return `${format(parseDateKeyToDate(subtitleRange.startKey), "do MMM")} - ${format(parseDateKeyToDate(subtitleRange.endKey), "do MMM, yyyy")}`;
89439
90087
  }, [subtitleRange.endKey, subtitleRange.startKey]);
89440
- const desktopSubtitle = React148__default.useMemo(() => {
90088
+ const desktopSubtitle = React125__default.useMemo(() => {
89441
90089
  if (subtitleRange.startKey === subtitleRange.endKey) {
89442
90090
  return format(parseDateKeyToDate(subtitleRange.startKey), "do MMMM, yyyy");
89443
90091
  }
89444
90092
  return `${format(parseDateKeyToDate(subtitleRange.startKey), "do MMMM, yyyy")} - ${format(parseDateKeyToDate(subtitleRange.endKey), "do MMMM, yyyy")}`;
89445
90093
  }, [subtitleRange.endKey, subtitleRange.startKey]);
89446
- const availableLineIds = React148__default.useMemo(
90094
+ const availableLineIds = React125__default.useMemo(
89447
90095
  () => lineOptions.map((line) => line.id),
89448
90096
  [lineOptions]
89449
90097
  );
89450
- const selectedLineIdSet = React148__default.useMemo(
90098
+ const selectedLineIdSet = React125__default.useMemo(
89451
90099
  () => new Set(selectedLineIds),
89452
90100
  [selectedLineIds]
89453
90101
  );
89454
- const isAllLinesSelected = React148__default.useMemo(() => {
90102
+ const isAllLinesSelected = React125__default.useMemo(() => {
89455
90103
  if (availableLineIds.length === 0) return true;
89456
90104
  return availableLineIds.every((lineId) => selectedLineIdSet.has(lineId));
89457
90105
  }, [availableLineIds, selectedLineIdSet]);
89458
- const activeFilterCount = React148__default.useMemo(() => {
90106
+ const activeFilterCount = React125__default.useMemo(() => {
89459
90107
  let count = 0;
89460
90108
  if (trendMode !== "all") count += 1;
89461
90109
  if (selectedSupervisorId !== "all") count += 1;
89462
90110
  if (!isAllLinesSelected) count += 1;
89463
90111
  return count;
89464
90112
  }, [isAllLinesSelected, selectedSupervisorId, trendMode]);
89465
- const handleFilterToggle = React148__default.useCallback(() => {
90113
+ const handleFilterToggle = React125__default.useCallback(() => {
89466
90114
  trackCoreEvent("Operations Overview Filter Toggled", {
89467
90115
  action: !isFilterOpen ? "open" : "close"
89468
90116
  });
89469
90117
  setIsFilterOpen((previous) => !previous);
89470
90118
  }, [isFilterOpen]);
89471
- const handleTrendModeChange = React148__default.useCallback((event) => {
90119
+ const handleTrendModeChange = React125__default.useCallback((event) => {
89472
90120
  const nextMode = event.target.value;
89473
90121
  trackCoreEvent("Operations Overview Shift Filter Changed", {
89474
90122
  shift_mode: nextMode
89475
90123
  });
89476
90124
  onTrendModeChange(nextMode);
89477
90125
  }, [onTrendModeChange]);
89478
- const handleAllLinesToggle = React148__default.useCallback(() => {
90126
+ const handleAllLinesToggle = React125__default.useCallback(() => {
89479
90127
  trackCoreEvent("Operations Overview Line Filter Changed", {
89480
90128
  selected_line_ids: availableLineIds,
89481
90129
  selected_line_count: availableLineIds.length,
@@ -89483,7 +90131,7 @@ var OperationsOverviewHeader = React148__default.memo(({
89483
90131
  });
89484
90132
  onSelectedLineIdsChange(availableLineIds);
89485
90133
  }, [availableLineIds, onSelectedLineIdsChange]);
89486
- const handleSupervisorChange = React148__default.useCallback((event) => {
90134
+ const handleSupervisorChange = React125__default.useCallback((event) => {
89487
90135
  const supervisorId = event.target.value;
89488
90136
  const selectedSupervisor = supervisorOptions.find((option) => option.id === supervisorId);
89489
90137
  trackCoreEvent("Operations Overview Supervisor Filter Changed", {
@@ -89494,7 +90142,7 @@ var OperationsOverviewHeader = React148__default.memo(({
89494
90142
  });
89495
90143
  onSelectedSupervisorIdChange(supervisorId);
89496
90144
  }, [availableLineIds, onSelectedSupervisorIdChange, supervisorOptions]);
89497
- const handleLineToggle = React148__default.useCallback((lineId) => {
90145
+ const handleLineToggle = React125__default.useCallback((lineId) => {
89498
90146
  const current = new Set(selectedLineIds);
89499
90147
  if (current.has(lineId)) {
89500
90148
  if (current.size <= 1) return;
@@ -89510,13 +90158,13 @@ var OperationsOverviewHeader = React148__default.memo(({
89510
90158
  });
89511
90159
  onSelectedLineIdsChange(next);
89512
90160
  }, [availableLineIds, onSelectedLineIdsChange, selectedLineIds]);
89513
- const handleClearAllFilters = React148__default.useCallback(() => {
90161
+ const handleClearAllFilters = React125__default.useCallback(() => {
89514
90162
  onTrendModeChange("all");
89515
90163
  onSelectedSupervisorIdChange("all");
89516
90164
  onSelectedLineIdsChange(availableLineIds);
89517
90165
  setIsFilterOpen(false);
89518
90166
  }, [availableLineIds, onSelectedLineIdsChange, onSelectedSupervisorIdChange, onTrendModeChange]);
89519
- React148__default.useEffect(() => {
90167
+ React125__default.useEffect(() => {
89520
90168
  const handleClickOutside = (event) => {
89521
90169
  const target = event.target;
89522
90170
  if (filterRef.current && !filterRef.current.contains(target) && filterButtonRef.current && !filterButtonRef.current.contains(target) && mobileFilterButtonRef.current && !mobileFilterButtonRef.current.contains(target)) {
@@ -89751,12 +90399,12 @@ var OperationsOverviewHeader = React148__default.memo(({
89751
90399
  ] }) });
89752
90400
  });
89753
90401
  OperationsOverviewHeader.displayName = "OperationsOverviewHeader";
89754
- var OverviewSummaryCards = React148__default.memo(({ store }) => {
90402
+ var OverviewSummaryCards = React125__default.memo(({ store }) => {
89755
90403
  bumpRenderCounter();
89756
90404
  const scope = useOperationsOverviewScope(store);
89757
90405
  const snapshot = useOperationsOverviewSnapshot(store);
89758
90406
  const showSnapshotSkeleton = snapshot.loading && !snapshot.hasLoadedOnce;
89759
- const comparisonLabel = React148__default.useMemo(() => {
90407
+ const comparisonLabel = React125__default.useMemo(() => {
89760
90408
  return formatComparisonWindow({
89761
90409
  currentDayCount: scope.current_range?.day_count ?? null,
89762
90410
  previousDayCount: scope.previous_range?.day_count ?? null,
@@ -89769,27 +90417,27 @@ var OverviewSummaryCards = React148__default.memo(({ store }) => {
89769
90417
  scope.previous_range?.day_count,
89770
90418
  scope.shift_mode
89771
90419
  ]);
89772
- const [isIdleContributorsOpen, setIsIdleContributorsOpen] = React148__default.useState(false);
89773
- const [isIdleContributorsPinned, setIsIdleContributorsPinned] = React148__default.useState(false);
89774
- const idleContributorsRef = React148__default.useRef(null);
89775
- const plantEfficiencyBadge = React148__default.useMemo(() => {
90420
+ const [isIdleContributorsOpen, setIsIdleContributorsOpen] = React125__default.useState(false);
90421
+ const [isIdleContributorsPinned, setIsIdleContributorsPinned] = React125__default.useState(false);
90422
+ const idleContributorsRef = React125__default.useRef(null);
90423
+ const plantEfficiencyBadge = React125__default.useMemo(() => {
89776
90424
  return buildDeltaBadge(snapshot.data.summary.plant_efficiency?.delta_pp, {
89777
90425
  positiveIsGood: true,
89778
90426
  formatter: (value) => `${value >= 0 ? "+" : ""}${roundOne(value)}%`,
89779
90427
  comparisonLabel
89780
90428
  });
89781
90429
  }, [comparisonLabel, snapshot.data.summary.plant_efficiency?.delta_pp]);
89782
- const idleBadge = React148__default.useMemo(() => {
90430
+ const idleBadge = React125__default.useMemo(() => {
89783
90431
  return buildDeltaBadge(snapshot.data.summary.avg_idle_per_workstation?.delta_seconds, {
89784
90432
  positiveIsGood: false,
89785
90433
  formatter: (value) => formatSignedIdleDuration(value),
89786
90434
  comparisonLabel
89787
90435
  });
89788
90436
  }, [comparisonLabel, snapshot.data.summary.avg_idle_per_workstation?.delta_seconds]);
89789
- const canInspectIdleContributors = React148__default.useMemo(() => {
90437
+ const canInspectIdleContributors = React125__default.useMemo(() => {
89790
90438
  return !showSnapshotSkeleton && snapshot.data.summary.avg_idle_per_workstation?.current_seconds !== null && snapshot.data.summary.avg_idle_per_workstation?.current_seconds !== void 0;
89791
90439
  }, [showSnapshotSkeleton, snapshot.data.summary.avg_idle_per_workstation?.current_seconds]);
89792
- const idleTopContributors = React148__default.useMemo(() => {
90440
+ const idleTopContributors = React125__default.useMemo(() => {
89793
90441
  return (snapshot.data.summary.avg_idle_per_workstation?.top_contributors || []).map((item) => ({
89794
90442
  workspaceId: item.workspace_id || "",
89795
90443
  workspaceName: item.workspace_name?.trim() || item.workspace_id || "Unknown",
@@ -89797,14 +90445,14 @@ var OverviewSummaryCards = React148__default.memo(({ store }) => {
89797
90445
  avgIdleSeconds: toNumber4(item.avg_idle_seconds)
89798
90446
  })).slice(0, 5);
89799
90447
  }, [snapshot.data.summary.avg_idle_per_workstation?.top_contributors]);
89800
- const showIdleContributorLineNames = React148__default.useMemo(() => {
90448
+ const showIdleContributorLineNames = React125__default.useMemo(() => {
89801
90449
  return (scope.line_count ?? 0) > 1;
89802
90450
  }, [scope.line_count]);
89803
- const closeIdleContributors = React148__default.useCallback(() => {
90451
+ const closeIdleContributors = React125__default.useCallback(() => {
89804
90452
  setIsIdleContributorsOpen(false);
89805
90453
  setIsIdleContributorsPinned(false);
89806
90454
  }, []);
89807
- const handleIdleContributorsToggle = React148__default.useCallback(() => {
90455
+ const handleIdleContributorsToggle = React125__default.useCallback(() => {
89808
90456
  if (!canInspectIdleContributors) return;
89809
90457
  setIsIdleContributorsPinned((previous) => {
89810
90458
  const next = !previous;
@@ -89812,7 +90460,7 @@ var OverviewSummaryCards = React148__default.memo(({ store }) => {
89812
90460
  return next;
89813
90461
  });
89814
90462
  }, [canInspectIdleContributors]);
89815
- const handleIdleContributorsKeyDown = React148__default.useCallback((event) => {
90463
+ const handleIdleContributorsKeyDown = React125__default.useCallback((event) => {
89816
90464
  if (!canInspectIdleContributors) return;
89817
90465
  if (event.key === "Enter" || event.key === " ") {
89818
90466
  event.preventDefault();
@@ -89824,11 +90472,11 @@ var OverviewSummaryCards = React148__default.memo(({ store }) => {
89824
90472
  closeIdleContributors();
89825
90473
  }
89826
90474
  }, [canInspectIdleContributors, closeIdleContributors, handleIdleContributorsToggle]);
89827
- React148__default.useEffect(() => {
90475
+ React125__default.useEffect(() => {
89828
90476
  setIsIdleContributorsOpen(false);
89829
90477
  setIsIdleContributorsPinned(false);
89830
90478
  }, [scope.comparison_strategy, scope.current_range?.start_date, scope.current_range?.end_date, scope.line_count, scope.shift_mode]);
89831
- React148__default.useEffect(() => {
90479
+ React125__default.useEffect(() => {
89832
90480
  if (!isIdleContributorsOpen) return void 0;
89833
90481
  const handleClickOutside = (event) => {
89834
90482
  if (!isIdleContributorsPinned) return;
@@ -89966,7 +90614,7 @@ var OverviewSummaryCards = React148__default.memo(({ store }) => {
89966
90614
  ] });
89967
90615
  });
89968
90616
  OverviewSummaryCards.displayName = "OverviewSummaryCards";
89969
- var PoorestPerformersCard = React148__default.memo(({
90617
+ var PoorestPerformersCard = React125__default.memo(({
89970
90618
  store,
89971
90619
  supervisorsByLineId,
89972
90620
  onViewAll,
@@ -89975,9 +90623,9 @@ var PoorestPerformersCard = React148__default.memo(({
89975
90623
  bumpRenderCounter();
89976
90624
  const scope = useOperationsOverviewScope(store);
89977
90625
  const snapshot = useOperationsOverviewSnapshot(store);
89978
- const [poorestLineMode, setPoorestLineMode] = React148__default.useState("output");
90626
+ const [poorestLineMode, setPoorestLineMode] = React125__default.useState("output");
89979
90627
  const availableLineModes = scope.available_line_modes;
89980
- React148__default.useEffect(() => {
90628
+ React125__default.useEffect(() => {
89981
90629
  const hasOutput = !!availableLineModes?.has_output;
89982
90630
  const hasUptime = !!availableLineModes?.has_uptime;
89983
90631
  if (hasOutput && !hasUptime && poorestLineMode !== "output") {
@@ -89986,7 +90634,7 @@ var PoorestPerformersCard = React148__default.memo(({
89986
90634
  setPoorestLineMode("uptime");
89987
90635
  }
89988
90636
  }, [availableLineModes?.has_output, availableLineModes?.has_uptime, poorestLineMode]);
89989
- const comparisonLabel = React148__default.useMemo(() => {
90637
+ const comparisonLabel = React125__default.useMemo(() => {
89990
90638
  return formatComparisonWindow({
89991
90639
  currentDayCount: scope.current_range?.day_count ?? null,
89992
90640
  previousDayCount: scope.previous_range?.day_count ?? null,
@@ -90000,7 +90648,7 @@ var PoorestPerformersCard = React148__default.memo(({
90000
90648
  scope.shift_mode
90001
90649
  ]);
90002
90650
  const showSnapshotSkeleton = snapshot.loading && !snapshot.hasLoadedOnce;
90003
- const mergedPoorestLines = React148__default.useMemo(() => {
90651
+ const mergedPoorestLines = React125__default.useMemo(() => {
90004
90652
  const rows = snapshot.data.poorest_lines?.[poorestLineMode] || [];
90005
90653
  const lineRows = [];
90006
90654
  const areaGroups = /* @__PURE__ */ new Map();
@@ -90080,7 +90728,7 @@ var PoorestPerformersCard = React148__default.memo(({
90080
90728
  }, [poorestLineMode, snapshot.data.poorest_lines, supervisorsByLineId]);
90081
90729
  const showPoorestModeToggle = !!availableLineModes?.has_output && !!availableLineModes?.has_uptime;
90082
90730
  const poorestMetricLabel = poorestLineMode === "uptime" ? "Uptime" : "Efficiency";
90083
- const handlePoorestLineModeChange = React148__default.useCallback((mode) => {
90731
+ const handlePoorestLineModeChange = React125__default.useCallback((mode) => {
90084
90732
  trackCoreEvent("Operations Overview Poorest Line Mode Changed", { mode });
90085
90733
  setPoorestLineMode(mode);
90086
90734
  }, []);
@@ -90166,14 +90814,14 @@ var PoorestPerformersCard = React148__default.memo(({
90166
90814
  ] });
90167
90815
  });
90168
90816
  PoorestPerformersCard.displayName = "PoorestPerformersCard";
90169
- var IdleBreakdownCard = React148__default.memo(({
90817
+ var IdleBreakdownCard = React125__default.memo(({
90170
90818
  store,
90171
90819
  scopedLineCount
90172
90820
  }) => {
90173
90821
  bumpRenderCounter();
90174
90822
  const idle = useOperationsOverviewIdle(store);
90175
90823
  const showInitialSkeleton = idle.loading && idle.lastUpdated === null;
90176
- const idleBreakdown = React148__default.useMemo(() => {
90824
+ const idleBreakdown = React125__default.useMemo(() => {
90177
90825
  return idle.data.map((item) => ({
90178
90826
  name: item.display_name?.trim() || item.reason?.trim() || "Unknown",
90179
90827
  reasonKey: item.reason_key?.trim() || item.reason?.trim() || "unknown",
@@ -90192,7 +90840,7 @@ var IdleBreakdownCard = React148__default.memo(({
90192
90840
  }))
90193
90841
  })).filter((item) => item.value > 0);
90194
90842
  }, [idle.data]);
90195
- const showIdleModuleNotEnabledState = React148__default.useMemo(() => {
90843
+ const showIdleModuleNotEnabledState = React125__default.useMemo(() => {
90196
90844
  const enabledLineCount = idle.scope.idle_time_vlm_enabled_line_count;
90197
90845
  return !showInitialSkeleton && scopedLineCount > 0 && typeof enabledLineCount === "number" && enabledLineCount === 0;
90198
90846
  }, [idle.scope.idle_time_vlm_enabled_line_count, scopedLineCount, showInitialSkeleton]);
@@ -90213,7 +90861,7 @@ var IdleBreakdownCard = React148__default.memo(({
90213
90861
  ] });
90214
90862
  });
90215
90863
  IdleBreakdownCard.displayName = "IdleBreakdownCard";
90216
- var EfficiencyTrendCard = React148__default.memo(({
90864
+ var EfficiencyTrendCard = React125__default.memo(({
90217
90865
  store,
90218
90866
  dateRange,
90219
90867
  appTimezone,
@@ -90221,14 +90869,14 @@ var EfficiencyTrendCard = React148__default.memo(({
90221
90869
  }) => {
90222
90870
  bumpRenderCounter();
90223
90871
  const trend = useOperationsOverviewTrend(store);
90224
- const currentWeekRange = React148__default.useMemo(
90872
+ const currentWeekRange = React125__default.useMemo(
90225
90873
  () => getCurrentWeekToDateRange(appTimezone),
90226
90874
  [appTimezone]
90227
90875
  );
90228
90876
  const isCurrentWeekToDateRange = dateRange.startKey === currentWeekRange.startKey && dateRange.endKey === currentWeekRange.endKey;
90229
90877
  const showInitialSkeleton = trend.loading && trend.lastUpdated === null;
90230
90878
  const isHourlyTrend = trend.data.granularity === "hour";
90231
- const trendData = React148__default.useMemo(() => {
90879
+ const trendData = React125__default.useMemo(() => {
90232
90880
  if (isHourlyTrend) {
90233
90881
  return (trend.data.points || []).map((point, index) => ({
90234
90882
  name: (() => {
@@ -90300,13 +90948,13 @@ var EfficiencyTrendCard = React148__default.memo(({
90300
90948
  };
90301
90949
  });
90302
90950
  }, [currentWeekRange.startKey, hourlyLabelStartTime, isCurrentWeekToDateRange, isHourlyTrend, trend.data.points]);
90303
- const trendTooltipLabelFormatter = React148__default.useCallback((label, payload) => {
90951
+ const trendTooltipLabelFormatter = React125__default.useCallback((label, payload) => {
90304
90952
  if (isHourlyTrend) return label;
90305
90953
  const dayOfWeek = payload?.[0]?.payload?.dayOfWeek;
90306
90954
  if (!dayOfWeek || typeof label !== "string") return label;
90307
90955
  return `${label} (${dayOfWeek})`;
90308
90956
  }, [isHourlyTrend]);
90309
- const trendXAxisTickFormatter = React148__default.useCallback((value, index) => {
90957
+ const trendXAxisTickFormatter = React125__default.useCallback((value, index) => {
90310
90958
  if (!isHourlyTrend) {
90311
90959
  return typeof value === "string" ? value : String(value ?? "");
90312
90960
  }
@@ -90333,7 +90981,7 @@ var EfficiencyTrendCard = React148__default.memo(({
90333
90981
  ] });
90334
90982
  });
90335
90983
  EfficiencyTrendCard.displayName = "EfficiencyTrendCard";
90336
- var TopImprovementsCard = React148__default.memo(({
90984
+ var TopImprovementsCard = React125__default.memo(({
90337
90985
  store,
90338
90986
  supervisorsByLineId,
90339
90987
  onViewAll,
@@ -90342,7 +90990,7 @@ var TopImprovementsCard = React148__default.memo(({
90342
90990
  bumpRenderCounter();
90343
90991
  const improvements = useOperationsOverviewImprovements(store);
90344
90992
  const showInitialSkeleton = improvements.loading && improvements.lastUpdated === null;
90345
- const displayImprovements = React148__default.useMemo(() => {
90993
+ const displayImprovements = React125__default.useMemo(() => {
90346
90994
  return improvements.data.map((item) => {
90347
90995
  const supervisors = item.lineId ? supervisorsByLineId.get(item.lineId) || [] : [];
90348
90996
  return {
@@ -90470,33 +91118,33 @@ var useOperationsOverviewRefresh = ({
90470
91118
  isLiveScope,
90471
91119
  enabled = true
90472
91120
  }) => {
90473
- const lineIdsKey = React148__default.useMemo(() => lineIds.join(","), [lineIds]);
90474
- const scopeSignature = React148__default.useMemo(
91121
+ const lineIdsKey = React125__default.useMemo(() => lineIds.join(","), [lineIds]);
91122
+ const scopeSignature = React125__default.useMemo(
90475
91123
  () => [companyId || "", startKey, endKey, trendMode, comparisonStrategy || "", lineIdsKey].join("::"),
90476
91124
  [companyId, comparisonStrategy, endKey, lineIdsKey, startKey, trendMode]
90477
91125
  );
90478
- const controllersRef = React148__default.useRef({});
90479
- const requestIdsRef = React148__default.useRef({
91126
+ const controllersRef = React125__default.useRef({});
91127
+ const requestIdsRef = React125__default.useRef({
90480
91128
  snapshot: 0,
90481
91129
  trend: 0,
90482
91130
  idle: 0,
90483
91131
  improvements: 0
90484
91132
  });
90485
- const intervalRef = React148__default.useRef(null);
90486
- const isPageActiveRef = React148__default.useRef(true);
90487
- const lastResumeRefreshAtRef = React148__default.useRef(0);
90488
- const abortAll = React148__default.useCallback(() => {
91133
+ const intervalRef = React125__default.useRef(null);
91134
+ const isPageActiveRef = React125__default.useRef(true);
91135
+ const lastResumeRefreshAtRef = React125__default.useRef(0);
91136
+ const abortAll = React125__default.useCallback(() => {
90489
91137
  Object.values(controllersRef.current).forEach((controller) => {
90490
91138
  controller?.abort();
90491
91139
  });
90492
91140
  controllersRef.current = {};
90493
91141
  }, []);
90494
- React148__default.useEffect(() => {
91142
+ React125__default.useEffect(() => {
90495
91143
  return () => {
90496
91144
  abortAll();
90497
91145
  };
90498
91146
  }, [abortAll]);
90499
- const getIsPageActive = React148__default.useCallback(() => {
91147
+ const getIsPageActive = React125__default.useCallback(() => {
90500
91148
  if (typeof document === "undefined") {
90501
91149
  return true;
90502
91150
  }
@@ -90504,7 +91152,7 @@ var useOperationsOverviewRefresh = ({
90504
91152
  const hasFocus = typeof document.hasFocus === "function" ? document.hasFocus() : true;
90505
91153
  return isVisible && hasFocus;
90506
91154
  }, []);
90507
- const stopPolling = React148__default.useCallback((reason) => {
91155
+ const stopPolling = React125__default.useCallback((reason) => {
90508
91156
  if (intervalRef.current === null) {
90509
91157
  return;
90510
91158
  }
@@ -90512,7 +91160,7 @@ var useOperationsOverviewRefresh = ({
90512
91160
  intervalRef.current = null;
90513
91161
  debugRefreshLog("poll stopped", { reason });
90514
91162
  }, []);
90515
- const runRefresh = React148__default.useCallback(
91163
+ const runRefresh = React125__default.useCallback(
90516
91164
  async (section, begin, onSuccess, onError, request, reason) => {
90517
91165
  if (!enabled || !supabase || !companyId || lineIds.length === 0) return;
90518
91166
  const requestId = requestIdsRef.current[section] + 1;
@@ -90559,7 +91207,7 @@ var useOperationsOverviewRefresh = ({
90559
91207
  },
90560
91208
  [companyId, comparisonStrategy, enabled, endKey, lineIds, startKey, supabase, trendMode]
90561
91209
  );
90562
- const refreshSnapshot = React148__default.useCallback(
91210
+ const refreshSnapshot = React125__default.useCallback(
90563
91211
  async (reason) => {
90564
91212
  await runRefresh(
90565
91213
  "snapshot",
@@ -90591,7 +91239,7 @@ var useOperationsOverviewRefresh = ({
90591
91239
  },
90592
91240
  [companyId, comparisonStrategy, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
90593
91241
  );
90594
- const refreshTrend = React148__default.useCallback(
91242
+ const refreshTrend = React125__default.useCallback(
90595
91243
  async (reason) => {
90596
91244
  await runRefresh(
90597
91245
  "trend",
@@ -90620,7 +91268,7 @@ var useOperationsOverviewRefresh = ({
90620
91268
  },
90621
91269
  [companyId, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
90622
91270
  );
90623
- const refreshIdle = React148__default.useCallback(
91271
+ const refreshIdle = React125__default.useCallback(
90624
91272
  async (reason) => {
90625
91273
  await runRefresh(
90626
91274
  "idle",
@@ -90649,7 +91297,7 @@ var useOperationsOverviewRefresh = ({
90649
91297
  },
90650
91298
  [companyId, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
90651
91299
  );
90652
- const refreshImprovements = React148__default.useCallback(
91300
+ const refreshImprovements = React125__default.useCallback(
90653
91301
  async (reason) => {
90654
91302
  await runRefresh(
90655
91303
  "improvements",
@@ -90679,7 +91327,7 @@ var useOperationsOverviewRefresh = ({
90679
91327
  },
90680
91328
  [companyId, lineIds, lineIdsKey, runRefresh, scopeSignature, store, supabase]
90681
91329
  );
90682
- const refreshAll = React148__default.useCallback(
91330
+ const refreshAll = React125__default.useCallback(
90683
91331
  async (reason) => {
90684
91332
  await Promise.allSettled([
90685
91333
  refreshSnapshot(reason),
@@ -90690,7 +91338,7 @@ var useOperationsOverviewRefresh = ({
90690
91338
  },
90691
91339
  [refreshIdle, refreshImprovements, refreshSnapshot, refreshTrend]
90692
91340
  );
90693
- const startPolling = React148__default.useCallback((reason) => {
91341
+ const startPolling = React125__default.useCallback((reason) => {
90694
91342
  if (!isLiveScope || !supabase || !companyId || lineIds.length === 0) {
90695
91343
  return;
90696
91344
  }
@@ -90711,7 +91359,7 @@ var useOperationsOverviewRefresh = ({
90711
91359
  }, LIVE_REFRESH_INTERVAL_MS);
90712
91360
  debugRefreshLog("poll started", { reason, intervalMs: LIVE_REFRESH_INTERVAL_MS });
90713
91361
  }, [companyId, isLiveScope, lineIds.length, refreshAll, stopPolling, supabase]);
90714
- const refreshFromResume = React148__default.useCallback((reason) => {
91362
+ const refreshFromResume = React125__default.useCallback((reason) => {
90715
91363
  const now4 = Date.now();
90716
91364
  if (now4 - lastResumeRefreshAtRef.current < 1e3) {
90717
91365
  debugRefreshLog("resume refresh suppressed", { reason });
@@ -90726,7 +91374,7 @@ var useOperationsOverviewRefresh = ({
90726
91374
  }
90727
91375
  });
90728
91376
  }, [refreshAll, startPolling, stopPolling]);
90729
- React148__default.useEffect(() => {
91377
+ React125__default.useEffect(() => {
90730
91378
  if (!enabled) {
90731
91379
  stopPolling("disabled");
90732
91380
  abortAll();
@@ -90741,7 +91389,7 @@ var useOperationsOverviewRefresh = ({
90741
91389
  }
90742
91390
  void refreshAll("scope_change");
90743
91391
  }, [abortAll, companyId, enabled, lineIds.length, refreshAll, scopeSignature, stopPolling, store, supabase]);
90744
- React148__default.useEffect(() => {
91392
+ React125__default.useEffect(() => {
90745
91393
  if (!enabled || !isLiveScope || !supabase || !companyId || lineIds.length === 0) {
90746
91394
  isPageActiveRef.current = false;
90747
91395
  stopPolling("live_scope_disabled");
@@ -90954,55 +91602,55 @@ var PlantHeadView = () => {
90954
91602
  const { accessibleLineIds } = useUserLineAccess();
90955
91603
  const mobileMenuContext = useMobileMenu();
90956
91604
  useHideMobileHeader(!!mobileMenuContext);
90957
- const storeRef = React148__default.useRef(createOperationsOverviewStore());
91605
+ const storeRef = React125__default.useRef(createOperationsOverviewStore());
90958
91606
  const store = storeRef.current;
90959
- const fallbackOperationalDate = React148__default.useMemo(
91607
+ const fallbackOperationalDate = React125__default.useMemo(
90960
91608
  () => getOperationalDate(appTimezone),
90961
91609
  [appTimezone]
90962
91610
  );
90963
- const [dateRange, setDateRange] = React148__default.useState(() => ({
91611
+ const [dateRange, setDateRange] = React125__default.useState(() => ({
90964
91612
  startKey: fallbackOperationalDate,
90965
91613
  endKey: fallbackOperationalDate
90966
91614
  }));
90967
- const [usesThisWeekComparison, setUsesThisWeekComparison] = React148__default.useState(false);
90968
- const [trendMode, setTrendMode] = React148__default.useState("all");
90969
- const [selectedSupervisorId, setSelectedSupervisorId] = React148__default.useState("all");
90970
- const [selectedLineIds, setSelectedLineIds] = React148__default.useState([]);
90971
- const [isInitialScopeReady, setIsInitialScopeReady] = React148__default.useState(false);
90972
- const [shiftResolutionTick, setShiftResolutionTick] = React148__default.useState(0);
90973
- const hasAutoInitializedScopeRef = React148__default.useRef(false);
90974
- const hasUserAdjustedScopeRef = React148__default.useRef(false);
90975
- React148__default.useEffect(() => {
91615
+ const [usesThisWeekComparison, setUsesThisWeekComparison] = React125__default.useState(false);
91616
+ const [trendMode, setTrendMode] = React125__default.useState("all");
91617
+ const [selectedSupervisorId, setSelectedSupervisorId] = React125__default.useState("all");
91618
+ const [selectedLineIds, setSelectedLineIds] = React125__default.useState([]);
91619
+ const [isInitialScopeReady, setIsInitialScopeReady] = React125__default.useState(false);
91620
+ const [shiftResolutionTick, setShiftResolutionTick] = React125__default.useState(0);
91621
+ const hasAutoInitializedScopeRef = React125__default.useRef(false);
91622
+ const hasUserAdjustedScopeRef = React125__default.useRef(false);
91623
+ React125__default.useEffect(() => {
90976
91624
  trackCorePageView("Operations Overview", {
90977
91625
  dashboard_surface: "operations_overview"
90978
91626
  });
90979
91627
  }, []);
90980
- const currentWeekRange = React148__default.useMemo(
91628
+ const currentWeekRange = React125__default.useMemo(
90981
91629
  () => getCurrentWeekToDateRange(appTimezone),
90982
91630
  [appTimezone]
90983
91631
  );
90984
- const currentWeekDisplayRange = React148__default.useMemo(
91632
+ const currentWeekDisplayRange = React125__default.useMemo(
90985
91633
  () => getCurrentWeekFullRange(appTimezone),
90986
91634
  [appTimezone]
90987
91635
  );
90988
91636
  const isCurrentWeekToDateRange = dateRange.startKey === currentWeekRange.startKey && dateRange.endKey === currentWeekRange.endKey;
90989
- const headerDateRange = React148__default.useMemo(() => {
91637
+ const headerDateRange = React125__default.useMemo(() => {
90990
91638
  if (usesThisWeekComparison && isCurrentWeekToDateRange) {
90991
91639
  return currentWeekDisplayRange;
90992
91640
  }
90993
91641
  return dateRange;
90994
91642
  }, [currentWeekDisplayRange, dateRange, isCurrentWeekToDateRange, usesThisWeekComparison]);
90995
- const normalizedLineIds = React148__default.useMemo(
91643
+ const normalizedLineIds = React125__default.useMemo(
90996
91644
  () => Array.from(new Set(
90997
91645
  (accessibleLineIds || []).filter(Boolean).filter((lineId) => lineId !== factoryViewId)
90998
91646
  )).sort(),
90999
91647
  [accessibleLineIds, factoryViewId]
91000
91648
  );
91001
- const lineIdsKey = React148__default.useMemo(
91649
+ const lineIdsKey = React125__default.useMemo(
91002
91650
  () => normalizedLineIds.join(","),
91003
91651
  [normalizedLineIds]
91004
91652
  );
91005
- const lineOptions = React148__default.useMemo(
91653
+ const lineOptions = React125__default.useMemo(
91006
91654
  () => normalizedLineIds.map((lineId) => ({
91007
91655
  id: lineId,
91008
91656
  name: getLineDisplayName(entityConfig, lineId)
@@ -91014,7 +91662,7 @@ var PlantHeadView = () => {
91014
91662
  companyId: entityConfig.companyId,
91015
91663
  useBackend: true
91016
91664
  });
91017
- const supervisorOptions = React148__default.useMemo(
91665
+ const supervisorOptions = React125__default.useMemo(
91018
91666
  () => {
91019
91667
  const optionsById = /* @__PURE__ */ new Map();
91020
91668
  normalizedLineIds.forEach((lineId) => {
@@ -91040,7 +91688,7 @@ var PlantHeadView = () => {
91040
91688
  },
91041
91689
  [normalizedLineIds, supervisorsByLineId]
91042
91690
  );
91043
- React148__default.useEffect(() => {
91691
+ React125__default.useEffect(() => {
91044
91692
  if (selectedSupervisorId === "all") {
91045
91693
  setSelectedLineIds((previous) => {
91046
91694
  if (normalizedLineIds.length === 0) {
@@ -91066,7 +91714,7 @@ var PlantHeadView = () => {
91066
91714
  const scopedSupervisorLineIds = normalizedLineIds.filter((lineId) => supervisorLineIdSet.has(lineId));
91067
91715
  setSelectedLineIds((previous) => previous.length === scopedSupervisorLineIds.length && previous.every((lineId, index) => lineId === scopedSupervisorLineIds[index]) ? previous : scopedSupervisorLineIds);
91068
91716
  }, [lineIdsKey, normalizedLineIds, selectedSupervisorId, supervisorOptions]);
91069
- const scopedLineIds = React148__default.useMemo(
91717
+ const scopedLineIds = React125__default.useMemo(
91070
91718
  () => selectedLineIds.length > 0 ? selectedLineIds : normalizedLineIds,
91071
91719
  [normalizedLineIds, selectedLineIds]
91072
91720
  );
@@ -91074,7 +91722,7 @@ var PlantHeadView = () => {
91074
91722
  shiftConfigMap,
91075
91723
  isLoading: isShiftConfigLoading
91076
91724
  } = useMultiLineShiftConfigs(scopedLineIds, staticShiftConfig);
91077
- const shiftFilterOptions = React148__default.useMemo(() => {
91725
+ const shiftFilterOptions = React125__default.useMemo(() => {
91078
91726
  const optionsById = /* @__PURE__ */ new Map();
91079
91727
  scopedLineIds.forEach((lineId) => {
91080
91728
  const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
@@ -91113,7 +91761,7 @@ var PlantHeadView = () => {
91113
91761
  ...dynamicOptions
91114
91762
  ];
91115
91763
  }, [appTimezone, scopedLineIds, shiftConfigMap, staticShiftConfig]);
91116
- React148__default.useEffect(() => {
91764
+ React125__default.useEffect(() => {
91117
91765
  if (scopedLineIds.length === 0 || isShiftConfigLoading) {
91118
91766
  return;
91119
91767
  }
@@ -91124,11 +91772,11 @@ var PlantHeadView = () => {
91124
91772
  clearInterval(intervalId);
91125
91773
  };
91126
91774
  }, [isShiftConfigLoading, scopedLineIds.length]);
91127
- const shiftResolutionNow = React148__default.useMemo(
91775
+ const shiftResolutionNow = React125__default.useMemo(
91128
91776
  () => /* @__PURE__ */ new Date(),
91129
91777
  [shiftResolutionTick]
91130
91778
  );
91131
- const earliestDayShiftStartTime = React148__default.useMemo(() => {
91779
+ const earliestDayShiftStartTime = React125__default.useMemo(() => {
91132
91780
  const candidateStarts = [];
91133
91781
  scopedLineIds.forEach((lineId) => {
91134
91782
  const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
@@ -91164,11 +91812,11 @@ var PlantHeadView = () => {
91164
91812
  const minutes = earliestMinutes % 60;
91165
91813
  return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
91166
91814
  }, [appTimezone, scopedLineIds, shiftConfigMap, staticShiftConfig]);
91167
- const resolvedOperationalToday = React148__default.useMemo(
91815
+ const resolvedOperationalToday = React125__default.useMemo(
91168
91816
  () => getOperationalDate(appTimezone, shiftResolutionNow, earliestDayShiftStartTime),
91169
91817
  [appTimezone, earliestDayShiftStartTime, shiftResolutionNow]
91170
91818
  );
91171
- const activeLineShiftStates = React148__default.useMemo(() => {
91819
+ const activeLineShiftStates = React125__default.useMemo(() => {
91172
91820
  return scopedLineIds.flatMap((lineId) => {
91173
91821
  const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
91174
91822
  const activeShift = getActiveShift(appTimezone, shiftConfig, shiftResolutionNow);
@@ -91198,7 +91846,7 @@ var PlantHeadView = () => {
91198
91846
  });
91199
91847
  }, [appTimezone, scopedLineIds, shiftConfigMap, shiftResolutionNow, staticShiftConfig]);
91200
91848
  const resolvedTrendMode = isInitialScopeReady ? trendMode : "all";
91201
- const hourlyWindowStartTime = React148__default.useMemo(() => {
91849
+ const hourlyWindowStartTime = React125__default.useMemo(() => {
91202
91850
  if (scopedLineIds.length === 0) {
91203
91851
  return null;
91204
91852
  }
@@ -91255,12 +91903,12 @@ var PlantHeadView = () => {
91255
91903
  const minutes = earliestMinutes % 60;
91256
91904
  return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
91257
91905
  }, [appTimezone, resolvedTrendMode, scopedLineIds, shiftConfigMap, staticShiftConfig]);
91258
- const isShiftScopeResolved = React148__default.useMemo(
91906
+ const isShiftScopeResolved = React125__default.useMemo(
91259
91907
  () => !isShiftConfigLoading,
91260
91908
  [isShiftConfigLoading]
91261
91909
  );
91262
- const initializedTimezoneRef = React148__default.useRef(appTimezone);
91263
- React148__default.useEffect(() => {
91910
+ const initializedTimezoneRef = React125__default.useRef(appTimezone);
91911
+ React125__default.useEffect(() => {
91264
91912
  if (initializedTimezoneRef.current === appTimezone) return;
91265
91913
  hasAutoInitializedScopeRef.current = false;
91266
91914
  hasUserAdjustedScopeRef.current = false;
@@ -91273,7 +91921,7 @@ var PlantHeadView = () => {
91273
91921
  setIsInitialScopeReady(false);
91274
91922
  initializedTimezoneRef.current = appTimezone;
91275
91923
  }, [appTimezone, fallbackOperationalDate]);
91276
- React148__default.useEffect(() => {
91924
+ React125__default.useEffect(() => {
91277
91925
  if (hasAutoInitializedScopeRef.current || hasUserAdjustedScopeRef.current) {
91278
91926
  return;
91279
91927
  }
@@ -91298,7 +91946,7 @@ var PlantHeadView = () => {
91298
91946
  hasAutoInitializedScopeRef.current = true;
91299
91947
  setIsInitialScopeReady(true);
91300
91948
  }, [fallbackOperationalDate, isShiftScopeResolved, resolvedOperationalToday, scopedLineIds.length]);
91301
- const handleDateRangeChange = React148__default.useCallback((range, meta) => {
91949
+ const handleDateRangeChange = React125__default.useCallback((range, meta) => {
91302
91950
  hasUserAdjustedScopeRef.current = true;
91303
91951
  setIsInitialScopeReady(true);
91304
91952
  trackCoreEvent("Operations Overview Date Range Changed", {
@@ -91316,12 +91964,12 @@ var PlantHeadView = () => {
91316
91964
  return previous;
91317
91965
  });
91318
91966
  }, []);
91319
- const handleTrendModeChange = React148__default.useCallback((mode) => {
91967
+ const handleTrendModeChange = React125__default.useCallback((mode) => {
91320
91968
  hasUserAdjustedScopeRef.current = true;
91321
91969
  setIsInitialScopeReady(true);
91322
91970
  setTrendMode(mode);
91323
91971
  }, []);
91324
- const handleSelectedLineIdsChange = React148__default.useCallback((lineIds) => {
91972
+ const handleSelectedLineIdsChange = React125__default.useCallback((lineIds) => {
91325
91973
  setSelectedSupervisorId("all");
91326
91974
  if (normalizedLineIds.length === 0) {
91327
91975
  setSelectedLineIds([]);
@@ -91332,10 +91980,10 @@ var PlantHeadView = () => {
91332
91980
  const next = normalizedLineIds.filter((lineId) => selectedSet.has(lineId));
91333
91981
  setSelectedLineIds(next.length > 0 ? next : normalizedLineIds);
91334
91982
  }, [normalizedLineIds]);
91335
- const handleSelectedSupervisorIdChange = React148__default.useCallback((supervisorId) => {
91983
+ const handleSelectedSupervisorIdChange = React125__default.useCallback((supervisorId) => {
91336
91984
  setSelectedSupervisorId(supervisorId);
91337
91985
  }, []);
91338
- const buildLineMonthlyHistoryUrl = React148__default.useCallback((lineId) => {
91986
+ const buildLineMonthlyHistoryUrl = React125__default.useCallback((lineId) => {
91339
91987
  const rangeStartDate = parseDateKeyToDate(dateRange.startKey);
91340
91988
  const params = new URLSearchParams();
91341
91989
  params.set("tab", "monthly_history");
@@ -91345,15 +91993,15 @@ var PlantHeadView = () => {
91345
91993
  params.set("rangeEnd", dateRange.endKey);
91346
91994
  return `/kpis/${lineId}?${params.toString()}`;
91347
91995
  }, [dateRange.endKey, dateRange.startKey]);
91348
- const handleViewAllPoorestPerformers = React148__default.useCallback(() => {
91996
+ const handleViewAllPoorestPerformers = React125__default.useCallback(() => {
91349
91997
  trackCoreEvent("Operations Overview View All Clicked", { section: "poorest_performers" });
91350
91998
  navigate("/kpis?tab=leaderboard");
91351
91999
  }, [navigate]);
91352
- const handleViewAllImprovements = React148__default.useCallback(() => {
92000
+ const handleViewAllImprovements = React125__default.useCallback(() => {
91353
92001
  trackCoreEvent("Operations Overview View All Clicked", { section: "improvements" });
91354
92002
  navigate("/improvement-center");
91355
92003
  }, [navigate]);
91356
- const handleOpenImprovement = React148__default.useCallback((item) => {
92004
+ const handleOpenImprovement = React125__default.useCallback((item) => {
91357
92005
  trackCoreEvent("Operations Overview Improvement Clicked", {
91358
92006
  issue_id: item.issueId,
91359
92007
  issue_number: item.issueNumber,
@@ -91364,13 +92012,13 @@ var PlantHeadView = () => {
91364
92012
  });
91365
92013
  navigate(`/improvement-center?${params.toString()}`);
91366
92014
  }, [navigate]);
91367
- const comparisonStrategy = React148__default.useMemo(() => {
92015
+ const comparisonStrategy = React125__default.useMemo(() => {
91368
92016
  if (usesThisWeekComparison && isCurrentWeekToDateRange) {
91369
92017
  return "previous_full_week";
91370
92018
  }
91371
92019
  return void 0;
91372
92020
  }, [isCurrentWeekToDateRange, usesThisWeekComparison]);
91373
- const effectiveDateRange = React148__default.useMemo(() => {
92021
+ const effectiveDateRange = React125__default.useMemo(() => {
91374
92022
  if (isInitialScopeReady) {
91375
92023
  return dateRange;
91376
92024
  }
@@ -91380,11 +92028,11 @@ var PlantHeadView = () => {
91380
92028
  endKey: nextStartKey
91381
92029
  };
91382
92030
  }, [dateRange, fallbackOperationalDate, isInitialScopeReady, resolvedOperationalToday]);
91383
- const effectiveTrendMode = React148__default.useMemo(
92031
+ const effectiveTrendMode = React125__default.useMemo(
91384
92032
  () => resolvedTrendMode,
91385
92033
  [resolvedTrendMode]
91386
92034
  );
91387
- const hasActiveSelectedShiftLine = React148__default.useMemo(
92035
+ const hasActiveSelectedShiftLine = React125__default.useMemo(
91388
92036
  () => activeLineShiftStates.some((shift) => {
91389
92037
  if (shift.date !== resolvedOperationalToday) return false;
91390
92038
  if (effectiveTrendMode === "all") return true;
@@ -91396,7 +92044,7 @@ var PlantHeadView = () => {
91396
92044
  }),
91397
92045
  [activeLineShiftStates, effectiveTrendMode, resolvedOperationalToday]
91398
92046
  );
91399
- const activeLiveShiftName = React148__default.useMemo(
92047
+ const activeLiveShiftName = React125__default.useMemo(
91400
92048
  () => {
91401
92049
  if (effectiveTrendMode === "all") return null;
91402
92050
  const matchingShift = activeLineShiftStates.find((shift) => {
@@ -91411,17 +92059,17 @@ var PlantHeadView = () => {
91411
92059
  },
91412
92060
  [activeLineShiftStates, effectiveTrendMode, resolvedOperationalToday]
91413
92061
  );
91414
- const hourlyLabelStartTime = React148__default.useMemo(() => {
92062
+ const hourlyLabelStartTime = React125__default.useMemo(() => {
91415
92063
  if (scopedLineIds.length === 0) {
91416
92064
  return null;
91417
92065
  }
91418
92066
  return hourlyWindowStartTime;
91419
92067
  }, [hourlyWindowStartTime, scopedLineIds.length]);
91420
- const isSingleDayScope = React148__default.useMemo(
92068
+ const isSingleDayScope = React125__default.useMemo(
91421
92069
  () => effectiveDateRange.startKey === effectiveDateRange.endKey,
91422
92070
  [effectiveDateRange.endKey, effectiveDateRange.startKey]
91423
92071
  );
91424
- const isLiveScope = React148__default.useMemo(
92072
+ const isLiveScope = React125__default.useMemo(
91425
92073
  () => isSingleDayScope && effectiveDateRange.startKey === resolvedOperationalToday && hasActiveSelectedShiftLine,
91426
92074
  [
91427
92075
  effectiveDateRange.startKey,
@@ -91431,7 +92079,7 @@ var PlantHeadView = () => {
91431
92079
  resolvedOperationalToday
91432
92080
  ]
91433
92081
  );
91434
- const handleOpenLineDetails = React148__default.useCallback((line) => {
92082
+ const handleOpenLineDetails = React125__default.useCallback((line) => {
91435
92083
  trackCoreEvent("Operations Overview Line Clicked", {
91436
92084
  line_id: line.rowType === "line" ? line.id : null,
91437
92085
  line_name: line.name,