@optifye/dashboard-core 6.11.17 → 6.11.19

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,22 +1,22 @@
1
- import * as React141 from 'react';
2
- import React141__default, { createContext, useRef, useCallback, useState, useMemo, useEffect, forwardRef, useImperativeHandle, useLayoutEffect, memo as memo$1, useContext, useSyncExternalStore, useId, Children, isValidElement, useInsertionEffect, startTransition, Fragment as Fragment$1, createElement, Component } from 'react';
1
+ import * as React142 from 'react';
2
+ import React142__default, { createContext, useRef, useCallback, useState, useMemo, useEffect, forwardRef, useImperativeHandle, useLayoutEffect, memo as memo$1, useContext, useSyncExternalStore, useId, Children, isValidElement, useInsertionEffect, startTransition, Fragment as Fragment$1, createElement, Component } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { useRouter } from 'next/router';
5
5
  import { toast } from 'sonner';
6
- import { fromZonedTime, formatInTimeZone, toZonedTime } from 'date-fns-tz';
6
+ import { formatInTimeZone, fromZonedTime, toZonedTime } from 'date-fns-tz';
7
7
  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';
8
8
  import mixpanel from 'mixpanel-browser';
9
9
  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, Map as Map$1, Video, ShieldCheck, Star, Award, Filter, X, Coffee, Plus, ArrowUp, ArrowDown, ArrowRight, ArrowLeft, Clock, Calendar, Save, AlertCircle, Loader2, Minus, ChevronLeft, ChevronRight, TrendingUp, Sparkles, Pause, Play, XCircle, HelpCircle, Activity, Wrench, UserX, Package, RefreshCw, Palette, CheckCircle2, TrendingDown, FolderOpen, Folder, Tag, Sliders, Layers, Search, Edit2, CheckCircle, User, Users, Shield, Building2, Mail, Lock, Info, Share2, Trophy, Target, Download, Sun, Moon, MousePointer, UserPlus, UserCog, Trash2, Eye, MoreVertical, BarChart3, Pencil, UserCheck, LogOut, Film, MessageSquare, Menu, Send, Copy, Settings, LifeBuoy, EyeOff, Zap, Flame, Crown, Medal } from 'lucide-react';
13
+ import { Camera, AlertTriangle, ChevronDown, ChevronUp, Check, Map as Map$1, Video, ShieldCheck, Star, Award, Filter, X, Coffee, Plus, ArrowUp, ArrowDown, ArrowRight, ArrowLeft, Clock, Calendar, Save, AlertCircle, Loader2, Minus, ChevronLeft, ChevronRight, TrendingUp, Sparkles, Pause, Play, XCircle, HelpCircle, Activity, Wrench, UserX, Package, RefreshCw, Palette, CheckCircle2, TrendingDown, FolderOpen, Folder, Tag, Sliders, Layers, Search, Edit2, CheckCircle, User, Users, Shield, Building2, Mail, Lock, Info, Share2, Trophy, Target, Download, Copy, Sun, Moon, MousePointer, UserPlus, UserCog, Trash2, Eye, MoreVertical, BarChart3, Pencil, UserCheck, LogOut, Film, MessageSquare, Menu, Send, Settings, LifeBuoy, EyeOff, Zap, 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, PieChart, Pie, Cell, LineChart as LineChart$1, Line, ComposedChart, Area, ScatterChart, Scatter } from 'recharts';
16
16
  import { Slot } from '@radix-ui/react-slot';
17
17
  import * as SelectPrimitive from '@radix-ui/react-select';
18
18
  import { DayPicker, useNavigation as useNavigation$1 } from 'react-day-picker';
19
- import { AdjustmentsHorizontalIcon, ClockIcon, UsersIcon, UserCircleIcon, TicketIcon, CurrencyDollarIcon, QuestionMarkCircleIcon, XMarkIcon, ArrowRightIcon, Bars3Icon, HomeIcon, VideoCameraIcon, TrophyIcon, ChartBarIcon, LightBulbIcon, CubeIcon, HeartIcon, BellIcon, Cog6ToothIcon, ChevronRightIcon, ArrowRightStartOnRectangleIcon, ExclamationCircleIcon, ExclamationTriangleIcon, CalendarIcon, ChevronDownIcon, ChevronLeftIcon, EnvelopeIcon, DocumentTextIcon, ChevronUpIcon, ArrowDownTrayIcon, CheckCircleIcon, ChatBubbleLeftRightIcon, XCircleIcon, FunnelIcon, EyeIcon, InformationCircleIcon, ArrowLeftIcon, PlayCircleIcon } from '@heroicons/react/24/outline';
19
+ import { AdjustmentsHorizontalIcon, ClockIcon, UsersIcon, UserCircleIcon, TicketIcon, CurrencyDollarIcon, QuestionMarkCircleIcon, XMarkIcon, InformationCircleIcon, ArrowRightIcon, 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, ArrowLeftIcon, PlayCircleIcon } from '@heroicons/react/24/outline';
20
20
  import { CheckIcon } from '@heroicons/react/24/solid';
21
21
  import html2canvas from 'html2canvas';
22
22
  import jsPDF, { jsPDF as jsPDF$1 } from 'jspdf';
@@ -1938,14 +1938,14 @@ var useIdleTimeVlmConfig = () => {
1938
1938
  }
1939
1939
  return context;
1940
1940
  };
