@optifye/dashboard-core 6.0.3 → 6.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import * as React14 from 'react';
2
- import React14__default, { createContext, useRef, useCallback, useState, useMemo, useEffect, memo, useContext, useLayoutEffect, useId, Children, isValidElement, useInsertionEffect, forwardRef, Fragment as Fragment$1, createElement, Component } from 'react';
1
+ import * as React19 from 'react';
2
+ import React19__default, { createContext, useRef, useCallback, useState, useMemo, useEffect, memo, useContext, useLayoutEffect, useId, Children, isValidElement, useInsertionEffect, forwardRef, Fragment as Fragment$1, createElement, Component } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { useRouter } from 'next/router';
5
5
  import { toZonedTime, formatInTimeZone } from 'date-fns-tz';
@@ -10,15 +10,15 @@ import Hls2 from 'hls.js';
10
10
  import useSWR from 'swr';
11
11
  import { noop, warning, invariant, progress, secondsToMilliseconds, millisecondsToSeconds, memo as memo$1 } from 'motion-utils';
12
12
  import { getValueTransition, hover, press, isPrimaryPointer, GroupPlaybackControls, setDragLock, supportsLinearEasing, attachTimeline, isGenerator, calcGeneratorDuration, isWaapiSupportedEasing, mapEasingToNativeEasing, maxGeneratorDuration, generateLinearEasing, isBezierDefinition } from 'motion-dom';
13
- import { Bar, LabelList, ResponsiveContainer, BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, Tooltip, ReferenceLine, Cell, PieChart, Pie, Legend, LineChart as LineChart$1, Line, ComposedChart, Area, ScatterChart, Scatter } from 'recharts';
13
+ 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';
14
14
  import { Slot } from '@radix-ui/react-slot';
15
- import { Camera, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, X, Coffee, Plus, Clock, Minus, ArrowDown, ArrowUp, Search, CheckCircle, AlertTriangle, Info, Share2, Download, User, XCircle, ChevronLeft, ChevronRight, AlertCircle, Sun, Moon, MessageSquare, Trash2, ArrowLeft, RefreshCw, Menu, Send, Copy, Edit2, UserCheck, Save, LogOut, Calendar, Settings, LifeBuoy, Loader2, ArrowLeftIcon as ArrowLeftIcon$1, Settings2, CheckCircle2, EyeOff, Eye, Zap, UserCircle } from 'lucide-react';
15
+ import { Camera, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, X, Coffee, Plus, Clock, Minus, ArrowDown, ArrowUp, Search, CheckCircle, AlertTriangle, Info, Share2, Download, User, XCircle, ChevronLeft, ChevronRight, AlertCircle, Sun, Moon, MessageSquare, Trash2, ArrowLeft, RefreshCw, Menu, Send, Copy, Edit2, UserCheck, Save, LogOut, Calendar, Package, Settings, LifeBuoy, Loader2, ArrowLeftIcon as ArrowLeftIcon$1, Settings2, CheckCircle2, EyeOff, Eye, Zap, UserCircle } from 'lucide-react';
16
16
  import { DayPicker, useNavigation as useNavigation$1 } from 'react-day-picker';
17
17
  import html2canvas from 'html2canvas';
18
18
  import jsPDF, { jsPDF as jsPDF$1 } from 'jspdf';
19
19
  import * as SelectPrimitive from '@radix-ui/react-select';
20
20
  import { S3Client, ListObjectsV2Command, GetObjectCommand } from '@aws-sdk/client-s3';
