@optifye/dashboard-core 6.6.5 → 6.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import * as React19 from 'react';
2
- import React19__default, { createContext, useRef, useCallback, useState, useMemo, useEffect, memo, forwardRef, useImperativeHandle, useContext, useLayoutEffect, useId, Children, isValidElement, useInsertionEffect, Fragment as Fragment$1, createElement, Component } from 'react';
1
+ import * as React20 from 'react';
2
+ import React20__default, { createContext, useRef, useCallback, useState, useMemo, useEffect, memo, forwardRef, useImperativeHandle, useContext, useLayoutEffect, useId, Children, isValidElement, useInsertionEffect, 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 { toZonedTime, formatInTimeZone } from 'date-fns-tz';
@@ -13,7 +13,7 @@ import { noop, warning, invariant, progress, secondsToMilliseconds, milliseconds
13
13
  import { getValueTransition, hover, press, isPrimaryPointer, GroupPlaybackControls, setDragLock, supportsLinearEasing, attachTimeline, isGenerator, calcGeneratorDuration, isWaapiSupportedEasing, mapEasingToNativeEasing, maxGeneratorDuration, generateLinearEasing, isBezierDefinition } from 'motion-dom';
14
14
  import { BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, Tooltip, Legend, Bar, LabelList, ResponsiveContainer, LineChart as LineChart$1, Line, PieChart, Pie, Cell, ReferenceLine, ComposedChart, Area, ScatterChart, Scatter } from 'recharts';
15
15
  import { Slot } from '@radix-ui/react-slot';
16
- import { Camera, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, ArrowLeft, X, Coffee, Plus, Clock, Calendar, Save, Minus, ArrowDown, ArrowUp, Settings2, CheckCircle2, Search, Loader2, AlertCircle, Edit2, CheckCircle, AlertTriangle, Info, Share2, Trophy, Target, Download, User, RefreshCw, XCircle, ChevronLeft, ChevronRight, Activity, Sun, Moon, MousePointer, ArrowRight, MessageSquare, Trash2, Menu, Send, Copy, UserCheck, LogOut, Package, TrendingUp, TrendingDown, Building2, FolderOpen, Folder, HelpCircle, Play, Settings, LifeBuoy, EyeOff, Eye, Zap, UserCircle } from 'lucide-react';
16
+ import { Camera, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, ArrowLeft, X, Coffee, Plus, Clock, Calendar, Save, Minus, ArrowDown, ArrowUp, Settings2, CheckCircle2, Search, Loader2, AlertCircle, Edit2, CheckCircle, AlertTriangle, Info, Share2, Trophy, Target, Download, User, RefreshCw, Sliders, Sparkles, TrendingDown, TrendingUp, FolderOpen, Folder, HelpCircle, Play, Activity, Layers, Filter, XCircle, ChevronLeft, ChevronRight, Sun, Moon, MousePointer, ArrowRight, MessageSquare, Trash2, Menu, Send, Copy, UserCheck, LogOut, Package, Building2, Settings, LifeBuoy, EyeOff, Eye, Zap, UserCircle } from 'lucide-react';
17
17
  import { DayPicker, useNavigation as useNavigation$1 } from 'react-day-picker';
18
18
  import { XMarkIcon, ArrowRightIcon, HomeIcon, TrophyIcon, ChartBarIcon, AdjustmentsHorizontalIcon, ClockIcon, UsersIcon, CubeIcon, SparklesIcon, QuestionMarkCircleIcon, HeartIcon, UserCircleIcon, ExclamationCircleIcon, EnvelopeIcon, DocumentTextIcon, ChevronUpIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, Bars3Icon, CheckCircleIcon, ChatBubbleLeftRightIcon, ArrowLeftIcon, XCircleIcon, InformationCircleIcon } from '@heroicons/react/24/outline';
19
19
  import { CheckIcon } from '@heroicons/react/24/solid';
@@ -268,14 +268,14 @@ var _getDashboardConfigInstance = () => {
268
268
  }
269
269
  return dashboardConfigInstance;
270
270
  };
271
- var DashboardConfigContext = React19.createContext(void 0);
271
+ var DashboardConfigContext = React20.createContext(void 0);
272
272
  var DashboardProvider = ({ config: userProvidedConfig, children }) => {
273
- const fullConfig = React19.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
273
+ const fullConfig = React20.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
274
274
  _setDashboardConfigInstance(fullConfig);
275
- React19.useEffect(() => {
275
+ React20.useEffect(() => {
276
276
  _setDashboardConfigInstance(fullConfig);
277
277
  }, [fullConfig]);
278
- React19.useEffect(() => {
278
+ React20.useEffect(() => {
279
279
  if (!fullConfig.theme) return;
280
280
  const styleId = "dashboard-core-theme-vars";
281
281
  let styleEl = document.getElementById(styleId);
@@ -301,7 +301,7 @@ var DashboardProvider = ({ config: userProvidedConfig, children }) => {
301
301
  return /* @__PURE__ */ jsx(DashboardConfigContext.Provider, { value: fullConfig, children });
302
302
  };
303
303
  var useDashboardConfig = () => {
304
- const ctx = React19.useContext(DashboardConfigContext);
304
+ const ctx = React20.useContext(DashboardConfigContext);
305
305
  if (!ctx) throw new Error("useDashboardConfig must be used within a DashboardProvider");
306
306
  return ctx;
307
307
  };
@@ -1281,7 +1281,18 @@ var dashboardService = {
1281
1281
  const formattedStartDate = formatDate(startDate);
1282
1282
  const formattedEndDate = formatDate(endDate);
1283
1283
  try {
1284
- const { data, error } = await supabase.from(metricsTable).select("date, shift_id, efficiency, total_output, avg_cycle_time, ideal_output, avg_pph, pph_threshold, workspace_rank, idle_time").eq("workspace_id", workspaceUuid).gte("date", formattedStartDate).lte("date", formattedEndDate).order("date", { ascending: true }).order("shift_id", { ascending: true });
1284
+ const { data, error } = await supabase.from(metricsTable).select(`
1285
+ date,
1286
+ shift_id,
1287
+ efficiency,
1288
+ total_output,
1289
+ avg_cycle_time,
1290
+ avg_pph,
1291
+ pph_threshold,
1292
+ workspace_rank,
1293
+ idle_time,
1294
+ total_day_output
1295
+ `).eq("workspace_id", workspaceUuid).gte("date", formattedStartDate).lte("date", formattedEndDate).order("date", { ascending: true }).order("shift_id", { ascending: true });
1285
1296
  if (error) throw error;
1286
1297
  if (!data) return [];
1287
1298
  const transformedData = data.map((item) => ({
@@ -1291,7 +1302,8 @@ var dashboardService = {
1291
1302
  avg_efficiency: item.efficiency || 0,
1292
1303
  total_output: item.total_output || 0,
1293
1304
  avg_cycle_time: item.avg_cycle_time || 0,
1294
- ideal_output: item.ideal_output || 0,
1305
+ ideal_output: item.total_day_output || 0,
1306
+ // Use daily target directly from performance_metrics table
1295
1307
  avg_pph: item.avg_pph || 0,
1296
1308
  pph_threshold: item.pph_threshold || 0,
1297
1309
  workspace_rank: item.workspace_rank || 0,
@@ -4743,21 +4755,60 @@ var S3ClipsSupabaseService = class {
4743
4755
  return video || null;
4744
4756
  });
4745
4757
  }
4758
+ /**
4759
+ * Map percentile category to actual implementation
4760
+ */
4761
+ mapPercentileCategoryToType(category) {
4762
+ switch (category) {
4763
+ case "fast-cycles":
4764
+ return { type: "fast-cycles", isPercentile: true };
4765
+ case "slow-cycles":
4766
+ return { type: "slow-cycles", isPercentile: true };
4767
+ case "longest-idles":
4768
+ return { type: "idle-times", isPercentile: true };
4769
+ default:
4770
+ return { type: null, isPercentile: false };
4771
+ }
4772
+ }
4746
4773
  /**
4747
4774
  * Get neighboring clips for navigation
4748
4775
  * Returns previous and next clips based on timestamp
4776
+ * Handles both regular and percentile categories
4749
4777
  */
4750
4778
  async getNeighboringClips(workspaceId, date, shiftId, category, currentClipId, sopCategories) {
4751
- console.log(`[S3ClipsSupabase] Getting neighboring clips for ID: ${currentClipId}`);
4752
- const response = await this.fetchWithAuth("neighbors", {
4753
- workspaceId,
4754
- date,
4755
- shift: shiftId.toString(),
4756
- category,
4757
- currentClipId,
4758
- sopCategories: sopCategories || this.config.s3Config?.sopCategories?.default
4759
- });
4760
- return response.neighbors || { previous: null, next: null };
4779
+ console.log(`[S3ClipsSupabase] Getting neighboring clips for ID: ${currentClipId}, category: ${category}`);
4780
+ const percentileMapping = this.mapPercentileCategoryToType(category);
4781
+ if (percentileMapping.isPercentile && percentileMapping.type) {
4782
+ console.log(`[S3ClipsSupabase] Handling percentile category: ${category} -> ${percentileMapping.type}`);
4783
+ const percentileClips = await this.getPercentileClips(
4784
+ workspaceId,
4785
+ date,
4786
+ shiftId,
4787
+ percentileMapping.type,
4788
+ 10,
4789
+ // Default percentile, should be configurable
4790
+ 1e3
4791
+ // Large limit to get all clips for navigation
4792
+ );
4793
+ const currentIndex = percentileClips.clips.findIndex((clip) => clip.id === currentClipId);
4794
+ if (currentIndex === -1) {
4795
+ return { previous: null, next: null };
4796
+ }
4797
+ return {
4798
+ previous: currentIndex > 0 ? percentileClips.clips[currentIndex - 1] : null,
4799
+ next: currentIndex < percentileClips.clips.length - 1 ? percentileClips.clips[currentIndex + 1] : null
4800
+ };
4801
+ } else {
4802
+ const response = await this.fetchWithAuth("neighbors", {
4803
+ workspaceId,
4804
+ date,
4805
+ shift: shiftId.toString(),
4806
+ category,
4807
+ currentClipId,
4808
+ sopCategories: sopCategories || this.config.s3Config?.sopCategories?.default
4809
+ });
4810
+ return response.neighbors || { previous: null, next: null };
4811
+ }
4761
4812
  }
4762
4813
  /**
4763
4814
  * Get clip by index
@@ -4867,6 +4918,93 @@ var S3ClipsSupabaseService = class {
4867
4918
  await this.batchFetchClips(workspaceId, date, shiftId, requests);
4868
4919
  }
4869
4920
  }
4921
+ /**
4922
+ * Get percentile-based clips (fast cycles, slow cycles, idle times)
4923
+ */
4924
+ async getPercentileClips(workspaceId, date, shiftId, type, percentile = 10, limit = 100) {
4925
+ const cacheKey = `percentile:${workspaceId}:${date}:${shiftId}:${type}:${percentile}`;
4926
+ return this.deduplicate(cacheKey, async () => {
4927
+ console.log(`[S3ClipsSupabase] Fetching ${type} clips at ${percentile}% percentile`);
4928
+ const startDate = `${date}T00:00:00Z`;
4929
+ const endDate = `${date}T23:59:59Z`;
4930
+ const response = await this.fetchWithAuth("percentile-clips", {
4931
+ action: type,
4932
+ workspaceId,
4933
+ startDate,
4934
+ endDate,
4935
+ percentile,
4936
+ shiftId: shiftId || null,
4937
+ limit
4938
+ });
4939
+ console.log(`[S3ClipsSupabase] Fetched ${response.clips?.length || 0} ${type} clips`);
4940
+ const transformedClips = (response.clips || []).map((clip) => ({
4941
+ id: clip.clip_id,
4942
+ src: clip.playlist,
4943
+ // Raw playlist content
4944
+ timestamp: new Date(clip.date).toLocaleTimeString("en-US", {
4945
+ hour12: false,
4946
+ hour: "2-digit",
4947
+ minute: "2-digit",
4948
+ second: "2-digit"
4949
+ }),
4950
+ severity: this.getSeverityFromClipType(clip.clip_type_name),
4951
+ description: this.getDescriptionFromClipType(clip.clip_type_name),
4952
+ type: clip.clip_type_name,
4953
+ originalUri: `clips:${clip.clip_id}`,
4954
+ cycle_time_seconds: clip.metadata?.request?.metadata?.cycle_time ? clip.metadata.request.metadata.cycle_time / 20 : void 0,
4955
+ creation_timestamp: clip.created_at,
4956
+ percentile: clip.cycle_time_percentile || clip.idle_time_percentile
4957
+ }));
4958
+ return {
4959
+ clips: transformedClips,
4960
+ total: response.total || transformedClips.length,
4961
+ hasMore: response.hasMore || false
4962
+ };
4963
+ });
4964
+ }
4965
+ /**
4966
+ * Get workspace statistics
4967
+ */
4968
+ async getWorkspaceStats(workspaceId, startDate, endDate) {
4969
+ const cacheKey = `stats:${workspaceId}:${startDate || "all"}:${endDate || "all"}`;
4970
+ return this.deduplicate(cacheKey, async () => {
4971
+ console.log(`[S3ClipsSupabase] Fetching workspace statistics`);
4972
+ const response = await this.fetchWithAuth("workspace-stats", {
4973
+ workspaceId,
4974
+ startDate,
4975
+ endDate
4976
+ });
4977
+ console.log(`[S3ClipsSupabase] Fetched workspace statistics`, response.stats);
4978
+ return response.stats;
4979
+ });
4980
+ }
4981
+ /**
4982
+ * Helper to get severity from clip type
4983
+ * Updated for new materialized view structure (only cycle_completion in 'cycle' category)
4984
+ */
4985
+ getSeverityFromClipType(clipType) {
4986
+ switch (clipType) {
4987
+ case "sop_deviations":
4988
+ return "high";
4989
+ case "idle_time":
4990
+ return "medium";
4991
+ case "cycle_completion":
4992
+ default:
4993
+ return "low";
4994
+ }
4995
+ }
4996
+ /**
4997
+ * Helper to get description from clip type
4998
+ * Updated for new materialized view structure
4999
+ */
5000
+ getDescriptionFromClipType(clipType) {
5001
+ const descriptions = {
5002
+ "idle_time": "Idle Time Detected",
5003
+ "sop_deviations": "SOP Deviations",
5004
+ "cycle_completion": "Cycle Completion"
5005
+ };
5006
+ return descriptions[clipType] || "Analysis Clip";
5007
+ }
4870
5008
  };
4871
5009
  var S3ClipsService2 = S3ClipsSupabaseService ;
4872
5010
  var VideoPrefetchManager = class extends EventEmitter {
@@ -5702,6 +5840,95 @@ var useSubscriptionManagerSafe = () => {
5702
5840
  const { subscriptionManager } = useContext(SubscriptionManagerContext);
5703
5841
  return subscriptionManager;
5704
5842
  };
5843
+ var defaultState = {
5844
+ percentile: 10,
5845
+ showFastCycles: true,
5846
+ showSlowCycles: true,
5847
+ showLongestIdles: true,
5848
+ showIdleTime: true,
5849
+ showCycleCompletion: true,
5850
+ showBestCycleTime: false,
5851
+ showWorstCycleTime: false,
5852
+ showLongCycleTime: false,
5853
+ showSopDeviations: false,
5854
+ dateRange: {
5855
+ start: /* @__PURE__ */ new Date(),
5856
+ end: /* @__PURE__ */ new Date()
5857
+ },
5858
+ shiftFilter: void 0,
5859
+ percentileRange: void 0,
5860
+ isAdvancedPanelOpen: false,
5861
+ isLoadingPercentileClips: false
5862
+ };
5863
+ var ClipFilterContext = createContext(void 0);
5864
+ var ClipFilterProvider = ({ children }) => {
5865
+ const [state, setState] = useState(defaultState);
5866
+ const updatePercentile = useCallback((percentile) => {
5867
+ if (percentile >= 1 && percentile <= 100) {
5868
+ setState((prev) => ({ ...prev, percentile }));
5869
+ }
5870
+ }, []);
5871
+ const toggleClipType = useCallback((clipType) => {
5872
+ setState((prev) => ({
5873
+ ...prev,
5874
+ [clipType]: !prev[clipType]
5875
+ }));
5876
+ }, []);
5877
+ const updateDateRange = useCallback((start, end) => {
5878
+ setState((prev) => ({
5879
+ ...prev,
5880
+ dateRange: { start, end }
5881
+ }));
5882
+ }, []);
5883
+ const updateShiftFilter = useCallback((shiftId) => {
5884
+ setState((prev) => ({
5885
+ ...prev,
5886
+ shiftFilter: shiftId
5887
+ }));
5888
+ }, []);
5889
+ const setPercentileRange = useCallback((min, max) => {
5890
+ if (min >= 0 && max <= 100 && min < max) {
5891
+ setState((prev) => ({
5892
+ ...prev,
5893
+ percentileRange: { min, max }
5894
+ }));
5895
+ }
5896
+ }, []);
5897
+ const toggleAdvancedPanel = useCallback(() => {
5898
+ setState((prev) => ({
5899
+ ...prev,
5900
+ isAdvancedPanelOpen: !prev.isAdvancedPanelOpen
5901
+ }));
5902
+ }, []);
5903
+ const setLoadingPercentileClips = useCallback((loading) => {
5904
+ setState((prev) => ({
5905
+ ...prev,
5906
+ isLoadingPercentileClips: loading
5907
+ }));
5908
+ }, []);
5909
+ const resetFilters = useCallback(() => {
5910
+ setState(defaultState);
5911
+ }, []);
5912
+ const value = {
5913
+ state,
5914
+ updatePercentile,
5915
+ toggleClipType,
5916
+ updateDateRange,
5917
+ updateShiftFilter,
5918
+ setPercentileRange,
5919
+ toggleAdvancedPanel,
5920
+ resetFilters,
5921
+ setLoadingPercentileClips
5922
+ };
5923
+ return /* @__PURE__ */ jsx(ClipFilterContext.Provider, { value, children });
5924
+ };
5925
+ var useClipFilter = () => {
5926
+ const context = useContext(ClipFilterContext);
5927
+ if (!context) {
5928
+ throw new Error("useClipFilter must be used within ClipFilterProvider");
5929
+ }
5930
+ return context;
5931
+ };
5705
5932
  var DEFAULT_COMPANY_ID = "default-company-id";
5706
5933
  var useWorkspaceMetrics = (workspaceId) => {
5707
5934
  const supabase = useSupabase();
@@ -12932,7 +13159,7 @@ var MotionConfigContext = createContext({
12932
13159
  });
12933
13160
 
12934
13161
  // ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PopChild.mjs
12935
- var PopChildMeasure = class extends React19.Component {
13162
+ var PopChildMeasure = class extends React20.Component {
12936
13163
  getSnapshotBeforeUpdate(prevProps) {
12937
13164
  const element = this.props.childRef.current;
12938
13165
  if (element && prevProps.isPresent && !this.props.isPresent) {
@@ -12987,7 +13214,7 @@ function PopChild({ children, isPresent }) {
12987
13214
  document.head.removeChild(style);
12988
13215
  };
12989
13216
  }, [isPresent]);
12990
- return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React19.cloneElement(children, { ref }) });
13217
+ return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React20.cloneElement(children, { ref }) });
12991
13218
  }
12992
13219
 
12993
13220
  // ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PresenceChild.mjs
@@ -13024,7 +13251,7 @@ var PresenceChild = ({ children, initial, isPresent, onExitComplete, custom, pre
13024
13251
  useMemo(() => {
13025
13252
  presenceChildren.forEach((_, key) => presenceChildren.set(key, false));
13026
13253
  }, [isPresent]);
13027
- React19.useEffect(() => {
13254
+ React20.useEffect(() => {
13028
13255
  !isPresent && !presenceChildren.size && onExitComplete && onExitComplete();
13029
13256
  }, [isPresent]);
13030
13257
  if (mode === "popLayout") {
@@ -20308,7 +20535,7 @@ var LoadingPage = ({
20308
20535
  subMessage = "Please wait while we prepare your data",
20309
20536
  className
20310
20537
  }) => {
20311
- React19__default.useEffect(() => {
20538
+ React20__default.useEffect(() => {
20312
20539
  console.log("LoadingPage rendered with message:", message);
20313
20540
  const timeout = setTimeout(() => {
20314
20541
  console.warn("LoadingPage has been visible for more than 8 seconds. This might indicate an issue.");
@@ -20349,15 +20576,15 @@ var withAuth = (WrappedComponent2, options) => {
20349
20576
  requireAuth: true,
20350
20577
  ...options
20351
20578
  };
20352
- const WithAuthComponent = React19.memo(function WithAuthComponent2(props) {
20579
+ const WithAuthComponent = React20.memo(function WithAuthComponent2(props) {
20353
20580
  const { session, loading, error } = useAuth();
20354
20581
  const router = useRouter();
20355
- React19.useEffect(() => {
20582
+ React20.useEffect(() => {
20356
20583
  if (process.env.NODE_ENV === "development" && process.env.DEBUG_AUTH === "true") {
20357
20584
  console.log("withAuth state:", { loading, hasSession: !!session, requireAuth: defaultOptions.requireAuth });
20358
20585
  }
20359
20586
  }, [session, loading]);
20360
- React19.useEffect(() => {
20587
+ React20.useEffect(() => {
20361
20588
  if (!loading && defaultOptions.requireAuth && !session && !error) {
20362
20589
  console.log("Redirecting to login from withAuth");
20363
20590
  router.replace(defaultOptions.redirectTo);
@@ -20733,11 +20960,11 @@ var BarChartComponent = ({
20733
20960
  aspect = 2,
20734
20961
  ...restOfChartProps
20735
20962
  }) => {
20736
- const containerRef = React19__default.useRef(null);
20737
- const [containerReady, setContainerReady] = React19__default.useState(false);
20963
+ const containerRef = React20__default.useRef(null);
20964
+ const [containerReady, setContainerReady] = React20__default.useState(false);
20738
20965
  const themeConfig = useThemeConfig();
20739
20966
  const { formatNumber } = useFormatNumber();
20740
- React19__default.useEffect(() => {
20967
+ React20__default.useEffect(() => {
20741
20968
  const checkContainerDimensions = () => {
20742
20969
  if (containerRef.current) {
20743
20970
  const rect = containerRef.current.getBoundingClientRect();
@@ -20835,7 +21062,7 @@ var BarChartComponent = ({
20835
21062
  }
20836
21063
  return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: chartContent });
20837
21064
  };
20838
- var BarChart = React19__default.memo(BarChartComponent, (prevProps, nextProps) => {
21065
+ var BarChart = React20__default.memo(BarChartComponent, (prevProps, nextProps) => {
20839
21066
  if (prevProps.xAxisDataKey !== nextProps.xAxisDataKey || prevProps.xAxisLabel !== nextProps.xAxisLabel || prevProps.yAxisLabel !== nextProps.yAxisLabel || prevProps.yAxisUnit !== nextProps.yAxisUnit || 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) {
20840
21067
  return false;
20841
21068
  }
@@ -20883,11 +21110,11 @@ var LineChartComponent = ({
20883
21110
  aspect = 2,
20884
21111
  ...restOfChartProps
20885
21112
  }) => {
20886
- const containerRef = React19__default.useRef(null);
20887
- const [containerReady, setContainerReady] = React19__default.useState(false);
21113
+ const containerRef = React20__default.useRef(null);
21114
+ const [containerReady, setContainerReady] = React20__default.useState(false);
20888
21115
  const themeConfig = useThemeConfig();
20889
21116
  const { formatNumber } = useFormatNumber();
20890
- React19__default.useEffect(() => {
21117
+ React20__default.useEffect(() => {
20891
21118
  const checkContainerDimensions = () => {
20892
21119
  if (containerRef.current) {
20893
21120
  const rect = containerRef.current.getBoundingClientRect();
@@ -20986,7 +21213,7 @@ var LineChartComponent = ({
20986
21213
  }
20987
21214
  return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: chartContent });
20988
21215
  };
20989
- var LineChart = React19__default.memo(LineChartComponent, (prevProps, nextProps) => {
21216
+ var LineChart = React20__default.memo(LineChartComponent, (prevProps, nextProps) => {
20990
21217
  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)) {
20991
21218
  return false;
20992
21219
  }
@@ -21063,7 +21290,7 @@ var OutputProgressChartComponent = ({
21063
21290
  ] }) })
21064
21291
  ] }) });
21065
21292
  };
21066
- var OutputProgressChart = React19__default.memo(OutputProgressChartComponent);
21293
+ var OutputProgressChart = React20__default.memo(OutputProgressChartComponent);
21067
21294
  OutputProgressChart.displayName = "OutputProgressChart";
21068
21295
  var LargeOutputProgressChart = ({
21069
21296
  currentOutput,
@@ -21179,7 +21406,7 @@ var CycleTimeChartComponent = ({
21179
21406
  }
21180
21407
  ) }) });
21181
21408
  };
21182
- var CycleTimeChart = React19__default.memo(CycleTimeChartComponent, (prevProps, nextProps) => {
21409
+ var CycleTimeChart = React20__default.memo(CycleTimeChartComponent, (prevProps, nextProps) => {
21183
21410
  if (prevProps.className !== nextProps.className) {
21184
21411
  return false;
21185
21412
  }
@@ -21205,8 +21432,8 @@ var CycleTimeOverTimeChart = ({
21205
21432
  className = ""
21206
21433
  }) => {
21207
21434
  const MAX_DATA_POINTS = 40;
21208
- const containerRef = React19__default.useRef(null);
21209
- const [containerReady, setContainerReady] = React19__default.useState(false);
21435
+ const containerRef = React20__default.useRef(null);
21436
+ const [containerReady, setContainerReady] = React20__default.useState(false);
21210
21437
  const getHourFromTimeString = (timeStr) => {
21211
21438
  const [hours, minutes] = timeStr.split(":");
21212
21439
  return parseInt(hours);
@@ -21217,10 +21444,10 @@ var CycleTimeOverTimeChart = ({
21217
21444
  };
21218
21445
  const displayData = getDisplayData(data);
21219
21446
  const DURATION = displayData.length;
21220
- const [animatedData, setAnimatedData] = React19__default.useState(Array(DURATION).fill(0));
21221
- const prevDataRef = React19__default.useRef(Array(DURATION).fill(0));
21222
- const animationFrameRef = React19__default.useRef(null);
21223
- const animateToNewData = React19__default.useCallback((targetData) => {
21447
+ const [animatedData, setAnimatedData] = React20__default.useState(Array(DURATION).fill(0));
21448
+ const prevDataRef = React20__default.useRef(Array(DURATION).fill(0));
21449
+ const animationFrameRef = React20__default.useRef(null);
21450
+ const animateToNewData = React20__default.useCallback((targetData) => {
21224
21451
  const startData = [...prevDataRef.current];
21225
21452
  const startTime = performance.now();
21226
21453
  const duration = 1200;
@@ -21250,7 +21477,7 @@ var CycleTimeOverTimeChart = ({
21250
21477
  }
21251
21478
  animationFrameRef.current = requestAnimationFrame(animate);
21252
21479
  }, []);
21253
- React19__default.useEffect(() => {
21480
+ React20__default.useEffect(() => {
21254
21481
  if (JSON.stringify(data) !== JSON.stringify(prevDataRef.current)) {
21255
21482
  const processedData = getDisplayData(data);
21256
21483
  animateToNewData(processedData);
@@ -21261,7 +21488,7 @@ var CycleTimeOverTimeChart = ({
21261
21488
  }
21262
21489
  };
21263
21490
  }, [data, animateToNewData]);
21264
- React19__default.useEffect(() => {
21491
+ React20__default.useEffect(() => {
21265
21492
  const checkContainerDimensions = () => {
21266
21493
  if (containerRef.current) {
21267
21494
  const rect = containerRef.current.getBoundingClientRect();
@@ -21504,7 +21731,7 @@ var CycleTimeOverTimeChart = ({
21504
21731
  }
21505
21732
  );
21506
21733
  };
21507
- var Card = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21734
+ var Card = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21508
21735
  "div",
21509
21736
  {
21510
21737
  ref,
@@ -21516,7 +21743,7 @@ var Card = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
21516
21743
  }
21517
21744
  ));
21518
21745
  Card.displayName = "Card";
21519
- var CardHeader = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21746
+ var CardHeader = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21520
21747
  "div",
21521
21748
  {
21522
21749
  ref,
@@ -21525,7 +21752,7 @@ var CardHeader = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE
21525
21752
  }
21526
21753
  ));
21527
21754
  CardHeader.displayName = "CardHeader";
21528
- var CardTitle = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21755
+ var CardTitle = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21529
21756
  "h3",
21530
21757
  {
21531
21758
  ref,
@@ -21537,7 +21764,7 @@ var CardTitle = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE_
21537
21764
  }
21538
21765
  ));
21539
21766
  CardTitle.displayName = "CardTitle";
21540
- var CardDescription = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21767
+ var CardDescription = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21541
21768
  "p",
21542
21769
  {
21543
21770
  ref,
@@ -21546,9 +21773,9 @@ var CardDescription = React19.forwardRef(({ className, ...props }, ref) => /* @_
21546
21773
  }
21547
21774
  ));
21548
21775
  CardDescription.displayName = "CardDescription";
21549
- var CardContent = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
21776
+ var CardContent = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
21550
21777
  CardContent.displayName = "CardContent";
21551
- var CardFooter = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21778
+ var CardFooter = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21552
21779
  "div",
21553
21780
  {
21554
21781
  ref,
@@ -21624,7 +21851,7 @@ var buttonVariants = cva(
21624
21851
  }
21625
21852
  }
21626
21853
  );
21627
- var Button = React19.forwardRef(
21854
+ var Button = React20.forwardRef(
21628
21855
  ({ className, variant, size, asChild = false, ...props }, ref) => {
21629
21856
  const Comp = asChild ? Slot : "button";
21630
21857
  return /* @__PURE__ */ jsx(
@@ -21647,8 +21874,8 @@ var HourlyOutputChartComponent = ({
21647
21874
  idleTimeHourly,
21648
21875
  className = ""
21649
21876
  }) => {
21650
- const containerRef = React19__default.useRef(null);
21651
- const [containerReady, setContainerReady] = React19__default.useState(false);
21877
+ const containerRef = React20__default.useRef(null);
21878
+ const [containerReady, setContainerReady] = React20__default.useState(false);
21652
21879
  const getTimeFromTimeString = (timeStr) => {
21653
21880
  const [hours, minutes] = timeStr.split(":");
21654
21881
  const hour = parseInt(hours);
@@ -21657,7 +21884,7 @@ var HourlyOutputChartComponent = ({
21657
21884
  return { hour, minute, decimalHour };
21658
21885
  };
21659
21886
  const shiftStartTime = getTimeFromTimeString(shiftStart);
21660
- const { shiftDuration, shiftEndTime, hasPartialLastHour } = React19__default.useMemo(() => {
21887
+ const { shiftDuration, shiftEndTime, hasPartialLastHour } = React20__default.useMemo(() => {
21661
21888
  console.log("[HourlyOutputChart] Calculating shift duration with:", {
21662
21889
  shiftStart,
21663
21890
  shiftEnd,
@@ -21692,12 +21919,12 @@ var HourlyOutputChartComponent = ({
21692
21919
  }, [shiftEnd, shiftStartTime.decimalHour]);
21693
21920
  const SHIFT_DURATION = shiftDuration;
21694
21921
  shiftEndTime ? shiftEndTime.hour : (shiftStartTime.hour + SHIFT_DURATION) % 24;
21695
- const [animatedData, setAnimatedData] = React19__default.useState(
21922
+ const [animatedData, setAnimatedData] = React20__default.useState(
21696
21923
  () => Array(SHIFT_DURATION).fill(0)
21697
21924
  );
21698
- const prevDataRef = React19__default.useRef(Array(SHIFT_DURATION).fill(0));
21699
- const animationFrameRef = React19__default.useRef(null);
21700
- React19__default.useEffect(() => {
21925
+ const prevDataRef = React20__default.useRef(Array(SHIFT_DURATION).fill(0));
21926
+ const animationFrameRef = React20__default.useRef(null);
21927
+ React20__default.useEffect(() => {
21701
21928
  setAnimatedData((prev) => {
21702
21929
  if (prev.length !== SHIFT_DURATION) {
21703
21930
  return Array(SHIFT_DURATION).fill(0);
@@ -21706,14 +21933,14 @@ var HourlyOutputChartComponent = ({
21706
21933
  });
21707
21934
  prevDataRef.current = Array(SHIFT_DURATION).fill(0);
21708
21935
  }, [SHIFT_DURATION]);
21709
- const [idleBarState, setIdleBarState] = React19__default.useState({
21936
+ const [idleBarState, setIdleBarState] = React20__default.useState({
21710
21937
  visible: showIdleTime,
21711
21938
  key: 0,
21712
21939
  shouldAnimate: false
21713
21940
  });
21714
- const prevShowIdleTimeRef = React19__default.useRef(showIdleTime);
21715
- const stateUpdateTimeoutRef = React19__default.useRef(null);
21716
- React19__default.useEffect(() => {
21941
+ const prevShowIdleTimeRef = React20__default.useRef(showIdleTime);
21942
+ const stateUpdateTimeoutRef = React20__default.useRef(null);
21943
+ React20__default.useEffect(() => {
21717
21944
  if (stateUpdateTimeoutRef.current) {
21718
21945
  clearTimeout(stateUpdateTimeoutRef.current);
21719
21946
  }
@@ -21738,7 +21965,7 @@ var HourlyOutputChartComponent = ({
21738
21965
  }
21739
21966
  };
21740
21967
  }, [showIdleTime]);
21741
- const animateToNewData = React19__default.useCallback((targetData) => {
21968
+ const animateToNewData = React20__default.useCallback((targetData) => {
21742
21969
  const startData = [...prevDataRef.current];
21743
21970
  const startTime = performance.now();
21744
21971
  const duration = 1200;
@@ -21768,7 +21995,7 @@ var HourlyOutputChartComponent = ({
21768
21995
  }
21769
21996
  animationFrameRef.current = requestAnimationFrame(animate);
21770
21997
  }, []);
21771
- React19__default.useEffect(() => {
21998
+ React20__default.useEffect(() => {
21772
21999
  if (JSON.stringify(data) !== JSON.stringify(prevDataRef.current)) {
21773
22000
  const shiftData = data.slice(0, SHIFT_DURATION);
21774
22001
  animateToNewData(shiftData);
@@ -21779,7 +22006,7 @@ var HourlyOutputChartComponent = ({
21779
22006
  }
21780
22007
  };
21781
22008
  }, [data, animateToNewData]);
21782
- React19__default.useEffect(() => {
22009
+ React20__default.useEffect(() => {
21783
22010
  const checkContainerDimensions = () => {
21784
22011
  if (containerRef.current) {
21785
22012
  const rect = containerRef.current.getBoundingClientRect();
@@ -21801,7 +22028,7 @@ var HourlyOutputChartComponent = ({
21801
22028
  clearTimeout(fallbackTimeout);
21802
22029
  };
21803
22030
  }, []);
21804
- const formatHour = React19__default.useCallback((hourIndex) => {
22031
+ const formatHour = React20__default.useCallback((hourIndex) => {
21805
22032
  const isLastHour = hourIndex === SHIFT_DURATION - 1;
21806
22033
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
21807
22034
  const startHour = Math.floor(startDecimalHour) % 24;
@@ -21825,7 +22052,7 @@ var HourlyOutputChartComponent = ({
21825
22052
  };
21826
22053
  return `${formatTime3(startHour, startMinute)}-${formatTime3(endHour, endMinute)}`;
21827
22054
  }, [shiftStartTime.decimalHour, SHIFT_DURATION, shiftEndTime]);
21828
- const formatTimeRange = React19__default.useCallback((hourIndex) => {
22055
+ const formatTimeRange = React20__default.useCallback((hourIndex) => {
21829
22056
  const isLastHour = hourIndex === SHIFT_DURATION - 1;
21830
22057
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
21831
22058
  const startHour = Math.floor(startDecimalHour) % 24;
@@ -21846,7 +22073,7 @@ var HourlyOutputChartComponent = ({
21846
22073
  };
21847
22074
  return `${formatTime3(startHour, startMinute)} - ${formatTime3(endHour, endMinute)}`;
21848
22075
  }, [shiftStartTime.decimalHour, SHIFT_DURATION, shiftEndTime]);
21849
- const chartData = React19__default.useMemo(() => {
22076
+ const chartData = React20__default.useMemo(() => {
21850
22077
  return Array.from({ length: SHIFT_DURATION }, (_, i) => {
21851
22078
  const actualHour = (shiftStartTime.hour + i) % 24;
21852
22079
  const startMinute = shiftStartTime.minute;
@@ -21915,7 +22142,7 @@ var HourlyOutputChartComponent = ({
21915
22142
  };
21916
22143
  });
21917
22144
  }, [animatedData, data, pphThreshold, idleTimeHourly, shiftStartTime.hour, shiftStartTime.minute, shiftEndTime, formatHour, formatTimeRange, SHIFT_DURATION]);
21918
- const IdleBar = React19__default.useMemo(() => {
22145
+ const IdleBar = React20__default.useMemo(() => {
21919
22146
  if (!idleBarState.visible) return null;
21920
22147
  return /* @__PURE__ */ jsx(
21921
22148
  Bar,
@@ -22240,7 +22467,7 @@ var HourlyOutputChartComponent = ({
22240
22467
  }
22241
22468
  );
22242
22469
  };
22243
- var HourlyOutputChart = React19__default.memo(HourlyOutputChartComponent, (prevProps, nextProps) => {
22470
+ var HourlyOutputChart = React20__default.memo(HourlyOutputChartComponent, (prevProps, nextProps) => {
22244
22471
  if (prevProps.pphThreshold !== nextProps.pphThreshold || prevProps.shiftStart !== nextProps.shiftStart || prevProps.showIdleTime !== nextProps.showIdleTime || prevProps.className !== nextProps.className) {
22245
22472
  return false;
22246
22473
  }
@@ -22276,7 +22503,7 @@ function getTrendArrowAndColor(trend) {
22276
22503
  return { arrow: "\u2192", color: "text-gray-400" };
22277
22504
  }
22278
22505
  }
22279
- var VideoCard = React19__default.memo(({
22506
+ var VideoCard = React20__default.memo(({
22280
22507
  workspace,
22281
22508
  hlsUrl,
22282
22509
  shouldPlay,
@@ -22425,7 +22652,7 @@ var VideoCard = React19__default.memo(({
22425
22652
  });
22426
22653
  VideoCard.displayName = "VideoCard";
22427
22654
  var DEFAULT_HLS_URL = "https://192.168.5.9:8443/cam1.m3u8";
22428
- var VideoGridView = React19__default.memo(({
22655
+ var VideoGridView = React20__default.memo(({
22429
22656
  workspaces,
22430
22657
  selectedLine,
22431
22658
  className = "",
@@ -23203,7 +23430,7 @@ var PieChart4 = ({
23203
23430
  }
23204
23431
  );
23205
23432
  };
23206
- const CustomTooltip = ({ active, payload }) => {
23433
+ const CustomTooltip2 = ({ active, payload }) => {
23207
23434
  if (active && payload && payload.length) {
23208
23435
  const data2 = payload[0];
23209
23436
  return /* @__PURE__ */ jsxs("div", { className: "bg-white px-3 py-2 shadow-lg rounded-lg border border-gray-200", children: [
@@ -23234,7 +23461,7 @@ var PieChart4 = ({
23234
23461
  children: dataWithPercentage.map((entry, index) => /* @__PURE__ */ jsx(Cell, { fill: colors[index % colors.length] }, `cell-${index}`))
23235
23462
  }
23236
23463
  ),
23237
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip, {}) }),
23464
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip2, {}) }),
23238
23465
  /* @__PURE__ */ jsx(
23239
23466
  Legend,
23240
23467
  {
@@ -23362,7 +23589,7 @@ var EmptyStateMessage = ({
23362
23589
  iconClassName
23363
23590
  }) => {
23364
23591
  let IconContent = null;
23365
- if (React19__default.isValidElement(iconType)) {
23592
+ if (React20__default.isValidElement(iconType)) {
23366
23593
  IconContent = iconType;
23367
23594
  } else if (typeof iconType === "string") {
23368
23595
  const MappedIcon = IconMap[iconType];
@@ -26365,6 +26592,28 @@ var getOrdinal = (n) => {
26365
26592
  const v = n % 100;
26366
26593
  return n + (suffix[(v - 20) % 10] || suffix[v] || suffix[0]);
26367
26594
  };
26595
+ var CustomTooltip = ({ active, payload, label }) => {
26596
+ if (active && payload && payload.length) {
26597
+ return /* @__PURE__ */ jsxs("div", { className: "bg-white/95 backdrop-blur-sm p-3 rounded-lg shadow-lg border border-gray-100", children: [
26598
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-gray-800 mb-1", children: label }),
26599
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
26600
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-600", children: [
26601
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Actual:" }),
26602
+ " ",
26603
+ Math.round(payload[0].value),
26604
+ " units"
26605
+ ] }),
26606
+ payload[0].payload.idealOutput > 0 && /* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-600", children: [
26607
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Target:" }),
26608
+ " ",
26609
+ Math.round(payload[0].payload.idealOutput),
26610
+ " units"
26611
+ ] })
26612
+ ] })
26613
+ ] });
26614
+ }
26615
+ return null;
26616
+ };
26368
26617
  var WorkspaceMonthlyHistory = ({
26369
26618
  data,
26370
26619
  month,
@@ -26416,8 +26665,31 @@ var WorkspaceMonthlyHistory = ({
26416
26665
  });
26417
26666
  }
26418
26667
  const avgIdealOutput = validDaysCount > 0 ? totalIdealOutput / validDaysCount : 0;
26419
- return { data: dailyData, maxOutput, avgIdealOutput };
26668
+ const calculatedMax = Math.max(maxOutput, avgIdealOutput);
26669
+ const yAxisMax = calculatedMax > 0 ? calculatedMax * 1.1 : 100;
26670
+ return { data: dailyData, maxOutput, avgIdealOutput, yAxisMax };
26420
26671
  }, [data, month, year, selectedShift]);
26672
+ const yAxisTicks = useMemo(() => {
26673
+ const max = chartData.yAxisMax;
26674
+ const target = chartData.avgIdealOutput;
26675
+ if (!max || max <= 0) return void 0;
26676
+ const desiredIntervals = 4;
26677
+ const roughStep = max / desiredIntervals;
26678
+ const power = Math.pow(10, Math.floor(Math.log10(roughStep)));
26679
+ const normalized = roughStep / power;
26680
+ let step = 1 * power;
26681
+ if (normalized >= 1.5 && normalized < 3) step = 2 * power;
26682
+ else if (normalized >= 3 && normalized < 7) step = 5 * power;
26683
+ else if (normalized >= 7) step = 10 * power;
26684
+ const ticks = [];
26685
+ for (let v = 0; v <= max; v += step) {
26686
+ ticks.push(Math.round(v));
26687
+ }
26688
+ if (target > 0) {
26689
+ ticks.push(Math.round(target));
26690
+ }
26691
+ return Array.from(new Set(ticks)).filter((v) => v >= 0 && v <= max).sort((a, b) => a - b);
26692
+ }, [chartData.yAxisMax, chartData.avgIdealOutput]);
26421
26693
  const pieChartData = useMemo(() => {
26422
26694
  const validShifts = data.map((d) => selectedShift === "day" ? d.dayShift : d.nightShift).filter(hasRealData);
26423
26695
  if (validShifts.length === 0) return [];
@@ -26627,24 +26899,18 @@ var WorkspaceMonthlyHistory = ({
26627
26899
  }, children: [
26628
26900
  metrics2?.avgEfficiency ?? 0,
26629
26901
  "%"
26630
- ] }),
26631
- /* @__PURE__ */ jsxs("div", { className: "text-[10px] text-gray-500 text-center mt-1", children: [
26632
- new Date(year, month).toLocaleString("default", { month: "short" }),
26633
- " avg"
26634
26902
  ] })
26635
26903
  ] }),
26636
26904
  /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4", children: [
26637
26905
  /* @__PURE__ */ jsx("div", { className: "text-xs font-medium text-gray-600 text-center mb-1", children: "Avg Daily Output" }),
26638
- /* @__PURE__ */ jsx("div", { className: "text-2xl font-bold text-center text-gray-900", children: metrics2?.avgDailyOutput?.toLocaleString?.() ?? 0 }),
26639
- /* @__PURE__ */ jsx("div", { className: "text-[10px] text-gray-500 text-center mt-1", children: "units/day" })
26906
+ /* @__PURE__ */ jsx("div", { className: "text-2xl font-bold text-center text-gray-900", children: metrics2?.avgDailyOutput?.toLocaleString?.() ?? 0 })
26640
26907
  ] }),
26641
26908
  /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4", children: [
26642
26909
  /* @__PURE__ */ jsx("div", { className: "text-xs font-medium text-gray-600 text-center mb-1", children: "Avg Cycle Time" }),
26643
26910
  /* @__PURE__ */ jsxs("div", { className: "text-2xl font-bold text-center text-gray-900", children: [
26644
26911
  metrics2?.avgCycleTime ?? 0,
26645
26912
  "s"
26646
- ] }),
26647
- /* @__PURE__ */ jsx("div", { className: "text-[10px] text-gray-500 text-center mt-1", children: "per unit" })
26913
+ ] })
26648
26914
  ] })
26649
26915
  ] }),
26650
26916
  /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4", children: [
@@ -26708,43 +26974,55 @@ var WorkspaceMonthlyHistory = ({
26708
26974
  ] }),
26709
26975
  /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex-1", children: [
26710
26976
  /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-700 mb-3", children: "Daily Output" }),
26711
- /* @__PURE__ */ jsx("div", { style: { height: "200px" }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
26977
+ /* @__PURE__ */ jsx("div", { style: { height: "220px" }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
26712
26978
  BarChart$1,
26713
26979
  {
26714
26980
  data: chartData.data,
26715
- margin: { top: 5, right: 5, bottom: 35, left: 5 },
26981
+ margin: { top: 20, right: 10, bottom: 40, left: 10 },
26716
26982
  children: [
26717
26983
  /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#f3f4f6" }),
26718
26984
  /* @__PURE__ */ jsx(
26719
26985
  XAxis,
26720
26986
  {
26721
26987
  dataKey: "hour",
26722
- tick: { fontSize: 9, fill: "#9ca3af" },
26988
+ tick: { fontSize: 10, fill: "#6b7280" },
26723
26989
  interval: 0,
26724
26990
  angle: -45,
26725
- textAnchor: "end"
26991
+ textAnchor: "end",
26992
+ height: 60
26726
26993
  }
26727
26994
  ),
26728
26995
  /* @__PURE__ */ jsx(
26729
26996
  YAxis,
26730
26997
  {
26731
- tick: { fontSize: 9, fill: "#9ca3af" },
26732
- domain: [0, "dataMax"],
26733
- width: 30
26998
+ domain: [0, chartData.yAxisMax],
26999
+ width: 35,
27000
+ ticks: yAxisTicks,
27001
+ tick: (props) => {
27002
+ const { x, y, payload } = props;
27003
+ const value = Math.round(payload.value);
27004
+ const targetValue = Math.round(chartData.avgIdealOutput);
27005
+ const isTarget = Math.abs(value - targetValue) < 1 && targetValue > 0;
27006
+ return /* @__PURE__ */ jsx(
27007
+ "text",
27008
+ {
27009
+ x: x - 5,
27010
+ y: y + 4,
27011
+ textAnchor: "end",
27012
+ fontSize: "10",
27013
+ fill: isTarget ? "#E34329" : "#6b7280",
27014
+ fontWeight: isTarget ? "600" : "normal",
27015
+ children: value < 1e-3 ? "" : value.toString()
27016
+ }
27017
+ );
27018
+ }
26734
27019
  }
26735
27020
  ),
26736
27021
  /* @__PURE__ */ jsx(
26737
27022
  Tooltip,
26738
27023
  {
26739
27024
  cursor: false,
26740
- contentStyle: {
26741
- backgroundColor: "rgba(255, 255, 255, 0.95)",
26742
- border: "1px solid #e5e7eb",
26743
- borderRadius: "6px",
26744
- fontSize: "11px",
26745
- padding: "8px"
26746
- },
26747
- labelStyle: { fontSize: "11px", fontWeight: "600" }
27025
+ content: CustomTooltip
26748
27026
  }
26749
27027
  ),
26750
27028
  chartData.avgIdealOutput > 0 && /* @__PURE__ */ jsx(
@@ -26752,40 +27030,68 @@ var WorkspaceMonthlyHistory = ({
26752
27030
  {
26753
27031
  y: chartData.avgIdealOutput,
26754
27032
  stroke: "#E34329",
26755
- strokeDasharray: "3 3",
27033
+ strokeDasharray: "5 5",
26756
27034
  strokeWidth: 2
26757
27035
  }
26758
27036
  ),
26759
- /* @__PURE__ */ jsx(Bar, { dataKey: "output", radius: [3, 3, 0, 0], children: chartData.data.map((entry, index) => /* @__PURE__ */ jsx(
26760
- Cell,
26761
- {
26762
- fill: entry.output === 0 ? "#f3f4f6" : entry.color,
26763
- style: {
26764
- filter: "brightness(1)",
26765
- transition: "filter 0.3s ease, transform 0.3s ease",
26766
- cursor: "pointer"
26767
- },
26768
- onMouseEnter: (e) => {
26769
- const target = e.target;
26770
- target.style.filter = "brightness(1.1)";
26771
- target.style.transform = "translateY(-4px)";
27037
+ /* @__PURE__ */ jsxs(Bar, { dataKey: "output", radius: [4, 4, 0, 0], children: [
27038
+ chartData.data.map((entry, index) => /* @__PURE__ */ jsx(
27039
+ Cell,
27040
+ {
27041
+ fill: entry.output === 0 ? "#f3f4f6" : entry.color,
27042
+ style: {
27043
+ filter: "brightness(1)",
27044
+ transition: "all 0.3s ease",
27045
+ cursor: entry.output > 0 ? "pointer" : "default"
27046
+ },
27047
+ onMouseEnter: (e) => {
27048
+ if (entry.output > 0) {
27049
+ const target = e.target;
27050
+ target.style.filter = "brightness(1.1)";
27051
+ target.style.transform = "translateY(-2px)";
27052
+ }
27053
+ },
27054
+ onMouseLeave: (e) => {
27055
+ const target = e.target;
27056
+ target.style.filter = "brightness(1)";
27057
+ target.style.transform = "translateY(0)";
27058
+ }
26772
27059
  },
26773
- onMouseLeave: (e) => {
26774
- const target = e.target;
26775
- target.style.filter = "brightness(1)";
26776
- target.style.transform = "translateY(0)";
27060
+ `cell-${index}`
27061
+ )),
27062
+ /* @__PURE__ */ jsx(
27063
+ LabelList,
27064
+ {
27065
+ dataKey: "originalOutput",
27066
+ position: "top",
27067
+ content: (props) => {
27068
+ const { x, y, width, value } = props;
27069
+ if (!value || value === 0) return null;
27070
+ return /* @__PURE__ */ jsx(
27071
+ "text",
27072
+ {
27073
+ x: x + width / 2,
27074
+ y: y - 5,
27075
+ textAnchor: "middle",
27076
+ fontSize: "11",
27077
+ fontWeight: "600",
27078
+ fill: "#374151",
27079
+ children: Math.round(value)
27080
+ }
27081
+ );
27082
+ }
26777
27083
  }
26778
- },
26779
- `cell-${index}`
26780
- )) })
27084
+ )
27085
+ ] })
26781
27086
  ]
26782
27087
  }
26783
27088
  ) }) }),
26784
- chartData.avgIdealOutput > 0 && /* @__PURE__ */ jsx("div", { className: "flex justify-center items-center gap-4 mt-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
26785
- /* @__PURE__ */ jsx("div", { className: "w-8 h-0.5 border-t border-dashed", style: { borderColor: "#E34329" } }),
26786
- /* @__PURE__ */ jsxs("span", { className: "text-[9px] text-gray-500", children: [
27089
+ /* @__PURE__ */ jsx("div", { className: "flex justify-center items-center gap-6 mt-3", children: chartData.avgIdealOutput > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
27090
+ /* @__PURE__ */ jsx("div", { className: "w-12 h-0.5 border-t-2 border-dashed", style: { borderColor: "#E34329" } }),
27091
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-600", children: [
26787
27092
  "Target: ",
26788
- Math.round(chartData.avgIdealOutput)
27093
+ Math.round(chartData.avgIdealOutput),
27094
+ " units/day"
26789
27095
  ] })
26790
27096
  ] }) })
26791
27097
  ] })
@@ -27298,7 +27604,7 @@ function Skeleton({ className, ...props }) {
27298
27604
  var Select = SelectPrimitive.Root;
27299
27605
  var SelectGroup = SelectPrimitive.Group;
27300
27606
  var SelectValue = SelectPrimitive.Value;
27301
- var SelectTrigger = React19.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
27607
+ var SelectTrigger = React20.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
27302
27608
  SelectPrimitive.Trigger,
27303
27609
  {
27304
27610
  ref,
@@ -27314,7 +27620,7 @@ var SelectTrigger = React19.forwardRef(({ className, children, ...props }, ref)
27314
27620
  }
27315
27621
  ));
27316
27622
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
27317
- var SelectScrollUpButton = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
27623
+ var SelectScrollUpButton = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
27318
27624
  SelectPrimitive.ScrollUpButton,
27319
27625
  {
27320
27626
  ref,
@@ -27324,7 +27630,7 @@ var SelectScrollUpButton = React19.forwardRef(({ className, ...props }, ref) =>
27324
27630
  }
27325
27631
  ));
27326
27632
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
27327
- var SelectScrollDownButton = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
27633
+ var SelectScrollDownButton = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
27328
27634
  SelectPrimitive.ScrollDownButton,
27329
27635
  {
27330
27636
  ref,
@@ -27334,7 +27640,7 @@ var SelectScrollDownButton = React19.forwardRef(({ className, ...props }, ref) =
27334
27640
  }
27335
27641
  ));
27336
27642
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
27337
- var SelectContent = React19.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
27643
+ var SelectContent = React20.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
27338
27644
  SelectPrimitive.Content,
27339
27645
  {
27340
27646
  ref,
@@ -27362,7 +27668,7 @@ var SelectContent = React19.forwardRef(({ className, children, position = "poppe
27362
27668
  }
27363
27669
  ) }));
27364
27670
  SelectContent.displayName = SelectPrimitive.Content.displayName;
27365
- var SelectLabel = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
27671
+ var SelectLabel = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
27366
27672
  SelectPrimitive.Label,
27367
27673
  {
27368
27674
  ref,
@@ -27371,7 +27677,7 @@ var SelectLabel = React19.forwardRef(({ className, ...props }, ref) => /* @__PUR
27371
27677
  }
27372
27678
  ));
27373
27679
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
27374
- var SelectItem = React19.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
27680
+ var SelectItem = React20.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
27375
27681
  SelectPrimitive.Item,
27376
27682
  {
27377
27683
  ref,
@@ -27387,7 +27693,7 @@ var SelectItem = React19.forwardRef(({ className, children, ...props }, ref) =>
27387
27693
  }
27388
27694
  ));
27389
27695
  SelectItem.displayName = SelectPrimitive.Item.displayName;
27390
- var SelectSeparator = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
27696
+ var SelectSeparator = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
27391
27697
  SelectPrimitive.Separator,
27392
27698
  {
27393
27699
  ref,
@@ -27680,7 +27986,7 @@ if (typeof document !== "undefined") {
27680
27986
  document.head.appendChild(style);
27681
27987
  }
27682
27988
  }
27683
- var VideoPlayer = React19__default.forwardRef(({
27989
+ var VideoPlayer = React20__default.forwardRef(({
27684
27990
  src,
27685
27991
  poster,
27686
27992
  autoplay = false,
@@ -27965,7 +28271,7 @@ var VideoPlayer = React19__default.forwardRef(({
27965
28271
  setIsReady(false);
27966
28272
  }
27967
28273
  }, []);
27968
- React19__default.useImperativeHandle(ref, () => ({
28274
+ React20__default.useImperativeHandle(ref, () => ({
27969
28275
  player: playerRef.current,
27970
28276
  play,
27971
28277
  pause,
@@ -28645,6 +28951,47 @@ function useWorkspaceCrop(workspaceId) {
28645
28951
  }, [workspaceId]);
28646
28952
  return { crop, isLoading, error };
28647
28953
  }
28954
+ var FilterDialogTrigger = ({
28955
+ className = ""
28956
+ }) => {
28957
+ const { state, toggleAdvancedPanel } = useClipFilter();
28958
+ const activeFiltersCount = [
28959
+ state.showFastCycles,
28960
+ state.showSlowCycles,
28961
+ state.showLongestIdles,
28962
+ state.showCycleCompletion,
28963
+ state.showIdleTime
28964
+ ].filter(Boolean).length;
28965
+ const isDefaultPercentile = state.percentile === 10;
28966
+ const isDefaultShift = state.shiftFilter === void 0;
28967
+ const hasCustomFilters = !isDefaultPercentile || !isDefaultShift || activeFiltersCount < 5;
28968
+ return /* @__PURE__ */ jsxs(
28969
+ "button",
28970
+ {
28971
+ onClick: toggleAdvancedPanel,
28972
+ className: `relative group p-2.5 bg-gradient-to-r from-blue-50 to-indigo-50 hover:from-blue-100 hover:to-indigo-100 border border-blue-200/60 hover:border-blue-300 rounded-xl transition-all duration-200 hover:shadow-lg hover:shadow-blue-100/50 ${className}`,
28973
+ title: "Advanced Filters",
28974
+ children: [
28975
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
28976
+ /* @__PURE__ */ jsx(Sliders, { className: "h-5 w-5 text-blue-600 group-hover:text-blue-700 transition-colors" }),
28977
+ hasCustomFilters && /* @__PURE__ */ jsx(Sparkles, { className: "absolute -top-1 -right-1 h-3 w-3 text-yellow-500 animate-pulse" })
28978
+ ] }),
28979
+ hasCustomFilters && /* @__PURE__ */ jsx("div", { className: "absolute -top-1 -right-1 bg-gradient-to-r from-yellow-400 to-orange-400 text-white text-xs font-bold rounded-full h-5 w-5 flex items-center justify-center shadow-lg animate-bounce", children: activeFiltersCount < 5 ? activeFiltersCount : "!" }),
28980
+ /* @__PURE__ */ jsxs("div", { className: "absolute bottom-full right-0 mb-2 px-3 py-1.5 bg-gray-900 text-white text-xs rounded-lg opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none whitespace-nowrap", children: [
28981
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
28982
+ /* @__PURE__ */ jsx("div", { className: "font-semibold", children: "Advanced Filters" }),
28983
+ /* @__PURE__ */ jsx("div", { className: "text-gray-300", children: hasCustomFilters ? /* @__PURE__ */ jsxs(Fragment, { children: [
28984
+ !isDefaultPercentile && `${state.percentile}% percentile`,
28985
+ !isDefaultShift && ` \u2022 Shift ${state.shiftFilter === 0 ? "Day" : "Night"}`,
28986
+ activeFiltersCount < 5 && ` \u2022 ${activeFiltersCount}/5 types`
28987
+ ] }) : "Default settings" })
28988
+ ] }),
28989
+ /* @__PURE__ */ jsx("div", { className: "absolute top-full right-4 w-0 h-0 border-l-2 border-r-2 border-t-4 border-transparent border-t-gray-900" })
28990
+ ] })
28991
+ ]
28992
+ }
28993
+ );
28994
+ };
28648
28995
  var getSeverityIcon = (severity) => {
28649
28996
  switch (severity) {
28650
28997
  case "high":
@@ -28708,6 +29055,10 @@ var FileManagerFilters = ({
28708
29055
  const [loadingCategories, setLoadingCategories] = useState(/* @__PURE__ */ new Set());
28709
29056
  const [categoryPages, setCategoryPages] = useState({});
28710
29057
  const [categoryHasMore, setCategoryHasMore] = useState({});
29058
+ const { state: filterState, updatePercentile } = useClipFilter();
29059
+ const [percentileCounts, setPercentileCounts] = useState({});
29060
+ const [percentileClips, setPercentileClips] = useState({});
29061
+ const [loadingPercentile, setLoadingPercentile] = useState(false);
28711
29062
  const fetchClipMetadata = useCallback(async (categoryId, page = 1) => {
28712
29063
  if (!workspaceId || !date || shift === void 0) {
28713
29064
  console.warn("[FileManager] Missing required params for clip metadata fetch");
@@ -28767,6 +29118,91 @@ var FileManagerFilters = ({
28767
29118
  return null;
28768
29119
  }
28769
29120
  };
29121
+ const fetchPercentileClips = useCallback(async (type) => {
29122
+ if (!workspaceId || !date || shift === void 0) {
29123
+ console.warn("[FileManager] Missing required params for percentile clips fetch");
29124
+ return;
29125
+ }
29126
+ try {
29127
+ const startDate = `${date}T00:00:00Z`;
29128
+ const endDate = `${date}T23:59:59Z`;
29129
+ const response = await fetch("/api/clips/supabase", {
29130
+ method: "POST",
29131
+ headers: {
29132
+ "Content-Type": "application/json",
29133
+ "Authorization": `Bearer ${await getAuthToken4()}`
29134
+ },
29135
+ body: JSON.stringify({
29136
+ action: "percentile-clips",
29137
+ workspaceId,
29138
+ startDate,
29139
+ endDate,
29140
+ percentile: filterState.percentile,
29141
+ shiftId: shift,
29142
+ limit: 50,
29143
+ // The actual percentile action (fast-cycles, slow-cycles, idle-times)
29144
+ percentileAction: type
29145
+ })
29146
+ });
29147
+ if (!response.ok) {
29148
+ throw new Error(`API error: ${response.status}`);
29149
+ }
29150
+ const data = await response.json();
29151
+ setPercentileClips((prev) => ({
29152
+ ...prev,
29153
+ [type]: data.clips || []
29154
+ }));
29155
+ setPercentileCounts((prev) => ({
29156
+ ...prev,
29157
+ [type]: data.total || 0
29158
+ }));
29159
+ console.log(`[FileManager] Loaded ${data.clips?.length || 0} ${type} clips (percentile: ${filterState.percentile}%)`);
29160
+ } catch (error) {
29161
+ console.error(`[FileManager] Error fetching ${type} clips:`, error);
29162
+ }
29163
+ }, [workspaceId, date, shift, filterState.percentile]);
29164
+ useEffect(() => {
29165
+ if (workspaceId && date && shift !== void 0) {
29166
+ setLoadingPercentile(true);
29167
+ Promise.all([
29168
+ fetchPercentileClips("fast-cycles"),
29169
+ fetchPercentileClips("slow-cycles")
29170
+ // fetchPercentileClips('idle-times') // Temporarily commented out
29171
+ ]).finally(() => {
29172
+ setLoadingPercentile(false);
29173
+ });
29174
+ }
29175
+ }, [fetchPercentileClips]);
29176
+ const shouldShowCategory = useCallback((categoryId) => {
29177
+ switch (categoryId) {
29178
+ case "fast-cycles":
29179
+ return filterState.showFastCycles;
29180
+ case "slow-cycles":
29181
+ return filterState.showSlowCycles;
29182
+ case "longest-idles":
29183
+ return false;
29184
+ // filterState.showLongestIdles; // Temporarily disabled
29185
+ case "cycle_completion":
29186
+ return filterState.showCycleCompletion;
29187
+ case "idle_time":
29188
+ return filterState.showIdleTime;
29189
+ case "sop_deviations":
29190
+ return filterState.showSopDeviations;
29191
+ default:
29192
+ return true;
29193
+ }
29194
+ }, [filterState]);
29195
+ const getPercentileIcon = useCallback((type, isExpanded, colorClasses) => {
29196
+ const iconMap = {
29197
+ "fast-cycles": { icon: TrendingUp, color: "text-green-600" },
29198
+ "slow-cycles": { icon: TrendingDown, color: "text-red-600" },
29199
+ "longest-idles": { icon: Clock, color: "text-orange-600" }
29200
+ };
29201
+ const config = iconMap[type];
29202
+ if (!config) return null;
29203
+ const IconComponent = config.icon;
29204
+ return isExpanded ? /* @__PURE__ */ jsx(FolderOpen, { className: `h-4 w-4 ${config.color}` }) : /* @__PURE__ */ jsx(IconComponent, { className: `h-4 w-4 ${config.color}` });
29205
+ }, []);
28770
29206
  const filterTree = useMemo(() => {
28771
29207
  const tree = [];
28772
29208
  categories.forEach((category) => {
@@ -28778,7 +29214,7 @@ var FileManagerFilters = ({
28778
29214
  (clip) => clip.description.toLowerCase().includes(searchTerm.toLowerCase()) || clip.clip_timestamp.includes(searchTerm) || clip.severity.toLowerCase().includes(searchTerm.toLowerCase())
28779
29215
  );
28780
29216
  }
28781
- if (categoryCount > 0) {
29217
+ if (categoryCount > 0 && shouldShowCategory(category.id)) {
28782
29218
  const colorClasses = getColorClasses(category.color);
28783
29219
  const clipNodes = filteredClips.map((clip) => {
28784
29220
  const timeString = new Date(clip.clip_timestamp).toLocaleTimeString("en-US", {
@@ -28802,6 +29238,8 @@ var FileManagerFilters = ({
28802
29238
  tree.push({
28803
29239
  id: category.id,
28804
29240
  label: category.label,
29241
+ subtitle: category.subtitle || category.description,
29242
+ description: category.description,
28805
29243
  type: "category",
28806
29244
  count: categoryCount,
28807
29245
  // Use API count
@@ -28812,8 +29250,84 @@ var FileManagerFilters = ({
28812
29250
  });
28813
29251
  }
28814
29252
  });
29253
+ const percentileCategories = [
29254
+ {
29255
+ id: "fast-cycles",
29256
+ label: "Fast Cycles",
29257
+ subtitle: `Top ${filterState.percentile}% fastest performance`,
29258
+ description: `Top ${filterState.percentile}% fastest performance`,
29259
+ type: "percentile-category",
29260
+ count: percentileCounts["fast-cycles"] || 0,
29261
+ icon: getPercentileIcon("fast-cycles", expandedNodes.has("fast-cycles"), { text: "text-green-600" }),
29262
+ color: "green",
29263
+ percentileType: "fast-cycles",
29264
+ isPercentile: true,
29265
+ children: (percentileClips["fast-cycles"] || []).map((clip, index) => ({
29266
+ id: clip.id,
29267
+ // Remove prefix to match currentVideoId
29268
+ label: `${clip.timestamp} - ${clip.description}${clip.cycle_time_seconds ? ` (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
29269
+ type: "video",
29270
+ icon: getSeverityIcon(clip.severity),
29271
+ timestamp: clip.creation_timestamp,
29272
+ severity: clip.severity,
29273
+ clipId: clip.id,
29274
+ categoryId: "fast-cycles"
29275
+ }))
29276
+ },
29277
+ {
29278
+ id: "slow-cycles",
29279
+ label: "Slow Cycles",
29280
+ subtitle: `Top ${filterState.percentile}% slowest performance`,
29281
+ description: `Top ${filterState.percentile}% slowest performance`,
29282
+ type: "percentile-category",
29283
+ count: percentileCounts["slow-cycles"] || 0,
29284
+ icon: getPercentileIcon("slow-cycles", expandedNodes.has("slow-cycles"), { text: "text-red-600" }),
29285
+ color: "red",
29286
+ percentileType: "slow-cycles",
29287
+ isPercentile: true,
29288
+ children: (percentileClips["slow-cycles"] || []).map((clip, index) => ({
29289
+ id: clip.id,
29290
+ // Remove prefix to match currentVideoId
29291
+ label: `${clip.timestamp} - ${clip.description}${clip.cycle_time_seconds ? ` (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
29292
+ type: "video",
29293
+ icon: getSeverityIcon(clip.severity),
29294
+ timestamp: clip.creation_timestamp,
29295
+ severity: clip.severity,
29296
+ clipId: clip.id,
29297
+ categoryId: "slow-cycles"
29298
+ }))
29299
+ }
29300
+ // Temporarily commented out longest idle times
29301
+ /* {
29302
+ id: 'longest-idles',
29303
+ label: 'Longest Idle Times',
29304
+ subtitle: `Top ${filterState.percentile}% longest idle periods`,
29305
+ description: `Top ${filterState.percentile}% longest idle periods`,
29306
+ type: 'percentile-category' as const,
29307
+ count: percentileCounts['idle-times'] || 0,
29308
+ icon: getPercentileIcon('longest-idles', expandedNodes.has('longest-idles'), { text: 'text-orange-600' }),
29309
+ color: 'orange',
29310
+ percentileType: 'idle-times' as const,
29311
+ isPercentile: true,
29312
+ children: (percentileClips['idle-times'] || []).map((clip, index) => ({
29313
+ id: clip.id, // Remove prefix to match currentVideoId
29314
+ label: `${clip.timestamp} - ${clip.description}${clip.cycle_time_seconds ? ` (${clip.cycle_time_seconds.toFixed(1)}s)` : ''}`,
29315
+ type: 'video' as const,
29316
+ icon: getSeverityIcon(clip.severity),
29317
+ timestamp: clip.creation_timestamp,
29318
+ severity: clip.severity,
29319
+ clipId: clip.id,
29320
+ categoryId: 'longest-idles'
29321
+ }))
29322
+ } */
29323
+ ];
29324
+ percentileCategories.forEach((category) => {
29325
+ if (category.count > 0 && shouldShowCategory(category.id)) {
29326
+ tree.unshift(category);
29327
+ }
29328
+ });
28815
29329
  return tree;
28816
- }, [categories, expandedNodes, searchTerm, counts, clipMetadata]);
29330
+ }, [categories, expandedNodes, searchTerm, counts, clipMetadata, filterState.percentile, percentileCounts, percentileClips, shouldShowCategory, getPercentileIcon]);
28817
29331
  const toggleExpanded = (nodeId) => {
28818
29332
  const newExpanded = new Set(expandedNodes);
28819
29333
  if (newExpanded.has(nodeId)) {
@@ -28829,7 +29343,7 @@ var FileManagerFilters = ({
28829
29343
  setExpandedNodes(newExpanded);
28830
29344
  };
28831
29345
  const handleNodeClick = (node) => {
28832
- if (node.type === "category") {
29346
+ if (node.type === "category" || node.type === "percentile-category") {
28833
29347
  toggleExpanded(node.id);
28834
29348
  onFilterChange(node.id);
28835
29349
  } else if (node.type === "video") {
@@ -28848,7 +29362,7 @@ var FileManagerFilters = ({
28848
29362
  const isExpanded = expandedNodes.has(node.id);
28849
29363
  const isActive = activeFilter === node.id;
28850
29364
  const isCurrentVideo = currentVideoId === node.id;
28851
- const hasChildren = node.children && node.children.length > 0;
29365
+ const hasChildren = (node.count || 0) > 0;
28852
29366
  const colorClasses = node.color ? getColorClasses(node.color) : null;
28853
29367
  return /* @__PURE__ */ jsxs("div", { className: "select-none animate-in", children: [
28854
29368
  /* @__PURE__ */ jsxs(
@@ -28865,25 +29379,26 @@ var FileManagerFilters = ({
28865
29379
  e.stopPropagation();
28866
29380
  toggleExpanded(node.id);
28867
29381
  },
28868
- children: isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: `text-slate-600 group-hover:text-blue-600 transition-colors duration-200 ${node.type === "category" ? "h-4 w-4" : "h-3.5 w-3.5"}` }) : /* @__PURE__ */ jsx(ChevronRight, { className: `text-slate-600 group-hover:text-blue-600 transition-colors duration-200 ${node.type === "category" ? "h-4 w-4" : "h-3.5 w-3.5"}` })
29382
+ children: isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: `text-slate-600 group-hover:text-blue-600 transition-colors duration-200 ${node.type === "category" || node.type === "percentile-category" ? "h-4 w-4" : "h-3.5 w-3.5"}` }) : /* @__PURE__ */ jsx(ChevronRight, { className: `text-slate-600 group-hover:text-blue-600 transition-colors duration-200 ${node.type === "category" || node.type === "percentile-category" ? "h-4 w-4" : "h-3.5 w-3.5"}` })
28869
29383
  }
28870
29384
  ),
28871
- /* @__PURE__ */ jsx("div", { className: `flex-shrink-0 mr-3 ${node.type === "category" ? "p-2 rounded-lg shadow-sm group-hover:scale-110 transition-transform duration-200" : "p-0.5"} ${colorClasses && node.type === "category" ? `${colorClasses.bg} border border-white/60` : ""}`, children: node.icon }),
29385
+ /* @__PURE__ */ jsx("div", { className: `flex-shrink-0 mr-3 ${node.type === "category" || node.type === "percentile-category" ? "p-2 rounded-lg shadow-sm group-hover:scale-110 transition-transform duration-200" : "p-0.5"} ${colorClasses && (node.type === "category" || node.type === "percentile-category") ? `${colorClasses.bg} border border-white/60` : ""}`, children: node.icon }),
28872
29386
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 flex items-center justify-between", children: [
28873
29387
  /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
28874
- /* @__PURE__ */ jsx("div", { className: `font-semibold tracking-tight ${node.type === "category" ? "text-slate-800 text-sm" : "text-slate-700 text-xs"} ${isCurrentVideo ? "text-emerald-700 font-bold" : ""} group-hover:text-slate-900 transition-colors duration-200`, children: node.label }),
29388
+ /* @__PURE__ */ jsx("div", { className: `font-semibold tracking-tight ${node.type === "category" || node.type === "percentile-category" ? "text-slate-800 text-sm" : "text-slate-700 text-xs"} ${isCurrentVideo ? "text-emerald-700 font-bold" : ""} group-hover:text-slate-900 transition-colors duration-200`, children: node.label }),
28875
29389
  node.type === "category" && categories.find((c) => c.id === node.id)?.description && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: categories.find((c) => c.id === node.id)?.description }),
29390
+ node.type === "percentile-category" && node.subtitle && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: node.subtitle }),
28876
29391
  node.type === "video" && node.severity && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 capitalize mt-0.5 font-medium", children: /* @__PURE__ */ jsxs("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-medium ${node.severity === "high" ? "bg-red-100 text-red-700" : node.severity === "medium" ? "bg-yellow-100 text-yellow-700" : "bg-green-100 text-green-700"}`, children: [
28877
29392
  node.severity,
28878
29393
  " priority"
28879
29394
  ] }) })
28880
29395
  ] }),
28881
- node.count !== void 0 && node.type === "category" && /* @__PURE__ */ jsx("div", { className: "flex items-center ml-2", children: /* @__PURE__ */ jsx("span", { className: `px-2.5 py-1 text-sm font-bold rounded-lg shadow-sm border backdrop-blur-sm flex-shrink-0 group-hover:scale-105 transition-all duration-200 ${colorClasses ? `${colorClasses.bg} ${colorClasses.text} ${colorClasses.border} bg-opacity-80` : "bg-slate-100/80 text-slate-700 border-slate-200/60"}`, children: node.count }) })
29396
+ node.count !== void 0 && (node.type === "category" || node.type === "percentile-category") && /* @__PURE__ */ jsx("div", { className: "flex items-center ml-2", children: /* @__PURE__ */ jsx("span", { className: `px-2.5 py-1 text-sm font-bold rounded-lg shadow-sm border backdrop-blur-sm flex-shrink-0 group-hover:scale-105 transition-all duration-200 ${colorClasses ? `${colorClasses.bg} ${colorClasses.text} ${colorClasses.border} bg-opacity-80` : "bg-slate-100/80 text-slate-700 border-slate-200/60"}`, children: node.count }) })
28882
29397
  ] })
28883
29398
  ]
28884
29399
  }
28885
29400
  ),
28886
- hasChildren && isExpanded && node.type === "category" && /* @__PURE__ */ jsx("div", { className: "mt-2 ml-3 animate-in border-l-2 border-slate-100 pl-3", children: /* @__PURE__ */ jsxs("div", { className: "max-h-64 overflow-y-auto space-y-1 scrollbar-thin scrollbar-track-slate-100 scrollbar-thumb-slate-300", children: [
29401
+ hasChildren && isExpanded && (node.type === "category" || node.type === "percentile-category") && /* @__PURE__ */ jsx("div", { className: "mt-2 ml-3 animate-in border-l-2 border-slate-100 pl-3", children: /* @__PURE__ */ jsxs("div", { className: "max-h-64 overflow-y-auto space-y-1 scrollbar-thin scrollbar-track-slate-100 scrollbar-thumb-slate-300", children: [
28887
29402
  node.children.map((child) => renderNode(child, depth + 1)),
28888
29403
  loadingCategories.has(`${node.id}-${(categoryPages[node.id] || 0) + 1}`) && /* @__PURE__ */ jsx("div", { className: "py-2 px-3 text-center", children: /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center text-sm text-slate-500", children: [
28889
29404
  /* @__PURE__ */ jsx("div", { className: "animate-spin mr-2 h-4 w-4 border-2 border-slate-300 border-t-blue-500 rounded-full" }),
@@ -28909,11 +29424,14 @@ var FileManagerFilters = ({
28909
29424
  ] }, node.id);
28910
29425
  };
28911
29426
  return /* @__PURE__ */ jsxs("div", { className: `bg-white rounded-2xl shadow-lg border border-gray-100 h-full hover:shadow-xl transition-all duration-300 ease-out backdrop-blur-sm ${className}`, children: [
28912
- /* @__PURE__ */ jsx("div", { className: "p-4 border-b border-gray-50 bg-gradient-to-br from-slate-50/80 via-white to-blue-50/30", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
28913
- /* @__PURE__ */ jsx("div", { className: "mr-3", children: /* @__PURE__ */ jsx(Folder, { className: "h-5 w-5 text-slate-700" }) }),
28914
- /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx("h2", { className: "text-lg font-bold text-slate-900 tracking-tight", children: "Clips Explorer" }) })
29427
+ /* @__PURE__ */ jsx("div", { className: "p-4 border-b border-gray-50 bg-gradient-to-br from-slate-50/80 via-white to-blue-50/30", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
29428
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
29429
+ /* @__PURE__ */ jsx("div", { className: "mr-3", children: /* @__PURE__ */ jsx(Folder, { className: "h-5 w-5 text-slate-700" }) }),
29430
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx("h2", { className: "text-lg font-bold text-slate-900 tracking-tight", children: "Clips Explorer" }) })
29431
+ ] }),
29432
+ /* @__PURE__ */ jsx("div", { className: "hidden", children: /* @__PURE__ */ jsx(FilterDialogTrigger, {}) })
28915
29433
  ] }) }),
28916
- /* @__PURE__ */ jsx("div", { className: "px-4 py-3 border-b border-slate-100/80", children: /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
29434
+ /* @__PURE__ */ jsx("div", { className: "hidden px-4 py-3 border-b border-slate-100/80", children: /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
28917
29435
  /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none", children: /* @__PURE__ */ jsx(Search, { className: "h-5 w-5 text-slate-400 group-focus-within:text-blue-500 transition-colors duration-200" }) }),
28918
29436
  /* @__PURE__ */ jsx(
28919
29437
  "input",
@@ -28927,7 +29445,7 @@ var FileManagerFilters = ({
28927
29445
  ),
28928
29446
  searchTerm && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 pr-4 flex items-center", children: /* @__PURE__ */ jsx("div", { className: "h-2 w-2 bg-blue-500 rounded-full animate-pulse" }) })
28929
29447
  ] }) }),
28930
- /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 h-[calc(100%-14rem)] overflow-y-auto scrollbar-thin", children: [
29448
+ /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 h-[calc(100%-8rem)] overflow-y-auto scrollbar-thin", children: [
28931
29449
  /* @__PURE__ */ jsx("div", { className: "space-y-2", children: filterTree.map((node) => renderNode(node)) }),
28932
29450
  filterTree.length === 0 && searchTerm && /* @__PURE__ */ jsxs("div", { className: "text-center py-12", children: [
28933
29451
  /* @__PURE__ */ jsx("div", { className: "text-slate-300 mb-4", children: /* @__PURE__ */ jsx(Search, { className: "h-12 w-12 mx-auto" }) }),
@@ -28959,6 +29477,301 @@ var FileManagerFilters = ({
28959
29477
  ] })
28960
29478
  ] });
28961
29479
  };
29480
+ var PERCENTILE_PRESETS = [5, 10, 15, 20, 25, 30];
29481
+ var AdvancedFilterDialog = ({
29482
+ onApply
29483
+ }) => {
29484
+ const {
29485
+ state,
29486
+ updatePercentile,
29487
+ toggleClipType,
29488
+ resetFilters,
29489
+ toggleAdvancedPanel
29490
+ } = useClipFilter();
29491
+ const [customPercentile, setCustomPercentile] = useState(state.percentile.toString());
29492
+ useEffect(() => {
29493
+ setCustomPercentile(state.percentile.toString());
29494
+ }, [state.percentile]);
29495
+ const handlePercentileChange = (value) => {
29496
+ updatePercentile(value);
29497
+ setCustomPercentile(value.toString());
29498
+ };
29499
+ const handleCustomPercentileSubmit = () => {
29500
+ const value = parseInt(customPercentile);
29501
+ if (!isNaN(value) && value >= 1 && value <= 100) {
29502
+ updatePercentile(value);
29503
+ }
29504
+ };
29505
+ const handleClipTypeToggle = (clipType) => {
29506
+ toggleClipType(clipType);
29507
+ };
29508
+ const handleApply = () => {
29509
+ onApply?.();
29510
+ toggleAdvancedPanel();
29511
+ };
29512
+ const handleReset = () => {
29513
+ resetFilters();
29514
+ setCustomPercentile("10");
29515
+ };
29516
+ if (!state.isAdvancedPanelOpen) return null;
29517
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
29518
+ /* @__PURE__ */ jsx(
29519
+ "div",
29520
+ {
29521
+ className: "fixed inset-0 bg-black/30 backdrop-blur-sm z-50 transition-opacity duration-300",
29522
+ onClick: toggleAdvancedPanel
29523
+ }
29524
+ ),
29525
+ /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs(
29526
+ "div",
29527
+ {
29528
+ className: "bg-white/95 backdrop-blur-xl rounded-2xl shadow-2xl border border-white/20 w-full max-w-2xl max-h-[80vh] overflow-hidden transform transition-all duration-300 scale-100",
29529
+ onClick: (e) => e.stopPropagation(),
29530
+ children: [
29531
+ /* @__PURE__ */ jsx("div", { className: "bg-gradient-to-r from-blue-50 via-indigo-50 to-purple-50 px-6 py-4 border-b border-gray-100/80", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
29532
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3", children: [
29533
+ /* @__PURE__ */ jsx("div", { className: "p-2 bg-blue-100 rounded-xl", children: /* @__PURE__ */ jsx(Sliders, { className: "h-6 w-6 text-blue-600" }) }),
29534
+ /* @__PURE__ */ jsxs("div", { children: [
29535
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-gray-900", children: "Clip Filters" }),
29536
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600", children: "Customize your clip exploration experience" })
29537
+ ] })
29538
+ ] }),
29539
+ /* @__PURE__ */ jsx(
29540
+ "button",
29541
+ {
29542
+ onClick: toggleAdvancedPanel,
29543
+ className: "p-2 hover:bg-white/50 rounded-xl transition-colors",
29544
+ children: /* @__PURE__ */ jsx(X, { className: "h-5 w-5 text-gray-500" })
29545
+ }
29546
+ )
29547
+ ] }) }),
29548
+ /* @__PURE__ */ jsxs("div", { className: "p-6 space-y-8 overflow-y-auto max-h-[60vh]", children: [
29549
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
29550
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3", children: [
29551
+ /* @__PURE__ */ jsx("div", { className: "p-2 bg-gradient-to-r from-emerald-100 to-blue-100 rounded-lg", children: /* @__PURE__ */ jsx(Activity, { className: "h-5 w-5 text-emerald-600" }) }),
29552
+ /* @__PURE__ */ jsxs("div", { children: [
29553
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-900", children: "Performance Percentile" }),
29554
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600", children: "Filter clips by performance ranking" })
29555
+ ] })
29556
+ ] }),
29557
+ /* @__PURE__ */ jsxs("div", { className: "bg-gradient-to-r from-gray-50 to-blue-50 rounded-xl p-6 space-y-4", children: [
29558
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
29559
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
29560
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-700", children: "Percentile Range" }),
29561
+ /* @__PURE__ */ jsx("div", { className: "bg-white px-3 py-1.5 rounded-lg border border-blue-200", children: /* @__PURE__ */ jsxs("span", { className: "text-lg font-bold text-blue-600", children: [
29562
+ "Top ",
29563
+ state.percentile,
29564
+ "%"
29565
+ ] }) })
29566
+ ] }),
29567
+ /* @__PURE__ */ jsx(
29568
+ "input",
29569
+ {
29570
+ type: "range",
29571
+ min: "5",
29572
+ max: "50",
29573
+ step: "1",
29574
+ value: state.percentile,
29575
+ onChange: (e) => handlePercentileChange(parseInt(e.target.value)),
29576
+ className: "w-full h-3 bg-gradient-to-r from-green-200 via-yellow-200 to-red-200 rounded-lg appearance-none cursor-pointer",
29577
+ style: {
29578
+ background: `linear-gradient(to right, #86efac 0%, #fde047 50%, #fca5a5 100%)`
29579
+ }
29580
+ }
29581
+ ),
29582
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-xs text-gray-500", children: [
29583
+ /* @__PURE__ */ jsx("span", { children: "5% (Best)" }),
29584
+ /* @__PURE__ */ jsx("span", { children: "25% (Average)" }),
29585
+ /* @__PURE__ */ jsx("span", { children: "50% (Worst)" })
29586
+ ] })
29587
+ ] }),
29588
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
29589
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-700", children: "Quick Presets" }),
29590
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: PERCENTILE_PRESETS.map((preset) => /* @__PURE__ */ jsxs(
29591
+ "button",
29592
+ {
29593
+ onClick: () => handlePercentileChange(preset),
29594
+ className: `px-4 py-2 text-sm font-medium rounded-lg transition-all duration-200 ${state.percentile === preset ? "bg-blue-600 text-white shadow-lg shadow-blue-200 scale-105" : "bg-white text-gray-700 border border-gray-200 hover:bg-blue-50 hover:border-blue-300"}`,
29595
+ children: [
29596
+ "Top ",
29597
+ preset,
29598
+ "%"
29599
+ ]
29600
+ },
29601
+ preset
29602
+ )) })
29603
+ ] }),
29604
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3", children: [
29605
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-700", children: "Custom:" }),
29606
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
29607
+ /* @__PURE__ */ jsx(
29608
+ "input",
29609
+ {
29610
+ type: "number",
29611
+ min: "1",
29612
+ max: "100",
29613
+ value: customPercentile,
29614
+ onChange: (e) => setCustomPercentile(e.target.value),
29615
+ onKeyPress: (e) => e.key === "Enter" && handleCustomPercentileSubmit(),
29616
+ className: "w-20 px-3 py-2 text-sm border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500",
29617
+ placeholder: "10"
29618
+ }
29619
+ ),
29620
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-600", children: "%" }),
29621
+ /* @__PURE__ */ jsx(
29622
+ "button",
29623
+ {
29624
+ onClick: handleCustomPercentileSubmit,
29625
+ className: "px-3 py-2 text-sm font-medium bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors",
29626
+ children: "Apply"
29627
+ }
29628
+ )
29629
+ ] })
29630
+ ] })
29631
+ ] })
29632
+ ] }),
29633
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
29634
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3", children: [
29635
+ /* @__PURE__ */ jsx("div", { className: "p-2 bg-gradient-to-r from-purple-100 to-pink-100 rounded-lg", children: /* @__PURE__ */ jsx(Layers, { className: "h-5 w-5 text-purple-600" }) }),
29636
+ /* @__PURE__ */ jsxs("div", { children: [
29637
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-900", children: "Clip Categories" }),
29638
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600", children: "Choose which types of clips to display" })
29639
+ ] })
29640
+ ] }),
29641
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
29642
+ /* @__PURE__ */ jsxs("div", { className: "bg-gradient-to-br from-green-50 to-red-50 rounded-xl p-4 space-y-3", children: [
29643
+ /* @__PURE__ */ jsxs("h4", { className: "text-sm font-bold text-gray-700 uppercase tracking-wide flex items-center space-x-2", children: [
29644
+ /* @__PURE__ */ jsx(Sparkles, { className: "h-4 w-4 text-emerald-600" }),
29645
+ /* @__PURE__ */ jsx("span", { children: "Performance Extremes" })
29646
+ ] }),
29647
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
29648
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center space-x-3 cursor-pointer group", children: [
29649
+ /* @__PURE__ */ jsx(
29650
+ "input",
29651
+ {
29652
+ type: "checkbox",
29653
+ checked: state.showFastCycles,
29654
+ onChange: () => handleClipTypeToggle("showFastCycles"),
29655
+ className: "w-4 h-4 text-green-600 border-gray-300 rounded focus:ring-green-500"
29656
+ }
29657
+ ),
29658
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
29659
+ /* @__PURE__ */ jsx(TrendingUp, { className: "h-4 w-4 text-green-600" }),
29660
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-700 group-hover:text-green-700", children: "Fast Cycles" })
29661
+ ] })
29662
+ ] }),
29663
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center space-x-3 cursor-pointer group", children: [
29664
+ /* @__PURE__ */ jsx(
29665
+ "input",
29666
+ {
29667
+ type: "checkbox",
29668
+ checked: state.showSlowCycles,
29669
+ onChange: () => handleClipTypeToggle("showSlowCycles"),
29670
+ className: "w-4 h-4 text-red-600 border-gray-300 rounded focus:ring-red-500"
29671
+ }
29672
+ ),
29673
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
29674
+ /* @__PURE__ */ jsx(TrendingDown, { className: "h-4 w-4 text-red-600" }),
29675
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-700 group-hover:text-red-700", children: "Slow Cycles" })
29676
+ ] })
29677
+ ] }),
29678
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center space-x-3 cursor-pointer group", children: [
29679
+ /* @__PURE__ */ jsx(
29680
+ "input",
29681
+ {
29682
+ type: "checkbox",
29683
+ checked: state.showLongestIdles,
29684
+ onChange: () => handleClipTypeToggle("showLongestIdles"),
29685
+ className: "w-4 h-4 text-orange-600 border-gray-300 rounded focus:ring-orange-500"
29686
+ }
29687
+ ),
29688
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
29689
+ /* @__PURE__ */ jsx(Clock, { className: "h-4 w-4 text-orange-600" }),
29690
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-700 group-hover:text-orange-700", children: "Longest Idle Times" })
29691
+ ] })
29692
+ ] })
29693
+ ] })
29694
+ ] }),
29695
+ /* @__PURE__ */ jsxs("div", { className: "bg-gradient-to-br from-blue-50 to-indigo-50 rounded-xl p-4 space-y-3", children: [
29696
+ /* @__PURE__ */ jsxs("h4", { className: "text-sm font-bold text-gray-700 uppercase tracking-wide flex items-center space-x-2", children: [
29697
+ /* @__PURE__ */ jsx(CheckCircle2, { className: "h-4 w-4 text-blue-600" }),
29698
+ /* @__PURE__ */ jsx("span", { children: "Standard Categories" })
29699
+ ] }),
29700
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
29701
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center space-x-3 cursor-pointer group", children: [
29702
+ /* @__PURE__ */ jsx(
29703
+ "input",
29704
+ {
29705
+ type: "checkbox",
29706
+ checked: state.showCycleCompletion,
29707
+ onChange: () => handleClipTypeToggle("showCycleCompletion"),
29708
+ className: "w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
29709
+ }
29710
+ ),
29711
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
29712
+ /* @__PURE__ */ jsx(CheckCircle2, { className: "h-4 w-4 text-blue-600" }),
29713
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-700 group-hover:text-blue-700", children: "Cycle Completion" })
29714
+ ] })
29715
+ ] }),
29716
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center space-x-3 cursor-pointer group", children: [
29717
+ /* @__PURE__ */ jsx(
29718
+ "input",
29719
+ {
29720
+ type: "checkbox",
29721
+ checked: state.showIdleTime,
29722
+ onChange: () => handleClipTypeToggle("showIdleTime"),
29723
+ className: "w-4 h-4 text-purple-600 border-gray-300 rounded focus:ring-purple-500"
29724
+ }
29725
+ ),
29726
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
29727
+ /* @__PURE__ */ jsx(Clock, { className: "h-4 w-4 text-purple-600" }),
29728
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-700 group-hover:text-purple-700", children: "Idle Time" })
29729
+ ] })
29730
+ ] })
29731
+ ] })
29732
+ ] })
29733
+ ] })
29734
+ ] })
29735
+ ] }),
29736
+ /* @__PURE__ */ jsx("div", { className: "bg-gray-50/80 px-6 py-4 border-t border-gray-100/80", children: /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center", children: [
29737
+ /* @__PURE__ */ jsxs(
29738
+ "button",
29739
+ {
29740
+ onClick: handleReset,
29741
+ className: "flex items-center space-x-2 px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors",
29742
+ children: [
29743
+ /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" }),
29744
+ /* @__PURE__ */ jsx("span", { children: "Reset All Filters" })
29745
+ ]
29746
+ }
29747
+ ),
29748
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
29749
+ /* @__PURE__ */ jsx(
29750
+ "button",
29751
+ {
29752
+ onClick: toggleAdvancedPanel,
29753
+ className: "px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors",
29754
+ children: "Cancel"
29755
+ }
29756
+ ),
29757
+ /* @__PURE__ */ jsxs(
29758
+ "button",
29759
+ {
29760
+ onClick: handleApply,
29761
+ className: "flex items-center space-x-2 px-6 py-2 text-sm font-medium text-white bg-gradient-to-r from-blue-600 to-indigo-600 rounded-lg hover:from-blue-700 hover:to-indigo-700 shadow-lg shadow-blue-200 transition-all duration-200",
29762
+ children: [
29763
+ /* @__PURE__ */ jsx(Filter, { className: "h-4 w-4" }),
29764
+ /* @__PURE__ */ jsx("span", { children: "Apply Filters" })
29765
+ ]
29766
+ }
29767
+ )
29768
+ ] })
29769
+ ] }) })
29770
+ ]
29771
+ }
29772
+ ) })
29773
+ ] });
29774
+ };
28962
29775
  function useClipsRealtimeUpdates({
28963
29776
  workspaceId,
28964
29777
  date,
@@ -29366,18 +30179,46 @@ var BottlenecksContent = ({
29366
30179
  }
29367
30180
  }
29368
30181
  }, [activeFilter, allVideos, mergedCounts]);
30182
+ const isPercentileCategory = useCallback((categoryId) => {
30183
+ return ["fast-cycles", "slow-cycles", "longest-idles"].includes(categoryId);
30184
+ }, []);
30185
+ const getClipTypesForPercentileCategory = useCallback((categoryId) => {
30186
+ switch (categoryId) {
30187
+ case "fast-cycles":
30188
+ case "slow-cycles":
30189
+ return ["cycle_completion"];
30190
+ // Only cycle_completion now (best/worst/long moved to 'other')
30191
+ case "longest-idles":
30192
+ return ["idle_time"];
30193
+ default:
30194
+ return [categoryId];
30195
+ }
30196
+ }, []);
30197
+ const getCategoryCount = useCallback((categoryId) => {
30198
+ if (isPercentileCategory(categoryId)) {
30199
+ if (isPercentileCategory(activeFilter) && activeFilter === categoryId) {
30200
+ return allVideos.length;
30201
+ }
30202
+ return 0;
30203
+ }
30204
+ return mergedCounts[categoryId] || 0;
30205
+ }, [isPercentileCategory, allVideos, mergedCounts, activeFilter]);
29369
30206
  const filteredVideos = useMemo(() => {
29370
30207
  if (!allVideos) return [];
29371
30208
  let filtered = [];
29372
30209
  if (activeFilter === "all") {
29373
30210
  filtered = [...allVideos];
30211
+ } else if (isPercentileCategory(activeFilter)) {
30212
+ const allowedTypes = getClipTypesForPercentileCategory(activeFilter);
30213
+ filtered = allVideos.filter((video) => allowedTypes.includes(video.type));
30214
+ console.log(`[BottlenecksContent] Filtering percentile category ${activeFilter}: found ${filtered.length} videos of types [${allowedTypes.join(", ")}]`);
29374
30215
  } else {
29375
30216
  filtered = allVideos.filter((video) => video.type === activeFilter);
29376
30217
  }
29377
30218
  return filtered.sort((a, b) => {
29378
30219
  return new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime();
29379
30220
  });
29380
- }, [activeFilter, allVideos]);
30221
+ }, [activeFilter, allVideos, isPercentileCategory, getClipTypesForPercentileCategory]);
29381
30222
  useEffect(() => {
29382
30223
  if (isNavigating && currentIndex < filteredVideos.length) {
29383
30224
  setIsNavigating(false);
@@ -29393,21 +30234,63 @@ var BottlenecksContent = ({
29393
30234
  updateActiveFilter(categoryId);
29394
30235
  }
29395
30236
  try {
29396
- const video = await s3ClipsService.getClipById(clipId);
29397
- if (video && isMountedRef.current) {
29398
- console.log(`[BottlenecksContent] Processing loaded video by ID: ${video.id}`);
29399
- setCurrentClipId(clipId);
29400
- setAllVideos([video]);
29401
- setCurrentIndex(0);
29402
- const counts = await s3ClipsService.getClipCounts(
29403
- workspaceId,
29404
- date || getOperationalDate(),
29405
- effectiveShift
30237
+ if (isPercentileCategory(categoryId)) {
30238
+ console.log(`[BottlenecksContent] Loading percentile category: ${categoryId}`);
30239
+ const percentileType = categoryId === "fast-cycles" ? "fast-cycles" : categoryId === "slow-cycles" ? "slow-cycles" : "idle-times";
30240
+ const { createClient: createClient5 } = await import('@supabase/supabase-js');
30241
+ const supabase = createClient5(
30242
+ process.env.NEXT_PUBLIC_SUPABASE_URL || "",
30243
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || ""
29406
30244
  );
29407
- setCategoryPosition(1);
29408
- setIsNavigating(false);
29409
- console.log(`[BottlenecksContent] Successfully loaded clip by ID: ${video.id}`);
30245
+ const { data: { session } } = await supabase.auth.getSession();
30246
+ const authToken = session?.access_token;
30247
+ if (!authToken) {
30248
+ throw new Error("Authentication required");
30249
+ }
30250
+ const response = await fetch("/api/clips/supabase", {
30251
+ method: "POST",
30252
+ headers: {
30253
+ "Content-Type": "application/json",
30254
+ "Authorization": `Bearer ${authToken}`
30255
+ },
30256
+ body: JSON.stringify({
30257
+ action: "percentile-clips",
30258
+ percentileAction: percentileType,
30259
+ workspaceId,
30260
+ startDate: `${date || getOperationalDate()}T00:00:00Z`,
30261
+ endDate: `${date || getOperationalDate()}T23:59:59Z`,
30262
+ percentile: 10,
30263
+ shiftId: effectiveShift,
30264
+ limit: 100
30265
+ })
30266
+ });
30267
+ if (!response.ok) {
30268
+ const errorData = await response.json();
30269
+ throw new Error(errorData.error || `API error: ${response.status}`);
30270
+ }
30271
+ const percentileData = await response.json();
30272
+ if (percentileData.clips && percentileData.clips.length > 0 && isMountedRef.current) {
30273
+ const clickedClipIndex = percentileData.clips.findIndex((clip) => clip.id === clipId);
30274
+ if (clickedClipIndex !== -1) {
30275
+ setCurrentClipId(clipId);
30276
+ setAllVideos(percentileData.clips);
30277
+ setCurrentIndex(clickedClipIndex);
30278
+ setCategoryPosition(clickedClipIndex + 1);
30279
+ console.log(`[BottlenecksContent] Loaded ${percentileData.clips.length} ${categoryId} clips, playing #${clickedClipIndex + 1}`);
30280
+ }
30281
+ }
30282
+ } else {
30283
+ const video = await s3ClipsService.getClipById(clipId);
30284
+ if (video && isMountedRef.current) {
30285
+ console.log(`[BottlenecksContent] Processing loaded video by ID: ${video.id}`);
30286
+ setCurrentClipId(clipId);
30287
+ setAllVideos([video]);
30288
+ setCurrentIndex(0);
30289
+ setCategoryPosition(1);
30290
+ console.log(`[BottlenecksContent] Successfully loaded clip by ID: ${video.id}`);
30291
+ }
29410
30292
  }
30293
+ setIsNavigating(false);
29411
30294
  } catch (error2) {
29412
30295
  console.error(`[BottlenecksContent] Error loading clip by ID (${clipId}):`, error2);
29413
30296
  if (isMountedRef.current) {
@@ -29441,69 +30324,107 @@ var BottlenecksContent = ({
29441
30324
  }
29442
30325
  }, [workspaceId, s3ClipsService, date, effectiveShift, loadAndPlayClipById]);
29443
30326
  const handleNext = useCallback(async () => {
29444
- if (!isMountedRef.current || !currentClipId || !s3ClipsService) return;
30327
+ if (!isMountedRef.current) return;
29445
30328
  const currentFilter = activeFilterRef.current;
29446
- console.log(`[handleNext] Navigating from clip ID: ${currentClipId}`);
30329
+ console.log(`[handleNext] Navigating in category: ${currentFilter}, current index: ${currentIndex}`);
29447
30330
  setIsNavigating(true);
29448
30331
  setError(null);
29449
30332
  try {
29450
- const neighbors = await s3ClipsService.getNeighboringClips(
29451
- workspaceId,
29452
- date || getOperationalDate(),
29453
- effectiveShift,
29454
- currentFilter,
29455
- currentClipId
29456
- );
29457
- if (neighbors.next) {
29458
- console.log(`[handleNext] Found next clip: ${neighbors.next.id}`);
29459
- setCurrentClipId(neighbors.next.id || null);
29460
- setAllVideos([neighbors.next]);
29461
- setCurrentIndex(0);
29462
- setCategoryPosition(categoryPosition + 1);
29463
- setIsNavigating(false);
29464
- videoRetryCountRef.current = 0;
30333
+ if (isPercentileCategory(currentFilter)) {
30334
+ if (currentIndex < allVideos.length - 1) {
30335
+ const nextIndex = currentIndex + 1;
30336
+ const nextVideo = allVideos[nextIndex];
30337
+ console.log(`[handleNext] Moving to next percentile clip: ${nextVideo.id} (index ${nextIndex})`);
30338
+ setCurrentClipId(nextVideo.id);
30339
+ setCurrentIndex(nextIndex);
30340
+ setCategoryPosition(nextIndex + 1);
30341
+ setIsNavigating(false);
30342
+ } else {
30343
+ console.log(`[handleNext] Already at last clip in percentile category`);
30344
+ setIsNavigating(false);
30345
+ }
29465
30346
  } else {
29466
- console.log(`[handleNext] No next clip available`);
29467
- setIsNavigating(false);
30347
+ if (!currentClipId || !s3ClipsService) {
30348
+ setIsNavigating(false);
30349
+ return;
30350
+ }
30351
+ const neighbors = await s3ClipsService.getNeighboringClips(
30352
+ workspaceId,
30353
+ date || getOperationalDate(),
30354
+ effectiveShift,
30355
+ currentFilter,
30356
+ currentClipId
30357
+ );
30358
+ if (neighbors.next) {
30359
+ console.log(`[handleNext] Found next clip: ${neighbors.next.id}`);
30360
+ setCurrentClipId(neighbors.next.id || null);
30361
+ setAllVideos([neighbors.next]);
30362
+ setCurrentIndex(0);
30363
+ setCategoryPosition(categoryPosition + 1);
30364
+ setIsNavigating(false);
30365
+ videoRetryCountRef.current = 0;
30366
+ } else {
30367
+ console.log(`[handleNext] No next clip available`);
30368
+ setIsNavigating(false);
30369
+ }
29468
30370
  }
29469
30371
  } catch (error2) {
29470
- console.error(`[handleNext] Error getting next clip:`, error2);
30372
+ console.error(`[handleNext] Error navigating:`, error2);
29471
30373
  setError("Failed to navigate to next clip");
29472
30374
  setIsNavigating(false);
29473
30375
  }
29474
- }, [currentClipId, workspaceId, date, effectiveShift, s3ClipsService, categoryPosition]);
30376
+ }, [currentIndex, allVideos, currentClipId, workspaceId, date, effectiveShift, s3ClipsService, categoryPosition, isPercentileCategory]);
29475
30377
  const handlePrevious = useCallback(async () => {
29476
- if (!isMountedRef.current || !currentClipId || !s3ClipsService) return;
30378
+ if (!isMountedRef.current) return;
29477
30379
  const currentFilter = activeFilterRef.current;
29478
- console.log(`[handlePrevious] Navigating from clip ID: ${currentClipId}`);
30380
+ console.log(`[handlePrevious] Navigating in category: ${currentFilter}, current index: ${currentIndex}`);
29479
30381
  setIsNavigating(true);
29480
30382
  setError(null);
29481
30383
  try {
29482
- const neighbors = await s3ClipsService.getNeighboringClips(
29483
- workspaceId,
29484
- date || getOperationalDate(),
29485
- effectiveShift,
29486
- currentFilter,
29487
- currentClipId
29488
- );
29489
- if (neighbors.previous) {
29490
- console.log(`[handlePrevious] Found previous clip: ${neighbors.previous.id}`);
29491
- setCurrentClipId(neighbors.previous.id || null);
29492
- setAllVideos([neighbors.previous]);
29493
- setCurrentIndex(0);
29494
- setCategoryPosition(Math.max(1, categoryPosition - 1));
29495
- setIsNavigating(false);
29496
- videoRetryCountRef.current = 0;
30384
+ if (isPercentileCategory(currentFilter)) {
30385
+ if (currentIndex > 0) {
30386
+ const prevIndex = currentIndex - 1;
30387
+ const prevVideo = allVideos[prevIndex];
30388
+ console.log(`[handlePrevious] Moving to previous percentile clip: ${prevVideo.id} (index ${prevIndex})`);
30389
+ setCurrentClipId(prevVideo.id);
30390
+ setCurrentIndex(prevIndex);
30391
+ setCategoryPosition(prevIndex + 1);
30392
+ setIsNavigating(false);
30393
+ } else {
30394
+ console.log(`[handlePrevious] Already at first clip in percentile category`);
30395
+ setIsNavigating(false);
30396
+ }
29497
30397
  } else {
29498
- console.log(`[handlePrevious] No previous clip available`);
29499
- setIsNavigating(false);
30398
+ if (!currentClipId || !s3ClipsService) {
30399
+ setIsNavigating(false);
30400
+ return;
30401
+ }
30402
+ const neighbors = await s3ClipsService.getNeighboringClips(
30403
+ workspaceId,
30404
+ date || getOperationalDate(),
30405
+ effectiveShift,
30406
+ currentFilter,
30407
+ currentClipId
30408
+ );
30409
+ if (neighbors.previous) {
30410
+ console.log(`[handlePrevious] Found previous clip: ${neighbors.previous.id}`);
30411
+ setCurrentClipId(neighbors.previous.id || null);
30412
+ setAllVideos([neighbors.previous]);
30413
+ setCurrentIndex(0);
30414
+ setCategoryPosition(Math.max(1, categoryPosition - 1));
30415
+ setIsNavigating(false);
30416
+ videoRetryCountRef.current = 0;
30417
+ } else {
30418
+ console.log(`[handlePrevious] No previous clip available`);
30419
+ setIsNavigating(false);
30420
+ }
29500
30421
  }
29501
30422
  } catch (error2) {
29502
- console.error(`[handlePrevious] Error getting previous clip:`, error2);
30423
+ console.error(`[handlePrevious] Error navigating:`, error2);
29503
30424
  setError("Failed to navigate to previous clip");
29504
30425
  setIsNavigating(false);
29505
30426
  }
29506
- }, [currentClipId, workspaceId, date, effectiveShift, s3ClipsService, categoryPosition]);
30427
+ }, [currentIndex, allVideos, currentClipId, workspaceId, date, effectiveShift, s3ClipsService, categoryPosition, isPercentileCategory]);
29507
30428
  const currentVideo = useMemo(() => {
29508
30429
  if (!filteredVideos || filteredVideos.length === 0 || currentIndex >= filteredVideos.length) {
29509
30430
  return null;
@@ -29617,24 +30538,36 @@ var BottlenecksContent = ({
29617
30538
  };
29618
30539
  const getClipTypeLabel = (video) => {
29619
30540
  if (!video) return "";
30541
+ const currentFilter = activeFilterRef.current;
30542
+ if (isPercentileCategory(currentFilter)) {
30543
+ const percentileValue = video.percentile?.toFixed(1);
30544
+ switch (currentFilter) {
30545
+ case "fast-cycles":
30546
+ return `\u26A1 Fast Cycle ${percentileValue ? `(${percentileValue}%)` : ""}`;
30547
+ case "slow-cycles":
30548
+ return `\u{1F40C} Slow Cycle ${percentileValue ? `(${percentileValue}%)` : ""}`;
30549
+ case "longest-idles":
30550
+ return `\u23F0 Long Idle ${percentileValue ? `(${percentileValue}%)` : ""}`;
30551
+ default:
30552
+ return video.description || "Performance Clip";
30553
+ }
30554
+ }
29620
30555
  switch (video.type) {
29621
30556
  case "low_value":
29622
30557
  return "Idle Moment";
29623
30558
  case "missing_quality_check":
29624
30559
  return "SOP Deviation";
29625
- case "best_cycle_time":
29626
- return "Best Cycle Time";
29627
- case "worst_cycle_time":
29628
- return "Worst Cycle Time";
29629
30560
  case "cycle_completion":
29630
30561
  return "Cycle Completion";
30562
+ case "idle_time":
30563
+ return "Idle Time";
29631
30564
  case "running_cycle":
29632
30565
  return "Running Cycle";
29633
30566
  case "setup_state":
29634
30567
  return "Setup State";
29635
30568
  case "bottleneck":
29636
30569
  default:
29637
- return "";
30570
+ return video.description || "";
29638
30571
  }
29639
30572
  };
29640
30573
  if (!dashboardConfig?.s3Config) {
@@ -29690,22 +30623,22 @@ var BottlenecksContent = ({
29690
30623
  "button",
29691
30624
  {
29692
30625
  onClick: handlePrevious,
29693
- disabled: categoryPosition <= 1 || (mergedCounts[activeFilter] || 0) === 0,
29694
- className: `p-2 rounded-full transition-colors ${categoryPosition <= 1 || (mergedCounts[activeFilter] || 0) === 0 ? "text-gray-300 cursor-not-allowed" : "text-gray-600 hover:bg-gray-100"}`,
30626
+ disabled: categoryPosition <= 1 || getCategoryCount(activeFilter) === 0,
30627
+ className: `p-2 rounded-full transition-colors ${categoryPosition <= 1 || getCategoryCount(activeFilter) === 0 ? "text-gray-300 cursor-not-allowed" : "text-gray-600 hover:bg-gray-100"}`,
29695
30628
  "aria-label": "Previous video",
29696
30629
  children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-5 w-5" })
29697
30630
  }
29698
30631
  ),
29699
30632
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1", children: [
29700
- /* @__PURE__ */ jsx("span", { className: "text-sm px-2 py-1 bg-blue-50 text-blue-700 rounded-full font-medium tabular-nums", children: (mergedCounts[activeFilter] || 0) > 0 ? `${categoryPosition} / ${mergedCounts[activeFilter]}` : "0 / 0" }),
30633
+ /* @__PURE__ */ jsx("span", { className: "text-sm px-2 py-1 bg-blue-50 text-blue-700 rounded-full font-medium tabular-nums", children: getCategoryCount(activeFilter) > 0 ? `${categoryPosition} / ${getCategoryCount(activeFilter)}` : "0 / 0" }),
29701
30634
  error && /* @__PURE__ */ jsx("span", { className: "text-xs text-red-600 font-medium", children: error })
29702
30635
  ] }),
29703
30636
  /* @__PURE__ */ jsx(
29704
30637
  "button",
29705
30638
  {
29706
30639
  onClick: handleNext,
29707
- disabled: categoryPosition >= (mergedCounts[activeFilter] || 0) || (mergedCounts[activeFilter] || 0) === 0,
29708
- className: `p-2 rounded-full transition-colors ${categoryPosition >= (mergedCounts[activeFilter] || 0) || (mergedCounts[activeFilter] || 0) === 0 ? "text-gray-300 cursor-not-allowed" : "text-gray-600 hover:bg-gray-100"}`,
30640
+ disabled: categoryPosition >= getCategoryCount(activeFilter) || getCategoryCount(activeFilter) === 0,
30641
+ className: `p-2 rounded-full transition-colors ${categoryPosition >= getCategoryCount(activeFilter) || getCategoryCount(activeFilter) === 0 ? "text-gray-300 cursor-not-allowed" : "text-gray-600 hover:bg-gray-100"}`,
29709
30642
  "aria-label": "Next video",
29710
30643
  children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-5 w-5" })
29711
30644
  }
@@ -29776,9 +30709,9 @@ var BottlenecksContent = ({
29776
30709
  }
29777
30710
  )
29778
30711
  ] }) }),
29779
- (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "cycle_completion" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "low_value" ? /* @__PURE__ */ jsx("div", { className: "absolute top-3 left-3 z-10 bg-black/60 backdrop-blur-sm px-3 py-1.5 rounded-lg text-white shadow-lg text-xs", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
29780
- /* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${currentVideo.type === "low_value" ? "bg-purple-400" : currentVideo.type === "best_cycle_time" ? "bg-green-600" : currentVideo.type === "worst_cycle_time" ? "bg-red-700" : currentVideo.type === "cycle_completion" ? "bg-blue-600" : "bg-red-500"} mr-2 animate-pulse` }),
29781
- (currentVideo.type === "best_cycle_time" || currentVideo.type === "worst_cycle_time" || currentVideo.type === "cycle_completion" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds ? /* @__PURE__ */ jsxs("span", { className: "opacity-90 font-mono bg-black/30 px-2 py-0.5 rounded", children: [
30712
+ (currentVideo.type === "cycle_completion" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "idle_time" || currentVideo.type === "low_value" ? /* @__PURE__ */ jsx("div", { className: "absolute top-3 left-3 z-10 bg-black/60 backdrop-blur-sm px-3 py-1.5 rounded-lg text-white shadow-lg text-xs", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
30713
+ /* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${currentVideo.type === "low_value" || currentVideo.type === "idle_time" ? "bg-purple-400" : isPercentileCategory(activeFilterRef.current) ? activeFilterRef.current === "fast-cycles" ? "bg-green-600" : activeFilterRef.current === "slow-cycles" ? "bg-red-700" : "bg-orange-500" : currentVideo.type === "cycle_completion" ? "bg-blue-600" : "bg-gray-500"} mr-2 animate-pulse` }),
30714
+ (currentVideo.type === "cycle_completion" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds ? /* @__PURE__ */ jsxs("span", { className: "opacity-90 font-mono bg-black/30 px-2 py-0.5 rounded", children: [
29782
30715
  "Cycle time: ",
29783
30716
  currentVideo.cycle_time_seconds.toFixed(1),
29784
30717
  "s"
@@ -29908,7 +30841,15 @@ var BottlenecksContent = ({
29908
30841
  className: "h-full"
29909
30842
  }
29910
30843
  ) })
29911
- ] })
30844
+ ] }),
30845
+ /* @__PURE__ */ jsx(
30846
+ AdvancedFilterDialog,
30847
+ {
30848
+ onApply: () => {
30849
+ console.log("[BottlenecksContent] Advanced filters applied, will refresh clips...");
30850
+ }
30851
+ }
30852
+ )
29912
30853
  ] });
29913
30854
  };
29914
30855
  var getEfficiencyColor = (efficiency) => {
@@ -30011,7 +30952,7 @@ var arePropsEqual = (prevProps, nextProps) => {
30011
30952
  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 && // Position doesn't need deep equality check as it's generally static
30012
30953
  prevProps.position.id === nextProps.position.id;
30013
30954
  };
30014
- var WorkspaceGridItem = React19__default.memo(({
30955
+ var WorkspaceGridItem = React20__default.memo(({
30015
30956
  data,
30016
30957
  position,
30017
30958
  isBottleneck = false,
@@ -30104,7 +31045,7 @@ var WorkspaceGridItem = React19__default.memo(({
30104
31045
  );
30105
31046
  }, arePropsEqual);
30106
31047
  WorkspaceGridItem.displayName = "WorkspaceGridItem";
30107
- var WorkspaceGrid = React19__default.memo(({
31048
+ var WorkspaceGrid = React20__default.memo(({
30108
31049
  workspaces,
30109
31050
  isPdfMode = false,
30110
31051
  customWorkspacePositions,
@@ -30298,7 +31239,7 @@ var KPICard = ({
30298
31239
  }) => {
30299
31240
  useThemeConfig();
30300
31241
  const { formatNumber } = useFormatNumber();
30301
- const trendInfo = React19__default.useMemo(() => {
31242
+ const trendInfo = React20__default.useMemo(() => {
30302
31243
  let trendValue = trend || "neutral";
30303
31244
  if (change !== void 0 && trend === void 0) {
30304
31245
  trendValue = change > 0 ? "up" : change < 0 ? "down" : "neutral";
@@ -30321,7 +31262,7 @@ var KPICard = ({
30321
31262
  const shouldShowTrend = !(change === 0 && trend === void 0);
30322
31263
  return { trendValue, Icon: Icon2, colorClass, shouldShowTrend };
30323
31264
  }, [trend, change]);
30324
- const formattedValue = React19__default.useMemo(() => {
31265
+ const formattedValue = React20__default.useMemo(() => {
30325
31266
  if (title === "Quality Compliance" && typeof value === "number") {
30326
31267
  return value.toFixed(1);
30327
31268
  }
@@ -30335,7 +31276,7 @@ var KPICard = ({
30335
31276
  }
30336
31277
  return value;
30337
31278
  }, [value, title]);
30338
- const formattedChange = React19__default.useMemo(() => {
31279
+ const formattedChange = React20__default.useMemo(() => {
30339
31280
  if (change === void 0 || change === 0) return null;
30340
31281
  const absChange = Math.abs(change);
30341
31282
  return formatNumber(absChange, { minimumFractionDigits: 0, maximumFractionDigits: 1 });
@@ -31242,6 +32183,237 @@ var WorkspaceDisplayNameExample = () => {
31242
32183
  ] })
31243
32184
  ] });
31244
32185
  };
32186
+ var AdvancedFilterPanel = ({
32187
+ className = "",
32188
+ onApply
32189
+ }) => {
32190
+ const {
32191
+ state,
32192
+ updatePercentile,
32193
+ toggleClipType,
32194
+ updateShiftFilter,
32195
+ resetFilters,
32196
+ toggleAdvancedPanel
32197
+ } = useClipFilter();
32198
+ const [customPercentile, setCustomPercentile] = useState(state.percentile.toString());
32199
+ const handlePercentileChange = (value) => {
32200
+ updatePercentile(value);
32201
+ setCustomPercentile(value.toString());
32202
+ onApply?.();
32203
+ };
32204
+ const handleShiftChange = (shiftId) => {
32205
+ updateShiftFilter(shiftId);
32206
+ onApply?.();
32207
+ };
32208
+ const handleClipTypeToggle = (clipType) => {
32209
+ toggleClipType(clipType);
32210
+ onApply?.();
32211
+ };
32212
+ const handleReset = () => {
32213
+ resetFilters();
32214
+ setCustomPercentile("10");
32215
+ onApply?.();
32216
+ };
32217
+ return /* @__PURE__ */ jsxs("div", { className: `bg-white rounded-xl shadow-lg border border-gray-100 ${className}`, children: [
32218
+ /* @__PURE__ */ jsx(
32219
+ "div",
32220
+ {
32221
+ className: "p-4 border-b border-gray-100 bg-gradient-to-r from-blue-50 to-indigo-50 cursor-pointer rounded-t-xl",
32222
+ onClick: toggleAdvancedPanel,
32223
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
32224
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3", children: [
32225
+ /* @__PURE__ */ jsx(Sliders, { className: "h-5 w-5 text-blue-600" }),
32226
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-900", children: "Advanced Filters" })
32227
+ ] }),
32228
+ /* @__PURE__ */ jsx("button", { className: "p-1 hover:bg-white/50 rounded-lg transition-colors", children: state.isAdvancedPanelOpen ? /* @__PURE__ */ jsx(ChevronUp, { className: "h-5 w-5 text-gray-600" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "h-5 w-5 text-gray-600" }) })
32229
+ ] })
32230
+ }
32231
+ ),
32232
+ state.isAdvancedPanelOpen && /* @__PURE__ */ jsxs("div", { className: "p-4 space-y-3", children: [
32233
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
32234
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3", children: [
32235
+ /* @__PURE__ */ jsx(Activity, { className: "h-4 w-4 text-blue-600" }),
32236
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-gray-700", children: "Percentile:" }),
32237
+ /* @__PURE__ */ jsx(
32238
+ "input",
32239
+ {
32240
+ type: "range",
32241
+ min: "5",
32242
+ max: "30",
32243
+ step: "5",
32244
+ value: state.percentile,
32245
+ onChange: (e) => handlePercentileChange(parseInt(e.target.value)),
32246
+ className: "w-24 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"
32247
+ }
32248
+ ),
32249
+ /* @__PURE__ */ jsxs("span", { className: "text-sm font-semibold text-blue-600 min-w-[50px]", children: [
32250
+ state.percentile,
32251
+ "%"
32252
+ ] })
32253
+ ] }),
32254
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1", children: [5, 10, 15, 20].map((preset) => /* @__PURE__ */ jsxs(
32255
+ "button",
32256
+ {
32257
+ onClick: () => handlePercentileChange(preset),
32258
+ className: `px-2 py-1 text-xs font-medium rounded transition-colors ${state.percentile === preset ? "bg-blue-600 text-white" : "bg-gray-100 text-gray-600 hover:bg-gray-200"}`,
32259
+ children: [
32260
+ preset,
32261
+ "%"
32262
+ ]
32263
+ },
32264
+ preset
32265
+ )) })
32266
+ ] }),
32267
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
32268
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3", children: [
32269
+ /* @__PURE__ */ jsx(Layers, { className: "h-4 w-4 text-purple-600" }),
32270
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-gray-700", children: "Types:" }),
32271
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
32272
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center space-x-1 cursor-pointer", children: [
32273
+ /* @__PURE__ */ jsx(
32274
+ "input",
32275
+ {
32276
+ type: "checkbox",
32277
+ checked: state.showFastCycles,
32278
+ onChange: () => handleClipTypeToggle("showFastCycles"),
32279
+ className: "w-3 h-3 text-blue-600 border-gray-300 rounded"
32280
+ }
32281
+ ),
32282
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-700", children: "Fast" })
32283
+ ] }),
32284
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center space-x-1 cursor-pointer", children: [
32285
+ /* @__PURE__ */ jsx(
32286
+ "input",
32287
+ {
32288
+ type: "checkbox",
32289
+ checked: state.showSlowCycles,
32290
+ onChange: () => handleClipTypeToggle("showSlowCycles"),
32291
+ className: "w-3 h-3 text-blue-600 border-gray-300 rounded"
32292
+ }
32293
+ ),
32294
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-700", children: "Slow" })
32295
+ ] }),
32296
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center space-x-1 cursor-pointer", children: [
32297
+ /* @__PURE__ */ jsx(
32298
+ "input",
32299
+ {
32300
+ type: "checkbox",
32301
+ checked: state.showLongestIdles,
32302
+ onChange: () => handleClipTypeToggle("showLongestIdles"),
32303
+ className: "w-3 h-3 text-blue-600 border-gray-300 rounded"
32304
+ }
32305
+ ),
32306
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-700", children: "LongIdle" })
32307
+ ] }),
32308
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center space-x-1 cursor-pointer", children: [
32309
+ /* @__PURE__ */ jsx(
32310
+ "input",
32311
+ {
32312
+ type: "checkbox",
32313
+ checked: state.showCycleCompletion,
32314
+ onChange: () => handleClipTypeToggle("showCycleCompletion"),
32315
+ className: "w-3 h-3 text-blue-600 border-gray-300 rounded"
32316
+ }
32317
+ ),
32318
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-700", children: "Completion" })
32319
+ ] }),
32320
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center space-x-1 cursor-pointer", children: [
32321
+ /* @__PURE__ */ jsx(
32322
+ "input",
32323
+ {
32324
+ type: "checkbox",
32325
+ checked: state.showIdleTime,
32326
+ onChange: () => handleClipTypeToggle("showIdleTime"),
32327
+ className: "w-3 h-3 text-blue-600 border-gray-300 rounded"
32328
+ }
32329
+ ),
32330
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-700", children: "Idle" })
32331
+ ] })
32332
+ ] })
32333
+ ] }),
32334
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
32335
+ /* @__PURE__ */ jsx(Calendar, { className: "h-4 w-4 text-indigo-600" }),
32336
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-gray-700", children: "Shift:" }),
32337
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1", children: [
32338
+ /* @__PURE__ */ jsx(
32339
+ "button",
32340
+ {
32341
+ onClick: () => handleShiftChange(void 0),
32342
+ className: `px-2 py-1 text-xs font-medium rounded transition-colors ${state.shiftFilter === void 0 ? "bg-indigo-600 text-white" : "bg-gray-100 text-gray-700 hover:bg-gray-200"}`,
32343
+ children: "All"
32344
+ }
32345
+ ),
32346
+ /* @__PURE__ */ jsx(
32347
+ "button",
32348
+ {
32349
+ onClick: () => handleShiftChange(0),
32350
+ className: `px-2 py-1 text-xs font-medium rounded transition-colors ${state.shiftFilter === 0 ? "bg-indigo-600 text-white" : "bg-gray-100 text-gray-700 hover:bg-gray-200"}`,
32351
+ children: "Day"
32352
+ }
32353
+ ),
32354
+ /* @__PURE__ */ jsx(
32355
+ "button",
32356
+ {
32357
+ onClick: () => handleShiftChange(1),
32358
+ className: `px-2 py-1 text-xs font-medium rounded transition-colors ${state.shiftFilter === 1 ? "bg-indigo-600 text-white" : "bg-gray-100 text-gray-700 hover:bg-gray-200"}`,
32359
+ children: "Night"
32360
+ }
32361
+ )
32362
+ ] })
32363
+ ] })
32364
+ ] }),
32365
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between pt-2 border-t border-gray-100", children: [
32366
+ /* @__PURE__ */ jsxs(
32367
+ "button",
32368
+ {
32369
+ onClick: handleReset,
32370
+ className: "flex items-center space-x-1 px-3 py-1.5 text-xs font-medium text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors",
32371
+ children: [
32372
+ /* @__PURE__ */ jsx(RefreshCw, { className: "h-3 w-3" }),
32373
+ /* @__PURE__ */ jsx("span", { children: "Reset" })
32374
+ ]
32375
+ }
32376
+ ),
32377
+ /* @__PURE__ */ jsxs(
32378
+ "button",
32379
+ {
32380
+ onClick: () => {
32381
+ onApply?.();
32382
+ toggleAdvancedPanel();
32383
+ },
32384
+ className: "flex items-center space-x-1 px-3 py-1.5 text-xs font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 transition-colors",
32385
+ children: [
32386
+ /* @__PURE__ */ jsx(Filter, { className: "h-3 w-3" }),
32387
+ /* @__PURE__ */ jsx("span", { children: "Apply & Close" })
32388
+ ]
32389
+ }
32390
+ )
32391
+ ] })
32392
+ ] }),
32393
+ !state.isAdvancedPanelOpen && /* @__PURE__ */ jsx("div", { className: "px-4 py-3", children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-4 text-sm", children: [
32394
+ /* @__PURE__ */ jsxs("span", { className: "text-gray-600", children: [
32395
+ "Percentile: ",
32396
+ /* @__PURE__ */ jsxs("span", { className: "font-semibold text-blue-600", children: [
32397
+ state.percentile,
32398
+ "%"
32399
+ ] })
32400
+ ] }),
32401
+ /* @__PURE__ */ jsxs("span", { className: "text-gray-600", children: [
32402
+ "Shift: ",
32403
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-indigo-600", children: state.shiftFilter === void 0 ? "All" : state.shiftFilter === 0 ? "Day" : "Night" })
32404
+ ] }),
32405
+ /* @__PURE__ */ jsxs("span", { className: "text-gray-600", children: [
32406
+ "Categories: ",
32407
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-purple-600", children: [
32408
+ state.showFastCycles && "Fast",
32409
+ state.showSlowCycles && "Slow",
32410
+ state.showLongestIdles && "Idle",
32411
+ state.showCycleCompletion && "Completion"
32412
+ ].filter(Boolean).join(", ") || "None" })
32413
+ ] })
32414
+ ] }) }) })
32415
+ ] });
32416
+ };
31245
32417
  var HamburgerButton = ({
31246
32418
  onClick,
31247
32419
  className = "",
@@ -31274,7 +32446,7 @@ var Breadcrumbs = ({ items }) => {
31274
32446
  }
31275
32447
  }
31276
32448
  };