1941
- var DashboardConfigContext = React141.createContext(void 0);
1941
+ var DashboardConfigContext = React142.createContext(void 0);
1942
1942
  var DashboardProvider = ({ config: userProvidedConfig, children }) => {
1943
- const fullConfig = React141.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
1943
+ const fullConfig = React142.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
1944
1944
  _setDashboardConfigInstance(fullConfig);
1945
- React141.useEffect(() => {
1945
+ React142.useEffect(() => {
1946
1946
  _setDashboardConfigInstance(fullConfig);
1947
1947
  }, [fullConfig]);
1948
- React141.useEffect(() => {
1948
+ React142.useEffect(() => {
1949
1949
  if (!fullConfig.theme) return;
1950
1950
  const styleId = "dashboard-core-theme-vars";
1951
1951
  let styleEl = document.getElementById(styleId);
@@ -1971,7 +1971,7 @@ var DashboardProvider = ({ config: userProvidedConfig, children }) => {
1971
1971
  return /* @__PURE__ */ jsx(DashboardConfigContext.Provider, { value: fullConfig, children: /* @__PURE__ */ jsx(IdleTimeVlmConfigProvider, { children }) });
1972
1972
  };
1973
1973
  var useDashboardConfig = () => {
1974
- const ctx = React141.useContext(DashboardConfigContext);
1974
+ const ctx = React142.useContext(DashboardConfigContext);
1975
1975
  if (!ctx) throw new Error("useDashboardConfig must be used within a DashboardProvider");
1976
1976
  return ctx;
1977
1977
  };
@@ -3981,7 +3981,8 @@ var dashboardService = {
3981
3981
  enable,
3982
3982
  monitoring_mode,
3983
3983
  assembly,
3984
- video_grid_metric_mode
3984
+ video_grid_metric_mode,
3985
+ recent_flow_window_minutes
3985
3986
  `).eq("enable", true);
3986
3987
  if (companyId) {
3987
3988
  query = query.eq("company_id", companyId);
@@ -4006,7 +4007,8 @@ var dashboardService = {
4006
4007
  video_grid_metric_mode: normalizeVideoGridMetricMode(
4007
4008
  line.video_grid_metric_mode,
4008
4009
  line.assembly ?? false
4009
- )
4010
+ ),
4011
+ recent_flow_window_minutes: line.recent_flow_window_minutes ?? 7
4010
4012
  }));
4011
4013
  return transformedLines;
4012
4014
  } catch (err) {
@@ -4043,7 +4045,7 @@ var dashboardService = {
4043
4045
  }
4044
4046
  const lineIdsToQuery = configuredLineIds;
4045
4047
  const [line1Result, metricsResult2] = await Promise.all([
4046
- supabase.from(linesTable).select("id, line_name, factory_id, monitoring_mode, assembly, video_grid_metric_mode, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", defaultLineId).single(),
4048
+ supabase.from(linesTable).select("id, line_name, factory_id, monitoring_mode, assembly, video_grid_metric_mode, recent_flow_window_minutes, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", defaultLineId).single(),
4047
4049
  supabase.from(lineMetricsTable).select("*").in("line_id", lineIdsToQuery).eq("shift_id", queryShiftId).eq("date", queryDate)
4048
4050
  ]);
4049
4051
  if (line1Result.error) throw line1Result.error;
@@ -4099,6 +4101,7 @@ var dashboardService = {
4099
4101
  date: queryDate,
4100
4102
  shift_id: queryShiftId,
4101
4103
  monitoring_mode: line1Data.monitoring_mode ?? void 0,
4104
+ recent_flow_window_minutes: line1Data.recent_flow_window_minutes ?? 7,
4102
4105
  metrics: {
4103
4106
  avg_efficiency: avgEfficiency,
4104
4107
  avg_cycle_time: combinedMetricsData.avg_cycle_time / numLines,
@@ -4122,7 +4125,7 @@ var dashboardService = {
4122
4125
  throw new Error("Company ID must be configured for detailed line requests.");
4123
4126
  }
4124
4127
  const [lineResult, metricsResult] = await Promise.all([
4125
- supabase.from(linesTable).select("id, line_name, factory_id, monitoring_mode, assembly, video_grid_metric_mode, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", lineIdToQuery).single(),
4128
+ supabase.from(linesTable).select("id, line_name, factory_id, monitoring_mode, assembly, video_grid_metric_mode, recent_flow_window_minutes, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", lineIdToQuery).single(),
4126
4129
  supabase.from(lineMetricsTable).select("*").eq("line_id", lineIdToQuery).eq("shift_id", queryShiftId).eq("date", queryDate)
4127
4130
  ]);
4128
4131
  if (lineResult.error) throw lineResult.error;
@@ -4147,6 +4150,7 @@ var dashboardService = {
4147
4150
  date: queryDate,
4148
4151
  shift_id: queryShiftId,
4149
4152
  monitoring_mode: lineData.monitoring_mode ?? void 0,
4153
+ recent_flow_window_minutes: lineData.recent_flow_window_minutes ?? 7,
4150
4154
  metrics: {
4151
4155
  avg_efficiency: metrics2?.avg_efficiency ?? 0,
4152
4156
  avg_cycle_time: metrics2?.avg_cycle_time || 0,
@@ -4635,6 +4639,11 @@ var workspaceService = {
4635
4639
  _workspaceVideoStreamsInFlight: /* @__PURE__ */ new Map(),
4636
4640
  _workspaceVideoStreamsCacheExpiryMs: 5 * 60 * 1e3,
4637
4641
  // 5 minutes cache
4642
+ // Cache for workspace camera IPs derived from CV configs
4643
+ _workspaceCameraIpsCache: /* @__PURE__ */ new Map(),
4644
+ _workspaceCameraIpsInFlight: /* @__PURE__ */ new Map(),
4645
+ _workspaceCameraIpsCacheExpiryMs: 5 * 60 * 1e3,
4646
+ // 5 minutes cache
4638
4647
  async getWorkspaces(lineId, options) {
4639
4648
  const enabledOnly = options?.enabledOnly ?? false;
4640
4649
  const force = options?.force ?? false;
@@ -4736,6 +4745,61 @@ var workspaceService = {
4736
4745
  this._workspaceVideoStreamsInFlight.set(cacheKey, fetchPromise);
4737
4746
  return fetchPromise;
4738
4747
  },
4748
+ async getWorkspaceCameraIps(params) {
4749
+ const workspaceIds = (params.workspaceIds || []).filter(Boolean);
4750
+ const lineIds = (params.lineIds || []).filter(Boolean);
4751
+ const force = params.force ?? false;
4752
+ if (!workspaceIds.length && !lineIds.length) {
4753
+ return {};
4754
+ }
4755
+ const workspaceKey = workspaceIds.slice().sort().join(",");
4756
+ const lineKey = lineIds.slice().sort().join(",");
4757
+ const cacheKey = workspaceKey ? `workspaces:${workspaceKey}` : `lines:${lineKey}`;
4758
+ const now4 = Date.now();
4759
+ const cached = this._workspaceCameraIpsCache.get(cacheKey);
4760
+ if (!force && cached && now4 - cached.timestamp < this._workspaceCameraIpsCacheExpiryMs) {
4761
+ return cached.cameraIps;
4762
+ }
4763
+ const inFlight = this._workspaceCameraIpsInFlight.get(cacheKey);
4764
+ if (!force && inFlight) {
4765
+ return inFlight;
4766
+ }
4767
+ const fetchPromise = (async () => {
4768
+ try {
4769
+ const token = await getAuthToken2();
4770
+ const apiUrl = getBackendUrl2();
4771
+ const response = await fetch(`${apiUrl}/api/workspaces/camera-ips`, {
4772
+ method: "POST",
4773
+ headers: {
4774
+ "Authorization": `Bearer ${token}`,
4775
+ "Content-Type": "application/json"
4776
+ },
4777
+ body: JSON.stringify({
4778
+ workspace_ids: workspaceIds.length ? workspaceIds : void 0,
4779
+ line_ids: lineIds.length ? lineIds : void 0
4780
+ })
4781
+ });
4782
+ if (!response.ok) {
4783
+ const errorText = await response.text();
4784
+ throw new Error(`Backend API error (${response.status}): ${errorText}`);
4785
+ }
4786
+ const data = await response.json();
4787
+ const cameraIps = data.camera_ips || {};
4788
+ this._workspaceCameraIpsCache.set(cacheKey, {
4789
+ cameraIps,
4790
+ timestamp: Date.now()
4791
+ });
4792
+ return cameraIps;
4793
+ } catch (error) {
4794
+ console.error("Error fetching workspace camera IPs:", error);
4795
+ throw error;
4796
+ } finally {
4797
+ this._workspaceCameraIpsInFlight.delete(cacheKey);
4798
+ }
4799
+ })();
4800
+ this._workspaceCameraIpsInFlight.set(cacheKey, fetchPromise);
4801
+ return fetchPromise;
4802
+ },
4739
4803
  /**
4740
4804
  * Fetches workspace display names from the database
4741
4805
  * Returns a map of workspace_id -> display_name
@@ -8480,7 +8544,8 @@ var LinesService = class {
8480
8544
  videoGridMetricMode: normalizeVideoGridMetricMode(
8481
8545
  line.video_grid_metric_mode,
8482
8546
  line.assembly ?? false
8483
- )
8547
+ ),
8548
+ recentFlowWindowMinutes: line.recent_flow_window_minutes ?? 7
8484
8549
  }));
8485
8550
  } catch (error) {
8486
8551
  console.error("Error fetching lines:", error);
@@ -8528,7 +8593,8 @@ var LinesService = class {
8528
8593
  videoGridMetricMode: normalizeVideoGridMetricMode(
8529
8594
  line.video_grid_metric_mode,
8530
8595
  line.assembly ?? false
8531
- )
8596
+ ),
8597
+ recentFlowWindowMinutes: line.recent_flow_window_minutes ?? 7
8532
8598
  }));
8533
8599
  } catch (error) {
8534
8600
  console.error("Error fetching all lines:", error);
@@ -8585,7 +8651,8 @@ var LinesService = class {
8585
8651
  videoGridMetricMode: normalizeVideoGridMetricMode(
8586
8652
  data.video_grid_metric_mode,
8587
8653
  data.assembly ?? false
8588
- )
8654
+ ),
8655
+ recentFlowWindowMinutes: data.recent_flow_window_minutes ?? 7
8589
8656
  };
8590
8657
  } catch (error) {
8591
8658
  console.error("Error fetching line:", error);
@@ -11123,7 +11190,7 @@ var useMobileMenu = () => {
11123
11190
  };
11124
11191
  var useHideMobileHeader = (shouldHide = true) => {
11125
11192
  const context = useMobileMenu();
11126
- React141__default.useEffect(() => {
11193
+ React142__default.useEffect(() => {
11127
11194
  if (context && shouldHide) {
11128
11195
  context.setHideMobileHeader(true);
11129
11196
  return () => {
@@ -13339,6 +13406,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
13339
13406
  actionName: item.action_name
13340
13407
  }),
13341
13408
  recent_flow_percent: item.recent_flow_percent ?? null,
13409
+ recent_flow_window_minutes: item.recent_flow_window_minutes ?? null,
13342
13410
  recent_flow_effective_end_at: item.recent_flow_effective_end_at ?? null,
13343
13411
  recent_flow_computed_at: item.recent_flow_computed_at ?? null,
13344
13412
  incoming_wip_current: item.incoming_wip_current ?? null,
@@ -19883,6 +19951,53 @@ function useCompanyClipsCost() {
19883
19951
  refetch: fetchData
19884
19952
  };
19885
19953
  }
19954
+ function useCompanyHasVlmEnabledLine(options = {}) {
19955
+ const { enabled = true } = options;
19956
+ const { user } = useAuth();
19957
+ const supabase = useSupabase();
19958
+ const entityConfig = useEntityConfig();
19959
+ const [hasVlmEnabledLine, setHasVlmEnabledLine] = useState(false);
19960
+ const [isLoading, setIsLoading] = useState(enabled);
19961
+ const companyId = user?.properties?.company_id || user?.company_id || entityConfig.companyId;
19962
+ useEffect(() => {
19963
+ let isCancelled = false;
19964
+ const load = async () => {
19965
+ if (!enabled || !companyId || !supabase) {
19966
+ setHasVlmEnabledLine(false);
19967
+ setIsLoading(false);
19968
+ return;
19969
+ }
19970
+ setIsLoading(true);
19971
+ try {
19972
+ const { data, error } = await supabase.from("lines").select("id").eq("company_id", companyId).eq("idle_time_vlm_enabled", true).limit(1);
19973
+ if (error) {
19974
+ throw error;
19975
+ }
19976
+ if (isCancelled) {
19977
+ return;
19978
+ }
19979
+ setHasVlmEnabledLine((data?.length || 0) > 0);
19980
+ } catch (error) {
19981
+ console.error("[useCompanyHasVlmEnabledLine] Error:", error);
19982
+ if (!isCancelled) {
19983
+ setHasVlmEnabledLine(false);
19984
+ }
19985
+ } finally {
19986
+ if (!isCancelled) {
19987
+ setIsLoading(false);
19988
+ }
19989
+ }
19990
+ };
19991
+ void load();
19992
+ return () => {
19993
+ isCancelled = true;
19994
+ };
19995
+ }, [companyId, enabled, supabase]);
19996
+ return {
19997
+ hasVlmEnabledLine,
19998
+ isLoading
19999
+ };
20000
+ }
19886
20001
 
19887
20002
  // src/lib/utils/api.ts
19888
20003
  var apiUtils = {
@@ -23115,7 +23230,7 @@ var MotionConfigContext = createContext({
23115
23230
  });
23116
23231
 
23117
23232
  // ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PopChild.mjs
23118
- var PopChildMeasure = class extends React141.Component {
23233
+ var PopChildMeasure = class extends React142.Component {
23119
23234
  getSnapshotBeforeUpdate(prevProps) {
23120
23235
  const element = this.props.childRef.current;
23121
23236
  if (element && prevProps.isPresent && !this.props.isPresent) {
@@ -23170,7 +23285,7 @@ function PopChild({ children, isPresent }) {
23170
23285
  document.head.removeChild(style);
23171
23286
  };
23172
23287
  }, [isPresent]);
23173
- return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React141.cloneElement(children, { ref }) });
23288
+ return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React142.cloneElement(children, { ref }) });
23174
23289
  }
23175
23290
 
23176
23291
  // ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PresenceChild.mjs
@@ -23207,7 +23322,7 @@ var PresenceChild = ({ children, initial, isPresent, onExitComplete, custom, pre
23207
23322
  useMemo(() => {
23208
23323
  presenceChildren.forEach((_, key) => presenceChildren.set(key, false));
23209
23324
  }, [isPresent]);
23210
- React141.useEffect(() => {
23325
+ React142.useEffect(() => {
23211
23326
  !isPresent && !presenceChildren.size && onExitComplete && onExitComplete();
23212
23327
  }, [isPresent]);
23213
23328
  if (mode === "popLayout") {
@@ -30992,7 +31107,7 @@ var withAuth = (WrappedComponent2, options) => {
30992
31107
  requireAuth: true,
30993
31108
  ...options
30994
31109
  };
30995
- const WithAuthComponent = React141.memo(function WithAuthComponent2(props) {
31110
+ const WithAuthComponent = React142.memo(function WithAuthComponent2(props) {
30996
31111
  const {
30997
31112
  session,
30998
31113
  user,
@@ -31003,9 +31118,9 @@ var withAuth = (WrappedComponent2, options) => {
31003
31118
  retrySessionHydration
31004
31119
  } = useAuth();
31005
31120
  const router = useRouter();
31006
- const [localLoading, setLocalLoading] = React141.useState(loading);
31007
- const [loadingTimeoutReached, setLoadingTimeoutReached] = React141.useState(false);
31008
- React141.useEffect(() => {
31121
+ const [localLoading, setLocalLoading] = React142.useState(loading);
31122
+ const [loadingTimeoutReached, setLoadingTimeoutReached] = React142.useState(false);
31123
+ React142.useEffect(() => {
31009
31124
  if (process.env.NODE_ENV === "development" && process.env.DEBUG_AUTH === "true") {
31010
31125
  console.log("withAuth state:", {
31011
31126
  loading,
@@ -31017,7 +31132,7 @@ var withAuth = (WrappedComponent2, options) => {
31017
31132
  });
31018
31133
  }
31019
31134
  }, [authStatus, error, loading, session, user]);
31020
- const handleLoadingTimeout = React141.useCallback(() => {
31135
+ const handleLoadingTimeout = React142.useCallback(() => {
31021
31136
  console.warn("[withAuth] Loading timeout reached");
31022
31137
  setLoadingTimeoutReached(true);
31023
31138
  if (hasStoredSupabaseSession()) {
@@ -31029,13 +31144,13 @@ var withAuth = (WrappedComponent2, options) => {
31029
31144
  router.replace(defaultOptions.redirectTo);
31030
31145
  }
31031
31146
  }, [retrySessionHydration, router]);
31032
- React141.useEffect(() => {
31147
+ React142.useEffect(() => {
31033
31148
  if (!loading && authStatus !== "recovering" && defaultOptions.requireAuth && !session && !error) {
31034
31149
  console.log("[withAuth] No session found, redirecting to login");
31035
31150
  router.replace(defaultOptions.redirectTo);
31036
31151
  }
31037
31152
  }, [authStatus, defaultOptions.requireAuth, error, loading, router, session]);
31038
- React141.useEffect(() => {
31153
+ React142.useEffect(() => {
31039
31154
  setLocalLoading(loading);
31040
31155
  }, [loading]);
31041
31156
  if (loading || localLoading) {
@@ -32034,11 +32149,11 @@ var BarChartComponent = ({
32034
32149
  aspect = 2,
32035
32150
  ...restOfChartProps
32036
32151
  }) => {
32037
- const containerRef = React141__default.useRef(null);
32038
- const [containerReady, setContainerReady] = React141__default.useState(false);
32152
+ const containerRef = React142__default.useRef(null);
32153
+ const [containerReady, setContainerReady] = React142__default.useState(false);
32039
32154
  const themeConfig = useThemeConfig();
32040
32155
  const { formatNumber } = useFormatNumber();
32041
- React141__default.useEffect(() => {
32156
+ React142__default.useEffect(() => {
32042
32157
  const checkContainerDimensions = () => {
32043
32158
  if (containerRef.current) {
32044
32159
  const rect = containerRef.current.getBoundingClientRect();
@@ -32152,7 +32267,7 @@ var BarChartComponent = ({
32152
32267
  }
32153
32268
  return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: chartContent });
32154
32269
  };
32155
- var BarChart = React141__default.memo(BarChartComponent, (prevProps, nextProps) => {
32270
+ var BarChart = React142__default.memo(BarChartComponent, (prevProps, nextProps) => {
32156
32271
  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) {
32157
32272
  return false;
32158
32273
  }
@@ -32203,10 +32318,10 @@ var LineChartComponent = ({
32203
32318
  fillContainer = false,
32204
32319
  ...restOfChartProps
32205
32320
  }) => {
32206
- const containerRef = React141__default.useRef(null);
32207
- const [dimensions, setDimensions] = React141__default.useState({ width: 0, height: 0 });
32208
- const [hasValidData, setHasValidData] = React141__default.useState(false);
32209
- React141__default.useEffect(() => {
32321
+ const containerRef = React142__default.useRef(null);
32322
+ const [dimensions, setDimensions] = React142__default.useState({ width: 0, height: 0 });
32323
+ const [hasValidData, setHasValidData] = React142__default.useState(false);
32324
+ React142__default.useEffect(() => {
32210
32325
  const currentHasValidData = data && lines && lines.length > 0 && data.some(
32211
32326
  (item) => lines.some((line) => {
32212
32327
  const val = item[line.dataKey];
@@ -32217,7 +32332,7 @@ var LineChartComponent = ({
32217
32332
  setHasValidData(true);
32218
32333
  }
32219
32334
  }, [data, lines, hasValidData]);
32220
- React141__default.useEffect(() => {
32335
+ React142__default.useEffect(() => {
32221
32336
  if (!containerRef.current) return;
32222
32337
  const observer = new ResizeObserver((entries) => {
32223
32338
  const entry = entries[0];
@@ -32342,7 +32457,7 @@ var LineChartComponent = ({
32342
32457
  }
32343
32458
  return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: renderChartContent(restOfChartProps.width, restOfChartProps.height) });
32344
32459
  };
32345
- var LineChart = React141__default.memo(LineChartComponent, (prevProps, nextProps) => {
32460
+ var LineChart = React142__default.memo(LineChartComponent, (prevProps, nextProps) => {
32346
32461
  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)) {
32347
32462
  return false;
32348
32463
  }
@@ -32436,7 +32551,7 @@ var OutputProgressChartComponent = ({
32436
32551
  ] }) })
32437
32552
  ] }) });
32438
32553
  };
32439
- var OutputProgressChart = React141__default.memo(OutputProgressChartComponent);
32554
+ var OutputProgressChart = React142__default.memo(OutputProgressChartComponent);
32440
32555
  OutputProgressChart.displayName = "OutputProgressChart";
32441
32556
  var LargeOutputProgressChart = ({
32442
32557
  currentOutput,
@@ -32576,7 +32691,7 @@ var CycleTimeChartComponent = ({
32576
32691
  }
32577
32692
  ) }) });
32578
32693
  };
32579
- var CycleTimeChart = React141__default.memo(CycleTimeChartComponent, (prevProps, nextProps) => {
32694
+ var CycleTimeChart = React142__default.memo(CycleTimeChartComponent, (prevProps, nextProps) => {
32580
32695
  if (prevProps.className !== nextProps.className) {
32581
32696
  return false;
32582
32697
  }
@@ -32595,6 +32710,212 @@ var CycleTimeChart = React141__default.memo(CycleTimeChartComponent, (prevProps,
32595
32710
  });
32596
32711
  });
32597
32712
  CycleTimeChart.displayName = "CycleTimeChart";
32713
+
32714
+ // src/lib/utils/hourlyIdle.ts
32715
+ var DEFAULT_SHIFT_DURATION = 11;
32716
+ var normalizeMinuteSeries = (idleTimeHourly) => {
32717
+ if (!idleTimeHourly || typeof idleTimeHourly !== "object") {
32718
+ return {};
32719
+ }
32720
+ return Object.fromEntries(
32721
+ Object.entries(idleTimeHourly).map(([key, value]) => {
32722
+ if (Array.isArray(value)) {
32723
+ return [key, value];
32724
+ }
32725
+ if (value && Array.isArray(value.values)) {
32726
+ return [key, value.values];
32727
+ }
32728
+ return [key, []];
32729
+ })
32730
+ );
32731
+ };
32732
+ var parseTimeString = (timeValue) => {
32733
+ const [hoursPart, minutesPart] = timeValue.split(":");
32734
+ const hour = Number.parseInt(hoursPart, 10);
32735
+ const minute = Number.parseInt(minutesPart ?? "0", 10);
32736
+ const safeHour = Number.isFinite(hour) ? hour : 0;
32737
+ const safeMinute = Number.isFinite(minute) ? minute : 0;
32738
+ return {
32739
+ hour: safeHour,
32740
+ minute: safeMinute,
32741
+ decimalHour: safeHour + safeMinute / 60
32742
+ };
32743
+ };
32744
+ var buildShiftLayout = ({
32745
+ shiftStart,
32746
+ shiftEnd
32747
+ }) => {
32748
+ const shiftStartTime = parseTimeString(shiftStart);
32749
+ if (!shiftEnd) {
32750
+ return {
32751
+ shiftDuration: DEFAULT_SHIFT_DURATION,
32752
+ shiftStartTime,
32753
+ shiftEndTime: null,
32754
+ hasPartialLastHour: false
32755
+ };
32756
+ }
32757
+ const shiftEndTime = parseTimeString(shiftEnd);
32758
+ let duration = shiftEndTime.decimalHour - shiftStartTime.decimalHour;
32759
+ if (duration <= 0) {
32760
+ duration += 24;
32761
+ }
32762
+ const hasPartialLastHour = shiftEndTime.minute > 0 && shiftEndTime.minute < 60;
32763
+ const shiftDuration = hasPartialLastHour ? Math.ceil(duration) : Math.round(duration);
32764
+ return {
32765
+ shiftDuration,
32766
+ shiftStartTime,
32767
+ shiftEndTime,
32768
+ hasPartialLastHour
32769
+ };
32770
+ };
32771
+ var formatCompactTime = (hour, minute) => {
32772
+ const period = hour >= 12 ? "PM" : "AM";
32773
+ const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
32774
+ if (minute === 0) {
32775
+ return `${hour12}${period}`;
32776
+ }
32777
+ return `${hour12}:${minute.toString().padStart(2, "0")}${period}`;
32778
+ };
32779
+ var formatFullTime = (hour, minute) => {
32780
+ const period = hour >= 12 ? "PM" : "AM";
32781
+ const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
32782
+ return `${hour12}:${minute.toString().padStart(2, "0")} ${period}`;
32783
+ };
32784
+ var getSlotTimeBounds = (hourIndex, layout2) => {
32785
+ const isLastHour = hourIndex === layout2.shiftDuration - 1;
32786
+ const startDecimalHour = layout2.shiftStartTime.decimalHour + hourIndex;
32787
+ const startHour = Math.floor(startDecimalHour) % 24;
32788
+ const startMinute = Math.round(startDecimalHour % 1 * 60);
32789
+ let endHour;
32790
+ let endMinute;
32791
+ if (isLastHour && layout2.shiftEndTime) {
32792
+ endHour = layout2.shiftEndTime.hour;
32793
+ endMinute = layout2.shiftEndTime.minute;
32794
+ } else {
32795
+ const endDecimalHour = startDecimalHour + 1;
32796
+ endHour = Math.floor(endDecimalHour) % 24;
32797
+ endMinute = Math.round(endDecimalHour % 1 * 60);
32798
+ }
32799
+ return {
32800
+ startHour,
32801
+ startMinute,
32802
+ endHour,
32803
+ endMinute
32804
+ };
32805
+ };
32806
+ var getIdleArrayForHour = (hourIndex, idleTimeHourly, layout2) => {
32807
+ const actualHour = (layout2.shiftStartTime.hour + hourIndex) % 24;
32808
+ const startMinute = layout2.shiftStartTime.minute;
32809
+ if (startMinute > 0) {
32810
+ if (hourIndex === 0) {
32811
+ const firstHourData = idleTimeHourly[actualHour.toString()] || [];
32812
+ const nextHourData2 = idleTimeHourly[((actualHour + 1) % 24).toString()] || [];
32813
+ return [
32814
+ ...firstHourData.slice(startMinute),
32815
+ ...nextHourData2.slice(0, startMinute)
32816
+ ];
32817
+ }
32818
+ if (hourIndex < layout2.shiftDuration - 1) {
32819
+ const currentHourData3 = idleTimeHourly[actualHour.toString()] || [];
32820
+ const nextHourData2 = idleTimeHourly[((actualHour + 1) % 24).toString()] || [];
32821
+ return [
32822
+ ...currentHourData3.slice(startMinute),
32823
+ ...nextHourData2.slice(0, startMinute)
32824
+ ];
32825
+ }
32826
+ if (layout2.hasPartialLastHour && layout2.shiftEndTime) {
32827
+ const currentHourData3 = idleTimeHourly[actualHour.toString()] || [];
32828
+ const nextHourData2 = idleTimeHourly[((actualHour + 1) % 24).toString()] || [];
32829
+ return [
32830
+ ...currentHourData3.slice(startMinute),
32831
+ ...nextHourData2.slice(0, layout2.shiftEndTime.minute)
32832
+ ];
32833
+ }
32834
+ const currentHourData2 = idleTimeHourly[actualHour.toString()] || [];
32835
+ const nextHourData = idleTimeHourly[((actualHour + 1) % 24).toString()] || [];
32836
+ return [
32837
+ ...currentHourData2.slice(startMinute),
32838
+ ...nextHourData.slice(0, startMinute)
32839
+ ];
32840
+ }
32841
+ const currentHourData = idleTimeHourly[actualHour.toString()] || [];
32842
+ if (hourIndex === layout2.shiftDuration - 1 && layout2.hasPartialLastHour && layout2.shiftEndTime) {
32843
+ return currentHourData.slice(0, layout2.shiftEndTime.minute);
32844
+ }
32845
+ return currentHourData;
32846
+ };
32847
+ var buildHourlyIdleSlots = ({
32848
+ idleTimeHourly,
32849
+ shiftStart,
32850
+ shiftEnd
32851
+ }) => {
32852
+ const normalizedIdleTimeHourly = normalizeMinuteSeries(idleTimeHourly);
32853
+ const layout2 = buildShiftLayout({ shiftStart, shiftEnd });
32854
+ return Array.from({ length: layout2.shiftDuration }, (_, hourIndex) => {
32855
+ const { startHour, startMinute, endHour, endMinute } = getSlotTimeBounds(hourIndex, layout2);
32856
+ const idleArray = getIdleArrayForHour(hourIndex, normalizedIdleTimeHourly, layout2);
32857
+ const idleMinutes = idleArray.filter((value) => value === 1 || value === "1").length;
32858
+ return {
32859
+ hourIndex,
32860
+ hour: `${formatCompactTime(startHour, startMinute)}-${formatCompactTime(endHour, endMinute)}`,
32861
+ timeRange: `${formatFullTime(startHour, startMinute)} - ${formatFullTime(endHour, endMinute)}`,
32862
+ idleMinutes,
32863
+ idleArray
32864
+ };
32865
+ });
32866
+ };
32867
+ var formatIdleTimestamp = ({
32868
+ shiftStart,
32869
+ hourIndex,
32870
+ minuteIndex
32871
+ }) => {
32872
+ const shiftStartTime = parseTimeString(shiftStart);
32873
+ const totalMinutes = (shiftStartTime.hour + hourIndex) * 60 + shiftStartTime.minute + minuteIndex;
32874
+ const hour = Math.floor(totalMinutes / 60) % 24;
32875
+ const minute = totalMinutes % 60;
32876
+ return formatFullTime(hour, minute);
32877
+ };
32878
+ var getHourlyIdlePeriods = ({
32879
+ idleArray,
32880
+ shiftStart,
32881
+ hourIndex
32882
+ }) => {
32883
+ if (!Array.isArray(idleArray) || idleArray.length === 0) {
32884
+ return [];
32885
+ }
32886
+ const periods = [];
32887
+ let currentRange = null;
32888
+ idleArray.forEach((value, minuteIndex) => {
32889
+ if (value === 1 || value === "1") {
32890
+ if (!currentRange) {
32891
+ currentRange = { start: minuteIndex, end: minuteIndex };
32892
+ } else {
32893
+ currentRange.end = minuteIndex;
32894
+ }
32895
+ } else if (value !== "x" && currentRange) {
32896
+ periods.push(currentRange);
32897
+ currentRange = null;
32898
+ }
32899
+ });
32900
+ if (currentRange) {
32901
+ periods.push(currentRange);
32902
+ }
32903
+ return periods.map((period) => ({
32904
+ start: period.start,
32905
+ end: period.end,
32906
+ duration: period.end - period.start + 1,
32907
+ startTime: formatIdleTimestamp({
32908
+ shiftStart,
32909
+ hourIndex,
32910
+ minuteIndex: period.start
32911
+ }),
32912
+ endTime: formatIdleTimestamp({
32913
+ shiftStart,
32914
+ hourIndex,
32915
+ minuteIndex: period.end + 1
32916
+ })
32917
+ }));
32918
+ };
32598
32919
  var CycleTimeOverTimeChart = ({
32599
32920
  data,
32600
32921
  idealCycleTime,
@@ -32604,19 +32925,20 @@ var CycleTimeOverTimeChart = ({
32604
32925
  datasetKey,
32605
32926
  className = "",
32606
32927
  showIdleTime = false,
32607
- idleTimeData = []
32928
+ idleTimeData = [],
32929
+ idleTimeSlots = []
32608
32930
  }) => {
32609
32931
  const MAX_DATA_POINTS = 40;
32610
- const containerRef = React141__default.useRef(null);
32611
- const [dimensions, setDimensions] = React141__default.useState({ width: 0, height: 0 });
32612
- const [hasValidData, setHasValidData] = React141__default.useState(false);
32613
- React141__default.useEffect(() => {
32932
+ const containerRef = React142__default.useRef(null);
32933
+ const [dimensions, setDimensions] = React142__default.useState({ width: 0, height: 0 });
32934
+ const [hasValidData, setHasValidData] = React142__default.useState(false);
32935
+ React142__default.useEffect(() => {
32614
32936
  const currentHasValidData = data && data.some((val) => val !== null && val > 0);
32615
32937
  if (currentHasValidData && !hasValidData) {
32616
32938
  setHasValidData(true);
32617
32939
  }
32618
32940
  }, [data, hasValidData]);
32619
- React141__default.useEffect(() => {
32941
+ React142__default.useEffect(() => {
32620
32942
  if (!containerRef.current) return;
32621
32943
  const observer = new ResizeObserver((entries) => {
32622
32944
  const entry = entries[0];
@@ -32648,7 +32970,7 @@ var CycleTimeOverTimeChart = ({
32648
32970
  const endLabel = shiftEnd && slotIndex === DURATION - 1 ? formatHourLabel(slotIndex + 1) : formatHourLabel(slotIndex + 1);
32649
32971
  return `${startLabel} - ${endLabel}`;
32650
32972
  };
32651
- const getDisplayData = React141__default.useCallback((rawData) => {
32973
+ const getDisplayData = React142__default.useCallback((rawData) => {
32652
32974
  if (xAxisMode === "hourly") return rawData;
32653
32975
  return rawData.slice(Math.max(0, rawData.length - MAX_DATA_POINTS));
32654
32976
  }, [xAxisMode]);
@@ -32656,7 +32978,7 @@ var CycleTimeOverTimeChart = ({
32656
32978
  const DURATION = displayData.length;
32657
32979
  const effectiveDatasetKey = datasetKey || `cycle-time:${xAxisMode}`;
32658
32980
  const finalData = displayData;
32659
- const labelInterval = React141__default.useMemo(() => {
32981
+ const labelInterval = React142__default.useMemo(() => {
32660
32982
  if (xAxisMode === "hourly") {
32661
32983
  return Math.max(1, Math.ceil(DURATION / 8));
32662
32984
  }
@@ -32697,8 +33019,8 @@ var CycleTimeOverTimeChart = ({
32697
33019
  return `${minutes} minutes ${seconds} seconds ago`;
32698
33020
  }
32699
33021
  };
32700
- const getNumericValue = React141__default.useCallback((value) => typeof value === "number" && Number.isFinite(value) ? value : null, []);
32701
- const renderChartTooltip = React141__default.useCallback((tooltipProps) => {
33022
+ const getNumericValue = React142__default.useCallback((value) => typeof value === "number" && Number.isFinite(value) ? value : null, []);
33023
+ const renderChartTooltip = React142__default.useCallback((tooltipProps) => {
32702
33024
  const { active, payload } = tooltipProps;
32703
33025
  if (!active || !Array.isArray(payload) || payload.length === 0) {
32704
33026
  return null;
@@ -32707,51 +33029,61 @@ var CycleTimeOverTimeChart = ({
32707
33029
  if (!visibleEntries.length) {
32708
33030
  return null;
32709
33031
  }
32710
- return /* @__PURE__ */ jsxs(
32711
- "div",
32712
- {
32713
- style: {
32714
- backgroundColor: "white",
32715
- border: "none",
32716
- borderRadius: "8px",
32717
- boxShadow: "0 4px 12px rgba(0,0,0,0.1)",
32718
- padding: "8px 12px",
32719
- fontSize: "13px"
32720
- },
32721
- children: [
32722
- /* @__PURE__ */ jsx(
32723
- "div",
32724
- {
32725
- style: {
32726
- color: "#374151",
32727
- fontWeight: 600,
32728
- marginBottom: "4px"
32729
- },
32730
- children: payload[0]?.payload?.tooltip || ""
32731
- }
32732
- ),
32733
- visibleEntries.map((entry) => {
32734
- const numericValue = getNumericValue(entry.value);
32735
- if (numericValue === null) {
32736
- return null;
32737
- }
32738
- return /* @__PURE__ */ jsx(
32739
- "div",
32740
- {
32741
- style: {
32742
- color: "#4B5563",
32743
- padding: "2px 0"
32744
- },
32745
- children: entry.name === "idleMinutes" ? `Idle Time: ${numericValue.toFixed(0)} minutes` : `Cycle Time: ${numericValue.toFixed(1)} seconds`
32746
- },
32747
- `${entry.name}-${numericValue}`
32748
- );
32749
- })
32750
- ]
32751
- }
32752
- );
32753
- }, [getNumericValue]);
32754
- const renderCycleDot = React141__default.useCallback((props) => {
33032
+ const dataPoint = payload[0]?.payload || {};
33033
+ const idlePeriods = showIdleTime && typeof dataPoint.idleMinutes === "number" && dataPoint.idleMinutes > 0 ? getHourlyIdlePeriods({
33034
+ idleArray: dataPoint.idleArray,
33035
+ shiftStart,
33036
+ hourIndex: Number.isFinite(dataPoint.hourIndex) ? dataPoint.hourIndex : 0
33037
+ }) : [];
33038
+ return /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl shadow-xl border border-gray-100 p-4 min-w-[220px]", children: [
33039
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-3", children: /* @__PURE__ */ jsx("p", { className: "font-semibold text-gray-900 text-sm", children: dataPoint.timeRange || dataPoint.tooltip || "" }) }),
33040
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
33041
+ visibleEntries.map((entry) => {
33042
+ const numericValue = getNumericValue(entry.value);
33043
+ if (numericValue === null) {
33044
+ return null;
33045
+ }
33046
+ if (entry.name === "idleMinutes") {
33047
+ if (!showIdleTime) return null;
33048
+ return /* @__PURE__ */ jsx("div", { className: "border-t border-gray-100 pt-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
33049
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-500", children: "Idle Time" }),
33050
+ /* @__PURE__ */ jsxs("span", { className: "font-semibold text-orange-600 text-sm", children: [
33051
+ numericValue.toFixed(0),
33052
+ " minutes"
33053
+ ] })
33054
+ ] }) }, `${entry.name}-${numericValue}`);
33055
+ }
33056
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
33057
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-500", children: "Cycle Time" }),
33058
+ /* @__PURE__ */ jsxs("span", { className: "font-semibold text-gray-900 text-sm", children: [
33059
+ numericValue.toFixed(1),
33060
+ " seconds"
33061
+ ] })
33062
+ ] }, `${entry.name}-${numericValue}`);
33063
+ }),
33064
+ idlePeriods.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-3 bg-gray-50 rounded-lg p-2.5", children: [
33065
+ /* @__PURE__ */ jsx("p", { className: "font-medium text-gray-700 text-xs mb-2", children: "Idle periods:" }),
33066
+ /* @__PURE__ */ jsx("div", { className: "space-y-1 max-h-32 overflow-y-auto pr-1", children: idlePeriods.map((period, index) => /* @__PURE__ */ jsxs("div", { className: "text-gray-600 flex items-center gap-2 text-xs", children: [
33067
+ /* @__PURE__ */ jsx("span", { className: "inline-block w-1.5 h-1.5 bg-orange-400 rounded-full flex-shrink-0" }),
33068
+ /* @__PURE__ */ jsx("span", { children: period.duration === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
33069
+ period.startTime,
33070
+ " (",
33071
+ period.duration,
33072
+ " min)"
33073
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
33074
+ period.startTime,
33075
+ " - ",
33076
+ period.endTime,
33077
+ " (",
33078
+ period.duration,
33079
+ " mins)"
33080
+ ] }) })
33081
+ ] }, index)) })
33082
+ ] })
33083
+ ] })
33084
+ ] });
33085
+ }, [getNumericValue, shiftStart, showIdleTime]);
33086
+ const renderCycleDot = React142__default.useCallback((props) => {
32755
33087
  const { cx: cx2, cy, payload } = props;
32756
33088
  const cycleTime = getNumericValue(payload?.cycleTime);
32757
33089
  if (cycleTime === null) {
@@ -32784,7 +33116,7 @@ var CycleTimeOverTimeChart = ({
32784
33116
  }
32785
33117
  );
32786
33118
  }, [getNumericValue, idealCycleTime]);
32787
- const renderCycleActiveDot = React141__default.useCallback((props) => {
33119
+ const renderCycleActiveDot = React142__default.useCallback((props) => {
32788
33120
  const { cx: cx2, cy, payload } = props;
32789
33121
  const cycleTime = getNumericValue(payload?.cycleTime);
32790
33122
  if (cycleTime === null) {
@@ -32805,7 +33137,7 @@ var CycleTimeOverTimeChart = ({
32805
33137
  }
32806
33138
  );
32807
33139
  }, [getNumericValue, idealCycleTime]);
32808
- const renderIdleDot = React141__default.useCallback((props) => {
33140
+ const renderIdleDot = React142__default.useCallback((props) => {
32809
33141
  const { cx: cx2, cy, payload } = props;
32810
33142
  const idleMinutes = getNumericValue(payload?.idleMinutes);
32811
33143
  if (idleMinutes === null) {
@@ -32819,14 +33151,18 @@ var CycleTimeOverTimeChart = ({
32819
33151
  r: 4,
32820
33152
  fill: "#f59e0b",
32821
33153
  stroke: "#fff",
32822
- strokeWidth: 1
33154
+ strokeWidth: 1,
33155
+ style: {
33156
+ opacity: showIdleTime ? 1 : 0,
33157
+ transition: "opacity 0.3s ease-in-out"
33158
+ }
32823
33159
  }
32824
33160
  );
32825
- }, [getNumericValue]);
32826
- const renderIdleActiveDot = React141__default.useCallback((props) => {
33161
+ }, [getNumericValue, showIdleTime]);
33162
+ const renderIdleActiveDot = React142__default.useCallback((props) => {
32827
33163
  const { cx: cx2, cy, payload } = props;
32828
33164
  const idleMinutes = getNumericValue(payload?.idleMinutes);
32829
- if (idleMinutes === null) {
33165
+ if (idleMinutes === null || !showIdleTime) {
32830
33166
  return /* @__PURE__ */ jsx("g", {});
32831
33167
  }
32832
33168
  return /* @__PURE__ */ jsx(
@@ -32840,25 +33176,40 @@ var CycleTimeOverTimeChart = ({
32840
33176
  strokeWidth: 2
32841
33177
  }
32842
33178
  );
32843
- }, [getNumericValue]);
32844
- const chartData = React141__default.useMemo(() => Array.from({ length: DURATION }, (_, i) => {
33179
+ }, [getNumericValue, showIdleTime]);
33180
+ const chartData = React142__default.useMemo(() => Array.from({ length: DURATION }, (_, i) => {
32845
33181
  const cycleTime = getNumericValue(finalData[i]);
32846
- const idleMinutes = showIdleTime ? getNumericValue(idleTimeData[i]) : null;
33182
+ const useIdleSlots = idleTimeSlots.length > 0;
33183
+ const idleSlot = useIdleSlots ? idleTimeSlots[i] ?? null : null;
33184
+ const idleMinutes = useIdleSlots ? idleSlot?.idleMinutes ?? null : getNumericValue(idleTimeData[i]);
32847
33185
  return {
32848
33186
  timeIndex: i,
32849
33187
  label: formatTimeLabel(i),
32850
- tooltip: formatTooltipTime(i),
33188
+ tooltip: idleSlot?.timeRange || formatTooltipTime(i),
33189
+ timeRange: idleSlot?.timeRange || formatTooltipTime(i),
33190
+ hourIndex: idleSlot?.hourIndex ?? i,
32851
33191
  cycleTime,
32852
33192
  idleMinutes,
33193
+ idleArray: idleSlot?.idleArray || [],
32853
33194
  color: cycleTime !== null && cycleTime <= idealCycleTime ? "#00AB45" : "#E34329"
32854
33195
  };
32855
- }), [DURATION, finalData, showIdleTime, idleTimeData, idealCycleTime, getNumericValue]);
33196
+ }), [DURATION, finalData, idleTimeData, idleTimeSlots, idealCycleTime, getNumericValue]);
32856
33197
  const renderLegend = () => {
32857
- if (!showIdleTime) return null;
32858
- return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-start text-[10px] font-bold text-gray-500 mb-6 tracking-[0.05em] gap-5", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
32859
- /* @__PURE__ */ jsx("div", { className: "w-2.5 h-2.5 rounded-full bg-[#f59e0b]" }),
32860
- /* @__PURE__ */ jsx("span", { children: "Idle Time (min)" })
32861
- ] }) });
33198
+ return /* @__PURE__ */ jsx(
33199
+ "div",
33200
+ {
33201
+ className: "flex items-center justify-start text-[10px] font-bold text-gray-500 mb-6 tracking-[0.05em] gap-5",
33202
+ style: {
33203
+ opacity: showIdleTime ? 1 : 0,
33204
+ pointerEvents: showIdleTime ? "auto" : "none",
33205
+ transition: "opacity 0.3s ease-in-out"
33206
+ },
33207
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
33208
+ /* @__PURE__ */ jsx("div", { className: "w-2.5 h-2.5 rounded-full bg-[#f59e0b]" }),
33209
+ /* @__PURE__ */ jsx("span", { children: "Idle Time (min)" })
33210
+ ] })
33211
+ }
33212
+ );
32862
33213
  };
32863
33214
  return /* @__PURE__ */ jsxs(
32864
33215
  "div",
@@ -32929,7 +33280,7 @@ var CycleTimeOverTimeChart = ({
32929
33280
  }
32930
33281
  }
32931
33282
  ),
32932
- showIdleTime && /* @__PURE__ */ jsx(
33283
+ /* @__PURE__ */ jsx(
32933
33284
  YAxis,
32934
33285
  {
32935
33286
  yAxisId: "idle",
@@ -32938,7 +33289,11 @@ var CycleTimeOverTimeChart = ({
32938
33289
  width: 35,
32939
33290
  domain: [0, 60],
32940
33291
  tickFormatter: (value) => `${value}m`,
32941
- tick: { fontSize: 11, fill: "#f59e0b" },
33292
+ tick: {
33293
+ fontSize: 11,
33294
+ fill: showIdleTime ? "#f59e0b" : "transparent",
33295
+ style: { transition: "fill 0.3s ease-in-out" }
33296
+ },
32942
33297
  axisLine: false,
32943
33298
  tickLine: false
32944
33299
  }
@@ -32986,7 +33341,7 @@ var CycleTimeOverTimeChart = ({
32986
33341
  },
32987
33342
  `${effectiveDatasetKey}:cycle`
32988
33343
  ),
32989
- showIdleTime && /* @__PURE__ */ jsx(
33344
+ /* @__PURE__ */ jsx(
32990
33345
  Line,
32991
33346
  {
32992
33347
  type: "monotone",
@@ -33001,7 +33356,11 @@ var CycleTimeOverTimeChart = ({
33001
33356
  isAnimationActive: true,
33002
33357
  animationBegin: 300,
33003
33358
  animationDuration: 1500,
33004
- animationEasing: "ease-out"
33359
+ animationEasing: "ease-out",
33360
+ style: {
33361
+ strokeOpacity: showIdleTime ? 1 : 0,
33362
+ transition: "stroke-opacity 0.3s ease-in-out"
33363
+ }
33005
33364
  },
33006
33365
  `${effectiveDatasetKey}:idle`
33007
33366
  )
@@ -33015,7 +33374,7 @@ var CycleTimeOverTimeChart = ({
33015
33374
  }
33016
33375
  );
33017
33376
  };
33018
- var Card = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33377
+ var Card = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33019
33378
  "div",
33020
33379
  {
33021
33380
  ref,
@@ -33027,7 +33386,7 @@ var Card = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
33027
33386
  }
33028
33387
  ));
33029
33388
  Card.displayName = "Card";
33030
- var CardHeader = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33389
+ var CardHeader = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33031
33390
  "div",
33032
33391
  {
33033
33392
  ref,
@@ -33036,7 +33395,7 @@ var CardHeader = React141.forwardRef(({ className, ...props }, ref) => /* @__PUR
33036
33395
  }
33037
33396
  ));
33038
33397
  CardHeader.displayName = "CardHeader";
33039
- var CardTitle = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33398
+ var CardTitle = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33040
33399
  "h3",
33041
33400
  {
33042
33401
  ref,
@@ -33048,7 +33407,7 @@ var CardTitle = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE
33048
33407
  }
33049
33408
  ));
33050
33409
  CardTitle.displayName = "CardTitle";
33051
- var CardDescription = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33410
+ var CardDescription = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33052
33411
  "p",
33053
33412
  {
33054
33413
  ref,
@@ -33057,9 +33416,9 @@ var CardDescription = React141.forwardRef(({ className, ...props }, ref) => /* @
33057
33416
  }
33058
33417
  ));
33059
33418
  CardDescription.displayName = "CardDescription";
33060
- var CardContent = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
33419
+ var CardContent = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
33061
33420
  CardContent.displayName = "CardContent";
33062
- var CardFooter = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33421
+ var CardFooter = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33063
33422
  "div",
33064
33423
  {
33065
33424
  ref,
@@ -33135,7 +33494,7 @@ var buttonVariants = cva(
33135
33494
  }
33136
33495
  }
33137
33496
  );
33138
- var Button = React141.forwardRef(
33497
+ var Button = React142.forwardRef(
33139
33498
  ({ className, variant, size, asChild = false, ...props }, ref) => {
33140
33499
  const Comp = asChild ? Slot : "button";
33141
33500
  return /* @__PURE__ */ jsx(
@@ -33156,95 +33515,26 @@ var HourlyOutputChartComponent = ({
33156
33515
  shiftEnd,
33157
33516
  showIdleTime = false,
33158
33517
  idleTimeHourly,
33159
- idleTimeClips,
33160
- idleTimeClipClassifications,
33161
- shiftDate,
33162
- timezone,
33163
33518
  className = ""
33164
33519
  }) => {
33165
- const containerRef = React141__default.useRef(null);
33166
- const [containerReady, setContainerReady] = React141__default.useState(false);
33167
- const [containerWidth, setContainerWidth] = React141__default.useState(0);
33168
- const getTimeFromTimeString2 = (timeStr) => {
33169
- const [hours, minutes] = timeStr.split(":");
33170
- const hour = parseInt(hours);
33171
- const minute = parseInt(minutes || "0");
33172
- const decimalHour = hour + minute / 60;
33173
- return { hour, minute, decimalHour };
33174
- };
33175
- const shiftStartTime = getTimeFromTimeString2(shiftStart);
33176
- React141__default.useMemo(() => {
33177
- if (!shiftDate || !timezone) return null;
33178
- const hour = shiftStartTime.hour.toString().padStart(2, "0");
33179
- const minute = shiftStartTime.minute.toString().padStart(2, "0");
33180
- return fromZonedTime(`${shiftDate}T${hour}:${minute}:00`, timezone);
33181
- }, [shiftDate, timezone, shiftStartTime.hour, shiftStartTime.minute]);
33182
- const idleClipRanges = React141__default.useMemo(() => {
33183
- if (!idleTimeClips || idleTimeClips.length === 0) return [];
33184
- return idleTimeClips.map((clip) => ({
33185
- id: clip.id,
33186
- start: clip.idle_start_time ? new Date(clip.idle_start_time) : null,
33187
- end: clip.idle_end_time ? new Date(clip.idle_end_time) : null
33188
- })).filter((clip) => clip.start && clip.end);
33189
- }, [idleTimeClips]);
33190
- React141__default.useCallback((rangeStart, rangeEnd) => {
33191
- if (!rangeStart || !rangeEnd || idleClipRanges.length === 0) {
33192
- return "Reason unavailable";
33193
- }
33194
- const matchingClip = idleClipRanges.find((clip) => rangeStart >= clip.start && rangeEnd <= clip.end) || idleClipRanges.find((clip) => rangeStart < clip.end && rangeEnd > clip.start);
33195
- if (!matchingClip) {
33196
- return "Reason unavailable";
33197
- }
33198
- const classification = idleTimeClipClassifications?.[matchingClip.id];
33199
- if (!classification || classification.status === "processing") {
33200
- return "Analyzing...";
33201
- }
33202
- if (!classification.label) {
33203
- return "Reason unavailable";
33204
- }
33205
- return classification.displayName || classification.label.replace(/_/g, " ");
33206
- }, [idleClipRanges, idleTimeClipClassifications]);
33207
- const { shiftDuration, shiftEndTime, hasPartialLastHour } = React141__default.useMemo(() => {
33208
- console.log("[HourlyOutputChart] Calculating shift duration with:", {
33520
+ const containerRef = React142__default.useRef(null);
33521
+ const [containerReady, setContainerReady] = React142__default.useState(false);
33522
+ const [containerWidth, setContainerWidth] = React142__default.useState(0);
33523
+ const idleSlots = React142__default.useMemo(
33524
+ () => buildHourlyIdleSlots({
33525
+ idleTimeHourly,
33209
33526
  shiftStart,
33210
- shiftEnd,
33211
- shiftStartTime
33212
- });
33213
- if (!shiftEnd) {
33214
- console.log("[HourlyOutputChart] No shiftEnd provided, using default 11 hours");
33215
- return {
33216
- shiftDuration: 11,
33217
- shiftEndTime: null,
33218
- hasPartialLastHour: false
33219
- };
33220
- }
33221
- const endTime = getTimeFromTimeString2(shiftEnd);
33222
- let duration = endTime.decimalHour - shiftStartTime.decimalHour;
33223
- if (duration <= 0) {
33224
- duration += 24;
33225
- }
33226
- const hasPartial = endTime.minute > 0 && endTime.minute < 60;
33227
- const hourCount = hasPartial ? Math.ceil(duration) : Math.round(duration);
33228
- console.log("[HourlyOutputChart] Shift calculation results:", {
33229
- endTime,
33230
- duration,
33231
- hasPartial,
33232
- hourCount
33233
- });
33234
- return {
33235
- shiftDuration: hourCount,
33236
- shiftEndTime: endTime,
33237
- hasPartialLastHour: hasPartial
33238
- };
33239
- }, [shiftEnd, shiftStartTime.decimalHour]);
33240
- const SHIFT_DURATION = shiftDuration;
33241
- shiftEndTime ? shiftEndTime.hour : (shiftStartTime.hour + SHIFT_DURATION) % 24;
33242
- const [animatedData, setAnimatedData] = React141__default.useState(
33527
+ shiftEnd
33528
+ }),
33529
+ [idleTimeHourly, shiftStart, shiftEnd]
33530
+ );
33531
+ const SHIFT_DURATION = idleSlots.length;
33532
+ const [animatedData, setAnimatedData] = React142__default.useState(
33243
33533
  () => Array(SHIFT_DURATION).fill(0)
33244
33534
  );
33245
- const prevDataRef = React141__default.useRef(Array(SHIFT_DURATION).fill(0));
33246
- const animationFrameRef = React141__default.useRef(null);
33247
- React141__default.useEffect(() => {
33535
+ const prevDataRef = React142__default.useRef(Array(SHIFT_DURATION).fill(0));
33536
+ const animationFrameRef = React142__default.useRef(null);
33537
+ React142__default.useEffect(() => {
33248
33538
  setAnimatedData((prev) => {
33249
33539
  if (prev.length !== SHIFT_DURATION) {
33250
33540
  return Array(SHIFT_DURATION).fill(0);
@@ -33253,14 +33543,14 @@ var HourlyOutputChartComponent = ({
33253
33543
  });
33254
33544
  prevDataRef.current = Array(SHIFT_DURATION).fill(0);
33255
33545
  }, [SHIFT_DURATION]);
33256
- const [idleBarState, setIdleBarState] = React141__default.useState({
33546
+ const [idleBarState, setIdleBarState] = React142__default.useState({
33257
33547
  visible: showIdleTime,
33258
33548
  key: 0,
33259
33549
  shouldAnimate: false
33260
33550
  });
33261
- const prevShowIdleTimeRef = React141__default.useRef(showIdleTime);
33262
- const stateUpdateTimeoutRef = React141__default.useRef(null);
33263
- React141__default.useEffect(() => {
33551
+ const prevShowIdleTimeRef = React142__default.useRef(showIdleTime);
33552
+ const stateUpdateTimeoutRef = React142__default.useRef(null);
33553
+ React142__default.useEffect(() => {
33264
33554
  if (stateUpdateTimeoutRef.current) {
33265
33555
  clearTimeout(stateUpdateTimeoutRef.current);
33266
33556
  }
@@ -33285,7 +33575,7 @@ var HourlyOutputChartComponent = ({
33285
33575
  }
33286
33576
  };
33287
33577
  }, [showIdleTime]);
33288
- const animateToNewData = React141__default.useCallback((targetData) => {
33578
+ const animateToNewData = React142__default.useCallback((targetData) => {
33289
33579
  const startData = [...prevDataRef.current];
33290
33580
  const startTime = performance.now();
33291
33581
  const duration = 1200;
@@ -33315,7 +33605,7 @@ var HourlyOutputChartComponent = ({
33315
33605
  }
33316
33606
  animationFrameRef.current = requestAnimationFrame(animate);
33317
33607
  }, []);
33318
- React141__default.useEffect(() => {
33608
+ React142__default.useEffect(() => {
33319
33609
  if (JSON.stringify(data) !== JSON.stringify(prevDataRef.current)) {
33320
33610
  const shiftData = data.slice(0, SHIFT_DURATION);
33321
33611
  animateToNewData(shiftData);
@@ -33326,7 +33616,7 @@ var HourlyOutputChartComponent = ({
33326
33616
  }
33327
33617
  };
33328
33618
  }, [data, animateToNewData]);
33329
- React141__default.useEffect(() => {
33619
+ React142__default.useEffect(() => {
33330
33620
  const checkContainerDimensions = () => {
33331
33621
  if (containerRef.current) {
33332
33622
  const rect = containerRef.current.getBoundingClientRect();
@@ -33352,7 +33642,7 @@ var HourlyOutputChartComponent = ({
33352
33642
  clearTimeout(fallbackTimeout);
33353
33643
  };
33354
33644
  }, []);
33355
- const xAxisConfig = React141__default.useMemo(() => {
33645
+ const xAxisConfig = React142__default.useMemo(() => {
33356
33646
  if (containerWidth >= 960) {
33357
33647
  return { interval: 0, angle: -45, height: 92, tickFont: 10, tickMargin: 12 };
33358
33648
  }
@@ -33361,122 +33651,23 @@ var HourlyOutputChartComponent = ({
33361
33651
  }
33362
33652
  return { interval: 0, angle: -30, height: 64, tickFont: 9, tickMargin: 6 };
33363
33653
  }, [containerWidth]);
33364
- const formatHour = React141__default.useCallback((hourIndex) => {
33365
- const isLastHour = hourIndex === SHIFT_DURATION - 1;
33366
- const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
33367
- const startHour = Math.floor(startDecimalHour) % 24;
33368
- const startMinute = Math.round(startDecimalHour % 1 * 60);
33369
- let endHour, endMinute;
33370
- if (isLastHour && shiftEndTime) {
33371
- endHour = shiftEndTime.hour;
33372
- endMinute = shiftEndTime.minute;
33373
- } else {
33374
- const endDecimalHour = startDecimalHour + 1;
33375
- endHour = Math.floor(endDecimalHour) % 24;
33376
- endMinute = Math.round(endDecimalHour % 1 * 60);
33377
- }
33378
- const formatTime5 = (h, m) => {
33379
- const period = h >= 12 ? "PM" : "AM";
33380
- const hour12 = h === 0 ? 12 : h > 12 ? h - 12 : h;
33381
- if (m === 0) {
33382
- return `${hour12}${period}`;
33383
- }
33384
- return `${hour12}:${m.toString().padStart(2, "0")}${period}`;
33385
- };
33386
- return `${formatTime5(startHour, startMinute)}-${formatTime5(endHour, endMinute)}`;
33387
- }, [shiftStartTime.decimalHour, SHIFT_DURATION, shiftEndTime]);
33388
- const formatTimeRange2 = React141__default.useCallback((hourIndex) => {
33389
- const isLastHour = hourIndex === SHIFT_DURATION - 1;
33390
- const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
33391
- const startHour = Math.floor(startDecimalHour) % 24;
33392
- const startMinute = Math.round(startDecimalHour % 1 * 60);
33393
- let endHour, endMinute;
33394
- if (isLastHour && shiftEndTime) {
33395
- endHour = shiftEndTime.hour;
33396
- endMinute = shiftEndTime.minute;
33397
- } else {
33398
- const endDecimalHour = startDecimalHour + 1;
33399
- endHour = Math.floor(endDecimalHour) % 24;
33400
- endMinute = Math.round(endDecimalHour % 1 * 60);
33401
- }
33402
- const formatTime5 = (h, m) => {
33403
- const period = h >= 12 ? "PM" : "AM";
33404
- const hour12 = h === 0 ? 12 : h > 12 ? h - 12 : h;
33405
- return `${hour12}:${m.toString().padStart(2, "0")} ${period}`;
33406
- };
33407
- return `${formatTime5(startHour, startMinute)} - ${formatTime5(endHour, endMinute)}`;
33408
- }, [shiftStartTime.decimalHour, SHIFT_DURATION, shiftEndTime]);
33409
- const chartData = React141__default.useMemo(() => {
33654
+ const chartData = React142__default.useMemo(() => {
33410
33655
  return Array.from({ length: SHIFT_DURATION }, (_, i) => {
33411
- const actualHour = (shiftStartTime.hour + i) % 24;
33412
- const startMinute = shiftStartTime.minute;
33413
- let idleArray = [];
33414
- let idleMinutes = 0;
33415
- if (idleTimeHourly) {
33416
- if (startMinute > 0) {
33417
- if (i === 0) {
33418
- const firstHourData = idleTimeHourly[actualHour.toString()] || [];
33419
- const nextHour = (actualHour + 1) % 24;
33420
- const nextHourData = idleTimeHourly[nextHour.toString()] || [];
33421
- idleArray = [
33422
- ...firstHourData.slice(startMinute) || [],
33423
- ...nextHourData.slice(0, startMinute) || []
33424
- ];
33425
- } else if (i < SHIFT_DURATION - 1) {
33426
- const currentHourData = idleTimeHourly[actualHour.toString()] || [];
33427
- const nextHour = (actualHour + 1) % 24;
33428
- const nextHourData = idleTimeHourly[nextHour.toString()] || [];
33429
- idleArray = [
33430
- ...currentHourData.slice(startMinute) || [],
33431
- ...nextHourData.slice(0, startMinute) || []
33432
- ];
33433
- } else {
33434
- const hasPartialLastHour2 = shiftEndTime && shiftEndTime.minute > 0 && shiftEndTime.minute < 60;
33435
- if (hasPartialLastHour2) {
33436
- const currentHourData = idleTimeHourly[actualHour.toString()] || [];
33437
- const nextHour = (actualHour + 1) % 24;
33438
- const nextHourData = idleTimeHourly[nextHour.toString()] || [];
33439
- if (startMinute > 0) {
33440
- const firstPart = currentHourData.slice(startMinute) || [];
33441
- const secondPart = nextHourData.slice(0, shiftEndTime.minute) || [];
33442
- idleArray = [...firstPart, ...secondPart];
33443
- } else {
33444
- idleArray = currentHourData.slice(0, shiftEndTime.minute) || [];
33445
- }
33446
- } else {
33447
- const currentHourData = idleTimeHourly[actualHour.toString()] || [];
33448
- const nextHour = (actualHour + 1) % 24;
33449
- const nextHourData = idleTimeHourly[nextHour.toString()] || [];
33450
- idleArray = [
33451
- ...currentHourData.slice(startMinute) || [],
33452
- ...nextHourData.slice(0, startMinute) || []
33453
- ];
33454
- }
33455
- }
33456
- } else {
33457
- const currentHourData = idleTimeHourly[actualHour.toString()] || [];
33458
- if (i === SHIFT_DURATION - 1 && shiftEndTime && shiftEndTime.minute > 0 && shiftEndTime.minute < 60) {
33459
- idleArray = currentHourData.slice(0, shiftEndTime.minute) || [];
33460
- } else {
33461
- idleArray = currentHourData || [];
33462
- }
33463
- }
33464
- }
33465
- idleMinutes = idleArray.filter((val) => val === "1" || val === 1).length;
33656
+ const idleSlot = idleSlots[i];
33466
33657
  return {
33467
- hourIndex: i,
33468
- hour: formatHour(i),
33469
- timeRange: formatTimeRange2(i),
33658
+ hourIndex: idleSlot?.hourIndex ?? i,
33659
+ hour: idleSlot?.hour || "",
33660
+ timeRange: idleSlot?.timeRange || "",
33470
33661
  output: animatedData[i] || 0,
33471
33662
  originalOutput: data[i] || 0,
33472
33663
  // Keep original data for labels
33473
33664
  color: (animatedData[i] || 0) >= Math.round(pphThreshold) ? "#00AB45" : "#E34329",
33474
- idleMinutes,
33475
- idleArray
33665
+ idleMinutes: idleSlot?.idleMinutes || 0,
33666
+ idleArray: idleSlot?.idleArray || []
33476
33667
  };
33477
33668
  });
33478
- }, [animatedData, data, pphThreshold, idleTimeHourly, shiftStartTime.hour, shiftStartTime.minute, shiftEndTime, formatHour, formatTimeRange2, SHIFT_DURATION]);
33479
- const IdleBar = React141__default.useMemo(() => {
33669
+ }, [animatedData, data, pphThreshold, idleSlots, SHIFT_DURATION]);
33670
+ const IdleBar = React142__default.useMemo(() => {
33480
33671
  if (!idleBarState.visible) return null;
33481
33672
  return /* @__PURE__ */ jsx(
33482
33673
  Bar,
@@ -33637,36 +33828,11 @@ var HourlyOutputChartComponent = ({
33637
33828
  content: (props) => {
33638
33829
  if (!props.active || !props.payload || props.payload.length === 0) return null;
33639
33830
  const data2 = props.payload[0].payload;
33640
- const idleRanges = [];
33641
- if (showIdleTime && data2.idleArray) {
33642
- let currentRange = null;
33643
- data2.idleArray.forEach((val, idx) => {
33644
- if (val === "1" || val === 1) {
33645
- if (!currentRange) {
33646
- currentRange = { start: idx, end: idx };
33647
- } else {
33648
- currentRange.end = idx;
33649
- }
33650
- } else if (val !== "x" && currentRange) {
33651
- idleRanges.push(currentRange);
33652
- currentRange = null;
33653
- }
33654
- });
33655
- if (currentRange) {
33656
- idleRanges.push(currentRange);
33657
- }
33658
- }
33659
- const formatIdleTimestamp = (minuteIdx) => {
33660
- const fallbackIndex = chartData.findIndex((item) => item.timeRange === data2.timeRange);
33661
- const hourOffset = Number.isFinite(data2.hourIndex) ? data2.hourIndex : fallbackIndex;
33662
- const safeHourOffset = hourOffset >= 0 ? hourOffset : 0;
33663
- const totalMinutes = (shiftStartTime.hour + safeHourOffset) * 60 + shiftStartTime.minute + minuteIdx;
33664
- const hour = Math.floor(totalMinutes / 60) % 24;
33665
- const minute = totalMinutes % 60;
33666
- const period = hour >= 12 ? "PM" : "AM";
33667
- const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
33668
- return `${hour12}:${minute.toString().padStart(2, "0")} ${period}`;
33669
- };
33831
+ const idlePeriods = showIdleTime ? getHourlyIdlePeriods({
33832
+ idleArray: data2.idleArray,
33833
+ shiftStart,
33834
+ hourIndex: Number.isFinite(data2.hourIndex) ? data2.hourIndex : 0
33835
+ }) : [];
33670
33836
  return /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl shadow-xl border border-gray-100 p-4 min-w-[220px]", children: [
33671
33837
  /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-3", children: /* @__PURE__ */ jsx("p", { className: "font-semibold text-gray-900 text-sm", children: data2.timeRange }) }),
33672
33838
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
@@ -33685,27 +33851,22 @@ var HourlyOutputChartComponent = ({
33685
33851
  " minutes"
33686
33852
  ] })
33687
33853
  ] }) }),
33688
- idleRanges.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-3 bg-gray-50 rounded-lg p-2.5", children: [
33854
+ idlePeriods.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-3 bg-gray-50 rounded-lg p-2.5", children: [
33689
33855
  /* @__PURE__ */ jsx("p", { className: "font-medium text-gray-700 text-xs mb-2", children: "Idle periods:" }),
33690
- /* @__PURE__ */ jsx("div", { className: "space-y-1 max-h-32 overflow-y-auto pr-1", children: idleRanges.map((range, index) => {
33691
- const duration = range.end - range.start + 1;
33692
- const startTime = formatIdleTimestamp(range.start);
33693
- const endTime = formatIdleTimestamp(range.end + 1);
33694
- const fallbackIndex = chartData.findIndex((item) => item.timeRange === data2.timeRange);
33695
- Number.isFinite(data2.hourIndex) ? data2.hourIndex : fallbackIndex;
33856
+ /* @__PURE__ */ jsx("div", { className: "space-y-1 max-h-32 overflow-y-auto pr-1", children: idlePeriods.map((period, index) => {
33696
33857
  return /* @__PURE__ */ jsxs("div", { className: "text-gray-600 flex items-center gap-2 text-xs", children: [
33697
33858
  /* @__PURE__ */ jsx("span", { className: "inline-block w-1.5 h-1.5 bg-orange-400 rounded-full flex-shrink-0" }),
33698
- /* @__PURE__ */ jsx("span", { children: duration === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
33699
- startTime,
33859
+ /* @__PURE__ */ jsx("span", { children: period.duration === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
33860
+ period.startTime,
33700
33861
  " (",
33701
- duration,
33862
+ period.duration,
33702
33863
  " min)"
33703
33864
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
33704
- startTime,
33865
+ period.startTime,
33705
33866
  " - ",
33706
- endTime,
33867
+ period.endTime,
33707
33868
  " (",
33708
- duration,
33869
+ period.duration,
33709
33870
  " mins)"
33710
33871
  ] }) })
33711
33872
  ] }, index);
@@ -33804,7 +33965,7 @@ var HourlyOutputChartComponent = ({
33804
33965
  }
33805
33966
  );
33806
33967
  };
33807
- var HourlyOutputChart = React141__default.memo(HourlyOutputChartComponent, (prevProps, nextProps) => {
33968
+ var HourlyOutputChart = React142__default.memo(HourlyOutputChartComponent, (prevProps, nextProps) => {
33808
33969
  if (prevProps.pphThreshold !== nextProps.pphThreshold || prevProps.shiftStart !== nextProps.shiftStart || prevProps.shiftEnd !== nextProps.shiftEnd || prevProps.shiftDate !== nextProps.shiftDate || prevProps.timezone !== nextProps.timezone || prevProps.showIdleTime !== nextProps.showIdleTime || prevProps.className !== nextProps.className) {
33809
33970
  return false;
33810
33971
  }
@@ -33860,9 +34021,8 @@ var HourlyOutputChart = React141__default.memo(HourlyOutputChartComponent, (prev
33860
34021
  HourlyOutputChart.displayName = "HourlyOutputChart";
33861
34022
 
33862
34023
  // src/components/dashboard/grid/videoGridMetricUtils.ts
33863
- var VIDEO_GRID_LEGEND_LABEL = "7 Minute Efficiency";
33864
34024
  var MAP_GRID_LEGEND_LABEL = "Efficiency";
33865
- var MIXED_VIDEO_GRID_LEGEND_LABEL = "Efficiency";
34025
+ var MIXED_VIDEO_GRID_LEGEND_LABEL = "Flow Efficiency";
33866
34026
  var isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
33867
34027
  var isVideoGridRecentFlowEnabled = (workspace) => isRecentFlowVideoGridMetricMode(
33868
34028
  workspace.video_grid_metric_mode,
@@ -33893,6 +34053,9 @@ var getVideoGridBaseColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND)
33893
34053
  return getEfficiencyColor(metricValue, legend);
33894
34054
  };
33895
34055
  var isLowWipGreenOverride = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
34056
+ if (workspace.scheduled_break_active === true) {
34057
+ return false;
34058
+ }
33896
34059
  if (!hasVideoGridRecentFlow(workspace) || !isVideoGridWipGated(workspace)) {
33897
34060
  return false;
33898
34061
  }
@@ -33961,8 +34124,15 @@ var getVideoGridLegendLabel = (workspaces) => {
33961
34124
  if (recentFlowEnabledCount === 0) {
33962
34125
  return MAP_GRID_LEGEND_LABEL;
33963
34126
  }
34127
+ const recentFlowWindows = new Set(
34128
+ visibleWorkspaces.filter(isVideoGridRecentFlowEnabled).map((workspace) => workspace.recent_flow_window_minutes ?? 7).filter((value) => typeof value === "number" && Number.isFinite(value))
34129
+ );
33964
34130
  if (recentFlowEnabledCount === visibleWorkspaces.length) {
33965
- return VIDEO_GRID_LEGEND_LABEL;
34131
+ if (recentFlowWindows.size === 1) {
34132
+ const [windowMinutes] = Array.from(recentFlowWindows);
34133
+ return `${windowMinutes} Minute Efficiency`;
34134
+ }
34135
+ return MIXED_VIDEO_GRID_LEGEND_LABEL;
33966
34136
  }
33967
34137
  return MIXED_VIDEO_GRID_LEGEND_LABEL;
33968
34138
  };
@@ -33975,7 +34145,7 @@ function getTrendArrowAndColor(trend) {
33975
34145
  return { arrow: "\u2192", color: "text-gray-400" };
33976
34146
  }
33977
34147
  }
33978
- var VideoCard = React141__default.memo(({
34148
+ var VideoCard = React142__default.memo(({
33979
34149
  workspace,
33980
34150
  hlsUrl,
33981
34151
  shouldPlay,
@@ -34137,7 +34307,7 @@ var VideoCard = React141__default.memo(({
34137
34307
  }
34138
34308
  );
34139
34309
  }, (prevProps, nextProps) => {
34140
- if (prevProps.workspace.efficiency !== nextProps.workspace.efficiency || prevProps.workspace.assembly_enabled !== nextProps.workspace.assembly_enabled || prevProps.workspace.video_grid_metric_mode !== nextProps.workspace.video_grid_metric_mode || prevProps.workspace.recent_flow_percent !== nextProps.workspace.recent_flow_percent || prevProps.workspace.recent_flow_effective_end_at !== nextProps.workspace.recent_flow_effective_end_at || prevProps.workspace.incoming_wip_current !== nextProps.workspace.incoming_wip_current || prevProps.workspace.incoming_wip_buffer_name !== nextProps.workspace.incoming_wip_buffer_name || prevProps.workspace.trend !== nextProps.workspace.trend || prevProps.workspace.performance_score !== nextProps.workspace.performance_score || prevProps.workspace.pph !== nextProps.workspace.pph) {
34310
+ if (prevProps.workspace.efficiency !== nextProps.workspace.efficiency || prevProps.workspace.assembly_enabled !== nextProps.workspace.assembly_enabled || prevProps.workspace.video_grid_metric_mode !== nextProps.workspace.video_grid_metric_mode || prevProps.workspace.recent_flow_percent !== nextProps.workspace.recent_flow_percent || prevProps.workspace.recent_flow_effective_end_at !== nextProps.workspace.recent_flow_effective_end_at || prevProps.workspace.scheduled_break_active !== nextProps.workspace.scheduled_break_active || prevProps.workspace.incoming_wip_current !== nextProps.workspace.incoming_wip_current || prevProps.workspace.incoming_wip_buffer_name !== nextProps.workspace.incoming_wip_buffer_name || prevProps.workspace.trend !== nextProps.workspace.trend || prevProps.workspace.performance_score !== nextProps.workspace.performance_score || prevProps.workspace.pph !== nextProps.workspace.pph) {
34141
34311
  return false;
34142
34312
  }
34143
34313
  if (prevProps.workspace.workspace_uuid !== nextProps.workspace.workspace_uuid || prevProps.workspace.workspace_name !== nextProps.workspace.workspace_name || prevProps.workspace.line_id !== nextProps.workspace.line_id) {
@@ -34173,7 +34343,7 @@ var logDebug2 = (...args) => {
34173
34343
  if (!DEBUG_DASHBOARD_LOGS2) return;
34174
34344
  console.log(...args);
34175
34345
  };
34176
- var VideoGridView = React141__default.memo(({
34346
+ var VideoGridView = React142__default.memo(({
34177
34347
  workspaces,
34178
34348
  selectedLine,
34179
34349
  className = "",
@@ -34545,7 +34715,7 @@ var VideoGridView = React141__default.memo(({
34545
34715
  ) }) });
34546
34716
  });
34547
34717
  VideoGridView.displayName = "VideoGridView";
34548
- var MapGridView = React141__default.memo(({
34718
+ var MapGridView = React142__default.memo(({
34549
34719
  workspaces,
34550
34720
  className = "",
34551
34721
  displayNames = {},
@@ -35384,7 +35554,7 @@ var UptimeLineChartComponent = ({ points, className = "" }) => {
35384
35554
  )
35385
35555
  ] }) }) });
35386
35556
  };
35387
- var UptimeLineChart = React141__default.memo(UptimeLineChartComponent);
35557
+ var UptimeLineChart = React142__default.memo(UptimeLineChartComponent);
35388
35558
  var padTime = (value) => value.toString().padStart(2, "0");
35389
35559
  var parseTime = (timeValue) => {
35390
35560
  if (!timeValue) return null;
@@ -35624,10 +35794,10 @@ var HourlyUptimeChartComponent = ({
35624
35794
  elapsedMinutes,
35625
35795
  className = ""
35626
35796
  }) => {
35627
- const containerRef = React141__default.useRef(null);
35628
- const [containerReady, setContainerReady] = React141__default.useState(false);
35629
- const [containerWidth, setContainerWidth] = React141__default.useState(0);
35630
- const uptimeSeries = React141__default.useMemo(() => buildUptimeSeries({
35797
+ const containerRef = React142__default.useRef(null);
35798
+ const [containerReady, setContainerReady] = React142__default.useState(false);
35799
+ const [containerWidth, setContainerWidth] = React142__default.useState(0);
35800
+ const uptimeSeries = React142__default.useMemo(() => buildUptimeSeries({
35631
35801
  idleTimeHourly,
35632
35802
  shiftStart,
35633
35803
  shiftEnd,
@@ -35636,11 +35806,11 @@ var HourlyUptimeChartComponent = ({
35636
35806
  elapsedMinutes
35637
35807
  }), [idleTimeHourly, shiftStart, shiftEnd, shiftDate, timezone, elapsedMinutes]);
35638
35808
  const hasAggregateData = Boolean(hourlyAggregates && hourlyAggregates.length > 0);
35639
- const shiftStartTime = React141__default.useMemo(
35809
+ const shiftStartTime = React142__default.useMemo(
35640
35810
  () => getTimeFromTimeString(shiftStart),
35641
35811
  [shiftStart]
35642
35812
  );
35643
- const { shiftDuration, shiftEndTime } = React141__default.useMemo(() => {
35813
+ const { shiftDuration, shiftEndTime } = React142__default.useMemo(() => {
35644
35814
  if (!shiftEnd) {
35645
35815
  const fallbackHours = uptimeSeries.shiftMinutes > 0 ? Math.ceil(uptimeSeries.shiftMinutes / 60) : 0;
35646
35816
  return { shiftDuration: fallbackHours, shiftEndTime: null };
@@ -35654,7 +35824,7 @@ var HourlyUptimeChartComponent = ({
35654
35824
  const hourCount = hasPartial ? Math.ceil(duration) : Math.round(duration);
35655
35825
  return { shiftDuration: hourCount, shiftEndTime: endTime };
35656
35826
  }, [shiftEnd, shiftStartTime.decimalHour, uptimeSeries.shiftMinutes]);
35657
- const formatHour = React141__default.useCallback((hourIndex) => {
35827
+ const formatHour = React142__default.useCallback((hourIndex) => {
35658
35828
  const isLastHour = hourIndex === shiftDuration - 1;
35659
35829
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
35660
35830
  const startHour = Math.floor(startDecimalHour) % 24;
@@ -35679,7 +35849,7 @@ var HourlyUptimeChartComponent = ({
35679
35849
  };
35680
35850
  return `${formatTime5(startHour, startMinute)}-${formatTime5(endHour, endMinute)}`;
35681
35851
  }, [shiftDuration, shiftStartTime.decimalHour, shiftEndTime]);
35682
- const formatTimeRange2 = React141__default.useCallback((hourIndex) => {
35852
+ const formatTimeRange2 = React142__default.useCallback((hourIndex) => {
35683
35853
  const isLastHour = hourIndex === shiftDuration - 1;
35684
35854
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
35685
35855
  const startHour = Math.floor(startDecimalHour) % 24;
@@ -35701,7 +35871,7 @@ var HourlyUptimeChartComponent = ({
35701
35871
  };
35702
35872
  return `${formatTime5(startHour, startMinute)} - ${formatTime5(endHour, endMinute)}`;
35703
35873
  }, [shiftDuration, shiftStartTime.decimalHour, shiftEndTime]);
35704
- const chartData = React141__default.useMemo(() => {
35874
+ const chartData = React142__default.useMemo(() => {
35705
35875
  if (shiftDuration <= 0) return [];
35706
35876
  if (hasAggregateData) {
35707
35877
  return hourlyAggregates.map((entry, hourIndex) => ({
@@ -35743,7 +35913,7 @@ var HourlyUptimeChartComponent = ({
35743
35913
  }, [hasAggregateData, hourlyAggregates, uptimeSeries.points, uptimeSeries.elapsedMinutes, uptimeSeries.shiftMinutes, shiftDuration, formatHour, formatTimeRange2]);
35744
35914
  const maxYValue = 100;
35745
35915
  const yAxisTicks = [0, 25, 50, 75, 100];
35746
- React141__default.useEffect(() => {
35916
+ React142__default.useEffect(() => {
35747
35917
  const checkContainerDimensions = () => {
35748
35918
  if (containerRef.current) {
35749
35919
  const rect = containerRef.current.getBoundingClientRect();
@@ -35769,7 +35939,7 @@ var HourlyUptimeChartComponent = ({
35769
35939
  clearTimeout(fallbackTimeout);
35770
35940
  };
35771
35941
  }, []);
35772
- const xAxisConfig = React141__default.useMemo(() => {
35942
+ const xAxisConfig = React142__default.useMemo(() => {
35773
35943
  if (containerWidth >= 960) {
35774
35944
  return { interval: 0, angle: -45, height: 92, tickFont: 10, tickMargin: 12, labelMode: "full" };
35775
35945
  }
@@ -35778,7 +35948,7 @@ var HourlyUptimeChartComponent = ({
35778
35948
  }
35779
35949
  return { interval: 0, angle: -30, height: 64, tickFont: 9, tickMargin: 6, labelMode: "start" };
35780
35950
  }, [containerWidth]);
35781
- const formatXAxisTick = React141__default.useCallback((raw) => {
35951
+ const formatXAxisTick = React142__default.useCallback((raw) => {
35782
35952
  const label = typeof raw === "string" ? raw : String(raw);
35783
35953
  if (xAxisConfig.labelMode === "full") return label;
35784
35954
  const parts = label.split("-");
@@ -35909,7 +36079,7 @@ var HourlyUptimeChartComponent = ({
35909
36079
  idleRanges.push(currentRange);
35910
36080
  }
35911
36081
  }
35912
- const formatIdleTimestamp = (minuteIdx) => {
36082
+ const formatIdleTimestamp2 = (minuteIdx) => {
35913
36083
  const totalMinutes = (shiftStartTime.hour + data.hourIndex) * 60 + shiftStartTime.minute + minuteIdx;
35914
36084
  const hour = Math.floor(totalMinutes / 60) % 24;
35915
36085
  const minute = totalMinutes % 60;
@@ -35939,8 +36109,8 @@ var HourlyUptimeChartComponent = ({
35939
36109
  /* @__PURE__ */ jsx("p", { className: "font-medium text-gray-700 text-xs mb-2", children: "Idle periods:" }),
35940
36110
  /* @__PURE__ */ jsx("div", { className: "space-y-1 max-h-32 overflow-y-auto pr-1", children: idleRanges.map((range, index) => {
35941
36111
  const duration = range.end - range.start + 1;
35942
- const startTime = formatIdleTimestamp(range.start);
35943
- const endTime = formatIdleTimestamp(range.end + 1);
36112
+ const startTime = formatIdleTimestamp2(range.start);
36113
+ const endTime = formatIdleTimestamp2(range.end + 1);
35944
36114
  return /* @__PURE__ */ jsxs("div", { className: "text-gray-600 flex items-center gap-2 text-xs", children: [
35945
36115
  /* @__PURE__ */ jsx("span", { className: "inline-block w-1.5 h-1.5 bg-orange-400 rounded-full flex-shrink-0" }),
35946
36116
  /* @__PURE__ */ jsx("span", { children: duration === 1 ? `${startTime} (${duration} min)` : `${startTime} - ${endTime} (${duration} mins)` })
@@ -35984,7 +36154,7 @@ var HourlyUptimeChartComponent = ({
35984
36154
  }
35985
36155
  );
35986
36156
  };
35987
- var HourlyUptimeChart = React141__default.memo(HourlyUptimeChartComponent);
36157
+ var HourlyUptimeChart = React142__default.memo(HourlyUptimeChartComponent);
35988
36158
  var DEFAULT_COLORS2 = ["#00AB45", "#ef4444"];
35989
36159
  var UptimeDonutChartComponent = ({
35990
36160
  data,
@@ -36054,7 +36224,7 @@ var UptimeDonutChartComponent = ({
36054
36224
  ] }) })
36055
36225
  ] }) });
36056
36226
  };
36057
- var UptimeDonutChart = React141__default.memo(UptimeDonutChartComponent);
36227
+ var UptimeDonutChart = React142__default.memo(UptimeDonutChartComponent);
36058
36228
  UptimeDonutChart.displayName = "UptimeDonutChart";
36059
36229
  var TrendIcon = ({ trend }) => {
36060
36230
  if (trend === "up") {
@@ -36173,7 +36343,7 @@ var EmptyStateMessage = ({
36173
36343
  iconClassName
36174
36344
  }) => {
36175
36345
  let IconContent = null;
36176
- if (React141__default.isValidElement(iconType)) {
36346
+ if (React142__default.isValidElement(iconType)) {
36177
36347
  IconContent = iconType;
36178
36348
  } else if (typeof iconType === "string") {
36179
36349
  const MappedIcon = IconMap[iconType];
@@ -36826,6 +36996,7 @@ var VideoControls = ({
36826
36996
  return /* @__PURE__ */ jsxs(
36827
36997
  "div",
36828
36998
  {
36999
+ onClick: (e) => e.stopPropagation(),
36829
37000
  className: `absolute bottom-0 left-0 right-0 px-3 pb-3 pt-12 bg-gradient-to-t from-black/80 via-black/40 to-transparent transition-opacity duration-300 ${controlsVisible ? "opacity-100" : "opacity-0 pointer-events-none"} ${className}`,
36830
37001
  style: { touchAction: "none" },
36831
37002
  children: [
@@ -37869,13 +38040,11 @@ var HlsVideoPlayer = forwardRef(({
37869
38040
  player: playerLikeObject()
37870
38041
  }), [play, pause, currentTimeProp, durationProp, paused, mute, volumeProp, playbackRateProp, dispose, isReady, playerLikeObject]);
37871
38042
  const handleContainerClick = useCallback(() => {
37872
- if (!onClick && !controls) {
37873
- handleTogglePlay();
37874
- }
38043
+ handleTogglePlay();
37875
38044
  if (onClick) {
37876
38045
  onClick();
37877
38046
  }
37878
- }, [onClick, controls, handleTogglePlay]);
38047
+ }, [onClick, handleTogglePlay]);
37879
38048
  return /* @__PURE__ */ jsxs(
37880
38049
  "div",
37881
38050
  {
@@ -38300,9 +38469,7 @@ var CroppedHlsVideoPlayer = forwardRef(({
38300
38469
  return /* @__PURE__ */ jsx(HlsVideoPlayer, { ref, ...videoProps, onClick, controls });
38301
38470
  }
38302
38471
  const handleClick = () => {
38303
- if (!onClick && !controls) {
38304
- handleTogglePlay();
38305
- }
38472
+ handleTogglePlay();
38306
38473
  if (onClick) onClick();
38307
38474
  };
38308
38475
  return /* @__PURE__ */ jsxs(
@@ -38458,7 +38625,7 @@ function Skeleton({ className, ...props }) {
38458
38625
  var Select = SelectPrimitive.Root;
38459
38626
  var SelectGroup = SelectPrimitive.Group;
38460
38627
  var SelectValue = SelectPrimitive.Value;
38461
- var SelectTrigger = React141.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
38628
+ var SelectTrigger = React142.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
38462
38629
  SelectPrimitive.Trigger,
38463
38630
  {
38464
38631
  ref,
@@ -38474,7 +38641,7 @@ var SelectTrigger = React141.forwardRef(({ className, children, ...props }, ref)
38474
38641
  }
38475
38642
  ));
38476
38643
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
38477
- var SelectScrollUpButton = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
38644
+ var SelectScrollUpButton = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
38478
38645
  SelectPrimitive.ScrollUpButton,
38479
38646
  {
38480
38647
  ref,
@@ -38484,7 +38651,7 @@ var SelectScrollUpButton = React141.forwardRef(({ className, ...props }, ref) =>
38484
38651
  }
38485
38652
  ));
38486
38653
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
38487
- var SelectScrollDownButton = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
38654
+ var SelectScrollDownButton = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
38488
38655
  SelectPrimitive.ScrollDownButton,
38489
38656
  {
38490
38657
  ref,
@@ -38494,7 +38661,7 @@ var SelectScrollDownButton = React141.forwardRef(({ className, ...props }, ref)
38494
38661
  }
38495
38662
  ));
38496
38663
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
38497
- var SelectContent = React141.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
38664
+ var SelectContent = React142.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
38498
38665
  SelectPrimitive.Content,
38499
38666
  {
38500
38667
  ref,
@@ -38522,7 +38689,7 @@ var SelectContent = React141.forwardRef(({ className, children, position = "popp
38522
38689
  }
38523
38690
  ) }));
38524
38691
  SelectContent.displayName = SelectPrimitive.Content.displayName;
38525
- var SelectLabel = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
38692
+ var SelectLabel = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
38526
38693
  SelectPrimitive.Label,
38527
38694
  {
38528
38695
  ref,
@@ -38531,7 +38698,7 @@ var SelectLabel = React141.forwardRef(({ className, ...props }, ref) => /* @__PU
38531
38698
  }
38532
38699
  ));
38533
38700
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
38534
- var SelectItem = React141.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
38701
+ var SelectItem = React142.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
38535
38702
  SelectPrimitive.Item,
38536
38703
  {
38537
38704
  ref,
@@ -38547,7 +38714,7 @@ var SelectItem = React141.forwardRef(({ className, children, ...props }, ref) =>
38547
38714
  }
38548
38715
  ));
38549
38716
  SelectItem.displayName = SelectPrimitive.Item.displayName;
38550
- var SelectSeparator = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
38717
+ var SelectSeparator = React142.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
38551
38718
  SelectPrimitive.Separator,
38552
38719
  {
38553
38720
  ref,
@@ -38846,7 +39013,7 @@ var TimePickerDropdown = ({
38846
39013
  ] })
38847
39014
  ] });
38848
39015
  };
38849
- var SilentErrorBoundary = class extends React141__default.Component {
39016
+ var SilentErrorBoundary = class extends React142__default.Component {
38850
39017
  constructor(props) {
38851
39018
  super(props);
38852
39019
  this.handleClearAndReload = () => {
@@ -42805,17 +42972,6 @@ var BottlenecksContent = ({
42805
42972
  window.addEventListener("keydown", handleKeyDown);
42806
42973
  return () => window.removeEventListener("keydown", handleKeyDown);
42807
42974
  }, [handlePrevious, handleNext]);
42808
- const togglePlayback = () => {
42809
- const player = videoRef.current?.player;
42810
- if (!player) return;
42811
- if (player.paused()) {
42812
- player.play()?.catch((err) => {
42813
- console.error("Error playing video:", err);
42814
- });
42815
- } else {
42816
- player.pause();
42817
- }
42818
- };
42819
42975
  const handlePlaybackSpeedChange = useCallback((speed) => {
42820
42976
  setPlaybackSpeed(speed);
42821
42977
  if (videoRef.current?.playbackRate) {
@@ -42985,7 +43141,6 @@ var BottlenecksContent = ({
42985
43141
  poster: "",
42986
43142
  className: "w-full h-full",
42987
43143
  crop: workspaceCrop?.crop,
42988
- onClick: togglePlayback,
42989
43144
  autoplay: true,
42990
43145
  playsInline: true,
42991
43146
  loop: false,
@@ -43410,7 +43565,6 @@ var BottlenecksContent = ({
43410
43565
  poster: "",
43411
43566
  className: "w-full h-full",
43412
43567
  crop: workspaceCrop?.crop,
43413
- onClick: togglePlayback,
43414
43568
  autoplay: true,
43415
43569
  playsInline: true,
43416
43570
  loop: false,
@@ -43929,7 +44083,7 @@ function DiagnosisVideoModal({
43929
44083
  src: playlistUrl,
43930
44084
  className: "w-full h-full",
43931
44085
  crop: null,
43932
- onClick: togglePlayback,
44086
+ controls: false,
43933
44087
  autoplay: false,
43934
44088
  playsInline: true,
43935
44089
  loop: false,
@@ -45448,8 +45602,8 @@ var IdleTimeReasonChartComponent = ({
45448
45602
  updateAnimation = "replay",
45449
45603
  variant = "pie"
45450
45604
  }) => {
45451
- const [activeData, setActiveData] = React141__default.useState([]);
45452
- React141__default.useEffect(() => {
45605
+ const [activeData, setActiveData] = React142__default.useState([]);
45606
+ React142__default.useEffect(() => {
45453
45607
  if (updateAnimation === "smooth") {
45454
45608
  setActiveData(data && data.length > 0 ? data : []);
45455
45609
  return;
@@ -45468,7 +45622,7 @@ var IdleTimeReasonChartComponent = ({
45468
45622
  setActiveData([]);
45469
45623
  }
45470
45624
  }, [data, updateAnimation]);
45471
- React141__default.useEffect(() => {
45625
+ React142__default.useEffect(() => {
45472
45626
  if (!data || data.length === 0) return;
45473
45627
  data.forEach((entry, index) => {
45474
45628
  if (entry.name.toLowerCase().includes("other")) {
@@ -45476,7 +45630,7 @@ var IdleTimeReasonChartComponent = ({
45476
45630
  }
45477
45631
  });
45478
45632
  }, [data]);
45479
- const pieKey = React141__default.useMemo(() => {
45633
+ const pieKey = React142__default.useMemo(() => {
45480
45634
  if (updateAnimation === "smooth") {
45481
45635
  return "smooth";
45482
45636
  }
@@ -45646,7 +45800,7 @@ var IdleTimeReasonChartComponent = ({
45646
45800
  )
45647
45801
  ] });
45648
45802
  };
45649
- var IdleTimeReasonChart = React141__default.memo(IdleTimeReasonChartComponent);
45803
+ var IdleTimeReasonChart = React142__default.memo(IdleTimeReasonChartComponent);
45650
45804
  IdleTimeReasonChart.displayName = "IdleTimeReasonChart";
45651
45805
  var IdleTimeReasonChart_default = IdleTimeReasonChart;
45652
45806
  var DEFAULT_PERFORMANCE_DATA = {
@@ -46921,10 +47075,17 @@ Underperforming Workspaces: ${lineInfo.metrics.underperforming_workspaces} / ${l
46921
47075
  var LinePdfGenerator = ({
46922
47076
  lineInfo,
46923
47077
  workspaceData,
47078
+ issueResolutionSummary,
46924
47079
  shiftName,
46925
47080
  className
46926
47081
  }) => {
46927
47082
  const [isGenerating, setIsGenerating] = useState(false);
47083
+ const formatResolutionDuration2 = (seconds) => {
47084
+ if (seconds === null || seconds === void 0 || seconds <= 0) {
47085
+ return "-";
47086
+ }
47087
+ return formatIdleTime(Math.max(0, Math.floor(seconds)));
47088
+ };
46928
47089
  const generatePDF = async () => {
46929
47090
  setIsGenerating(true);
46930
47091
  try {
@@ -47264,9 +47425,11 @@ var LinePdfGenerator = ({
47264
47425
  doc.text(`${lineInfo.metrics.current_output} / ${lineInfo.metrics.line_threshold}`, 120, kpiStartY);
47265
47426
  createKPIBox(kpiStartY + kpiSpacing);
47266
47427
  doc.setFont("helvetica", "normal");
47267
- doc.text("Underperforming Workspaces:", 25, kpiStartY + kpiSpacing);
47428
+ doc.text("Average Issue Resolution Time:", 25, kpiStartY + kpiSpacing);
47268
47429
  doc.setFont("helvetica", "bold");
47269
- doc.text(`${lineInfo.metrics.underperforming_workspaces} / ${lineInfo.metrics.total_workspaces}`, 120, kpiStartY + kpiSpacing);
47430
+ const resolutionSeconds = issueResolutionSummary ? issueResolutionSummary.mean_resolution_seconds ?? issueResolutionSummary.median_resolution_seconds : null;
47431
+ const displayValue = resolutionSeconds !== null ? formatResolutionDuration2(resolutionSeconds) : "-";
47432
+ doc.text(displayValue, 120, kpiStartY + kpiSpacing);
47270
47433
  createKPIBox(kpiStartY + kpiSpacing * 2);
47271
47434
  doc.setFont("helvetica", "normal");
47272
47435
  doc.text("Average Efficiency:", 25, kpiStartY + kpiSpacing * 2);
@@ -50004,7 +50167,7 @@ var arePropsEqual = (prevProps, nextProps) => {
50004
50167
  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
50005
50168
  prevProps.position.id === nextProps.position.id;
50006
50169
  };
50007
- var WorkspaceGridItem = React141__default.memo(({
50170
+ var WorkspaceGridItem = React142__default.memo(({
50008
50171
  data,
50009
50172
  position,
50010
50173
  isBottleneck = false,
@@ -50099,7 +50262,7 @@ var WorkspaceGridItem = React141__default.memo(({
50099
50262
  );
50100
50263
  }, arePropsEqual);
50101
50264
  WorkspaceGridItem.displayName = "WorkspaceGridItem";
50102
- var WorkspaceGrid = React141__default.memo(({
50265
+ var WorkspaceGrid = React142__default.memo(({
50103
50266
  workspaces,
50104
50267
  isPdfMode = false,
50105
50268
  customWorkspacePositions,
@@ -50358,7 +50521,7 @@ var KPICard = ({
50358
50521
  }) => {
50359
50522
  useThemeConfig();
50360
50523
  const { formatNumber } = useFormatNumber();
50361
- const trendInfo = React141__default.useMemo(() => {
50524
+ const trendInfo = React142__default.useMemo(() => {
50362
50525
  let trendValue = trend || "neutral";
50363
50526
  if (change !== void 0 && trend === void 0) {
50364
50527
  trendValue = change > 0 ? "up" : change < 0 ? "down" : "neutral";
@@ -50385,7 +50548,7 @@ var KPICard = ({
50385
50548
  const shouldShowTrend = !(change === 0 && trend === void 0);
50386
50549
  return { trendValue, Icon: Icon2, colorClass, bgClass, shouldShowTrend };
50387
50550
  }, [trend, change]);
50388
- const formattedValue = React141__default.useMemo(() => {
50551
+ const formattedValue = React142__default.useMemo(() => {
50389
50552
  if (title === "Quality Compliance" && typeof value === "number") {
50390
50553
  return value.toFixed(1);
50391
50554
  }
@@ -50399,7 +50562,7 @@ var KPICard = ({
50399
50562
  }
50400
50563
  return value;
50401
50564
  }, [value, title]);
50402
- const formattedChange = React141__default.useMemo(() => {
50565
+ const formattedChange = React142__default.useMemo(() => {
50403
50566
  if (change === void 0 || change === 0 && !showZeroChange) return null;
50404
50567
  const absChange = Math.abs(change);
50405
50568
  return formatNumber(absChange, { minimumFractionDigits: 0, maximumFractionDigits: 1 });
@@ -50773,6 +50936,7 @@ var WorkspaceHealthCard = ({
50773
50936
  className = "",
50774
50937
  onViewDetails
50775
50938
  }) => {
50939
+ const [copiedIp, setCopiedIp] = useState(false);
50776
50940
  const getStatusConfig = () => {
50777
50941
  switch (workspace.status) {
50778
50942
  case "healthy":
@@ -50947,6 +51111,34 @@ var WorkspaceHealthCard = ({
50947
51111
  /* @__PURE__ */ jsx("span", { className: "font-medium", children: formatTimeAgo(workspace.timeSinceLastUpdate) })
50948
51112
  ] })
50949
51113
  ] }),
51114
+ workspace.cameraIp ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-2 mt-1.5 -mx-2 rounded-md bg-slate-50/50 dark:bg-slate-900/50 border border-slate-100 dark:border-slate-800/60 group/ip transition-colors hover:bg-slate-100/50 dark:hover:bg-slate-800/50", children: [
51115
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
51116
+ /* @__PURE__ */ jsx(Video, { className: "h-3.5 w-3.5 text-slate-400" }),
51117
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium uppercase tracking-wide text-slate-500", children: "Camera IP" })
51118
+ ] }),
51119
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
51120
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-slate-700 dark:text-slate-300 select-all", children: workspace.cameraIp }),
51121
+ /* @__PURE__ */ jsx(
51122
+ "button",
51123
+ {
51124
+ onClick: (e) => {
51125
+ e.stopPropagation();
51126
+ e.preventDefault();
51127
+ navigator.clipboard.writeText(workspace.cameraIp);
51128
+ setCopiedIp(true);
51129
+ setTimeout(() => setCopiedIp(false), 2e3);
51130
+ },
51131
+ className: "p-1 rounded-md text-slate-400 hover:text-slate-600 hover:bg-slate-200 dark:hover:bg-slate-700 dark:hover:text-slate-300 transition-all opacity-0 group-hover/ip:opacity-100 focus:opacity-100",
51132
+ title: "Copy IP address",
51133
+ "aria-label": "Copy IP address",
51134
+ children: copiedIp ? /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 text-emerald-500" }) : /* @__PURE__ */ jsx(Copy, { className: "h-3.5 w-3.5" })
51135
+ }
51136
+ )
51137
+ ] })
51138
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 min-h-[1rem]", children: [
51139
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium uppercase tracking-wide text-slate-500", children: "Camera IP:" }),
51140
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: "N/A" })
51141
+ ] }),
50950
51142
  /* @__PURE__ */ jsx("div", { className: "mt-3 pt-3 border-t border-slate-100 dark:border-slate-800", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
50951
51143
  /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-slate-500 uppercase tracking-wide", children: downtimeConfig.label }),
50952
51144
  /* @__PURE__ */ jsx("span", { className: clsx("text-sm font-semibold", downtimeConfig.className), children: downtimeConfig.text })
@@ -51877,7 +52069,7 @@ var Breadcrumbs = ({ items }) => {
51877
52069
  }
51878
52070
  }
51879
52071
  };
51880
- 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(React141__default.Fragment, { children: [
52072
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "mb-1 flex items-center space-x-1 text-xs font-medium text-gray-500 dark:text-gray-400", children: items.map((item, index) => /* @__PURE__ */ jsxs(React142__default.Fragment, { children: [
51881
52073
  index > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "h-3 w-3 text-gray-400 dark:text-gray-500" }),
51882
52074
  /* @__PURE__ */ jsxs(
51883
52075
  "span",
@@ -52438,7 +52630,11 @@ var SideNavBar = memo$1(({
52438
52630
  dashboardConfig?.supervisorConfig?.enabled || false;
52439
52631
  const showSupervisorManagement = false;
52440
52632
  const ticketsEnabled = dashboardConfig?.ticketsConfig?.enabled ?? true;
52441
- const showBillingLink = canRoleViewClipsCost(role);
52633
+ const canViewBillingByRole = canRoleViewClipsCost(role);
52634
+ const { hasVlmEnabledLine } = useCompanyHasVlmEnabledLine({
52635
+ enabled: canViewBillingByRole
52636
+ });
52637
+ const showBillingLink = canViewBillingByRole && hasVlmEnabledLine;
52442
52638
  console.log("\u{1F50D} [SideNavBar] dashboardConfig:", dashboardConfig);
52443
52639
  console.log("\u{1F50D} [SideNavBar] ticketsConfig:", dashboardConfig?.ticketsConfig);
52444
52640
  console.log("\u{1F50D} [SideNavBar] ticketsEnabled:", ticketsEnabled);
@@ -52637,7 +52833,6 @@ var SideNavBar = memo$1(({
52637
52833
  return prev;
52638
52834
  });
52639
52835
  }, [alertsCount, isAlertsOpen]);
52640
- const unreadCount = alertsCount !== null ? Math.max(0, alertsCount - lastViewedCount) : 0;
52641
52836
  const alertsTriggerRef = useRef(null);
52642
52837
  const alertsCompanyId = entityConfig.companyId || user?.company_id;
52643
52838
  const showAlertsButton = (role === "supervisor" || role === "optifye") && !!alertsCompanyId && !!supabase;
@@ -52777,7 +52972,7 @@ var SideNavBar = memo$1(({
52777
52972
  ${isActive ? "bg-blue-50/80 text-blue-600 font-medium" : "hover:bg-gray-50 text-gray-500 hover:text-gray-700 font-medium active:bg-gray-100"}
52778
52973
  transition-all duration-200 ease-out focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2`;
52779
52974
  }, [isSettingsOpen, settingsItems]);
52780
- const alertsButtonClasses = useMemo(() => {
52975
+ useMemo(() => {
52781
52976
  const isActive = isAlertsOpen;
52782
52977
  return `w-full flex flex-col items-center justify-center py-4 sm:py-3 px-2 sm:px-1 rounded-lg relative group min-h-[44px] sm:min-h-0
52783
52978
  ${isActive ? "bg-blue-50/80 text-blue-600 font-medium" : "hover:bg-gray-50 text-gray-500 hover:text-gray-700 font-medium active:bg-gray-100"}
@@ -52905,54 +53100,25 @@ var SideNavBar = memo$1(({
52905
53100
  )
52906
53101
  ] })
52907
53102
  ] }),
52908
- /* @__PURE__ */ jsxs("div", { className: "w-full py-4 px-4 border-t border-gray-100 flex-shrink-0 flex flex-col gap-2", children: [
52909
- showAlertsButton && /* @__PURE__ */ jsxs(
52910
- "button",
52911
- {
52912
- ref: alertsTriggerRef,
52913
- onClick: () => {
52914
- const willOpen = !isAlertsOpen;
52915
- setIsAlertsOpen(willOpen);
52916
- setIsSettingsOpen(false);
52917
- if (willOpen) {
52918
- trackCoreEvent("Alerts page clicked", { source: "side_nav" });
52919
- void refreshAlertsSummary();
52920
- }
52921
- },
52922
- className: alertsButtonClasses,
52923
- "aria-label": "Alerts",
52924
- tabIndex: 0,
52925
- role: "tab",
52926
- "aria-selected": isAlertsOpen,
52927
- children: [
52928
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
52929
- /* @__PURE__ */ jsx(BellIcon, { className: "w-5 h-5 mb-1" }),
52930
- unreadCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute -top-1.5 -right-1.5 flex h-4 min-w-[16px] items-center justify-center rounded-full bg-red-500 px-1 text-[9px] font-bold text-white shadow-sm ring-2 ring-white", children: unreadCount > 99 ? "99+" : unreadCount })
52931
- ] }),
52932
- /* @__PURE__ */ jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight mt-1", children: "Alerts" })
52933
- ]
52934
- }
52935
- ),
52936
- settingsItems.length > 0 && /* @__PURE__ */ jsxs(
52937
- "button",
52938
- {
52939
- ref: settingsTriggerRef,
52940
- onClick: () => {
52941
- setIsSettingsOpen(!isSettingsOpen);
52942
- setIsAlertsOpen(false);
52943
- },
52944
- className: settingsButtonClasses,
52945
- "aria-label": "Settings",
52946
- tabIndex: 0,
52947
- role: "tab",
52948
- "aria-selected": isSettingsOpen || settingsItems.some((item) => item.isActive),
52949
- children: [
52950
- /* @__PURE__ */ jsx(Cog6ToothIcon, { className: "w-5 h-5 mb-1" }),
52951
- /* @__PURE__ */ jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Settings" })
52952
- ]
52953
- }
52954
- )
52955
- ] })
53103
+ /* @__PURE__ */ jsx("div", { className: "w-full py-4 px-4 border-t border-gray-100 flex-shrink-0 flex flex-col gap-2", children: settingsItems.length > 0 && /* @__PURE__ */ jsxs(
53104
+ "button",
53105
+ {
53106
+ ref: settingsTriggerRef,
53107
+ onClick: () => {
53108
+ setIsSettingsOpen(!isSettingsOpen);
53109
+ setIsAlertsOpen(false);
53110
+ },
53111
+ className: settingsButtonClasses,
53112
+ "aria-label": "Settings",
53113
+ tabIndex: 0,
53114
+ role: "tab",
53115
+ "aria-selected": isSettingsOpen || settingsItems.some((item) => item.isActive),
53116
+ children: [
53117
+ /* @__PURE__ */ jsx(Cog6ToothIcon, { className: "w-5 h-5 mb-1" }),
53118
+ /* @__PURE__ */ jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Settings" })
53119
+ ]
53120
+ }
53121
+ ) })
52956
53122
  ] });
52957
53123
  const MobileNavigationContent = () => {
52958
53124
  const isActive = (path) => {
@@ -53065,26 +53231,6 @@ var SideNavBar = memo$1(({
53065
53231
  /* @__PURE__ */ jsxs("div", { className: "mt-8 pt-6 border-t border-gray-100", children: [
53066
53232
  /* @__PURE__ */ jsx("h3", { className: "px-5 mb-3 text-[10px] font-bold text-gray-400 uppercase tracking-widest", children: "Settings & Support" }),
53067
53233
  /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
53068
- showAlertsButton && /* @__PURE__ */ jsxs(
53069
- "button",
53070
- {
53071
- onClick: () => {
53072
- setIsAlertsOpen(true);
53073
- trackCoreEvent("Alerts page clicked", { source: "side_nav_mobile" });
53074
- void refreshAlertsSummary();
53075
- onMobileMenuClose?.();
53076
- },
53077
- className: getMobileButtonClass("/alerts"),
53078
- "aria-label": "Alerts",
53079
- children: [
53080
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
53081
- /* @__PURE__ */ jsx(BellIcon, { className: getIconClass("/alerts") }),
53082
- unreadCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute -top-1.5 -right-1.5 flex h-4 min-w-[16px] items-center justify-center rounded-full bg-red-500 px-1 text-[9px] font-bold text-white shadow-sm ring-2 ring-white", children: unreadCount > 99 ? "99+" : unreadCount })
53083
- ] }),
53084
- /* @__PURE__ */ jsx("span", { className: "text-base font-medium ml-3", children: "Alerts" })
53085
- ]
53086
- }
53087
- ),
53088
53234
  canAccessPath("/targets") && /* @__PURE__ */ jsxs(
53089
53235
  "button",
53090
53236
  {
@@ -53399,7 +53545,7 @@ var AwardBadge = ({
53399
53545
  }) => {
53400
53546
  const styles2 = getBadgeStyles(type);
53401
53547
  const Icon2 = CustomIcon || getDefaultIcon(type);
53402
- const randomDelay = React141__default.useMemo(() => Math.random() * 2, []);
53548
+ const randomDelay = React142__default.useMemo(() => Math.random() * 2, []);
53403
53549
  const floatingAnimation = {
53404
53550
  animate: {
53405
53551
  y: [0, -10, 0],
@@ -59314,6 +59460,17 @@ function HomeView({
59314
59460
  }
59315
59461
  return allActiveBreaks.filter((breakItem) => breakItem.lineId === selectedLineId);
59316
59462
  }, [allActiveBreaks, selectedLineId, factoryViewId]);
59463
+ const activeBreakLineIds = useMemo(
59464
+ () => new Set(activeBreaks.map((breakItem) => breakItem.lineId)),
59465
+ [activeBreaks]
59466
+ );
59467
+ const workspaceMetricsWithBreakState = useMemo(
59468
+ () => workspaceMetrics.map((workspace) => ({
59469
+ ...workspace,
59470
+ scheduled_break_active: activeBreakLineIds.has(workspace.line_id)
59471
+ })),
59472
+ [workspaceMetrics, activeBreakLineIds]
59473
+ );
59317
59474
  const [breakNotificationsDismissed, setBreakNotificationsDismissed] = useState(false);
59318
59475
  useEffect(() => {
59319
59476
  if (activeBreaks.length > 0) {
@@ -59788,15 +59945,15 @@ function HomeView({
59788
59945
  ) }) }),
59789
59946
  /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto sm:overflow-hidden relative", children: [
59790
59947
  /* @__PURE__ */ jsx("div", { className: "absolute right-2 top-1 sm:right-6 sm:top-3 z-30 flex items-center space-x-2", children: lineSelectorComponent && lineSelectorComponent }),
59791
- /* @__PURE__ */ jsx("div", { className: "h-full sm:h-full min-h-[calc(100vh-100px)] sm:min-h-0", children: workspaceMetrics.length > 0 ? /* @__PURE__ */ jsx(
59948
+ /* @__PURE__ */ jsx("div", { className: "h-full sm:h-full min-h-[calc(100vh-100px)] sm:min-h-0", children: workspaceMetricsWithBreakState.length > 0 ? /* @__PURE__ */ jsx(
59792
59949
  motion.div,
59793
59950
  {
59794
59951
  initial: { opacity: 0, scale: 0.98 },
59795
59952
  animate: { opacity: 1, scale: 1 },
59796
59953
  transition: { duration: 0.3 },
59797
59954
  className: "h-full",
59798
- children: React141__default.createElement(WorkspaceGrid, {
59799
- workspaces: workspaceMetrics,
59955
+ children: React142__default.createElement(WorkspaceGrid, {
59956
+ workspaces: workspaceMetricsWithBreakState,
59800
59957
  lineNames,
59801
59958
  factoryView: factoryViewId,
59802
59959
  legend: efficiencyLegend,
@@ -59826,7 +59983,7 @@ function HomeView({
59826
59983
  animate: { opacity: 1, scale: 1 },
59827
59984
  transition: { duration: 0.3 },
59828
59985
  className: "h-full",
59829
- children: React141__default.createElement(WorkspaceGrid, {
59986
+ children: React142__default.createElement(WorkspaceGrid, {
59830
59987
  workspaces: [],
59831
59988
  // Show empty grid while loading
59832
59989
  lineNames,
@@ -59893,7 +60050,7 @@ function HomeView({
59893
60050
  }
59894
60051
  );
59895
60052
  }
59896
- var AuthenticatedHomeView = withAuth(React141__default.memo(HomeView));
60053
+ var AuthenticatedHomeView = withAuth(React142__default.memo(HomeView));
59897
60054
  var HomeView_default = HomeView;
59898
60055
  function withWorkspaceDisplayNames(Component3, options = {}) {
59899
60056
  const {
@@ -60076,6 +60233,295 @@ var lineDetailStore = {
60076
60233
  }
60077
60234
  };
60078
60235
 
60236
+ // src/lib/hooks/useLineDetailPageData.ts
60237
+ var buildLineInfoSnapshot = (lineDetails, metrics2) => {
60238
+ if (!lineDetails || !metrics2) {
60239
+ return null;
60240
+ }
60241
+ return {
60242
+ line_id: lineDetails.id,
60243
+ line_name: lineDetails.line_name,
60244
+ company_id: "",
60245
+ company_name: "",
60246
+ factory_id: lineDetails.factory_id,
60247
+ factory_name: lineDetails.factory.factory_name,
60248
+ shift_id: metrics2.shift_id ?? 0,
60249
+ date: metrics2.date || "",
60250
+ monitoring_mode: lineDetails.monitoring_mode ?? void 0,
60251
+ metrics: {
60252
+ avg_efficiency: metrics2.avg_efficiency ?? 0,
60253
+ avg_cycle_time: metrics2.avg_cycle_time ?? 0,
60254
+ current_output: metrics2.current_output ?? 0,
60255
+ ideal_output: metrics2.ideal_output ?? 0,
60256
+ total_workspaces: metrics2.total_workspaces ?? 0,
60257
+ underperforming_workspaces: metrics2.underperforming_workspaces ?? 0,
60258
+ underperforming_workspace_names: metrics2.underperforming_workspace_names || [],
60259
+ underperforming_workspace_uuids: metrics2.underperforming_workspace_uuids || [],
60260
+ output_array: metrics2.output_array || [],
60261
+ output_hourly: metrics2.output_hourly,
60262
+ line_threshold: metrics2.line_threshold ?? 0,
60263
+ threshold_pph: metrics2.threshold_pph ?? 0,
60264
+ shift_start: metrics2.shift_start || "06:00",
60265
+ shift_end: metrics2.shift_end || "14:00",
60266
+ last_updated: metrics2.last_updated || (/* @__PURE__ */ new Date()).toISOString(),
60267
+ poorest_performing_workspaces: metrics2.poorest_performing_workspaces || [],
60268
+ idle_time_hourly: metrics2.idle_time_hourly || null
60269
+ }
60270
+ };
60271
+ };
60272
+ var transformWorkspaceMetrics = (workspaceData, lineId, companyId, queryDate, queryShiftId) => (workspaceData || []).map((item) => ({
60273
+ company_id: item.company_id || companyId,
60274
+ line_id: item.line_id || lineId,
60275
+ shift_id: item.shift_id ?? queryShiftId,
60276
+ date: item.date || queryDate,
60277
+ workspace_uuid: item.workspace_id,
60278
+ workspace_name: item.workspace_name,
60279
+ action_count: item.total_output || 0,
60280
+ pph: item.avg_pph || 0,
60281
+ performance_score: item.performance_score || 0,
60282
+ avg_cycle_time: item.avg_cycle_time || 0,
60283
+ trend: item.trend_score === 1 ? 2 : 0,
60284
+ predicted_output: item.ideal_output || 0,
60285
+ efficiency: item.efficiency || 0,
60286
+ action_threshold: item.total_day_output || 0,
60287
+ idle_time: item.idle_time ?? void 0,
60288
+ idle_time_hourly: item.idle_time_hourly || null,
60289
+ shift_start: item.shift_start || void 0,
60290
+ shift_end: item.shift_end || void 0,
60291
+ monitoring_mode: item.monitoring_mode ?? void 0,
60292
+ assembly_enabled: item.assembly_enabled ?? false,
60293
+ video_grid_metric_mode: item.video_grid_metric_mode ?? void 0,
60294
+ action_type: item.action_type ?? void 0,
60295
+ action_family: item.action_family ?? void 0,
60296
+ action_display_name: item.action_display_name ?? void 0,
60297
+ recent_flow_percent: item.recent_flow_percent ?? null,
60298
+ recent_flow_window_minutes: item.recent_flow_window_minutes ?? null,
60299
+ recent_flow_effective_end_at: item.recent_flow_effective_end_at ?? null,
60300
+ recent_flow_computed_at: item.recent_flow_computed_at ?? null,
60301
+ incoming_wip_current: item.incoming_wip_current ?? null,
60302
+ incoming_wip_effective_at: item.incoming_wip_effective_at ?? null,
60303
+ incoming_wip_buffer_name: item.incoming_wip_buffer_name ?? null,
60304
+ show_exclamation: item.show_exclamation ?? void 0
60305
+ })).sort((a, b) => a.workspace_name.localeCompare(b.workspace_name));
60306
+ var transformLineDetails = (lineId, detailResponse) => {
60307
+ if (!detailResponse.line_details) {
60308
+ return null;
60309
+ }
60310
+ return {
60311
+ id: lineId,
60312
+ line_name: detailResponse.line_details.line_name || "Line",
60313
+ factory_id: detailResponse.line_details.factory_id || "",
60314
+ factory: {
60315
+ id: detailResponse.line_details.factory_id || "",
60316
+ factory_name: detailResponse.line_details.factory_name || ""
60317
+ },
60318
+ monitoring_mode: detailResponse.line_details.monitoring_mode ?? void 0
60319
+ };
60320
+ };
60321
+ var transformLineMetrics = (lineId, detailResponse, queryDate, queryShiftId) => {
60322
+ const poorestPerformingWorkspaces = detailResponse.poorest_performing_workspaces || [];
60323
+ const baseMetrics = detailResponse.line_metrics;
60324
+ if (!baseMetrics) {
60325
+ return {
60326
+ line_id: lineId,
60327
+ shift_id: queryShiftId,
60328
+ date: queryDate,
60329
+ factory_id: detailResponse.line_details?.factory_id || "",
60330
+ avg_efficiency: 0,
60331
+ avg_cycle_time: 0,
60332
+ current_output: 0,
60333
+ ideal_output: 0,
60334
+ total_workspaces: 0,
60335
+ underperforming_workspaces: 0,
60336
+ underperforming_workspace_names: [],
60337
+ underperforming_workspace_uuids: [],
60338
+ output_array: [],
60339
+ line_threshold: 0,
60340
+ threshold_pph: 0,
60341
+ shift_start: "06:00",
60342
+ shift_end: "14:00",
60343
+ last_updated: (/* @__PURE__ */ new Date()).toISOString(),
60344
+ poorest_performing_workspaces: poorestPerformingWorkspaces,
60345
+ idle_time_hourly: {}
60346
+ };
60347
+ }
60348
+ return {
60349
+ ...baseMetrics,
60350
+ line_id: lineId,
60351
+ shift_id: baseMetrics.shift_id ?? queryShiftId,
60352
+ date: baseMetrics.date ?? queryDate,
60353
+ factory_id: baseMetrics.factory_id ?? detailResponse.line_details?.factory_id ?? "",
60354
+ poorest_performing_workspaces: poorestPerformingWorkspaces
60355
+ };
60356
+ };
60357
+ var useLineDetailPageData = ({
60358
+ lineId,
60359
+ companyId,
60360
+ timezone,
60361
+ shiftConfig,
60362
+ date: urlDate,
60363
+ shiftId: urlShiftId,
60364
+ enabled = true
60365
+ }) => {
60366
+ const supabase = useSupabase();
60367
+ const { hydrateFromBackend } = useIdleTimeVlmConfig();
60368
+ const realtimeEnabled = enabled && urlDate === void 0 && urlShiftId === void 0;
60369
+ const { shiftKey: operationalShiftKey } = useOperationalShiftKey({
60370
+ enabled: realtimeEnabled,
60371
+ timezone,
60372
+ shiftConfig: shiftConfig || void 0
60373
+ });
60374
+ const currentShift = useMemo(
60375
+ () => shiftConfig ? getCurrentShift(timezone, shiftConfig) : null,
60376
+ [timezone, shiftConfig, operationalShiftKey]
60377
+ );
60378
+ const queryShiftId = useMemo(
60379
+ () => urlShiftId !== void 0 ? urlShiftId : currentShift?.shiftId ?? 0,
60380
+ [urlShiftId, currentShift]
60381
+ );
60382
+ const queryDate = useMemo(
60383
+ () => urlDate || getOperationalDate(timezone),
60384
+ [urlDate, timezone]
60385
+ );
60386
+ const [detailResponse, setDetailResponse] = useState(null);
60387
+ const [loading, setLoading] = useState(true);
60388
+ const [error, setError] = useState(null);
60389
+ const channelsRef = useRef([]);
60390
+ const requestIdRef = useRef(0);
60391
+ const fetchTimeoutRef = useRef(null);
60392
+ const fetchDetail = useCallback(async () => {
60393
+ if (!enabled || !supabase || !lineId || !companyId) {
60394
+ setLoading(false);
60395
+ if (!companyId) {
60396
+ setError({ message: "Company ID is not configured", code: "CONFIG_ERROR" });
60397
+ }
60398
+ return;
60399
+ }
60400
+ const requestId = requestIdRef.current + 1;
60401
+ requestIdRef.current = requestId;
60402
+ setLoading(true);
60403
+ setError(null);
60404
+ try {
60405
+ const nextDetail = await fetchLineDetail(supabase, {
60406
+ lineId,
60407
+ date: queryDate,
60408
+ shiftId: queryShiftId,
60409
+ companyId
60410
+ });
60411
+ if (requestId !== requestIdRef.current) {
60412
+ return;
60413
+ }
60414
+ hydrateFromBackend(nextDetail?.idle_time_vlm_by_line);
60415
+ setDetailResponse(nextDetail);
60416
+ const metrics3 = transformLineMetrics(lineId, nextDetail, queryDate, queryShiftId);
60417
+ const lineDetails2 = transformLineDetails(lineId, nextDetail);
60418
+ const workspaces2 = transformWorkspaceMetrics(
60419
+ nextDetail.workspace_metrics || [],
60420
+ lineId,
60421
+ companyId,
60422
+ queryDate,
60423
+ queryShiftId
60424
+ );
60425
+ const lineInfo2 = buildLineInfoSnapshot(lineDetails2, metrics3);
60426
+ if (lineInfo2) {
60427
+ lineDetailStore.setSnapshot(lineId, lineInfo2.date, lineInfo2.shift_id, {
60428
+ lineInfo: lineInfo2,
60429
+ workspaces: workspaces2
60430
+ });
60431
+ }
60432
+ } catch (err) {
60433
+ if (requestId !== requestIdRef.current) {
60434
+ return;
60435
+ }
60436
+ setError({ message: err.message, code: err.code || "FETCH_ERROR" });
60437
+ } finally {
60438
+ if (requestId === requestIdRef.current) {
60439
+ setLoading(false);
60440
+ }
60441
+ }
60442
+ }, [enabled, supabase, lineId, companyId, queryDate, queryShiftId, hydrateFromBackend]);
60443
+ const queueUpdate = useCallback(() => {
60444
+ if (fetchTimeoutRef.current) {
60445
+ clearTimeout(fetchTimeoutRef.current);
60446
+ }
60447
+ fetchTimeoutRef.current = setTimeout(() => {
60448
+ fetchDetail();
60449
+ fetchTimeoutRef.current = null;
60450
+ }, 300);
60451
+ }, [fetchDetail]);
60452
+ useEffect(() => {
60453
+ if (!enabled) {
60454
+ setLoading(false);
60455
+ return;
60456
+ }
60457
+ fetchDetail();
60458
+ }, [enabled, fetchDetail]);
60459
+ useEffect(() => {
60460
+ channelsRef.current.forEach((channel) => {
60461
+ supabase.removeChannel(channel);
60462
+ });
60463
+ channelsRef.current = [];
60464
+ if (!supabase || !companyId || !lineId || !realtimeEnabled) {
60465
+ return;
60466
+ }
60467
+ const metricsTable = `${getMetricsTablePrefix()}_${companyId.replace(/-/g, "_")}`;
60468
+ const timestamp = Date.now();
60469
+ const currentDate = queryDate;
60470
+ const currentShiftId = queryShiftId;
60471
+ const lineFilter = `line_id=eq.${lineId}`;
60472
+ const createChannel = (name, table, filter2) => supabase.channel(`${name}-${timestamp}`).on(
60473
+ "postgres_changes",
60474
+ { event: "*", schema: "public", table, filter: filter2 },
60475
+ (payload) => {
60476
+ const payloadData = payload.new || payload.old;
60477
+ if (payloadData?.date !== currentDate || payloadData?.shift_id !== currentShiftId) {
60478
+ return;
60479
+ }
60480
+ queueUpdate();
60481
+ }
60482
+ ).subscribe();
60483
+ channelsRef.current = [
60484
+ createChannel("line-detail-line-metrics", "line_metrics", lineFilter),
60485
+ createChannel("line-detail-performance-metrics", metricsTable, lineFilter),
60486
+ createChannel("line-detail-wip-buffer-metrics", "wip_buffer_metrics", lineFilter)
60487
+ ];
60488
+ return () => {
60489
+ if (fetchTimeoutRef.current) {
60490
+ clearTimeout(fetchTimeoutRef.current);
60491
+ fetchTimeoutRef.current = null;
60492
+ }
60493
+ channelsRef.current.forEach((channel) => {
60494
+ supabase.removeChannel(channel);
60495
+ });
60496
+ channelsRef.current = [];
60497
+ };
60498
+ }, [supabase, companyId, lineId, realtimeEnabled, queryDate, queryShiftId, queueUpdate]);
60499
+ const metrics2 = useMemo(
60500
+ () => detailResponse ? transformLineMetrics(lineId, detailResponse, queryDate, queryShiftId) : null,
60501
+ [detailResponse, lineId, queryDate, queryShiftId]
60502
+ );
60503
+ const lineDetails = useMemo(
60504
+ () => detailResponse ? transformLineDetails(lineId, detailResponse) : null,
60505
+ [detailResponse, lineId]
60506
+ );
60507
+ const workspaces = useMemo(
60508
+ () => detailResponse && companyId ? transformWorkspaceMetrics(detailResponse.workspace_metrics || [], lineId, companyId, queryDate, queryShiftId) : [],
60509
+ [detailResponse, companyId, lineId, queryDate, queryShiftId]
60510
+ );
60511
+ const lineInfo = useMemo(() => buildLineInfoSnapshot(lineDetails, metrics2), [lineDetails, metrics2]);
60512
+ return {
60513
+ detailResponse,
60514
+ lineDetails,
60515
+ metrics: metrics2,
60516
+ workspaces,
60517
+ lineInfo,
60518
+ issueResolutionSummary: detailResponse?.issue_resolution_summary ?? null,
60519
+ loading,
60520
+ error,
60521
+ refresh: () => fetchDetail()
60522
+ };
60523
+ };
60524
+
60079
60525
  // src/lib/services/efficiencyLegendService.ts
60080
60526
  var EfficiencyLegendService = class {
60081
60527
  // 5 minutes
@@ -60670,21 +61116,45 @@ var formatLocalDate = (date) => {
60670
61116
  };
60671
61117
  return date.toLocaleDateString("en-US", options);
60672
61118
  };
61119
+ var formatResolutionDuration = (seconds) => {
61120
+ if (seconds === null || seconds === void 0 || seconds <= 0) {
61121
+ return "-";
61122
+ }
61123
+ return formatIdleTime(Math.max(0, Math.floor(seconds)));
61124
+ };
61125
+ var getIssueResolutionSecondaryText = (summary) => {
61126
+ if (!summary) {
61127
+ return "No issue data";
61128
+ }
61129
+ const parts = [`${summary.resolved_issue_count} resolved`];
61130
+ if ((summary.open_issue_count || 0) > 0) {
61131
+ parts.push(`oldest open ${formatResolutionDuration(summary.oldest_open_issue_age_seconds)}`);
61132
+ }
61133
+ return parts.join(" \u2022 ");
61134
+ };
60673
61135
  var MetricCards = memo$1(({
60674
61136
  lineInfo,
61137
+ issueResolutionSummary,
60675
61138
  idleTimeData,
60676
61139
  showIdleTime,
60677
61140
  efficiencyLegend
60678
61141
  }) => {
60679
61142
  const efficiency = lineInfo?.metrics.avg_efficiency || 0;
60680
61143
  const efficiencyColorClass = getEfficiencyTextColorClasses(efficiency, efficiencyLegend);
61144
+ const showIssueResolutionCard = Boolean(issueResolutionSummary);
61145
+ const largeGridColumns = showIdleTime ? showIssueResolutionCard ? "lg:grid-cols-5" : "lg:grid-cols-4" : showIssueResolutionCard ? "lg:grid-cols-4" : "lg:grid-cols-3";
61146
+ const shouldMaskIssueResolution = efficiency < 5;
61147
+ const issueResolutionValue = shouldMaskIssueResolution ? "-" : formatResolutionDuration(
61148
+ issueResolutionSummary?.mean_resolution_seconds ?? issueResolutionSummary?.median_resolution_seconds
61149
+ );
61150
+ getIssueResolutionSecondaryText(issueResolutionSummary);
60681
61151
  return /* @__PURE__ */ jsxs(
60682
61152
  motion.div,
60683
61153
  {
60684
61154
  variants: containerVariants,
60685
61155
  initial: "initial",
60686
61156
  animate: "animate",
60687
- className: `grid grid-cols-1 sm:grid-cols-2 ${showIdleTime ? "lg:grid-cols-4" : "lg:grid-cols-3"} gap-3 sm:gap-4 mb-2 h-auto lg:flex-[2] lg:min-h-[250px]`,
61157
+ className: `grid grid-cols-1 sm:grid-cols-2 ${largeGridColumns} gap-3 sm:gap-4 mb-2 h-auto lg:flex-[2] lg:min-h-[250px]`,
60688
61158
  children: [
60689
61159
  /* @__PURE__ */ jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
60690
61160
  /* @__PURE__ */ jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 mb-2 text-center", children: "Line Output" }),
@@ -60713,6 +61183,28 @@ var MetricCards = memo$1(({
60713
61183
  "%"
60714
61184
  ] }) })
60715
61185
  ] }),
61186
+ showIssueResolutionCard && /* @__PURE__ */ jsxs(
61187
+ motion.div,
61188
+ {
61189
+ variants: itemVariants,
61190
+ className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 h-[240px] sm:h-[260px] md:h-auto",
61191
+ children: [
61192
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-1.5 mb-2 relative group z-10", children: [
61193
+ /* @__PURE__ */ jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700", children: "Average Issue Resolution Time" }),
61194
+ /* @__PURE__ */ jsx(InformationCircleIcon, { className: "w-4 h-4 text-gray-400 cursor-help" }),
61195
+ /* @__PURE__ */ jsxs("div", { className: "absolute top-full left-1/2 transform -translate-x-1/2 mt-2.5 w-[260px] p-3 bg-white rounded-lg shadow-xl border border-gray-200 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 pointer-events-none z-50", children: [
61196
+ /* @__PURE__ */ jsx("p", { className: "text-center text-xs text-gray-600 leading-relaxed mb-2.5 px-1", children: "The average time a supervisor takes to resolve a workstation in red." }),
61197
+ /* @__PURE__ */ jsx("div", { className: "bg-gray-50 rounded-md py-1.5 border border-gray-100/80", children: /* @__PURE__ */ jsxs("p", { className: "text-center font-medium text-[11px] text-gray-500", children: [
61198
+ ((issueResolutionSummary?.resolved_issue_count || 0) + (issueResolutionSummary?.open_issue_count || 0)).toLocaleString(),
61199
+ " recorded issues"
61200
+ ] }) }),
61201
+ /* @__PURE__ */ jsx("div", { className: "absolute -top-1.5 left-1/2 transform -translate-x-1/2 w-3 h-3 bg-white border-l border-t border-gray-200 rotate-45" })
61202
+ ] })
61203
+ ] }),
61204
+ /* @__PURE__ */ jsx("div", { className: "h-[calc(100%-2.5rem)] flex flex-col items-center justify-center gap-3", children: /* @__PURE__ */ jsx("span", { className: `text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-bold ${shouldMaskIssueResolution ? "text-gray-400" : "text-gray-900"}`, children: issueResolutionValue }) })
61205
+ ]
61206
+ }
61207
+ ),
60716
61208
  showIdleTime && /* @__PURE__ */ jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
60717
61209
  /* @__PURE__ */ jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center mb-2", children: "Idle Time Breakdown" }),
60718
61210
  /* @__PURE__ */ jsx("div", { className: "h-[calc(100%-2.5rem)]", children: /* @__PURE__ */ jsx(
@@ -60733,6 +61225,8 @@ var MetricCards = memo$1(({
60733
61225
  if (prevProps.efficiencyLegend !== nextProps.efficiencyLegend) return false;
60734
61226
  const prevMetrics = prevProps.lineInfo.metrics;
60735
61227
  const nextMetrics = nextProps.lineInfo.metrics;
61228
+ const prevIssueSummary = prevProps.issueResolutionSummary;
61229
+ const nextIssueSummary = nextProps.issueResolutionSummary;
60736
61230
  const prevIdleChartSignature = JSON.stringify(
60737
61231
  (prevProps.idleTimeData?.chartData || []).map((entry) => ({
60738
61232
  name: entry.name,
@@ -60751,6 +61245,9 @@ var MetricCards = memo$1(({
60751
61245
  );
60752
61246
  const idleTimeChanged = prevProps.idleTimeData?.isLoading !== nextProps.idleTimeData?.isLoading || prevProps.idleTimeData?.error !== nextProps.idleTimeData?.error || prevIdleChartSignature !== nextIdleChartSignature || prevProps.idleTimeData?.data?.total_idle_time_seconds !== nextProps.idleTimeData?.data?.total_idle_time_seconds || prevProps.idleTimeData?.data?.scope_work_seconds !== nextProps.idleTimeData?.data?.scope_work_seconds;
60753
61247
  if (idleTimeChanged) return false;
61248
+ if (prevIssueSummary?.mean_resolution_seconds !== nextIssueSummary?.mean_resolution_seconds || prevIssueSummary?.median_resolution_seconds !== nextIssueSummary?.median_resolution_seconds || prevIssueSummary?.resolved_issue_count !== nextIssueSummary?.resolved_issue_count || prevIssueSummary?.open_issue_count !== nextIssueSummary?.open_issue_count || prevIssueSummary?.oldest_open_issue_age_seconds !== nextIssueSummary?.oldest_open_issue_age_seconds || prevIssueSummary?.total_issue_seconds !== nextIssueSummary?.total_issue_seconds) {
61249
+ return false;
61250
+ }
60754
61251
  return prevMetrics.current_output === nextMetrics.current_output && prevMetrics.line_threshold === nextMetrics.line_threshold && prevMetrics.underperforming_workspaces === nextMetrics.underperforming_workspaces && prevMetrics.total_workspaces === nextMetrics.total_workspaces && prevMetrics.avg_efficiency === nextMetrics.avg_efficiency;
60755
61252
  });
60756
61253
  MetricCards.displayName = "MetricCards";
@@ -61257,11 +61754,16 @@ var KPIDetailView = ({
61257
61754
  const {
61258
61755
  metrics: metrics2,
61259
61756
  lineDetails,
61260
- loading: lineMetricsLoading,
61261
- error: lineMetricsError,
61262
- refreshMetrics
61263
- } = useRealtimeLineMetrics({
61757
+ workspaces,
61758
+ issueResolutionSummary,
61759
+ loading: lineDetailLoading,
61760
+ error: lineDetailError,
61761
+ refresh: refreshLineDetail
61762
+ } = useLineDetailPageData({
61264
61763
  lineId,
61764
+ companyId: resolvedCompanyId,
61765
+ timezone: configuredTimezone,
61766
+ shiftConfig,
61265
61767
  date: typeof urlDate === "string" ? urlDate : void 0,
61266
61768
  shiftId: parsedShiftId,
61267
61769
  enabled: !isShiftConfigLoading && (!historicalRouteRequested || historicalParamsReady)
@@ -61269,16 +61771,11 @@ var KPIDetailView = ({
61269
61771
  const resolvedMonitoringMode = lineDetails?.monitoring_mode ?? "output";
61270
61772
  const isUptimeMode = resolvedMonitoringMode === "uptime";
61271
61773
  const overviewTabLabel = isUptimeMode ? "Utilization" : "Efficiency";
61272
- const {
61273
- workspaces,
61274
- loading: workspacesLoading,
61275
- error: workspacesError,
61276
- refreshWorkspaces
61277
- } = useLineWorkspaceMetrics(lineId, {
61278
- initialDate: typeof urlDate === "string" ? urlDate : void 0,
61279
- initialShiftId: parsedShiftId,
61280
- enabled: !isShiftConfigLoading && (!historicalRouteRequested || historicalParamsReady)
61281
- });
61774
+ const lineMetricsLoading = lineDetailLoading;
61775
+ const workspacesLoading = lineDetailLoading;
61776
+ const lineMetricsError = lineDetailError;
61777
+ const workspacesError = lineDetailError;
61778
+ const refreshMetrics = refreshLineDetail;
61282
61779
  const idleTimeDate = historicalRouteRequested ? historicalParamsReady ? urlDate : void 0 : typeof urlDate === "string" ? urlDate : metrics2?.date || cachedLineInfo?.date;
61283
61780
  const idleTimeShiftId = historicalRouteRequested ? historicalParamsReady ? parsedShiftId : void 0 : parsedShiftId ?? metrics2?.shift_id ?? cachedLineInfo?.shift_id;
61284
61781
  const idleTimeEnabled = activeTab === "overview" && !!lineId && idleTimeVlmEnabled && !!idleTimeDate && idleTimeShiftId !== void 0 && (!historicalRouteRequested || historicalParamsReady);
@@ -61994,7 +62491,6 @@ var KPIDetailView = ({
61994
62491
  {
61995
62492
  onClick: () => {
61996
62493
  refreshMetrics();
61997
- refreshWorkspaces();
61998
62494
  },
61999
62495
  className: "mt-4 px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2",
62000
62496
  children: "Try Again"
@@ -62021,7 +62517,7 @@ var KPIDetailView = ({
62021
62517
  return /* @__PURE__ */ jsx(LoadingPage, { message: "Processing line data..." });
62022
62518
  }
62023
62519
  return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-gray-50 flex flex-col", children: [
62024
- /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-10 bg-white border-b flex-shrink-0 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3", children: [
62520
+ /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-40 bg-white border-b flex-shrink-0 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3", children: [
62025
62521
  /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
62026
62522
  /* @__PURE__ */ jsx(
62027
62523
  "button",
@@ -62197,7 +62693,7 @@ var KPIDetailView = ({
62197
62693
  )
62198
62694
  ] }),
62199
62695
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 ml-auto", children: [
62200
- resolvedLineInfo && activeTab === "overview" && /* @__PURE__ */ jsx(LinePdfGenerator, { lineInfo: resolvedLineInfo, workspaceData: resolvedWorkspaces || [], shiftName: getShiftName(resolvedLineInfo.shift_id) }),
62696
+ resolvedLineInfo && activeTab === "overview" && /* @__PURE__ */ jsx(LinePdfGenerator, { lineInfo: resolvedLineInfo, workspaceData: resolvedWorkspaces || [], issueResolutionSummary, shiftName: getShiftName(resolvedLineInfo.shift_id) }),
62201
62697
  activeTab === "monthly_history" && !urlDate && !urlShift && /* @__PURE__ */ jsxs(Fragment, { children: [
62202
62698
  /* @__PURE__ */ jsx(
62203
62699
  MonthlyRangeFilter_default,
@@ -62256,6 +62752,7 @@ var KPIDetailView = ({
62256
62752
  MetricCards,
62257
62753
  {
62258
62754
  lineInfo: resolvedLineInfo,
62755
+ issueResolutionSummary,
62259
62756
  idleTimeData,
62260
62757
  showIdleTime: idleTimeVlmEnabled,
62261
62758
  efficiencyLegend
@@ -62353,6 +62850,7 @@ var KPIDetailView = ({
62353
62850
  MetricCards,
62354
62851
  {
62355
62852
  lineInfo: resolvedLineInfo,
62853
+ issueResolutionSummary,
62356
62854
  idleTimeData,
62357
62855
  showIdleTime: idleTimeVlmEnabled,
62358
62856
  efficiencyLegend
@@ -62522,18 +63020,18 @@ var LinesLeaderboard = ({
62522
63020
  isHistoricalDaily
62523
63021
  }) => {
62524
63022
  const formatEfficiency = (value) => typeof value === "number" && Number.isFinite(value) ? `${value.toFixed(1)}%` : "--";
62525
- const assignedLineIdSet = React141__default.useMemo(
63023
+ const assignedLineIdSet = React142__default.useMemo(
62526
63024
  () => new Set(assignedLineIds || []),
62527
63025
  [assignedLineIds]
62528
63026
  );
62529
- const canClickLine = React141__default.useCallback(
63027
+ const canClickLine = React142__default.useCallback(
62530
63028
  (lineId) => {
62531
63029
  if (!assignedLineIds) return true;
62532
63030
  return assignedLineIdSet.has(lineId);
62533
63031
  },
62534
63032
  [assignedLineIds, assignedLineIdSet]
62535
63033
  );
62536
- const handleTimeRangeChange = React141__default.useCallback((newRange) => {
63034
+ const handleTimeRangeChange = React142__default.useCallback((newRange) => {
62537
63035
  if (newRange === timeRange) return;
62538
63036
  trackCoreEvent("Leaderboard Time Range Changed", {
62539
63037
  from_range: timeRange,
@@ -62544,7 +63042,7 @@ var LinesLeaderboard = ({
62544
63042
  });
62545
63043
  setTimeRange(newRange);
62546
63044
  }, [timeRange, lines.length, monthlyEfficiencyByLineId, setTimeRange]);
62547
- const handleLeaderboardLineClick = React141__default.useCallback((item, clickSource) => {
63045
+ const handleLeaderboardLineClick = React142__default.useCallback((item, clickSource) => {
62548
63046
  if (!canClickLine(item.line.id)) return;
62549
63047
  trackCoreEvent("Leaderboard Line Clicked", {
62550
63048
  line_id: item.line.id,
@@ -62558,8 +63056,8 @@ var LinesLeaderboard = ({
62558
63056
  });
62559
63057
  onLineClick(item.line);
62560
63058
  }, [canClickLine, onLineClick, timeRange]);
62561
- const viewLoadedTrackedRef = React141__default.useRef(null);
62562
- const leaderboardData = React141__default.useMemo(() => {
63059
+ const viewLoadedTrackedRef = React142__default.useRef(null);
63060
+ const leaderboardData = React142__default.useMemo(() => {
62563
63061
  const loading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
62564
63062
  const efficiencyMap = timeRange === "today" ? todayEfficiencyByLineId : monthlyEfficiencyByLineId;
62565
63063
  return lines.map((line) => {
@@ -62590,7 +63088,7 @@ var LinesLeaderboard = ({
62590
63088
  isLoadingToday,
62591
63089
  isLoadingMonthly
62592
63090
  ]);
62593
- React141__default.useEffect(() => {
63091
+ React142__default.useEffect(() => {
62594
63092
  const isLoading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
62595
63093
  const trackingKey = `${timeRange}-${leaderboardData.length}`;
62596
63094
  if (leaderboardData.length > 0 && !isLoading && viewLoadedTrackedRef.current !== trackingKey) {
@@ -62616,7 +63114,7 @@ var LinesLeaderboard = ({
62616
63114
  const countdownFormat = timeRange === "monthly" ? "days" : "clock";
62617
63115
  const countdownFinishedLabel = timeRange === "monthly" ? "Finished" : "Shift Ended";
62618
63116
  const showCountdown = timeRange === "monthly" || !isHistoricalDaily;
62619
- const handleCountdownFinished = React141__default.useCallback(() => {
63117
+ const handleCountdownFinished = React142__default.useCallback(() => {
62620
63118
  trackCoreEvent("Leaderboard Countdown Finished", {
62621
63119
  countdown_type: timeRange === "monthly" ? "month_end" : "shift_end",
62622
63120
  time_range: timeRange,
@@ -62643,7 +63141,7 @@ var LinesLeaderboard = ({
62643
63141
  return "bg-white border-gray-100";
62644
63142
  }
62645
63143
  };
62646
- React141__default.useEffect(() => {
63144
+ React142__default.useEffect(() => {
62647
63145
  const style = document.createElement("style");
62648
63146
  style.innerHTML = `
62649
63147
  @keyframes float {
@@ -62830,7 +63328,7 @@ var LineCard = ({
62830
63328
  supervisors
62831
63329
  }) => {
62832
63330
  const isUptimeLine = (line.monitoring_mode ?? "output") === "uptime";
62833
- const isOnTrack = React141__default.useMemo(() => {
63331
+ const isOnTrack = React142__default.useMemo(() => {
62834
63332
  if (!kpis) return null;
62835
63333
  return isEfficiencyOnTrack(kpis.efficiency.value);
62836
63334
  }, [kpis]);
@@ -62988,6 +63486,9 @@ var KPIsOverviewView = ({
62988
63486
  const [selectedLeaderboardShiftId, setSelectedLeaderboardShiftId] = useState(0);
62989
63487
  const [hasHydratedLeaderboardRouteState, setHasHydratedLeaderboardRouteState] = useState(false);
62990
63488
  const [loading, setLoading] = useState(true);
63489
+ const [isFilterOpen, setIsFilterOpen] = useState(false);
63490
+ const filterRef = useRef(null);
63491
+ const filterButtonRef = useRef(null);
62991
63492
  const [error, setError] = useState(null);
62992
63493
  const [topPerformer, setTopPerformer] = useState({
62993
63494
  name: "Top Performer",
@@ -63025,46 +63526,46 @@ var KPIsOverviewView = ({
63025
63526
  const configuredTimezone = dbTimezone || dateTimeConfig.defaultTimezone || "UTC";
63026
63527
  const { startDate: monthStartDate, endDate: monthEndDateKey, monthEndDate } = getMonthDateInfo(configuredTimezone);
63027
63528
  const isSuperAdmin = user?.scope_mode === "SUPER_ADMIN" || !!user?.access_scope?.is_super_admin;
63028
- const scopedLineIds = React141__default.useMemo(
63529
+ const scopedLineIds = React142__default.useMemo(
63029
63530
  () => Array.isArray(user?.access_scope?.line_ids) ? user.access_scope.line_ids.filter((lineId) => typeof lineId === "string" && lineId.length > 0) : [],
63030
63531
  [user?.access_scope?.line_ids]
63031
63532
  );
63032
63533
  const hasCanonicalScope = !!user?.scope_mode || !!user?.access_scope;
63033
63534
  const scopeRole = (user?.role_level || user?.role || "").toLowerCase();
63034
63535
  const isStrictLineScopedRole = scopeRole === "supervisor" || isFactoryScopedRole(scopeRole);
63035
- const resolvedAssignedLineIds = React141__default.useMemo(() => {
63536
+ const resolvedAssignedLineIds = React142__default.useMemo(() => {
63036
63537
  if (isSuperAdmin) return [];
63037
63538
  if (scopedLineIds.length > 0) return scopedLineIds;
63038
63539
  if (lineIds && lineIds.length > 0) return lineIds;
63039
63540
  if (isStrictLineScopedRole && hasCanonicalScope) return [];
63040
63541
  return [];
63041
63542
  }, [isSuperAdmin, scopedLineIds, lineIds, isStrictLineScopedRole, hasCanonicalScope]);
63042
- const assignedLineIdSet = React141__default.useMemo(
63543
+ const assignedLineIdSet = React142__default.useMemo(
63043
63544
  () => new Set(resolvedAssignedLineIds),
63044
63545
  [resolvedAssignedLineIds]
63045
63546
  );
63046
- const metricsLineIds = React141__default.useMemo(() => {
63547
+ const metricsLineIds = React142__default.useMemo(() => {
63047
63548
  if (isSuperAdmin) {
63048
63549
  return lineIds ?? [];
63049
63550
  }
63050
63551
  return resolvedAssignedLineIds;
63051
63552
  }, [isSuperAdmin, lineIds, resolvedAssignedLineIds]);
63052
63553
  const assignedLineIdsForLeaderboard = isSuperAdmin ? void 0 : resolvedAssignedLineIds;
63053
- const leaderboardLinesForView = React141__default.useMemo(() => {
63554
+ const leaderboardLinesForView = React142__default.useMemo(() => {
63054
63555
  const targetMode = viewType === "machine" ? "uptime" : "output";
63055
63556
  return leaderboardLines.filter((line) => (line.monitoring_mode ?? "output") === targetMode);
63056
63557
  }, [leaderboardLines, viewType]);
63057
- const linesForView = React141__default.useMemo(() => {
63558
+ const linesForView = React142__default.useMemo(() => {
63058
63559
  const targetMode = viewType === "machine" ? "uptime" : "output";
63059
63560
  return lines.filter((line) => (line.monitoring_mode ?? "output") === targetMode);
63060
63561
  }, [lines, viewType]);
63061
- const relevantLinesForMode = React141__default.useMemo(() => {
63562
+ const relevantLinesForMode = React142__default.useMemo(() => {
63062
63563
  if (activeTab === "leaderboard") {
63063
63564
  return leaderboardLines.length > 0 ? leaderboardLines : lines;
63064
63565
  }
63065
63566
  return lines;
63066
63567
  }, [activeTab, leaderboardLines, lines]);
63067
- const { hasUptime, hasOutput } = React141__default.useMemo(() => {
63568
+ const { hasUptime, hasOutput } = React142__default.useMemo(() => {
63068
63569
  let uptime = false;
63069
63570
  let output = false;
63070
63571
  for (const line of relevantLinesForMode) {
@@ -63089,11 +63590,32 @@ var KPIsOverviewView = ({
63089
63590
  const currentShiftDetails = getCurrentShift(configuredTimezone, shiftConfig);
63090
63591
  const currentShiftDate = currentShiftDetails.date;
63091
63592
  const currentShiftId = currentShiftDetails.shiftId;
63092
- const shiftEndDate = React141__default.useMemo(
63593
+ const activeFiltersCount = React142__default.useMemo(() => {
63594
+ let count = 0;
63595
+ if (selectedLeaderboardShiftId !== currentShiftId) {
63596
+ count++;
63597
+ }
63598
+ return count;
63599
+ }, [selectedLeaderboardShiftId, currentShiftId]);
63600
+ const clearFilters = React142__default.useCallback(() => {
63601
+ setSelectedLeaderboardShiftId(currentShiftId);
63602
+ }, [currentShiftId]);
63603
+ useEffect(() => {
63604
+ const handleClickOutside = (event) => {
63605
+ const target = event.target;
63606
+ if (filterButtonRef.current?.contains(target)) return;
63607
+ if (filterRef.current && !filterRef.current.contains(target)) {
63608
+ setIsFilterOpen(false);
63609
+ }
63610
+ };
63611
+ document.addEventListener("mousedown", handleClickOutside);
63612
+ return () => document.removeEventListener("mousedown", handleClickOutside);
63613
+ }, []);
63614
+ const shiftEndDate = React142__default.useMemo(
63093
63615
  () => getShiftEndDate(currentShiftDetails, configuredTimezone),
63094
63616
  [currentShiftDetails, configuredTimezone]
63095
63617
  );
63096
- const leaderboardShiftOptions = React141__default.useMemo(() => {
63618
+ const leaderboardShiftOptions = React142__default.useMemo(() => {
63097
63619
  if (shiftConfig?.shifts && shiftConfig.shifts.length > 0) {
63098
63620
  return shiftConfig.shifts.map((shift) => ({
63099
63621
  id: shift.shiftId,
@@ -63173,15 +63695,15 @@ var KPIsOverviewView = ({
63173
63695
  lineId: factoryViewId,
63174
63696
  userAccessibleLineIds: metricsLineIds
63175
63697
  });
63176
- const defaultKPIs = React141__default.useMemo(() => createDefaultKPIs(), []);
63177
- const kpisByLineId = React141__default.useMemo(() => {
63698
+ const defaultKPIs = React142__default.useMemo(() => createDefaultKPIs(), []);
63699
+ const kpisByLineId = React142__default.useMemo(() => {
63178
63700
  const map = /* @__PURE__ */ new Map();
63179
63701
  lineMetrics.forEach((row) => {
63180
63702
  if (row?.line_id) map.set(row.line_id, buildKPIsFromLineMetricsRow(row));
63181
63703
  });
63182
63704
  return map;
63183
63705
  }, [lineMetrics]);
63184
- const supervisorLineIds = React141__default.useMemo(
63706
+ const supervisorLineIds = React142__default.useMemo(
63185
63707
  () => (leaderboardLines.length > 0 ? leaderboardLines : lines).map((l) => l.id),
63186
63708
  [leaderboardLines, lines]
63187
63709
  );
@@ -63544,7 +64066,7 @@ var KPIsOverviewView = ({
63544
64066
  }
63545
64067
  if (error) {
63546
64068
  return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-gray-50 flex flex-col", children: [
63547
- /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-10 bg-white border-b flex-shrink-0 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3", children: [
64069
+ /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-40 bg-white border-b flex-shrink-0 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3", children: [
63548
64070
  /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
63549
64071
  mobileMenuContext && /* @__PURE__ */ jsx(
63550
64072
  HamburgerButton,
@@ -63580,7 +64102,7 @@ var KPIsOverviewView = ({
63580
64102
  }
63581
64103
  if (lines.length === 0) {
63582
64104
  return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-gray-50 flex flex-col", children: [
63583
- /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-10 bg-white border-b flex-shrink-0 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3", children: [
64105
+ /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-40 bg-white border-b flex-shrink-0 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3", children: [
63584
64106
  /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
63585
64107
  mobileMenuContext && /* @__PURE__ */ jsx(
63586
64108
  HamburgerButton,
@@ -63618,7 +64140,7 @@ var KPIsOverviewView = ({
63618
64140
  ] });
63619
64141
  }
63620
64142
  return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-gray-50 flex flex-col", children: [
63621
- /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-10 bg-white border-b flex-shrink-0", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3", children: [
64143
+ /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-40 bg-white border-b flex-shrink-0", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3", children: [
63622
64144
  /* @__PURE__ */ jsxs("div", { className: "sm:hidden", children: [
63623
64145
  /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
63624
64146
  mobileMenuContext && /* @__PURE__ */ jsx(
@@ -63630,12 +64152,7 @@ var KPIsOverviewView = ({
63630
64152
  ),
63631
64153
  /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
63632
64154
  /* @__PURE__ */ jsx("h1", { className: "text-lg font-semibold text-gray-900", children: activeTab === "leaderboard" ? "Leaderboard" : "Overview" }),
63633
- /* @__PURE__ */ jsx(
63634
- "div",
63635
- {
63636
- className: `h-2 w-2 rounded-full ring-2 ${showHistoricalLeaderboardHeader ? "bg-amber-500 ring-amber-500/20" : "bg-emerald-500 animate-pulse ring-emerald-500/20"}`
63637
- }
63638
- )
64155
+ !showHistoricalLeaderboardHeader && /* @__PURE__ */ jsx("div", { className: "h-2 w-2 rounded-full bg-emerald-500 animate-pulse ring-2 ring-emerald-500/20" })
63639
64156
  ] }) }),
63640
64157
  /* @__PURE__ */ jsx("div", { className: "w-12" })
63641
64158
  ] }),
@@ -63646,9 +64163,23 @@ var KPIsOverviewView = ({
63646
64163
  /* @__PURE__ */ jsx("div", { className: "text-gray-700 scale-90", children: getShiftIcon2(headerShiftId) }),
63647
64164
  /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-700", children: headerShiftName })
63648
64165
  ] }),
63649
- showHistoricalLeaderboardHeader ? /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-1 px-2.5 py-1 bg-amber-50 text-amber-700 rounded-full", children: [
63650
- /* @__PURE__ */ jsx(Clock, { className: "w-3 h-3" }),
63651
- /* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: "Historical" })
64166
+ showHistoricalLeaderboardHeader ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
64167
+ /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-1 px-2.5 py-1 bg-amber-50 text-amber-700 rounded-full", children: [
64168
+ /* @__PURE__ */ jsx(Clock, { className: "w-3 h-3" }),
64169
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: "Historical" })
64170
+ ] }),
64171
+ activeTab === "leaderboard" && isHistoricalLeaderboardDaily && /* @__PURE__ */ jsx(
64172
+ "button",
64173
+ {
64174
+ type: "button",
64175
+ onClick: () => {
64176
+ setSelectedLeaderboardDate(currentShiftDate);
64177
+ setSelectedLeaderboardShiftId(currentShiftId);
64178
+ },
64179
+ className: "text-[10px] font-medium text-blue-600 hover:text-blue-700 hover:underline bg-blue-50 px-2 py-1 rounded-md",
64180
+ children: "Return to Live"
64181
+ }
64182
+ )
63652
64183
  ] }) : /* @__PURE__ */ jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-green-100 rounded-full", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-green-700", children: /* @__PURE__ */ jsx(ISTTimer_default, {}) }) })
63653
64184
  ] })
63654
64185
  ] }),
@@ -63750,79 +64281,88 @@ var KPIsOverviewView = ({
63750
64281
  ) }),
63751
64282
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
63752
64283
  /* @__PURE__ */ jsx("h1", { className: "text-2xl md:text-3xl lg:text-4xl font-semibold text-gray-900 tracking-tight", children: activeTab === "leaderboard" ? "Leaderboard" : "Overview" }),
63753
- /* @__PURE__ */ jsx(
63754
- "div",
63755
- {
63756
- className: `h-2.5 w-2.5 rounded-full ring-4 flex-shrink-0 ${showHistoricalLeaderboardHeader ? "bg-amber-500 ring-amber-500/10" : "bg-emerald-500 animate-pulse ring-emerald-500/10"}`
63757
- }
63758
- )
64284
+ !showHistoricalLeaderboardHeader && /* @__PURE__ */ jsx("div", { className: "h-2.5 w-2.5 rounded-full ring-4 flex-shrink-0 bg-emerald-500 animate-pulse ring-emerald-500/10" })
63759
64285
  ] }),
63760
- !topPerformerLoading && activeTab !== "leaderboard" && /* @__PURE__ */ jsx("div", { className: "absolute right-0 top-1/2 -translate-y-1/2 z-10", children: /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-2xl border border-amber-200 shadow-md pl-1.5 pr-4 py-1.5 flex items-center gap-4 transition-all hover:shadow-lg hover:border-amber-300 group", children: [
63761
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
63762
- (!topPerformer.supervisors || topPerformer.supervisors.length <= 1) && /* @__PURE__ */ jsx("div", { className: "w-10 h-10 rounded-full ring-2 ring-amber-100 overflow-hidden bg-amber-50 shadow-inner flex-shrink-0 transition-transform group-hover:scale-105", children: showTopPerformerImage ? /* @__PURE__ */ jsx(
63763
- "img",
63764
- {
63765
- src: topPerformer.imageUrl || "",
63766
- alt: topPerformer.name,
63767
- className: "w-full h-full object-cover",
63768
- onError: () => setTopPerformerImageError(true)
63769
- }
63770
- ) : /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-sm font-bold text-amber-600 uppercase", children: topPerformer.initials }) }),
63771
- topPerformer.supervisors && topPerformer.supervisors.length > 1 && /* @__PURE__ */ jsxs("div", { className: "flex -space-x-2", children: [
63772
- topPerformer.supervisors.slice(0, 3).map((supervisor, idx) => /* @__PURE__ */ jsxs(
63773
- "div",
64286
+ /* @__PURE__ */ jsxs("div", { className: "absolute right-0 top-1/2 -translate-y-1/2 z-10 flex items-center", children: [
64287
+ !topPerformerLoading && activeTab !== "leaderboard" && /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-2xl border border-amber-200 shadow-md pl-1.5 pr-4 py-1.5 flex items-center gap-4 transition-all hover:shadow-lg hover:border-amber-300 group", children: [
64288
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
64289
+ (!topPerformer.supervisors || topPerformer.supervisors.length <= 1) && /* @__PURE__ */ jsx("div", { className: "w-10 h-10 rounded-full ring-2 ring-amber-100 overflow-hidden bg-amber-50 shadow-inner flex-shrink-0 transition-transform group-hover:scale-105", children: showTopPerformerImage ? /* @__PURE__ */ jsx(
64290
+ "img",
63774
64291
  {
63775
- className: "relative inline-block w-10 h-10 rounded-full ring-2 ring-white bg-amber-50 shadow-sm z-0 hover:z-10 transition-all hover:scale-110 group/avatar",
63776
- style: { zIndex: 3 - idx },
63777
- children: [
63778
- supervisor.imageUrl ? /* @__PURE__ */ jsx(
63779
- "img",
63780
- {
63781
- src: supervisor.imageUrl,
63782
- alt: supervisor.name,
63783
- className: "w-full h-full object-cover rounded-full"
63784
- }
63785
- ) : /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-sm font-bold text-amber-600 uppercase rounded-full", children: supervisor.initials }),
63786
- /* @__PURE__ */ jsxs("div", { className: "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 px-2 py-1 bg-gray-900 text-white text-[10px] font-medium rounded shadow-lg opacity-0 group-hover/avatar:opacity-100 transition-opacity whitespace-nowrap pointer-events-none z-20", children: [
63787
- supervisor.name,
63788
- /* @__PURE__ */ jsx("div", { className: "absolute top-full left-1/2 -translate-x-1/2 -mt-[1px] border-4 border-transparent border-t-gray-900" })
63789
- ] })
63790
- ]
63791
- },
63792
- supervisor.userId
63793
- )),
63794
- topPerformer.supervisors.length > 3 && /* @__PURE__ */ jsxs("div", { className: "inline-flex w-10 h-10 rounded-full ring-2 ring-white bg-amber-100 items-center justify-center text-sm font-medium text-amber-700 z-0", children: [
63795
- "+",
63796
- topPerformer.supervisors.length - 3
64292
+ src: topPerformer.imageUrl || "",
64293
+ alt: topPerformer.name,
64294
+ className: "w-full h-full object-cover",
64295
+ onError: () => setTopPerformerImageError(true)
64296
+ }
64297
+ ) : /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-sm font-bold text-amber-600 uppercase", children: topPerformer.initials }) }),
64298
+ topPerformer.supervisors && topPerformer.supervisors.length > 1 && /* @__PURE__ */ jsxs("div", { className: "flex -space-x-2", children: [
64299
+ topPerformer.supervisors.slice(0, 3).map((supervisor, idx) => /* @__PURE__ */ jsxs(
64300
+ "div",
64301
+ {
64302
+ className: "relative inline-block w-10 h-10 rounded-full ring-2 ring-white bg-amber-50 shadow-sm z-0 hover:z-10 transition-all hover:scale-110 group/avatar",
64303
+ style: { zIndex: 3 - idx },
64304
+ children: [
64305
+ supervisor.imageUrl ? /* @__PURE__ */ jsx(
64306
+ "img",
64307
+ {
64308
+ src: supervisor.imageUrl,
64309
+ alt: supervisor.name,
64310
+ className: "w-full h-full object-cover rounded-full"
64311
+ }
64312
+ ) : /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-sm font-bold text-amber-600 uppercase rounded-full", children: supervisor.initials }),
64313
+ /* @__PURE__ */ jsxs("div", { className: "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 px-2 py-1 bg-gray-900 text-white text-[10px] font-medium rounded shadow-lg opacity-0 group-hover/avatar:opacity-100 transition-opacity whitespace-nowrap pointer-events-none z-20", children: [
64314
+ supervisor.name,
64315
+ /* @__PURE__ */ jsx("div", { className: "absolute top-full left-1/2 -translate-x-1/2 -mt-[1px] border-4 border-transparent border-t-gray-900" })
64316
+ ] })
64317
+ ]
64318
+ },
64319
+ supervisor.userId
64320
+ )),
64321
+ topPerformer.supervisors.length > 3 && /* @__PURE__ */ jsxs("div", { className: "inline-flex w-10 h-10 rounded-full ring-2 ring-white bg-amber-100 items-center justify-center text-sm font-medium text-amber-700 z-0", children: [
64322
+ "+",
64323
+ topPerformer.supervisors.length - 3
64324
+ ] })
63797
64325
  ] })
63798
- ] })
63799
- ] }),
63800
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col min-w-0", children: [
63801
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[10px] leading-tight mb-1", children: [
63802
- /* @__PURE__ */ jsx("span", { className: "font-bold text-amber-600 uppercase tracking-widest", children: "Performer of the month" }),
63803
- /* @__PURE__ */ jsx("span", { className: "text-amber-200 opacity-50", children: "\u2022" }),
63804
- /* @__PURE__ */ jsx("span", { className: "font-semibold text-gray-400", children: topPerformer.periodLabel })
63805
64326
  ] }),
63806
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 leading-tight", children: [
63807
- /* @__PURE__ */ jsx("div", { className: "max-w-[140px]", children: /* @__PURE__ */ jsx(
63808
- FittingTitle,
63809
- {
63810
- title: topPerformer.name,
63811
- as: "span",
63812
- className: "text-sm text-gray-900 font-bold"
63813
- }
63814
- ) }),
63815
- /* @__PURE__ */ jsx("span", { className: "w-px h-3.5 bg-gray-200 flex-shrink-0" }),
63816
- /* @__PURE__ */ jsx("div", { className: "max-w-[150px]", children: /* @__PURE__ */ jsx(
63817
- FittingTitle,
63818
- {
63819
- title: topPerformer.unit,
63820
- className: "text-xs font-medium text-gray-500"
63821
- }
63822
- ) })
64327
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col min-w-0", children: [
64328
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[10px] leading-tight mb-1", children: [
64329
+ /* @__PURE__ */ jsx("span", { className: "font-bold text-amber-600 uppercase tracking-widest", children: "Performer of the month" }),
64330
+ /* @__PURE__ */ jsx("span", { className: "text-amber-200 opacity-50", children: "\u2022" }),
64331
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-gray-400", children: topPerformer.periodLabel })
64332
+ ] }),
64333
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 leading-tight", children: [
64334
+ /* @__PURE__ */ jsx("div", { className: "max-w-[140px]", children: /* @__PURE__ */ jsx(
64335
+ FittingTitle,
64336
+ {
64337
+ title: topPerformer.name,
64338
+ as: "span",
64339
+ className: "text-sm text-gray-900 font-bold"
64340
+ }
64341
+ ) }),
64342
+ /* @__PURE__ */ jsx("span", { className: "w-px h-3.5 bg-gray-200 flex-shrink-0" }),
64343
+ /* @__PURE__ */ jsx("div", { className: "max-w-[150px]", children: /* @__PURE__ */ jsx(
64344
+ FittingTitle,
64345
+ {
64346
+ title: topPerformer.unit,
64347
+ className: "text-xs font-medium text-gray-500"
64348
+ }
64349
+ ) })
64350
+ ] })
63823
64351
  ] })
63824
- ] })
63825
- ] }) })
64352
+ ] }),
64353
+ activeTab === "leaderboard" && isHistoricalLeaderboardDaily && /* @__PURE__ */ jsx(
64354
+ "button",
64355
+ {
64356
+ type: "button",
64357
+ onClick: () => {
64358
+ setSelectedLeaderboardDate(currentShiftDate);
64359
+ setSelectedLeaderboardShiftId(currentShiftId);
64360
+ },
64361
+ className: "text-xs sm:text-sm font-medium text-blue-600 bg-blue-50 border border-blue-100 hover:bg-blue-100 hover:text-blue-700 px-3 py-1.5 rounded-lg transition-colors shadow-sm ml-4 whitespace-nowrap",
64362
+ children: "Return to Live"
64363
+ }
64364
+ )
64365
+ ] })
63826
64366
  ] }),
63827
64367
  /* @__PURE__ */ jsx("div", { className: "bg-blue-50/50 px-4 py-2 rounded-xl border border-blue-100/50 backdrop-blur-sm", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-6", children: [
63828
64368
  !isMonthlyMode && !showHistoricalLeaderboardHeader && /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -63892,29 +64432,49 @@ var KPIsOverviewView = ({
63892
64432
  singleDateOnly: true
63893
64433
  }
63894
64434
  ),
63895
- /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(
63896
- "select",
63897
- {
63898
- "aria-label": "Leaderboard shift",
63899
- value: effectiveLeaderboardShiftId,
63900
- onChange: (e) => setSelectedLeaderboardShiftId(Number(e.target.value)),
63901
- className: "appearance-none pl-3 pr-8 py-1.5 text-sm font-medium bg-white border border-gray-200 hover:border-gray-300 rounded-lg text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all cursor-pointer shadow-sm min-w-[170px]",
63902
- 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.5rem center`, backgroundRepeat: `no-repeat`, backgroundSize: `1.2em 1.2em` },
63903
- children: leaderboardShiftOptions.map((shiftOption) => /* @__PURE__ */ jsx("option", { value: shiftOption.id, children: shiftOption.label }, shiftOption.id))
63904
- }
63905
- ) }),
63906
- isHistoricalLeaderboardDaily && /* @__PURE__ */ jsx(
63907
- "button",
63908
- {
63909
- type: "button",
63910
- onClick: () => {
63911
- setSelectedLeaderboardDate(currentShiftDate);
63912
- setSelectedLeaderboardShiftId(currentShiftId);
63913
- },
63914
- className: "text-xs font-medium text-blue-600 hover:text-blue-700 whitespace-nowrap",
63915
- children: "Return to Live"
63916
- }
63917
- )
64435
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
64436
+ /* @__PURE__ */ jsxs(
64437
+ "button",
64438
+ {
64439
+ ref: filterButtonRef,
64440
+ onClick: () => setIsFilterOpen(!isFilterOpen),
64441
+ 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"}`,
64442
+ children: [
64443
+ /* @__PURE__ */ jsx(Filter, { className: "w-4 h-4" }),
64444
+ /* @__PURE__ */ jsx("span", { children: "Filters" }),
64445
+ 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 }),
64446
+ /* @__PURE__ */ jsx(ChevronDown, { className: `w-3 h-3 ml-1 transition-transform ${isFilterOpen ? "rotate-180" : ""}` })
64447
+ ]
64448
+ }
64449
+ ),
64450
+ 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: [
64451
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
64452
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Filter View" }),
64453
+ activeFiltersCount > 0 && /* @__PURE__ */ jsx(
64454
+ "button",
64455
+ {
64456
+ onClick: clearFilters,
64457
+ className: "text-xs text-red-600 hover:text-red-700 font-medium",
64458
+ children: "Clear all"
64459
+ }
64460
+ )
64461
+ ] }),
64462
+ /* @__PURE__ */ jsx("div", { className: "space-y-3", children: /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
64463
+ /* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide ml-1", children: "Shift" }),
64464
+ /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(
64465
+ "select",
64466
+ {
64467
+ "aria-label": "Leaderboard shift",
64468
+ value: effectiveLeaderboardShiftId,
64469
+ onChange: (e) => setSelectedLeaderboardShiftId(Number(e.target.value)),
64470
+ 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",
64471
+ 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` },
64472
+ children: leaderboardShiftOptions.map((shiftOption) => /* @__PURE__ */ jsx("option", { value: shiftOption.id, children: shiftOption.label }, shiftOption.id))
64473
+ }
64474
+ ) })
64475
+ ] }) })
64476
+ ] })
64477
+ ] })
63918
64478
  ] }),