21
- import { HomeIcon, TrophyIcon, ChartBarIcon, AdjustmentsHorizontalIcon, ClockIcon, SparklesIcon, QuestionMarkCircleIcon, UserCircleIcon, ArrowRightIcon, ArrowLeftIcon, ChatBubbleLeftRightIcon, CheckCircleIcon, ExclamationCircleIcon, DocumentTextIcon, EnvelopeIcon, InformationCircleIcon, ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/24/outline';
21
+ import { HomeIcon, TrophyIcon, ChartBarIcon, AdjustmentsHorizontalIcon, ClockIcon, CubeIcon, SparklesIcon, QuestionMarkCircleIcon, UserCircleIcon, ArrowRightIcon, ArrowLeftIcon, ChatBubbleLeftRightIcon, CheckCircleIcon, ExclamationCircleIcon, DocumentTextIcon, EnvelopeIcon, InformationCircleIcon, ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/24/outline';
22
22
  import { Readable } from 'stream';
23
23
  import { toast } from 'sonner';
24
24
  import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
@@ -205,14 +205,14 @@ var _getDashboardConfigInstance = () => {
205
205
  }
206
206
  return dashboardConfigInstance;
207
207
  };
208
- var DashboardConfigContext = React14.createContext(void 0);
208
+ var DashboardConfigContext = React19.createContext(void 0);
209
209
  var DashboardProvider = ({ config: userProvidedConfig, children }) => {
210
- const fullConfig = React14.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
210
+ const fullConfig = React19.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
211
211
  _setDashboardConfigInstance(fullConfig);
212
- React14.useEffect(() => {
212
+ React19.useEffect(() => {
213
213
  _setDashboardConfigInstance(fullConfig);
214
214
  }, [fullConfig]);
215
- React14.useEffect(() => {
215
+ React19.useEffect(() => {
216
216
  if (!fullConfig.theme) return;
217
217
  const styleId = "dashboard-core-theme-vars";
218
218
  let styleEl = document.getElementById(styleId);
@@ -238,7 +238,7 @@ var DashboardProvider = ({ config: userProvidedConfig, children }) => {
238
238
  return /* @__PURE__ */ jsx(DashboardConfigContext.Provider, { value: fullConfig, children });
239
239
  };
240
240
  var useDashboardConfig = () => {
241
- const ctx = React14.useContext(DashboardConfigContext);
241
+ const ctx = React19.useContext(DashboardConfigContext);
242
242
  if (!ctx) throw new Error("useDashboardConfig must be used within a DashboardProvider");
243
243
  return ctx;
244
244
  };
@@ -331,6 +331,56 @@ var actionService = {
331
331
  return data || [];
332
332
  }
333
333
  };
334
+ function createMemoizedFunction(fn, getCacheKey) {
335
+ const cache = /* @__PURE__ */ new Map();
336
+ const CACHE_DURATION3 = 5 * 60 * 1e3;
337
+ return (...args) => {
338
+ const key = getCacheKey(...args);
339
+ const cached = cache.get(key);
340
+ if (cached && Date.now() - cached.timestamp < CACHE_DURATION3) {
341
+ return cached.result;
342
+ }
343
+ const result = fn(...args);
344
+ cache.set(key, { result, timestamp: Date.now() });
345
+ if (cache.size > 100) {
346
+ const firstKey = cache.keys().next().value;
347
+ if (firstKey) cache.delete(firstKey);
348
+ }
349
+ return result;
350
+ };
351
+ }
352
+ var memoizedEfficiencyFilter = createMemoizedFunction(
353
+ (data, minEfficiency, maxEfficiency) => {
354
+ return data.filter((item) => {
355
+ const eff = item.efficiency ?? 0;
356
+ return eff >= minEfficiency && (maxEfficiency === void 0 || eff < maxEfficiency);
357
+ });
358
+ },
359
+ (data, min, max = void 0) => `${data.length}-${min}-${max}`
360
+ );
361
+ var memoizedAverageEfficiency = createMemoizedFunction(
362
+ (data, minThreshold = 10) => {
363
+ const validItems = data.filter((item) => (item.efficiency ?? 0) >= minThreshold);
364
+ if (validItems.length === 0) return 0;
365
+ const sum = validItems.reduce((acc, item) => acc + (item.efficiency ?? 0), 0);
366
+ return sum / validItems.length;
367
+ },
368
+ (data, threshold) => `${data.length}-${threshold}`
369
+ );
370
+ var memoizedOutputArrayAggregation = createMemoizedFunction(
371
+ (arrays) => {
372
+ if (arrays.length === 0) return [];
373
+ const maxLength = Math.max(...arrays.map((arr) => arr.length));
374
+ const result = new Array(maxLength).fill(0);
375
+ for (const arr of arrays) {
376
+ for (let i = 0; i < arr.length; i++) {
377
+ result[i] += arr[i];
378
+ }
379
+ }
380
+ return result;
381
+ },
382
+ (arrays) => arrays.map((arr) => arr.length).join("-")
383
+ );
334
384
  var getOperationalDate = (timezone = "Asia/Kolkata", date = /* @__PURE__ */ new Date(), shiftStartTime = "06:00") => {
335
385
  const zonedDate = toZonedTime(date, timezone);
336
386
  const hours = zonedDate.getHours();
@@ -468,22 +518,32 @@ var dashboardService = {
468
518
  if (!defaultLineId || !secondaryLineId || !companyId) {
469
519
  throw new Error("Factory View requires defaultLineId, secondaryLineId, and companyId to be configured.");
470
520
  }
471
- const { data: lineData2, error: lineError2 } = await supabase.from(linesTable).select(`
472
- id,
473
- line_name,
474
- factory_id,
475
- factories!lines_factory_id_fkey(factory_name),
476
- company_id,
477
- companies!lines_company_id_fkey(company_name:name)
478
- `).eq("id", defaultLineId).maybeSingle();
479
- if (lineError2) throw lineError2;
480
- if (!lineData2) throw new Error(`Configured default line (${defaultLineId}) not found`);
481
- const { data: metricsData, error: metricsError } = await supabase.from(lineMetricsTable).select("*").in("line_id", [defaultLineId, secondaryLineId]).eq("shift_id", shiftId).eq("date", date);
482
- if (metricsError) throw metricsError;
483
- const { data: performanceData2, error: performanceError2 } = await supabase.from(metricsTable).select("efficiency").in("line_id", [defaultLineId, secondaryLineId]).eq("shift_id", shiftId).eq("date", date);
484
- if (performanceError2) throw performanceError2;
485
- const underperformingCount2 = performanceData2?.filter((w) => w.efficiency >= 10 && w.efficiency < 70).length || 0;
486
- const totalValidWorkspaces2 = performanceData2?.filter((w) => w.efficiency >= 10).length || 0;
521
+ const [lineResult, metricsResult, performanceResult] = await Promise.all([
522
+ // Get Line 1's info for general factory details
523
+ supabase.from(linesTable).select(`
524
+ id,
525
+ line_name,
526
+ factory_id,
527
+ factories!lines_factory_id_fkey(factory_name),
528
+ company_id,
529
+ companies!lines_company_id_fkey(company_name:name)
530
+ `).eq("id", defaultLineId).maybeSingle(),
531
+ // Get metrics from line_metrics table for both lines
532
+ supabase.from(lineMetricsTable).select("*").in("line_id", [defaultLineId, secondaryLineId]).eq("shift_id", shiftId).eq("date", date),
533
+ // Get performance data from the dynamic metrics table for both lines
534
+ supabase.from(metricsTable).select("efficiency").in("line_id", [defaultLineId, secondaryLineId]).eq("shift_id", shiftId).eq("date", date)
535
+ ]);
536
+ if (lineResult.error) throw lineResult.error;
537
+ if (!lineResult.data) throw new Error(`Configured default line (${defaultLineId}) not found`);
538
+ if (metricsResult.error) throw metricsResult.error;
539
+ if (performanceResult.error) throw performanceResult.error;
540
+ const lineData2 = lineResult.data;
541
+ const metricsData = metricsResult.data;
542
+ const performanceData2 = performanceResult.data;
543
+ const underperformingWorkspaces2 = memoizedEfficiencyFilter(performanceData2 || [], 10, 70);
544
+ const validWorkspaces2 = memoizedEfficiencyFilter(performanceData2 || [], 10);
545
+ const underperformingCount2 = underperformingWorkspaces2.length;
546
+ validWorkspaces2.length;
487
547
  const combinedMetrics = (metricsData || []).reduce((acc, m) => {
488
548
  acc.avg_efficiency += m.efficiency ?? 0;
489
549
  acc.current_output += m.current_output ?? 0;
@@ -503,13 +563,13 @@ var dashboardService = {
503
563
  shift_id: shiftId,
504
564
  date,
505
565
  metrics: {
506
- avg_efficiency: (performanceData2?.reduce((sum, m) => sum + (m.efficiency || 0), 0) || 0) / (totalValidWorkspaces2 || 1),
507
- // Use performance data for avg efficiency
566
+ avg_efficiency: memoizedAverageEfficiency(performanceData2 || [], 10),
567
+ // Use memoized calculation for efficiency
508
568
  avg_cycle_time: 0,
509
569
  // Needs calculation logic if required for factory view
510
570
  current_output: combinedMetrics.current_output,
511
571
  ideal_output: combinedMetrics.ideal_output,
512
- total_workspaces: 44,
572
+ total_workspaces: 0,
513
573
  // SRC ALIGNMENT: Use hardcoded 44 for factory view total_workspaces
514
574
  underperforming_workspaces: underperformingCount2,
515
575
  underperforming_workspace_names: [],
@@ -547,9 +607,11 @@ var dashboardService = {
547
607
  }
548
608
  const { data: performanceData, error: performanceError } = await supabase.from(metricsTable).select("efficiency").eq("line_id", lineId).eq("shift_id", shiftId).eq("date", date);
549
609
  if (performanceError) throw performanceError;
550
- const underperformingCount = performanceData?.filter((w) => w.efficiency >= 10 && w.efficiency < 70).length || 0;
551
- const totalValidWorkspaces = performanceData?.filter((w) => w.efficiency >= 10).length || 0;
552
- const avgEfficiencyFromPerf = (performanceData?.reduce((sum, m) => sum + (m.efficiency || 0), 0) || 0) / (totalValidWorkspaces || 1);
610
+ const underperformingWorkspaces = memoizedEfficiencyFilter(performanceData || [], 10, 70);
611
+ const validWorkspaces = memoizedEfficiencyFilter(performanceData || [], 10);
612
+ const underperformingCount = underperformingWorkspaces.length;
613
+ validWorkspaces.length;
614
+ const avgEfficiencyFromPerf = memoizedAverageEfficiency(performanceData || [], 10);
553
615
  const useFallbackMetrics = !metricsFromDb;
554
616
  let metricsForReturn;
555
617
  if (useFallbackMetrics) {
@@ -867,19 +929,26 @@ var dashboardService = {
867
929
  if (!defaultLineId || !companyId) {
868
930
  throw new Error("Factory View requires at least defaultLineId and companyId to be configured.");
869
931
  }
870
- const { data: line1Data, error: line1Error } = await supabase.from(linesTable).select("id, line_name, factory_id, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", defaultLineId).single();
871
- if (line1Error) throw line1Error;
872
- if (!line1Data) {
932
+ const lineIdsToQuery = [defaultLineId, secondaryLineId].filter((id3) => id3 !== void 0 && id3 !== null);
933
+ const [line1Result, metricsResult2, performanceResult2] = await Promise.all([
934
+ supabase.from(linesTable).select("id, line_name, factory_id, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", defaultLineId).single(),
935
+ supabase.from(lineMetricsTable).select("*").in("line_id", lineIdsToQuery).eq("shift_id", queryShiftId).eq("date", queryDate),
936
+ supabase.from(metricsTable).select("efficiency").in("line_id", lineIdsToQuery).eq("shift_id", queryShiftId).eq("date", queryDate)
937
+ ]);
938
+ if (line1Result.error) throw line1Result.error;
939
+ if (!line1Result.data) {
873
940
  throw new Error(`Default line ${defaultLineId} for Factory View not found.`);
874
941
  }
875
- const lineIdsToQuery = [defaultLineId, secondaryLineId].filter((id3) => id3 !== void 0 && id3 !== null);
876
- const { data: metricsData, error: metricsError2 } = await supabase.from(lineMetricsTable).select("*").in("line_id", lineIdsToQuery).eq("shift_id", queryShiftId).eq("date", queryDate);
877
- if (metricsError2) throw metricsError2;
878
- const { data: performanceData2, error: performanceError2 } = await supabase.from(metricsTable).select("efficiency").in("line_id", lineIdsToQuery).eq("shift_id", queryShiftId).eq("date", queryDate);
879
- if (performanceError2) throw performanceError2;
880
- const underperformingCount2 = performanceData2?.filter((w) => w.efficiency >= 10 && w.efficiency < 70).length || 0;
881
- const totalValidWorkspaces2 = performanceData2?.filter((w) => w.efficiency >= 10).length || 0;
882
- const avgEfficiencyFromPerf2 = (performanceData2?.reduce((sum, m) => sum + (m.efficiency || 0), 0) || 0) / (totalValidWorkspaces2 || 1);
942
+ if (metricsResult2.error) throw metricsResult2.error;
943
+ if (performanceResult2.error) throw performanceResult2.error;
944
+ const line1Data = line1Result.data;
945
+ const metricsData = metricsResult2.data;
946
+ const performanceData2 = performanceResult2.data;
947
+ const underperformingWorkspaces2 = memoizedEfficiencyFilter(performanceData2 || [], 10, 70);
948
+ const validWorkspaces2 = memoizedEfficiencyFilter(performanceData2 || [], 10);
949
+ const underperformingCount2 = underperformingWorkspaces2.length;
950
+ const totalValidWorkspaces2 = validWorkspaces2.length;
951
+ const avgEfficiencyFromPerf2 = memoizedAverageEfficiency(performanceData2 || [], 10);
883
952
  const initialAccumulator = {
884
953
  avg_cycle_time: 0,
885
954
  current_output: 0,
@@ -887,7 +956,8 @@ var dashboardService = {
887
956
  line_threshold: 0,
888
957
  threshold_pph: 0,
889
958
  total_workspaces: 0,
890
- output_array: []
959
+ output_array: [],
960
+ outputArrays: []
891
961
  };
892
962
  const combinedMetricsData = (metricsData || []).reduce((acc, m) => {
893
963
  acc.avg_cycle_time += m.avg_cycle_time ?? 0;
@@ -897,14 +967,7 @@ var dashboardService = {
897
967
  acc.threshold_pph += m.threshold_pph ?? 0;
898
968
  acc.total_workspaces += m.total_workspaces ?? 0;
899
969
  if (m.output_array && m.output_array.length > 0) {
900
- const currentMOutputArray = m.output_array;
901
- if (!acc.output_array || acc.output_array.length === 0) acc.output_array = [...currentMOutputArray];
902
- else {
903
- acc.output_array = acc.output_array.map((val, i) => val + (currentMOutputArray[i] ?? 0));
904
- if (currentMOutputArray.length > acc.output_array.length) {
905
- acc.output_array.push(...currentMOutputArray.slice(acc.output_array.length));
906
- }
907
- }
970
+ acc.outputArrays.push(m.output_array);
908
971
  }
909
972
  return acc;
910
973
  }, initialAccumulator);
@@ -925,7 +988,7 @@ var dashboardService = {
925
988
  avg_cycle_time: combinedMetricsData.avg_cycle_time / numLines,
926
989
  current_output: combinedMetricsData.current_output,
927
990
  ideal_output: combinedMetricsData.ideal_output,
928
- total_workspaces: combinedMetricsData.total_workspaces || 44,
991
+ total_workspaces: combinedMetricsData.total_workspaces || 0,
929
992
  // Use combined or default
930
993
  underperforming_workspaces: underperformingCount2,
931
994
  line_threshold: combinedMetricsData.line_threshold,
@@ -933,7 +996,7 @@ var dashboardService = {
933
996
  shift_start: metricsData?.[0]?.shift_start || shiftConfig.dayShift?.startTime || "06:00",
934
997
  shift_end: metricsData?.[0]?.shift_end || shiftConfig.dayShift?.endTime || "18:00",
935
998
  last_updated: (/* @__PURE__ */ new Date()).toISOString(),
936
- output_array: combinedMetricsData.output_array,
999
+ output_array: combinedMetricsData.outputArrays.length > 0 ? memoizedOutputArrayAggregation(combinedMetricsData.outputArrays) : [],
937
1000
  underperforming_workspace_names: [],
938
1001
  underperforming_workspace_uuids: [],
939
1002
  poorest_performing_workspaces: []
@@ -943,18 +1006,25 @@ var dashboardService = {
943
1006
  if (!companyId) {
944
1007
  throw new Error("Company ID must be configured for detailed line requests.");
945
1008
  }
946
- const { data: lineData, error: lineError } = await supabase.from(linesTable).select("id, line_name, factory_id, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", lineIdToQuery).single();
947
- if (lineError) throw lineError;
948
- if (!lineData) {
1009
+ const [lineResult, metricsResult, performanceResult] = await Promise.all([
1010
+ supabase.from(linesTable).select("id, line_name, factory_id, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", lineIdToQuery).single(),
1011
+ supabase.from(lineMetricsTable).select("*").eq("line_id", lineIdToQuery).eq("shift_id", queryShiftId).eq("date", queryDate).maybeSingle(),
1012
+ supabase.from(metricsTable).select("efficiency").eq("line_id", lineIdToQuery).eq("shift_id", queryShiftId).eq("date", queryDate)
1013
+ ]);
1014
+ if (lineResult.error) throw lineResult.error;
1015
+ if (!lineResult.data) {
949
1016
  throw new Error(`Line ${lineIdToQuery} not found.`);
950
1017
  }
951
- const { data: metrics2, error: metricsError } = await supabase.from(lineMetricsTable).select("*").eq("line_id", lineIdToQuery).eq("shift_id", queryShiftId).eq("date", queryDate).maybeSingle();
952
- if (metricsError) throw metricsError;
953
- const { data: performanceData, error: performanceError } = await supabase.from(metricsTable).select("efficiency").eq("line_id", lineIdToQuery).eq("shift_id", queryShiftId).eq("date", queryDate);
954
- if (performanceError) throw performanceError;
955
- const underperformingCount = performanceData?.filter((w) => w.efficiency >= 10 && w.efficiency < 70).length || 0;
956
- const totalValidWorkspaces = performanceData?.filter((w) => w.efficiency >= 10).length || 0;
957
- const avgEfficiencyFromPerf = (performanceData?.reduce((sum, m) => sum + (m.efficiency || 0), 0) || 0) / (totalValidWorkspaces || 1);
1018
+ if (metricsResult.error) throw metricsResult.error;
1019
+ if (performanceResult.error) throw performanceResult.error;
1020
+ const lineData = lineResult.data;
1021
+ const metrics2 = metricsResult.data;
1022
+ const performanceData = performanceResult.data;
1023
+ const underperformingWorkspaces = memoizedEfficiencyFilter(performanceData || [], 10, 70);
1024
+ const validWorkspaces = memoizedEfficiencyFilter(performanceData || [], 10);
1025
+ const underperformingCount = underperformingWorkspaces.length;
1026
+ const totalValidWorkspaces = validWorkspaces.length;
1027
+ const avgEfficiencyFromPerf = memoizedAverageEfficiency(performanceData || [], 10);
958
1028
  return {
959
1029
  line_id: lineData.id,
960
1030
  line_name: lineData.line_name,
@@ -1641,6 +1711,128 @@ var workspaceService = {
1641
1711
  }
1642
1712
  };
1643
1713
 
1714
+ // src/lib/services/skuService.ts
1715
+ var getTable4 = (dbConfig, tableName) => {
1716
+ const globalConfig = _getDashboardConfigInstance();
1717
+ const defaults2 = globalConfig?.databaseConfig?.tables;
1718
+ const userValue = dbConfig?.tables?.[tableName];
1719
+ const hardcodedDefaults = {
1720
+ skus: "skus"
1721
+ };
1722
+ return userValue ?? defaults2?.[tableName] ?? hardcodedDefaults[tableName];
1723
+ };
1724
+ var skuService = {
1725
+ /**
1726
+ * Fetch all active SKUs for a company
1727
+ */
1728
+ async getSKUs(companyId) {
1729
+ const supabase = _getSupabaseInstance();
1730
+ if (!supabase) throw new Error("Supabase client not initialized");
1731
+ const config = _getDashboardConfigInstance();
1732
+ const dbConfig = config?.databaseConfig;
1733
+ const skusTable = getTable4(dbConfig, "skus");
1734
+ const { data, error } = await supabase.from(skusTable).select("*").eq("company_id", companyId).eq("is_active", true).order("created_at", { ascending: false });
1735
+ if (error) {
1736
+ console.error(`Error fetching SKUs from ${skusTable}:`, error);
1737
+ throw error;
1738
+ }
1739
+ return data || [];
1740
+ },
1741
+ /**
1742
+ * Get a single SKU by ID
1743
+ */
1744
+ async getSKU(skuId) {
1745
+ const supabase = _getSupabaseInstance();
1746
+ if (!supabase) throw new Error("Supabase client not initialized");
1747
+ const config = _getDashboardConfigInstance();
1748
+ const dbConfig = config?.databaseConfig;
1749
+ const skusTable = getTable4(dbConfig, "skus");
1750
+ const { data, error } = await supabase.from(skusTable).select("*").eq("id", skuId).single();
1751
+ if (error) {
1752
+ console.error(`Error fetching SKU from ${skusTable}:`, error);
1753
+ throw error;
1754
+ }
1755
+ return data;
1756
+ },
1757
+ /**
1758
+ * Create a new SKU
1759
+ */
1760
+ async createSKU(skuData) {
1761
+ const supabase = _getSupabaseInstance();
1762
+ if (!supabase) throw new Error("Supabase client not initialized");
1763
+ const config = _getDashboardConfigInstance();
1764
+ const dbConfig = config?.databaseConfig;
1765
+ const skusTable = getTable4(dbConfig, "skus");
1766
+ const { data, error } = await supabase.from(skusTable).insert([{
1767
+ ...skuData,
1768
+ attributes: skuData.attributes || {},
1769
+ is_active: skuData.is_active ?? true
1770
+ }]).select("*").single();
1771
+ if (error) {
1772
+ console.error(`Error creating SKU in ${skusTable}:`, error);
1773
+ throw error;
1774
+ }
1775
+ return data;
1776
+ },
1777
+ /**
1778
+ * Update an existing SKU
1779
+ */
1780
+ async updateSKU(skuId, updates) {
1781
+ const supabase = _getSupabaseInstance();
1782
+ if (!supabase) throw new Error("Supabase client not initialized");
1783
+ const config = _getDashboardConfigInstance();
1784
+ const dbConfig = config?.databaseConfig;
1785
+ const skusTable = getTable4(dbConfig, "skus");
1786
+ const { data, error } = await supabase.from(skusTable).update({
1787
+ ...updates,
1788
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
1789
+ }).eq("id", skuId).select("*").single();
1790
+ if (error) {
1791
+ console.error(`Error updating SKU in ${skusTable}:`, error);
1792
+ throw error;
1793
+ }
1794
+ return data;
1795
+ },
1796
+ /**
1797
+ * Soft delete a SKU (set is_active to false)
1798
+ */
1799
+ async deleteSKU(skuId) {
1800
+ const supabase = _getSupabaseInstance();
1801
+ if (!supabase) throw new Error("Supabase client not initialized");
1802
+ const config = _getDashboardConfigInstance();
1803
+ const dbConfig = config?.databaseConfig;
1804
+ const skusTable = getTable4(dbConfig, "skus");
1805
+ const { error } = await supabase.from(skusTable).update({
1806
+ is_active: false,
1807
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
1808
+ }).eq("id", skuId);
1809
+ if (error) {
1810
+ console.error(`Error deleting SKU from ${skusTable}:`, error);
1811
+ throw error;
1812
+ }
1813
+ },
1814
+ /**
1815
+ * Check if a SKU ID already exists for a company
1816
+ */
1817
+ async checkSKUExists(companyId, skuId, excludeId) {
1818
+ const supabase = _getSupabaseInstance();
1819
+ if (!supabase) throw new Error("Supabase client not initialized");
1820
+ const config = _getDashboardConfigInstance();
1821
+ const dbConfig = config?.databaseConfig;
1822
+ const skusTable = getTable4(dbConfig, "skus");
1823
+ let query = supabase.from(skusTable).select("id").eq("company_id", companyId).eq("sku_id", skuId).eq("is_active", true);
1824
+ if (excludeId) {
1825
+ query = query.neq("id", excludeId);
1826
+ }
1827
+ const { data, error } = await query;
1828
+ if (error) {
1829
+ console.error(`Error checking SKU existence in ${skusTable}:`, error);
1830
+ throw error;
1831
+ }
1832
+ return data && data.length > 0 || false;
1833
+ }
1834
+ };
1835
+
1644
1836
  // src/lib/services/authCoreService.ts
1645
1837
  var AUTH_ERROR_MESSAGES = {
1646
1838
  "Invalid login credentials": "Invalid email or password",
@@ -2070,6 +2262,349 @@ async function deleteThread(threadId) {
2070
2262
  const { error } = await supabase.schema("ai").from("chat_threads").delete().eq("id", threadId);
2071
2263
  if (error) throw error;
2072
2264
  }
2265
+
2266
+ // src/lib/services/cacheService.ts
2267
+ var CacheService = class {
2268
+ constructor() {
2269
+ this.memoryCache = /* @__PURE__ */ new Map();
2270
+ this.DEFAULT_DURATION = 5 * 60 * 1e3;
2271
+ }
2272
+ // 5 minutes
2273
+ /**
2274
+ * Generate a cache key from multiple parts
2275
+ */
2276
+ generateKey(...parts) {
2277
+ return parts.filter((p) => p !== void 0 && p !== null).join(":");
2278
+ }
2279
+ /**
2280
+ * Get item from cache
2281
+ */
2282
+ get(key, options) {
2283
+ const storage = options?.storage || "memory";
2284
+ try {
2285
+ let cacheItem = null;
2286
+ if (storage === "memory") {
2287
+ cacheItem = this.memoryCache.get(key) || null;
2288
+ } else if (storage === "localStorage" || storage === "sessionStorage") {
2289
+ const stored = window[storage].getItem(key);
2290
+ if (stored) {
2291
+ cacheItem = JSON.parse(stored);
2292
+ }
2293
+ }
2294
+ if (!cacheItem) {
2295
+ return null;
2296
+ }
2297
+ if (Date.now() > cacheItem.expiresAt) {
2298
+ this.delete(key, options);
2299
+ return null;
2300
+ }
2301
+ return cacheItem.data;
2302
+ } catch (error) {
2303
+ console.error(`Error getting cache item ${key}:`, error);
2304
+ return null;
2305
+ }
2306
+ }
2307
+ /**
2308
+ * Set item in cache
2309
+ */
2310
+ set(key, data, options) {
2311
+ const storage = options?.storage || "memory";
2312
+ const duration = options?.duration || this.DEFAULT_DURATION;
2313
+ const cacheItem = {
2314
+ data,
2315
+ timestamp: Date.now(),
2316
+ expiresAt: Date.now() + duration
2317
+ };
2318
+ try {
2319
+ if (storage === "memory") {
2320
+ this.memoryCache.set(key, cacheItem);
2321
+ if (this.memoryCache.size > 100) {
2322
+ const firstKey = this.memoryCache.keys().next().value;
2323
+ if (firstKey) {
2324
+ this.memoryCache.delete(firstKey);
2325
+ }
2326
+ }
2327
+ } else if (storage === "localStorage" || storage === "sessionStorage") {
2328
+ window[storage].setItem(key, JSON.stringify(cacheItem));
2329
+ }
2330
+ } catch (error) {
2331
+ console.error(`Error setting cache item ${key}:`, error);
2332
+ }
2333
+ }
2334
+ /**
2335
+ * Delete item from cache
2336
+ */
2337
+ delete(key, options) {
2338
+ const storage = options?.storage || "memory";
2339
+ try {
2340
+ if (storage === "memory") {
2341
+ this.memoryCache.delete(key);
2342
+ } else if (storage === "localStorage" || storage === "sessionStorage") {
2343
+ window[storage].removeItem(key);
2344
+ }
2345
+ } catch (error) {
2346
+ console.error(`Error deleting cache item ${key}:`, error);
2347
+ }
2348
+ }
2349
+ /**
2350
+ * Clear all items from cache
2351
+ */
2352
+ clear(options) {
2353
+ const storage = options?.storage || "memory";
2354
+ try {
2355
+ if (storage === "memory") {
2356
+ this.memoryCache.clear();
2357
+ } else if (storage === "localStorage" || storage === "sessionStorage") {
2358
+ const keys = Object.keys(window[storage]);
2359
+ keys.forEach((key) => {
2360
+ try {
2361
+ const item = window[storage].getItem(key);
2362
+ if (item) {
2363
+ const parsed = JSON.parse(item);
2364
+ if (parsed.timestamp && parsed.expiresAt && parsed.data !== void 0) {
2365
+ window[storage].removeItem(key);
2366
+ }
2367
+ }
2368
+ } catch {
2369
+ }
2370
+ });
2371
+ }
2372
+ } catch (error) {
2373
+ console.error("Error clearing cache:", error);
2374
+ }
2375
+ }
2376
+ /**
2377
+ * Get or set item in cache with a factory function
2378
+ */
2379
+ async getOrSet(key, factory, options) {
2380
+ const cached = this.get(key, options);
2381
+ if (cached !== null) {
2382
+ return cached;
2383
+ }
2384
+ const data = await factory();
2385
+ this.set(key, data, options);
2386
+ return data;
2387
+ }
2388
+ /**
2389
+ * Invalidate cache entries matching a pattern
2390
+ */
2391
+ invalidatePattern(pattern, options) {
2392
+ const storage = options?.storage || "memory";
2393
+ const regex = typeof pattern === "string" ? new RegExp(pattern) : pattern;
2394
+ try {
2395
+ if (storage === "memory") {
2396
+ const keysToDelete = [];
2397
+ this.memoryCache.forEach((_, key) => {
2398
+ if (regex.test(key)) {
2399
+ keysToDelete.push(key);
2400
+ }
2401
+ });
2402
+ keysToDelete.forEach((key) => this.memoryCache.delete(key));
2403
+ } else if (storage === "localStorage" || storage === "sessionStorage") {
2404
+ const keys = Object.keys(window[storage]);
2405
+ keys.forEach((key) => {
2406
+ if (regex.test(key)) {
2407
+ window[storage].removeItem(key);
2408
+ }
2409
+ });
2410
+ }
2411
+ } catch (error) {
2412
+ console.error("Error invalidating cache pattern:", error);
2413
+ }
2414
+ }
2415
+ /**
2416
+ * Clean up expired items
2417
+ */
2418
+ cleanup(options) {
2419
+ const storage = options?.storage || "memory";
2420
+ const now2 = Date.now();
2421
+ try {
2422
+ if (storage === "memory") {
2423
+ const keysToDelete = [];
2424
+ this.memoryCache.forEach((item, key) => {
2425
+ if (now2 > item.expiresAt) {
2426
+ keysToDelete.push(key);
2427
+ }
2428
+ });
2429
+ keysToDelete.forEach((key) => this.memoryCache.delete(key));
2430
+ } else if (storage === "localStorage" || storage === "sessionStorage") {
2431
+ const keys = Object.keys(window[storage]);
2432
+ keys.forEach((key) => {
2433
+ try {
2434
+ const item = window[storage].getItem(key);
2435
+ if (item) {
2436
+ const parsed = JSON.parse(item);
2437
+ if (parsed.expiresAt && now2 > parsed.expiresAt) {
2438
+ window[storage].removeItem(key);
2439
+ }
2440
+ }
2441
+ } catch {
2442
+ }
2443
+ });
2444
+ }
2445
+ } catch (error) {
2446
+ console.error("Error cleaning up cache:", error);
2447
+ }
2448
+ }
2449
+ };
2450
+ var cacheService = new CacheService();
2451
+ if (typeof window !== "undefined") {
2452
+ setInterval(() => {
2453
+ cacheService.cleanup({ storage: "localStorage" });
2454
+ cacheService.cleanup({ storage: "sessionStorage" });
2455
+ cacheService.cleanup({ storage: "memory" });
2456
+ }, 60 * 1e3);
2457
+ }
2458
+
2459
+ // src/lib/services/subscriptionManager.ts
2460
+ var SubscriptionManager = class {
2461
+ constructor(supabase) {
2462
+ this.subscriptions = /* @__PURE__ */ new Map();
2463
+ this.debounceTimers = /* @__PURE__ */ new Map();
2464
+ this.supabase = supabase;
2465
+ }
2466
+ /**
2467
+ * Generate a unique key for a subscription configuration
2468
+ */
2469
+ generateKey(config) {
2470
+ const { table, schema = "public", event = "*", filter: filter2 = "" } = config;
2471
+ return `${schema}:${table}:${event}:${filter2}`;
2472
+ }
2473
+ /**
2474
+ * Subscribe to real-time changes with automatic deduplication
2475
+ */
2476
+ subscribe(config) {
2477
+ const key = this.generateKey(config);
2478
+ const existing = this.subscriptions.get(key);
2479
+ if (existing) {
2480
+ existing.configs.push(config);
2481
+ existing.refCount++;
2482
+ console.log(`[SubscriptionManager] Reusing existing subscription for ${key}, refCount: ${existing.refCount}`);
2483
+ return () => this.unsubscribe(key, config.callback);
2484
+ }
2485
+ const channelName = `subscription-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
2486
+ const channel = this.supabase.channel(channelName);
2487
+ channel.on(
2488
+ "postgres_changes",
2489
+ {
2490
+ event: config.event || "*",
2491
+ schema: config.schema || "public",
2492
+ table: config.table,
2493
+ ...config.filter && { filter: config.filter }
2494
+ },
2495
+ (payload) => {
2496
+ this.debouncedCallback(key, () => {
2497
+ const subscription = this.subscriptions.get(key);
2498
+ if (subscription) {
2499
+ subscription.configs.forEach((cfg) => {
2500
+ try {
2501
+ cfg.callback(payload);
2502
+ } catch (error) {
2503
+ console.error("[SubscriptionManager] Error in callback:", error);
2504
+ }
2505
+ });
2506
+ }
2507
+ });
2508
+ }
2509
+ );
2510
+ channel.subscribe((status) => {
2511
+ console.log(`[SubscriptionManager] Subscription status for ${key}:`, status);
2512
+ });
2513
+ this.subscriptions.set(key, {
2514
+ channel,
2515
+ configs: [config],
2516
+ refCount: 1
2517
+ });
2518
+ console.log(`[SubscriptionManager] Created new subscription for ${key}`);
2519
+ return () => this.unsubscribe(key, config.callback);
2520
+ }
2521
+ /**
2522
+ * Debounce callbacks to prevent excessive updates
2523
+ */
2524
+ debouncedCallback(key, callback, delay2 = 500) {
2525
+ const existingTimer = this.debounceTimers.get(key);
2526
+ if (existingTimer) {
2527
+ clearTimeout(existingTimer);
2528
+ }
2529
+ const timer = setTimeout(() => {
2530
+ callback();
2531
+ this.debounceTimers.delete(key);
2532
+ }, delay2);
2533
+ this.debounceTimers.set(key, timer);
2534
+ }
2535
+ /**
2536
+ * Unsubscribe from a specific subscription
2537
+ */
2538
+ unsubscribe(key, callback) {
2539
+ const subscription = this.subscriptions.get(key);
2540
+ if (!subscription) {
2541
+ console.warn(`[SubscriptionManager] No subscription found for key: ${key}`);
2542
+ return;
2543
+ }
2544
+ subscription.configs = subscription.configs.filter((cfg) => cfg.callback !== callback);
2545
+ subscription.refCount--;
2546
+ console.log(`[SubscriptionManager] Unsubscribed from ${key}, refCount: ${subscription.refCount}`);
2547
+ if (subscription.refCount <= 0) {
2548
+ this.supabase.removeChannel(subscription.channel);
2549
+ this.subscriptions.delete(key);
2550
+ const timer = this.debounceTimers.get(key);
2551
+ if (timer) {
2552
+ clearTimeout(timer);
2553
+ this.debounceTimers.delete(key);
2554
+ }
2555
+ console.log(`[SubscriptionManager] Removed subscription for ${key}`);
2556
+ }
2557
+ }
2558
+ /**
2559
+ * Subscribe to multiple tables with a single callback
2560
+ */
2561
+ subscribeMultiple(configs, callback) {
2562
+ const unsubscribeFunctions = configs.map(
2563
+ (config) => this.subscribe({ ...config, callback })
2564
+ );
2565
+ return () => {
2566
+ unsubscribeFunctions.forEach((fn) => fn());
2567
+ };
2568
+ }
2569
+ /**
2570
+ * Get current subscription statistics
2571
+ */
2572
+ getStats() {
2573
+ let totalCallbacks = 0;
2574
+ this.subscriptions.forEach((sub) => {
2575
+ totalCallbacks += sub.configs.length;
2576
+ });
2577
+ return {
2578
+ totalSubscriptions: this.subscriptions.size,
2579
+ totalCallbacks
2580
+ };
2581
+ }
2582
+ /**
2583
+ * Clean up all subscriptions
2584
+ */
2585
+ cleanup() {
2586
+ this.debounceTimers.forEach((timer) => clearTimeout(timer));
2587
+ this.debounceTimers.clear();
2588
+ this.subscriptions.forEach((subscription) => {
2589
+ this.supabase.removeChannel(subscription.channel);
2590
+ });
2591
+ this.subscriptions.clear();
2592
+ console.log("[SubscriptionManager] All subscriptions cleaned up");
2593
+ }
2594
+ };
2595
+ var managerInstance = null;
2596
+ function getSubscriptionManager(supabase) {
2597
+ if (!managerInstance) {
2598
+ managerInstance = new SubscriptionManager(supabase);
2599
+ }
2600
+ return managerInstance;
2601
+ }
2602
+ function resetSubscriptionManager() {
2603
+ if (managerInstance) {
2604
+ managerInstance.cleanup();
2605
+ managerInstance = null;
2606
+ }
2607
+ }
2073
2608
  var AuthContext = createContext({
2074
2609
  session: null,
2075
2610
  user: null,
@@ -2289,6 +2824,36 @@ var useSupabase = () => {
2289
2824
  }
2290
2825
  return context.supabase;
2291
2826
  };
2827
+ var SubscriptionManagerContext = createContext({
2828
+ subscriptionManager: null
2829
+ });
2830
+ var SubscriptionManagerProvider = ({ children }) => {
2831
+ const supabase = useSupabase();
2832
+ const subscriptionManager = useMemo(() => {
2833
+ if (!supabase) return null;
2834
+ return getSubscriptionManager(supabase);
2835
+ }, [supabase]);
2836
+ useEffect(() => {
2837
+ return () => {
2838
+ if (subscriptionManager) {
2839
+ console.log("[SubscriptionManagerProvider] Cleaning up subscriptions");
2840
+ subscriptionManager.cleanup();
2841
+ }
2842
+ };
2843
+ }, [subscriptionManager]);
2844
+ return /* @__PURE__ */ jsx(SubscriptionManagerContext.Provider, { value: { subscriptionManager }, children });
2845
+ };
2846
+ var useSubscriptionManager = () => {
2847
+ const { subscriptionManager } = useContext(SubscriptionManagerContext);
2848
+ if (!subscriptionManager) {
2849
+ throw new Error("useSubscriptionManager must be used within a SubscriptionManagerProvider");
2850
+ }
2851
+ return subscriptionManager;
2852
+ };
2853
+ var useSubscriptionManagerSafe = () => {
2854
+ const { subscriptionManager } = useContext(SubscriptionManagerContext);
2855
+ return subscriptionManager;
2856
+ };
2292
2857
  var DEFAULT_COMPANY_ID = "default-company-id";
2293
2858
  var useWorkspaceMetrics = (workspaceId) => {
2294
2859
  const supabase = useSupabase();
@@ -2545,7 +3110,7 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
2545
3110
  const defaultTimezone = dateTimeConfig.defaultTimezone;
2546
3111
  const workspaceMetricsBaseTable = databaseConfig.tables?.workspaces ?? "workspace_metrics";
2547
3112
  const workspaceActionsTable = databaseConfig.tables?.actions ?? "workspace_actions";
2548
- const fetchMetrics = useCallback(async () => {
3113
+ const fetchMetrics = useCallback(async (skipCache = false) => {
2549
3114
  if (!workspaceId || isFetchingRef.current) return;
2550
3115
  try {
2551
3116
  isFetchingRef.current = true;
@@ -2554,6 +3119,28 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
2554
3119
  const queryShiftId = shiftId !== void 0 ? shiftId : currentShift.shiftId;
2555
3120
  console.log("[useWorkspaceDetailedMetrics] Using shift ID:", queryShiftId, "from input shift:", shiftId);
2556
3121
  console.log("[useWorkspaceDetailedMetrics] Using date:", queryDate, "from input date:", date);
3122
+ const cacheKey = cacheService.generateKey(
3123
+ "workspace-detailed-metrics",
3124
+ workspaceId,
3125
+ queryDate,
3126
+ queryShiftId,
3127
+ companyId
3128
+ );
3129
+ if (!skipCache) {
3130
+ const cachedData = cacheService.get(cacheKey, {
3131
+ storage: "memory",
3132
+ duration: 5 * 60 * 1e3
3133
+ // 5 minutes
3134
+ });
3135
+ if (cachedData) {
3136
+ console.log("[useWorkspaceDetailedMetrics] Using cached data for:", cacheKey);
3137
+ setMetrics(cachedData);
3138
+ setIsLoading(false);
3139
+ updateQueueRef.current = false;
3140
+ isFetchingRef.current = false;
3141
+ return;
3142
+ }
3143
+ }
2557
3144
  console.log(`[useWorkspaceDetailedMetrics] Querying ${metricsTable} for workspace: ${workspaceId}, date: ${queryDate}, shift: ${queryShiftId}`);
2558
3145
  const { data, error: fetchError } = await supabase.from(metricsTable).select("*").eq("workspace_id", workspaceId).eq("date", queryDate).eq("shift_id", queryShiftId).maybeSingle();
2559
3146
  if (fetchError) throw fetchError;
@@ -2656,6 +3243,18 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
2656
3243
  setIsLoading(false);
2657
3244
  updateQueueRef.current = false;
2658
3245
  isFetchingRef.current = false;
3246
+ const fallbackCacheKey = cacheService.generateKey(
3247
+ "workspace-detailed-metrics",
3248
+ workspaceId,
3249
+ recentData.date,
3250
+ recentData.shift_id,
3251
+ companyId
3252
+ );
3253
+ cacheService.set(fallbackCacheKey, transformedData2, {
3254
+ storage: "memory",
3255
+ duration: 2 * 60 * 1e3
3256
+ // 2 minutes for fallback data
3257
+ });
2659
3258
  return;
2660
3259
  } else {
2661
3260
  console.warn("[useWorkspaceDetailedMetrics] No data found for workspace:", workspaceId, "at all");
@@ -2769,6 +3368,11 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
2769
3368
  ...data.sop_check !== void 0 && { sop_check: data.sop_check }
2770
3369
  };
2771
3370
  setMetrics(transformedData);
3371
+ cacheService.set(cacheKey, transformedData, {
3372
+ storage: "memory",
3373
+ duration: 5 * 60 * 1e3
3374
+ // 5 minutes
3375
+ });
2772
3376
  } catch (err) {
2773
3377
  console.error("Error fetching workspace metrics:", err);
2774
3378
  setError({ message: err.message, code: err.code });
@@ -2803,7 +3407,7 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
2803
3407
  },
2804
3408
  async (payload) => {
2805
3409
  console.log(`Received ${metricsTablePrefix} update:`, payload);
2806
- await fetchMetrics();
3410
+ await fetchMetrics(true);
2807
3411
  }
2808
3412
  ).subscribe((status) => {
2809
3413
  console.log(`Workspace detailed metrics subscription status:`, status);
@@ -2837,6 +3441,14 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
2837
3441
  matches: payloadData?.date === operationalDate && payloadData?.shift_id === queryShiftId
2838
3442
  });
2839
3443
  if (payloadData?.date === operationalDate && payloadData?.shift_id === queryShiftId) {
3444
+ const cacheKey = cacheService.generateKey(
3445
+ "workspace-detailed-metrics",
3446
+ workspaceId,
3447
+ operationalDate,
3448
+ queryShiftId,
3449
+ companyId
3450
+ );
3451
+ cacheService.delete(cacheKey, { storage: "memory" });
2840
3452
  queueUpdate();
2841
3453
  }
2842
3454
  }
@@ -2862,6 +3474,14 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
2862
3474
  matches: payloadData?.date === operationalDate && payloadData?.shift_id === queryShiftId
2863
3475
  });
2864
3476
  if (payloadData?.date === operationalDate && payloadData?.shift_id === queryShiftId) {
3477
+ const cacheKey = cacheService.generateKey(
3478
+ "workspace-detailed-metrics",
3479
+ workspaceId,
3480
+ operationalDate,
3481
+ queryShiftId,
3482
+ companyId
3483
+ );
3484
+ cacheService.delete(cacheKey, { storage: "memory" });
2865
3485
  queueUpdate();
2866
3486
  }
2867
3487
  }
@@ -2887,6 +3507,14 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
2887
3507
  matches: payloadData?.date === operationalDate && payloadData?.shift_id === queryShiftId
2888
3508
  });
2889
3509
  if (payloadData?.date === operationalDate && payloadData?.shift_id === queryShiftId) {
3510
+ const cacheKey = cacheService.generateKey(
3511
+ "workspace-detailed-metrics",
3512
+ workspaceId,
3513
+ operationalDate,
3514
+ queryShiftId,
3515
+ companyId
3516
+ );
3517
+ cacheService.delete(cacheKey, { storage: "memory" });
2890
3518
  queueUpdate();
2891
3519
  }
2892
3520
  }
@@ -2913,7 +3541,8 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
2913
3541
  metrics: metrics2,
2914
3542
  isLoading,
2915
3543
  error,
2916
- refetch: fetchMetrics
3544
+ refetch: () => fetchMetrics(true)
3545
+ // Force refresh without cache
2917
3546
  };
2918
3547
  };
2919
3548
  var useLineWorkspaceMetrics = (lineId, options) => {
@@ -5130,19 +5759,39 @@ var useActiveBreaks = (lineIds) => {
5130
5759
  let breaks = [];
5131
5760
  if (activeShift.breaks) {
5132
5761
  if (Array.isArray(activeShift.breaks)) {
5133
- breaks = activeShift.breaks.map((breakItem) => ({
5134
- startTime: breakItem.start || breakItem.startTime || "00:00",
5135
- endTime: breakItem.end || breakItem.endTime || "00:00",
5136
- duration: breakItem.duration || 0,
5137
- remarks: breakItem.remarks || breakItem.name || ""
5138
- }));
5762
+ breaks = activeShift.breaks.map((breakItem) => {
5763
+ const startTime = breakItem.start || breakItem.startTime || "00:00";
5764
+ const endTime = breakItem.end || breakItem.endTime || "00:00";
5765
+ let duration = breakItem.duration || 0;
5766
+ if (!duration || duration === 0) {
5767
+ const startMinutes = parseTimeToMinutes2(startTime);
5768
+ const endMinutes = parseTimeToMinutes2(endTime);
5769
+ duration = endMinutes < startMinutes ? endMinutes + 24 * 60 - startMinutes : endMinutes - startMinutes;
5770
+ }
5771
+ return {
5772
+ startTime,
5773
+ endTime,
5774
+ duration,
5775
+ remarks: breakItem.remarks || breakItem.name || ""
5776
+ };
5777
+ });
5139
5778
  } else if (activeShift.breaks.breaks && Array.isArray(activeShift.breaks.breaks)) {
5140
- breaks = activeShift.breaks.breaks.map((breakItem) => ({
5141
- startTime: breakItem.start || breakItem.startTime || "00:00",
5142
- endTime: breakItem.end || breakItem.endTime || "00:00",
5143
- duration: breakItem.duration || 0,
5144
- remarks: breakItem.remarks || breakItem.name || ""
5145
- }));
5779
+ breaks = activeShift.breaks.breaks.map((breakItem) => {
5780
+ const startTime = breakItem.start || breakItem.startTime || "00:00";
5781
+ const endTime = breakItem.end || breakItem.endTime || "00:00";
5782
+ let duration = breakItem.duration || 0;
5783
+ if (!duration || duration === 0) {
5784
+ const startMinutes = parseTimeToMinutes2(startTime);
5785
+ const endMinutes = parseTimeToMinutes2(endTime);
5786
+ duration = endMinutes < startMinutes ? endMinutes + 24 * 60 - startMinutes : endMinutes - startMinutes;
5787
+ }
5788
+ return {
5789
+ startTime,
5790
+ endTime,
5791
+ duration,
5792
+ remarks: breakItem.remarks || breakItem.name || ""
5793
+ };
5794
+ });
5146
5795
  }
5147
5796
  }
5148
5797
  for (const breakItem of breaks) {
@@ -5204,12 +5853,32 @@ var useAllWorkspaceMetrics = (options) => {
5204
5853
  return `${metricsTablePrefix}_${companyId.replace(/-/g, "_")}`;
5205
5854
  }, [entityConfig.companyId]);
5206
5855
  const schema = databaseConfig.schema ?? "public";
5207
- const fetchWorkspaceMetrics = useCallback(async () => {
5856
+ const fetchWorkspaceMetrics = useCallback(async (skipCache = false) => {
5208
5857
  if (!initialized) {
5209
5858
  setLoading(true);
5210
5859
  }
5211
5860
  setError(null);
5212
5861
  try {
5862
+ const cacheKey = cacheService.generateKey(
5863
+ "all-workspace-metrics",
5864
+ entityConfig.companyId,
5865
+ queryDate,
5866
+ queryShiftId
5867
+ );
5868
+ if (!skipCache && !loading) {
5869
+ const cachedData = cacheService.get(cacheKey, {
5870
+ storage: "memory",
5871
+ duration: 5 * 60 * 1e3
5872
+ // 5 minutes
5873
+ });
5874
+ if (cachedData) {
5875
+ console.log("[useAllWorkspaceMetrics] Using cached data for:", cacheKey);
5876
+ setWorkspaces(cachedData);
5877
+ setInitialized(true);
5878
+ setLoading(false);
5879
+ return;
5880
+ }
5881
+ }
5213
5882
  console.log("Fetching all workspace metrics with params:", {
5214
5883
  queryDate,
5215
5884
  queryShiftId,
@@ -5246,6 +5915,11 @@ var useAllWorkspaceMetrics = (options) => {
5246
5915
  }));
5247
5916
  setWorkspaces(transformedData);
5248
5917
  setInitialized(true);
5918
+ cacheService.set(cacheKey, transformedData, {
5919
+ storage: "memory",
5920
+ duration: 5 * 60 * 1e3
5921
+ // 5 minutes
5922
+ });
5249
5923
  } catch (err) {
5250
5924
  console.error("Error fetching all workspace metrics:", err);
5251
5925
  setError({ message: err.message, code: err.code || "FETCH_ERROR" });
@@ -5270,7 +5944,14 @@ var useAllWorkspaceMetrics = (options) => {
5270
5944
  },
5271
5945
  async (payload) => {
5272
5946
  console.log("All workspace metrics update received:", payload);
5273
- await fetchWorkspaceMetrics();
5947
+ const cacheKey = cacheService.generateKey(
5948
+ "all-workspace-metrics",
5949
+ entityConfig.companyId,
5950
+ queryDate,
5951
+ queryShiftId
5952
+ );
5953
+ cacheService.delete(cacheKey, { storage: "memory" });
5954
+ await fetchWorkspaceMetrics(true);
5274
5955
  }
5275
5956
  ).subscribe();
5276
5957
  return channel2;
@@ -5281,16 +5962,80 @@ var useAllWorkspaceMetrics = (options) => {
5281
5962
  supabase.removeChannel(channel);
5282
5963
  }
5283
5964
  };
5284
- }, [queryDate, queryShiftId, metricsTable, fetchWorkspaceMetrics, initialized, supabase, schema]);
5965
+ }, [queryDate, queryShiftId, metricsTable, fetchWorkspaceMetrics, initialized, supabase, schema, entityConfig.companyId]);
5285
5966
  useEffect(() => {
5286
5967
  setInitialized(false);
5287
5968
  }, [queryDate, queryShiftId]);
5288
- const refreshWorkspaces = fetchWorkspaceMetrics;
5969
+ const refreshWorkspaces = useCallback(() => fetchWorkspaceMetrics(true), [fetchWorkspaceMetrics]);
5289
5970
  return useMemo(
5290
5971
  () => ({ workspaces, loading, error, refreshWorkspaces }),
5291
5972
  [workspaces, loading, error, refreshWorkspaces]
5292
5973
  );
5293
5974
  };
5975
+ var useSKUs = (companyId) => {
5976
+ const [skus, setSKUs] = useState([]);
5977
+ const [isLoading, setIsLoading] = useState(true);
5978
+ const [error, setError] = useState(null);
5979
+ const supabase = useSupabase();
5980
+ const config = useDashboardConfig();
5981
+ const dbConfig = config?.databaseConfig;
5982
+ const skusTable = dbConfig?.tables?.skus || "skus";
5983
+ const fetchSKUs = useCallback(async () => {
5984
+ if (!companyId) {
5985
+ setIsLoading(false);
5986
+ return;
5987
+ }
5988
+ try {
5989
+ setIsLoading(true);
5990
+ setError(null);
5991
+ const data = await skuService.getSKUs(companyId);
5992
+ setSKUs(data);
5993
+ } catch (err) {
5994
+ setError(err instanceof Error ? err : new Error("Failed to fetch SKUs"));
5995
+ console.error("Error fetching SKUs:", err);
5996
+ } finally {
5997
+ setIsLoading(false);
5998
+ }
5999
+ }, [companyId]);
6000
+ useEffect(() => {
6001
+ fetchSKUs();
6002
+ }, [fetchSKUs]);
6003
+ useEffect(() => {
6004
+ if (!supabase || !companyId) return;
6005
+ const channel = supabase.channel(`skus:${companyId}`).on(
6006
+ "postgres_changes",
6007
+ {
6008
+ event: "*",
6009
+ schema: dbConfig?.schema || "public",
6010
+ table: skusTable,
6011
+ filter: `company_id=eq.${companyId}`
6012
+ },
6013
+ (payload) => {
6014
+ console.log("SKU change received:", payload);
6015
+ if (payload.eventType === "INSERT") {
6016
+ setSKUs((prev) => [...prev, payload.new]);
6017
+ } else if (payload.eventType === "UPDATE") {
6018
+ setSKUs(
6019
+ (prev) => prev.map(
6020
+ (sku) => sku.id === payload.new.id ? payload.new : sku
6021
+ )
6022
+ );
6023
+ } else if (payload.eventType === "DELETE") {
6024
+ setSKUs((prev) => prev.filter((sku) => sku.id !== payload.old.id));
6025
+ }
6026
+ }
6027
+ ).subscribe();
6028
+ return () => {
6029
+ supabase.removeChannel(channel);
6030
+ };
6031
+ }, [supabase, companyId, dbConfig?.schema, skusTable]);
6032
+ return {
6033
+ skus,
6034
+ isLoading,
6035
+ error,
6036
+ refetch: fetchSKUs
6037
+ };
6038
+ };
5294
6039
  var MAX_RETRIES = 10;
5295
6040
  var RETRY_DELAY = 500;
5296
6041
  function useNavigation(customNavigate) {
@@ -8522,7 +9267,7 @@ var MotionConfigContext = createContext({
8522
9267
  });
8523
9268
 
8524
9269
  // ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PopChild.mjs
8525
- var PopChildMeasure = class extends React14.Component {
9270
+ var PopChildMeasure = class extends React19.Component {
8526
9271
  getSnapshotBeforeUpdate(prevProps) {
8527
9272
  const element = this.props.childRef.current;
8528
9273
  if (element && prevProps.isPresent && !this.props.isPresent) {
@@ -8577,7 +9322,7 @@ function PopChild({ children, isPresent }) {
8577
9322
  document.head.removeChild(style);
8578
9323
  };
8579
9324
  }, [isPresent]);
8580
- return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React14.cloneElement(children, { ref }) });
9325
+ return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React19.cloneElement(children, { ref }) });
8581
9326
  }
8582
9327
 
8583
9328
  // ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PresenceChild.mjs
@@ -8614,7 +9359,7 @@ var PresenceChild = ({ children, initial, isPresent, onExitComplete, custom, pre
8614
9359
  useMemo(() => {
8615
9360
  presenceChildren.forEach((_, key) => presenceChildren.set(key, false));
8616
9361
  }, [isPresent]);
8617
- React14.useEffect(() => {
9362
+ React19.useEffect(() => {
8618
9363
  !isPresent && !presenceChildren.size && onExitComplete && onExitComplete();
8619
9364
  }, [isPresent]);
8620
9365
  if (mode === "popLayout") {
@@ -10021,7 +10766,7 @@ function removeItem(arr, item) {
10021
10766
  }
10022
10767
 
10023
10768
  // ../../node_modules/framer-motion/dist/es/utils/subscription-manager.mjs
10024
- var SubscriptionManager = class {
10769
+ var SubscriptionManager3 = class {
10025
10770
  constructor() {
10026
10771
  this.subscriptions = [];
10027
10772
  }
@@ -10150,7 +10895,7 @@ var MotionValue = class {
10150
10895
  }
10151
10896
  on(eventName, callback) {
10152
10897
  if (!this.events[eventName]) {
10153
- this.events[eventName] = new SubscriptionManager();
10898
+ this.events[eventName] = new SubscriptionManager3();
10154
10899
  }
10155
10900
  const unsubscribe = this.events[eventName].add(callback);
10156
10901
  if (eventName === "change") {
@@ -14144,7 +14889,7 @@ function createProjectionNode2({ attachResizeListener, defaultParent, measureScr
14144
14889
  }
14145
14890
  addEventListener(name, handler) {
14146
14891
  if (!this.eventHandlers.has(name)) {
14147
- this.eventHandlers.set(name, new SubscriptionManager());
14892
+ this.eventHandlers.set(name, new SubscriptionManager3());
14148
14893
  }
14149
14894
  return this.eventHandlers.get(name).add(handler);
14150
14895
  }
@@ -15734,7 +16479,7 @@ var VisualElement = class {
15734
16479
  }
15735
16480
  on(eventName, callback) {
15736
16481
  if (!this.events[eventName]) {
15737
- this.events[eventName] = new SubscriptionManager();
16482
+ this.events[eventName] = new SubscriptionManager3();
15738
16483
  }
15739
16484
  return this.events[eventName].add(callback);
15740
16485
  }
@@ -15883,7 +16628,7 @@ var LoadingPage = ({
15883
16628
  subMessage = "Please wait while we prepare your data",
15884
16629
  className
15885
16630
  }) => {
15886
- React14__default.useEffect(() => {
16631
+ React19__default.useEffect(() => {
15887
16632
  console.log("LoadingPage rendered with message:", message);
15888
16633
  const timeout = setTimeout(() => {
15889
16634
  console.warn("LoadingPage has been visible for more than 8 seconds. This might indicate an issue.");
@@ -15926,10 +16671,10 @@ var withAuth = (WrappedComponent2, options) => {
15926
16671
  return function WithAuthComponent(props) {
15927
16672
  const { session, loading } = useAuth();
15928
16673
  const router = useRouter();
15929
- React14.useEffect(() => {
16674
+ React19.useEffect(() => {
15930
16675
  console.log("withAuth state:", { loading, hasSession: !!session, requireAuth: defaultOptions.requireAuth });
15931
16676
  }, [session, loading]);
15932
- React14.useEffect(() => {
16677
+ React19.useEffect(() => {
15933
16678
  if (!loading && defaultOptions.requireAuth && !session) {
15934
16679
  console.log("Redirecting to login from withAuth");
15935
16680
  router.replace(defaultOptions.redirectTo);
@@ -16257,7 +17002,7 @@ var DebugAuth = () => {
16257
17002
  ] }) });
16258
17003
  };
16259
17004
  var DEFAULT_BAR_RADIUS = [4, 4, 0, 0];
16260
- var BarChart = ({
17005
+ var BarChartComponent = ({
16261
17006
  data,
16262
17007
  bars,
16263
17008
  xAxisDataKey = "name",
@@ -16345,7 +17090,35 @@ var BarChart = ({
16345
17090
  }
16346
17091
  return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: chartContent });
16347
17092
  };
16348
- var LineChart = ({
17093
+ var BarChart = React19__default.memo(BarChartComponent, (prevProps, nextProps) => {
17094
+ if (prevProps.xAxisDataKey !== nextProps.xAxisDataKey || prevProps.xAxisLabel !== nextProps.xAxisLabel || prevProps.yAxisLabel !== nextProps.yAxisLabel || prevProps.yAxisUnit !== nextProps.yAxisUnit || prevProps.layout !== nextProps.layout || prevProps.className !== nextProps.className || prevProps.showGrid !== nextProps.showGrid || prevProps.showLegend !== nextProps.showLegend || prevProps.showTooltip !== nextProps.showTooltip || prevProps.responsive !== nextProps.responsive || prevProps.aspect !== nextProps.aspect) {
17095
+ return false;
17096
+ }
17097
+ if (prevProps.data.length !== nextProps.data.length) {
17098
+ return false;
17099
+ }
17100
+ if (!prevProps.data.every((item, idx) => {
17101
+ const nextItem = nextProps.data[idx];
17102
+ return Object.keys(item).every((key) => item[key] === nextItem[key]);
17103
+ })) {
17104
+ return false;
17105
+ }
17106
+ if (prevProps.bars.length !== nextProps.bars.length) {
17107
+ return false;
17108
+ }
17109
+ if (!prevProps.bars.every((bar, idx) => {
17110
+ const nextBar = nextProps.bars[idx];
17111
+ return bar.dataKey === nextBar.dataKey && bar.name === nextBar.name && bar.fill === nextBar.fill && JSON.stringify(bar.radius) === JSON.stringify(nextBar.radius) && bar.labelList === nextBar.labelList;
17112
+ })) {
17113
+ return false;
17114
+ }
17115
+ if (prevProps.tooltipFormatter !== nextProps.tooltipFormatter || JSON.stringify(prevProps.legendPayload) !== JSON.stringify(nextProps.legendPayload)) {
17116
+ return false;
17117
+ }
17118
+ return true;
17119
+ });
17120
+ BarChart.displayName = "BarChart";
17121
+ var LineChartComponent = ({
16349
17122
  data,
16350
17123
  lines,
16351
17124
  xAxisDataKey = "name",
@@ -16436,7 +17209,35 @@ var LineChart = ({
16436
17209
  }
16437
17210
  return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: chartContent });
16438
17211
  };
16439
- var OutputProgressChart = ({
17212
+ var LineChart = React19__default.memo(LineChartComponent, (prevProps, nextProps) => {
17213
+ if (prevProps.xAxisDataKey !== nextProps.xAxisDataKey || prevProps.xAxisLabel !== nextProps.xAxisLabel || prevProps.yAxisLabel !== nextProps.yAxisLabel || prevProps.yAxisUnit !== nextProps.yAxisUnit || prevProps.className !== nextProps.className || prevProps.showGrid !== nextProps.showGrid || prevProps.showLegend !== nextProps.showLegend || prevProps.showTooltip !== nextProps.showTooltip || prevProps.responsive !== nextProps.responsive || prevProps.aspect !== nextProps.aspect || JSON.stringify(prevProps.yAxisDomain) !== JSON.stringify(nextProps.yAxisDomain)) {
17214
+ return false;
17215
+ }
17216
+ if (prevProps.data.length !== nextProps.data.length) {
17217
+ return false;
17218
+ }
17219
+ if (!prevProps.data.every((item, idx) => {
17220
+ const nextItem = nextProps.data[idx];
17221
+ return Object.keys(item).every((key) => item[key] === nextItem[key]);
17222
+ })) {
17223
+ return false;
17224
+ }
17225
+ if (prevProps.lines.length !== nextProps.lines.length) {
17226
+ return false;
17227
+ }
17228
+ if (!prevProps.lines.every((line, idx) => {
17229
+ const nextLine = nextProps.lines[idx];
17230
+ return line.dataKey === nextLine.dataKey && line.name === nextLine.name && line.stroke === nextLine.stroke && line.strokeWidth === nextLine.strokeWidth && line.type === nextLine.type && JSON.stringify(line.dot) === JSON.stringify(nextLine.dot) && JSON.stringify(line.activeDot) === JSON.stringify(nextLine.activeDot) && line.labelList === nextLine.labelList;
17231
+ })) {
17232
+ return false;
17233
+ }
17234
+ if (prevProps.tooltipFormatter !== nextProps.tooltipFormatter || prevProps.xAxisTickFormatter !== nextProps.xAxisTickFormatter || JSON.stringify(prevProps.legendPayload) !== JSON.stringify(nextProps.legendPayload)) {
17235
+ return false;
17236
+ }
17237
+ return true;
17238
+ });
17239
+ LineChart.displayName = "LineChart";
17240
+ var OutputProgressChartComponent = ({
16440
17241
  currentOutput,
16441
17242
  targetOutput,
16442
17243
  className = ""
@@ -16485,6 +17286,8 @@ var OutputProgressChart = ({
16485
17286
  ] }) })
16486
17287
  ] }) });
16487
17288
  };
17289
+ var OutputProgressChart = React19__default.memo(OutputProgressChartComponent);
17290
+ OutputProgressChart.displayName = "OutputProgressChart";
16488
17291
  var LargeOutputProgressChart = ({
16489
17292
  currentOutput,
16490
17293
  targetOutput,
@@ -16534,7 +17337,7 @@ var LargeOutputProgressChart = ({
16534
17337
  ] }) })
16535
17338
  ] }) });
16536
17339
  };
16537
- var CycleTimeChart = ({
17340
+ var CycleTimeChartComponent = ({
16538
17341
  data = [],
16539
17342
  className = ""
16540
17343
  }) => {
@@ -16599,6 +17402,25 @@ var CycleTimeChart = ({
16599
17402
  }
16600
17403
  ) }) });
16601
17404
  };
17405
+ var CycleTimeChart = React19__default.memo(CycleTimeChartComponent, (prevProps, nextProps) => {
17406
+ if (prevProps.className !== nextProps.className) {
17407
+ return false;
17408
+ }
17409
+ if (!prevProps.data && !nextProps.data) {
17410
+ return true;
17411
+ }
17412
+ if (!prevProps.data || !nextProps.data) {
17413
+ return false;
17414
+ }
17415
+ if (prevProps.data.length !== nextProps.data.length) {
17416
+ return false;
17417
+ }
17418
+ return prevProps.data.every((item, index) => {
17419
+ const nextItem = nextProps.data[index];
17420
+ return item.time === nextItem.time && item.value === nextItem.value;
17421
+ });
17422
+ });
17423
+ CycleTimeChart.displayName = "CycleTimeChart";
16602
17424
  var CycleTimeOverTimeChart = ({
16603
17425
  data,
16604
17426
  idealCycleTime,
@@ -16616,10 +17438,10 @@ var CycleTimeOverTimeChart = ({
16616
17438
  };
16617
17439
  const displayData = getDisplayData(data);
16618
17440
  const DURATION = displayData.length;
16619
- const [animatedData, setAnimatedData] = React14__default.useState(Array(DURATION).fill(0));
16620
- const prevDataRef = React14__default.useRef(Array(DURATION).fill(0));
16621
- const animationFrameRef = React14__default.useRef(null);
16622
- const animateToNewData = React14__default.useCallback((targetData) => {
17441
+ const [animatedData, setAnimatedData] = React19__default.useState(Array(DURATION).fill(0));
17442
+ const prevDataRef = React19__default.useRef(Array(DURATION).fill(0));
17443
+ const animationFrameRef = React19__default.useRef(null);
17444
+ const animateToNewData = React19__default.useCallback((targetData) => {
16623
17445
  const startData = [...prevDataRef.current];
16624
17446
  const startTime = performance.now();
16625
17447
  const duration = 1200;
@@ -16649,7 +17471,7 @@ var CycleTimeOverTimeChart = ({
16649
17471
  }
16650
17472
  animationFrameRef.current = requestAnimationFrame(animate);
16651
17473
  }, []);
16652
- React14__default.useEffect(() => {
17474
+ React19__default.useEffect(() => {
16653
17475
  if (JSON.stringify(data) !== JSON.stringify(prevDataRef.current)) {
16654
17476
  const processedData = getDisplayData(data);
16655
17477
  animateToNewData(processedData);
@@ -16873,7 +17695,7 @@ var CycleTimeOverTimeChart = ({
16873
17695
  renderLegend()
16874
17696
  ] });
16875
17697
  };
16876
- var Card = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
17698
+ var Card = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
16877
17699
  "div",
16878
17700
  {
16879
17701
  ref,
@@ -16885,7 +17707,7 @@ var Card = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
16885
17707
  }
16886
17708
  ));
16887
17709
  Card.displayName = "Card";
16888
- var CardHeader = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
17710
+ var CardHeader = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
16889
17711
  "div",
16890
17712
  {
16891
17713
  ref,
@@ -16894,7 +17716,7 @@ var CardHeader = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE
16894
17716
  }
16895
17717
  ));
16896
17718
  CardHeader.displayName = "CardHeader";
16897
- var CardTitle = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
17719
+ var CardTitle = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
16898
17720
  "h3",
16899
17721
  {
16900
17722
  ref,
@@ -16906,7 +17728,7 @@ var CardTitle = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE_
16906
17728
  }
16907
17729
  ));
16908
17730
  CardTitle.displayName = "CardTitle";
16909
- var CardDescription = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
17731
+ var CardDescription = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
16910
17732
  "p",
16911
17733
  {
16912
17734
  ref,
@@ -16915,9 +17737,9 @@ var CardDescription = React14.forwardRef(({ className, ...props }, ref) => /* @_
16915
17737
  }
16916
17738
  ));
16917
17739
  CardDescription.displayName = "CardDescription";
16918
- var CardContent = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
17740
+ var CardContent = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
16919
17741
  CardContent.displayName = "CardContent";
16920
- var CardFooter = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
17742
+ var CardFooter = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
16921
17743
  "div",
16922
17744
  {
16923
17745
  ref,
@@ -16993,7 +17815,7 @@ var buttonVariants = cva(
16993
17815
  }
16994
17816
  }
16995
17817
  );
16996
- var Button = React14.forwardRef(
17818
+ var Button = React19.forwardRef(
16997
17819
  ({ className, variant, size, asChild = false, ...props }, ref) => {
16998
17820
  const Comp = asChild ? Slot : "button";
16999
17821
  return /* @__PURE__ */ jsx(
@@ -17007,7 +17829,7 @@ var Button = React14.forwardRef(
17007
17829
  }
17008
17830
  );
17009
17831
  Button.displayName = "Button";
17010
- var HourlyOutputChart = ({
17832
+ var HourlyOutputChartComponent = ({
17011
17833
  data,
17012
17834
  pphThreshold,
17013
17835
  shiftStart,
@@ -17024,17 +17846,17 @@ var HourlyOutputChart = ({
17024
17846
  };
17025
17847
  const shiftStartTime = getTimeFromTimeString(shiftStart);
17026
17848
  const SHIFT_DURATION = 11;
17027
- const [animatedData, setAnimatedData] = React14__default.useState(Array(SHIFT_DURATION).fill(0));
17028
- const prevDataRef = React14__default.useRef(Array(SHIFT_DURATION).fill(0));
17029
- const animationFrameRef = React14__default.useRef(null);
17030
- const [idleBarState, setIdleBarState] = React14__default.useState({
17849
+ const [animatedData, setAnimatedData] = React19__default.useState(Array(SHIFT_DURATION).fill(0));
17850
+ const prevDataRef = React19__default.useRef(Array(SHIFT_DURATION).fill(0));
17851
+ const animationFrameRef = React19__default.useRef(null);
17852
+ const [idleBarState, setIdleBarState] = React19__default.useState({
17031
17853
  visible: showIdleTime,
17032
17854
  key: 0,
17033
17855
  shouldAnimate: false
17034
17856
  });
17035
- const prevShowIdleTimeRef = React14__default.useRef(showIdleTime);
17036
- const stateUpdateTimeoutRef = React14__default.useRef(null);
17037
- React14__default.useEffect(() => {
17857
+ const prevShowIdleTimeRef = React19__default.useRef(showIdleTime);
17858
+ const stateUpdateTimeoutRef = React19__default.useRef(null);
17859
+ React19__default.useEffect(() => {
17038
17860
  if (stateUpdateTimeoutRef.current) {
17039
17861
  clearTimeout(stateUpdateTimeoutRef.current);
17040
17862
  }
@@ -17059,7 +17881,7 @@ var HourlyOutputChart = ({
17059
17881
  }
17060
17882
  };
17061
17883
  }, [showIdleTime]);
17062
- const animateToNewData = React14__default.useCallback((targetData) => {
17884
+ const animateToNewData = React19__default.useCallback((targetData) => {
17063
17885
  const startData = [...prevDataRef.current];
17064
17886
  const startTime = performance.now();
17065
17887
  const duration = 1200;
@@ -17089,7 +17911,7 @@ var HourlyOutputChart = ({
17089
17911
  }
17090
17912
  animationFrameRef.current = requestAnimationFrame(animate);
17091
17913
  }, []);
17092
- React14__default.useEffect(() => {
17914
+ React19__default.useEffect(() => {
17093
17915
  if (JSON.stringify(data) !== JSON.stringify(prevDataRef.current)) {
17094
17916
  const shiftData = data.slice(0, SHIFT_DURATION);
17095
17917
  animateToNewData(shiftData);
@@ -17100,7 +17922,7 @@ var HourlyOutputChart = ({
17100
17922
  }
17101
17923
  };
17102
17924
  }, [data, animateToNewData]);
17103
- const formatHour = React14__default.useCallback((hourIndex) => {
17925
+ const formatHour = React19__default.useCallback((hourIndex) => {
17104
17926
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
17105
17927
  const startHour = Math.floor(startDecimalHour) % 24;
17106
17928
  const startMinute = Math.round(startDecimalHour % 1 * 60);
@@ -17117,7 +17939,7 @@ var HourlyOutputChart = ({
17117
17939
  };
17118
17940
  return `${formatTime2(startHour, startMinute)}-${formatTime2(endHour, endMinute)}`;
17119
17941
  }, [shiftStartTime.decimalHour]);
17120
- const formatTimeRange = React14__default.useCallback((hourIndex) => {
17942
+ const formatTimeRange = React19__default.useCallback((hourIndex) => {
17121
17943
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
17122
17944
  const startHour = Math.floor(startDecimalHour) % 24;
17123
17945
  const startMinute = Math.round(startDecimalHour % 1 * 60);
@@ -17131,7 +17953,7 @@ var HourlyOutputChart = ({
17131
17953
  };
17132
17954
  return `${formatTime2(startHour, startMinute)} - ${formatTime2(endHour, endMinute)}`;
17133
17955
  }, [shiftStartTime.decimalHour]);
17134
- const chartData = React14__default.useMemo(() => {
17956
+ const chartData = React19__default.useMemo(() => {
17135
17957
  return Array.from({ length: SHIFT_DURATION }, (_, i) => {
17136
17958
  const actualHour = (shiftStartTime.hour + i) % 24;
17137
17959
  const idleArray = idleTimeHourly?.[actualHour.toString()] || [];
@@ -17148,7 +17970,7 @@ var HourlyOutputChart = ({
17148
17970
  };
17149
17971
  });
17150
17972
  }, [animatedData, data, pphThreshold, idleTimeHourly, shiftStartTime.hour, formatHour, formatTimeRange]);
17151
- const IdleBar = React14__default.useMemo(() => {
17973
+ const IdleBar = React19__default.useMemo(() => {
17152
17974
  if (!idleBarState.visible) return null;
17153
17975
  return /* @__PURE__ */ jsx(
17154
17976
  Bar,
@@ -17465,6 +18287,33 @@ var HourlyOutputChart = ({
17465
18287
  renderLegend()
17466
18288
  ] });
17467
18289
  };
18290
+ var HourlyOutputChart = React19__default.memo(HourlyOutputChartComponent, (prevProps, nextProps) => {
18291
+ if (prevProps.pphThreshold !== nextProps.pphThreshold || prevProps.shiftStart !== nextProps.shiftStart || prevProps.showIdleTime !== nextProps.showIdleTime || prevProps.className !== nextProps.className) {
18292
+ return false;
18293
+ }
18294
+ if (prevProps.data.length !== nextProps.data.length) {
18295
+ return false;
18296
+ }
18297
+ if (!prevProps.data.every((val, idx) => val === nextProps.data[idx])) {
18298
+ return false;
18299
+ }
18300
+ const prevIdle = prevProps.idleTimeHourly || {};
18301
+ const nextIdle = nextProps.idleTimeHourly || {};
18302
+ const prevKeys = Object.keys(prevIdle);
18303
+ const nextKeys = Object.keys(nextIdle);
18304
+ if (prevKeys.length !== nextKeys.length) {
18305
+ return false;
18306
+ }
18307
+ for (const key of prevKeys) {
18308
+ if (!nextIdle[key]) return false;
18309
+ const prevArray = prevIdle[key];
18310
+ const nextArray = nextIdle[key];
18311
+ if (prevArray.length !== nextArray.length) return false;
18312
+ if (!prevArray.every((val, idx) => val === nextArray[idx])) return false;
18313
+ }
18314
+ return true;
18315
+ });
18316
+ HourlyOutputChart.displayName = "HourlyOutputChart";
17468
18317
  function getTrendArrowAndColor(trend) {
17469
18318
  if (trend > 0) {
17470
18319
  return { arrow: "\u2191", color: "text-green-400" };
@@ -17474,7 +18323,7 @@ function getTrendArrowAndColor(trend) {
17474
18323
  return { arrow: "\u2192", color: "text-gray-400" };
17475
18324
  }
17476
18325
  }
17477
- var VideoCard = React14__default.memo(({
18326
+ var VideoCard = React19__default.memo(({
17478
18327
  workspace,
17479
18328
  hlsUrl,
17480
18329
  shouldPlay,
@@ -17617,7 +18466,7 @@ var VideoCard = React14__default.memo(({
17617
18466
  });
17618
18467
  VideoCard.displayName = "VideoCard";
17619
18468
  var DEFAULT_HLS_URL = "https://192.168.5.9:8443/cam1.m3u8";
17620
- var VideoGridView = React14__default.memo(({
18469
+ var VideoGridView = React19__default.memo(({
17621
18470
  workspaces,
17622
18471
  selectedLine,
17623
18472
  className = "",
@@ -18419,7 +19268,7 @@ var EmptyStateMessage = ({
18419
19268
  iconClassName
18420
19269
  }) => {
18421
19270
  let IconContent = null;
18422
- if (React14__default.isValidElement(iconType)) {
19271
+ if (React19__default.isValidElement(iconType)) {
18423
19272
  IconContent = iconType;
18424
19273
  } else if (typeof iconType === "string") {
18425
19274
  const MappedIcon = IconMap[iconType];
@@ -18552,7 +19401,10 @@ var BreakNotificationPopup = ({
18552
19401
  /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3 flex-1", children: [
18553
19402
  /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-amber-500 rounded-full animate-pulse flex-shrink-0 mt-2" }),
18554
19403
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
18555
- /* @__PURE__ */ jsx("div", { className: "mb-1", children: /* @__PURE__ */ jsx("h4", { className: "font-semibold text-sm text-gray-900", children: breakItem.remarks || "Break" }) }),
19404
+ /* @__PURE__ */ jsxs("div", { className: "mb-1", children: [
19405
+ /* @__PURE__ */ jsx("h4", { className: "font-semibold text-sm text-gray-900", children: breakItem.remarks || "Break" }),
19406
+ (activeBreaks.length > 1 || lineNames[breakItem.lineId]) && /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500 mt-0.5", children: lineNames[breakItem.lineId] || `Line ${breakItem.lineId.substring(0, 8)}` })
19407
+ ] }),
18556
19408
  /* @__PURE__ */ jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxs("div", { className: "text-xs text-gray-600 font-medium", children: [
18557
19409
  breakItem.startTime,
18558
19410
  " - ",
@@ -18561,8 +19413,7 @@ var BreakNotificationPopup = ({
18561
19413
  /* @__PURE__ */ jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxs("div", { className: "text-xs text-gray-500", children: [
18562
19414
  formatTime2(breakItem.elapsedMinutes),
18563
19415
  " / ",
18564
- breakItem.duration,
18565
- " min"
19416
+ formatTime2(breakItem.duration)
18566
19417
  ] }) }),
18567
19418
  /* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx("div", { className: "w-full bg-gray-200 rounded-full h-1.5", children: /* @__PURE__ */ jsx(
18568
19419
  "div",
@@ -21001,7 +21852,7 @@ function Skeleton({ className, ...props }) {
21001
21852
  var Select = SelectPrimitive.Root;
21002
21853
  var SelectGroup = SelectPrimitive.Group;
21003
21854
  var SelectValue = SelectPrimitive.Value;
21004
- var SelectTrigger = React14.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
21855
+ var SelectTrigger = React19.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
21005
21856
  SelectPrimitive.Trigger,
21006
21857
  {
21007
21858
  ref,
@@ -21017,7 +21868,7 @@ var SelectTrigger = React14.forwardRef(({ className, children, ...props }, ref)
21017
21868
  }
21018
21869
  ));
21019
21870
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
21020
- var SelectScrollUpButton = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21871
+ var SelectScrollUpButton = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21021
21872
  SelectPrimitive.ScrollUpButton,
21022
21873
  {
21023
21874
  ref,
@@ -21027,7 +21878,7 @@ var SelectScrollUpButton = React14.forwardRef(({ className, ...props }, ref) =>
21027
21878
  }
21028
21879
  ));
21029
21880
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
21030
- var SelectScrollDownButton = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21881
+ var SelectScrollDownButton = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21031
21882
  SelectPrimitive.ScrollDownButton,
21032
21883
  {
21033
21884
  ref,
@@ -21037,7 +21888,7 @@ var SelectScrollDownButton = React14.forwardRef(({ className, ...props }, ref) =
21037
21888
  }
21038
21889
  ));
21039
21890
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
21040
- var SelectContent = React14.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
21891
+ var SelectContent = React19.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
21041
21892
  SelectPrimitive.Content,
21042
21893
  {
21043
21894
  ref,
@@ -21065,7 +21916,7 @@ var SelectContent = React14.forwardRef(({ className, children, position = "poppe
21065
21916
  }
21066
21917
  ) }));
21067
21918
  SelectContent.displayName = SelectPrimitive.Content.displayName;
21068
- var SelectLabel = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21919
+ var SelectLabel = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21069
21920
  SelectPrimitive.Label,
21070
21921
  {
21071
21922
  ref,
@@ -21074,7 +21925,7 @@ var SelectLabel = React14.forwardRef(({ className, ...props }, ref) => /* @__PUR
21074
21925
  }
21075
21926
  ));
21076
21927
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
21077
- var SelectItem = React14.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
21928
+ var SelectItem = React19.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
21078
21929
  SelectPrimitive.Item,
21079
21930
  {
21080
21931
  ref,
@@ -21090,7 +21941,7 @@ var SelectItem = React14.forwardRef(({ className, children, ...props }, ref) =>
21090
21941
  }
21091
21942
  ));
21092
21943
  SelectItem.displayName = SelectPrimitive.Item.displayName;
21093
- var SelectSeparator = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21944
+ var SelectSeparator = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
21094
21945
  SelectPrimitive.Separator,
21095
21946
  {
21096
21947
  ref,
@@ -21965,7 +22816,7 @@ var BottlenecksContent = ({
21965
22816
  className
21966
22817
  }) => {
21967
22818
  const dashboardConfig = useDashboardConfig();
21968
- const sopCategories = React14__default.useMemo(() => {
22819
+ const sopCategories = React19__default.useMemo(() => {
21969
22820
  const sopConfig = dashboardConfig?.s3Config?.sopCategories;
21970
22821
  if (!sopConfig) return null;
21971
22822
  if (sopConfig.workspaceOverrides && sopConfig.workspaceOverrides[workspaceId]) {
@@ -22944,7 +23795,7 @@ var arePropsEqual = (prevProps, nextProps) => {
22944
23795
  return prevProps.data.efficiency === nextProps.data.efficiency && prevProps.data.trend_score === nextProps.data.trend_score && prevProps.data.workspace_id === nextProps.data.workspace_id && prevProps.data.workspace_name === nextProps.data.workspace_name && prevProps.isBottleneck === nextProps.isBottleneck && prevProps.isLowEfficiency === nextProps.isLowEfficiency && prevProps.isVeryLowEfficiency === nextProps.isVeryLowEfficiency && // Position doesn't need deep equality check as it's generally static
22945
23796
  prevProps.position.id === nextProps.position.id;
22946
23797
  };
22947
- var WorkspaceGridItem = React14__default.memo(({
23798
+ var WorkspaceGridItem = React19__default.memo(({
22948
23799
  data,
22949
23800
  position,
22950
23801
  isBottleneck = false,
@@ -23037,7 +23888,7 @@ var WorkspaceGridItem = React14__default.memo(({
23037
23888
  );
23038
23889
  }, arePropsEqual);
23039
23890
  WorkspaceGridItem.displayName = "WorkspaceGridItem";
23040
- var WorkspaceGrid = React14__default.memo(({
23891
+ var WorkspaceGrid = React19__default.memo(({
23041
23892
  workspaces,
23042
23893
  isPdfMode = false,
23043
23894
  customWorkspacePositions,
@@ -23227,7 +24078,7 @@ var KPICard = ({
23227
24078
  }) => {
23228
24079
  useThemeConfig();
23229
24080
  const { formatNumber } = useFormatNumber();
23230
- const trendInfo = React14__default.useMemo(() => {
24081
+ const trendInfo = React19__default.useMemo(() => {
23231
24082
  let trendValue = trend || "neutral";
23232
24083
  if (change !== void 0 && trend === void 0) {
23233
24084
  trendValue = change > 0 ? "up" : change < 0 ? "down" : "neutral";
@@ -23250,7 +24101,7 @@ var KPICard = ({
23250
24101
  const shouldShowTrend = !(change === 0 && trend === void 0);
23251
24102
  return { trendValue, Icon: Icon2, colorClass, shouldShowTrend };
23252
24103
  }, [trend, change]);
23253
- const formattedValue = React14__default.useMemo(() => {
24104
+ const formattedValue = React19__default.useMemo(() => {
23254
24105
  if (title === "Quality Compliance" && typeof value === "number") {
23255
24106
  return value.toFixed(1);
23256
24107
  }
@@ -23264,7 +24115,7 @@ var KPICard = ({
23264
24115
  }
23265
24116
  return value;
23266
24117
  }, [value, title]);
23267
- const formattedChange = React14__default.useMemo(() => {
24118
+ const formattedChange = React19__default.useMemo(() => {
23268
24119
  if (change === void 0 || change === 0) return null;
23269
24120
  const absChange = Math.abs(change);
23270
24121
  return formatNumber(absChange, { minimumFractionDigits: 0, maximumFractionDigits: 1 });
@@ -23751,7 +24602,7 @@ var Breadcrumbs = ({ items }) => {
23751
24602
  }
23752
24603
  }
23753
24604
  };
23754
- return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "mb-1 flex items-center space-x-1 text-xs font-medium text-gray-500 dark:text-gray-400", children: items.map((item, index) => /* @__PURE__ */ jsxs(React14__default.Fragment, { children: [
24605
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "mb-1 flex items-center space-x-1 text-xs font-medium text-gray-500 dark:text-gray-400", children: items.map((item, index) => /* @__PURE__ */ jsxs(React19__default.Fragment, { children: [
23755
24606
  index > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "h-3 w-3 text-gray-400 dark:text-gray-500" }),
23756
24607
  /* @__PURE__ */ jsxs(
23757
24608
  "span",
@@ -23943,7 +24794,9 @@ var SideNavBar = memo(({
23943
24794
  const router = useRouter();
23944
24795
  const { navigate } = useNavigation();
23945
24796
  const entityConfig = useEntityConfig();
24797
+ const dashboardConfig = useDashboardConfig();
23946
24798
  const lineId = entityConfig.defaultLineId || LINE_1_UUID;
24799
+ const skuEnabled = dashboardConfig?.skuConfig?.enabled || false;
23947
24800
  const pathname = propPathname || router.pathname;
23948
24801
  const getButtonClasses = useCallback((path) => {
23949
24802
  const isActive = pathname === path || pathname.startsWith(path + "/");
@@ -24018,6 +24871,14 @@ var SideNavBar = memo(({
24018
24871
  }
24019
24872
  }
24020
24873
  }), [navigate]);
24874
+ const handleSKUsClick = useCallback(() => navigate("/skus", {
24875
+ trackingEvent: {
24876
+ name: "SKU Management Page Clicked",
24877
+ properties: {
24878
+ source: "side_nav"
24879
+ }
24880
+ }
24881
+ }), [navigate]);
24021
24882
  const homeButtonClasses = useMemo(() => getButtonClasses("/"), [getButtonClasses, pathname]);
24022
24883
  const leaderboardButtonClasses = useMemo(() => getButtonClasses("/leaderboard"), [getButtonClasses, pathname]);
24023
24884
  const kpisButtonClasses = useMemo(() => getButtonClasses("/kpis"), [getButtonClasses, pathname]);
@@ -24026,6 +24887,7 @@ var SideNavBar = memo(({
24026
24887
  const aiAgentButtonClasses = useMemo(() => getButtonClasses("/ai-agent"), [getButtonClasses, pathname]);
24027
24888
  const profileButtonClasses = useMemo(() => getButtonClasses("/profile"), [getButtonClasses, pathname]);
24028
24889
  const helpButtonClasses = useMemo(() => getButtonClasses("/help"), [getButtonClasses, pathname]);
24890
+ const skusButtonClasses = useMemo(() => getButtonClasses("/skus"), [getButtonClasses, pathname]);
24029
24891
  return /* @__PURE__ */ jsxs("aside", { className: `w-20 h-screen bg-white shadow-lg border-r border-gray-100 flex flex-col items-center fixed ${className}`, children: [
24030
24892
  /* @__PURE__ */ jsx("div", { className: "w-full py-6 px-4 flex-shrink-0", children: /* @__PURE__ */ jsx(
24031
24893
  "button",
@@ -24126,6 +24988,21 @@ var SideNavBar = memo(({
24126
24988
  ]
24127
24989
  }
24128
24990
  ),
24991
+ skuEnabled && /* @__PURE__ */ jsxs(
24992
+ "button",
24993
+ {
24994
+ onClick: handleSKUsClick,
24995
+ className: skusButtonClasses,
24996
+ "aria-label": "SKU Management",
24997
+ tabIndex: 0,
24998
+ role: "tab",
24999
+ "aria-selected": pathname === "/skus" || pathname.startsWith("/skus/"),
25000
+ children: [
25001
+ /* @__PURE__ */ jsx(CubeIcon, { className: "w-5 h-5 mb-1" }),
25002
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium leading-tight", children: "SKUs" })
25003
+ ]
25004
+ }
25005
+ ),
24129
25006
  /* @__PURE__ */ jsxs(
24130
25007
  "button",
24131
25008
  {
@@ -24310,6 +25187,103 @@ var Header = ({
24310
25187
  ] })
24311
25188
  ] }) });
24312
25189
  };
25190
+ var LoadingState = ({
25191
+ message = "Loading...",
25192
+ subMessage,
25193
+ size = "lg",
25194
+ className = ""
25195
+ }) => {
25196
+ return /* @__PURE__ */ jsx("div", { className: `flex h-full w-full items-center justify-center bg-gray-50/50 ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center space-y-4 text-center", children: [
25197
+ /* @__PURE__ */ jsx(LoadingSpinner_default, { size }),
25198
+ /* @__PURE__ */ jsxs("div", { children: [
25199
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-medium text-gray-900", children: message }),
25200
+ subMessage && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-gray-600", children: subMessage })
25201
+ ] })
25202
+ ] }) });
25203
+ };
25204
+ var LoadingSkeleton = ({
25205
+ type,
25206
+ count = 1,
25207
+ className = "",
25208
+ showLoadingIndicator = true
25209
+ }) => {
25210
+ const renderSkeleton = () => {
25211
+ switch (type) {
25212
+ case "card":
25213
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-3 p-4 border rounded-lg relative", children: [
25214
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-3/4" }),
25215
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-1/2" }),
25216
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-full" }),
25217
+ showLoadingIndicator && /* @__PURE__ */ jsx("div", { className: "absolute top-2 right-2", children: /* @__PURE__ */ jsxs("div", { className: "flex space-x-1", children: [
25218
+ /* @__PURE__ */ jsx("div", { className: "w-1.5 h-1.5 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0ms" } }),
25219
+ /* @__PURE__ */ jsx("div", { className: "w-1.5 h-1.5 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "150ms" } }),
25220
+ /* @__PURE__ */ jsx("div", { className: "w-1.5 h-1.5 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "300ms" } })
25221
+ ] }) })
25222
+ ] });
25223
+ case "chart":
25224
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-3 p-4 relative", children: [
25225
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-1/3" }),
25226
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
25227
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-64 w-full" }),
25228
+ showLoadingIndicator && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "bg-white/80 rounded-lg p-3 shadow-sm", children: /* @__PURE__ */ jsxs("svg", { className: "animate-spin h-6 w-6 text-blue-500", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
25229
+ /* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
25230
+ /* @__PURE__ */ jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
25231
+ ] }) }) })
25232
+ ] })
25233
+ ] });
25234
+ case "table":
25235
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
25236
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full" }),
25237
+ [...Array(5)].map((_, i) => /* @__PURE__ */ jsx(Skeleton, { className: "h-12 w-full" }, i))
25238
+ ] });
25239
+ case "list":
25240
+ return /* @__PURE__ */ jsx("div", { className: "space-y-2", children: [...Array(5)].map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3", children: [
25241
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-10 rounded-full" }),
25242
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-2", children: [
25243
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-3/4" }),
25244
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-1/2" })
25245
+ ] })
25246
+ ] }, i)) });
25247
+ case "kpi":
25248
+ return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-4 gap-4", children: [...Array(4)].map((_, i) => /* @__PURE__ */ jsxs("div", { className: "p-4 border rounded-lg space-y-2", children: [
25249
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-2/3" }),
25250
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-1/2" }),
25251
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-full" })
25252
+ ] }, i)) });
25253
+ case "workspace-card":
25254
+ return /* @__PURE__ */ jsxs("div", { className: "p-4 border rounded-lg space-y-3", children: [
25255
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-start", children: [
25256
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-1/3" }),
25257
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-16" })
25258
+ ] }),
25259
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-32 w-full" }),
25260
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
25261
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-full" }),
25262
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-full" })
25263
+ ] })
25264
+ ] });
25265
+ case "video-grid":
25266
+ return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: [...Array(6)].map((_, i) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
25267
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-48 w-full rounded-lg" }),
25268
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-3/4" }),
25269
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-1/2" })
25270
+ ] }, i)) });
25271
+ default:
25272
+ return /* @__PURE__ */ jsx(Skeleton, { className: "h-20 w-full" });
25273
+ }
25274
+ };
25275
+ return /* @__PURE__ */ jsx("div", { className, children: [...Array(count)].map((_, index) => /* @__PURE__ */ jsx("div", { children: renderSkeleton() }, index)) });
25276
+ };
25277
+ var LoadingInline = ({
25278
+ message,
25279
+ size = "sm",
25280
+ className = ""
25281
+ }) => {
25282
+ return /* @__PURE__ */ jsxs("div", { className: `inline-flex items-center space-x-2 ${className}`, children: [
25283
+ /* @__PURE__ */ jsx(LoadingSpinner_default, { size }),
25284
+ message && /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-600", children: message })
25285
+ ] });
25286
+ };
24313
25287
  var DEFAULT_HLS_CONFIG = {
24314
25288
  maxBufferLength: 15,
24315
25289
  // Moderate buffer length for faster startup
@@ -24569,7 +25543,7 @@ var ThreadSidebar = ({
24569
25543
  ] });