31277
- 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(React19__default.Fragment, { children: [
32449
+ 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(React20__default.Fragment, { children: [
31278
32450
  index > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "h-3 w-3 text-gray-400 dark:text-gray-500" }),
31279
32451
  /* @__PURE__ */ jsxs(
31280
32452
  "span",
@@ -33731,7 +34903,7 @@ var ThreadSidebar = ({
33731
34903
  ] });
33732
34904
  };
33733
34905
  var axelProfilePng = "/axel-profile.png";
33734
- var ProfilePicture = React19__default.memo(({ alt = "Axel", className = "w-8 h-8 sm:w-10 sm:h-10 md:w-12 md:h-12" }) => {
34906
+ var ProfilePicture = React20__default.memo(({ alt = "Axel", className = "w-8 h-8 sm:w-10 sm:h-10 md:w-12 md:h-12" }) => {
33735
34907
  return /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx("div", { className: `${className} rounded-xl overflow-hidden shadow-sm`, children: /* @__PURE__ */ jsx(
33736
34908
  "img",
33737
34909
  {
@@ -34622,7 +35794,7 @@ var AIAgentView = () => {
34622
35794
  barRadius: [4, 4, 0, 0]
34623
35795
  // Top corners rounded
34624
35796
  };
34625
- const CustomTooltip = ({ active, payload, label }) => {
35797
+ const CustomTooltip2 = ({ active, payload, label }) => {
34626
35798
  if (active && payload && payload.length) {
34627
35799
  return /* @__PURE__ */ jsxs("div", { className: "bg-white px-4 py-3 shadow-lg rounded-lg border border-gray-200", children: [
34628
35800
  /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-900 mb-1", children: label }),
@@ -34722,7 +35894,7 @@ var AIAgentView = () => {
34722
35894
  tickFormatter: (value) => formatNumber(value)
34723
35895
  }
34724
35896
  ),
34725
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
35897
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip2, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
34726
35898
  /* @__PURE__ */ jsx(
34727
35899
  Bar,
34728
35900
  {
@@ -34766,7 +35938,7 @@ var AIAgentView = () => {
34766
35938
  tickFormatter: (value) => formatNumber(value)
34767
35939
  }
34768
35940
  ),
34769
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip, {}), cursor: { strokeDasharray: "3 3" } }),
35941
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip2, {}), cursor: { strokeDasharray: "3 3" } }),
34770
35942
  /* @__PURE__ */ jsx(
34771
35943
  Line,
34772
35944
  {
@@ -34886,7 +36058,7 @@ var AIAgentView = () => {
34886
36058
  tickFormatter: (value) => formatNumber(value)
34887
36059
  }
34888
36060
  ),
34889
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip, {}), cursor: { strokeDasharray: "3 3" } }),
36061
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip2, {}), cursor: { strokeDasharray: "3 3" } }),
34890
36062
  /* @__PURE__ */ jsx(
34891
36063
  Legend,
34892
36064
  {
@@ -34946,7 +36118,7 @@ var AIAgentView = () => {
34946
36118
  tickFormatter: (value) => formatNumber(value)
34947
36119
  }
34948
36120
  ),
34949
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
36121
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip2, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
34950
36122
  /* @__PURE__ */ jsx(
34951
36123
  Legend,
34952
36124
  {
@@ -35110,7 +36282,7 @@ var AIAgentView = () => {
35110
36282
  Tooltip,
35111
36283
  {
35112
36284
  cursor: { strokeDasharray: "3 3" },
35113
- content: /* @__PURE__ */ jsx(CustomTooltip, {})
36285
+ content: /* @__PURE__ */ jsx(CustomTooltip2, {})
35114
36286
  }
35115
36287
  ),
35116
36288
  /* @__PURE__ */ jsx(
@@ -35180,7 +36352,7 @@ var AIAgentView = () => {
35180
36352
  tickFormatter: (value) => formatNumber(value)
35181
36353
  }
35182
36354
  ),
35183
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
36355
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip2, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
35184
36356
  /* @__PURE__ */ jsx(
35185
36357
  Legend,
35186
36358
  {
@@ -35254,7 +36426,7 @@ var AIAgentView = () => {
35254
36426
  tickFormatter: (value) => formatNumber(value)
35255
36427
  }
35256
36428
  ),
35257
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip, {}), cursor: { strokeDasharray: "3 3" } }),
36429
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip2, {}), cursor: { strokeDasharray: "3 3" } }),
35258
36430
  /* @__PURE__ */ jsx(
35259
36431
  Legend,
35260
36432
  {
@@ -36440,7 +37612,7 @@ function HomeView({
36440
37612
  animate: { opacity: 1, scale: 1 },
36441
37613
  transition: { duration: 0.3 },
36442
37614
  className: "h-full",
36443
- children: React19__default.createElement(WorkspaceGrid, {
37615
+ children: React20__default.createElement(WorkspaceGrid, {
36444
37616
  workspaces: memoizedWorkspaceMetrics,
36445
37617
  lineNames,
36446
37618
  factoryView: factoryViewId,
@@ -36466,7 +37638,7 @@ function HomeView({
36466
37638
  animate: { opacity: 1, scale: 1 },
36467
37639
  transition: { duration: 0.3 },
36468
37640
  className: "h-full",
36469
- children: React19__default.createElement(WorkspaceGrid, {
37641
+ children: React20__default.createElement(WorkspaceGrid, {
36470
37642
  workspaces: [],
36471
37643
  // Show empty grid while loading
36472
37644
  lineNames,
@@ -36493,7 +37665,7 @@ function HomeView({
36493
37665
  }
36494
37666
  );
36495
37667
  }
36496
- var AuthenticatedHomeView = withAuth(React19__default.memo(HomeView));
37668
+ var AuthenticatedHomeView = withAuth(React20__default.memo(HomeView));
36497
37669
  var HomeView_default = HomeView;
36498
37670
  function withWorkspaceDisplayNames(Component3, options = {}) {
36499
37671
  const {
@@ -37611,7 +38783,7 @@ var KPIDetailViewWithDisplayNames = withSelectedLineDisplayNames(KPIDetailView);
37611
38783
  var KPIDetailView_default = KPIDetailViewWithDisplayNames;
37612
38784
  var LineCard = ({ line, onClick, supervisorEnabled = false }) => {
37613
38785
  const { kpis, isLoading, error } = useLineKPIs({ lineId: line.id });
37614
- const isOnTrack = React19__default.useMemo(() => {
38786
+ const isOnTrack = React20__default.useMemo(() => {
37615
38787
  if (!kpis) return null;
37616
38788
  return kpis.efficiency.value > 90;
37617
38789
  }, [kpis]);
@@ -39414,7 +40586,7 @@ var ShiftsView = ({
39414
40586
  ] })
39415
40587
  ] });
39416
40588
  };
39417
- var AuthenticatedShiftsView = withAuth(React19__default.memo(ShiftsView));
40589
+ var AuthenticatedShiftsView = withAuth(React20__default.memo(ShiftsView));
39418
40590
  var ShiftsView_default = ShiftsView;
39419
40591
 
39420
40592
  // src/lib/constants/actions.ts
@@ -41330,7 +42502,7 @@ var TargetsView = ({
41330
42502
  };
41331
42503
  var TargetsViewWithDisplayNames = withAllWorkspaceDisplayNames(TargetsView);
41332
42504
  var TargetsView_default = TargetsViewWithDisplayNames;
41333
- var AuthenticatedTargetsView = withAuth(React19__default.memo(TargetsViewWithDisplayNames));
42505
+ var AuthenticatedTargetsView = withAuth(React20__default.memo(TargetsViewWithDisplayNames));
41334
42506
 
41335
42507
  // src/views/workspace-detail-view.utils.ts
41336
42508
  var formatISTDate2 = (date = /* @__PURE__ */ new Date(), options) => {
@@ -42219,7 +43391,7 @@ var WorkspaceDetailView = ({
42219
43391
  }
42220
43392
  )
42221
43393
  ] }),
42222
- activeTab === "bottlenecks" && /* @__PURE__ */ jsx(
43394
+ activeTab === "bottlenecks" && /* @__PURE__ */ jsx(ClipFilterProvider, { children: /* @__PURE__ */ jsx(
42223
43395
  BottlenecksContent,
42224
43396
  {
42225
43397
  workspaceId,
@@ -42228,7 +43400,7 @@ var WorkspaceDetailView = ({
42228
43400
  shift,
42229
43401
  className: "h-[calc(100vh-10rem)]"
42230
43402
  }
42231
- )
43403
+ ) })
42232
43404
  ] })
42233
43405
  ] }),
42234
43406
  /* @__PURE__ */ jsx(
@@ -43304,4 +44476,4 @@ var streamProxyConfig = {
43304
44476
  }
43305
44477
  };
43306
44478
 
43307
- export { ACTION_NAMES, AIAgentView_default as AIAgentView, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedWorkspaceHealthView, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, CompactWorkspaceHealthCard, CongratulationsOverlay, 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_SHIFT_CONFIG, 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, EmptyStateMessage, EncouragementOverlay, FactoryView_default as FactoryView, FirstTimeLoginDebug, FirstTimeLoginHandler, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, InlineEditableText, InteractiveOnboardingTour, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend6 as Legend, 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, MainLayout, MetricCard_default as MetricCard, MinimalOnboardingPopup, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TimeDisplay_default as TimeDisplay, TimePickerDropdown, UserService, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createLinesService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserService, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isLegacyConfiguration, isPrefetchError, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, optifyeAgentClient, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useAccessControl, useActiveBreaks, useAllWorkspaceMetrics, useAnalyticsConfig, useAudioService, useAuth, useAuthConfig, useCanSaveTargets, useClipTypes, useClipTypesWithCounts, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useTicketHistory, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealth, useWorkspaceHealthById, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, userService, videoPrefetchManager, videoPreloader, whatsappService, withAccessControl, withAuth, withRegistry, workspaceHealthService, workspaceService };
44479
+ export { ACTION_NAMES, AIAgentView_default as AIAgentView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedWorkspaceHealthView, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ClipFilterProvider, CompactWorkspaceHealthCard, CongratulationsOverlay, 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_SHIFT_CONFIG, 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, EmptyStateMessage, EncouragementOverlay, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, InlineEditableText, InteractiveOnboardingTour, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend6 as Legend, 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, MainLayout, MetricCard_default as MetricCard, MinimalOnboardingPopup, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TimeDisplay_default as TimeDisplay, TimePickerDropdown, UserService, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createLinesService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserService, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isLegacyConfiguration, isPrefetchError, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, optifyeAgentClient, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useAccessControl, useActiveBreaks, useAllWorkspaceMetrics, useAnalyticsConfig, useAudioService, useAuth, useAuthConfig, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useTicketHistory, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealth, useWorkspaceHealthById, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, userService, videoPrefetchManager, videoPreloader, whatsappService, withAccessControl, withAuth, withRegistry, workspaceHealthService, workspaceService };