63919
64479
  (activeTab === "leaderboard" || activeTab === "today") && showViewTypeDropdown && /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsxs(
63920
64480
  "select",
@@ -64005,29 +64565,16 @@ var formatCycleTimeValue = (value) => {
64005
64565
  return `${numericValue.toFixed(1)}s`;
64006
64566
  };
64007
64567
  var CycleTimeComparison = memo$1(({
64008
- workspace,
64009
- variant = "table"
64568
+ workspace
64010
64569
  }) => {
64011
64570
  const averageValue = formatCycleTimeValue(workspace.avg_cycle_time);
64012
64571
  const standardValue = formatCycleTimeValue(workspace.ideal_cycle_time);
64013
- if (variant === "mobile") {
64014
- return /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center justify-between py-2 border-t border-gray-100", children: [
64015
- /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Standard Cycle Time" }),
64016
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium tabular-nums text-gray-500", children: standardValue })
64017
- ] });
64018
- }
64019
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
64020
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
64021
- /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium uppercase tracking-wider text-gray-500", children: "Average" }),
64022
- /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold tabular-nums text-gray-900", children: averageValue })
64023
- ] }),
64024
- /* @__PURE__ */ jsx("div", { className: "h-6 w-px bg-gray-200" }),
64025
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
64026
- /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium uppercase tracking-wider text-gray-500", children: "Standard" }),
64027
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium tabular-nums text-gray-500", children: standardValue })
64028
- ] })
64572
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 tabular-nums", children: [
64573
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-gray-900", children: averageValue }),
64574
+ /* @__PURE__ */ jsx("span", { className: "text-gray-400 font-normal", children: "/" }),
64575
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-500", children: standardValue })
64029
64576
  ] });