24570
25544
  };
24571
25545
  var axelProfilePng = "/axel-profile.png";
24572
- var ProfilePicture = React14__default.memo(({ alt = "Axel", className = "w-12 h-12" }) => {
25546
+ var ProfilePicture = React19__default.memo(({ alt = "Axel", className = "w-12 h-12" }) => {
24573
25547
  return /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx("div", { className: `${className} rounded-xl overflow-hidden shadow-sm`, children: /* @__PURE__ */ jsx(
24574
25548
  "img",
24575
25549
  {
@@ -24687,6 +25661,7 @@ var AIAgentView = () => {
24687
25661
  const textareaRef = useRef(null);
24688
25662
  const messagesEndRef = useRef(null);
24689
25663
  const containerRef = useRef(null);
25664
+ const renderedContentCache = useRef(/* @__PURE__ */ new Map());
24690
25665
  const { createThread, mutate: mutateThreads } = useThreads();
24691
25666
  const { messages, addMessage, setMessages } = useMessages(activeThreadId);
24692
25667
  const agnoApiUrl = config.endpoints?.agnoApiUrl || "https://optifye-agent-production.up.railway.app";
@@ -25172,6 +26147,10 @@ var AIAgentView = () => {
25172
26147
  });
25173
26148
  }
25174
26149
  const renderAssistantContent = (content) => {
26150
+ const cached = renderedContentCache.current.get(content);
26151
+ if (cached) {
26152
+ return cached;
26153
+ }
25175
26154
  const parseChartPatterns = (text) => {
25176
26155
  const chartElements = [];
25177
26156
  let lastIndex = 0;
@@ -26036,16 +27015,20 @@ var AIAgentView = () => {
26036
27015
  }
26037
27016
  };
26038
27017
  const chartContent = parseChartPatterns(content);
27018
+ let finalNode;
26039
27019
  if (chartContent) {
26040
- return /* @__PURE__ */ jsx("div", { className: "formatted-content", children: chartContent });
27020
+ finalNode = /* @__PURE__ */ jsx("div", { className: "formatted-content", children: chartContent });
27021
+ } else {
27022
+ finalNode = /* @__PURE__ */ jsx(
27023
+ "div",
27024
+ {
27025
+ className: "formatted-content",
27026
+ dangerouslySetInnerHTML: { __html: formatMessage(content) }
27027
+ }
27028
+ );
26041
27029
  }
26042
- return /* @__PURE__ */ jsx(
26043
- "div",
26044
- {
26045
- className: "formatted-content",
26046
- dangerouslySetInnerHTML: { __html: formatMessage(content) }
26047
- }
26048
- );
27030
+ renderedContentCache.current.set(content, finalNode);
27031
+ return finalNode;
26049
27032
  };
26050
27033
  return /* @__PURE__ */ jsxs("div", { className: "flex h-screen bg-white", children: [
26051
27034
  /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: {
@@ -27287,8 +28270,6 @@ var HelpView = ({
27287
28270
  var AuthenticatedHelpView = withAuth(HelpView);
27288
28271
  var HelpView_default = HelpView;
27289
28272
  var KPISection2 = KPISection;
27290
- var LoadingPageCmp = LoadingPage_default;
27291
- var LoadingOverlayCmp = LoadingOverlay_default;
27292
28273
  function HomeView({
27293
28274
  defaultLineId,
27294
28275
  factoryViewId,
@@ -27307,6 +28288,7 @@ function HomeView({
27307
28288
  const [isChangingFilter, setIsChangingFilter] = useState(false);
27308
28289
  const [errorMessage, setErrorMessage] = useState(null);
27309
28290
  const [displayNamesInitialized, setDisplayNamesInitialized] = useState(false);
28291
+ const [hasInitialDataLoaded, setHasInitialDataLoaded] = useState(false);
27310
28292
  useEffect(() => {
27311
28293
  const initDisplayNames = async () => {
27312
28294
  try {
@@ -27357,17 +28339,17 @@ function HomeView({
27357
28339
  lineId: selectedLineId,
27358
28340
  onLineMetricsUpdate
27359
28341
  });
27360
- const lineIdsForBreaks = useMemo(() => {
27361
- if (selectedLineId === factoryViewId) {
27362
- return allLineIds;
27363
- }
27364
- return [selectedLineId];
27365
- }, [selectedLineId, factoryViewId, allLineIds]);
27366
28342
  const {
27367
- activeBreaks,
28343
+ activeBreaks: allActiveBreaks,
27368
28344
  isLoading: breaksLoading,
27369
28345
  error: breaksError
27370
- } = useActiveBreaks(lineIdsForBreaks);
28346
+ } = useActiveBreaks(allLineIds);
28347
+ const activeBreaks = useMemo(() => {
28348
+ if (selectedLineId === factoryViewId) {
28349
+ return allActiveBreaks;
28350
+ }
28351
+ return allActiveBreaks.filter((breakItem) => breakItem.lineId === selectedLineId);
28352
+ }, [allActiveBreaks, selectedLineId, factoryViewId]);
27371
28353
  const memoizedWorkspaceMetrics = useMemo(() => workspaceMetrics, [
27372
28354
  // Only update reference if meaningful properties change
27373
28355
  workspaceMetrics.length,
@@ -27407,6 +28389,11 @@ function HomeView({
27407
28389
  }
27408
28390
  }
27409
28391
  }, [metricsLoading, kpisLoading, workspaceMetrics, isChangingFilter, selectedLineId, factoryViewId]);
28392
+ useEffect(() => {
28393
+ if (!metricsLoading && !kpisLoading && !hasInitialDataLoaded) {
28394
+ setHasInitialDataLoaded(true);
28395
+ }
28396
+ }, [metricsLoading, kpisLoading, hasInitialDataLoaded]);
27410
28397
  const lineTitle = useMemo(() => {
27411
28398
  return factoryName;
27412
28399
  }, [factoryName]);
@@ -27419,9 +28406,56 @@ function HomeView({
27419
28406
  /* @__PURE__ */ jsx(SelectContent, { className: "z-50 bg-white shadow-lg border border-gray-200 rounded-md", children: availableLineIds.map((id3) => /* @__PURE__ */ jsx(SelectItem, { value: id3, children: lineNames[id3] || (id3 === factoryViewId ? "All Lines" : `Line ${id3.substring(0, 4)}`) }, id3)) })
27420
28407
  ] });
27421
28408
  }, [availableLineIds, handleLineChange, selectedLineId, lineNames, factoryViewId, allLineIds.length]);
27422
- const isLoading = !isHydrated || metricsLoading || kpisLoading || isChangingFilter || displayNamesLoading || !displayNamesInitialized;
27423
- if (isLoading) {
27424
- return /* @__PURE__ */ jsx("div", { className: "min-h-screen bg-slate-50", children: /* @__PURE__ */ jsx(LoadingPageCmp, { message: "Loading dashboard..." }) });
28409
+ const isInitialLoading = !isHydrated || !displayNamesInitialized && displayNamesLoading;
28410
+ const isDataLoading = metricsLoading || kpisLoading;
28411
+ if (isInitialLoading) {
28412
+ return /* @__PURE__ */ jsx("div", { className: "min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-slate-50 flex items-center justify-center", children: /* @__PURE__ */ jsx(
28413
+ motion.div,
28414
+ {
28415
+ className: "text-center",
28416
+ initial: { opacity: 0, scale: 0.9 },
28417
+ animate: { opacity: 1, scale: 1 },
28418
+ transition: { duration: 0.5 },
28419
+ children: /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-2xl shadow-2xl p-12 max-w-md mx-auto", children: [
28420
+ /* @__PURE__ */ jsx("div", { className: "relative mb-8", children: /* @__PURE__ */ jsxs("div", { className: "w-24 h-24 mx-auto", children: [
28421
+ /* @__PURE__ */ jsxs("svg", { className: "animate-spin", viewBox: "0 0 100 100", xmlns: "http://www.w3.org/2000/svg", children: [
28422
+ /* @__PURE__ */ jsx("circle", { cx: "50", cy: "50", r: "45", fill: "none", stroke: "#e5e7eb", strokeWidth: "8" }),
28423
+ /* @__PURE__ */ jsx(
28424
+ "circle",
28425
+ {
28426
+ cx: "50",
28427
+ cy: "50",
28428
+ r: "45",
28429
+ fill: "none",
28430
+ stroke: "#3b82f6",
28431
+ strokeWidth: "8",
28432
+ strokeDasharray: "150 283",
28433
+ strokeLinecap: "round",
28434
+ className: "transform -rotate-90 origin-center"
28435
+ }
28436
+ )
28437
+ ] }),
28438
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "w-16 h-16 bg-gradient-to-br from-blue-500 to-blue-600 rounded-full animate-pulse" }) })
28439
+ ] }) }),
28440
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold text-gray-800 mb-2", children: "Loading Dashboard" }),
28441
+ /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-6", children: "Initializing your workspace..." }),
28442
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
28443
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center space-x-2 text-sm text-gray-500", children: [
28444
+ /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-pulse" }),
28445
+ /* @__PURE__ */ jsx("span", { children: "Connecting to services" })
28446
+ ] }),
28447
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center space-x-2 text-sm text-gray-500", children: [
28448
+ /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-pulse", style: { animationDelay: "0.2s" } }),
28449
+ /* @__PURE__ */ jsx("span", { children: "Loading workspace configurations" })
28450
+ ] }),
28451
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center space-x-2 text-sm text-gray-500", children: [
28452
+ /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-pulse", style: { animationDelay: "0.4s" } }),
28453
+ /* @__PURE__ */ jsx("span", { children: "Preparing dashboard view" })
28454
+ ] })
28455
+ ] })
28456
+ ] })
28457
+ }
28458
+ ) });
27425
28459
  }
