@optifye/dashboard-core 6.3.5 → 6.4.0

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
@@ -14,9 +14,9 @@ import { noop, warning, invariant, progress, secondsToMilliseconds, milliseconds
14
14
  import { getValueTransition, hover, press, isPrimaryPointer, GroupPlaybackControls, setDragLock, supportsLinearEasing, attachTimeline, isGenerator, calcGeneratorDuration, isWaapiSupportedEasing, mapEasingToNativeEasing, maxGeneratorDuration, generateLinearEasing, isBezierDefinition } from 'motion-dom';
15
15
  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';
16
16
  import { Slot } from '@radix-ui/react-slot';
17
- import { Camera, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, X, Coffee, Plus, Clock, Minus, ArrowDown, ArrowUp, Search, CheckCircle, AlertTriangle, Info, Share2, Trophy, Target, Download, User, XCircle, ChevronLeft, ChevronRight, AlertCircle, Sun, Moon, MessageSquare, Trash2, ArrowLeft, RefreshCw, Menu, Send, Copy, Edit2, UserCheck, Save, LogOut, Calendar, Package, Settings, LifeBuoy, EyeOff, Eye, Zap, UserCircle, ArrowLeftIcon as ArrowLeftIcon$1, Settings2, CheckCircle2 } from 'lucide-react';
17
+ import { Camera, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, X, Coffee, Plus, Clock, ArrowLeft, Calendar, Save, Minus, ArrowDown, ArrowUp, ArrowLeftIcon, Settings2, CheckCircle2, Search, CheckCircle, AlertTriangle, Info, Share2, Trophy, Target, Download, User, XCircle, ChevronLeft, ChevronRight, AlertCircle, Sun, Moon, MessageSquare, Trash2, RefreshCw, Menu, Send, Copy, Edit2, UserCheck, LogOut, Package, Settings, LifeBuoy, EyeOff, Eye, Zap, UserCircle } from 'lucide-react';
18
18
  import { DayPicker, useNavigation as useNavigation$1 } from 'react-day-picker';
19
- import { XMarkIcon, ArrowRightIcon, HomeIcon, TrophyIcon, ChartBarIcon, AdjustmentsHorizontalIcon, ClockIcon, CubeIcon, SparklesIcon, QuestionMarkCircleIcon, UserCircleIcon, ExclamationCircleIcon, EnvelopeIcon, DocumentTextIcon, Bars3Icon, ArrowLeftIcon, CheckCircleIcon, ChatBubbleLeftRightIcon, XCircleIcon, InformationCircleIcon, ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/24/outline';
19
+ import { XMarkIcon, ArrowRightIcon, HomeIcon, TrophyIcon, ChartBarIcon, AdjustmentsHorizontalIcon, ClockIcon, CubeIcon, SparklesIcon, QuestionMarkCircleIcon, UserCircleIcon, ExclamationCircleIcon, EnvelopeIcon, DocumentTextIcon, Bars3Icon, ArrowLeftIcon as ArrowLeftIcon$1, CheckCircleIcon, ChatBubbleLeftRightIcon, XCircleIcon, InformationCircleIcon, ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/24/outline';
20
20
  import html2canvas from 'html2canvas';
21
21
  import jsPDF, { jsPDF as jsPDF$1 } from 'jspdf';
22
22
  import * as SelectPrimitive from '@radix-ui/react-select';
@@ -3779,6 +3779,11 @@ var S3ClipsService = class {
3779
3779
  this.requestCache = new RequestDeduplicationCache();
3780
3780
  // Flag to prevent metadata fetching during index building
3781
3781
  this.isIndexBuilding = false;
3782
+ // Flag to prevent metadata fetching during entire prefetch operation
3783
+ this.isPrefetching = false;
3784
+ // Global safeguard: limit concurrent metadata fetches to prevent flooding
3785
+ this.currentMetadataFetches = 0;
3786
+ this.MAX_CONCURRENT_METADATA = 3;
3782
3787
  this.config = config;
3783
3788
  if (!config.s3Config) {
3784
3789
  throw new Error("S3 configuration is required");
@@ -3926,20 +3931,36 @@ var S3ClipsService = class {
3926
3931
  return null;
3927
3932
  }
3928
3933
  }
3934
+ /**
3935
+ * Control prefetch mode to prevent metadata fetching during background operations
3936
+ */
3937
+ setPrefetchMode(enabled) {
3938
+ this.isPrefetching = enabled;
3939
+ console.log(`[S3ClipsService] Prefetch mode ${enabled ? "enabled" : "disabled"} - metadata fetching ${enabled ? "blocked" : "allowed"}`);
3940
+ }
3929
3941
  /**
3930
3942
  * Fetches full metadata including timestamps with deduplication
3931
3943
  */
3932
3944
  async getFullMetadata(playlistUri) {
3933
- if (this.isIndexBuilding) {
3934
- console.warn(`[S3ClipsService] Skipping metadata fetch during index building for: ${playlistUri}`);
3945
+ if (this.isIndexBuilding || this.isPrefetching) {
3946
+ console.warn(`[S3ClipsService] Skipping metadata fetch - building: ${this.isIndexBuilding}, prefetching: ${this.isPrefetching}`);
3935
3947
  return null;
3936
3948
  }
3937
- const deduplicationKey = `full-metadata:${playlistUri}`;
3938
- return this.requestCache.deduplicate(
3939
- deduplicationKey,
3940
- () => this.executeGetFullMetadata(playlistUri),
3941
- "FullMetadata"
3942
- );
3949
+ if (this.currentMetadataFetches >= this.MAX_CONCURRENT_METADATA) {
3950
+ console.warn(`[S3ClipsService] Skipping metadata - max concurrent fetches (${this.MAX_CONCURRENT_METADATA}) reached`);
3951
+ return null;
3952
+ }
3953
+ this.currentMetadataFetches++;
3954
+ try {
3955
+ const deduplicationKey = `full-metadata:${playlistUri}`;
3956
+ return await this.requestCache.deduplicate(
3957
+ deduplicationKey,
3958
+ () => this.executeGetFullMetadata(playlistUri),
3959
+ "FullMetadata"
3960
+ );
3961
+ } finally {
3962
+ this.currentMetadataFetches--;
3963
+ }
3943
3964
  }
3944
3965
  /**
3945
3966
  * Internal implementation of full metadata fetching
@@ -4441,7 +4462,8 @@ var S3ClipsService = class {
4441
4462
  date,
4442
4463
  shiftId.toString(),
4443
4464
  includeCycleTime || false,
4444
- includeMetadata || (!!timestampStart || !!timestampEnd)
4465
+ includeMetadata || false
4466
+ // Never fetch metadata for timestamp filtering to prevent flooding
4445
4467
  );
4446
4468
  });
4447
4469
  const videoResults = await Promise.all(videoPromises);
@@ -4512,6 +4534,7 @@ var VideoPrefetchManager = class extends EventEmitter {
4512
4534
  }
4513
4535
  /**
4514
4536
  * Get or create S3 service instance for dashboard config
4537
+ * Public method to allow sharing the same S3Service instance across components
4515
4538
  */
4516
4539
  getS3Service(dashboardConfig) {
4517
4540
  const configKey = JSON.stringify(dashboardConfig.s3Config);
@@ -4581,75 +4604,80 @@ var VideoPrefetchManager = class extends EventEmitter {
4581
4604
  * Perform the actual prefetch work
4582
4605
  */
4583
4606
  async performPrefetchWork(key, params, s3Service, buildIndex) {
4584
- const cacheKey = `clip-counts:${params.workspaceId}:${params.date}:${params.shift}`;
4585
- const cachedResult = await smartVideoCache.getClipCounts(cacheKey);
4586
- if (cachedResult) {
4587
- console.log(`[VideoPrefetchManager] Found cached data for ${key}`);
4588
- this.updateRequestStatus(key, "fully_indexed" /* FULLY_INDEXED */, cachedResult);
4589
- return cachedResult;
4590
- }
4591
- if (buildIndex) {
4592
- const countsOnly = await s3Service.getClipCounts(
4607
+ s3Service.setPrefetchMode(true);
4608
+ try {
4609
+ const cacheKey = `clip-counts:${params.workspaceId}:${params.date}:${params.shift}`;
4610
+ const cachedResult = await smartVideoCache.getClipCounts(cacheKey);
4611
+ if (cachedResult) {
4612
+ console.log(`[VideoPrefetchManager] Found cached data for ${key}`);
4613
+ this.updateRequestStatus(key, "fully_indexed" /* FULLY_INDEXED */, cachedResult);
4614
+ return cachedResult;
4615
+ }
4616
+ if (buildIndex) {
4617
+ const countsOnly = await s3Service.getClipCounts(
4618
+ params.workspaceId,
4619
+ params.date,
4620
+ params.shift
4621
+ );
4622
+ if (typeof countsOnly === "object" && countsOnly !== null) {
4623
+ const renderReadyData = {
4624
+ counts: countsOnly,
4625
+ videoIndex: {
4626
+ byCategory: /* @__PURE__ */ new Map(),
4627
+ allVideos: [],
4628
+ counts: countsOnly,
4629
+ workspaceId: params.workspaceId,
4630
+ date: params.date,
4631
+ shiftId: params.shift,
4632
+ lastUpdated: /* @__PURE__ */ new Date(),
4633
+ _debugId: `vid_RENDER_READY_${Date.now()}_${Math.random().toString(36).substring(7)}`
4634
+ }
4635
+ };
4636
+ this.updateRequestStatus(key, "render_ready" /* RENDER_READY */, renderReadyData);
4637
+ console.log(`[VideoPrefetchManager] Render ready, building full index for ${key}`);
4638
+ }
4639
+ }
4640
+ const fullResult = await s3Service.getClipCountsCacheFirst(
4593
4641
  params.workspaceId,
4594
4642
  params.date,
4595
- params.shift
4643
+ params.shift,
4644
+ true
4596
4645
  );
4597
- if (typeof countsOnly === "object" && countsOnly !== null) {
4598
- const renderReadyData = {
4599
- counts: countsOnly,
4646
+ if (fullResult && typeof fullResult === "object" && "videoIndex" in fullResult) {
4647
+ const clipCountsWithIndex = fullResult;
4648
+ if (clipCountsWithIndex.videoIndex.allVideos.length > 0) {
4649
+ console.log(`[VideoPrefetchManager] Video index properly populated with ${clipCountsWithIndex.videoIndex.allVideos.length} videos`);
4650
+ } else {
4651
+ console.warn(`[VideoPrefetchManager] Video index is empty, but counts available:`, clipCountsWithIndex.counts);
4652
+ }
4653
+ await smartVideoCache.setClipCounts(cacheKey, clipCountsWithIndex, 5 * 60);
4654
+ this.updateRequestStatus(key, "fully_indexed" /* FULLY_INDEXED */, clipCountsWithIndex);
4655
+ console.log(`[VideoPrefetchManager] Fully indexed: ${key} (${clipCountsWithIndex.videoIndex.allVideos.length} videos)`);
4656
+ return clipCountsWithIndex;
4657
+ } else if (fullResult && typeof fullResult === "object") {
4658
+ console.log(`[VideoPrefetchManager] Received counts only, building fallback data structure`);
4659
+ const countsResult = fullResult;
4660
+ const fallbackData = {
4661
+ counts: countsResult,
4600
4662
  videoIndex: {
4601
4663
  byCategory: /* @__PURE__ */ new Map(),
4602
4664
  allVideos: [],
4603
- counts: countsOnly,
4665
+ counts: countsResult,
4604
4666
  workspaceId: params.workspaceId,
4605
4667
  date: params.date,
4606
4668
  shiftId: params.shift,
4607
4669
  lastUpdated: /* @__PURE__ */ new Date(),
4608
- _debugId: `vid_RENDER_READY_${Date.now()}_${Math.random().toString(36).substring(7)}`
4670
+ _debugId: `vid_FALLBACK_${Date.now()}_${Math.random().toString(36).substring(7)}`
4609
4671
  }
4610
4672
  };
4611
- this.updateRequestStatus(key, "render_ready" /* RENDER_READY */, renderReadyData);
4612
- console.log(`[VideoPrefetchManager] Render ready, building full index for ${key}`);
4613
- }
4614
- }
4615
- const fullResult = await s3Service.getClipCountsCacheFirst(
4616
- params.workspaceId,
4617
- params.date,
4618
- params.shift,
4619
- true
4620
- );
4621
- if (fullResult && typeof fullResult === "object" && "videoIndex" in fullResult) {
4622
- const clipCountsWithIndex = fullResult;
4623
- if (clipCountsWithIndex.videoIndex.allVideos.length > 0) {
4624
- console.log(`[VideoPrefetchManager] Video index properly populated with ${clipCountsWithIndex.videoIndex.allVideos.length} videos`);
4673
+ this.updateRequestStatus(key, "render_ready" /* RENDER_READY */, fallbackData);
4674
+ return fallbackData;
4625
4675
  } else {
4626
- console.warn(`[VideoPrefetchManager] Video index is empty, but counts available:`, clipCountsWithIndex.counts);
4627
- }
4628
- await smartVideoCache.setClipCounts(cacheKey, clipCountsWithIndex, 5 * 60);
4629
- this.updateRequestStatus(key, "fully_indexed" /* FULLY_INDEXED */, clipCountsWithIndex);
4630
- console.log(`[VideoPrefetchManager] Fully indexed: ${key} (${clipCountsWithIndex.videoIndex.allVideos.length} videos)`);
4631
- return clipCountsWithIndex;
4632
- } else if (fullResult && typeof fullResult === "object") {
4633
- console.log(`[VideoPrefetchManager] Received counts only, building fallback data structure`);
4634
- const countsResult = fullResult;
4635
- const fallbackData = {
4636
- counts: countsResult,
4637
- videoIndex: {
4638
- byCategory: /* @__PURE__ */ new Map(),
4639
- allVideos: [],
4640
- counts: countsResult,
4641
- workspaceId: params.workspaceId,
4642
- date: params.date,
4643
- shiftId: params.shift,
4644
- lastUpdated: /* @__PURE__ */ new Date(),
4645
- _debugId: `vid_FALLBACK_${Date.now()}_${Math.random().toString(36).substring(7)}`
4646
- }
4647
- };
4648
- this.updateRequestStatus(key, "render_ready" /* RENDER_READY */, fallbackData);
4649
- return fallbackData;
4650
- } else {
4651
- console.error(`[VideoPrefetchManager] Received null/undefined result from S3 service`);
4652
- throw new Error("Failed to fetch clip counts from S3 service");
4676
+ console.error(`[VideoPrefetchManager] Received null/undefined result from S3 service`);
4677
+ throw new Error("Failed to fetch clip counts from S3 service");
4678
+ }
4679
+ } finally {
4680
+ s3Service.setPrefetchMode(false);
4653
4681
  }
4654
4682
  }
4655
4683
  /**
@@ -4912,9 +4940,13 @@ var AuthProvider = ({ children }) => {
4912
4940
  const [loading, setLoading] = useState(true);
4913
4941
  const [error, setError] = useState(null);
4914
4942
  const router = useRouter();
4915
- const userProfileTable = authConfig?.userProfileTable;
4916
- const roleColumn = authConfig?.roleColumn || "role";
4943
+ authConfig?.userProfileTable;
4944
+ authConfig?.roleColumn || "role";
4917
4945
  const fetchUserDetails = useCallback(async (supabaseUser) => {
4946
+ console.log("[fetchUserDetails] Called for user:", supabaseUser.id, {
4947
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4948
+ stackTrace: new Error().stack?.split("\n").slice(1, 4).join(" -> ")
4949
+ });
4918
4950
  if (!supabaseUser) return null;
4919
4951
  const basicUser = {
4920
4952
  id: supabaseUser.id,
@@ -4923,42 +4955,34 @@ var AuthProvider = ({ children }) => {
4923
4955
  if (!supabase) return basicUser;
4924
4956
  try {
4925
4957
  const timeoutPromise = new Promise(
4926
- (_, reject) => setTimeout(() => reject(new Error("Profile fetch timeout")), 5e3)
4958
+ (_, reject) => setTimeout(() => {
4959
+ console.log("[fetchUserDetails] Timeout triggered after 2 seconds");
4960
+ reject(new Error("Profile fetch timeout"));
4961
+ }, 2e3)
4927
4962
  );
4928
4963
  const rolePromise = supabase.from("user_roles").select("role_level").eq("user_id", supabaseUser.id).single();
4929
- let profilePromise = null;
4930
- if (userProfileTable) {
4931
- profilePromise = supabase.from(userProfileTable).select(roleColumn).eq("id", supabaseUser.id).single();
4932
- }
4933
- const [roleResult, profileResult] = await Promise.race([
4934
- Promise.all([
4935
- rolePromise,
4936
- profilePromise || Promise.resolve(null)
4937
- ]),
4938
- timeoutPromise.then(() => {
4939
- throw new Error("Timeout");
4940
- })
4964
+ const roleResult = await Promise.race([
4965
+ rolePromise,
4966
+ timeoutPromise
4967
+ // Fixed: removed .then() which was causing the bug
4941
4968
  ]);
4942
4969
  let roleLevel = void 0;
4943
4970
  if (roleResult && !roleResult.error && roleResult.data) {
4944
4971
  roleLevel = roleResult.data.role_level;
4945
- } else if (roleResult?.error) {
4972
+ } else if (roleResult?.error && roleResult.error.code !== "PGRST116") {
4946
4973
  console.log("Error fetching role_level:", roleResult.error.message);
4947
4974
  }
4948
- let roleValue = void 0;
4949
- if (profileResult && !profileResult.error && profileResult.data) {
4950
- roleValue = profileResult.data[roleColumn];
4951
- }
4952
4975
  return {
4953
4976
  ...basicUser,
4954
- role: roleValue,
4955
4977
  role_level: roleLevel
4956
4978
  };
4957
4979
  } catch (err) {
4958
- console.error("Error fetching user details:", err);
4980
+ if (err instanceof Error && err.message.includes("timeout")) {
4981
+ console.warn("Auth fetch timeout - using basic user info");
4982
+ }
4959
4983
  return basicUser;
4960
4984
  }
4961
- }, [supabase, userProfileTable, roleColumn]);
4985
+ }, [supabase]);
4962
4986
  useEffect(() => {
4963
4987
  if (!supabase) return;
4964
4988
  let mounted = true;
@@ -4969,6 +4993,7 @@ var AuthProvider = ({ children }) => {
4969
4993
  }
4970
4994
  }, 1e4);
4971
4995
  const initializeAuth = async () => {
4996
+ const startTime = performance.now();
4972
4997
  try {
4973
4998
  const { data: { session: initialSession }, error: sessionError } = await supabase.auth.getSession();
4974
4999
  if (!mounted) return;
@@ -5011,12 +5036,38 @@ var AuthProvider = ({ children }) => {
5011
5036
  if (mounted) {
5012
5037
  setLoading(false);
5013
5038
  clearTimeout(safetyTimeout);
5039
+ const duration = performance.now() - startTime;
5040
+ if (duration > 3e3) {
5041
+ console.warn(`[Auth] Initialization took ${duration.toFixed(0)}ms - consider optimization`);
5042
+ } else if (process.env.NODE_ENV === "development") {
5043
+ console.log(`[Auth] Initialized in ${duration.toFixed(0)}ms`);
5044
+ }
5014
5045
  }
5015
5046
  }
5016
5047
  };
5017
5048
  initializeAuth();
5018
- const { data: { subscription } } = supabase.auth.onAuthStateChange(async (_event, currentSession) => {
5049
+ const { data: { subscription } } = supabase.auth.onAuthStateChange(async (event, currentSession) => {
5019
5050
  if (!mounted) return;
5051
+ console.log("[AuthContext] Auth event fired:", {
5052
+ event,
5053
+ sessionId: currentSession?.user?.id,
5054
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5055
+ currentPath: typeof window !== "undefined" ? window.location.pathname : "unknown"
5056
+ });
5057
+ if (event === "TOKEN_REFRESHED") {
5058
+ if (session?.user?.id === currentSession?.user?.id && session?.user?.email === currentSession?.user?.email) {
5059
+ console.log("[AuthContext] Skipping TOKEN_REFRESHED - session unchanged");
5060
+ return;
5061
+ }
5062
+ }
5063
+ if (event !== "TOKEN_REFRESHED" && currentSession?.user) {
5064
+ console.log("[AuthContext] Non-TOKEN_REFRESHED event will trigger fetchUserDetails:", event);
5065
+ }
5066
+ const sessionChanged = session?.user?.id !== currentSession?.user?.id || session?.user?.email !== currentSession?.user?.email;
5067
+ if (!sessionChanged && user) {
5068
+ console.log("[AuthContext] Session and user unchanged, skipping update");
5069
+ return;
5070
+ }
5020
5071
  setSession(currentSession);
5021
5072
  setUser(null);
5022
5073
  setLoading(false);
@@ -6937,16 +6988,12 @@ var useTargets = (options) => {
6937
6988
  };
6938
6989
  var DEFAULT_SHIFTS_TABLE_NAME = "shift_configurations";
6939
6990
  var useShifts = () => {
6940
- const { supabaseUrl, supabaseKey } = useDashboardConfig();
6941
6991
  const { companyId } = useEntityConfig();
6942
6992
  const { tables } = useDatabaseConfig();
6993
+ const supabase = useSupabase();
6943
6994
  const [shifts, setShifts] = useState([]);
6944
6995
  const [isLoading, setIsLoading] = useState(true);
6945
6996
  const [error, setError] = useState(null);
6946
- const supabase = useMemo(() => {
6947
- if (!supabaseUrl || !supabaseKey) return null;
6948
- return createClient(supabaseUrl, supabaseKey);
6949
- }, [supabaseUrl, supabaseKey]);
6950
6997
  const shiftsTable = tables?.shiftConfigurations || DEFAULT_SHIFTS_TABLE_NAME;
6951
6998
  const fetchData = useCallback(async () => {
6952
6999
  if (!supabase) {
@@ -7645,6 +7692,7 @@ var runtimeWorkspaceDisplayNames = {};
7645
7692
  var isInitialized = false;
7646
7693
  var isInitializing = false;
7647
7694
  var initializedWithLineIds = [];
7695
+ var initializationPromise = null;
7648
7696
  function getCurrentLineIds() {
7649
7697
  try {
7650
7698
  const config = _getDashboardConfigInstance();
@@ -7665,52 +7713,79 @@ function getCurrentLineIds() {
7665
7713
  }
7666
7714
  async function initializeWorkspaceDisplayNames(explicitLineId) {
7667
7715
  console.log("\u{1F504} initializeWorkspaceDisplayNames called", { isInitialized, isInitializing, explicitLineId });
7668
- if (isInitialized || isInitializing) return;
7669
- isInitializing = true;
7670
- try {
7671
- console.log("\u{1F504} Starting Supabase workspace display names initialization...");
7672
- let targetLineIds = [];
7673
- if (explicitLineId) {
7674
- targetLineIds = [explicitLineId];
7675
- } else {
7676
- targetLineIds = getCurrentLineIds();
7716
+ if (isInitialized) return;
7717
+ if (initializationPromise) {
7718
+ console.log("\u{1F504} Already initializing, waiting for existing initialization...");
7719
+ await initializationPromise;
7720
+ return;
7721
+ }
7722
+ initializationPromise = (async () => {
7723
+ isInitializing = true;
7724
+ try {
7725
+ console.log("\u{1F504} Starting Supabase workspace display names initialization...");
7726
+ let targetLineIds = [];
7727
+ if (explicitLineId) {
7728
+ targetLineIds = [explicitLineId];
7729
+ } else {
7730
+ targetLineIds = getCurrentLineIds();
7731
+ }
7732
+ console.log("\u{1F504} Target line IDs for workspace filtering:", targetLineIds);
7733
+ runtimeWorkspaceDisplayNames = {};
7734
+ if (targetLineIds.length > 0) {
7735
+ for (const lineId of targetLineIds) {
7736
+ console.log(`\u{1F504} Fetching workspaces for line: ${lineId}`);
7737
+ const lineDisplayNamesMap = await workspaceService.getWorkspaceDisplayNames(void 0, lineId);
7738
+ runtimeWorkspaceDisplayNames[lineId] = {};
7739
+ lineDisplayNamesMap.forEach((displayName, workspaceId) => {
7740
+ runtimeWorkspaceDisplayNames[lineId][workspaceId] = displayName;
7741
+ });
7742
+ console.log(`\u2705 Stored ${lineDisplayNamesMap.size} workspaces for line ${lineId}`);
7743
+ }
7744
+ } else {
7745
+ console.warn("\u26A0\uFE0F No line IDs found, fetching all workspaces (less efficient)");
7746
+ const allWorkspacesMap = await workspaceService.getWorkspaceDisplayNames();
7747
+ runtimeWorkspaceDisplayNames["global"] = {};
7748
+ allWorkspacesMap.forEach((displayName, workspaceId) => {
7749
+ runtimeWorkspaceDisplayNames["global"][workspaceId] = displayName;
7750
+ });
7751
+ }
7752
+ isInitialized = true;
7753
+ initializedWithLineIds = targetLineIds;
7754
+ console.log("\u2705 Workspace display names initialized from Supabase:", runtimeWorkspaceDisplayNames);
7755
+ console.log("\u2705 Initialized with line IDs:", initializedWithLineIds);
7756
+ } catch (error) {
7757
+ console.error("\u274C Failed to initialize workspace display names from Supabase:", error);
7758
+ } finally {
7759
+ isInitializing = false;
7760
+ initializationPromise = null;
7677
7761
  }
7678
- console.log("\u{1F504} Target line IDs for workspace filtering:", targetLineIds);
7679
- runtimeWorkspaceDisplayNames = {};
7680
- if (targetLineIds.length > 0) {
7681
- for (const lineId of targetLineIds) {
7682
- console.log(`\u{1F504} Fetching workspaces for line: ${lineId}`);
7762
+ })();
7763
+ await initializationPromise;
7764
+ }
7765
+ var preInitializeWorkspaceDisplayNames = async (lineId) => {
7766
+ console.log("\u{1F504} preInitializeWorkspaceDisplayNames called for lineId:", lineId);
7767
+ if (isInitialized) {
7768
+ console.log("\u{1F504} Already initialized");
7769
+ if (lineId && !runtimeWorkspaceDisplayNames[lineId]) {
7770
+ console.log(`\u{1F504} Line ${lineId} not in cache, fetching...`);
7771
+ try {
7683
7772
  const lineDisplayNamesMap = await workspaceService.getWorkspaceDisplayNames(void 0, lineId);
7684
7773
  runtimeWorkspaceDisplayNames[lineId] = {};
7685
7774
  lineDisplayNamesMap.forEach((displayName, workspaceId) => {
7686
7775
  runtimeWorkspaceDisplayNames[lineId][workspaceId] = displayName;
7687
7776
  });
7688
- console.log(`\u2705 Stored ${lineDisplayNamesMap.size} workspaces for line ${lineId}`);
7777
+ console.log(`\u2705 Added ${lineDisplayNamesMap.size} workspaces for line ${lineId}`);
7778
+ } catch (error) {
7779
+ console.error(`\u274C Failed to fetch workspaces for line ${lineId}:`, error);
7689
7780
  }
7690
- } else {
7691
- console.warn("\u26A0\uFE0F No line IDs found, fetching all workspaces (less efficient)");
7692
- const allWorkspacesMap = await workspaceService.getWorkspaceDisplayNames();
7693
- runtimeWorkspaceDisplayNames["global"] = {};
7694
- allWorkspacesMap.forEach((displayName, workspaceId) => {
7695
- runtimeWorkspaceDisplayNames["global"][workspaceId] = displayName;
7696
- });
7697
7781
  }
7698
- isInitialized = true;
7699
- initializedWithLineIds = targetLineIds;
7700
- console.log("\u2705 Workspace display names initialized from Supabase:", runtimeWorkspaceDisplayNames);
7701
- console.log("\u2705 Initialized with line IDs:", initializedWithLineIds);
7702
- } catch (error) {
7703
- console.error("\u274C Failed to initialize workspace display names from Supabase:", error);
7704
- } finally {
7705
- isInitializing = false;
7782
+ return;
7706
7783
  }
7707
- }
7708
- var preInitializeWorkspaceDisplayNames = async (lineId) => {
7709
- console.log("\u{1F504} preInitializeWorkspaceDisplayNames called for lineId:", lineId);
7710
- if (isInitialized || isInitializing) {
7711
- console.log("\u{1F504} Already initialized or initializing");
7784
+ if (initializationPromise) {
7785
+ console.log("\u{1F504} Already initializing, waiting for completion...");
7786
+ await initializationPromise;
7712
7787
  if (lineId && !runtimeWorkspaceDisplayNames[lineId]) {
7713
- console.log(`\u{1F504} Line ${lineId} not in cache, fetching...`);
7788
+ console.log(`\u{1F504} Line ${lineId} not in cache after init, fetching...`);
7714
7789
  try {
7715
7790
  const lineDisplayNamesMap = await workspaceService.getWorkspaceDisplayNames(void 0, lineId);
7716
7791
  runtimeWorkspaceDisplayNames[lineId] = {};
@@ -7728,7 +7803,12 @@ var preInitializeWorkspaceDisplayNames = async (lineId) => {
7728
7803
  };
7729
7804
  var forceRefreshWorkspaceDisplayNames = async (lineId) => {
7730
7805
  console.log("\u{1F504} forceRefreshWorkspaceDisplayNames called for lineId:", lineId);
7806
+ if (initializationPromise) {
7807
+ console.log("\u{1F504} Waiting for existing initialization to complete before refresh...");
7808
+ await initializationPromise;
7809
+ }
7731
7810
  clearWorkspaceDisplayNamesCache();
7811
+ initializationPromise = null;
7732
7812
  await initializeWorkspaceDisplayNames(lineId);
7733
7813
  };
7734
7814
  console.log("\u{1F504} Module loaded, will initialize lazily when first function is called");
@@ -7876,6 +7956,7 @@ var clearWorkspaceDisplayNamesCache = () => {
7876
7956
  isInitialized = false;
7877
7957
  isInitializing = false;
7878
7958
  initializedWithLineIds = [];
7959
+ initializationPromise = null;
7879
7960
  };
7880
7961
 
7881
7962
  // src/lib/hooks/useWorkspaceDisplayNames.ts
@@ -19516,11 +19597,13 @@ var withAuth = (WrappedComponent2, options) => {
19516
19597
  requireAuth: true,
19517
19598
  ...options
19518
19599
  };
19519
- return function WithAuthComponent(props) {
19600
+ const WithAuthComponent = React19.memo(function WithAuthComponent2(props) {
19520
19601
  const { session, loading } = useAuth();
19521
19602
  const router = useRouter();
19522
19603
  React19.useEffect(() => {
19523
- console.log("withAuth state:", { loading, hasSession: !!session, requireAuth: defaultOptions.requireAuth });
19604
+ if (process.env.NODE_ENV === "development" && process.env.DEBUG_AUTH === "true") {
19605
+ console.log("withAuth state:", { loading, hasSession: !!session, requireAuth: defaultOptions.requireAuth });
19606
+ }
19524
19607
  }, [session, loading]);
19525
19608
  React19.useEffect(() => {
19526
19609
  if (!loading && defaultOptions.requireAuth && !session) {
@@ -19535,7 +19618,9 @@ var withAuth = (WrappedComponent2, options) => {
19535
19618
  return null;
19536
19619
  }
19537
19620
  return /* @__PURE__ */ jsx(WrappedComponent2, { ...props });
19538
- };
19621
+ });
19622
+ WithAuthComponent.displayName = `withAuth(${WrappedComponent2.displayName || WrappedComponent2.name || "Component"})`;
19623
+ return WithAuthComponent;
19539
19624
  };
19540
19625
  var LoginPage = ({
19541
19626
  onRateLimitCheck,
@@ -26123,7 +26208,7 @@ var BottlenecksContent = ({
26123
26208
  const [duration, setDuration] = useState(0);
26124
26209
  const [currentIndex, setCurrentIndex] = useState(0);
26125
26210
  const [activeFilter, setActiveFilter] = useState(initialFilter);
26126
- const previousFilterRef = useRef(initialFilter);
26211
+ const previousFilterRef = useRef("");
26127
26212
  const [allVideos, setAllVideos] = useState([]);
26128
26213
  const [isLoading, setIsLoading] = useState(true);
26129
26214
  const [isCategoryLoading, setIsCategoryLoading] = useState(false);
@@ -26173,7 +26258,7 @@ var BottlenecksContent = ({
26173
26258
  console.warn("S3 configuration not found in dashboard config");
26174
26259
  return null;
26175
26260
  }
26176
- return new S3ClipsService(dashboardConfig);
26261
+ return videoPrefetchManager.getS3Service(dashboardConfig);
26177
26262
  }, [dashboardConfig]);
26178
26263
  const {
26179
26264
  data: prefetchData,
@@ -26280,8 +26365,8 @@ var BottlenecksContent = ({
26280
26365
  index,
26281
26366
  true,
26282
26367
  // includeCycleTime - OK for preloading
26283
- true
26284
- // includeMetadata - OK for just +3/-1 videos, not ALL videos
26368
+ false
26369
+ // includeMetadata - NO metadata during bulk preloading to prevent flooding
26285
26370
  );
26286
26371
  }
26287
26372
  if (!video) {
@@ -26295,8 +26380,8 @@ var BottlenecksContent = ({
26295
26380
  index,
26296
26381
  true,
26297
26382
  // includeCycleTime - OK for preloading
26298
- true
26299
- // includeMetadata - OK for just +3/-1 videos, not ALL videos
26383
+ false
26384
+ // includeMetadata - NO metadata during bulk preloading to prevent flooding
26300
26385
  );
26301
26386
  }
26302
26387
  if (video && isMountedRef.current) {
@@ -26356,8 +26441,16 @@ var BottlenecksContent = ({
26356
26441
  );
26357
26442
  if (firstVideo) {
26358
26443
  console.log(`[BottlenecksContent] Successfully loaded first video via direct S3 method`);
26359
- setAllVideos([firstVideo]);
26444
+ setAllVideos((prev) => {
26445
+ const exists = prev.some((v) => v.id === firstVideo.id);
26446
+ if (!exists) {
26447
+ return [...prev, firstVideo];
26448
+ }
26449
+ return prev;
26450
+ });
26360
26451
  preloadVideoUrl(firstVideo.src);
26452
+ setIsLoading(false);
26453
+ setHasInitialLoad(true);
26361
26454
  loadingCategoryRef.current = null;
26362
26455
  setIsCategoryLoading(false);
26363
26456
  return;
@@ -26380,7 +26473,13 @@ var BottlenecksContent = ({
26380
26473
  );
26381
26474
  if (firstVideo && isMountedRef.current) {
26382
26475
  console.log(`[BottlenecksContent] Successfully loaded first video via video index`);
26383
- setAllVideos([firstVideo]);
26476
+ setAllVideos((prev) => {
26477
+ const exists = prev.some((v) => v.id === firstVideo.id);
26478
+ if (!exists) {
26479
+ return [...prev, firstVideo];
26480
+ }
26481
+ return prev;
26482
+ });
26384
26483
  preloadVideoUrl(firstVideo.src);
26385
26484
  setIsCategoryLoading(false);
26386
26485
  return;
@@ -26405,15 +26504,17 @@ var BottlenecksContent = ({
26405
26504
  }
26406
26505
  }, [workspaceId, date, s3ClipsService, clipCounts, videoIndex, shift, updateClipCounts, updateVideoIndex]);
26407
26506
  useEffect(() => {
26408
- if (s3ClipsService) {
26507
+ if (s3ClipsService && !prefetchData) {
26409
26508
  fetchClipCounts();
26410
26509
  }
26411
- }, [workspaceId, date, shift, s3ClipsService, fetchClipCounts, updateClipCounts, updateVideoIndex]);
26510
+ }, [workspaceId, date, shift, s3ClipsService, fetchClipCounts, updateClipCounts, updateVideoIndex, prefetchData]);
26412
26511
  useEffect(() => {
26413
26512
  if (prefetchData) {
26414
26513
  console.log(`[BottlenecksContent] Received prefetch update - status: ${prefetchStatus}, videos: ${prefetchData.videoIndex.allVideos.length}, ID: ${prefetchData.videoIndex._debugId || "NO_ID"}`);
26415
26514
  updateClipCounts(prefetchData.counts);
26416
- updateVideoIndex(prefetchData.videoIndex);
26515
+ if (prefetchData.videoIndex.allVideos.length > 0) {
26516
+ updateVideoIndex(prefetchData.videoIndex);
26517
+ }
26417
26518
  if (!hasInitialLoad && prefetchData.videoIndex.allVideos.length > 0) {
26418
26519
  setIsLoading(false);
26419
26520
  setHasInitialLoad(true);
@@ -26421,12 +26522,45 @@ var BottlenecksContent = ({
26421
26522
  }
26422
26523
  }, [prefetchData, prefetchStatus, updateClipCounts, updateVideoIndex, hasInitialLoad]);
26423
26524
  useEffect(() => {
26424
- if (s3ClipsService && videoIndex && clipCounts[activeFilter] > 0) {
26425
- if (allVideos.length === 0) {
26525
+ if (s3ClipsService && clipCounts[activeFilter] > 0) {
26526
+ const hasVideosForCurrentFilter = allVideos.some((video) => {
26527
+ if (sopCategories && sopCategories.length > 0) {
26528
+ const selectedCategory = sopCategories.find((cat) => cat.id === activeFilter);
26529
+ if (selectedCategory) {
26530
+ return video.type === selectedCategory.id;
26531
+ }
26532
+ }
26533
+ if (activeFilter === "all") return true;
26534
+ if (activeFilter === "low_value") {
26535
+ return video.type === "low_value";
26536
+ }
26537
+ if (activeFilter === "idle_time") {
26538
+ return video.type === "idle_time";
26539
+ }
26540
+ if (activeFilter === "sop_deviations") {
26541
+ return video.type === "missing_quality_check";
26542
+ }
26543
+ if (activeFilter === "best_cycle_time") {
26544
+ return video.type === "best_cycle_time";
26545
+ }
26546
+ if (activeFilter === "worst_cycle_time") {
26547
+ return video.type === "worst_cycle_time";
26548
+ }
26549
+ if (activeFilter === "cycle_completion") {
26550
+ return video.type === "cycle_completion";
26551
+ }
26552
+ if (activeFilter === "long_cycle_time") {
26553
+ return video.type === "long_cycle_time";
26554
+ }
26555
+ return video.type === "bottleneck" && video.severity === activeFilter;
26556
+ });
26557
+ if (!hasVideosForCurrentFilter) {
26426
26558
  loadFirstVideoForCategory(activeFilter);
26559
+ } else {
26560
+ setIsCategoryLoading(false);
26427
26561
  }
26428
26562
  }
26429
- }, [activeFilter, s3ClipsService, videoIndex, clipCounts, loadFirstVideoForCategory, allVideos.length]);
26563
+ }, [activeFilter, s3ClipsService, videoIndex, clipCounts, loadFirstVideoForCategory, allVideos, sopCategories]);
26430
26564
  useEffect(() => {
26431
26565
  if (previousFilterRef.current !== activeFilter) {
26432
26566
  console.log(`Filter changed from ${previousFilterRef.current} to ${activeFilter} - resetting to first video`);
@@ -26609,14 +26743,39 @@ var BottlenecksContent = ({
26609
26743
  }
26610
26744
  }
26611
26745
  }, [filteredVideos.length]);
26746
+ const currentVideo = useMemo(() => {
26747
+ if (!filteredVideos || filteredVideos.length === 0 || currentIndex >= filteredVideos.length) {
26748
+ return null;
26749
+ }
26750
+ return filteredVideos[currentIndex];
26751
+ }, [filteredVideos, currentIndex]);
26612
26752
  const handleVideoReady = useCallback((player) => {
26613
26753
  console.log("Video.js player ready");
26614
26754
  }, []);
26615
- const handleVideoPlay = useCallback((player) => {
26755
+ const handleVideoPlay = useCallback(async (player) => {
26616
26756
  setIsPlaying(true);
26617
26757
  const currentIdx = currentIndexRef.current;
26618
26758
  ensureVideosLoaded(currentIdx);
26619
- }, []);
26759
+ if (currentVideo && !currentVideo.creation_timestamp && s3ClipsService) {
26760
+ try {
26761
+ const originalUri = currentVideo.originalUri || currentVideo.src;
26762
+ if (originalUri && originalUri.includes("s3://")) {
26763
+ const metadata = await s3ClipsService.getFullMetadata(originalUri);
26764
+ if (metadata && isMountedRef.current) {
26765
+ setAllVideos((prev) => prev.map(
26766
+ (v) => v.id === currentVideo.id ? {
26767
+ ...v,
26768
+ creation_timestamp: metadata.upload_timestamp || metadata.original_task_metadata?.timestamp || metadata.creation_timestamp,
26769
+ cycle_time_seconds: metadata.original_task_metadata?.cycle_time || v.cycle_time_seconds
26770
+ } : v
26771
+ ));
26772
+ }
26773
+ }
26774
+ } catch (error2) {
26775
+ console.warn("[BottlenecksContent] Failed to load metadata for current video:", error2);
26776
+ }
26777
+ }
26778
+ }, [currentVideo, s3ClipsService]);
26620
26779
  const handleVideoPause = useCallback((player) => {
26621
26780
  setIsPlaying(false);
26622
26781
  }, []);
@@ -26643,13 +26802,6 @@ var BottlenecksContent = ({
26643
26802
  fetchInProgressRef.current.clear();
26644
26803
  setIsCategoryLoading(false);
26645
26804
  setIsNavigating(false);
26646
- if (s3ClipsService) {
26647
- try {
26648
- s3ClipsService.dispose();
26649
- } catch (error2) {
26650
- console.warn("[BottlenecksContent] Error disposing S3 service:", error2);
26651
- }
26652
- }
26653
26805
  };
26654
26806
  }, [s3ClipsService]);
26655
26807
  useEffect(() => {
@@ -26690,12 +26842,6 @@ var BottlenecksContent = ({
26690
26842
  counts.bottlenecks = counts.bottleneck || counts.bottlenecks || 0;
26691
26843
  return counts;
26692
26844
  }, [clipCounts]);
26693
- const currentVideo = useMemo(() => {
26694
- if (!filteredVideos || filteredVideos.length === 0 || currentIndex >= filteredVideos.length) {
26695
- return null;
26696
- }
26697
- return filteredVideos[currentIndex];
26698
- }, [filteredVideos, currentIndex]);
26699
26845
  const getClipTypeLabel = (video) => {
26700
26846
  if (!video) return "";
26701
26847
  switch (video.type) {
@@ -26930,8 +27076,8 @@ var BottlenecksContent = ({
26930
27076
  ] }),
26931
27077
  /* Priority 1: Show loading if initial load hasn't completed yet */
26932
27078
  isLoading && !hasInitialLoad ? /* @__PURE__ */ jsx("div", { className: "p-4 h-[calc(100%-4rem)]", children: /* @__PURE__ */ jsx("div", { className: "relative h-full", children: /* @__PURE__ */ jsx("div", { className: "relative w-full h-full overflow-hidden rounded-md shadow-inner bg-gray-900 flex items-center justify-center", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading clips..." }) }) }) }) : (
26933
- /* Priority 2: Show loading if category is loading (prevents "no matching clips" flash) */
26934
- isCategoryLoading ? /* @__PURE__ */ jsx("div", { className: "p-4 h-[calc(100%-4rem)]", children: /* @__PURE__ */ jsx("div", { className: "relative h-full", children: /* @__PURE__ */ jsx("div", { className: "relative w-full h-full overflow-hidden rounded-md shadow-inner bg-gray-900 flex items-center justify-center", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading videos..." }) }) }) }) : (
27079
+ /* Priority 2: Show loading if category is loading BUT only if no video is available */
27080
+ isCategoryLoading && (!filteredVideos.length || !currentVideo) ? /* @__PURE__ */ jsx("div", { className: "p-4 h-[calc(100%-4rem)]", children: /* @__PURE__ */ jsx("div", { className: "relative h-full", children: /* @__PURE__ */ jsx("div", { className: "relative w-full h-full overflow-hidden rounded-md shadow-inner bg-gray-900 flex items-center justify-center", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading videos..." }) }) }) }) : (
26935
27081
  /* Priority 3: Show loading if navigating and current video not available */
26936
27082
  isNavigating || currentIndex >= filteredVideos.length && currentIndex < clipCounts[activeFilter] ? /* @__PURE__ */ jsx("div", { className: "p-4 h-[calc(100%-4rem)]", children: /* @__PURE__ */ jsx("div", { className: "relative h-full", children: /* @__PURE__ */ jsx("div", { className: "relative w-full h-full overflow-hidden rounded-md shadow-inner bg-gray-900 flex items-center justify-center", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }) }) }) : (
26937
27083
  /* Priority 4: Show video if we have filtered videos and current video */
@@ -31288,7 +31434,7 @@ var HelpView = ({
31288
31434
  onClick: handleBackClick,
31289
31435
  className: "flex items-center text-gray-600 hover:text-gray-900",
31290
31436
  children: [
31291
- /* @__PURE__ */ jsx(ArrowLeftIcon, { className: "h-5 w-5" }),
31437
+ /* @__PURE__ */ jsx(ArrowLeftIcon$1, { className: "h-5 w-5" }),
31292
31438
  /* @__PURE__ */ jsx("span", { className: "ml-2", children: "Back" })
31293
31439
  ]
31294
31440
  }
@@ -31729,9 +31875,25 @@ function withWorkspaceDisplayNames(Component3, options = {}) {
31729
31875
  return function WithWorkspaceDisplayNamesWrapper(props) {
31730
31876
  const [isInitialized2, setIsInitialized] = useState(false);
31731
31877
  const [error, setError] = useState(null);
31878
+ const [lastInitKey, setLastInitKey] = useState("");
31879
+ const lineIdsKey = useMemo(() => {
31880
+ if (!props.lineIds) return "";
31881
+ if (Array.isArray(props.lineIds)) {
31882
+ return props.lineIds.sort().join(",");
31883
+ }
31884
+ const values = Object.values(props.lineIds).filter(Boolean);
31885
+ return values.sort().join(",");
31886
+ }, [props.lineIds]);
31887
+ const initKey = useMemo(() => {
31888
+ return `${lineIdsKey}-${props.selectedLineId || ""}-${props.factoryViewId || ""}-${initializeFor}`;
31889
+ }, [lineIdsKey, props.selectedLineId, props.factoryViewId]);
31732
31890
  useEffect(() => {
31733
- setIsInitialized(false);
31734
- setError(null);
31891
+ if (initKey === lastInitKey && isInitialized2) {
31892
+ return;
31893
+ }
31894
+ if (initKey !== lastInitKey) {
31895
+ setError(null);
31896
+ }
31735
31897
  const initializeDisplayNames = async () => {
31736
31898
  try {
31737
31899
  const { lineIds, selectedLineId, factoryViewId } = props;
@@ -31757,20 +31919,17 @@ function withWorkspaceDisplayNames(Component3, options = {}) {
31757
31919
  await preInitializeWorkspaceDisplayNames();
31758
31920
  }
31759
31921
  setIsInitialized(true);
31922
+ setLastInitKey(initKey);
31760
31923
  } catch (err) {
31761
31924
  console.error("Failed to initialize workspace display names:", err);
31762
31925
  setError(err);
31763
31926
  setIsInitialized(true);
31927
+ setLastInitKey(initKey);
31764
31928
  }
31765
31929
  };
31766
31930
  initializeDisplayNames();
31767
- }, [
31768
- Array.isArray(props.lineIds) ? props.lineIds.join(",") : JSON.stringify(props.lineIds),
31769
- props.selectedLineId,
31770
- props.factoryViewId,
31771
- initializeFor
31772
- ]);
31773
- if (!isInitialized2 && showLoading) {
31931
+ }, [initKey]);
31932
+ if (!isInitialized2 && showLoading && lastInitKey === "") {
31774
31933
  return /* @__PURE__ */ jsx(LoadingPage, { message: loadingMessage });
31775
31934
  }
31776
31935
  if (error && showLoading) {
@@ -32410,7 +32569,7 @@ var KPIDetailView = ({
32410
32569
  onClick: handleBackClick,
32411
32570
  className: "absolute left-0 flex items-center text-gray-600 hover:text-gray-900 cursor-pointer",
32412
32571
  children: [
32413
- /* @__PURE__ */ jsx(ArrowLeftIcon, { className: "h-5 w-5" }),
32572
+ /* @__PURE__ */ jsx(ArrowLeftIcon$1, { className: "h-5 w-5" }),
32414
32573
  /* @__PURE__ */ jsx("span", { className: "ml-2", children: "Back" })
32415
32574
  ]
32416
32575
  }
@@ -32782,7 +32941,7 @@ var KPIsOverviewView = ({
32782
32941
  onClick: handleBackClick,
32783
32942
  className: "absolute left-0 flex items-center text-gray-600 hover:text-gray-900 cursor-pointer",
32784
32943
  children: [
32785
- /* @__PURE__ */ jsx(ArrowLeftIcon, { className: "h-5 w-5" }),
32944
+ /* @__PURE__ */ jsx(ArrowLeftIcon$1, { className: "h-5 w-5" }),
32786
32945
  /* @__PURE__ */ jsx("span", { className: "ml-2", children: "Back" })
32787
32946
  ]
32788
32947
  }
@@ -32804,7 +32963,7 @@ var KPIsOverviewView = ({
32804
32963
  onClick: handleBackClick,
32805
32964
  className: "absolute left-0 flex items-center text-gray-600 hover:text-gray-900 cursor-pointer",
32806
32965
  children: [
32807
- /* @__PURE__ */ jsx(ArrowLeftIcon, { className: "h-5 w-5" }),
32966
+ /* @__PURE__ */ jsx(ArrowLeftIcon$1, { className: "h-5 w-5" }),
32808
32967
  /* @__PURE__ */ jsx("span", { className: "ml-2", children: "Back" })
32809
32968
  ]
32810
32969
  }
@@ -32829,7 +32988,7 @@ var KPIsOverviewView = ({
32829
32988
  onClick: handleBackClick,
32830
32989
  className: "absolute left-0 flex items-center text-gray-600 hover:text-gray-900 cursor-pointer",
32831
32990
  children: [
32832
- /* @__PURE__ */ jsx(ArrowLeftIcon, { className: "h-5 w-5" }),
32991
+ /* @__PURE__ */ jsx(ArrowLeftIcon$1, { className: "h-5 w-5" }),
32833
32992
  /* @__PURE__ */ jsx("span", { className: "ml-2", children: "Back" })
32834
32993
  ]
32835
32994
  }
@@ -33841,7 +34000,15 @@ var ShiftsView = ({
33841
34000
  className = ""
33842
34001
  }) => {
33843
34002
  const supabase = useSupabase();
33844
- const auth = useAuth();
34003
+ useEffect(() => {
34004
+ console.log("[ShiftsView] Component mounted/re-rendered", {
34005
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
34006
+ lineIds: lineIds.length
34007
+ });
34008
+ return () => {
34009
+ console.log("[ShiftsView] Component unmounting");
34010
+ };
34011
+ }, []);
33845
34012
  const [lineConfigs, setLineConfigs] = useState(
33846
34013
  () => lineIds.map((id3) => ({
33847
34014
  id: id3,
@@ -33939,7 +34106,7 @@ var ShiftsView = ({
33939
34106
  }
33940
34107
  };
33941
34108
  fetchShiftConfigs();
33942
- }, [supabase, lineIds, showToast]);
34109
+ }, [lineIds, showToast]);
33943
34110
  useCallback((lineId) => {
33944
34111
  setLineConfigs((prev) => {
33945
34112
  const typedPrev = prev;
@@ -34132,7 +34299,6 @@ var ShiftsView = ({
34132
34299
  }));
34133
34300
  }, []);
34134
34301
  const handleSaveShifts = useCallback(async (lineId) => {
34135
- if (!auth.user?.id && false) ;
34136
34302
  setLineConfigs((prev) => prev.map(
34137
34303
  (config) => config.id === lineId ? { ...config, isSaving: true, saveSuccess: false } : config
34138
34304
  ));
@@ -34179,7 +34345,7 @@ var ShiftsView = ({
34179
34345
  (config) => config.id === lineId ? { ...config, isSaving: false, saveSuccess: false } : config
34180
34346
  ));
34181
34347
  }
34182
- }, [auth.user?.id, lineConfigs, supabase, showToast]);
34348
+ }, [lineConfigs, supabase, showToast]);
34183
34349
  return /* @__PURE__ */ jsxs("div", { className: `min-h-screen bg-slate-50 ${className}`, children: [
34184
34350
  /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-10 bg-white border-b border-gray-200/80 shadow-sm", children: /* @__PURE__ */ jsx("div", { className: "px-4 sm:px-8 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center relative", children: [
34185
34351
  /* @__PURE__ */ jsxs(
@@ -34287,6 +34453,7 @@ var ShiftsView = ({
34287
34453
  ] })
34288
34454
  ] });
34289
34455
  };
34456
+ var AuthenticatedShiftsView = withAuth(React19__default.memo(ShiftsView));
34290
34457
  var ShiftsView_default = ShiftsView;
34291
34458
 
34292
34459
  // src/lib/constants/actions.ts
@@ -35074,6 +35241,7 @@ var TargetsViewUI = ({
35074
35241
  isLoading,
35075
35242
  lineWorkspaces,
35076
35243
  lineNames,
35244
+ dropdownStates,
35077
35245
  savingLines,
35078
35246
  saveSuccess,
35079
35247
  selectedShift,
@@ -35106,7 +35274,7 @@ var TargetsViewUI = ({
35106
35274
  onClick: onBack,
35107
35275
  className: "flex items-center text-gray-600 hover:text-gray-900",
35108
35276
  children: [
35109
- /* @__PURE__ */ jsx(ArrowLeftIcon$1, { className: "h-5 w-5" }),
35277
+ /* @__PURE__ */ jsx(ArrowLeftIcon, { className: "h-5 w-5" }),
35110
35278
  /* @__PURE__ */ jsx("span", { className: "ml-2", children: "Back" })
35111
35279
  ]
35112
35280
  }
@@ -35159,13 +35327,13 @@ var TargetsViewUI = ({
35159
35327
  {
35160
35328
  onClick: () => onToggleLineDropdown(lineId),
35161
35329
  className: "flex items-center gap-3 text-lg font-medium transition-colors duration-200 \n focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 rounded-lg \n hover:bg-blue-50 px-3 py-2 group",
35162
- "aria-expanded": line.isOpen,
35330
+ "aria-expanded": dropdownStates[lineId],
35163
35331
  "aria-controls": `line-${lineId}-content`,
35164
35332
  children: [
35165
35333
  /* @__PURE__ */ jsx(
35166
35334
  ChevronDown,
35167
35335
  {
35168
- className: `w-5 h-5 text-blue-500 transform transition-transform duration-200 ${line.isOpen ? "rotate-180" : ""}`
35336
+ className: `w-5 h-5 text-blue-500 transform transition-transform duration-200 ${dropdownStates[lineId] ? "rotate-180" : ""}`
35169
35337
  }
35170
35338
  ),
35171
35339
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5", children: [
@@ -35212,7 +35380,7 @@ var TargetsViewUI = ({
35212
35380
  )
35213
35381
  ] })
35214
35382
  ] }) }),
35215
- line.isOpen && /* @__PURE__ */ jsxs("div", { id: `line-${lineId}-content`, className: "border-t border-gray-200", children: [
35383
+ dropdownStates[lineId] && /* @__PURE__ */ jsxs("div", { id: `line-${lineId}-content`, className: "border-t border-gray-200", children: [
35216
35384
  skuEnabled && /* @__PURE__ */ jsx("div", { className: "px-6 py-4 border-b border-gray-200 bg-gray-50/50", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
35217
35385
  /* @__PURE__ */ jsx("label", { htmlFor: `sku-${lineId}`, className: "text-sm font-medium text-gray-700", children: "Select SKU:" }),
35218
35386
  /* @__PURE__ */ jsx("div", { className: "flex-1 max-w-md", children: /* @__PURE__ */ jsx(
@@ -35249,68 +35417,71 @@ var TargetsViewUI = ({
35249
35417
  /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400", children: "pieces per day" })
35250
35418
  ] })
35251
35419
  ] }) }),
35252
- /* @__PURE__ */ jsx("div", { className: "divide-y divide-gray-100", children: line.workspaces.map((workspace) => /* @__PURE__ */ jsx(
35253
- "div",
35254
- {
35255
- className: "px-6 py-4 hover:bg-gray-50 transition-all duration-200",
35256
- children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-12 gap-6 items-center", children: [
35257
- /* @__PURE__ */ jsx("div", { className: "col-span-2", children: /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-900", children: formatWorkspaceName(workspace.name, lineId) }) }),
35258
- /* @__PURE__ */ jsx("div", { className: "col-span-2", children: /* @__PURE__ */ jsxs(
35259
- "select",
35260
- {
35261
- value: workspace.actionType,
35262
- onChange: (e) => {
35263
- const newActionType = e.target.value;
35264
- onActionTypeChange(lineId, workspace.id, newActionType);
35265
- },
35266
- className: "w-full p-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm",
35267
- "aria-label": `Action type for ${formatWorkspaceName(workspace.name, lineId)}`,
35268
- children: [
35269
- /* @__PURE__ */ jsx("option", { value: "assembly", className: "py-2", children: "Assembly" }),
35270
- /* @__PURE__ */ jsx("option", { value: "packaging", className: "py-2", children: "Packaging" })
35271
- ]
35272
- }
35273
- ) }),
35274
- /* @__PURE__ */ jsx("div", { className: "col-span-3", children: /* @__PURE__ */ jsx(
35275
- "input",
35276
- {
35277
- type: "number",
35278
- value: workspace.targetCycleTime === 0 ? "" : workspace.targetCycleTime,
35279
- onChange: (e) => onUpdateWorkspaceTarget(lineId, workspace.id, "targetCycleTime", Number(e.target.value) || ""),
35280
- className: "block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm\n shadow-sm focus:border-blue-500 focus:ring-blue-500 \n transition-all duration-200 hover:border-gray-400",
35281
- min: "0",
35282
- step: "0.01",
35283
- placeholder: "Enter cycle time"
35284
- }
35285
- ) }),
35286
- /* @__PURE__ */ jsx("div", { className: "col-span-3", children: /* @__PURE__ */ jsx(
35287
- "input",
35288
- {
35289
- type: "number",
35290
- value: workspace.targetPPH === 0 ? "" : workspace.targetPPH,
35291
- onChange: (e) => onUpdateWorkspaceTarget(lineId, workspace.id, "targetPPH", Number(e.target.value) || ""),
35292
- className: "block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm\n shadow-sm focus:border-blue-500 focus:ring-blue-500 \n transition-all duration-200 hover:border-gray-400 \n placeholder:text-gray-400",
35293
- min: "0",
35294
- step: "0.1",
35295
- placeholder: "Enter PPH"
35296
- }
35297
- ) }),
35298
- /* @__PURE__ */ jsx("div", { className: "col-span-2", children: /* @__PURE__ */ jsx(
35299
- "input",
35300
- {
35301
- type: "number",
35302
- value: workspace.targetDayOutput === 0 ? "" : workspace.targetDayOutput,
35303
- onChange: (e) => onUpdateWorkspaceTarget(lineId, workspace.id, "targetDayOutput", Number(e.target.value) || ""),
35304
- className: "block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm\n shadow-sm focus:border-blue-500 focus:ring-blue-500 \n transition-all duration-200 hover:border-gray-400 \n placeholder:text-gray-400",
35305
- min: "0",
35306
- step: "1",
35307
- placeholder: "Enter day output"
35308
- }
35309
- ) })
35310
- ] })
35311
- },
35312
- workspace.id
35313
- )) })
35420
+ /* @__PURE__ */ jsx("div", { className: "divide-y divide-gray-100", children: line.workspaces.map((workspace) => {
35421
+ const formattedName = formatWorkspaceName(workspace.name, lineId);
35422
+ return /* @__PURE__ */ jsx(
35423
+ "div",
35424
+ {
35425
+ className: "px-6 py-4 hover:bg-gray-50 transition-all duration-200",
35426
+ children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-12 gap-6 items-center", children: [
35427
+ /* @__PURE__ */ jsx("div", { className: "col-span-2", children: /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-900", children: formattedName }) }),
35428
+ /* @__PURE__ */ jsx("div", { className: "col-span-2", children: /* @__PURE__ */ jsxs(
35429
+ "select",
35430
+ {
35431
+ value: workspace.actionType,
35432
+ onChange: (e) => {
35433
+ const newActionType = e.target.value;
35434
+ onActionTypeChange(lineId, workspace.id, newActionType);
35435
+ },
35436
+ className: "w-full p-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm",
35437
+ "aria-label": `Action type for ${formattedName}`,
35438
+ children: [
35439
+ /* @__PURE__ */ jsx("option", { value: "assembly", className: "py-2", children: "Assembly" }),
35440
+ /* @__PURE__ */ jsx("option", { value: "packaging", className: "py-2", children: "Packaging" })
35441
+ ]
35442
+ }
35443
+ ) }),
35444
+ /* @__PURE__ */ jsx("div", { className: "col-span-3", children: /* @__PURE__ */ jsx(
35445
+ "input",
35446
+ {
35447
+ type: "number",
35448
+ value: workspace.targetCycleTime === 0 ? "" : workspace.targetCycleTime,
35449
+ onChange: (e) => onUpdateWorkspaceTarget(lineId, workspace.id, "targetCycleTime", Number(e.target.value) || ""),
35450
+ className: "block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm\n shadow-sm focus:border-blue-500 focus:ring-blue-500 \n transition-all duration-200 hover:border-gray-400",
35451
+ min: "0",
35452
+ step: "0.01",
35453
+ placeholder: "Enter cycle time"
35454
+ }
35455
+ ) }),
35456
+ /* @__PURE__ */ jsx("div", { className: "col-span-3", children: /* @__PURE__ */ jsx(
35457
+ "input",
35458
+ {
35459
+ type: "number",
35460
+ value: workspace.targetPPH === 0 ? "" : workspace.targetPPH,
35461
+ onChange: (e) => onUpdateWorkspaceTarget(lineId, workspace.id, "targetPPH", Number(e.target.value) || ""),
35462
+ className: "block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm\n shadow-sm focus:border-blue-500 focus:ring-blue-500 \n transition-all duration-200 hover:border-gray-400 \n placeholder:text-gray-400",
35463
+ min: "0",
35464
+ step: "0.1",
35465
+ placeholder: "Enter PPH"
35466
+ }
35467
+ ) }),
35468
+ /* @__PURE__ */ jsx("div", { className: "col-span-2", children: /* @__PURE__ */ jsx(
35469
+ "input",
35470
+ {
35471
+ type: "number",
35472
+ value: workspace.targetDayOutput === 0 ? "" : workspace.targetDayOutput,
35473
+ onChange: (e) => onUpdateWorkspaceTarget(lineId, workspace.id, "targetDayOutput", Number(e.target.value) || ""),
35474
+ className: "block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm\n shadow-sm focus:border-blue-500 focus:ring-blue-500 \n transition-all duration-200 hover:border-gray-400 \n placeholder:text-gray-400",
35475
+ min: "0",
35476
+ step: "1",
35477
+ placeholder: "Enter day output"
35478
+ }
35479
+ ) })
35480
+ ] })
35481
+ },
35482
+ workspace.id
35483
+ );
35484
+ }) })
35314
35485
  ] })
35315
35486
  ]
35316
35487
  },
@@ -35343,7 +35514,6 @@ var TargetsView = ({
35343
35514
  return lineIds.reduce((acc, lineId) => ({
35344
35515
  ...acc,
35345
35516
  [lineId]: {
35346
- isOpen: getStoredLineState2(lineId),
35347
35517
  productId: "",
35348
35518
  shiftStartTime: "08:00",
35349
35519
  shiftEndTime: "19:00",
@@ -35356,6 +35526,12 @@ var TargetsView = ({
35356
35526
  }
35357
35527
  }), {});
35358
35528
  }, [lineIds]);
35529
+ const [dropdownStates, setDropdownStates] = useState(() => {
35530
+ return lineIds.reduce((acc, lineId) => ({
35531
+ ...acc,
35532
+ [lineId]: getStoredLineState2(lineId)
35533
+ }), {});
35534
+ });
35359
35535
  const [allShiftsData, setAllShiftsData] = useState({
35360
35536
  0: initialLineWorkspaces,
35361
35537
  // Day shift
@@ -35373,6 +35549,8 @@ var TargetsView = ({
35373
35549
  const [isBulkConfigureOpen, setIsBulkConfigureOpen] = useState(false);
35374
35550
  const [selectedWorkspaces, setSelectedWorkspaces] = useState([]);
35375
35551
  const [selectedShift, setSelectedShift] = useState(0);
35552
+ const [dbValues, setDbValues] = useState({ 0: {}, 1: {} });
35553
+ const [userEditedFields, setUserEditedFields] = useState(/* @__PURE__ */ new Set());
35376
35554
  const lineWorkspaces = allShiftsData[selectedShift] || initialLineWorkspaces;
35377
35555
  const setLineWorkspaces = useCallback((updater) => {
35378
35556
  setAllShiftsData((prev) => ({
@@ -35381,18 +35559,123 @@ var TargetsView = ({
35381
35559
  }));
35382
35560
  }, [selectedShift]);
35383
35561
  const supabase = useSupabase();
35384
- const auth = useAuth();
35385
- userId || auth?.user?.id;
35562
+ const effectiveUserId = userId || "6bf6f271-1e55-4a95-9b89-1c3820b58739";
35386
35563
  const dashboardConfig = useDashboardConfig();
35387
35564
  const { skus, isLoading: skusLoading } = useSKUs(companyId);
35388
35565
  const skuEnabled = dashboardConfig?.skuConfig?.enabled || false;
35566
+ const loadOperatingHours = useCallback(async (lineId, shiftId) => {
35567
+ try {
35568
+ if (!supabase) return null;
35569
+ const { data, error } = await supabase.from("line_operating_hours").select("start_time, end_time, breaks").eq("line_id", lineId).eq("shift_id", shiftId).maybeSingle();
35570
+ if (error) {
35571
+ if (error.code === "PGRST116") {
35572
+ console.log(`No operating hours found for line ${lineId}, shift ${shiftId}`);
35573
+ return {
35574
+ startTime: "08:00",
35575
+ // Default values
35576
+ endTime: "19:00",
35577
+ breaks: []
35578
+ };
35579
+ } else {
35580
+ console.error("Error fetching operating hours:", error);
35581
+ return null;
35582
+ }
35583
+ }
35584
+ let breaks = [];
35585
+ if (data?.breaks) {
35586
+ if (Array.isArray(data.breaks)) {
35587
+ breaks = data.breaks.map((breakItem) => {
35588
+ const startTime = breakItem.start || breakItem.startTime || "00:00";
35589
+ const endTime = breakItem.end || breakItem.endTime || "00:00";
35590
+ const calculateDuration = (start, end) => {
35591
+ const [startHour, startMinute] = start.split(":").map(Number);
35592
+ const [endHour, endMinute] = end.split(":").map(Number);
35593
+ let startMinutes = startHour * 60 + startMinute;
35594
+ let endMinutes = endHour * 60 + endMinute;
35595
+ if (endMinutes < startMinutes) {
35596
+ endMinutes += 24 * 60;
35597
+ }
35598
+ return endMinutes - startMinutes;
35599
+ };
35600
+ return {
35601
+ startTime,
35602
+ endTime,
35603
+ duration: breakItem.duration || calculateDuration(startTime, endTime)
35604
+ };
35605
+ });
35606
+ } else if (typeof data.breaks === "object" && data.breaks.breaks) {
35607
+ breaks = data.breaks.breaks.map((breakItem) => {
35608
+ const startTime = breakItem.start || breakItem.startTime || "00:00";
35609
+ const endTime = breakItem.end || breakItem.endTime || "00:00";
35610
+ const calculateDuration = (start, end) => {
35611
+ const [startHour, startMinute] = start.split(":").map(Number);
35612
+ const [endHour, endMinute] = end.split(":").map(Number);
35613
+ let startMinutes = startHour * 60 + startMinute;
35614
+ let endMinutes = endHour * 60 + endMinute;
35615
+ if (endMinutes < startMinutes) {
35616
+ endMinutes += 24 * 60;
35617
+ }
35618
+ return endMinutes - startMinutes;
35619
+ };
35620
+ return {
35621
+ startTime,
35622
+ endTime,
35623
+ duration: breakItem.duration || calculateDuration(startTime, endTime)
35624
+ };
35625
+ });
35626
+ } else if (typeof data.breaks === "string") {
35627
+ try {
35628
+ const parsedBreaks = JSON.parse(data.breaks);
35629
+ if (Array.isArray(parsedBreaks)) {
35630
+ breaks = parsedBreaks.map((breakItem) => ({
35631
+ startTime: breakItem.start || breakItem.startTime || "00:00",
35632
+ endTime: breakItem.end || breakItem.endTime || "00:00",
35633
+ duration: breakItem.duration || 0
35634
+ }));
35635
+ } else if (parsedBreaks.breaks && Array.isArray(parsedBreaks.breaks)) {
35636
+ breaks = parsedBreaks.breaks.map((breakItem) => ({
35637
+ startTime: breakItem.start || breakItem.startTime || "00:00",
35638
+ endTime: breakItem.end || breakItem.endTime || "00:00",
35639
+ duration: breakItem.duration || 0
35640
+ }));
35641
+ }
35642
+ } catch (e) {
35643
+ console.error("Error parsing breaks data:", e);
35644
+ }
35645
+ }
35646
+ }
35647
+ return {
35648
+ startTime: data?.start_time || "08:00",
35649
+ endTime: data?.end_time || "19:00",
35650
+ breaks
35651
+ };
35652
+ } catch (e) {
35653
+ console.error("Exception when loading operating hours:", e);
35654
+ return {
35655
+ startTime: "08:00",
35656
+ endTime: "19:00",
35657
+ breaks: []
35658
+ };
35659
+ }
35660
+ }, [supabase]);
35661
+ useEffect(() => {
35662
+ console.log("[TargetsView] Component mounted/re-rendered", {
35663
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
35664
+ lineIds: lineIds.length,
35665
+ effectiveUserId
35666
+ });
35667
+ return () => {
35668
+ console.log("[TargetsView] Component unmounting");
35669
+ };
35670
+ }, []);
35389
35671
  useEffect(() => {
35390
35672
  let timeoutId;
35391
35673
  let retryCount = 0;
35392
35674
  const MAX_RETRIES2 = 2;
35393
35675
  const LOADING_TIMEOUT = 15e3;
35394
35676
  const fetchInitialData = async () => {
35395
- if (!supabase || lineIds.length === 0) return;
35677
+ if (lineIds.length === 0) return;
35678
+ console.log("[TargetsView] Starting fetchInitialData");
35396
35679
  setIsLoading(true);
35397
35680
  timeoutId = setTimeout(() => {
35398
35681
  console.error("Loading timeout reached");
@@ -35456,10 +35739,32 @@ var TargetsView = ({
35456
35739
  const actionThresholds = await workspaceService.getActionThresholds(
35457
35740
  lineId,
35458
35741
  currentDate,
35459
- selectedShift
35742
+ 0
35743
+ // Always use day shift for initial load
35460
35744
  );
35745
+ const operatingHoursData = await loadOperatingHours(lineId, 0);
35746
+ if (operatingHoursData) {
35747
+ updatedLineWorkspaces[lineId].shiftStartTime = operatingHoursData.startTime;
35748
+ updatedLineWorkspaces[lineId].shiftEndTime = operatingHoursData.endTime;
35749
+ updatedLineWorkspaces[lineId].breaks = operatingHoursData.breaks;
35750
+ updatedLineWorkspaces[lineId].shiftHours = calculateShiftHours2(
35751
+ operatingHoursData.startTime,
35752
+ operatingHoursData.endTime,
35753
+ operatingHoursData.breaks
35754
+ );
35755
+ }
35461
35756
  const mappedWorkspaces = enabledWorkspaces.map((ws) => {
35462
35757
  const threshold = actionThresholds.find((t) => t.workspace_id === ws.id);
35758
+ if (!dbValues[0][lineId]) {
35759
+ dbValues[0][lineId] = {};
35760
+ }
35761
+ if (threshold) {
35762
+ dbValues[0][lineId][ws.id] = {
35763
+ targetPPH: threshold.pph_threshold,
35764
+ targetCycleTime: threshold.ideal_cycle_time,
35765
+ targetDayOutput: threshold.total_day_output
35766
+ };
35767
+ }
35463
35768
  return {
35464
35769
  id: ws.id,
35465
35770
  name: ws.workspace_id,
@@ -35500,90 +35805,7 @@ var TargetsView = ({
35500
35805
  return () => {
35501
35806
  clearTimeout(timeoutId);
35502
35807
  };
35503
- }, [supabase, lineIds, companyId]);
35504
- useCallback(async (shiftId) => {
35505
- try {
35506
- if (!supabase) return;
35507
- const currentDate = getOperationalDate();
35508
- const updatedLineWorkspaces = { ...lineWorkspaces };
35509
- let hasUpdates = false;
35510
- for (const lineId of lineIds) {
35511
- const lineState = lineWorkspaces[lineId];
35512
- if (!lineState || !lineState.factoryId) {
35513
- console.warn(`Skipping line thresholds for ${lineId} as factoryId is not yet available.`);
35514
- continue;
35515
- }
35516
- const currentFactoryId = lineState.factoryId;
35517
- try {
35518
- const { data: lineThresholdsRows, error: thresholdError } = await supabase.from("line_thresholds").select("product_code").eq("line_id", lineId).eq("date", currentDate).eq("shift_id", selectedShift).eq("factory_id", currentFactoryId);
35519
- if (thresholdError) {
35520
- console.error(`Error fetching line threshold for line ${lineId}, factory ${currentFactoryId}:`, thresholdError);
35521
- continue;
35522
- }
35523
- let determinedProductId = updatedLineWorkspaces[lineId]?.productId || "";
35524
- if (lineThresholdsRows && lineThresholdsRows.length > 0) {
35525
- if (lineThresholdsRows.length > 1) {
35526
- console.warn(
35527
- `Multiple line_thresholds records found for line ${lineId}, factory ${currentFactoryId}, date ${currentDate}, shift ${selectedShift}. Using product_code from the first record. Rows:`,
35528
- lineThresholdsRows
35529
- );
35530
- }
35531
- determinedProductId = lineThresholdsRows[0].product_code;
35532
- } else {
35533
- console.log(
35534
- `No line_thresholds record found for line ${lineId}, factory ${currentFactoryId}, date ${currentDate}, shift ${selectedShift}. Using existing/default product ID.`
35535
- );
35536
- }
35537
- const { data: operatingHours, error: hoursError } = await supabase.from("line_operating_hours").select("start_time, end_time, breaks").eq("line_id", lineId).eq("shift_id", selectedShift).maybeSingle();
35538
- if (hoursError) {
35539
- console.error(`Error fetching operating hours for line ${lineId}:`, hoursError);
35540
- continue;
35541
- }
35542
- const startTime = operatingHours?.start_time || updatedLineWorkspaces[lineId]?.shiftStartTime || "08:00";
35543
- const endTime = operatingHours?.end_time || updatedLineWorkspaces[lineId]?.shiftEndTime || "19:00";
35544
- let breaks = [];
35545
- if (operatingHours?.breaks) {
35546
- if (Array.isArray(operatingHours.breaks)) {
35547
- breaks = operatingHours.breaks.map((breakItem) => ({
35548
- startTime: breakItem.start || breakItem.startTime || "00:00",
35549
- endTime: breakItem.end || breakItem.endTime || "00:00",
35550
- duration: breakItem.duration || calculateShiftHours2(breakItem.start || breakItem.startTime || "00:00", breakItem.end || breakItem.endTime || "00:00", []) * 60
35551
- }));
35552
- } else if (typeof operatingHours.breaks === "object" && operatingHours.breaks.breaks) {
35553
- breaks = operatingHours.breaks.breaks.map((breakItem) => ({
35554
- startTime: breakItem.start || breakItem.startTime || "00:00",
35555
- endTime: breakItem.end || breakItem.endTime || "00:00",
35556
- duration: breakItem.duration || calculateShiftHours2(breakItem.start || breakItem.startTime || "00:00", breakItem.end || breakItem.endTime || "00:00", []) * 60
35557
- }));
35558
- }
35559
- }
35560
- const shiftHours = calculateShiftHours2(startTime, endTime, breaks);
35561
- const currentLineStateFromLoop = updatedLineWorkspaces[lineId];
35562
- if (determinedProductId !== currentLineStateFromLoop?.productId || startTime !== currentLineStateFromLoop?.shiftStartTime || endTime !== currentLineStateFromLoop?.shiftEndTime || shiftHours !== currentLineStateFromLoop?.shiftHours || JSON.stringify(breaks) !== JSON.stringify(currentLineStateFromLoop?.breaks)) {
35563
- updatedLineWorkspaces[lineId] = {
35564
- ...currentLineStateFromLoop || {},
35565
- factoryId: currentFactoryId,
35566
- // Ensure factoryId is preserved
35567
- productId: determinedProductId,
35568
- shiftStartTime: startTime,
35569
- shiftEndTime: endTime,
35570
- breaks,
35571
- shiftHours: Number(shiftHours),
35572
- workspaces: currentLineStateFromLoop?.workspaces || []
35573
- };
35574
- hasUpdates = true;
35575
- }
35576
- } catch (lineError) {
35577
- console.error(`Error processing line ${lineId}:`, lineError);
35578
- }
35579
- }
35580
- if (hasUpdates) {
35581
- setLineWorkspaces(updatedLineWorkspaces);
35582
- }
35583
- } catch (error) {
35584
- console.error("Error in fetchLineThresholds outer try-catch:", error);
35585
- }
35586
- }, [selectedShift, supabase, lineIds, lineWorkspaces, allShiftsData]);
35808
+ }, [lineIds, companyId, loadOperatingHours]);
35587
35809
  const fetchAllShiftsData = useCallback(async (currentWorkspaces) => {
35588
35810
  if (!supabase) return;
35589
35811
  const currentDate = getOperationalDate();
@@ -35593,32 +35815,25 @@ var TargetsView = ({
35593
35815
  1: JSON.parse(JSON.stringify(currentWorkspaces))
35594
35816
  // Deep clone for night shift
35595
35817
  };
35818
+ const newDbValues = { 0: {}, 1: {} };
35596
35819
  for (const shiftId of [0, 1]) {
35597
35820
  for (const lineId of lineIds) {
35598
35821
  try {
35599
- const { data: operatingHours, error: hoursError } = await supabase.from("line_operating_hours").select("start_time, end_time, breaks").eq("line_id", lineId).eq("shift_id", shiftId).maybeSingle();
35600
- if (hoursError) {
35601
- console.error(`Error fetching operating hours for line ${lineId}, shift ${shiftId}:`, hoursError);
35822
+ const operatingHoursData = await loadOperatingHours(lineId, shiftId);
35823
+ if (!operatingHoursData) {
35824
+ console.warn(`No operating hours for line ${lineId}, shift ${shiftId} - using defaults`);
35602
35825
  continue;
35603
35826
  }
35604
- let breaks = [];
35605
- if (operatingHours?.breaks) {
35606
- if (Array.isArray(operatingHours.breaks)) {
35607
- breaks = operatingHours.breaks.map((breakItem) => ({
35608
- startTime: breakItem.start || breakItem.startTime || "00:00",
35609
- endTime: breakItem.end || breakItem.endTime || "00:00",
35610
- duration: breakItem.duration || calculateShiftHours2(breakItem.start || breakItem.startTime || "00:00", breakItem.end || breakItem.endTime || "00:00", []) * 60
35611
- }));
35612
- }
35613
- }
35614
- const startTime = operatingHours?.start_time || "08:00";
35615
- const endTime = operatingHours?.end_time || "19:00";
35827
+ const { startTime, endTime, breaks } = operatingHoursData;
35616
35828
  const shiftHours = calculateShiftHours2(startTime, endTime, breaks);
35617
35829
  const actionThresholds = await workspaceService.getActionThresholds(
35618
35830
  lineId,
35619
35831
  currentDate,
35620
35832
  shiftId
35621
35833
  );
35834
+ if (!newDbValues[shiftId][lineId]) {
35835
+ newDbValues[shiftId][lineId] = {};
35836
+ }
35622
35837
  const existingLine = newAllShiftsData[shiftId][lineId];
35623
35838
  if (existingLine) {
35624
35839
  newAllShiftsData[shiftId][lineId] = {
@@ -35630,6 +35845,11 @@ var TargetsView = ({
35630
35845
  workspaces: existingLine.workspaces.map((ws) => {
35631
35846
  const threshold = actionThresholds.find((t) => t.workspace_id === ws.id);
35632
35847
  if (threshold) {
35848
+ newDbValues[shiftId][lineId][ws.id] = {
35849
+ targetPPH: threshold.pph_threshold,
35850
+ targetCycleTime: threshold.ideal_cycle_time,
35851
+ targetDayOutput: threshold.total_day_output
35852
+ };
35633
35853
  return {
35634
35854
  ...ws,
35635
35855
  targetPPH: threshold.pph_threshold,
@@ -35647,114 +35867,17 @@ var TargetsView = ({
35647
35867
  }
35648
35868
  }
35649
35869
  setAllShiftsData(newAllShiftsData);
35650
- }, [supabase, lineIds]);
35651
- const loadOperatingHours = useCallback(async (lineId, shiftId) => {
35652
- try {
35653
- if (!supabase) return null;
35654
- const { data, error } = await supabase.from("line_operating_hours").select("start_time, end_time, breaks").eq("line_id", lineId).eq("shift_id", shiftId).maybeSingle();
35655
- if (error) {
35656
- if (error.code === "PGRST116") {
35657
- console.log(`No operating hours found for line ${lineId}, shift ${shiftId}`);
35658
- return {
35659
- startTime: "08:00",
35660
- // Default values
35661
- endTime: "19:00",
35662
- breaks: []
35663
- };
35664
- } else {
35665
- console.error("Error fetching operating hours:", error);
35666
- return null;
35667
- }
35668
- }
35669
- let breaks = [];
35670
- if (data?.breaks) {
35671
- if (Array.isArray(data.breaks)) {
35672
- breaks = data.breaks.map((breakItem) => {
35673
- const startTime = breakItem.start || breakItem.startTime || "00:00";
35674
- const endTime = breakItem.end || breakItem.endTime || "00:00";
35675
- const calculateDuration = (start, end) => {
35676
- const [startHour, startMinute] = start.split(":").map(Number);
35677
- const [endHour, endMinute] = end.split(":").map(Number);
35678
- let startMinutes = startHour * 60 + startMinute;
35679
- let endMinutes = endHour * 60 + endMinute;
35680
- if (endMinutes < startMinutes) {
35681
- endMinutes += 24 * 60;
35682
- }
35683
- return endMinutes - startMinutes;
35684
- };
35685
- return {
35686
- startTime,
35687
- endTime,
35688
- duration: breakItem.duration || calculateDuration(startTime, endTime)
35689
- };
35690
- });
35691
- } else if (typeof data.breaks === "object" && data.breaks.breaks) {
35692
- breaks = data.breaks.breaks.map((breakItem) => {
35693
- const startTime = breakItem.start || breakItem.startTime || "00:00";
35694
- const endTime = breakItem.end || breakItem.endTime || "00:00";
35695
- const calculateDuration = (start, end) => {
35696
- const [startHour, startMinute] = start.split(":").map(Number);
35697
- const [endHour, endMinute] = end.split(":").map(Number);
35698
- let startMinutes = startHour * 60 + startMinute;
35699
- let endMinutes = endHour * 60 + endMinute;
35700
- if (endMinutes < startMinutes) {
35701
- endMinutes += 24 * 60;
35702
- }
35703
- return endMinutes - startMinutes;
35704
- };
35705
- return {
35706
- startTime,
35707
- endTime,
35708
- duration: breakItem.duration || calculateDuration(startTime, endTime)
35709
- };
35710
- });
35711
- } else if (typeof data.breaks === "string") {
35712
- try {
35713
- const parsedBreaks = JSON.parse(data.breaks);
35714
- if (Array.isArray(parsedBreaks)) {
35715
- breaks = parsedBreaks.map((breakItem) => ({
35716
- startTime: breakItem.start || breakItem.startTime || "00:00",
35717
- endTime: breakItem.end || breakItem.endTime || "00:00",
35718
- duration: breakItem.duration || 0
35719
- }));
35720
- } else if (parsedBreaks.breaks && Array.isArray(parsedBreaks.breaks)) {
35721
- breaks = parsedBreaks.breaks.map((breakItem) => ({
35722
- startTime: breakItem.start || breakItem.startTime || "00:00",
35723
- endTime: breakItem.end || breakItem.endTime || "00:00",
35724
- duration: breakItem.duration || 0
35725
- }));
35726
- }
35727
- } catch (e) {
35728
- console.error("Error parsing breaks data:", e);
35729
- }
35730
- }
35731
- }
35732
- return {
35733
- startTime: data?.start_time || "08:00",
35734
- endTime: data?.end_time || "19:00",
35735
- breaks
35736
- };
35737
- } catch (e) {
35738
- console.error("Exception when loading operating hours:", e);
35739
- return {
35740
- startTime: "08:00",
35741
- endTime: "19:00",
35742
- breaks: []
35743
- };
35744
- }
35745
- }, [supabase]);
35870
+ setDbValues(newDbValues);
35871
+ }, [supabase, lineIds, loadOperatingHours]);
35746
35872
  const toggleLineDropdown = useCallback((lineId) => {
35747
- setLineWorkspaces((prev) => {
35748
- const newIsOpen = !prev[lineId].isOpen;
35873
+ setDropdownStates((prev) => {
35874
+ const newIsOpen = !prev[lineId];
35749
35875
  if (typeof window !== "undefined") {
35750
35876
  localStorage.setItem(`line_${lineId}_open`, JSON.stringify(newIsOpen));
35751
35877
  }
35752
35878
  return {
35753
35879
  ...prev,
35754
- [lineId]: {
35755
- ...prev[lineId],
35756
- isOpen: newIsOpen
35757
- }
35880
+ [lineId]: newIsOpen
35758
35881
  };
35759
35882
  });
35760
35883
  }, []);
@@ -35803,6 +35926,8 @@ var TargetsView = ({
35803
35926
  }
35804
35927
  };
35805
35928
  const updateWorkspaceTarget = (lineId, workspaceId, field, value) => {
35929
+ const fieldKey = `${lineId}-${workspaceId}-${field}`;
35930
+ setUserEditedFields((prev) => new Set(prev).add(fieldKey));
35806
35931
  setLineWorkspaces((prev) => {
35807
35932
  const shiftHours = prev[lineId].shiftHours;
35808
35933
  return {
@@ -35827,11 +35952,7 @@ var TargetsView = ({
35827
35952
  } else if (field === "targetDayOutput") {
35828
35953
  updates.targetDayOutput = value;
35829
35954
  if (value !== "") {
35830
- const breaks = prev[lineId].breaks;
35831
- const totalBreakMinutes = breaks.reduce((total, b) => total + b.duration, 0);
35832
- const totalBreakHours = totalBreakMinutes / 60;
35833
- const realWorkHours = shiftHours - totalBreakHours;
35834
- const calculatedPPH = Math.round(value / realWorkHours);
35955
+ const calculatedPPH = Math.round(value / shiftHours);
35835
35956
  updates.targetPPH = calculatedPPH;
35836
35957
  } else {
35837
35958
  updates.targetPPH = "";
@@ -35846,62 +35967,35 @@ var TargetsView = ({
35846
35967
  };
35847
35968
  const handleShiftChange = (shiftId) => {
35848
35969
  setSelectedShift(shiftId);
35849
- const loadShiftHours = async () => {
35850
- const updatedLineWorkspaces = { ...allShiftsData[shiftId] };
35851
- let hasUpdates = false;
35852
- for (const lineId of lineIds) {
35853
- try {
35854
- const operatingHours = await loadOperatingHours(lineId, shiftId);
35855
- if (!operatingHours) continue;
35856
- const shiftHours = calculateShiftHours2(
35857
- operatingHours.startTime,
35858
- operatingHours.endTime,
35859
- operatingHours.breaks
35860
- );
35861
- updatedLineWorkspaces[lineId] = {
35862
- ...updatedLineWorkspaces[lineId],
35863
- shiftStartTime: operatingHours.startTime,
35864
- shiftEndTime: operatingHours.endTime,
35865
- breaks: operatingHours.breaks,
35866
- shiftHours: Number(shiftHours),
35867
- workspaces: updatedLineWorkspaces[lineId].workspaces.map((ws) => {
35868
- let updatedPPH = ws.targetPPH;
35869
- if (ws.targetCycleTime !== "") {
35870
- const idealPPH = calculatePPH(
35871
- ws.targetCycleTime,
35872
- operatingHours.breaks,
35873
- Number(shiftHours)
35874
- );
35875
- const shouldUpdatePPH = typeof ws.targetPPH === "string" ? ws.targetPPH === "" : ws.targetPPH === 0 || !ws.targetPPH;
35876
- if (shouldUpdatePPH) {
35877
- updatedPPH = idealPPH;
35970
+ setUserEditedFields(/* @__PURE__ */ new Set());
35971
+ if (dbValues[shiftId] && Object.keys(dbValues[shiftId]).length > 0) {
35972
+ setAllShiftsData((prev) => {
35973
+ const updatedShiftData = { ...prev[shiftId] };
35974
+ for (const lineId of Object.keys(updatedShiftData)) {
35975
+ if (dbValues[shiftId][lineId]) {
35976
+ updatedShiftData[lineId] = {
35977
+ ...updatedShiftData[lineId],
35978
+ workspaces: updatedShiftData[lineId].workspaces.map((ws) => {
35979
+ const dbValue = dbValues[shiftId][lineId][ws.id];
35980
+ if (dbValue) {
35981
+ return {
35982
+ ...ws,
35983
+ targetPPH: dbValue.targetPPH,
35984
+ targetCycleTime: dbValue.targetCycleTime,
35985
+ targetDayOutput: dbValue.targetDayOutput
35986
+ };
35878
35987
  }
35879
- }
35880
- const updatedDayOutput = calculateDayOutput(
35881
- updatedPPH,
35882
- Number(shiftHours),
35883
- operatingHours.breaks
35884
- );
35885
- return {
35886
- ...ws,
35887
- targetPPH: updatedPPH,
35888
- targetDayOutput: updatedDayOutput
35889
- };
35890
- })
35891
- };
35892
- hasUpdates = true;
35893
- } catch (e) {
35894
- console.error(`Exception when loading shift hours for line ${lineId}:`, e);
35988
+ return ws;
35989
+ })
35990
+ };
35991
+ }
35895
35992
  }
35896
- }
35897
- if (hasUpdates) {
35898
- setAllShiftsData((prev) => ({
35993
+ return {
35899
35994
  ...prev,
35900
- [shiftId]: updatedLineWorkspaces
35901
- }));
35902
- }
35903
- };
35904
- loadShiftHours();
35995
+ [shiftId]: updatedShiftData
35996
+ };
35997
+ });
35998
+ }
35905
35999
  };
35906
36000
  const handleActionTypeChange = useCallback((lineId, workspaceId, newActionType) => {
35907
36001
  if (!actionIds) return;
@@ -35991,6 +36085,31 @@ var TargetsView = ({
35991
36085
  throw lineUpsertError;
35992
36086
  }
35993
36087
  console.log(`[handleSaveLine] Successfully upserted line_thresholds for ${lineId}`);
36088
+ setDbValues((prev) => ({
36089
+ ...prev,
36090
+ [selectedShift]: {
36091
+ ...prev[selectedShift],
36092
+ [lineId]: lineDataToSave.workspaces.reduce((acc, ws) => ({
36093
+ ...acc,
36094
+ [ws.id]: {
36095
+ targetPPH: ws.targetPPH,
36096
+ targetCycleTime: ws.targetCycleTime,
36097
+ targetDayOutput: ws.targetDayOutput
36098
+ }
36099
+ }), {})
36100
+ }
36101
+ }));
36102
+ console.log(`[handleSaveLine] Updated dbValues for line ${lineId}, shift ${selectedShift}`);
36103
+ setUserEditedFields((prev) => {
36104
+ const newSet = new Set(prev);
36105
+ lineDataToSave.workspaces.forEach((ws) => {
36106
+ newSet.delete(`${lineId}-${ws.id}-targetPPH`);
36107
+ newSet.delete(`${lineId}-${ws.id}-targetCycleTime`);
36108
+ newSet.delete(`${lineId}-${ws.id}-targetDayOutput`);
36109
+ });
36110
+ return newSet;
36111
+ });
36112
+ console.log(`[handleSaveLine] Cleared user edited fields for line ${lineId}`);
35994
36113
  setSaveSuccess((prev) => ({ ...prev, [lineId]: true }));
35995
36114
  toast.success(`${lineNames[lineId] || lineId} targets saved successfully`);
35996
36115
  if (onSaveChanges) onSaveChanges(lineId);
@@ -36004,7 +36123,7 @@ var TargetsView = ({
36004
36123
  setSavingLines((prev) => ({ ...prev, [lineId]: false }));
36005
36124
  console.log(`[handleSaveLine] Set savingLines to false for ${lineId} in finally block`);
36006
36125
  }
36007
- }, [supabase, lineWorkspaces, selectedShift, lineNames, onSaveChanges]);
36126
+ }, [supabase, lineWorkspaces, selectedShift, lineNames, onSaveChanges, skuEnabled, dashboardConfig]);
36008
36127
  const handleBulkConfigure = async (updates) => {
36009
36128
  if (!actionIds) return;
36010
36129
  if (updates.productId !== void 0) {
@@ -36052,6 +36171,7 @@ var TargetsView = ({
36052
36171
  isLoading: isLoading || skusLoading,
36053
36172
  lineWorkspaces,
36054
36173
  lineNames,
36174
+ dropdownStates,
36055
36175
  savingLines,
36056
36176
  saveSuccess,
36057
36177
  selectedShift,
@@ -36076,7 +36196,7 @@ var TargetsView = ({
36076
36196
  };
36077
36197
  var TargetsViewWithDisplayNames = withAllWorkspaceDisplayNames(TargetsView);
36078
36198
  var TargetsView_default = TargetsViewWithDisplayNames;
36079
- var AuthenticatedTargetsView = withAuth(TargetsViewWithDisplayNames);
36199
+ var AuthenticatedTargetsView = withAuth(React19__default.memo(TargetsViewWithDisplayNames));
36080
36200
 
36081
36201
  // src/views/workspace-detail-view.utils.ts
36082
36202
  var formatISTDate2 = (date = /* @__PURE__ */ new Date(), options) => {
@@ -37547,4 +37667,4 @@ var streamProxyConfig = {
37547
37667
  }
37548
37668
  };
37549
37669
 
37550
- export { ACTION_NAMES, AIAgentView_default as AIAgentView, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedTargetsView, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, CongratulationsOverlay, 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, EmptyStateMessage, EncouragementOverlay, FactoryView_default as FactoryView, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, 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, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, NoWorkspaceData, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TimeDisplay_default as TimeDisplay, TimePickerDropdown, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createStreamProxyHandler, createSupabaseClient, createThrottledReload, 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, mergeWithDefaultConfig, migrateLegacyConfiguration, optifyeAgentClient, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useActiveBreaks, useAllWorkspaceMetrics, useAnalyticsConfig, useAudioService, useAuth, useAuthConfig, 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, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, videoPrefetchManager, videoPreloader, whatsappService, withAuth, withRegistry, workspaceService };
37670
+ export { ACTION_NAMES, AIAgentView_default as AIAgentView, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, CongratulationsOverlay, 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, EmptyStateMessage, EncouragementOverlay, FactoryView_default as FactoryView, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, 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, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, NoWorkspaceData, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TimeDisplay_default as TimeDisplay, TimePickerDropdown, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createStreamProxyHandler, createSupabaseClient, createThrottledReload, 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, mergeWithDefaultConfig, migrateLegacyConfiguration, optifyeAgentClient, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useActiveBreaks, useAllWorkspaceMetrics, useAnalyticsConfig, useAudioService, useAuth, useAuthConfig, 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, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, videoPrefetchManager, videoPreloader, whatsappService, withAuth, withRegistry, workspaceService };