64030
- }, (prevProps, nextProps) => prevProps.variant === nextProps.variant && prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.ideal_cycle_time === nextProps.workspace.ideal_cycle_time);
64577
+ }, (prevProps, nextProps) => prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.ideal_cycle_time === nextProps.workspace.ideal_cycle_time);
64031
64578
  CycleTimeComparison.displayName = "CycleTimeComparison";
64032
64579
  var IsolatedTimer = memo$1(() => {
64033
64580
  return /* @__PURE__ */ jsx(ISTTimer_default, {});
@@ -64094,7 +64641,7 @@ var MobileWorkspaceCard = memo$1(({
64094
64641
  getMedalIcon,
64095
64642
  metricLabel,
64096
64643
  isAssemblyMode
64097
- }) => /* @__PURE__ */ jsxs(
64644
+ }) => /* @__PURE__ */ jsx(
64098
64645
  motion.div,
64099
64646
  {
64100
64647
  layout: true,
@@ -64105,28 +64652,25 @@ var MobileWorkspaceCard = memo$1(({
64105
64652
  },
64106
64653
  onClick: isClickable ? () => onWorkspaceClick(workspace, rank) : void 0,
64107
64654
  className: `${cardClass} p-3 rounded-lg border shadow-sm active:scale-[0.98] ${isClickable ? "cursor-pointer" : "cursor-not-allowed opacity-75"}`,
64108
- children: [
64109
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2 gap-3", children: [
64110
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
64111
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
64112
- /* @__PURE__ */ jsxs("div", { className: "text-2xl font-bold text-gray-700", children: [
64113
- "#",
64114
- rank
64115
- ] }),
64116
- getMedalIcon(rank)
64655
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2 gap-3", children: [
64656
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
64657
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
64658
+ /* @__PURE__ */ jsxs("div", { className: "text-2xl font-bold text-gray-700", children: [
64659
+ "#",
64660
+ rank
64117
64661
  ] }),
64118
- /* @__PURE__ */ jsxs("div", { children: [
64119
- /* @__PURE__ */ jsx("div", { className: "font-semibold text-gray-900", children: workspace.displayName }),
64120
- /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500", children: workspace.lineName })
64121
- ] })
64662
+ getMedalIcon(rank)
64122
64663
  ] }),
64123
- /* @__PURE__ */ jsxs("div", { className: "text-right", children: [
64124
- /* @__PURE__ */ jsx("div", { className: "font-bold text-gray-900 text-lg", children: isAssemblyMode ? /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: formatCycleTimeValue(workspace.avg_cycle_time) }) : /* @__PURE__ */ jsx(AnimatedEfficiency, { value: workspace.efficiency || 0 }) }),
64125
- /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500", children: metricLabel })
64664
+ /* @__PURE__ */ jsxs("div", { children: [
64665
+ /* @__PURE__ */ jsx("div", { className: "font-semibold text-gray-900", children: workspace.displayName }),
64666
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500", children: workspace.lineName })
64126
64667
  ] })
64127
64668
  ] }),
64128
- isAssemblyMode && /* @__PURE__ */ jsx(CycleTimeComparison, { workspace, variant: "mobile" })
64129
- ]
64669
+ /* @__PURE__ */ jsxs("div", { className: "text-right", children: [
64670
+ /* @__PURE__ */ jsx("div", { className: "font-bold text-gray-900 text-lg flex justify-end", children: isAssemblyMode ? /* @__PURE__ */ jsx(CycleTimeComparison, { workspace }) : /* @__PURE__ */ jsx(AnimatedEfficiency, { value: workspace.efficiency || 0 }) }),
64671
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500", children: metricLabel })
64672
+ ] })
64673
+ ] })
64130
64674
  }