27426
28460
  if (errorMessage || displayNamesError) {
27427
28461
  return /* @__PURE__ */ jsx("div", { className: "flex h-screen items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg bg-white p-6 shadow-lg", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3 text-red-500", children: [
@@ -27432,52 +28466,64 @@ function HomeView({
27432
28466
  ] })
27433
28467
  ] }) }) });
27434
28468
  }
27435
- if ((metricsLoading || kpisLoading) && (!workspaceMetrics || workspaceMetrics.length === 0) && selectedLineId !== factoryViewId) {
27436
- return /* @__PURE__ */ jsx("div", { className: "min-h-screen bg-slate-50", children: /* @__PURE__ */ jsx(LoadingPageCmp, { message: "Loading metrics..." }) });
27437
- }
27438
- return /* @__PURE__ */ jsxs(
28469
+ return /* @__PURE__ */ jsx(
27439
28470
  motion.div,
27440
28471
  {
27441
28472
  className: "flex min-h-screen bg-slate-50",
27442
28473
  initial: { opacity: 1 },
27443
28474
  animate: { opacity: 1 },
27444
- children: [
27445
- /* @__PURE__ */ jsx(LoadingOverlayCmp, { isVisible: isChangingFilter, message: "Loading new metrics..." }),
27446
- /* @__PURE__ */ jsxs("div", { className: "relative flex flex-1", children: [
27447
- /* @__PURE__ */ jsxs("main", { className: "flex flex-1 flex-col", children: [
27448
- /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-30 sm:static bg-white shadow-sm border-b border-gray-200/80", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between px-3 sm:px-6 lg:px-8 py-1.5 sm:py-2.5", children: /* @__PURE__ */ jsx(
27449
- DashboardHeader,
27450
- {
27451
- lineTitle,
27452
- className: "w-full",
27453
- headerControls: memoizedKPIs ? /* @__PURE__ */ jsx(KPISection2, { kpis: memoizedKPIs, className: "w-full sm:w-auto" }) : null
27454
- }
27455
- ) }) }),
27456
- /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto sm:overflow-hidden relative", children: [
27457
- lineSelectorComponent && /* @__PURE__ */ jsx("div", { className: "absolute right-3 top-2 sm:right-6 sm:top-3 z-30", children: lineSelectorComponent }),
27458
- memoizedWorkspaceMetrics.length > 0 ? /* @__PURE__ */ jsx("div", { className: "h-full sm:h-full min-h-[calc(100vh-80px)] sm:min-h-0", children: React14__default.createElement(WorkspaceGrid, {
27459
- workspaces: memoizedWorkspaceMetrics,
27460
- lineNames,
27461
- factoryView: factoryViewId,
27462
- videoSources,
27463
- className: "h-full"
27464
- }) }) : /* @__PURE__ */ jsx(NoWorkspaceData, { message: "No workspace data available. Select another line or check configurations." })
27465
- ] })
27466
- ] }),
27467
- /* @__PURE__ */ jsx(
27468
- BreakNotificationPopup,
28475
+ children: /* @__PURE__ */ jsxs("div", { className: "relative flex flex-1", children: [
28476
+ /* @__PURE__ */ jsxs("main", { className: "flex flex-1 flex-col", children: [
28477
+ /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-30 sm:static bg-white shadow-sm border-b border-gray-200/80", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between px-3 sm:px-6 lg:px-8 py-1.5 sm:py-2.5", children: /* @__PURE__ */ jsx(
28478
+ DashboardHeader,
27469
28479
  {
27470
- activeBreaks,
27471
- lineNames,
27472
- isVisible: !breaksLoading && !breaksError
28480
+ lineTitle,
28481
+ className: "w-full",
28482
+ headerControls: memoizedKPIs ? /* @__PURE__ */ jsx(KPISection2, { kpis: memoizedKPIs, className: "w-full sm:w-auto" }) : null
27473
28483
  }
27474
- )
27475
- ] })
27476
- ]
28484
+ ) }) }),
28485
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto sm:overflow-hidden relative", children: [
28486
+ lineSelectorComponent && /* @__PURE__ */ jsx("div", { className: "absolute right-3 top-2 sm:right-6 sm:top-3 z-30", children: lineSelectorComponent }),
28487
+ /* @__PURE__ */ jsx("div", { className: "h-full sm:h-full min-h-[calc(100vh-80px)] sm:min-h-0", children: isDataLoading && hasInitialDataLoaded && memoizedWorkspaceMetrics.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-3 sm:px-6 lg:px-8 py-4", children: /* @__PURE__ */ jsx(LoadingSkeleton, { type: "workspace-card", count: 8, className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4" }) }) : memoizedWorkspaceMetrics.length > 0 ? /* @__PURE__ */ jsx(
28488
+ motion.div,
28489
+ {
28490
+ initial: { opacity: 0, scale: 0.98 },
28491
+ animate: { opacity: 1, scale: 1 },
28492
+ transition: { duration: 0.3 },
28493
+ className: "h-full",
28494
+ children: React19__default.createElement(WorkspaceGrid, {
28495
+ workspaces: memoizedWorkspaceMetrics,
28496
+ lineNames,
28497
+ factoryView: factoryViewId,
28498
+ videoSources,
28499
+ className: "h-full"
28500
+ })
28501
+ },
28502
+ selectedLineId
28503
+ ) : /* @__PURE__ */ jsx(
28504
+ motion.div,
28505
+ {
28506
+ initial: { opacity: 0 },
28507
+ animate: { opacity: 1 },
28508
+ transition: { duration: 0.3 },
28509
+ children: /* @__PURE__ */ jsx(NoWorkspaceData, { message: "No workspace data available. Select another line or check configurations." })
28510
+ }
28511
+ ) })
28512
+ ] })
28513
+ ] }),
28514
+ /* @__PURE__ */ jsx(
28515
+ BreakNotificationPopup,
28516
+ {
28517
+ activeBreaks,
28518
+ lineNames,
28519
+ isVisible: !breaksLoading && !breaksError
28520
+ }
28521
+ )
28522
+ ] })
27477
28523
  }
27478
28524
  );
27479
28525
  }
27480
- var AuthenticatedHomeView = withAuth(React14__default.memo(HomeView));
28526
+ var AuthenticatedHomeView = withAuth(React19__default.memo(HomeView));
27481
28527
  var HomeView_default = HomeView;
27482
28528
 
27483
28529
  // src/views/kpi-detail-view.types.ts
@@ -28310,7 +29356,7 @@ var LineCard = ({ line, onClick }) => {
28310
29356
  const { kpis, isLoading, error } = useLineKPIs({ lineId: line.id });
28311
29357
  const shiftConfig = useShiftConfig();
28312
29358
  const dateTimeConfig = useDateTimeConfig();
28313
- const isOnTrack = React14__default.useMemo(() => {
29359
+ const isOnTrack = React19__default.useMemo(() => {
28314
29360
  if (!kpis) return null;
28315
29361
  const currentTime = /* @__PURE__ */ new Date();
28316
29362
  const timezone = dateTimeConfig.defaultTimezone || "Asia/Kolkata";
@@ -30335,7 +31381,7 @@ var BulkConfigureModal = ({
30335
31381
  },
30336
31382
  className: "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-blue-400",
30337
31383
  min: "0",
30338
- step: "1",
31384
+ step: "0.01",
30339
31385
  placeholder: "Enter cycle time"
30340
31386
  }
30341
31387
  ),
@@ -30456,6 +31502,343 @@ var BulkConfigureModal = ({
30456
31502
  );
30457
31503
  };
30458
31504
  var BulkConfigureModal_default = BulkConfigureModal;
31505
+ var SKUModal = ({
31506
+ isOpen,
31507
+ onClose,
31508
+ onSave,
31509
+ editingSKU
31510
+ }) => {
31511
+ const config = useDashboardConfig();
31512
+ const defaultProductionTarget = config?.skuConfig?.defaultProductionTarget || 1e3;
31513
+ const [formData, setFormData] = useState({
31514
+ sku_id: "",
31515
+ production_target: defaultProductionTarget,
31516
+ attributes: {}
31517
+ });
31518
+ const [isSaving, setIsSaving] = useState(false);
31519
+ const [error, setError] = useState(null);
31520
+ useEffect(() => {
31521
+ if (editingSKU) {
31522
+ setFormData({
31523
+ sku_id: editingSKU.sku_id,
31524
+ production_target: editingSKU.production_target,
31525
+ attributes: editingSKU.attributes || {}
31526
+ });
31527
+ } else {
31528
+ setFormData({
31529
+ sku_id: "",
31530
+ production_target: defaultProductionTarget,
31531
+ attributes: {}
31532
+ });
31533
+ }
31534
+ setError(null);
31535
+ }, [editingSKU, defaultProductionTarget]);
31536
+ const handleSubmit = async (e) => {
31537
+ e.preventDefault();
31538
+ setError(null);
31539
+ if (!formData.sku_id.trim()) {
31540
+ setError("SKU ID is required");
31541
+ return;
31542
+ }
31543
+ if (formData.production_target <= 0) {
31544
+ setError("Production target must be greater than 0");
31545
+ return;
31546
+ }
31547
+ setIsSaving(true);
31548
+ try {
31549
+ const skuData = {
31550
+ sku_id: formData.sku_id.trim(),
31551
+ production_target: formData.production_target,
31552
+ attributes: formData.attributes,
31553
+ company_id: config?.entityConfig?.companyId || ""
31554
+ };
31555
+ await onSave(skuData);
31556
+ onClose();
31557
+ } catch (err) {
31558
+ setError(err instanceof Error ? err.message : "Failed to save SKU");
31559
+ } finally {
31560
+ setIsSaving(false);
31561
+ }
31562
+ };
31563
+ if (!isOpen) return null;
31564
+ return /* @__PURE__ */ jsx("div", { className: "fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 p-4", children: /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl shadow-2xl max-w-md w-full transform transition-all", children: [
31565
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-6 border-b border-gray-200", children: [
31566
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-900", children: editingSKU ? "Edit SKU" : "Add New SKU" }),
31567
+ /* @__PURE__ */ jsx(
31568
+ "button",
31569
+ {
31570
+ onClick: onClose,
31571
+ className: "text-gray-400 hover:text-gray-600 transition-colors p-1 hover:bg-gray-100 rounded-lg",
31572
+ disabled: isSaving,
31573
+ children: /* @__PURE__ */ jsx(X, { className: "w-5 h-5" })
31574
+ }
31575
+ )
31576
+ ] }),
31577
+ /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "p-6", children: [
31578
+ error && /* @__PURE__ */ jsx("div", { className: "mb-4 p-3 bg-red-50 border border-red-200 text-red-700 rounded-lg text-sm", children: error }),
31579
+ /* @__PURE__ */ jsxs("div", { className: "space-y-5", children: [
31580
+ /* @__PURE__ */ jsxs("div", { children: [
31581
+ /* @__PURE__ */ jsxs("label", { htmlFor: "sku_id", className: "block text-sm font-medium text-gray-700 mb-2", children: [
31582
+ "SKU ID ",
31583
+ /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
31584
+ ] }),
31585
+ /* @__PURE__ */ jsx(
31586
+ "input",
31587
+ {
31588
+ type: "text",
31589
+ id: "sku_id",
31590
+ value: formData.sku_id,
31591
+ onChange: (e) => setFormData({ ...formData, sku_id: e.target.value }),
31592
+ className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200",
31593
+ placeholder: "Enter SKU ID",
31594
+ disabled: isSaving || !!editingSKU,
31595
+ required: true
31596
+ }
31597
+ )
31598
+ ] }),
31599
+ /* @__PURE__ */ jsxs("div", { children: [
31600
+ /* @__PURE__ */ jsxs("label", { htmlFor: "production_target", className: "block text-sm font-medium text-gray-700 mb-2", children: [
31601
+ "Production Target ",
31602
+ /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
31603
+ ] }),
31604
+ /* @__PURE__ */ jsx(
31605
+ "input",
31606
+ {
31607
+ type: "number",
31608
+ id: "production_target",
31609
+ value: formData.production_target,
31610
+ onChange: (e) => setFormData({ ...formData, production_target: parseInt(e.target.value) || 0 }),
31611
+ className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200",
31612
+ placeholder: "Enter production target",
31613
+ min: "1",
31614
+ disabled: isSaving,
31615
+ required: true
31616
+ }
31617
+ ),
31618
+ /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-sm text-gray-500", children: "Units per day for this SKU" })
31619
+ ] }),
31620
+ /* @__PURE__ */ jsxs("div", { children: [
31621
+ /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Additional Attributes (Optional)" }),
31622
+ /* @__PURE__ */ jsx(
31623
+ "textarea",
31624
+ {
31625
+ value: JSON.stringify(formData.attributes, null, 2),
31626
+ onChange: (e) => {
31627
+ try {
31628
+ const parsed = JSON.parse(e.target.value);
31629
+ setFormData({ ...formData, attributes: parsed });
31630
+ } catch {
31631
+ }
31632
+ },
31633
+ className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent font-mono text-sm transition-all duration-200",
31634
+ rows: 4,
31635
+ placeholder: '{"color": "red", "size": "large"}',
31636
+ disabled: isSaving
31637
+ }
31638
+ ),
31639
+ /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-sm text-gray-500", children: "Enter valid JSON for additional SKU attributes" })
31640
+ ] })
31641
+ ] }),
31642
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-end space-x-3 mt-6 pt-4 border-t border-gray-200", children: [
31643
+ /* @__PURE__ */ jsx(
31644
+ "button",
31645
+ {
31646
+ type: "button",
31647
+ onClick: onClose,
31648
+ className: "px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 transition-all duration-200",
31649
+ disabled: isSaving,
31650
+ children: "Cancel"
31651
+ }
31652
+ ),
31653
+ /* @__PURE__ */ jsx(
31654
+ "button",
31655
+ {
31656
+ type: "submit",
31657
+ className: "px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 shadow-sm",
31658
+ disabled: isSaving,
31659
+ children: isSaving ? "Saving..." : editingSKU ? "Update" : "Create"
31660
+ }
31661
+ )
31662
+ ] })
31663
+ ] })
31664
+ ] }) });
31665
+ };
31666
+ var SKUSelector = ({
31667
+ onSelect,
31668
+ selectedSKU,
31669
+ availableSKUs,
31670
+ className = "",
31671
+ lineId,
31672
+ disabled = false,
31673
+ required = false
31674
+ }) => {
31675
+ const [isOpen, setIsOpen] = useState(false);
31676
+ const [searchTerm, setSearchTerm] = useState("");
31677
+ const dropdownRef = useRef(null);
31678
+ useEffect(() => {
31679
+ const handleClickOutside = (event) => {
31680
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
31681
+ setIsOpen(false);
31682
+ }
31683
+ };
31684
+ document.addEventListener("mousedown", handleClickOutside);
31685
+ return () => {
31686
+ document.removeEventListener("mousedown", handleClickOutside);
31687
+ };
31688
+ }, []);
31689
+ const filteredSKUs = availableSKUs.filter(
31690
+ (sku) => sku.sku_id.toLowerCase().includes(searchTerm.toLowerCase()) || JSON.stringify(sku.attributes).toLowerCase().includes(searchTerm.toLowerCase())
31691
+ );
31692
+ const handleSelect = (sku) => {
31693
+ onSelect(sku);
31694
+ setIsOpen(false);
31695
+ setSearchTerm("");
31696
+ };
31697
+ return /* @__PURE__ */ jsxs("div", { className: `relative ${className}`, ref: dropdownRef, children: [
31698
+ /* @__PURE__ */ jsx(
31699
+ "button",
31700
+ {
31701
+ type: "button",
31702
+ onClick: () => !disabled && setIsOpen(!isOpen),
31703
+ className: `
31704
+ w-full px-3 py-2 text-left bg-white border rounded-md shadow-sm
31705
+ ${disabled ? "bg-gray-100 cursor-not-allowed" : "hover:bg-gray-50 cursor-pointer"}
31706
+ ${required && !selectedSKU ? "border-red-300" : "border-gray-300"}
31707
+ focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500
31708
+ `,
31709
+ disabled,
31710
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
31711
+ /* @__PURE__ */ jsx("span", { className: selectedSKU ? "text-gray-900" : "text-gray-500", children: selectedSKU ? /* @__PURE__ */ jsxs("div", { children: [
31712
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: selectedSKU.sku_id }),
31713
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-gray-500 ml-2", children: [
31714
+ "(Target: ",
31715
+ selectedSKU.production_target,
31716
+ " units/day)"
31717
+ ] })
31718
+ ] }) : "Select SKU" }),
31719
+ /* @__PURE__ */ jsx(ChevronDown, { className: `w-4 h-4 text-gray-400 transition-transform ${isOpen ? "rotate-180" : ""}` })
31720
+ ] })
31721
+ }
31722
+ ),
31723
+ isOpen && /* @__PURE__ */ jsxs("div", { className: "absolute z-10 w-full mt-1 bg-white border border-gray-300 rounded-md shadow-lg", children: [
31724
+ /* @__PURE__ */ jsx("div", { className: "p-2 border-b", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
31725
+ /* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" }),
31726
+ /* @__PURE__ */ jsx(
31727
+ "input",
31728
+ {
31729
+ type: "text",
31730
+ value: searchTerm,
31731
+ onChange: (e) => setSearchTerm(e.target.value),
31732
+ placeholder: "Search SKUs...",
31733
+ className: "w-full pl-9 pr-3 py-2 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500",
31734
+ onClick: (e) => e.stopPropagation()
31735
+ }
31736
+ )
31737
+ ] }) }),
31738
+ /* @__PURE__ */ jsxs("div", { className: "max-h-60 overflow-y-auto", children: [
31739
+ !required && /* @__PURE__ */ jsx(
31740
+ "button",
31741
+ {
31742
+ onClick: () => handleSelect(null),
31743
+ className: "w-full px-3 py-2 text-left text-sm hover:bg-gray-100 focus:outline-none focus:bg-gray-100",
31744
+ children: /* @__PURE__ */ jsx("span", { className: "text-gray-500", children: "No SKU" })
31745
+ }
31746
+ ),
31747
+ filteredSKUs.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-sm text-gray-500", children: "No SKUs found" }) : filteredSKUs.map((sku) => /* @__PURE__ */ jsx(
31748
+ "button",
31749
+ {
31750
+ onClick: () => handleSelect(sku),
31751
+ className: `
31752
+ w-full px-3 py-2 text-left text-sm hover:bg-gray-100 focus:outline-none focus:bg-gray-100
31753
+ ${selectedSKU?.id === sku.id ? "bg-blue-50" : ""}
31754
+ `,
31755
+ children: /* @__PURE__ */ jsxs("div", { children: [
31756
+ /* @__PURE__ */ jsx("div", { className: "font-medium", children: sku.sku_id }),
31757
+ /* @__PURE__ */ jsxs("div", { className: "text-xs text-gray-500", children: [
31758
+ "Target: ",
31759
+ sku.production_target,
31760
+ " units/day",
31761
+ Object.keys(sku.attributes || {}).length > 0 && /* @__PURE__ */ jsxs("span", { className: "ml-2", children: [
31762
+ "\u2022 ",
31763
+ Object.entries(sku.attributes).map(([key, value]) => `${key}: ${value}`).join(", ")
31764
+ ] })
31765
+ ] })
31766
+ ] })
31767
+ },
31768
+ sku.id
31769
+ ))
31770
+ ] })
31771
+ ] })
31772
+ ] });
31773
+ };
31774
+ var SKUList = ({
31775
+ skus,
31776
+ onEdit,
31777
+ onDelete,
31778
+ isLoading = false
31779
+ }) => {
31780
+ if (isLoading) {
31781
+ return /* @__PURE__ */ jsx("div", { className: "bg-white rounded-xl shadow-sm border border-gray-200 p-8", children: /* @__PURE__ */ jsxs("div", { className: "flex justify-center items-center", children: [
31782
+ /* @__PURE__ */ jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" }),
31783
+ /* @__PURE__ */ jsx("span", { className: "ml-3 text-gray-600", children: "Loading SKUs..." })
31784
+ ] }) });
31785
+ }
31786
+ if (skus.length === 0) {
31787
+ return /* @__PURE__ */ jsx("div", { className: "bg-white rounded-xl shadow-sm border border-gray-200 p-12", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
31788
+ /* @__PURE__ */ jsx(Package, { className: "mx-auto h-12 w-12 text-gray-400" }),
31789
+ /* @__PURE__ */ jsx("h3", { className: "mt-2 text-lg font-medium text-gray-900", children: "No SKUs found" }),
31790
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-gray-500", children: "Get started by creating a new SKU for production planning." })
31791
+ ] }) });
31792
+ }
31793
+ return /* @__PURE__ */ jsx("div", { className: "bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-gray-200", children: [
31794
+ /* @__PURE__ */ jsx("thead", { className: "bg-gray-50", children: /* @__PURE__ */ jsxs("tr", { children: [
31795
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "SKU ID" }),
31796
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Production Target" }),
31797
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Attributes" }),
31798
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Status" }),
31799
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Created" }),
31800
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "relative px-6 py-3", children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Actions" }) })
31801
+ ] }) }),
31802
+ /* @__PURE__ */ jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: skus.map((sku) => /* @__PURE__ */ jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [
31803
+ /* @__PURE__ */ jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold text-gray-900", children: sku.sku_id }) }),
31804
+ /* @__PURE__ */ jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: /* @__PURE__ */ jsxs("div", { className: "text-sm font-medium text-gray-700", children: [
31805
+ sku.production_target.toLocaleString(),
31806
+ " units/day"
31807
+ ] }) }),
31808
+ /* @__PURE__ */ jsx("td", { className: "px-6 py-4", children: /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-500", children: Object.keys(sku.attributes || {}).length === 0 ? /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: "No attributes" }) : /* @__PURE__ */ jsx("div", { className: "max-w-xs truncate", children: Object.entries(sku.attributes).map(([key, value], index) => /* @__PURE__ */ jsxs("span", { children: [
31809
+ index > 0 && ", ",
31810
+ /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
31811
+ key,
31812
+ ":"
31813
+ ] }),
31814
+ " ",
31815
+ String(value)
31816
+ ] }, key)) }) }) }),
31817
+ /* @__PURE__ */ jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: /* @__PURE__ */ jsx("span", { className: `inline-flex px-2 py-1 text-xs font-semibold rounded-full ${sku.is_active ? "bg-green-100 text-green-800" : "bg-gray-100 text-gray-800"}`, children: sku.is_active ? "Active" : "Inactive" }) }),
31818
+ /* @__PURE__ */ jsx("td", { className: "px-6 py-4 whitespace-nowrap text-sm text-gray-500", children: new Date(sku.created_at).toLocaleDateString() }),
31819
+ /* @__PURE__ */ jsxs("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm font-medium", children: [
31820
+ /* @__PURE__ */ jsx(
31821
+ "button",
31822
+ {
31823
+ onClick: () => onEdit(sku),
31824
+ className: "text-blue-600 hover:text-blue-800 mr-3 transition-colors duration-150 p-1 hover:bg-blue-50 rounded",
31825
+ title: "Edit SKU",
31826
+ children: /* @__PURE__ */ jsx(Edit2, { className: "w-4 h-4" })
31827
+ }
31828
+ ),
31829
+ /* @__PURE__ */ jsx(
31830
+ "button",
31831
+ {
31832
+ onClick: () => onDelete(sku),
31833
+ className: "text-red-600 hover:text-red-800 transition-colors duration-150 p-1 hover:bg-red-50 rounded",
31834
+ title: "Delete SKU",
31835
+ children: /* @__PURE__ */ jsx(Trash2, { className: "w-4 h-4" })
31836
+ }
31837
+ )
31838
+ ] })
31839
+ ] }, sku.id)) })
31840
+ ] }) }) });
31841
+ };
30459
31842
  var TargetsViewUI = ({
30460
31843
  isLoading,
30461
31844
  lineWorkspaces,
@@ -30474,7 +31857,12 @@ var TargetsViewUI = ({
30474
31857
  onShiftChange,
30475
31858
  onSaveLine,
30476
31859
  onToggleBulkConfigure,
30477
- onBulkConfigure
31860
+ onBulkConfigure,
31861
+ // SKU props
31862
+ skuEnabled = false,
31863
+ skus = [],
31864
+ onUpdateSelectedSKU,
31865
+ skuRequired = false
30478
31866
  }) => {
30479
31867
  if (isLoading) {
30480
31868
  return /* @__PURE__ */ jsx("div", { className: "flex h-screen bg-gray-50", children: /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsx(Loader2, { className: "w-8 h-8 animate-spin text-blue-600" }) }) });
@@ -30590,6 +31978,26 @@ var TargetsViewUI = ({
30590
31978
  ] })
30591
31979
  ] }) }),
30592
31980
  line.isOpen && /* @__PURE__ */ jsxs("div", { id: `line-${lineId}-content`, className: "border-t border-gray-200", children: [
31981
+ 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: [
31982
+ /* @__PURE__ */ jsx("label", { htmlFor: `sku-${lineId}`, className: "text-sm font-medium text-gray-700", children: "Select SKU:" }),
31983
+ /* @__PURE__ */ jsx("div", { className: "flex-1 max-w-md", children: /* @__PURE__ */ jsx(
31984
+ SKUSelector,
31985
+ {
31986
+ onSelect: (sku) => onUpdateSelectedSKU?.(lineId, sku),
31987
+ selectedSKU: line.selectedSKU || null,
31988
+ availableSKUs: skus,
31989
+ lineId,
31990
+ required: skuRequired,
31991
+ className: "w-full"
31992
+ }
31993
+ ) }),
31994
+ line.selectedSKU && /* @__PURE__ */ jsxs("div", { className: "text-sm text-gray-600", children: [
31995
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Production Target:" }),
31996
+ " ",
31997
+ line.selectedSKU.production_target.toLocaleString(),
31998
+ " units/day"
31999
+ ] })
32000
+ ] }) }),
30593
32001
  /* @__PURE__ */ jsx("div", { className: "px-6 py-3 bg-gray-50 border-b border-gray-200", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-12 gap-6 text-sm font-medium text-gray-600", children: [
30594
32002
  /* @__PURE__ */ jsx("div", { className: "col-span-2", children: "Workspace" }),
30595
32003
  /* @__PURE__ */ jsx("div", { className: "col-span-2", children: "Action Type" }),
@@ -30636,7 +32044,7 @@ var TargetsViewUI = ({
30636
32044
  onChange: (e) => onUpdateWorkspaceTarget(lineId, workspace.id, "targetCycleTime", Number(e.target.value) || ""),
30637
32045
  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",
30638
32046
  min: "0",
30639
- step: "1",
32047
+ step: "0.01",
30640
32048
  placeholder: "Enter cycle time"
30641
32049
  }
30642
32050
  ) }),