64131
64675
  ), (prevProps, nextProps) => {
64132
64676
  return prevProps.metricLabel === nextProps.metricLabel && prevProps.isAssemblyMode === nextProps.isAssemblyMode && prevProps.rank === nextProps.rank && prevProps.cardClass === nextProps.cardClass && prevProps.isClickable === nextProps.isClickable && prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.efficiency === nextProps.workspace.efficiency && prevProps.workspace.ideal_cycle_time === nextProps.workspace.ideal_cycle_time && prevProps.workspace.action_count === nextProps.workspace.action_count && prevProps.workspace.action_threshold === nextProps.workspace.action_threshold && prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.displayName === nextProps.workspace.displayName && prevProps.workspace.lineName === nextProps.workspace.lineName;
@@ -64156,7 +64700,7 @@ var DesktopWorkspaceRow = memo$1(({
64156
64700
  ] }) }),
64157
64701
  /* @__PURE__ */ jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsx("div", { className: "font-medium", children: workspace.displayName }) }),
64158
64702
  /* @__PURE__ */ jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsx("div", { className: "font-medium", children: workspace.lineName }) }),
64159
- /* @__PURE__ */ jsx("td", { className: `px-3 py-2.5 sm:p-4 text-sm sm:text-base font-medium ${isAssemblyMode ? "" : "whitespace-nowrap"}`, children: isAssemblyMode ? /* @__PURE__ */ jsx(CycleTimeComparison, { workspace, variant: "table" }) : /* @__PURE__ */ jsx(AnimatedEfficiency, { value: workspace.efficiency || 0 }) })
64703
+ /* @__PURE__ */ jsx("td", { className: `px-3 py-2.5 sm:p-4 text-sm sm:text-base font-medium ${isAssemblyMode ? "" : "whitespace-nowrap"}`, children: isAssemblyMode ? /* @__PURE__ */ jsx(CycleTimeComparison, { workspace }) : /* @__PURE__ */ jsx(AnimatedEfficiency, { value: workspace.efficiency || 0 }) })
64160
64704
  ]