@@ -30727,6 +32135,9 @@ var TargetsView = ({
30727
32135
  const supabase = useSupabase();
30728
32136
  const auth = useAuth();
30729
32137
  userId || auth?.user?.id;
32138
+ const dashboardConfig = useDashboardConfig();
32139
+ const { skus, isLoading: skusLoading } = useSKUs(companyId);
32140
+ const skuEnabled = dashboardConfig?.skuConfig?.enabled || false;
30730
32141
  useEffect(() => {
30731
32142
  const fetchLineDetails = async () => {
30732
32143
  if (!supabase || lineIds.length === 0) return;
@@ -31094,6 +32505,41 @@ var TargetsView = ({
31094
32505
  }
31095
32506
  }));
31096
32507
  };
32508
+ const updateSelectedSKU = (lineId, sku) => {
32509
+ setLineWorkspaces((prev) => ({
32510
+ ...prev,
32511
+ [lineId]: {
32512
+ ...prev[lineId],
32513
+ selectedSKU: sku,
32514
+ productId: sku?.sku_id || prev[lineId].productId
32515
+ // Update productId with SKU ID
32516
+ }
32517
+ }));
32518
+ if (sku && sku.production_target > 0) {
32519
+ const lineData = lineWorkspaces[lineId];
32520
+ const workspaceCount = lineData.workspaces.length;
32521
+ if (workspaceCount > 0) {
32522
+ const targetPerWorkspace = Math.floor(sku.production_target / workspaceCount);
32523
+ const pphPerWorkspace = calculatePPH(
32524
+ lineData.shiftHours > 0 ? lineData.shiftHours * 3600 / targetPerWorkspace : 0,
32525
+ lineData.breaks,
32526
+ lineData.shiftHours
32527
+ );
32528
+ setLineWorkspaces((prev) => ({
32529
+ ...prev,
32530
+ [lineId]: {
32531
+ ...prev[lineId],
32532
+ workspaces: prev[lineId].workspaces.map((ws) => ({
32533
+ ...ws,
32534
+ targetDayOutput: targetPerWorkspace,
32535
+ targetPPH: pphPerWorkspace,
32536
+ targetCycleTime: lineData.shiftHours > 0 ? parseFloat((lineData.shiftHours * 3600 / targetPerWorkspace).toFixed(2)) : ""
32537
+ }))
32538
+ }
32539
+ }));
32540
+ }
32541
+ }
32542
+ };
31097
32543
  const updateWorkspaceTarget = (lineId, workspaceId, field, value) => {
31098
32544
  setLineWorkspaces((prev) => {
31099
32545
  const shiftHours = prev[lineId].shiftHours;
@@ -31226,6 +32672,11 @@ var TargetsView = ({
31226
32672
  return;
31227
32673
  }
31228
32674
  console.log(`[handleSaveLine] factoryId for ${lineId}: ${lineDataToSave.factoryId}`);
32675
+ if (skuEnabled && dashboardConfig?.skuConfig?.requireSKUSelection && !lineDataToSave.selectedSKU) {
32676
+ console.log(`[handleSaveLine] Exiting: SKU selection required but not selected for lineId: ${lineId}`);
32677
+ toast.error("Please select a SKU before saving.");
32678
+ return;
32679
+ }
31229
32680
  const currentFactoryId = lineDataToSave.factoryId;
31230
32681
  const currentDate = getOperationalDate();
31231
32682
  console.log(`[handleSaveLine] currentDate: ${currentDate}, selectedShift: ${selectedShift}`);
@@ -31239,8 +32690,9 @@ var TargetsView = ({
31239
32690
  ideal_cycle_time: Number(ws.targetCycleTime) || 0,
31240
32691
  total_day_output: Number(ws.targetDayOutput) || 0,
31241
32692
  action_name: ws.actionType === "assembly" ? ACTION_NAMES.ASSEMBLY : ACTION_NAMES.PACKAGING,
31242
- updated_by: currentEffectiveUserId
32693
+ updated_by: currentEffectiveUserId,
31243
32694
  // Use the potentially hardcoded ID
32695
+ ...skuEnabled && lineDataToSave.selectedSKU ? { sku_id: lineDataToSave.selectedSKU.id } : {}
31244
32696
  }));
31245
32697
  console.log(`[handleSaveLine] workspaceThresholdUpdates for ${lineId}:`, workspaceThresholdUpdates);
31246
32698
  await workspaceService.updateActionThresholds(workspaceThresholdUpdates);
@@ -31252,7 +32704,8 @@ var TargetsView = ({
31252
32704
  shift_id: selectedShift,
31253
32705
  product_code: lineDataToSave.productId,
31254
32706
  threshold_day_output: lineDataToSave.workspaces.reduce((acc, ws) => acc + (Number(ws.targetDayOutput) || 0), 0),
31255
- threshold_pph: lineDataToSave.workspaces.reduce((acc, ws) => acc + (Number(ws.targetPPH) || 0), 0)
32707
+ threshold_pph: lineDataToSave.workspaces.reduce((acc, ws) => acc + (Number(ws.targetPPH) || 0), 0),
32708
+ ...skuEnabled && lineDataToSave.selectedSKU ? { sku_id: lineDataToSave.selectedSKU.id } : {}
31256
32709
  };
31257
32710
  console.log(`[handleSaveLine] lineThresholdData for upsert on ${lineId}:`, lineThresholdData);
31258
32711
  const { error: lineUpsertError } = await supabase.from("line_thresholds").upsert(lineThresholdData, { onConflict: "factory_id,line_id,date,shift_id" });
@@ -31347,7 +32800,7 @@ var TargetsView = ({
31347
32800
  return /* @__PURE__ */ jsx(
31348
32801
  TargetsViewUI_default,
31349
32802
  {
31350
- isLoading,
32803
+ isLoading: isLoading || skusLoading,
31351
32804
  lineWorkspaces,
31352
32805
  lineNames,
31353
32806
  savingLines,
@@ -31364,7 +32817,11 @@ var TargetsView = ({
31364
32817
  onShiftChange: handleShiftChange,
31365
32818
  onSaveLine: handleSaveLine,
31366
32819
  onToggleBulkConfigure: handleToggleBulkConfigure,
31367
- onBulkConfigure: handleBulkConfigure
32820
+ onBulkConfigure: handleBulkConfigure,
32821
+ skuEnabled,
32822
+ skus,
32823
+ onUpdateSelectedSKU: updateSelectedSKU,
32824
+ skuRequired: dashboardConfig?.skuConfig?.requireSKUSelection || false
31368
32825
  }
31369
32826
  );
31370
32827
  };
@@ -31623,7 +33080,43 @@ var WorkspaceDetailView = ({
31623
33080
  }
31624
33081
  };
31625
33082
  if (loading) {
31626
- return /* @__PURE__ */ jsx("div", { className: "min-h-screen flex items-center justify-center bg-slate-50", children: /* @__PURE__ */ jsx("div", { className: "text-xl text-gray-600", children: "Loading workspace details..." }) });
33083
+ return /* @__PURE__ */ jsx(
33084
+ motion.div,
33085
+ {
33086
+ className: "min-h-screen bg-slate-50",
33087
+ initial: { opacity: 0 },
33088
+ animate: { opacity: 1 },
33089
+ transition: { duration: 0.3 },
33090
+ children: /* @__PURE__ */ jsxs("div", { className: "min-h-screen w-full flex flex-col bg-slate-50", children: [
33091
+ /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-10 px-2 sm:px-2.5 lg:px-3 py-1.5 sm:py-2 lg:py-3 flex flex-col shadow-sm bg-white", children: /* @__PURE__ */ jsxs("div", { className: "relative flex items-center", children: [
33092
+ /* @__PURE__ */ jsx("div", { className: "absolute left-0 animate-pulse", children: /* @__PURE__ */ jsx("div", { className: "h-8 w-20 bg-gray-200 rounded" }) }),
33093
+ /* @__PURE__ */ jsx("div", { className: "absolute left-1/2 transform -translate-x-1/2 animate-pulse", children: /* @__PURE__ */ jsx("div", { className: "h-6 w-40 bg-gray-200 rounded" }) }),
33094
+ /* @__PURE__ */ jsx("div", { className: "w-full h-8" })
33095
+ ] }) }),
33096
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 p-4 sm:p-6 lg:p-8", children: [
33097
+ /* @__PURE__ */ jsx("div", { className: "mb-6", children: /* @__PURE__ */ jsxs("div", { className: "flex space-x-4 justify-center animate-pulse", children: [
33098
+ /* @__PURE__ */ jsx("div", { className: "h-10 w-32 bg-gray-200 rounded-lg" }),
33099
+ /* @__PURE__ */ jsx("div", { className: "h-10 w-32 bg-gray-200 rounded-lg" }),
33100
+ /* @__PURE__ */ jsx("div", { className: "h-10 w-32 bg-gray-200 rounded-lg" })
33101
+ ] }) }),
33102
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-4 gap-4 mb-6", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx("div", { className: "bg-white rounded-lg p-4 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse", children: [
33103
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-20 bg-gray-200 rounded mb-2" }),
33104
+ /* @__PURE__ */ jsx("div", { className: "h-8 w-16 bg-gray-200 rounded" })
33105
+ ] }) }, i)) }),
33106
+ /* @__PURE__ */ jsx("div", { className: "bg-white rounded-lg p-6 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse", children: [
33107
+ /* @__PURE__ */ jsx("div", { className: "h-6 w-40 bg-gray-200 rounded mb-4" }),
33108
+ /* @__PURE__ */ jsx("div", { className: "h-64 bg-gray-100 rounded relative overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "bg-white/80 rounded-lg p-4 shadow-sm", children: [
33109
+ /* @__PURE__ */ jsxs("svg", { className: "animate-spin h-8 w-8 text-blue-500", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
33110
+ /* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
33111
+ /* @__PURE__ */ jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
33112
+ ] }),
33113
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600 mt-2", children: "Loading chart data..." })
33114
+ ] }) }) })
33115
+ ] }) })
33116
+ ] })
33117
+ ] })
33118
+ }
33119
+ );
31627
33120
  }
31628
33121
  if (error) {
31629
33122
  return /* @__PURE__ */ jsxs("div", { className: "min-h-screen p-8 bg-slate-50", children: [
@@ -32063,6 +33556,144 @@ var WorkspaceDetailView = ({
32063
33556
  };
32064
33557
  var WrappedComponent = withAuth(WorkspaceDetailView);
32065
33558
  var WorkspaceDetailView_default = WrappedComponent;
33559
+ var SKUManagementView = () => {
33560
+ const config = useDashboardConfig();
33561
+ const companyId = config?.entityConfig?.companyId || "";
33562
+ const router = useRouter();
33563
+ const { skus, isLoading, error, refetch } = useSKUs(companyId);
33564
+ const [isModalOpen, setIsModalOpen] = useState(false);
33565
+ const [editingSKU, setEditingSKU] = useState(null);
33566
+ const [deleteConfirmSKU, setDeleteConfirmSKU] = useState(null);
33567
+ useEffect(() => {
33568
+ trackCoreEvent("SKU Management Page Viewed");
33569
+ }, []);
33570
+ const handleCreateOrUpdate = async (skuData) => {
33571
+ try {
33572
+ if (editingSKU) {
33573
+ await skuService.updateSKU(editingSKU.id, {
33574
+ production_target: skuData.production_target,
33575
+ attributes: skuData.attributes
33576
+ });
33577
+ trackCoreEvent("SKU Updated", {
33578
+ sku_id: editingSKU.sku_id,
33579
+ production_target: skuData.production_target
33580
+ });
33581
+ } else {
33582
+ const exists = await skuService.checkSKUExists(companyId, skuData.sku_id);
33583
+ if (exists) {
33584
+ throw new Error("SKU ID already exists");
33585
+ }
33586
+ await skuService.createSKU(skuData);
33587
+ trackCoreEvent("SKU Created", {
33588
+ sku_id: skuData.sku_id,
33589
+ production_target: skuData.production_target
33590
+ });
33591
+ }
33592
+ setIsModalOpen(false);
33593
+ setEditingSKU(null);
33594
+ refetch();
33595
+ } catch (error2) {
33596
+ console.error("Error saving SKU:", error2);
33597
+ throw error2;
33598
+ }
33599
+ };
33600
+ const handleEdit = (sku) => {
33601
+ setEditingSKU(sku);
33602
+ setIsModalOpen(true);
33603
+ };
33604
+ const handleDelete = async (sku) => {
33605
+ if (deleteConfirmSKU?.id === sku.id) {
33606
+ try {
33607
+ await skuService.deleteSKU(sku.id);
33608
+ trackCoreEvent("SKU Deleted", { sku_id: sku.sku_id });
33609
+ setDeleteConfirmSKU(null);
33610
+ refetch();
33611
+ } catch (error2) {
33612
+ console.error("Error deleting SKU:", error2);
33613
+ }
33614
+ } else {
33615
+ setDeleteConfirmSKU(sku);
33616
+ setTimeout(() => setDeleteConfirmSKU(null), 3e3);
33617
+ }
33618
+ };
33619
+ const handleAddNew = () => {
33620
+ setEditingSKU(null);
33621
+ setIsModalOpen(true);
33622
+ };
33623
+ const handleBack = () => {
33624
+ router.push("/");
33625
+ };
33626
+ if (!config?.skuConfig?.enabled) {
33627
+ return /* @__PURE__ */ jsx("div", { className: "min-h-screen bg-slate-50 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
33628
+ /* @__PURE__ */ jsx(Package, { className: "mx-auto h-12 w-12 text-gray-400" }),
33629
+ /* @__PURE__ */ jsx("h3", { className: "mt-2 text-sm font-medium text-gray-900", children: "SKU Management Disabled" }),
33630
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-gray-500", children: "SKU management is not enabled for this workspace." })
33631
+ ] }) });
33632
+ }
33633
+ return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-slate-50", children: [
33634
+ /* @__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: [
33635
+ /* @__PURE__ */ jsxs(
33636
+ "button",
33637
+ {
33638
+ onClick: handleBack,
33639
+ className: "absolute left-0 flex items-center gap-2 text-gray-600 hover:text-gray-900 transition-colors",
33640
+ children: [
33641
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "h-5 w-5" }),
33642
+ /* @__PURE__ */ jsx("span", { children: "Back" })
33643
+ ]
33644
+ }
33645
+ ),
33646
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 text-center mx-auto", children: [
33647
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold text-gray-900", children: "SKU Management" }),
33648
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-gray-500", children: "Manage Stock Keeping Units (SKUs) for production planning" })
33649
+ ] }),
33650
+ /* @__PURE__ */ jsxs(
33651
+ "button",
33652
+ {
33653
+ onClick: handleAddNew,
33654
+ className: "absolute right-0 inline-flex items-center px-4 py-2 bg-blue-600 text-white text-sm font-medium rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-all duration-200 shadow-sm",
33655
+ children: [
33656
+ /* @__PURE__ */ jsx(Plus, { className: "w-4 h-4 mr-2" }),
33657
+ "Add SKU"
33658
+ ]
33659
+ }
33660
+ )
33661
+ ] }) }) }),
33662
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-auto", children: /* @__PURE__ */ jsxs("div", { className: "px-4 sm:px-8 py-6", children: [
33663
+ /* @__PURE__ */ jsx("div", { className: "mb-6 bg-gradient-to-r from-blue-50 to-blue-50/50 p-4 rounded-xl border border-blue-100", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-blue-700 font-medium", children: "Create and manage SKUs with production targets. These will be available for selection in the production targets page." }) }),
33664
+ error ? /* @__PURE__ */ jsxs("div", { className: "bg-red-50 border border-red-200 text-red-700 p-4 rounded-lg", children: [
33665
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Error loading SKUs" }),
33666
+ /* @__PURE__ */ jsx("p", { className: "text-sm mt-1", children: error.message })
33667
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
33668
+ /* @__PURE__ */ jsx(
33669
+ SKUList,
33670
+ {
33671
+ skus,
33672
+ onEdit: handleEdit,
33673
+ onDelete: handleDelete,
33674
+ isLoading
33675
+ }
33676
+ ),
33677
+ deleteConfirmSKU && /* @__PURE__ */ jsx("div", { className: "mt-4 bg-yellow-50 border border-yellow-200 text-yellow-800 p-4 rounded-lg", children: /* @__PURE__ */ jsxs("p", { className: "text-sm", children: [
33678
+ "Click delete again to confirm deletion of SKU: ",
33679
+ /* @__PURE__ */ jsx("strong", { children: deleteConfirmSKU.sku_id })
33680
+ ] }) })
33681
+ ] })
33682
+ ] }) }),
33683
+ /* @__PURE__ */ jsx(
33684
+ SKUModal,
33685
+ {
33686
+ isOpen: isModalOpen,
33687
+ onClose: () => {
33688
+ setIsModalOpen(false);
33689
+ setEditingSKU(null);
33690
+ },
33691
+ onSave: handleCreateOrUpdate,
33692
+ editingSKU
33693
+ }
33694
+ )
33695
+ ] });
33696
+ };
32066
33697
  var S3Service = class {
32067
33698
  constructor(config) {
32068
33699
  this.s3Client = null;
@@ -32301,4 +33932,4 @@ var S3Service = class {
32301
33932
  }
32302
33933
  };
32303
33934
 
32304
- export { ACTION_NAMES, AIAgentView_default as AIAgentView, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedTargetsView, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, 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, FactoryView_default as FactoryView, GaugeChart, GridComponentsPlaceholder, 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, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSpinner_default as LoadingSpinner, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, NoWorkspaceData, OptifyeAgentClient, OutputProgressChart, PageHeader, PieChart4 as PieChart, ProfileView_default as ProfileView, RegistryProvider, S3Service, 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, SlackAPI, SupabaseProvider, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TimeDisplay_default as TimeDisplay, TimePickerDropdown, VideoCard, VideoGridView, 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, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultTabForWorkspace, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isTransitionPeriod, isValidLineInfoPayload, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, mergeWithDefaultConfig, optifyeAgentClient, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, s3VideoPreloader, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useActiveBreaks, useAllWorkspaceMetrics, useAnalyticsConfig, useAuth, useAuthConfig, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, useRealtimeLineMetrics, useRegistry, useShiftConfig, useShifts, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, videoPreloader, whatsappService, withAuth, withRegistry, workspaceService };
33935
+ export { ACTION_NAMES, AIAgentView_default as AIAgentView, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedTargetsView, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, 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, FactoryView_default as FactoryView, GaugeChart, GridComponentsPlaceholder, 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, LoadingSpinner_default as LoadingSpinner, LoadingState, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, NoWorkspaceData, OptifyeAgentClient, OutputProgressChart, PageHeader, PieChart4 as PieChart, 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, SlackAPI, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TimeDisplay_default as TimeDisplay, TimePickerDropdown, VideoCard, VideoGridView, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, cacheService, 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, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultTabForWorkspace, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isTransitionPeriod, isValidLineInfoPayload, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, mergeWithDefaultConfig, optifyeAgentClient, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetSubscriptionManager, s3VideoPreloader, skuService, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useActiveBreaks, useAllWorkspaceMetrics, useAnalyticsConfig, useAuth, useAuthConfig, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, useRealtimeLineMetrics, useRegistry, useSKUs, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, videoPreloader, whatsappService, withAuth, withRegistry, workspaceService };