64161
64705
  }
64162
64706
  ), (prevProps, nextProps) => {
@@ -64283,7 +64827,7 @@ var LeaderboardDetailView = memo$1(({
64283
64827
  return () => document.removeEventListener("mousedown", handleClickOutside);
64284
64828
  }, []);
64285
64829
  const [isMobile, setIsMobile] = useState(false);
64286
- React141__default.useEffect(() => {
64830
+ React142__default.useEffect(() => {
64287
64831
  const checkMobile = () => setIsMobile(window.innerWidth < 640);
64288
64832
  checkMobile();
64289
64833
  window.addEventListener("resize", checkMobile);
@@ -64929,7 +65473,7 @@ var LeaderboardDetailView = memo$1(({
64929
65473
  const descendingSortLabel = "Highest to Lowest";
64930
65474
  const ascendingSortLabel = "Lowest to Highest";
64931
65475
  return /* @__PURE__ */ jsxs("div", { className: `min-h-screen bg-slate-50 flex flex-col ${className}`, style: { willChange: "contents" }, children: [
64932
- /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-20 bg-white shadow-sm border-b border-gray-200/80", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-6 md:px-8 py-2 sm:py-2.5", children: [
65476
+ /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-40 bg-white shadow-sm border-b border-gray-200/80", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-6 md:px-8 py-2 sm:py-2.5", children: [
64933
65477
  /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
64934
65478
  mobileMenuContext && /* @__PURE__ */ jsx(
64935
65479
  HamburgerButton,
@@ -64940,7 +65484,7 @@ var LeaderboardDetailView = memo$1(({
64940
65484
  ),
64941
65485
  /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
64942
65486
  /* @__PURE__ */ jsx("h1", { className: "text-lg font-semibold text-gray-900", children: "Leaderboard" }),
64943
- /* @__PURE__ */ jsx("div", { className: "h-2 w-2 rounded-full bg-emerald-500 animate-pulse ring-2 ring-emerald-500/20" })
65487
+ realtimeEnabled && /* @__PURE__ */ jsx("div", { className: "h-2 w-2 rounded-full bg-emerald-500 animate-pulse ring-2 ring-emerald-500/20" })
64944
65488
  ] }) }),
64945
65489
  /* @__PURE__ */ jsx("div", { className: "w-9" })
64946
65490
  ] }) }),
@@ -64956,7 +65500,7 @@ var LeaderboardDetailView = memo$1(({
64956
65500
  ) }),
64957
65501
  /* @__PURE__ */ jsx("div", { className: "absolute left-1/2 transform -translate-x-1/2 max-w-[calc(100%-200px)]", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
64958
65502
  /* @__PURE__ */ jsx("h1", { className: "text-lg md:text-xl lg:text-2xl xl:text-3xl font-semibold text-gray-900 truncate", children: "Leaderboard" }),
64959
- /* @__PURE__ */ jsxs("div", { className: "relative flex h-2.5 w-2.5", children: [
65503
+ realtimeEnabled && /* @__PURE__ */ jsxs("div", { className: "relative flex h-2.5 w-2.5", children: [
64960
65504
  /* @__PURE__ */ jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" }),
64961
65505
  /* @__PURE__ */ jsx("span", { className: "relative inline-flex rounded-full h-2.5 w-2.5 bg-green-500" })
64962
65506
  ] })
@@ -65454,7 +65998,7 @@ var ProfileView = () => {
65454
65998
  ] }) });
65455
65999
  }
65456
66000
  return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-gray-50 flex flex-col", children: [
65457
- /* @__PURE__ */ jsxs("header", { className: "sticky top-0 z-10 bg-white border-b flex-shrink-0", children: [
66001
+ /* @__PURE__ */ jsxs("header", { className: "sticky top-0 z-40 bg-white border-b flex-shrink-0", children: [
65458
66002
  /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3", children: [
65459
66003
  /* @__PURE__ */ jsxs("div", { className: "sm:hidden flex items-center justify-between", children: [
65460
66004
  /* @__PURE__ */ jsx("div", { className: "flex items-center", children: mobileMenuContext && /* @__PURE__ */ jsx(
@@ -65678,7 +66222,7 @@ var ClipsCostView = () => {
65678
66222
  return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-screen bg-gray-50", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "lg", message: "Loading usage data..." }) });
65679
66223
  }
65680
66224
  return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-gray-50 flex flex-col", children: [
65681
- /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-10 bg-white border-b border-gray-200 shadow-sm flex-shrink-0", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-6 lg:px-8 py-3 sm:py-4 w-full", children: [
66225
+ /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-40 bg-white border-b border-gray-200 shadow-sm flex-shrink-0", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-6 lg:px-8 py-3 sm:py-4 w-full", children: [
65682
66226
  /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
65683
66227
  /* @__PURE__ */ jsx("div", { className: "flex items-center", children: mobileMenuContext && /* @__PURE__ */ jsx(
65684
66228
  HamburgerButton,
@@ -66565,7 +67109,7 @@ var ShiftsView = ({
66565
67109
  }
66566
67110
  }, [lineConfigs, recalculateTargetsForShiftHourChanges, supabase, showToast]);
66567
67111
  return /* @__PURE__ */ jsxs("div", { className: `min-h-screen bg-slate-50 ${className}`, children: [
66568
- /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-10 bg-white border-b border-gray-200/80 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 lg:px-8 py-3 sm:py-4", children: [
67112
+ /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-40 bg-white border-b border-gray-200/80 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 lg:px-8 py-3 sm:py-4", children: [
66569
67113
  /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
66570
67114
  mobileMenuContext && /* @__PURE__ */ jsx(
66571
67115
  HamburgerButton,
@@ -66679,7 +67223,7 @@ var ShiftsView = ({
66679
67223
  ] })
66680
67224
  ] });
66681
67225
  };
66682
- var AuthenticatedShiftsView = withAuth(React141__default.memo(ShiftsView));
67226
+ var AuthenticatedShiftsView = withAuth(React142__default.memo(ShiftsView));
66683
67227
  var ShiftsView_default = ShiftsView;
66684
67228
 
66685
67229
  // src/views/TargetsView.utils.ts
@@ -68381,7 +68925,7 @@ var TargetsView = ({
68381
68925
  };
68382
68926
  var TargetsViewWithDisplayNames = withAllWorkspaceDisplayNames(TargetsView);
68383
68927
  var TargetsView_default = TargetsViewWithDisplayNames;
68384
- var AuthenticatedTargetsView = withAuth(React141__default.memo(TargetsViewWithDisplayNames));
68928
+ var AuthenticatedTargetsView = withAuth(React142__default.memo(TargetsViewWithDisplayNames));
68385
68929
  function useTimezone(options = {}) {
68386
68930
  const dashboardConfig = useDashboardConfig();
68387
68931
  const workspaceConfig = useWorkspaceConfig();
@@ -69187,56 +69731,43 @@ var WorkspaceDetailView = ({
69187
69731
  const canToggleChartIdleTime = !isUptimeMode && !shouldShowCycleTimeLoadingState && !shouldShowCycleTimeUnavailableState;
69188
69732
  const idleClipDate = date || workspace?.date || calculatedOperationalDate || getOperationalDate(timezone);
69189
69733
  const idleClipShiftId = parsedShiftId ?? workspace?.shift_id;
69190
- const rawHourlyIdleMinutes = useMemo(() => {
69191
- if (!shouldShowCycleTimeChart || !workspace?.idle_time_hourly || !workspace?.shift_start) return [];
69192
- const parseTimeToMinutes4 = (time2) => {
69193
- const [h, m] = time2.split(":").map(Number);
69194
- if (!Number.isFinite(h) || !Number.isFinite(m)) return 0;
69195
- return h * 60 + m;
69196
- };
69197
- const startTotal = parseTimeToMinutes4(workspace.shift_start);
69198
- const endTotalRaw = workspace.shift_end ? parseTimeToMinutes4(workspace.shift_end) : startTotal + 11 * 60;
69199
- const endTotal = endTotalRaw <= startTotal ? endTotalRaw + 24 * 60 : endTotalRaw;
69200
- const shiftDuration = Math.max(60, endTotal - startTotal);
69201
- const totalHourSlots = Math.max(1, Math.ceil(shiftDuration / 60));
69202
- const idleTimeHourlyObj = workspace.idle_time_hourly || {};
69203
- const result = Array(totalHourSlots).fill(0);
69204
- for (let i = 0; i < totalHourSlots; i++) {
69205
- const startSlotMins = startTotal + i * 60;
69206
- let endSlotMins = startSlotMins + 60;
69207
- if (endSlotMins > endTotal) endSlotMins = endTotal;
69208
- let idleCount = 0;
69209
- for (let m = startSlotMins; m < endSlotMins; m++) {
69210
- const hourKey = Math.floor(m / 60) % 24;
69211
- const minuteKey = m % 60;
69212
- const hourData = idleTimeHourlyObj[hourKey.toString()] || [];
69213
- if (Array.isArray(hourData)) {
69214
- const val = hourData[minuteKey];
69215
- if (val === 1 || val === "1") {
69216
- idleCount++;
69217
- }
69218
- }
69219
- }
69220
- result[i] = idleCount;
69221
- }
69222
- return result;
69223
- }, [shouldShowCycleTimeChart, workspace?.idle_time_hourly, workspace?.shift_start, workspace?.shift_end]);
69734
+ const rawHourlyIdleSlots = useMemo(
69735
+ () => !shouldShowCycleTimeChart || !authoritativeCycleMetrics?.shift_start ? [] : buildHourlyIdleSlots({
69736
+ idleTimeHourly: authoritativeCycleMetrics.idle_time_hourly,
69737
+ shiftStart: authoritativeCycleMetrics.shift_start,
69738
+ shiftEnd: authoritativeCycleMetrics.shift_end
69739
+ }),
69740
+ [
69741
+ shouldShowCycleTimeChart,
69742
+ authoritativeCycleMetrics?.idle_time_hourly,
69743
+ authoritativeCycleMetrics?.shift_start,
69744
+ authoritativeCycleMetrics?.shift_end
69745
+ ]
69746
+ );
69747
+ const rawHourlyIdleMinutes = useMemo(
69748
+ () => rawHourlyIdleSlots.map((slot) => slot.idleMinutes),
69749
+ [rawHourlyIdleSlots]
69750
+ );
69224
69751
  const hourlyIdleMinutes = useMemo(
69225
69752
  () => maskFutureHourlySeries({
69226
69753
  data: rawHourlyIdleMinutes,
69227
- shiftStart: workspace?.shift_start,
69228
- shiftEnd: workspace?.shift_end,
69754
+ shiftStart: authoritativeCycleMetrics?.shift_start,
69755
+ shiftEnd: authoritativeCycleMetrics?.shift_end,
69229
69756
  shiftDate: idleClipDate,
69230
69757
  timezone: effectiveCycleTimeTimezone
69231
69758
  }),
69232
69759
  [
69233
69760
  rawHourlyIdleMinutes,
69234
- workspace?.shift_start,
69235
- workspace?.shift_end,
69761
+ authoritativeCycleMetrics?.shift_start,
69762
+ authoritativeCycleMetrics?.shift_end,
69236
69763
  idleClipDate,
69237
69764
  effectiveCycleTimeTimezone
69238
69765
  ]
69239
69766
  );
69767
+ const hourlyIdleSlots = useMemo(
69768
+ () => rawHourlyIdleSlots.map((slot, index) => hourlyIdleMinutes[index] === null ? null : slot),
69769
+ [rawHourlyIdleSlots, hourlyIdleMinutes]
69770
+ );
69240
69771
  const cycleTimeUnavailableView = useMemo(() => /* @__PURE__ */ jsxs("div", { className: "w-full h-full rounded-lg border border-amber-200 bg-amber-50/70 px-6 py-5 text-center flex flex-col items-center justify-center", children: [
69241
69772
  /* @__PURE__ */ jsx("h4", { className: "text-base font-semibold text-amber-900", children: "Cycle data unavailable" }),
69242
69773
  /* @__PURE__ */ jsx("p", { className: "mt-2 max-w-md text-sm text-amber-800", children: "This workstation has cycle-time metrics for the selected shift, but no matching `cycle_completion` clips were found for the chart." }),
@@ -69403,7 +69934,7 @@ var WorkspaceDetailView = ({
69403
69934
  animate: { opacity: 1 },
69404
69935
  transition: { duration: 0.3 },
69405
69936
  children: /* @__PURE__ */ jsxs("div", { className: "min-h-screen w-full flex flex-col bg-slate-50", children: [
69406
- /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-10 px-3 sm:px-4 md:px-5 lg:px-6 py-2 sm:py-2.5 lg:py-3 flex flex-col shadow-sm bg-white", children: /* @__PURE__ */ jsxs("div", { className: "relative flex items-center", children: [
69937
+ /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-40 px-3 sm:px-4 md:px-5 lg:px-6 py-2 sm:py-2.5 lg:py-3 flex flex-col shadow-sm bg-white", children: /* @__PURE__ */ jsxs("div", { className: "relative flex items-center", children: [
69407
69938
  /* @__PURE__ */ jsx("div", { className: "absolute left-0 animate-pulse", children: /* @__PURE__ */ jsx("div", { className: "h-6 sm:h-7 md:h-8 w-16 sm:w-20 bg-gray-200 rounded" }) }),
69408
69939
  /* @__PURE__ */ jsx("div", { className: "absolute left-1/2 transform -translate-x-1/2 animate-pulse max-w-[calc(100%-160px)] sm:max-w-[calc(100%-200px)]", children: /* @__PURE__ */ jsx("div", { className: "h-5 sm:h-6 md:h-7 w-28 sm:w-36 md:w-40 bg-gray-200 rounded" }) }),
69409
69940
  /* @__PURE__ */ jsx("div", { className: "w-full h-8" })
@@ -69465,7 +69996,7 @@ var WorkspaceDetailView = ({
69465
69996
  initial: { opacity: 1 },
69466
69997
  animate: { opacity: 1 },
69467
69998
  children: /* @__PURE__ */ jsxs("div", { className: "min-h-screen w-full flex flex-col bg-slate-50", children: [
69468
- /* @__PURE__ */ jsxs("header", { className: "sticky top-0 z-10 px-3 sm:px-4 md:px-5 lg:px-6 py-3 sm:py-3 lg:py-3.5 flex flex-col shadow-sm bg-white", children: [
69999
+ /* @__PURE__ */ jsxs("header", { className: "sticky top-0 z-40 px-3 sm:px-4 md:px-5 lg:px-6 py-3 sm:py-3 lg:py-3.5 flex flex-col shadow-sm bg-white", children: [
69469
70000
  /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
69470
70001
  /* @__PURE__ */ jsx(
69471
70002
  "button",
@@ -69792,7 +70323,8 @@ var WorkspaceDetailView = ({
69792
70323
  xAxisMode: "hourly",
69793
70324
  datasetKey: cycleTimeDatasetKey,
69794
70325
  showIdleTime: showChartIdleTime,
69795
- idleTimeData: hourlyIdleMinutes
70326
+ idleTimeData: hourlyIdleMinutes,
70327
+ idleTimeSlots: hourlyIdleSlots
69796
70328
  }
69797
70329
  ) : null : /* @__PURE__ */ jsx(
69798
70330
  HourlyOutputChart2,
@@ -69921,7 +70453,8 @@ var WorkspaceDetailView = ({
69921
70453
  xAxisMode: "hourly",
69922
70454
  datasetKey: cycleTimeDatasetKey,
69923
70455
  showIdleTime: showChartIdleTime,
69924
- idleTimeData: hourlyIdleMinutes
70456
+ idleTimeData: hourlyIdleMinutes,
70457
+ idleTimeSlots: hourlyIdleSlots
69925
70458
  }
69926
70459
  ) : null : /* @__PURE__ */ jsx(
69927
70460
  HourlyOutputChart2,
@@ -70141,7 +70674,7 @@ var SKUManagementView = () => {
70141
70674
  ] }) });
70142
70675
  }
70143
70676
  return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-slate-50", children: [
70144
- /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-10 bg-white border-b border-gray-200/80 shadow-sm", children: /* @__PURE__ */ jsx("div", { className: "px-3 sm:px-4 md:px-6 lg:px-8 py-3 sm:py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4 relative", children: [
70677
+ /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-40 bg-white border-b border-gray-200/80 shadow-sm", children: /* @__PURE__ */ jsx("div", { className: "px-3 sm:px-4 md:px-6 lg:px-8 py-3 sm:py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4 relative", children: [
70145
70678
  /* @__PURE__ */ jsx("div", { className: "sm:absolute sm:left-0", children: /* @__PURE__ */ jsx(
70146
70679
  BackButtonMinimal,
70147
70680
  {
@@ -70279,8 +70812,29 @@ var useWorkspaceHealth = (options) => {
70279
70812
  date: options.date,
70280
70813
  shiftId: options.shiftId
70281
70814
  });
70282
- setWorkspaces(workspacesWithStatus);
70283
- setSummary(computeSummary(workspacesWithStatus));
70815
+ let cameraIpMap = {};
70816
+ const workspaceIds = workspacesWithStatus.map((workspace) => workspace.workspace_id).filter(Boolean);
70817
+ if (workspaceIds.length > 0) {
70818
+ try {
70819
+ cameraIpMap = await workspaceService.getWorkspaceCameraIps({ workspaceIds });
70820
+ } catch (cameraError) {
70821
+ console.error("[useWorkspaceHealth] Error fetching camera IPs:", cameraError);
70822
+ }
70823
+ }
70824
+ const workspacesWithCameraIps = workspacesWithStatus.map((workspace) => {
70825
+ const cameraInfo = cameraIpMap[workspace.workspace_id];
70826
+ if (!cameraInfo) {
70827
+ return workspace;
70828
+ }
70829
+ return {
70830
+ ...workspace,
70831
+ cameraIp: cameraInfo.camera_ip ?? null,
70832
+ cameraResolutionMode: cameraInfo.resolution_mode ?? null,
70833
+ effectiveCameraUuid: cameraInfo.effective_camera_uuid ?? null
70834
+ };
70835
+ });
70836
+ setWorkspaces(workspacesWithCameraIps);
70837
+ setSummary(computeSummary(workspacesWithCameraIps));
70284
70838
  } catch (err) {
70285
70839
  console.error("[useWorkspaceHealth] Error fetching workspace health:", err);
70286
70840
  setError({ message: err.message, code: err.code || "FETCH_ERROR" });
@@ -70646,7 +71200,7 @@ var WorkspaceUptimeDetailModal = ({
70646
71200
  role: "document",
70647
71201
  "aria-labelledby": "uptime-detail-title",
70648
71202
  children: [
70649
- /* @__PURE__ */ jsxs("header", { className: "flex items-start justify-between border-b border-gray-100 px-8 py-6 sticky top-0 z-10 bg-white rounded-t-2xl", children: [
71203
+ /* @__PURE__ */ jsxs("header", { className: "flex items-start justify-between border-b border-gray-100 px-8 py-6 sticky top-0 z-40 bg-white rounded-t-2xl", children: [
70650
71204
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 mr-4", children: [
70651
71205
  /* @__PURE__ */ jsx("h2", { id: "uptime-detail-title", className: "text-2xl font-semibold text-gray-900 truncate mb-3", children: workspace.workspace_display_name || `Workspace ${workspace.workspace_id.slice(0, 6)}` }),
70652
71206
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 text-sm text-gray-600", children: [
@@ -70656,7 +71210,7 @@ var WorkspaceUptimeDetailModal = ({
70656
71210
  /* @__PURE__ */ jsx("span", { className: "text-gray-600", children: formatTimeRange(shiftStart, shiftEnd, timezone) })
70657
71211
  ] })
70658
71212
  ] }),
70659
- /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-2", children: [
71213
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-2", children: [
70660
71214
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
70661
71215
  /* @__PURE__ */ jsx("div", { className: `w-2 h-2 rounded-full ${workspace.status === "healthy" ? "bg-emerald-500 animate-pulse" : workspace.status === "warning" ? "bg-amber-500" : "bg-rose-500"}` }),
70662
71216
  /* @__PURE__ */ jsx("span", { className: `text-xs font-medium ${workspace.status === "healthy" ? "text-emerald-700" : workspace.status === "warning" ? "text-amber-700" : "text-rose-700"}`, children: workspace.status === "healthy" ? "Operational" : workspace.status === "warning" ? "Intermittent" : "Down" })
@@ -70665,6 +71219,13 @@ var WorkspaceUptimeDetailModal = ({
70665
71219
  /* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-500", children: [
70666
71220
  "Last heartbeat ",
70667
71221
  workspace.timeSinceLastUpdate
71222
+ ] }),
71223
+ workspace.cameraIp && /* @__PURE__ */ jsxs(Fragment, { children: [
71224
+ /* @__PURE__ */ jsx("span", { className: "text-gray-300 hidden sm:inline", children: "\u2022" }),
71225
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 bg-slate-50 dark:bg-slate-800/50 px-2 py-0.5 rounded border border-slate-100 dark:border-slate-700/50 group", title: "Camera IP", children: [
71226
+ /* @__PURE__ */ jsx(Video, { className: "h-3 w-3 text-slate-400" }),
71227
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-slate-600 dark:text-slate-300 select-all", children: workspace.cameraIp })
71228
+ ] })
70668
71229
  ] })
70669
71230
  ] })
70670
71231
  ] }),
@@ -70866,7 +71427,7 @@ var WorkspaceHealthView = ({
70866
71427
  }
70867
71428
  return /* @__PURE__ */ jsxs(Fragment, { children: [
70868
71429
  /* @__PURE__ */ jsxs("div", { className: clsx("min-h-screen bg-slate-50", className), children: [
70869
- /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-10 bg-white border-b border-gray-200 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-6 lg:px-8 py-3 sm:py-4", children: [
71430
+ /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-40 bg-white border-b border-gray-200 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-6 lg:px-8 py-3 sm:py-4", children: [
70870
71431
  /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
70871
71432
  mobileMenuContext && /* @__PURE__ */ jsx(
70872
71433
  HamburgerButton,
@@ -71200,7 +71761,7 @@ var SupervisorManagementView = ({
71200
71761
  ) }) });
71201
71762
  }
71202
71763
  return /* @__PURE__ */ jsxs("div", { className: clsx("min-h-screen bg-slate-50", className), children: [
71203
- /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-10 bg-white border-b border-gray-200/80 shadow-sm", children: /* @__PURE__ */ jsx("div", { className: "px-3 sm:px-4 md:px-6 lg:px-8 py-3 sm:py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center relative", children: [
71764
+ /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-40 bg-white border-b border-gray-200/80 shadow-sm", children: /* @__PURE__ */ jsx("div", { className: "px-3 sm:px-4 md:px-6 lg:px-8 py-3 sm:py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center relative", children: [
71204
71765
  /* @__PURE__ */ jsx("div", { className: "sm:absolute sm:left-0", children: /* @__PURE__ */ jsx(
71205
71766
  BackButtonMinimal,
71206
71767
  {
@@ -71622,7 +72183,7 @@ var TeamManagementView = ({
71622
72183
  ) }) });
71623
72184
  }
71624
72185
  return /* @__PURE__ */ jsxs("div", { className: cn("min-h-screen bg-slate-50", className), children: [
71625
- /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-10 bg-white border-b border-gray-200 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-6 lg:px-8 py-3 sm:py-4", children: [
72186
+ /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-40 bg-white border-b border-gray-200 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-6 lg:px-8 py-3 sm:py-4", children: [
71626
72187
  /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
71627
72188
  mobileMenuContext && /* @__PURE__ */ jsx(
71628
72189
  HamburgerButton,
@@ -71766,7 +72327,7 @@ function BottleneckClipsView({
71766
72327
  ) })
71767
72328
  ] }) });
71768
72329
  }
71769
- var AuthenticatedBottleneckClipsView = withAuth(React141__default.memo(BottleneckClipsView));
72330
+ var AuthenticatedBottleneckClipsView = withAuth(React142__default.memo(BottleneckClipsView));
71770
72331
  var BottleneckClipsView_default = BottleneckClipsView;
71771
72332
 
71772
72333
  // src/lib/services/ticketService.ts
@@ -72597,7 +73158,7 @@ Please ensure:
72597
73158
  )
72598
73159
  ] });
72599
73160
  }
72600
- var AuthenticatedTicketsView = withAuth(React141__default.memo(TicketsView));
73161
+ var AuthenticatedTicketsView = withAuth(React142__default.memo(TicketsView));
72601
73162
  var TicketsView_default = TicketsView;
72602
73163
 
72603
73164
  // src/lib/utils/improvementDisplay.ts
@@ -72927,6 +73488,18 @@ var buildInitials = (name) => {
72927
73488
  const second = parts.length > 1 ? parts[1]?.[0] || "" : "";
72928
73489
  return `${first}${second}`.toUpperCase();
72929
73490
  };
73491
+ var getRecommendationAssignedUserIds = (recommendation) => {
73492
+ if (Array.isArray(recommendation.assigned_user_ids) && recommendation.assigned_user_ids.length > 0) {
73493
+ return recommendation.assigned_user_ids.filter(
73494
+ (userId) => typeof userId === "string" && userId.trim().length > 0
73495
+ );
73496
+ }
73497
+ return recommendation.assigned_to_user_id ? [recommendation.assigned_to_user_id] : [];
73498
+ };
73499
+ var recommendationMatchesMember = (recommendation, memberId) => {
73500
+ if (memberId === "all") return true;
73501
+ return getRecommendationAssignedUserIds(recommendation).includes(memberId);
73502
+ };
72930
73503
  var getQueryParam = (value) => {
72931
73504
  if (typeof value === "string") {
72932
73505
  const trimmed = value.trim();
@@ -73021,7 +73594,6 @@ var ClipVideoCarousel = ({ clips, clipsService }) => {
73021
73594
  currentVideo.cycle_time_seconds.toFixed(1),
73022
73595
  "s"
73023
73596
  ] }),
73024
- !loading && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none group-hover:opacity-0 transition-opacity", children: /* @__PURE__ */ jsx(PlayCircleIcon, { className: "w-16 h-16 text-white opacity-80" }) }),
73025
73597
  videos.length > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
73026
73598
  /* @__PURE__ */ jsx(
73027
73599
  "button",
@@ -73418,10 +73990,7 @@ var ImprovementCenterView = () => {
73418
73990
  if (!supabase || !companyId) return;
73419
73991
  try {
73420
73992
  const userService2 = createUserManagementService(supabase);
73421
- const users = await userService2.getCompanyUsers(
73422
- companyId,
73423
- "supervisor,owner,industrial_engineer"
73424
- );
73993
+ const users = await userService2.getCompanyUsers(companyId);
73425
73994
  if (cancelled) return;
73426
73995
  const membersById = /* @__PURE__ */ new Map();
73427
73996
  users.forEach((user2) => {
@@ -73525,18 +74094,8 @@ var ImprovementCenterView = () => {
73525
74094
  const teamMembersById = useMemo(() => {
73526
74095
  return new Map(teamMembers.map((member) => [member.id, member]));
73527
74096
  }, [teamMembers]);
73528
- const getRecommendationDisplayMetadata = React141__default.useCallback((rec) => {
73529
- const supervisors = rec.line_id ? supervisorsByLineId.get(rec.line_id) || [] : [];
73530
- return getImprovementDisplayMetadata({
73531
- location: rec.location,
73532
- line: rec.line,
73533
- workspaceId: rec.workspace_id,
73534
- supervisors
73535
- });
73536
- }, [supervisorsByLineId]);
73537
- const filteredRecommendations = useMemo(() => {
73538
- const hasActiveFilters = selectedLineId !== "all" || selectedStatus !== "all" || selectedShift !== "all" || selectedWeeksRange !== "all" || selectedMemberId !== "all" || selectedSortBy !== "all";
73539
- const sortedRecommendations = recommendations.filter((rec) => {
74097
+ const recommendationsMatchingViewFilters = useMemo(() => {
74098
+ return recommendations.filter((rec) => {
73540
74099
  if (selectedLineId !== "all" && rec.line_id !== selectedLineId) return false;
73541
74100
  if (selectedStatus === "resolved" && rec.ticket_status !== "solved") return false;
73542
74101
  if (selectedStatus === "unresolved" && rec.ticket_status === "solved") return false;
@@ -73547,9 +74106,41 @@ var ImprovementCenterView = () => {
73547
74106
  if (selectedWeeksRange === "2" && weeks !== 2) return false;
73548
74107
  if (selectedWeeksRange === "3+" && weeks < 3) return false;
73549
74108
  }
73550
- if (selectedMemberId !== "all" && !(rec.assigned_user_ids?.includes(selectedMemberId) || rec.assigned_to_user_id === selectedMemberId)) return false;
73551
74109
  return true;
73552
- }).sort((a, b) => {
74110
+ });
74111
+ }, [recommendations, selectedLineId, selectedShift, selectedStatus, selectedWeeksRange]);
74112
+ const memberOptions = useMemo(() => {
74113
+ const uniqueAssigneeIds = /* @__PURE__ */ new Set();
74114
+ recommendationsMatchingViewFilters.forEach((recommendation) => {
74115
+ getRecommendationAssignedUserIds(recommendation).forEach((userId) => {
74116
+ uniqueAssigneeIds.add(userId);
74117
+ });
74118
+ });
74119
+ const options = Array.from(uniqueAssigneeIds).map((userId) => ({
74120
+ id: userId,
74121
+ label: teamMembersById.get(userId)?.name || userId
74122
+ })).sort((left, right) => left.label.localeCompare(right.label));
74123
+ return [{ id: "all", label: "All Members" }, ...options];
74124
+ }, [recommendationsMatchingViewFilters, teamMembersById]);
74125
+ useEffect(() => {
74126
+ if (selectedMemberId === "all") return;
74127
+ const memberStillAvailable = memberOptions.some((option) => option.id === selectedMemberId);
74128
+ if (!memberStillAvailable) {
74129
+ setSelectedMemberId("all");
74130
+ }
74131
+ }, [memberOptions, selectedMemberId]);
74132
+ const getRecommendationDisplayMetadata = React142__default.useCallback((rec) => {
74133
+ const supervisors = rec.line_id ? supervisorsByLineId.get(rec.line_id) || [] : [];
74134
+ return getImprovementDisplayMetadata({
74135
+ location: rec.location,
74136
+ line: rec.line,
74137
+ workspaceId: rec.workspace_id,
74138
+ supervisors
74139
+ });
74140
+ }, [supervisorsByLineId]);
74141
+ const filteredRecommendations = useMemo(() => {
74142
+ const hasActiveFilters = selectedLineId !== "all" || selectedStatus !== "all" || selectedShift !== "all" || selectedWeeksRange !== "all" || selectedMemberId !== "all" || selectedSortBy !== "all";
74143
+ const sortedRecommendations = recommendationsMatchingViewFilters.filter((rec) => recommendationMatchesMember(rec, selectedMemberId)).sort((a, b) => {
73553
74144
  if (selectedSortBy === "highest_to_lowest" || selectedSortBy === "lowest_to_highest") {
73554
74145
  const gainA = getImprovementPcsGainSortValue(a);
73555
74146
  const gainB = getImprovementPcsGainSortValue(b);
@@ -73580,12 +74171,8 @@ var ImprovementCenterView = () => {
73580
74171
  ];
73581
74172
  }, [
73582
74173
  focusIssueId,
73583
- recommendations,
73584
- selectedLineId,
74174
+ recommendationsMatchingViewFilters,
73585
74175
  selectedMemberId,
73586
- selectedShift,
73587
- selectedStatus,
73588
- selectedWeeksRange,
73589
74176
  selectedSortBy
73590
74177
  ]);
73591
74178
  const stats = useMemo(() => {
@@ -73598,7 +74185,7 @@ var ImprovementCenterView = () => {
73598
74185
  if (selectedWeeksRange === "2" && weeks !== 2) return false;
73599
74186
  if (selectedWeeksRange === "3+" && weeks < 3) return false;
73600
74187
  }
73601
- if (selectedMemberId !== "all" && !(rec.assigned_user_ids?.includes(selectedMemberId) || rec.assigned_to_user_id === selectedMemberId)) return false;
74188
+ if (!recommendationMatchesMember(rec, selectedMemberId)) return false;
73602
74189
  return true;
73603
74190
  });
73604
74191
  const total = baseFiltered.length;
@@ -73777,7 +74364,7 @@ var ImprovementCenterView = () => {
73777
74364
  { value: selectedSortBy, onChange: handleSortByChange, options: [{ id: "all", label: "All" }, { id: "highest_to_lowest", label: "Highest to Lowest" }, { id: "lowest_to_highest", label: "Lowest to Highest" }], label: "Priority" },
73778
74365
  { value: selectedShift, onChange: handleShiftFilterChange, options: shiftOptions, label: "Shift" },
73779
74366
  { value: selectedWeeksRange, onChange: handleWeeksFilterChange, options: weekOptions.map((o) => o.id), labels: weekOptions, label: "Duration" },
73780
- { value: selectedMemberId, onChange: handleMemberFilterChange, options: ["all", ...teamMembers.map((m) => m.id)], labels: teamMembers, label: "Member" },
74367
+ { value: selectedMemberId, onChange: handleMemberFilterChange, options: memberOptions, label: "Member" },
73781
74368
  { value: selectedLineId, onChange: handleLineFilterChange, options: lineOptions.map((o) => o.id), labels: lineOptions, label: "Line" }
73782
74369
  ].map((filter2, idx) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
73783
74370
  /* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide ml-1", children: filter2.label }),
@@ -73786,6 +74373,7 @@ var ImprovementCenterView = () => {
73786
74373
  {
73787
74374
  value: filter2.value,
73788
74375
  onChange: (e) => filter2.onChange(e.target.value),
74376
+ "aria-label": `${filter2.label} filter`,
73789
74377
  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",
73790
74378
  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` },
73791
74379
  children: filter2.options.map((opt) => {
@@ -74015,7 +74603,7 @@ var ThreadSidebar = ({
74015
74603
  ] }) })
74016
74604
  ] });
74017
74605
  };
74018
- var ProfilePicture = React141__default.memo(({
74606
+ var ProfilePicture = React142__default.memo(({
74019
74607
  alt = "Axel",
74020
74608
  className = "",
74021
74609
  size = "md",
@@ -75628,7 +76216,7 @@ var AIAgentView = () => {
75628
76216
  `
75629
76217
  } }),
75630
76218
  /* @__PURE__ */ jsxs("div", { className: `flex-1 flex flex-col h-screen transition-all duration-300 ${isSidebarOpen ? "lg:mr-80 mr-0" : "mr-0"}`, children: [
75631
- /* @__PURE__ */ jsxs("header", { className: "flex-shrink-0 bg-white px-3 sm:px-6 md:px-8 py-2 sm:py-5 md:py-6 shadow-sm border-b border-gray-200/80 sticky top-0 z-10", children: [
76219
+ /* @__PURE__ */ jsxs("header", { className: "flex-shrink-0 bg-white px-3 sm:px-6 md:px-8 py-2 sm:py-5 md:py-6 shadow-sm border-b border-gray-200/80 sticky top-0 z-40", children: [
75632
76220
  /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
75633
76221
  mobileMenuContext && /* @__PURE__ */ jsx(
75634
76222
  HamburgerButton,
@@ -76540,7 +77128,7 @@ var OverviewImprovementsSkeleton = () => /* @__PURE__ */ jsx("div", { className:
76540
77128
  ] }),
76541
77129
  /* @__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" }) })
76542
77130
  ] }, index)) });
76543
- var OperationsOverviewHeader = React141__default.memo(({
77131
+ var OperationsOverviewHeader = React142__default.memo(({
76544
77132
  dateRange,
76545
77133
  displayDateRange,
76546
77134
  trendMode,
@@ -76560,65 +77148,65 @@ var OperationsOverviewHeader = React141__default.memo(({
76560
77148
  bumpRenderCounter();
76561
77149
  const subtitleRange = displayDateRange || dateRange;
76562
77150
  const showLiveShiftMeta = isLiveScope && trendMode !== "all";
76563
- const liveShiftLabel = React141__default.useMemo(
77151
+ const liveShiftLabel = React142__default.useMemo(
76564
77152
  () => normalizeShiftLabel(liveShiftName, trendMode),
76565
77153
  [liveShiftName, trendMode]
76566
77154
  );
76567
- const liveShiftIcon = React141__default.useMemo(
77155
+ const liveShiftIcon = React142__default.useMemo(
76568
77156
  () => getShiftIcon(liveShiftName, trendMode),
76569
77157
  [liveShiftName, trendMode]
76570
77158
  );
76571
- const [isFilterOpen, setIsFilterOpen] = React141__default.useState(false);
76572
- const [isLinesDropdownOpen, setIsLinesDropdownOpen] = React141__default.useState(false);
76573
- const filterRef = React141__default.useRef(null);
76574
- const filterButtonRef = React141__default.useRef(null);
76575
- const mobileFilterButtonRef = React141__default.useRef(null);
76576
- const linesDropdownRef = React141__default.useRef(null);
76577
- const mobileSubtitle = React141__default.useMemo(() => {
77159
+ const [isFilterOpen, setIsFilterOpen] = React142__default.useState(false);
77160
+ const [isLinesDropdownOpen, setIsLinesDropdownOpen] = React142__default.useState(false);
77161
+ const filterRef = React142__default.useRef(null);
77162
+ const filterButtonRef = React142__default.useRef(null);
77163
+ const mobileFilterButtonRef = React142__default.useRef(null);
77164
+ const linesDropdownRef = React142__default.useRef(null);
77165
+ const mobileSubtitle = React142__default.useMemo(() => {
76578
77166
  if (subtitleRange.startKey === subtitleRange.endKey) {
76579
77167
  return format(parseDateKeyToDate(subtitleRange.startKey), "do MMM, yyyy");
76580
77168
  }
76581
77169
  return `${format(parseDateKeyToDate(subtitleRange.startKey), "do MMM")} - ${format(parseDateKeyToDate(subtitleRange.endKey), "do MMM, yyyy")}`;
76582
77170
  }, [subtitleRange.endKey, subtitleRange.startKey]);
76583
- const desktopSubtitle = React141__default.useMemo(() => {
77171
+ const desktopSubtitle = React142__default.useMemo(() => {
76584
77172
  if (subtitleRange.startKey === subtitleRange.endKey) {
76585
77173
  return format(parseDateKeyToDate(subtitleRange.startKey), "do MMMM, yyyy");
76586
77174
  }
76587
77175
  return `${format(parseDateKeyToDate(subtitleRange.startKey), "do MMMM, yyyy")} - ${format(parseDateKeyToDate(subtitleRange.endKey), "do MMMM, yyyy")}`;
76588
77176
  }, [subtitleRange.endKey, subtitleRange.startKey]);
76589
- const availableLineIds = React141__default.useMemo(
77177
+ const availableLineIds = React142__default.useMemo(
76590
77178
  () => lineOptions.map((line) => line.id),
76591
77179
  [lineOptions]
76592
77180
  );
76593
- const selectedLineIdSet = React141__default.useMemo(
77181
+ const selectedLineIdSet = React142__default.useMemo(
76594
77182
  () => new Set(selectedLineIds),
76595
77183
  [selectedLineIds]
76596
77184
  );
76597
- const isAllLinesSelected = React141__default.useMemo(() => {
77185
+ const isAllLinesSelected = React142__default.useMemo(() => {
76598
77186
  if (availableLineIds.length === 0) return true;
76599
77187
  return availableLineIds.every((lineId) => selectedLineIdSet.has(lineId));
76600
77188
  }, [availableLineIds, selectedLineIdSet]);
76601
- const activeFilterCount = React141__default.useMemo(() => {
77189
+ const activeFilterCount = React142__default.useMemo(() => {
76602
77190
  let count = 0;
76603
77191
  if (trendMode !== "all") count += 1;
76604
77192
  if (selectedSupervisorId !== "all") count += 1;
76605
77193
  if (!isAllLinesSelected) count += 1;
76606
77194
  return count;
76607
77195
  }, [isAllLinesSelected, selectedSupervisorId, trendMode]);
76608
- const handleFilterToggle = React141__default.useCallback(() => {
77196
+ const handleFilterToggle = React142__default.useCallback(() => {
76609
77197
  trackCoreEvent("Operations Overview Filter Toggled", {
76610
77198
  action: !isFilterOpen ? "open" : "close"
76611
77199
  });
76612
77200
  setIsFilterOpen((previous) => !previous);
76613
77201
  }, [isFilterOpen]);
76614
- const handleTrendModeChange = React141__default.useCallback((event) => {
77202
+ const handleTrendModeChange = React142__default.useCallback((event) => {
76615
77203
  const nextMode = event.target.value;
76616
77204
  trackCoreEvent("Operations Overview Shift Filter Changed", {
76617
77205
  shift_mode: nextMode
76618
77206
  });
76619
77207
  onTrendModeChange(nextMode);
76620
77208
  }, [onTrendModeChange]);
76621
- const handleAllLinesToggle = React141__default.useCallback(() => {
77209
+ const handleAllLinesToggle = React142__default.useCallback(() => {
76622
77210
  trackCoreEvent("Operations Overview Line Filter Changed", {
76623
77211
  selected_line_ids: availableLineIds,
76624
77212
  selected_line_count: availableLineIds.length,
@@ -76626,7 +77214,7 @@ var OperationsOverviewHeader = React141__default.memo(({
76626
77214
  });
76627
77215
  onSelectedLineIdsChange(availableLineIds);
76628
77216
  }, [availableLineIds, onSelectedLineIdsChange]);
76629
- const handleSupervisorChange = React141__default.useCallback((event) => {
77217
+ const handleSupervisorChange = React142__default.useCallback((event) => {
76630
77218
  const supervisorId = event.target.value;
76631
77219
  const selectedSupervisor = supervisorOptions.find((option) => option.id === supervisorId);
76632
77220
  trackCoreEvent("Operations Overview Supervisor Filter Changed", {
@@ -76637,7 +77225,7 @@ var OperationsOverviewHeader = React141__default.memo(({
76637
77225
  });
76638
77226
  onSelectedSupervisorIdChange(supervisorId);
76639
77227
  }, [availableLineIds, onSelectedSupervisorIdChange, supervisorOptions]);
76640
- const handleLineToggle = React141__default.useCallback((lineId) => {
77228
+ const handleLineToggle = React142__default.useCallback((lineId) => {
76641
77229
  const current = new Set(selectedLineIds);
76642
77230
  if (current.has(lineId)) {
76643
77231
  if (current.size <= 1) return;
@@ -76653,13 +77241,13 @@ var OperationsOverviewHeader = React141__default.memo(({
76653
77241
  });
76654
77242
  onSelectedLineIdsChange(next);
76655
77243
  }, [availableLineIds, onSelectedLineIdsChange, selectedLineIds]);
76656
- const handleClearAllFilters = React141__default.useCallback(() => {
77244
+ const handleClearAllFilters = React142__default.useCallback(() => {
76657
77245
  onTrendModeChange("all");
76658
77246
  onSelectedSupervisorIdChange("all");
76659
77247
  onSelectedLineIdsChange(availableLineIds);
76660
77248
  setIsFilterOpen(false);
76661
77249
  }, [availableLineIds, onSelectedLineIdsChange, onSelectedSupervisorIdChange, onTrendModeChange]);
76662
- React141__default.useEffect(() => {
77250
+ React142__default.useEffect(() => {
76663
77251
  const handleClickOutside = (event) => {
76664
77252
  const target = event.target;
76665
77253
  if (filterRef.current && !filterRef.current.contains(target) && filterButtonRef.current && !filterButtonRef.current.contains(target) && mobileFilterButtonRef.current && !mobileFilterButtonRef.current.contains(target)) {
@@ -76674,7 +77262,7 @@ var OperationsOverviewHeader = React141__default.memo(({
76674
77262
  document.removeEventListener("mousedown", handleClickOutside);
76675
77263
  };
76676
77264
  }, []);
76677
- return /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-10 bg-white border-b flex-shrink-0 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3 relative", children: [
77265
+ return /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-40 bg-white border-b flex-shrink-0 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3 relative", children: [
76678
77266
  /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
76679
77267
  mobileMenuContext ? /* @__PURE__ */ jsx(
76680
77268
  HamburgerButton,
@@ -76898,12 +77486,12 @@ var OperationsOverviewHeader = React141__default.memo(({
76898
77486
  ] }) });
76899
77487
  });
76900
77488
  OperationsOverviewHeader.displayName = "OperationsOverviewHeader";
76901
- var OverviewSummaryCards = React141__default.memo(({ store }) => {
77489
+ var OverviewSummaryCards = React142__default.memo(({ store }) => {
76902
77490
  bumpRenderCounter();
76903
77491
  const scope = useOperationsOverviewScope(store);
76904
77492
  const snapshot = useOperationsOverviewSnapshot(store);
76905
77493
  const showSnapshotSkeleton = snapshot.loading && !snapshot.hasLoadedOnce;
76906
- const comparisonLabel = React141__default.useMemo(() => {
77494
+ const comparisonLabel = React142__default.useMemo(() => {
76907
77495
  return formatComparisonWindow({
76908
77496
  currentDayCount: scope.current_range?.day_count ?? null,
76909
77497
  previousDayCount: scope.previous_range?.day_count ?? null,
@@ -76916,27 +77504,27 @@ var OverviewSummaryCards = React141__default.memo(({ store }) => {
76916
77504
  scope.previous_range?.day_count,
76917
77505
  scope.shift_mode
76918
77506
  ]);
76919
- const [isIdleContributorsOpen, setIsIdleContributorsOpen] = React141__default.useState(false);
76920
- const [isIdleContributorsPinned, setIsIdleContributorsPinned] = React141__default.useState(false);
76921
- const idleContributorsRef = React141__default.useRef(null);
76922
- const plantEfficiencyBadge = React141__default.useMemo(() => {
77507
+ const [isIdleContributorsOpen, setIsIdleContributorsOpen] = React142__default.useState(false);
77508
+ const [isIdleContributorsPinned, setIsIdleContributorsPinned] = React142__default.useState(false);
77509
+ const idleContributorsRef = React142__default.useRef(null);
77510
+ const plantEfficiencyBadge = React142__default.useMemo(() => {
76923
77511
  return buildDeltaBadge(snapshot.data.summary.plant_efficiency?.delta_pp, {
76924
77512
  positiveIsGood: true,
76925
77513
  formatter: (value) => `${value >= 0 ? "+" : ""}${roundOne(value)}%`,
76926
77514
  comparisonLabel
76927
77515
  });
76928
77516
  }, [comparisonLabel, snapshot.data.summary.plant_efficiency?.delta_pp]);
76929
- const idleBadge = React141__default.useMemo(() => {
77517
+ const idleBadge = React142__default.useMemo(() => {
76930
77518
  return buildDeltaBadge(snapshot.data.summary.avg_idle_per_workstation?.delta_seconds, {
76931
77519
  positiveIsGood: false,
76932
77520
  formatter: (value) => formatSignedIdleDuration(value),
76933
77521
  comparisonLabel
76934
77522
  });
76935
77523
  }, [comparisonLabel, snapshot.data.summary.avg_idle_per_workstation?.delta_seconds]);
76936
- const canInspectIdleContributors = React141__default.useMemo(() => {
77524
+ const canInspectIdleContributors = React142__default.useMemo(() => {
76937
77525
  return !showSnapshotSkeleton && snapshot.data.summary.avg_idle_per_workstation?.current_seconds !== null && snapshot.data.summary.avg_idle_per_workstation?.current_seconds !== void 0;
76938
77526
  }, [showSnapshotSkeleton, snapshot.data.summary.avg_idle_per_workstation?.current_seconds]);
76939
- const idleTopContributors = React141__default.useMemo(() => {
77527
+ const idleTopContributors = React142__default.useMemo(() => {
76940
77528
  return (snapshot.data.summary.avg_idle_per_workstation?.top_contributors || []).map((item) => ({
76941
77529
  workspaceId: item.workspace_id || "",
76942
77530
  workspaceName: item.workspace_name?.trim() || item.workspace_id || "Unknown",
@@ -76944,14 +77532,14 @@ var OverviewSummaryCards = React141__default.memo(({ store }) => {
76944
77532
  avgIdleSeconds: toNumber3(item.avg_idle_seconds)
76945
77533
  })).slice(0, 5);
76946
77534
  }, [snapshot.data.summary.avg_idle_per_workstation?.top_contributors]);
76947
- const showIdleContributorLineNames = React141__default.useMemo(() => {
77535
+ const showIdleContributorLineNames = React142__default.useMemo(() => {
76948
77536
  return (scope.line_count ?? 0) > 1;
76949
77537
  }, [scope.line_count]);
76950
- const closeIdleContributors = React141__default.useCallback(() => {
77538
+ const closeIdleContributors = React142__default.useCallback(() => {
76951
77539
  setIsIdleContributorsOpen(false);
76952
77540
  setIsIdleContributorsPinned(false);
76953
77541
  }, []);
76954
- const handleIdleContributorsToggle = React141__default.useCallback(() => {
77542
+ const handleIdleContributorsToggle = React142__default.useCallback(() => {
76955
77543
  if (!canInspectIdleContributors) return;
76956
77544
  setIsIdleContributorsPinned((previous) => {
76957
77545
  const next = !previous;
@@ -76959,7 +77547,7 @@ var OverviewSummaryCards = React141__default.memo(({ store }) => {
76959
77547
  return next;
76960
77548
  });
76961
77549
  }, [canInspectIdleContributors]);
76962
- const handleIdleContributorsKeyDown = React141__default.useCallback((event) => {
77550
+ const handleIdleContributorsKeyDown = React142__default.useCallback((event) => {
76963
77551
  if (!canInspectIdleContributors) return;
76964
77552
  if (event.key === "Enter" || event.key === " ") {
76965
77553
  event.preventDefault();
@@ -76971,11 +77559,11 @@ var OverviewSummaryCards = React141__default.memo(({ store }) => {
76971
77559
  closeIdleContributors();
76972
77560
  }
76973
77561
  }, [canInspectIdleContributors, closeIdleContributors, handleIdleContributorsToggle]);
76974
- React141__default.useEffect(() => {
77562
+ React142__default.useEffect(() => {
76975
77563
  setIsIdleContributorsOpen(false);
76976
77564
  setIsIdleContributorsPinned(false);
76977
77565
  }, [scope.comparison_strategy, scope.current_range?.start_date, scope.current_range?.end_date, scope.line_count, scope.shift_mode]);
76978
- React141__default.useEffect(() => {
77566
+ React142__default.useEffect(() => {
76979
77567
  if (!isIdleContributorsOpen) return void 0;
76980
77568
  const handleClickOutside = (event) => {
76981
77569
  if (!isIdleContributorsPinned) return;
@@ -77113,7 +77701,7 @@ var OverviewSummaryCards = React141__default.memo(({ store }) => {
77113
77701
  ] });
77114
77702
  });
77115
77703
  OverviewSummaryCards.displayName = "OverviewSummaryCards";
77116
- var PoorestPerformersCard = React141__default.memo(({
77704
+ var PoorestPerformersCard = React142__default.memo(({
77117
77705
  store,
77118
77706
  supervisorsByLineId,
77119
77707
  onViewAll,
@@ -77122,9 +77710,9 @@ var PoorestPerformersCard = React141__default.memo(({
77122
77710
  bumpRenderCounter();
77123
77711
  const scope = useOperationsOverviewScope(store);
77124
77712
  const snapshot = useOperationsOverviewSnapshot(store);
77125
- const [poorestLineMode, setPoorestLineMode] = React141__default.useState("output");
77713
+ const [poorestLineMode, setPoorestLineMode] = React142__default.useState("output");
77126
77714
  const availableLineModes = scope.available_line_modes;
77127
- React141__default.useEffect(() => {
77715
+ React142__default.useEffect(() => {
77128
77716
  const hasOutput = !!availableLineModes?.has_output;
77129
77717
  const hasUptime = !!availableLineModes?.has_uptime;
77130
77718
  if (hasOutput && !hasUptime && poorestLineMode !== "output") {
@@ -77133,7 +77721,7 @@ var PoorestPerformersCard = React141__default.memo(({
77133
77721
  setPoorestLineMode("uptime");
77134
77722
  }
77135
77723
  }, [availableLineModes?.has_output, availableLineModes?.has_uptime, poorestLineMode]);
77136
- const comparisonLabel = React141__default.useMemo(() => {
77724
+ const comparisonLabel = React142__default.useMemo(() => {
77137
77725
  return formatComparisonWindow({
77138
77726
  currentDayCount: scope.current_range?.day_count ?? null,
77139
77727
  previousDayCount: scope.previous_range?.day_count ?? null,
@@ -77147,7 +77735,7 @@ var PoorestPerformersCard = React141__default.memo(({
77147
77735
  scope.shift_mode
77148
77736
  ]);
77149
77737
  const showSnapshotSkeleton = snapshot.loading && !snapshot.hasLoadedOnce;
77150
- const mergedPoorestLines = React141__default.useMemo(() => {
77738
+ const mergedPoorestLines = React142__default.useMemo(() => {
77151
77739
  const rows = snapshot.data.poorest_lines?.[poorestLineMode] || [];
77152
77740
  return rows.slice(0, 3).map((line) => {
77153
77741
  const lineId = line.line_id || "";
@@ -77166,7 +77754,7 @@ var PoorestPerformersCard = React141__default.memo(({
77166
77754
  }, [poorestLineMode, snapshot.data.poorest_lines, supervisorsByLineId]);
77167
77755
  const showPoorestModeToggle = !!availableLineModes?.has_output && !!availableLineModes?.has_uptime;
77168
77756
  const poorestMetricLabel = poorestLineMode === "uptime" ? "Uptime" : "Efficiency";
77169
- const handlePoorestLineModeChange = React141__default.useCallback((mode) => {
77757
+ const handlePoorestLineModeChange = React142__default.useCallback((mode) => {
77170
77758
  trackCoreEvent("Operations Overview Poorest Line Mode Changed", { mode });
77171
77759
  setPoorestLineMode(mode);
77172
77760
  }, []);
@@ -77252,14 +77840,14 @@ var PoorestPerformersCard = React141__default.memo(({
77252
77840
  ] });
77253
77841
  });
77254
77842
  PoorestPerformersCard.displayName = "PoorestPerformersCard";
77255
- var IdleBreakdownCard = React141__default.memo(({
77843
+ var IdleBreakdownCard = React142__default.memo(({
77256
77844
  store,
77257
77845
  scopedLineCount
77258
77846
  }) => {
77259
77847
  bumpRenderCounter();
77260
77848
  const idle = useOperationsOverviewIdle(store);
77261
77849
  const showInitialSkeleton = idle.loading && idle.lastUpdated === null;
77262
- const idleBreakdown = React141__default.useMemo(() => {
77850
+ const idleBreakdown = React142__default.useMemo(() => {
77263
77851
  return idle.data.map((item) => ({
77264
77852
  name: item.display_name?.trim() || item.reason?.trim() || "Unknown",
77265
77853
  reasonKey: item.reason_key?.trim() || item.reason?.trim() || "unknown",
@@ -77278,7 +77866,7 @@ var IdleBreakdownCard = React141__default.memo(({
77278
77866
  }))
77279
77867
  })).filter((item) => item.value > 0);
77280
77868
  }, [idle.data]);
77281
- const showIdleModuleNotEnabledState = React141__default.useMemo(() => {
77869
+ const showIdleModuleNotEnabledState = React142__default.useMemo(() => {
77282
77870
  const enabledLineCount = idle.scope.idle_time_vlm_enabled_line_count;
77283
77871
  return !showInitialSkeleton && scopedLineCount > 0 && typeof enabledLineCount === "number" && enabledLineCount === 0;
77284
77872
  }, [idle.scope.idle_time_vlm_enabled_line_count, scopedLineCount, showInitialSkeleton]);
@@ -77299,7 +77887,7 @@ var IdleBreakdownCard = React141__default.memo(({
77299
77887
  ] });
77300
77888
  });
77301
77889
  IdleBreakdownCard.displayName = "IdleBreakdownCard";
77302
- var EfficiencyTrendCard = React141__default.memo(({
77890
+ var EfficiencyTrendCard = React142__default.memo(({
77303
77891
  store,
77304
77892
  dateRange,
77305
77893
  appTimezone,
@@ -77307,14 +77895,14 @@ var EfficiencyTrendCard = React141__default.memo(({
77307
77895
  }) => {
77308
77896
  bumpRenderCounter();
77309
77897
  const trend = useOperationsOverviewTrend(store);
77310
- const currentWeekRange = React141__default.useMemo(
77898
+ const currentWeekRange = React142__default.useMemo(
77311
77899
  () => getCurrentWeekToDateRange(appTimezone),
77312
77900
  [appTimezone]
77313
77901
  );
77314
77902
  const isCurrentWeekToDateRange = dateRange.startKey === currentWeekRange.startKey && dateRange.endKey === currentWeekRange.endKey;
77315
77903
  const showInitialSkeleton = trend.loading && trend.lastUpdated === null;
77316
77904
  const isHourlyTrend = trend.data.granularity === "hour";
77317
- const trendData = React141__default.useMemo(() => {
77905
+ const trendData = React142__default.useMemo(() => {
77318
77906
  if (isHourlyTrend) {
77319
77907
  return (trend.data.points || []).map((point, index) => ({
77320
77908
  name: (() => {
@@ -77386,13 +77974,13 @@ var EfficiencyTrendCard = React141__default.memo(({
77386
77974
  };
77387
77975
  });
77388
77976
  }, [currentWeekRange.startKey, hourlyLabelStartTime, isCurrentWeekToDateRange, isHourlyTrend, trend.data.points]);
77389
- const trendTooltipLabelFormatter = React141__default.useCallback((label, payload) => {
77977
+ const trendTooltipLabelFormatter = React142__default.useCallback((label, payload) => {
77390
77978
  if (isHourlyTrend) return label;
77391
77979
  const dayOfWeek = payload?.[0]?.payload?.dayOfWeek;
77392
77980
  if (!dayOfWeek || typeof label !== "string") return label;
77393
77981
  return `${label} (${dayOfWeek})`;
77394
77982
  }, [isHourlyTrend]);
77395
- const trendXAxisTickFormatter = React141__default.useCallback((value, index) => {
77983
+ const trendXAxisTickFormatter = React142__default.useCallback((value, index) => {
77396
77984
  if (!isHourlyTrend) {
77397
77985
  return typeof value === "string" ? value : String(value ?? "");
77398
77986
  }
@@ -77419,7 +78007,7 @@ var EfficiencyTrendCard = React141__default.memo(({
77419
78007
  ] });
77420
78008
  });
77421
78009
  EfficiencyTrendCard.displayName = "EfficiencyTrendCard";
77422
- var TopImprovementsCard = React141__default.memo(({
78010
+ var TopImprovementsCard = React142__default.memo(({
77423
78011
  store,
77424
78012
  supervisorsByLineId,
77425
78013
  onViewAll,
@@ -77428,7 +78016,7 @@ var TopImprovementsCard = React141__default.memo(({
77428
78016
  bumpRenderCounter();
77429
78017
  const improvements = useOperationsOverviewImprovements(store);
77430
78018
  const showInitialSkeleton = improvements.loading && improvements.lastUpdated === null;
77431
- const displayImprovements = React141__default.useMemo(() => {
78019
+ const displayImprovements = React142__default.useMemo(() => {
77432
78020
  return improvements.data.map((item) => {
77433
78021
  const supervisors = item.lineId ? supervisorsByLineId.get(item.lineId) || [] : [];
77434
78022
  return {
@@ -77465,7 +78053,7 @@ var TopImprovementsCard = React141__default.memo(({
77465
78053
  className: "flex items-center justify-between py-3 border-b border-slate-50 last:border-0 group cursor-pointer",
77466
78054
  children: [
77467
78055
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 flex-1 min-w-0 pr-4", children: [
77468
- item.ticketLabel ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-full border border-indigo-100 bg-indigo-50 px-2 py-0.5 text-[10px] font-semibold text-indigo-600", children: item.ticketLabel }) }) : null,
78056
+ item.ticketLabel ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-start flex-shrink-0 w-16", children: /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center min-w-[48px] max-w-[64px] truncate rounded-full border border-indigo-100 bg-indigo-50 px-2 py-0.5 text-[10px] font-semibold text-indigo-600", children: item.ticketLabel }) }) : null,
77469
78057
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
77470
78058
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 min-w-0 mb-0.5", children: /* @__PURE__ */ jsx("h4", { className: "text-[13px] font-semibold text-slate-800 truncate transition-colors group-hover:text-indigo-600", children: item.title }) }),
77471
78059
  /* @__PURE__ */ jsx(
@@ -77556,33 +78144,33 @@ var useOperationsOverviewRefresh = ({
77556
78144
  isLiveScope,
77557
78145
  enabled = true
77558
78146
  }) => {
77559
- const lineIdsKey = React141__default.useMemo(() => lineIds.join(","), [lineIds]);
77560
- const scopeSignature = React141__default.useMemo(
78147
+ const lineIdsKey = React142__default.useMemo(() => lineIds.join(","), [lineIds]);
78148
+ const scopeSignature = React142__default.useMemo(
77561
78149
  () => [companyId || "", startKey, endKey, trendMode, comparisonStrategy || "", lineIdsKey].join("::"),
77562
78150
  [companyId, comparisonStrategy, endKey, lineIdsKey, startKey, trendMode]
77563
78151
  );
77564
- const controllersRef = React141__default.useRef({});
77565
- const requestIdsRef = React141__default.useRef({
78152
+ const controllersRef = React142__default.useRef({});
78153
+ const requestIdsRef = React142__default.useRef({
77566
78154
  snapshot: 0,
77567
78155
  trend: 0,
77568
78156
  idle: 0,
77569
78157
  improvements: 0
77570
78158
  });
77571
- const intervalRef = React141__default.useRef(null);
77572
- const isPageActiveRef = React141__default.useRef(true);
77573
- const lastResumeRefreshAtRef = React141__default.useRef(0);
77574
- const abortAll = React141__default.useCallback(() => {
78159
+ const intervalRef = React142__default.useRef(null);
78160
+ const isPageActiveRef = React142__default.useRef(true);
78161
+ const lastResumeRefreshAtRef = React142__default.useRef(0);
78162
+ const abortAll = React142__default.useCallback(() => {
77575
78163
  Object.values(controllersRef.current).forEach((controller) => {
77576
78164
  controller?.abort();
77577
78165
  });
77578
78166
  controllersRef.current = {};
77579
78167
  }, []);
77580
- React141__default.useEffect(() => {
78168
+ React142__default.useEffect(() => {
77581
78169
  return () => {
77582
78170
  abortAll();
77583
78171
  };
77584
78172
  }, [abortAll]);
77585
- const getIsPageActive = React141__default.useCallback(() => {
78173
+ const getIsPageActive = React142__default.useCallback(() => {
77586
78174
  if (typeof document === "undefined") {
77587
78175
  return true;
77588
78176
  }
@@ -77590,7 +78178,7 @@ var useOperationsOverviewRefresh = ({
77590
78178
  const hasFocus = typeof document.hasFocus === "function" ? document.hasFocus() : true;
77591
78179
  return isVisible && hasFocus;
77592
78180
  }, []);
77593
- const stopPolling = React141__default.useCallback((reason) => {
78181
+ const stopPolling = React142__default.useCallback((reason) => {
77594
78182
  if (intervalRef.current === null) {
77595
78183
  return;
77596
78184
  }
@@ -77598,7 +78186,7 @@ var useOperationsOverviewRefresh = ({
77598
78186
  intervalRef.current = null;
77599
78187
  debugRefreshLog("poll stopped", { reason });
77600
78188
  }, []);
77601
- const runRefresh = React141__default.useCallback(
78189
+ const runRefresh = React142__default.useCallback(
77602
78190
  async (section, begin, onSuccess, onError, request, reason) => {
77603
78191
  if (!enabled || !supabase || !companyId || lineIds.length === 0) return;
77604
78192
  const requestId = requestIdsRef.current[section] + 1;
@@ -77622,7 +78210,7 @@ var useOperationsOverviewRefresh = ({
77622
78210
  },
77623
78211
  [companyId, enabled, lineIds.length, supabase]
77624
78212
  );
77625
- const refreshSnapshot = React141__default.useCallback(
78213
+ const refreshSnapshot = React142__default.useCallback(
77626
78214
  async (reason) => {
77627
78215
  await runRefresh(
77628
78216
  "snapshot",
@@ -77654,7 +78242,7 @@ var useOperationsOverviewRefresh = ({
77654
78242
  },
77655
78243
  [companyId, comparisonStrategy, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
77656
78244
  );
77657
- const refreshTrend = React141__default.useCallback(
78245
+ const refreshTrend = React142__default.useCallback(
77658
78246
  async (reason) => {
77659
78247
  await runRefresh(
77660
78248
  "trend",
@@ -77683,7 +78271,7 @@ var useOperationsOverviewRefresh = ({
77683
78271
  },
77684
78272
  [companyId, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
77685
78273
  );
77686
- const refreshIdle = React141__default.useCallback(
78274
+ const refreshIdle = React142__default.useCallback(
77687
78275
  async (reason) => {
77688
78276
  await runRefresh(
77689
78277
  "idle",
@@ -77712,7 +78300,7 @@ var useOperationsOverviewRefresh = ({
77712
78300
  },
77713
78301
  [companyId, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
77714
78302
  );
77715
- const refreshImprovements = React141__default.useCallback(
78303
+ const refreshImprovements = React142__default.useCallback(
77716
78304
  async (reason) => {
77717
78305
  await runRefresh(
77718
78306
  "improvements",
@@ -77742,7 +78330,7 @@ var useOperationsOverviewRefresh = ({
77742
78330
  },
77743
78331
  [companyId, lineIds, lineIdsKey, runRefresh, scopeSignature, store, supabase]
77744
78332
  );
77745
- const refreshAll = React141__default.useCallback(
78333
+ const refreshAll = React142__default.useCallback(
77746
78334
  async (reason) => {
77747
78335
  await Promise.allSettled([
77748
78336
  refreshSnapshot(reason),
@@ -77753,7 +78341,7 @@ var useOperationsOverviewRefresh = ({
77753
78341
  },
77754
78342
  [refreshIdle, refreshImprovements, refreshSnapshot, refreshTrend]
77755
78343
  );
77756
- const startPolling = React141__default.useCallback((reason) => {
78344
+ const startPolling = React142__default.useCallback((reason) => {
77757
78345
  if (!isLiveScope || !supabase || !companyId || lineIds.length === 0) {
77758
78346
  return;
77759
78347
  }
@@ -77774,7 +78362,7 @@ var useOperationsOverviewRefresh = ({
77774
78362
  }, LIVE_REFRESH_INTERVAL_MS);
77775
78363
  debugRefreshLog("poll started", { reason, intervalMs: LIVE_REFRESH_INTERVAL_MS });
77776
78364
  }, [companyId, isLiveScope, lineIds.length, refreshAll, stopPolling, supabase]);
77777
- const refreshFromResume = React141__default.useCallback((reason) => {
78365
+ const refreshFromResume = React142__default.useCallback((reason) => {
77778
78366
  const now4 = Date.now();
77779
78367
  if (now4 - lastResumeRefreshAtRef.current < 1e3) {
77780
78368
  debugRefreshLog("resume refresh suppressed", { reason });
@@ -77789,7 +78377,7 @@ var useOperationsOverviewRefresh = ({
77789
78377
  }
77790
78378
  });
77791
78379
  }, [refreshAll, startPolling, stopPolling]);
77792
- React141__default.useEffect(() => {
78380
+ React142__default.useEffect(() => {
77793
78381
  if (!enabled) {
77794
78382
  stopPolling("disabled");
77795
78383
  abortAll();
@@ -77804,7 +78392,7 @@ var useOperationsOverviewRefresh = ({
77804
78392
  }
77805
78393
  void refreshAll("scope_change");
77806
78394
  }, [abortAll, companyId, enabled, lineIds.length, refreshAll, scopeSignature, stopPolling, store, supabase]);
77807
- React141__default.useEffect(() => {
78395
+ React142__default.useEffect(() => {
77808
78396
  if (!enabled || !isLiveScope || !supabase || !companyId || lineIds.length === 0) {
77809
78397
  isPageActiveRef.current = false;
77810
78398
  stopPolling("live_scope_disabled");
@@ -77979,55 +78567,55 @@ var PlantHeadView = () => {
77979
78567
  const { accessibleLineIds } = useUserLineAccess();
77980
78568
  const mobileMenuContext = useMobileMenu();
77981
78569
  useHideMobileHeader(!!mobileMenuContext);
77982
- const storeRef = React141__default.useRef(createOperationsOverviewStore());
78570
+ const storeRef = React142__default.useRef(createOperationsOverviewStore());
77983
78571
  const store = storeRef.current;
77984
- const fallbackOperationalDate = React141__default.useMemo(
78572
+ const fallbackOperationalDate = React142__default.useMemo(
77985
78573
  () => getOperationalDate(appTimezone),
77986
78574
  [appTimezone]
77987
78575
  );
77988
- const [dateRange, setDateRange] = React141__default.useState(() => ({
78576
+ const [dateRange, setDateRange] = React142__default.useState(() => ({
77989
78577
  startKey: fallbackOperationalDate,
77990
78578
  endKey: fallbackOperationalDate
77991
78579
  }));
77992
- const [usesThisWeekComparison, setUsesThisWeekComparison] = React141__default.useState(false);
77993
- const [trendMode, setTrendMode] = React141__default.useState("all");
77994
- const [selectedSupervisorId, setSelectedSupervisorId] = React141__default.useState("all");
77995
- const [selectedLineIds, setSelectedLineIds] = React141__default.useState([]);
77996
- const [isInitialScopeReady, setIsInitialScopeReady] = React141__default.useState(false);
77997
- const [shiftResolutionTick, setShiftResolutionTick] = React141__default.useState(0);
77998
- const hasAutoInitializedScopeRef = React141__default.useRef(false);
77999
- const hasUserAdjustedScopeRef = React141__default.useRef(false);
78000
- React141__default.useEffect(() => {
78580
+ const [usesThisWeekComparison, setUsesThisWeekComparison] = React142__default.useState(false);
78581
+ const [trendMode, setTrendMode] = React142__default.useState("all");
78582
+ const [selectedSupervisorId, setSelectedSupervisorId] = React142__default.useState("all");
78583
+ const [selectedLineIds, setSelectedLineIds] = React142__default.useState([]);
78584
+ const [isInitialScopeReady, setIsInitialScopeReady] = React142__default.useState(false);
78585
+ const [shiftResolutionTick, setShiftResolutionTick] = React142__default.useState(0);
78586
+ const hasAutoInitializedScopeRef = React142__default.useRef(false);
78587
+ const hasUserAdjustedScopeRef = React142__default.useRef(false);
78588
+ React142__default.useEffect(() => {
78001
78589
  trackCorePageView("Operations Overview", {
78002
78590
  dashboard_surface: "operations_overview"
78003
78591
  });
78004
78592
  }, []);
78005
- const currentWeekRange = React141__default.useMemo(
78593
+ const currentWeekRange = React142__default.useMemo(
78006
78594
  () => getCurrentWeekToDateRange(appTimezone),
78007
78595
  [appTimezone]
78008
78596
  );
78009
- const currentWeekDisplayRange = React141__default.useMemo(
78597
+ const currentWeekDisplayRange = React142__default.useMemo(
78010
78598
  () => getCurrentWeekFullRange(appTimezone),
78011
78599
  [appTimezone]
78012
78600
  );
78013
78601
  const isCurrentWeekToDateRange = dateRange.startKey === currentWeekRange.startKey && dateRange.endKey === currentWeekRange.endKey;
78014
- const headerDateRange = React141__default.useMemo(() => {
78602
+ const headerDateRange = React142__default.useMemo(() => {
78015
78603
  if (usesThisWeekComparison && isCurrentWeekToDateRange) {
78016
78604
  return currentWeekDisplayRange;
78017
78605
  }
78018
78606
  return dateRange;
78019
78607
  }, [currentWeekDisplayRange, dateRange, isCurrentWeekToDateRange, usesThisWeekComparison]);
78020
- const normalizedLineIds = React141__default.useMemo(
78608
+ const normalizedLineIds = React142__default.useMemo(
78021
78609
  () => Array.from(new Set(
78022
78610
  (accessibleLineIds || []).filter(Boolean).filter((lineId) => lineId !== factoryViewId)
78023
78611
  )).sort(),
78024
78612
  [accessibleLineIds, factoryViewId]
78025
78613
  );
78026
- const lineIdsKey = React141__default.useMemo(
78614
+ const lineIdsKey = React142__default.useMemo(
78027
78615
  () => normalizedLineIds.join(","),
78028
78616
  [normalizedLineIds]
78029
78617
  );
78030
- const lineOptions = React141__default.useMemo(
78618
+ const lineOptions = React142__default.useMemo(
78031
78619
  () => normalizedLineIds.map((lineId) => ({
78032
78620
  id: lineId,
78033
78621
  name: getLineDisplayName(entityConfig, lineId)
@@ -78039,7 +78627,7 @@ var PlantHeadView = () => {
78039
78627
  companyId: entityConfig.companyId,
78040
78628
  useBackend: true
78041
78629
  });
78042
- const supervisorOptions = React141__default.useMemo(
78630
+ const supervisorOptions = React142__default.useMemo(
78043
78631
  () => {
78044
78632
  const optionsById = /* @__PURE__ */ new Map();
78045
78633
  normalizedLineIds.forEach((lineId) => {
@@ -78065,7 +78653,7 @@ var PlantHeadView = () => {
78065
78653
  },
78066
78654
  [normalizedLineIds, supervisorsByLineId]
78067
78655
  );
78068
- React141__default.useEffect(() => {
78656
+ React142__default.useEffect(() => {
78069
78657
  if (selectedSupervisorId === "all") {
78070
78658
  setSelectedLineIds((previous) => {
78071
78659
  if (normalizedLineIds.length === 0) {
@@ -78091,7 +78679,7 @@ var PlantHeadView = () => {
78091
78679
  const scopedSupervisorLineIds = normalizedLineIds.filter((lineId) => supervisorLineIdSet.has(lineId));
78092
78680
  setSelectedLineIds((previous) => previous.length === scopedSupervisorLineIds.length && previous.every((lineId, index) => lineId === scopedSupervisorLineIds[index]) ? previous : scopedSupervisorLineIds);
78093
78681
  }, [lineIdsKey, normalizedLineIds, selectedSupervisorId, supervisorOptions]);
78094
- const scopedLineIds = React141__default.useMemo(
78682
+ const scopedLineIds = React142__default.useMemo(
78095
78683
  () => selectedLineIds.length > 0 ? selectedLineIds : normalizedLineIds,
78096
78684
  [normalizedLineIds, selectedLineIds]
78097
78685
  );
@@ -78099,7 +78687,7 @@ var PlantHeadView = () => {
78099
78687
  shiftConfigMap,
78100
78688
  isLoading: isShiftConfigLoading
78101
78689
  } = useMultiLineShiftConfigs(scopedLineIds, staticShiftConfig);
78102
- React141__default.useEffect(() => {
78690
+ React142__default.useEffect(() => {
78103
78691
  if (scopedLineIds.length === 0 || isShiftConfigLoading) {
78104
78692
  return;
78105
78693
  }
@@ -78110,11 +78698,11 @@ var PlantHeadView = () => {
78110
78698
  clearInterval(intervalId);
78111
78699
  };
78112
78700
  }, [isShiftConfigLoading, scopedLineIds.length]);
78113
- const shiftResolutionNow = React141__default.useMemo(
78701
+ const shiftResolutionNow = React142__default.useMemo(
78114
78702
  () => /* @__PURE__ */ new Date(),
78115
78703
  [shiftResolutionTick]
78116
78704
  );
78117
- const earliestDayShiftStartTime = React141__default.useMemo(() => {
78705
+ const earliestDayShiftStartTime = React142__default.useMemo(() => {
78118
78706
  const candidateStarts = [];
78119
78707
  scopedLineIds.forEach((lineId) => {
78120
78708
  const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
@@ -78150,11 +78738,11 @@ var PlantHeadView = () => {
78150
78738
  const minutes = earliestMinutes % 60;
78151
78739
  return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
78152
78740
  }, [appTimezone, scopedLineIds, shiftConfigMap, staticShiftConfig]);
78153
- const resolvedOperationalToday = React141__default.useMemo(
78741
+ const resolvedOperationalToday = React142__default.useMemo(
78154
78742
  () => getOperationalDate(appTimezone, shiftResolutionNow, earliestDayShiftStartTime),
78155
78743
  [appTimezone, earliestDayShiftStartTime, shiftResolutionNow]
78156
78744
  );
78157
- const activeLineShiftStates = React141__default.useMemo(() => {
78745
+ const activeLineShiftStates = React142__default.useMemo(() => {
78158
78746
  return scopedLineIds.flatMap((lineId) => {
78159
78747
  const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
78160
78748
  const activeShift = getActiveShift(appTimezone, shiftConfig, shiftResolutionNow);
@@ -78181,16 +78769,16 @@ var PlantHeadView = () => {
78181
78769
  }];
78182
78770
  });
78183
78771
  }, [appTimezone, scopedLineIds, shiftConfigMap, shiftResolutionNow, staticShiftConfig]);
78184
- const hasActiveDayShiftLine = React141__default.useMemo(
78772
+ const hasActiveDayShiftLine = React142__default.useMemo(
78185
78773
  () => activeLineShiftStates.some((shift) => shift.trendMode === "day" && shift.date === resolvedOperationalToday),
78186
78774
  [activeLineShiftStates, resolvedOperationalToday]
78187
78775
  );
78188
- const hasActiveNightShiftLine = React141__default.useMemo(
78776
+ const hasActiveNightShiftLine = React142__default.useMemo(
78189
78777
  () => activeLineShiftStates.some((shift) => shift.trendMode === "night" && shift.date === resolvedOperationalToday),
78190
78778
  [activeLineShiftStates, resolvedOperationalToday]
78191
78779
  );
78192
78780
  const resolvedTrendMode = isInitialScopeReady ? trendMode : "all";
78193
- const hourlyWindowStartTime = React141__default.useMemo(() => {
78781
+ const hourlyWindowStartTime = React142__default.useMemo(() => {
78194
78782
  if (scopedLineIds.length === 0) {
78195
78783
  return null;
78196
78784
  }
@@ -78241,12 +78829,12 @@ var PlantHeadView = () => {
78241
78829
  const minutes = earliestMinutes % 60;
78242
78830
  return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
78243
78831
  }, [appTimezone, resolvedTrendMode, scopedLineIds, shiftConfigMap, staticShiftConfig]);
78244
- const isShiftScopeResolved = React141__default.useMemo(
78832
+ const isShiftScopeResolved = React142__default.useMemo(
78245
78833
  () => !isShiftConfigLoading,
78246
78834
  [isShiftConfigLoading]
78247
78835
  );
78248
- const initializedTimezoneRef = React141__default.useRef(appTimezone);
78249
- React141__default.useEffect(() => {
78836
+ const initializedTimezoneRef = React142__default.useRef(appTimezone);
78837
+ React142__default.useEffect(() => {
78250
78838
  if (initializedTimezoneRef.current === appTimezone) return;
78251
78839
  hasAutoInitializedScopeRef.current = false;
78252
78840
  hasUserAdjustedScopeRef.current = false;
@@ -78259,7 +78847,7 @@ var PlantHeadView = () => {
78259
78847
  setIsInitialScopeReady(false);
78260
78848
  initializedTimezoneRef.current = appTimezone;
78261
78849
  }, [appTimezone, fallbackOperationalDate]);
78262
- React141__default.useEffect(() => {
78850
+ React142__default.useEffect(() => {
78263
78851
  if (hasAutoInitializedScopeRef.current || hasUserAdjustedScopeRef.current) {
78264
78852
  return;
78265
78853
  }
@@ -78284,7 +78872,7 @@ var PlantHeadView = () => {
78284
78872
  hasAutoInitializedScopeRef.current = true;
78285
78873
  setIsInitialScopeReady(true);
78286
78874
  }, [fallbackOperationalDate, isShiftScopeResolved, resolvedOperationalToday, scopedLineIds.length]);
78287
- const handleDateRangeChange = React141__default.useCallback((range, meta) => {
78875
+ const handleDateRangeChange = React142__default.useCallback((range, meta) => {
78288
78876
  hasUserAdjustedScopeRef.current = true;
78289
78877
  setIsInitialScopeReady(true);
78290
78878
  trackCoreEvent("Operations Overview Date Range Changed", {
@@ -78302,12 +78890,12 @@ var PlantHeadView = () => {
78302
78890
  return previous;
78303
78891
  });
78304
78892
  }, []);
78305
- const handleTrendModeChange = React141__default.useCallback((mode) => {
78893
+ const handleTrendModeChange = React142__default.useCallback((mode) => {
78306
78894
  hasUserAdjustedScopeRef.current = true;
78307
78895
  setIsInitialScopeReady(true);
78308
78896
  setTrendMode(mode);
78309
78897
  }, []);
78310
- const handleSelectedLineIdsChange = React141__default.useCallback((lineIds) => {
78898
+ const handleSelectedLineIdsChange = React142__default.useCallback((lineIds) => {
78311
78899
  setSelectedSupervisorId("all");
78312
78900
  if (normalizedLineIds.length === 0) {
78313
78901
  setSelectedLineIds([]);
@@ -78318,10 +78906,10 @@ var PlantHeadView = () => {
78318
78906
  const next = normalizedLineIds.filter((lineId) => selectedSet.has(lineId));
78319
78907
  setSelectedLineIds(next.length > 0 ? next : normalizedLineIds);
78320
78908
  }, [normalizedLineIds]);
78321
- const handleSelectedSupervisorIdChange = React141__default.useCallback((supervisorId) => {
78909
+ const handleSelectedSupervisorIdChange = React142__default.useCallback((supervisorId) => {
78322
78910
  setSelectedSupervisorId(supervisorId);
78323
78911
  }, []);
78324
- const buildLineMonthlyHistoryUrl = React141__default.useCallback((lineId) => {
78912
+ const buildLineMonthlyHistoryUrl = React142__default.useCallback((lineId) => {
78325
78913
  const rangeStartDate = parseDateKeyToDate(dateRange.startKey);
78326
78914
  const params = new URLSearchParams();
78327
78915
  params.set("tab", "monthly_history");
@@ -78331,15 +78919,15 @@ var PlantHeadView = () => {
78331
78919
  params.set("rangeEnd", dateRange.endKey);
78332
78920
  return `/kpis/${lineId}?${params.toString()}`;
78333
78921
  }, [dateRange.endKey, dateRange.startKey]);
78334
- const handleViewAllPoorestPerformers = React141__default.useCallback(() => {
78922
+ const handleViewAllPoorestPerformers = React142__default.useCallback(() => {
78335
78923
  trackCoreEvent("Operations Overview View All Clicked", { section: "poorest_performers" });
78336
78924
  navigate("/kpis?tab=leaderboard");
78337
78925
  }, [navigate]);
78338
- const handleViewAllImprovements = React141__default.useCallback(() => {
78926
+ const handleViewAllImprovements = React142__default.useCallback(() => {
78339
78927
  trackCoreEvent("Operations Overview View All Clicked", { section: "improvements" });
78340
78928
  navigate("/improvement-center");
78341
78929
  }, [navigate]);
78342
- const handleOpenImprovement = React141__default.useCallback((item) => {
78930
+ const handleOpenImprovement = React142__default.useCallback((item) => {
78343
78931
  trackCoreEvent("Operations Overview Improvement Clicked", {
78344
78932
  issue_id: item.issueId,
78345
78933
  issue_number: item.issueNumber,
@@ -78350,13 +78938,13 @@ var PlantHeadView = () => {
78350
78938
  });
78351
78939
  navigate(`/improvement-center?${params.toString()}`);
78352
78940
  }, [navigate]);
78353
- const comparisonStrategy = React141__default.useMemo(() => {
78941
+ const comparisonStrategy = React142__default.useMemo(() => {
78354
78942
  if (usesThisWeekComparison && isCurrentWeekToDateRange) {
78355
78943
  return "previous_full_week";
78356
78944
  }
78357
78945
  return void 0;
78358
78946
  }, [isCurrentWeekToDateRange, usesThisWeekComparison]);
78359
- const effectiveDateRange = React141__default.useMemo(() => {
78947
+ const effectiveDateRange = React142__default.useMemo(() => {
78360
78948
  if (isInitialScopeReady) {
78361
78949
  return dateRange;
78362
78950
  }
@@ -78366,21 +78954,21 @@ var PlantHeadView = () => {
78366
78954
  endKey: nextStartKey
78367
78955
  };
78368
78956
  }, [dateRange, fallbackOperationalDate, isInitialScopeReady, resolvedOperationalToday]);
78369
- const effectiveTrendMode = React141__default.useMemo(
78957
+ const effectiveTrendMode = React142__default.useMemo(
78370
78958
  () => resolvedTrendMode,
78371
78959
  [resolvedTrendMode]
78372
78960
  );
78373
- const hourlyLabelStartTime = React141__default.useMemo(() => {
78961
+ const hourlyLabelStartTime = React142__default.useMemo(() => {
78374
78962
  if (scopedLineIds.length === 0) {
78375
78963
  return null;
78376
78964
  }
78377
78965
  return hourlyWindowStartTime;
78378
78966
  }, [hourlyWindowStartTime, scopedLineIds.length]);
78379
- const isSingleDayScope = React141__default.useMemo(
78967
+ const isSingleDayScope = React142__default.useMemo(
78380
78968
  () => effectiveDateRange.startKey === effectiveDateRange.endKey,
78381
78969
  [effectiveDateRange.endKey, effectiveDateRange.startKey]
78382
78970
  );
78383
- const isLiveScope = React141__default.useMemo(
78971
+ const isLiveScope = React142__default.useMemo(
78384
78972
  () => isSingleDayScope && effectiveDateRange.startKey === resolvedOperationalToday && (effectiveTrendMode === "all" || effectiveTrendMode === "day" && hasActiveDayShiftLine || effectiveTrendMode === "night" && hasActiveNightShiftLine),
78385
78973
  [
78386
78974
  effectiveDateRange.startKey,
@@ -78391,7 +78979,7 @@ var PlantHeadView = () => {
78391
78979
  resolvedOperationalToday
78392
78980
  ]
78393
78981
  );
78394
- const handleOpenLineDetails = React141__default.useCallback((lineId, lineName) => {
78982
+ const handleOpenLineDetails = React142__default.useCallback((lineId, lineName) => {
78395
78983
  trackCoreEvent("Operations Overview Line Clicked", {
78396
78984
  line_id: lineId,
78397
78985
  line_name: lineName,
@@ -78959,4 +79547,4 @@ var streamProxyConfig = {
78959
79547
  }
78960
79548
  };
78961
79549
 
78962
- export { ACTION_FAMILIES, ACTION_NAMES, AIAgentView_default as AIAgentView, AcceptInvite, AcceptInviteView_default as AcceptInviteView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthService, AuthenticatedBottleneckClipsView, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedTicketsView, AuthenticatedWorkspaceHealthView, AvatarUpload, AxelNotificationPopup, AxelOrb, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottleneckClipsModal, BottleneckClipsView_default as BottleneckClipsView, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ChangeRoleDialog, ClipFilterProvider, ClipsCostView_default as ClipsCostView, CompactWorkspaceHealthCard, ConfirmRemoveUserDialog, CongratulationsOverlay, CroppedHlsVideoPlayer, CroppedVideoPlayer, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_HOME_VIEW_CONFIG, DEFAULT_MAP_VIEW_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_SHIFT_DATA, DEFAULT_THEME_CONFIG, DEFAULT_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, DetailedHealthStatus, DiagnosisVideoModal, EFFICIENCY_ON_TRACK_THRESHOLD, EmptyStateMessage, EncouragementOverlay, FactoryAssignmentDropdown, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, FittingTitle, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthDateShiftSelector, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HlsVideoPlayer, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, HourlyUptimeChart, ISTTimer_default as ISTTimer, IdleTimeVlmConfigProvider, ImprovementCenterView_default as ImprovementCenterView, InlineEditableText, InteractiveOnboardingTour, InvitationService, InvitationsTable, InviteUserDialog, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend5 as Legend, LineAssignmentDropdown, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LinesService, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, Logo, MainLayout, MapGridView, MetricCard_default as MetricCard, MinimalOnboardingPopup, MobileMenuProvider, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PlantHeadView_default as PlantHeadView, PlayPauseIndicator, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, RoleBadge, S3ClipsSupabaseService as S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SessionTracker, SessionTrackingContext, SessionTrackingProvider, SettingsPopup, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SignupWithInvitation, SilentErrorBoundary, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, TeamManagementView_default as TeamManagementView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TicketsView_default as TicketsView, TimeDisplay_default as TimeDisplay, TimePickerDropdown, Timer_default as Timer, TimezoneProvider, TimezoneService, UptimeDonutChart, UptimeLineChart, UptimeMetricCards, UserAvatar, UserManagementService, UserManagementTable, UserService, UserUsageDetailModal, UserUsageStats, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceCycleTimeMetricCards, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, aggregateKPIsFromLineMetricsRows, alertsService, apiUtils, areAllLinesOnSameShift, authCoreService, authOTPService, authRateLimitService, awardsService, buildDateKey, buildKPIsFromLineMetricsRow, buildShiftGroupsKey, canRoleAccessDashboardPath, canRoleAccessTeamManagement, canRoleAssignFactories, canRoleAssignLines, canRoleChangeRole, canRoleInviteRole, canRoleManageCompany, canRoleManageTargets, canRoleManageUsers, canRoleRemoveUser, canRoleViewClipsCost, canRoleViewUsageStats, captureSentryException, captureSentryMessage, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearSentryContext, clearWorkspaceDisplayNamesCache, cn, createDefaultKPIs, createInvitationService, createLinesService, createSessionTracker, createStorageService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, fetchIdleTimeReasons, filterDataByDateKeyRange, forceRefreshWorkspaceDisplayNames, formatAwardMonth, formatDateInZone, formatDateKeyForDisplay, formatDateTimeInZone, formatDuration2 as formatDuration, formatISTDate, formatIdleTime, formatRangeLabel, formatReasonLabel, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getActionDisplayName, getActiveShift, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAllWorkspaceDisplayNamesSnapshot, getAnonClient, getAssignableRoles, getAssignmentColumnLabel, getAvailableShiftIds, getAwardBadgeType, getAwardDescription, getAwardTitle, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentShiftForLine, getCurrentTimeInZone, getCurrentWeekFullRange, getCurrentWeekToDateRange, getDashboardHeaderTimeInZone, getDateKeyFromDate, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getInitials, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getMonthKeyBounds, getMonthWeekRanges, getNextUpdateInterval, getOperationalDate, getRoleAssignmentKind, getRoleDescription, getRoleLabel, getRoleMetadata, getRoleNavPaths, getS3SignedUrl, getS3VideoSrc, getShiftData, getShiftNameById, getShiftWorkDurationSeconds, getShortShiftName, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUniformShiftGroup, getUserThreads, getUserThreadsPaginated, getVisibleRolesForCurrentUser, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, groupLinesByShift, hasAnyShiftData, identifyCoreUser, initializeCoreMixpanel, isEfficiencyOnTrack, isFactoryScopedRole, isFullMonthRange, isLegacyConfiguration, isLoopbackHostname, isPrefetchError, isRecentFlowVideoGridMetricMode, isSafari, isSupervisorRole, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWipGatedVideoGridMetricMode, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, lineLeaderboardService, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, normalizeActionFamily, normalizeDateKeyRange, normalizeRoleLevel, normalizeVideoGridMetricMode, optifyeAgentClient, parseDateKeyToDate, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, setSentryUserContext, setSentryWorkspaceContext, shouldEnableLocalDevTestLogin, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, subscribeWorkspaceDisplayNames, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, transformToChartData, updateThreadTitle, upsertWorkspaceDisplayNameInCache, useAccessControl, useActiveBreaks, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useClipsInit, useCompanyClipsCost, useCompanyUsersUsage, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHideMobileHeader, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useIdleTimeClipClassifications, useIdleTimeReasons, useIdleTimeVlmConfig, useKpiTrends, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useLines, useMessages, useMetrics, useMobileMenu, useMonthlyTrend, useMultiLineShiftConfigs, useNavigation, useOperationalShiftKey, useOptionalSupabase, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useSessionTracking, useSessionTrackingContext, useShiftConfig, useShiftGroups, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useSupervisorsByLineIds, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useUserUsage, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthLastSeen, useWorkspaceHealthStatus, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, useWorkspaceUptimeTimeline, useWorkspaceVideoStreams, userService, videoPrefetchManager, videoPreloader, weeklyTopPerformerService, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };
79550
+ export { ACTION_FAMILIES, ACTION_NAMES, AIAgentView_default as AIAgentView, AcceptInvite, AcceptInviteView_default as AcceptInviteView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthService, AuthenticatedBottleneckClipsView, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedTicketsView, AuthenticatedWorkspaceHealthView, AvatarUpload, AxelNotificationPopup, AxelOrb, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottleneckClipsModal, BottleneckClipsView_default as BottleneckClipsView, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ChangeRoleDialog, ClipFilterProvider, ClipsCostView_default as ClipsCostView, CompactWorkspaceHealthCard, ConfirmRemoveUserDialog, CongratulationsOverlay, CroppedHlsVideoPlayer, CroppedVideoPlayer, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_HOME_VIEW_CONFIG, DEFAULT_MAP_VIEW_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_SHIFT_DATA, DEFAULT_THEME_CONFIG, DEFAULT_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, DetailedHealthStatus, DiagnosisVideoModal, EFFICIENCY_ON_TRACK_THRESHOLD, EmptyStateMessage, EncouragementOverlay, FactoryAssignmentDropdown, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, FittingTitle, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthDateShiftSelector, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HlsVideoPlayer, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, HourlyUptimeChart, ISTTimer_default as ISTTimer, IdleTimeVlmConfigProvider, ImprovementCenterView_default as ImprovementCenterView, InlineEditableText, InteractiveOnboardingTour, InvitationService, InvitationsTable, InviteUserDialog, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend5 as Legend, LineAssignmentDropdown, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LinesService, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, Logo, MainLayout, MapGridView, MetricCard_default as MetricCard, MinimalOnboardingPopup, MobileMenuProvider, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PlantHeadView_default as PlantHeadView, PlayPauseIndicator, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, RoleBadge, S3ClipsSupabaseService as S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SessionTracker, SessionTrackingContext, SessionTrackingProvider, SettingsPopup, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SignupWithInvitation, SilentErrorBoundary, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, TeamManagementView_default as TeamManagementView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TicketsView_default as TicketsView, TimeDisplay_default as TimeDisplay, TimePickerDropdown, Timer_default as Timer, TimezoneProvider, TimezoneService, UptimeDonutChart, UptimeLineChart, UptimeMetricCards, UserAvatar, UserManagementService, UserManagementTable, UserService, UserUsageDetailModal, UserUsageStats, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceCycleTimeMetricCards, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, aggregateKPIsFromLineMetricsRows, alertsService, apiUtils, areAllLinesOnSameShift, authCoreService, authOTPService, authRateLimitService, awardsService, buildDateKey, buildKPIsFromLineMetricsRow, buildShiftGroupsKey, canRoleAccessDashboardPath, canRoleAccessTeamManagement, canRoleAssignFactories, canRoleAssignLines, canRoleChangeRole, canRoleInviteRole, canRoleManageCompany, canRoleManageTargets, canRoleManageUsers, canRoleRemoveUser, canRoleViewClipsCost, canRoleViewUsageStats, captureSentryException, captureSentryMessage, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearSentryContext, clearWorkspaceDisplayNamesCache, cn, createDefaultKPIs, createInvitationService, createLinesService, createSessionTracker, createStorageService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, fetchIdleTimeReasons, filterDataByDateKeyRange, forceRefreshWorkspaceDisplayNames, formatAwardMonth, formatDateInZone, formatDateKeyForDisplay, formatDateTimeInZone, formatDuration2 as formatDuration, formatISTDate, formatIdleTime, formatRangeLabel, formatReasonLabel, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getActionDisplayName, getActiveShift, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAllWorkspaceDisplayNamesSnapshot, getAnonClient, getAssignableRoles, getAssignmentColumnLabel, getAvailableShiftIds, getAwardBadgeType, getAwardDescription, getAwardTitle, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentShiftForLine, getCurrentTimeInZone, getCurrentWeekFullRange, getCurrentWeekToDateRange, getDashboardHeaderTimeInZone, getDateKeyFromDate, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getInitials, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getMonthKeyBounds, getMonthWeekRanges, getNextUpdateInterval, getOperationalDate, getRoleAssignmentKind, getRoleDescription, getRoleLabel, getRoleMetadata, getRoleNavPaths, getS3SignedUrl, getS3VideoSrc, getShiftData, getShiftNameById, getShiftWorkDurationSeconds, getShortShiftName, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUniformShiftGroup, getUserThreads, getUserThreadsPaginated, getVisibleRolesForCurrentUser, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, groupLinesByShift, hasAnyShiftData, identifyCoreUser, initializeCoreMixpanel, isEfficiencyOnTrack, isFactoryScopedRole, isFullMonthRange, isLegacyConfiguration, isLoopbackHostname, isPrefetchError, isRecentFlowVideoGridMetricMode, isSafari, isSupervisorRole, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWipGatedVideoGridMetricMode, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, lineLeaderboardService, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, normalizeActionFamily, normalizeDateKeyRange, normalizeRoleLevel, normalizeVideoGridMetricMode, optifyeAgentClient, parseDateKeyToDate, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, setSentryUserContext, setSentryWorkspaceContext, shouldEnableLocalDevTestLogin, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, subscribeWorkspaceDisplayNames, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, transformToChartData, updateThreadTitle, upsertWorkspaceDisplayNameInCache, useAccessControl, useActiveBreaks, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useClipsInit, useCompanyClipsCost, useCompanyHasVlmEnabledLine, useCompanyUsersUsage, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHideMobileHeader, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useIdleTimeClipClassifications, useIdleTimeReasons, useIdleTimeVlmConfig, useKpiTrends, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useLines, useMessages, useMetrics, useMobileMenu, useMonthlyTrend, useMultiLineShiftConfigs, useNavigation, useOperationalShiftKey, useOptionalSupabase, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useSessionTracking, useSessionTrackingContext, useShiftConfig, useShiftGroups, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useSupervisorsByLineIds, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useUserUsage, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthLastSeen, useWorkspaceHealthStatus, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, useWorkspaceUptimeTimeline, useWorkspaceVideoStreams, userService, videoPrefetchManager, videoPreloader, weeklyTopPerformerService, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };