@optifye/dashboard-core 6.6.11 → 6.6.13

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.js CHANGED
@@ -4044,12 +4044,8 @@ var S3ClipsSupabaseService = class {
4044
4044
  id: clip.clip_id,
4045
4045
  src: clip.playlist,
4046
4046
  // Raw playlist content
4047
- timestamp: new Date(clip.date).toLocaleTimeString("en-US", {
4048
- hour12: false,
4049
- hour: "2-digit",
4050
- minute: "2-digit",
4051
- second: "2-digit"
4052
- }),
4047
+ timestamp: clip.timestamp,
4048
+ // Use pre-formatted timestamp from API (already in 12-hour format with seconds)
4053
4049
  severity: this.getSeverityFromClipType(clip.clip_type_name),
4054
4050
  description: this.getDescriptionFromClipType(clip.clip_type_name),
4055
4051
  type: clip.clip_type_name,
@@ -6545,6 +6541,10 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
6545
6541
  const lineIdRef = React21.useRef(lineId);
6546
6542
  const isFetchingRef = React21.useRef(false);
6547
6543
  const updateQueueRef = React21.useRef(false);
6544
+ const onLineMetricsUpdateRef = React21.useRef(onLineMetricsUpdate);
6545
+ React21.useEffect(() => {
6546
+ onLineMetricsUpdateRef.current = onLineMetricsUpdate;
6547
+ }, [onLineMetricsUpdate]);
6548
6548
  const companySpecificMetricsTable = React21.useMemo(
6549
6549
  () => getCompanyMetricsTableName(entityConfig.companyId, "performance_metrics"),
6550
6550
  [entityConfig.companyId]
@@ -6660,13 +6660,17 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
6660
6660
  defaultTimezone,
6661
6661
  shiftConfig
6662
6662
  ]);
6663
+ const fetchAllMetricsRef = React21.useRef(fetchAllMetrics);
6664
+ React21.useEffect(() => {
6665
+ fetchAllMetricsRef.current = fetchAllMetrics;
6666
+ }, [fetchAllMetrics]);
6663
6667
  const queueUpdate = React21.useCallback(() => {
6664
6668
  if (updateQueueRef.current || !supabase) {
6665
6669
  return;
6666
6670
  }
6667
6671
  updateQueueRef.current = true;
6668
- fetchAllMetrics();
6669
- }, [fetchAllMetrics, supabase]);
6672
+ fetchAllMetricsRef.current();
6673
+ }, [supabase]);
6670
6674
  React21.useEffect(() => {
6671
6675
  if (lineId && supabase) {
6672
6676
  fetchAllMetrics();
@@ -6681,11 +6685,11 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
6681
6685
  const operationalDateForSubscription = getOperationalDate(defaultTimezone);
6682
6686
  const targetLineIds = currentLineIdToUse === (entityConfig.factoryViewId || "factory") ? getConfiguredLineIds(entityConfig) : [currentLineIdToUse];
6683
6687
  if (targetLineIds.length === 0) return;
6684
- const wsMetricsFilter = `date=eq.${operationalDateForSubscription}&shift_id=eq.${currentShiftDetails.shiftId}&line_id=in.(${targetLineIds.join(",")})`;
6685
- const lineMetricsFilter = `date=eq.${operationalDateForSubscription}&shift_id=eq.${currentShiftDetails.shiftId}&line_id=in.(${targetLineIds.join(",")})`;
6688
+ const wsMetricsFilter = `line_id=in.(${targetLineIds.map((id3) => `"${id3}"`).join(",")})`;
6689
+ const lineMetricsFilter = `line_id=in.(${targetLineIds.map((id3) => `"${id3}"`).join(",")})`;
6686
6690
  const channels = [];
6687
6691
  const createSubscription = (table, filter2, channelNameBase, callback) => {
6688
- const channelName = `${channelNameBase}-${currentLineIdToUse}-${operationalDateForSubscription}-${currentShiftDetails.shiftId}`.replace(/[^a-zA-Z0-9_-]/g, "");
6692
+ const channelName = `${channelNameBase}-${Date.now()}`.replace(/[^a-zA-Z0-9_-]/g, "");
6689
6693
  const channel = supabase.channel(channelName).on(
6690
6694
  "postgres_changes",
6691
6695
  { event: "*", schema, table, filter: filter2 },
@@ -6695,40 +6699,29 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
6695
6699
  callback();
6696
6700
  }
6697
6701
  }
6698
- ).subscribe((status, err) => {
6699
- if (status === supabaseJs.REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR && err) {
6700
- console.error(`[useDashboardMetrics] Subscription error for ${table} on ${currentLineIdToUse}:`, err.message);
6701
- } else if (status === supabaseJs.REALTIME_SUBSCRIBE_STATES.TIMED_OUT) {
6702
- console.warn(`[useDashboardMetrics] Subscription timeout for ${table} on ${currentLineIdToUse}.`);
6703
- }
6704
- });
6702
+ ).subscribe();
6705
6703
  channels.push(channel);
6706
6704
  };
6707
6705
  createSubscription(companySpecificMetricsTable, wsMetricsFilter, "dashboard-ws-metrics", queueUpdate);
6708
6706
  createSubscription(configuredLineMetricsTable, lineMetricsFilter, "dashboard-line-metrics", () => {
6709
6707
  queueUpdate();
6710
- onLineMetricsUpdate?.();
6708
+ onLineMetricsUpdateRef.current?.();
6711
6709
  });
6712
6710
  return () => {
6713
6711
  channels.forEach((channel) => {
6714
- supabase?.removeChannel(channel).catch((err) => console.error("[useDashboardMetrics] Error removing channel:", err.message));
6712
+ supabase?.removeChannel(channel);
6715
6713
  });
6716
6714
  };
6717
6715
  }, [
6718
6716
  supabase,
6719
- // fetchAllMetrics, // fetchAllMetrics is now a dependency of queueUpdate
6720
6717
  queueUpdate,
6721
- // Section 6: Add queueUpdate as dependency
6722
6718
  companySpecificMetricsTable,
6723
6719
  configuredLineMetricsTable,
6724
6720
  schema,
6725
- entityConfig,
6726
- // For companyId, factoryViewId, default/secondaryLineId
6721
+ entityConfig?.companyId,
6722
+ entityConfig?.factoryViewId,
6727
6723
  defaultTimezone,
6728
- shiftConfig,
6729
- onLineMetricsUpdate,
6730
6724
  lineId
6731
- // Add lineId from props to re-run effect if it changes, managed by lineIdRef inside effect
6732
6725
  ]);
6733
6726
  return {
6734
6727
  workspaceMetrics: metrics2?.workspaceMetrics || [],
@@ -6889,6 +6882,7 @@ var useRealtimeLineMetrics = ({
6889
6882
  const updateQueueRef = React21.useRef(false);
6890
6883
  const isFetchingRef = React21.useRef(false);
6891
6884
  const channelsRef = React21.useRef([]);
6885
+ const fetchTimeoutRef = React21.useRef(null);
6892
6886
  const currentShift = React21.useMemo(() => getCurrentShift(dateTimeConfig.defaultTimezone || "Asia/Kolkata", shiftConfig), [dateTimeConfig.defaultTimezone, shiftConfig]);
6893
6887
  const shiftId = React21.useMemo(
6894
6888
  () => urlShiftId !== void 0 ? urlShiftId : currentShift.shiftId,
@@ -7098,9 +7092,17 @@ var useRealtimeLineMetrics = ({
7098
7092
  }
7099
7093
  }, [supabase, date, shiftId, urlShiftId, onMetricsUpdate, entityConfig, dateTimeConfig.defaultTimezone]);
7100
7094
  const queueUpdate = React21.useCallback(() => {
7101
- if (updateQueueRef.current) return;
7102
- updateQueueRef.current = true;
7103
- fetchData();
7095
+ console.log("[useRealtimeLineMetrics] Update queued, debouncing...");
7096
+ if (fetchTimeoutRef.current) {
7097
+ clearTimeout(fetchTimeoutRef.current);
7098
+ }
7099
+ fetchTimeoutRef.current = setTimeout(() => {
7100
+ if (updateQueueRef.current) return;
7101
+ updateQueueRef.current = true;
7102
+ console.log("[useRealtimeLineMetrics] Debounced fetch triggered");
7103
+ fetchData();
7104
+ fetchTimeoutRef.current = null;
7105
+ }, 500);
7104
7106
  }, [fetchData]);
7105
7107
  const setupSubscriptions = React21.useCallback(() => {
7106
7108
  if (channelsRef.current.length > 0) {
@@ -7178,6 +7180,10 @@ var useRealtimeLineMetrics = ({
7178
7180
  }
7179
7181
  setupSubscriptions();
7180
7182
  return () => {
7183
+ if (fetchTimeoutRef.current) {
7184
+ clearTimeout(fetchTimeoutRef.current);
7185
+ fetchTimeoutRef.current = null;
7186
+ }
7181
7187
  if (channelsRef.current.length > 0) {
7182
7188
  channelsRef.current.forEach((channel) => {
7183
7189
  if (process.env.NODE_ENV === "development") {
@@ -8124,13 +8130,10 @@ var getWorkspaceDisplayName = (workspaceId, lineId) => {
8124
8130
  }
8125
8131
  }
8126
8132
  if (displayName) {
8127
- console.log(`getWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${displayName} (from Supabase)`);
8128
8133
  return displayName;
8129
8134
  } else {
8130
8135
  if (isInitialized) {
8131
- console.log(`getWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${workspaceId} (not found in Supabase data)`);
8132
- } else {
8133
- console.log(`getWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${workspaceId} (Supabase not initialized yet)`);
8136
+ console.warn(`getWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${workspaceId} (not found in Supabase data)`);
8134
8137
  }
8135
8138
  return workspaceId;
8136
8139
  }
@@ -8167,13 +8170,10 @@ var getShortWorkspaceDisplayName = (workspaceId, lineId) => {
8167
8170
  }
8168
8171
  }
8169
8172
  if (displayName) {
8170
- console.log(`getShortWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${displayName} (from Supabase)`);
8171
8173
  return displayName;
8172
8174
  } else {
8173
8175
  if (isInitialized) {
8174
- console.log(`getShortWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${workspaceId} (not found in Supabase data)`);
8175
- } else {
8176
- console.log(`getShortWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${workspaceId} (Supabase not initialized yet)`);
8176
+ console.warn(`getShortWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${workspaceId} (not found in Supabase data)`);
8177
8177
  }
8178
8178
  return workspaceId;
8179
8179
  }
@@ -8479,6 +8479,8 @@ var useAllWorkspaceMetrics = (options) => {
8479
8479
  const [loading, setLoading] = React21.useState(true);
8480
8480
  const [error, setError] = React21.useState(null);
8481
8481
  const [initialized, setInitialized] = React21.useState(false);
8482
+ const fetchTimeoutRef = React21.useRef(null);
8483
+ const isFetchingRef = React21.useRef(false);
8482
8484
  const queryShiftId = React21.useMemo(() => {
8483
8485
  const currentShift = getCurrentShift(
8484
8486
  dateTimeConfig.defaultTimezone || "Asia/Kolkata",
@@ -8497,16 +8499,15 @@ var useAllWorkspaceMetrics = (options) => {
8497
8499
  }, [entityConfig.companyId]);
8498
8500
  const schema = databaseConfig.schema ?? "public";
8499
8501
  const fetchWorkspaceMetrics = React21.useCallback(async () => {
8502
+ if (isFetchingRef.current) {
8503
+ return;
8504
+ }
8505
+ isFetchingRef.current = true;
8500
8506
  if (!initialized) {
8501
8507
  setLoading(true);
8502
8508
  }
8503
8509
  setError(null);
8504
8510
  try {
8505
- console.log("Fetching all workspace metrics with params:", {
8506
- queryDate,
8507
- queryShiftId,
8508
- metricsTable
8509
- });
8510
8511
  const configuredLineIds = getConfiguredLineIds(entityConfig);
8511
8512
  let enabledWorkspaceIds = [];
8512
8513
  for (const lineId of configuredLineIds) {
@@ -8549,13 +8550,26 @@ var useAllWorkspaceMetrics = (options) => {
8549
8550
  efficiency: item.efficiency || 0,
8550
8551
  action_threshold: item.total_day_output || 0
8551
8552
  }));
8552
- setWorkspaces(transformedData);
8553
+ setWorkspaces((prevWorkspaces) => {
8554
+ if (prevWorkspaces.length !== transformedData.length) {
8555
+ return transformedData;
8556
+ }
8557
+ const hasChanges = transformedData.some((newWs) => {
8558
+ const prevWs = prevWorkspaces.find((w) => w.workspace_uuid === newWs.workspace_uuid);
8559
+ if (!prevWs) {
8560
+ return true;
8561
+ }
8562
+ return prevWs.efficiency !== newWs.efficiency || prevWs.action_count !== newWs.action_count || prevWs.action_threshold !== newWs.action_threshold || prevWs.avg_cycle_time !== newWs.avg_cycle_time || prevWs.workspace_name !== newWs.workspace_name;
8563
+ });
8564
+ return hasChanges ? transformedData : prevWorkspaces;
8565
+ });
8553
8566
  setInitialized(true);
8554
8567
  } catch (err) {
8555
- console.error("Error fetching all workspace metrics:", err);
8568
+ console.error("[useAllWorkspaceMetrics] Error:", err.message);
8556
8569
  setError({ message: err.message, code: err.code || "FETCH_ERROR" });
8557
8570
  } finally {
8558
8571
  setLoading(false);
8572
+ isFetchingRef.current = false;
8559
8573
  }
8560
8574
  }, [queryDate, queryShiftId, metricsTable, supabase, entityConfig.companyId]);
8561
8575
  React21.useEffect(() => {
@@ -8563,25 +8577,37 @@ var useAllWorkspaceMetrics = (options) => {
8563
8577
  fetchWorkspaceMetrics();
8564
8578
  }
8565
8579
  const setupSubscription = () => {
8566
- const filter2 = `date=eq.${queryDate} AND shift_id=eq.${queryShiftId}`;
8567
- console.log("Setting up subscription for all workspaces with filter:", filter2);
8568
8580
  const channel2 = supabase.channel(`all-workspace-metrics-${Date.now()}`).on(
8569
8581
  "postgres_changes",
8570
8582
  {
8571
8583
  event: "*",
8572
8584
  schema,
8573
- table: metricsTable,
8574
- filter: filter2
8585
+ table: metricsTable
8575
8586
  },
8576
8587
  async (payload) => {
8577
- console.log("All workspace metrics update received:", payload);
8578
- await fetchWorkspaceMetrics();
8588
+ const data = payload.new || payload.old;
8589
+ if (data?.date !== queryDate || data?.shift_id !== queryShiftId) {
8590
+ return;
8591
+ }
8592
+ if (fetchTimeoutRef.current) {
8593
+ clearTimeout(fetchTimeoutRef.current);
8594
+ }
8595
+ fetchTimeoutRef.current = setTimeout(async () => {
8596
+ if (!isFetchingRef.current) {
8597
+ await fetchWorkspaceMetrics();
8598
+ }
8599
+ fetchTimeoutRef.current = null;
8600
+ }, 300);
8579
8601
  }
8580
8602
  ).subscribe();
8581
8603
  return channel2;
8582
8604
  };
8583
8605
  const channel = setupSubscription();
8584
8606
  return () => {
8607
+ if (fetchTimeoutRef.current) {
8608
+ clearTimeout(fetchTimeoutRef.current);
8609
+ fetchTimeoutRef.current = null;
8610
+ }
8585
8611
  if (channel) {
8586
8612
  supabase.removeChannel(channel);
8587
8613
  }
@@ -21983,7 +22009,16 @@ var VideoCard = React21__namespace.default.memo(({
21983
22009
  }
21984
22010
  );
21985
22011
  }, (prevProps, nextProps) => {
21986
- return prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.workspace_name === nextProps.workspace.workspace_name && Math.abs(prevProps.workspace.efficiency - nextProps.workspace.efficiency) < 1 && prevProps.hlsUrl === nextProps.hlsUrl && prevProps.shouldPlay === nextProps.shouldPlay && prevProps.cropping?.x === nextProps.cropping?.x && prevProps.cropping?.y === nextProps.cropping?.y && prevProps.cropping?.width === nextProps.cropping?.width && prevProps.cropping?.height === nextProps.cropping?.height;
22012
+ if (prevProps.workspace.efficiency !== nextProps.workspace.efficiency || prevProps.workspace.trend !== nextProps.workspace.trend || prevProps.workspace.performance_score !== nextProps.workspace.performance_score || prevProps.workspace.pph !== nextProps.workspace.pph) {
22013
+ return false;
22014
+ }
22015
+ if (prevProps.hlsUrl !== nextProps.hlsUrl || prevProps.shouldPlay !== nextProps.shouldPlay) {
22016
+ return false;
22017
+ }
22018
+ if (prevProps.cropping?.x !== nextProps.cropping?.x || prevProps.cropping?.y !== nextProps.cropping?.y || prevProps.cropping?.width !== nextProps.cropping?.width || prevProps.cropping?.height !== nextProps.cropping?.height) {
22019
+ return false;
22020
+ }
22021
+ return true;
21987
22022
  });
21988
22023
  VideoCard.displayName = "VideoCard";
21989
22024
  var DEFAULT_HLS_URL = "https://192.168.5.9:8443/cam1.m3u8";
@@ -22991,7 +23026,8 @@ var BreakNotificationPopup = ({
22991
23026
  onDismiss,
22992
23027
  isVisible = true,
22993
23028
  className = "",
22994
- lineNames = {}
23029
+ lineNames = {},
23030
+ axelImagePath = "/axel-profile.png"
22995
23031
  }) => {
22996
23032
  const [isDismissed, setIsDismissed] = React21.useState(false);
22997
23033
  const [currentTime, setCurrentTime] = React21.useState(/* @__PURE__ */ new Date());
@@ -23016,6 +23052,109 @@ var BreakNotificationPopup = ({
23016
23052
  if (!isVisible || isDismissed || activeBreaks.length === 0) {
23017
23053
  return null;
23018
23054
  }
23055
+ return /* @__PURE__ */ jsxRuntime.jsx(AnimatePresence, { children: activeBreaks.map((breakItem, index) => /* @__PURE__ */ jsxRuntime.jsx(
23056
+ motion.div,
23057
+ {
23058
+ initial: { opacity: 0, x: 100, y: -20 },
23059
+ animate: { opacity: 1, x: 0, y: 0 },
23060
+ exit: { opacity: 0, x: 100, y: -20 },
23061
+ transition: { duration: 0.3, ease: "easeOut", delay: index * 0.1 },
23062
+ className: `fixed right-4 z-50 max-w-xs w-full ${className}`,
23063
+ style: { top: `${6 + index * 12}rem` },
23064
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white text-gray-900 rounded-lg border border-gray-200 shadow-lg overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
23065
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start space-x-3 flex-1", children: [
23066
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
23067
+ "img",
23068
+ {
23069
+ src: axelImagePath,
23070
+ alt: "Axel AI",
23071
+ className: "w-10 h-10 rounded-full object-cover border-2 border-gray-200 shadow-sm",
23072
+ onError: (e) => {
23073
+ const target = e.currentTarget;
23074
+ target.style.display = "none";
23075
+ const fallback = document.createElement("div");
23076
+ fallback.className = "w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold text-base shadow-sm border-2 border-gray-200";
23077
+ fallback.textContent = "A";
23078
+ target.parentElement?.appendChild(fallback);
23079
+ }
23080
+ }
23081
+ ) }),
23082
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
23083
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [
23084
+ /* @__PURE__ */ jsxRuntime.jsxs("h4", { className: "font-semibold text-sm text-gray-900", children: [
23085
+ breakItem.remarks || "Break",
23086
+ (activeBreaks.length > 1 || lineNames[breakItem.lineId]) && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-500 ml-1", children: [
23087
+ "\u2022 ",
23088
+ lineNames[breakItem.lineId] || `Line ${breakItem.lineId.substring(0, 8)}`
23089
+ ] })
23090
+ ] }),
23091
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Coffee, { className: "w-4 h-4 text-amber-500" })
23092
+ ] }),
23093
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-600 leading-relaxed mb-2", children: [
23094
+ "Currently active from ",
23095
+ breakItem.startTime,
23096
+ " to ",
23097
+ breakItem.endTime,
23098
+ ". ",
23099
+ formatTime3(breakItem.elapsedMinutes),
23100
+ " elapsed of ",
23101
+ formatTime3(breakItem.duration),
23102
+ " total."
23103
+ ] }),
23104
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full bg-gray-200 rounded-full h-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(
23105
+ "div",
23106
+ {
23107
+ className: "h-1.5 bg-blue-500 rounded-full transition-all duration-1000",
23108
+ style: {
23109
+ width: `${Math.min(100, Math.max(0, breakItem.elapsedMinutes / breakItem.duration * 100))}%`
23110
+ }
23111
+ }
23112
+ ) }) })
23113
+ ] })
23114
+ ] }),
23115
+ /* @__PURE__ */ jsxRuntime.jsx(
23116
+ "button",
23117
+ {
23118
+ onClick: handleDismiss,
23119
+ onTouchStart: () => {
23120
+ },
23121
+ className: "ml-2 text-gray-400 hover:text-gray-600 transition-colors p-2 sm:p-1 rounded-full hover:bg-gray-100 active:bg-gray-200 touch-manipulation min-h-[44px] min-w-[44px] sm:min-h-0 sm:min-w-0 flex items-center justify-center flex-shrink-0",
23122
+ "aria-label": "Dismiss notification",
23123
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4 sm:w-3 sm:h-3" })
23124
+ }
23125
+ )
23126
+ ] }) }) })
23127
+ },
23128
+ `${breakItem.lineId}-${breakItem.startTime}-${index}`
23129
+ )) });
23130
+ };
23131
+ var AxelNotificationPopup = ({
23132
+ suggestion,
23133
+ isVisible = true,
23134
+ onDismiss,
23135
+ className = "",
23136
+ axelImagePath = "/axel-profile.png"
23137
+ }) => {
23138
+ const [isDismissed, setIsDismissed] = React21.useState(false);
23139
+ const handleDismiss = () => {
23140
+ setIsDismissed(true);
23141
+ onDismiss?.();
23142
+ };
23143
+ if (!isVisible || isDismissed || !suggestion) {
23144
+ return null;
23145
+ }
23146
+ const getTypeIcon = () => {
23147
+ switch (suggestion.type) {
23148
+ case "improvement":
23149
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingUp, { className: "w-4 h-4 text-blue-500" });
23150
+ case "alert":
23151
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "w-4 h-4 text-amber-500" });
23152
+ case "insight":
23153
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "w-4 h-4 text-purple-500" });
23154
+ default:
23155
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "w-4 h-4 text-blue-500" });
23156
+ }
23157
+ };
23019
23158
  return /* @__PURE__ */ jsxRuntime.jsx(AnimatePresence, { children: /* @__PURE__ */ jsxRuntime.jsx(
23020
23159
  motion.div,
23021
23160
  {
@@ -23023,58 +23162,54 @@ var BreakNotificationPopup = ({
23023
23162
  animate: { opacity: 1, x: 0, y: 0 },
23024
23163
  exit: { opacity: 0, x: 100, y: -20 },
23025
23164
  transition: { duration: 0.3, ease: "easeOut" },
23026
- className: `fixed top-24 right-4 z-50 max-w-xs w-full ${className}`,
23027
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white text-gray-900 rounded-lg border border-gray-200 shadow-lg overflow-hidden", children: activeBreaks.map((breakItem, index) => /* @__PURE__ */ jsxRuntime.jsx(
23165
+ className: `fixed top-24 right-4 z-40 max-w-xs w-full ${className}`,
23166
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white text-gray-900 rounded-lg border border-gray-200 shadow-lg overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
23028
23167
  motion.div,
23029
23168
  {
23030
- initial: { opacity: 0, y: 20 },
23169
+ initial: { opacity: 0, y: 10 },
23031
23170
  animate: { opacity: 1, y: 0 },
23032
- transition: { delay: index * 0.1 },
23033
- className: `p-3 ${index > 0 ? "border-t border-gray-100" : ""}`,
23171
+ transition: { delay: 0.1 },
23172
+ className: "p-3",
23034
23173
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
23035
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-3 flex-1", children: [
23036
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 bg-amber-500 rounded-full animate-pulse flex-shrink-0 mt-2" }),
23174
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start space-x-3 flex-1", children: [
23175
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
23176
+ "img",
23177
+ {
23178
+ src: axelImagePath,
23179
+ alt: "Axel AI",
23180
+ className: "w-10 h-10 rounded-full object-cover border-2 border-gray-200 shadow-sm",
23181
+ onError: (e) => {
23182
+ const target = e.currentTarget;
23183
+ target.style.display = "none";
23184
+ const fallback = document.createElement("div");
23185
+ fallback.className = "w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold text-base shadow-sm border-2 border-gray-200";
23186
+ fallback.textContent = "A";
23187
+ target.parentElement?.appendChild(fallback);
23188
+ }
23189
+ }
23190
+ ) }),
23037
23191
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
23038
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1", children: [
23039
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-semibold text-base sm:text-sm text-gray-900", children: breakItem.remarks || "Break" }),
23040
- (activeBreaks.length > 1 || lineNames[breakItem.lineId]) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm sm:text-xs text-gray-500 mt-0.5", children: lineNames[breakItem.lineId] || `Line ${breakItem.lineId.substring(0, 8)}` })
23192
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [
23193
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-semibold text-sm text-gray-900", children: suggestion.title }),
23194
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: getTypeIcon() })
23041
23195
  ] }),
23042
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm sm:text-xs text-gray-600 font-medium", children: [
23043
- breakItem.startTime,
23044
- " - ",
23045
- breakItem.endTime
23046
- ] }) }),
23047
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm sm:text-xs text-gray-500", children: [
23048
- formatTime3(breakItem.elapsedMinutes),
23049
- " / ",
23050
- formatTime3(breakItem.duration)
23051
- ] }) }),
23052
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full bg-gray-200 rounded-full h-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(
23053
- "div",
23054
- {
23055
- className: "h-1.5 bg-blue-500 rounded-full transition-all duration-1000",
23056
- style: {
23057
- width: `${Math.min(100, Math.max(0, breakItem.elapsedMinutes / breakItem.duration * 100))}%`
23058
- }
23059
- }
23060
- ) }) })
23196
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-600 leading-relaxed", children: suggestion.message })
23061
23197
  ] })
23062
23198
  ] }),
23063
- index === 0 && /* @__PURE__ */ jsxRuntime.jsx(
23199
+ /* @__PURE__ */ jsxRuntime.jsx(
23064
23200
  "button",
23065
23201
  {
23066
23202
  onClick: handleDismiss,
23067
23203
  onTouchStart: () => {
23068
23204
  },
23069
- className: "ml-2 text-gray-400 hover:text-gray-600 transition-colors p-2 sm:p-1 rounded-full hover:bg-gray-100 active:bg-gray-200 touch-manipulation min-h-[44px] min-w-[44px] sm:min-h-0 sm:min-w-0 flex items-center justify-center",
23205
+ className: "ml-2 text-gray-400 hover:text-gray-600 transition-colors p-2 sm:p-1 rounded-full hover:bg-gray-100 active:bg-gray-200 touch-manipulation min-h-[44px] min-w-[44px] sm:min-h-0 sm:min-w-0 flex items-center justify-center flex-shrink-0",
23070
23206
  "aria-label": "Dismiss notification",
23071
23207
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4 sm:w-3 sm:h-3" })
23072
23208
  }
23073
23209
  )
23074
23210
  ] })
23075
- },
23076
- `${breakItem.lineId}-${breakItem.startTime}-${index}`
23077
- )) })
23211
+ }
23212
+ ) })
23078
23213
  }
23079
23214
  ) });
23080
23215
  };
@@ -25905,12 +26040,6 @@ var WorkspaceHistoryCalendar = ({
25905
26040
  ] })
25906
26041
  ] });
25907
26042
  };
25908
-
25909
- // src/lib/constants/design-tokens.ts
25910
- var designTokens = {
25911
- // Typography scale with clear hierarchy
25912
- typography: {
25913
- body: "text-sm text-gray-600"}};
25914
26043
  var WEEKDAYS3 = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
25915
26044
  var getOrdinal = (n) => {
25916
26045
  const suffix = ["th", "st", "nd", "rd"];
@@ -26094,10 +26223,13 @@ var WorkspaceMonthlyHistory = ({
26094
26223
  }
26095
26224
  }, [workspaceId, onShiftChange]);
26096
26225
  if (monthlyDataLoading) {
26097
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-[calc(100vh-10rem)]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center space-y-4", children: [
26098
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-12 w-12 animate-spin rounded-full border-4 border-blue-200", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 rounded-full border-4 border-blue-600 border-t-transparent" }) }) }),
26099
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: designTokens.typography.body + " font-medium", children: "Loading monthly performance data..." })
26100
- ] }) });
26226
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-[calc(100vh-10rem)]", children: /* @__PURE__ */ jsxRuntime.jsx(
26227
+ OptifyeLogoLoader_default,
26228
+ {
26229
+ size: "lg",
26230
+ message: "Loading monthly performance data..."
26231
+ }
26232
+ ) });
26101
26233
  }
26102
26234
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col gap-2 min-h-0 overflow-y-auto pb-6 ${className}`, children: [
26103
26235
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center mb-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1 border border-gray-200 rounded-lg p-1 bg-gray-50", children: [
@@ -26534,7 +26666,7 @@ var WorkspacePdfGenerator = ({ workspace, className }) => {
26534
26666
  doc.roundedRect(22, y - 7, 165, 12, 2, 2, "S");
26535
26667
  };
26536
26668
  doc.setFillColor(245, 245, 245);
26537
- doc.roundedRect(15, 95, 180, 70, 3, 3, "F");
26669
+ doc.roundedRect(15, 95, 180, 60, 3, 3, "F");
26538
26670
  doc.setFontSize(18);
26539
26671
  doc.setFont("helvetica", "bold");
26540
26672
  doc.setTextColor(40, 40, 40);
@@ -26563,34 +26695,29 @@ var WorkspacePdfGenerator = ({ workspace, className }) => {
26563
26695
  doc.text("PPH (Pieces Per Hour):", 25, kpiStartY + kpiSpacing * 3);
26564
26696
  doc.setFont("helvetica", "bold");
26565
26697
  doc.text(`${workspace.avg_pph.toFixed(1)} (Standard: ${workspace.pph_threshold.toFixed(1)})`, 120, kpiStartY + kpiSpacing * 3);
26566
- createKPIBox(kpiStartY + kpiSpacing * 4);
26567
- doc.setFont("helvetica", "normal");
26568
- doc.text("Rank:", 25, kpiStartY + kpiSpacing * 4);
26569
- doc.setFont("helvetica", "bold");
26570
- doc.text(`${workspace.workspace_rank} of ${workspace.total_workspaces}`, 120, kpiStartY + kpiSpacing * 4);
26571
26698
  doc.setDrawColor(180, 180, 180);
26572
26699
  doc.setLineWidth(0.8);
26573
- doc.line(20, 180, 190, 180);
26700
+ doc.line(20, 170, 190, 170);
26574
26701
  doc.setFillColor(245, 245, 245);
26575
- doc.roundedRect(15, 185, 180, 85, 3, 3, "F");
26702
+ doc.roundedRect(15, 175, 180, 85, 3, 3, "F");
26576
26703
  doc.setFontSize(18);
26577
26704
  doc.setFont("helvetica", "bold");
26578
26705
  doc.setTextColor(40, 40, 40);
26579
- doc.text("Hourly Performance", 20, 195);
26706
+ doc.text("Hourly Performance", 20, 185);
26580
26707
  doc.setTextColor(0, 0, 0);
26581
26708
  doc.setFontSize(11);
26582
26709
  doc.setFont("helvetica", "bold");
26583
26710
  doc.setFillColor(245, 245, 245);
26584
- doc.roundedRect(20, 187, 170, 8, 1, 1, "F");
26585
- doc.text("Time Range", 25, 192);
26586
- doc.text("Output", 95, 192);
26587
- doc.text("Target", 135, 192);
26588
- doc.text("Status", 170, 192);
26711
+ doc.roundedRect(20, 177, 170, 8, 1, 1, "F");
26712
+ doc.text("Time Range", 25, 182);
26713
+ doc.text("Output", 95, 182);
26714
+ doc.text("Target", 135, 182);
26715
+ doc.text("Status", 170, 182);
26589
26716
  doc.setLineWidth(0.2);
26590
26717
  doc.setDrawColor(220, 220, 220);
26591
- doc.line(20, 195, 190, 195);
26718
+ doc.line(20, 185, 190, 185);
26592
26719
  doc.setFont("helvetica", "normal");
26593
- let yPos = 201;
26720
+ let yPos = 191;
26594
26721
  const hourlyData = workspace.hourly_action_counts || [];
26595
26722
  const hourlyTarget = workspace.pph_threshold;
26596
26723
  hourlyData.forEach((output, index) => {
@@ -28384,7 +28511,10 @@ var FilterDialogTrigger = ({
28384
28511
  }
28385
28512
  );
28386
28513
  };
28387
- var getSeverityIcon = (severity) => {
28514
+ var getSeverityIcon = (severity, categoryId) => {
28515
+ if (categoryId === "idle_time" || categoryId === "low_value" || categoryId === "longest-idles") {
28516
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3 w-3 text-red-500" });
28517
+ }
28388
28518
  switch (severity) {
28389
28519
  case "high":
28390
28520
  return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3 w-3 text-red-500" });
@@ -28611,17 +28741,17 @@ var FileManagerFilters = ({
28611
28741
  const colorClasses = getColorClasses(category.color);
28612
28742
  const clipNodes = filteredClips.map((clip, index) => {
28613
28743
  const timeString = new Date(clip.clip_timestamp).toLocaleTimeString("en-US", {
28614
- hour12: false,
28615
- hour: "2-digit",
28744
+ hour12: true,
28745
+ hour: "numeric",
28616
28746
  minute: "2-digit",
28617
28747
  timeZone: timezone
28618
28748
  // Use database timezone for display
28619
28749
  });
28620
28750
  return {
28621
28751
  id: clip.id,
28622
- label: `${timeString} - ${clip.description}${clip.duration && category.id !== "idle_time" ? ` (${clip.duration.toFixed(1)}s)` : ""}`,
28752
+ label: `${timeString}${clip.duration && category.id !== "idle_time" ? ` - (${clip.duration.toFixed(1)}s)` : ""}`,
28623
28753
  type: "video",
28624
- icon: getSeverityIcon(clip.severity),
28754
+ icon: getSeverityIcon(clip.severity, category.id),
28625
28755
  timestamp: clip.clip_timestamp,
28626
28756
  severity: clip.severity,
28627
28757
  clipId: clip.clipId,
@@ -28661,9 +28791,9 @@ var FileManagerFilters = ({
28661
28791
  children: (percentileClips["fast-cycles"] || []).map((clip, index) => ({
28662
28792
  id: clip.id,
28663
28793
  // Remove prefix to match currentVideoId
28664
- label: `${clip.timestamp} - ${clip.description}${clip.cycle_time_seconds ? ` (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
28794
+ label: `${clip.timestamp}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
28665
28795
  type: "video",
28666
- icon: getSeverityIcon(clip.severity),
28796
+ icon: getSeverityIcon(clip.severity, "fast-cycles"),
28667
28797
  timestamp: clip.creation_timestamp,
28668
28798
  severity: clip.severity,
28669
28799
  clipId: clip.id,
@@ -28684,9 +28814,9 @@ var FileManagerFilters = ({
28684
28814
  children: (percentileClips["slow-cycles"] || []).map((clip, index) => ({
28685
28815
  id: clip.id,
28686
28816
  // Remove prefix to match currentVideoId
28687
- label: `${clip.timestamp} - ${clip.description}${clip.cycle_time_seconds ? ` (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
28817
+ label: `${clip.timestamp}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
28688
28818
  type: "video",
28689
- icon: getSeverityIcon(clip.severity),
28819
+ icon: getSeverityIcon(clip.severity, "slow-cycles"),
28690
28820
  timestamp: clip.creation_timestamp,
28691
28821
  severity: clip.severity,
28692
28822
  clipId: clip.id,
@@ -28707,9 +28837,9 @@ var FileManagerFilters = ({
28707
28837
  isPercentile: true,
28708
28838
  children: (percentileClips['idle-times'] || []).map((clip, index) => ({
28709
28839
  id: clip.id, // Remove prefix to match currentVideoId
28710
- label: `${clip.timestamp} - ${clip.description}${clip.cycle_time_seconds ? ` (${clip.cycle_time_seconds.toFixed(1)}s)` : ''}`,
28840
+ label: `${clip.timestamp}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ''}`,
28711
28841
  type: 'video' as const,
28712
- icon: getSeverityIcon(clip.severity),
28842
+ icon: getSeverityIcon(clip.severity, 'longest-idles'),
28713
28843
  timestamp: clip.creation_timestamp,
28714
28844
  severity: clip.severity,
28715
28845
  clipId: clip.id,
@@ -28764,7 +28894,7 @@ var FileManagerFilters = ({
28764
28894
  /* @__PURE__ */ jsxRuntime.jsxs(
28765
28895
  "div",
28766
28896
  {
28767
- className: `flex items-center cursor-pointer transition-all duration-300 ease-out group relative overflow-hidden ${node.type === "category" && depth === 0 ? `py-3 px-4 rounded-2xl hover:bg-gradient-to-r hover:from-slate-50 hover:to-blue-50/30 hover:shadow-lg hover:shadow-blue-100/20 hover:scale-[1.02] hover:-translate-y-0.5 ${isActive ? "bg-gradient-to-r from-blue-50 via-blue-50/80 to-indigo-50/60 border border-blue-200/50 shadow-lg shadow-blue-100/30 scale-[1.02]" : "border border-transparent"}` : `py-2 px-3 rounded-xl hover:bg-gradient-to-r hover:from-slate-50 hover:to-slate-50/50 hover:shadow-sm ${isActive ? "bg-gradient-to-r from-blue-50/80 to-blue-50/40 border border-blue-200/30 shadow-sm" : "border border-transparent"} ${isCurrentVideo ? "bg-gradient-to-r from-emerald-50 to-green-50/60 border border-emerald-200/50 shadow-md shadow-emerald-100/20" : ""}`} ${node.type === "video" ? "ml-6" : ""}`,
28897
+ className: `flex items-center cursor-pointer transition-all duration-300 ease-out group relative overflow-hidden ${node.type === "category" && depth === 0 ? `py-3 px-4 rounded-2xl hover:bg-gradient-to-r hover:from-slate-50 hover:to-blue-50/30 hover:shadow-lg hover:shadow-blue-100/20 hover:scale-[1.02] hover:-translate-y-0.5 ${isActive ? "bg-gradient-to-r from-blue-50 via-blue-50/80 to-indigo-50/60 border border-blue-200/50 shadow-lg shadow-blue-100/30 scale-[1.02]" : "border border-transparent"}` : `py-2 px-3 rounded-xl hover:bg-gradient-to-r hover:from-slate-50 hover:to-slate-50/50 hover:shadow-sm ${isActive ? "bg-gradient-to-r from-blue-50/80 to-blue-50/40 border border-blue-200/30 shadow-sm" : "border border-transparent"} ${isCurrentVideo ? "bg-gradient-to-r from-blue-50 to-blue-50/60 border border-blue-200/50 shadow-md shadow-blue-100/20" : ""}`} ${node.type === "video" ? "ml-6" : ""}`,
28768
28898
  onClick: () => handleNodeClick(node),
28769
28899
  children: [
28770
28900
  hasChildren && /* @__PURE__ */ jsxRuntime.jsx(
@@ -28781,13 +28911,10 @@ var FileManagerFilters = ({
28781
28911
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-shrink-0 mr-3 ${node.type === "category" || node.type === "percentile-category" ? "p-2 rounded-lg shadow-sm group-hover:scale-110 transition-transform duration-200" : "p-0.5"} ${colorClasses && (node.type === "category" || node.type === "percentile-category") ? `${colorClasses.bg} border border-white/60` : ""}`, children: node.icon }),
28782
28912
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 flex items-center justify-between", children: [
28783
28913
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
28784
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `font-semibold tracking-tight ${node.type === "category" || node.type === "percentile-category" ? "text-slate-800 text-sm" : "text-slate-700 text-xs"} ${isCurrentVideo ? "text-emerald-700 font-bold" : ""} group-hover:text-slate-900 transition-colors duration-200`, children: node.label }),
28914
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `font-semibold tracking-tight ${node.type === "category" || node.type === "percentile-category" ? "text-slate-800 text-sm" : "text-slate-700 text-xs"} ${isCurrentVideo ? "text-blue-700 font-bold" : ""} group-hover:text-slate-900 transition-colors duration-200`, children: node.label }),
28785
28915
  node.type === "category" && categories.find((c) => c.id === node.id)?.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: categories.find((c) => c.id === node.id)?.description }),
28786
28916
  node.type === "percentile-category" && node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: node.subtitle }),
28787
- node.type === "video" && node.severity && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-slate-500 capitalize mt-0.5 font-medium", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-medium ${node.severity === "high" ? "bg-red-100 text-red-700" : node.severity === "medium" ? "bg-yellow-100 text-yellow-700" : "bg-green-100 text-green-700"}`, children: [
28788
- node.severity,
28789
- " priority"
28790
- ] }) })
28917
+ node.type === "video" && node.severity && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-slate-500 capitalize mt-0.5 font-medium", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-medium ${node.categoryId === "idle_time" || node.categoryId === "low_value" ? "bg-red-100 text-red-700" : node.severity === "high" ? "bg-red-100 text-red-700" : node.severity === "medium" ? "bg-yellow-100 text-yellow-700" : "bg-green-100 text-green-700"}`, children: node.categoryId === "idle_time" || node.categoryId === "low_value" ? "Idle" : node.severity === "low" ? "Fast" : node.severity === "medium" ? "Average" : "Slow" }) })
28791
28918
  ] }),
28792
28919
  node.count !== void 0 && (node.type === "category" || node.type === "percentile-category") && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center ml-2", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `px-2.5 py-1 text-sm font-bold rounded-lg shadow-sm border backdrop-blur-sm flex-shrink-0 group-hover:scale-105 transition-all duration-200 ${colorClasses ? `${colorClasses.bg} ${colorClasses.text} ${colorClasses.border} bg-opacity-80` : "bg-slate-100/80 text-slate-700 border-slate-200/60"}`, children: node.count }) })
28793
28920
  ] })
@@ -37028,6 +37155,8 @@ function HomeView({
37028
37155
  const [errorMessage, setErrorMessage] = React21.useState(null);
37029
37156
  const [displayNamesInitialized, setDisplayNamesInitialized] = React21.useState(false);
37030
37157
  const [hasInitialDataLoaded, setHasInitialDataLoaded] = React21.useState(false);
37158
+ const [axelSuggestion, setAxelSuggestion] = React21.useState(null);
37159
+ const [showAxelNotification, setShowAxelNotification] = React21.useState(false);
37031
37160
  const dashboardConfig = useDashboardConfig();
37032
37161
  const timezone = useAppTimezone();
37033
37162
  React21.useEffect(() => {
@@ -37102,12 +37231,7 @@ function HomeView({
37102
37231
  }, []);
37103
37232
  const handleWorkspaceHoverEnd = React21.useCallback((workspaceId) => {
37104
37233
  }, []);
37105
- const memoizedWorkspaceMetrics = React21.useMemo(() => workspaceMetrics, [
37106
- // Only update reference if meaningful properties change
37107
- workspaceMetrics.length,
37108
- // Use stable string representation instead of spreading array
37109
- JSON.stringify(workspaceMetrics.map((w) => `${w.workspace_uuid}-${Math.round(w.efficiency)}-${w.trend}`))
37110
- ]);
37234
+ const memoizedWorkspaceMetrics = workspaceMetrics;
37111
37235
  const memoizedKPIs = React21.useMemo(() => kpis, [
37112
37236
  // Only update reference when values change by at least 1%
37113
37237
  kpis?.efficiency?.value ? Math.round(kpis.efficiency.value) : null,
@@ -37135,6 +37259,9 @@ function HomeView({
37135
37259
  setIsChangingFilter(true);
37136
37260
  setSelectedLineId(value);
37137
37261
  }, []);
37262
+ const handleDismissAxelNotification = React21.useCallback(() => {
37263
+ setShowAxelNotification(false);
37264
+ }, []);
37138
37265
  React21.useEffect(() => {
37139
37266
  if (!metricsLoading && !kpisLoading && isChangingFilter) {
37140
37267
  if (workspaceMetrics.length > 0 || selectedLineId === factoryViewId) {
@@ -37246,6 +37373,14 @@ function HomeView({
37246
37373
  lineNames,
37247
37374
  isVisible: !breaksLoading && !breaksError
37248
37375
  }
37376
+ ),
37377
+ /* @__PURE__ */ jsxRuntime.jsx(
37378
+ AxelNotificationPopup,
37379
+ {
37380
+ suggestion: axelSuggestion,
37381
+ isVisible: showAxelNotification,
37382
+ onDismiss: handleDismissAxelNotification
37383
+ }
37249
37384
  )
37250
37385
  ] })
37251
37386
  }
@@ -38679,7 +38814,7 @@ var KPIsOverviewView = ({
38679
38814
  var KPIsOverviewView_default = KPIsOverviewView;
38680
38815
  var IsolatedTimer = React21.memo(() => {
38681
38816
  return /* @__PURE__ */ jsxRuntime.jsx(ISTTimer_default, {});
38682
- }, () => true);
38817
+ });
38683
38818
  IsolatedTimer.displayName = "IsolatedTimer";
38684
38819
  var HeaderRibbon = React21.memo(({
38685
38820
  currentDate,
@@ -38687,42 +38822,49 @@ var HeaderRibbon = React21.memo(({
38687
38822
  shiftId,
38688
38823
  getShiftIcon,
38689
38824
  getShiftName
38690
- }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
38691
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sm:hidden mt-3 flex items-center justify-center gap-2", children: [
38692
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-gray-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-700", children: currentMobileDate }) }),
38693
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-1 px-2.5 py-1 bg-gray-100 rounded-full", children: [
38694
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-700 scale-90", children: getShiftIcon(shiftId) }),
38695
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-700", children: getShiftName(shiftId) })
38825
+ }) => {
38826
+ const shiftIcon = React21.useMemo(() => getShiftIcon(shiftId), [getShiftIcon, shiftId]);
38827
+ const shiftName = React21.useMemo(() => getShiftName(shiftId), [getShiftName, shiftId]);
38828
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
38829
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sm:hidden mt-3 flex items-center justify-center gap-2", children: [
38830
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-gray-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-700", children: currentMobileDate }) }),
38831
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-1 px-2.5 py-1 bg-gray-100 rounded-full", children: [
38832
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-700 scale-90", children: shiftIcon }),
38833
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-700", children: shiftName })
38834
+ ] }),
38835
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-green-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-green-700", children: /* @__PURE__ */ jsxRuntime.jsx(IsolatedTimer, {}) }) })
38696
38836
  ] }),
38697
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-green-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-green-700", children: /* @__PURE__ */ jsxRuntime.jsx(IsolatedTimer, {}) }) })
38698
- ] }),
38699
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block mt-3 bg-blue-50 px-3 py-2 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-3 md:gap-4", children: [
38700
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base md:text-lg font-medium text-blue-600", children: /* @__PURE__ */ jsxRuntime.jsx(IsolatedTimer, {}) }),
38701
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-300" }),
38702
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm md:text-base font-medium text-blue-600", children: currentDate }),
38703
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-300" }),
38704
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
38705
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-blue-600", children: getShiftIcon(shiftId) }),
38706
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm md:text-base font-medium text-blue-600", children: [
38707
- getShiftName(shiftId),
38708
- " Shift"
38837
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block mt-3 bg-blue-50 px-3 py-2 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-3 md:gap-4", children: [
38838
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base md:text-lg font-medium text-blue-600", children: /* @__PURE__ */ jsxRuntime.jsx(IsolatedTimer, {}) }),
38839
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-300" }),
38840
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm md:text-base font-medium text-blue-600", children: currentDate }),
38841
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-300" }),
38842
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
38843
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-blue-600", children: shiftIcon }),
38844
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm md:text-base font-medium text-blue-600", children: [
38845
+ shiftName,
38846
+ " Shift"
38847
+ ] })
38709
38848
  ] })
38710
- ] })
38711
- ] }) })
38712
- ] }));
38849
+ ] }) })
38850
+ ] });
38851
+ });
38713
38852
  HeaderRibbon.displayName = "HeaderRibbon";
38714
38853
  var MobileWorkspaceCard = React21.memo(({
38715
38854
  workspace,
38716
38855
  rank,
38717
38856
  cardClass,
38718
38857
  onWorkspaceClick,
38719
- getMedalIcon,
38720
- getLineName
38858
+ getMedalIcon
38721
38859
  }) => /* @__PURE__ */ jsxRuntime.jsxs(
38722
38860
  "div",
38723
38861
  {
38724
38862
  onClick: () => onWorkspaceClick(workspace, rank),
38725
- className: `${cardClass} p-3 rounded-lg border shadow-sm active:scale-[0.98] transition-all cursor-pointer`,
38863
+ className: `${cardClass} p-3 rounded-lg border shadow-sm active:scale-[0.98] transition-all duration-300 cursor-pointer`,
38864
+ style: {
38865
+ willChange: "opacity, transform",
38866
+ animation: "fadeIn 0.3s ease-in-out"
38867
+ },
38726
38868
  children: [
38727
38869
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
38728
38870
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
@@ -38734,8 +38876,8 @@ var MobileWorkspaceCard = React21.memo(({
38734
38876
  getMedalIcon(rank)
38735
38877
  ] }),
38736
38878
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
38737
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-gray-900", children: getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id) }),
38738
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500", children: getLineName(workspace.line_id) })
38879
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-gray-900", children: workspace.displayName }),
38880
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500", children: workspace.lineName })
38739
38881
  ] })
38740
38882
  ] }),
38741
38883
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-right", children: [
@@ -38765,27 +38907,32 @@ var MobileWorkspaceCard = React21.memo(({
38765
38907
  ] })
38766
38908
  ]
38767
38909
  }
38768
- ));
38910
+ ), (prevProps, nextProps) => {
38911
+ return prevProps.rank === nextProps.rank && prevProps.cardClass === nextProps.cardClass && prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.efficiency === nextProps.workspace.efficiency && prevProps.workspace.action_count === nextProps.workspace.action_count && prevProps.workspace.action_threshold === nextProps.workspace.action_threshold && prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.displayName === nextProps.workspace.displayName && prevProps.workspace.lineName === nextProps.workspace.lineName && prevProps.onWorkspaceClick === nextProps.onWorkspaceClick && prevProps.getMedalIcon === nextProps.getMedalIcon;
38912
+ });
38769
38913
  MobileWorkspaceCard.displayName = "MobileWorkspaceCard";
38770
38914
  var DesktopWorkspaceRow = React21.memo(({
38771
38915
  workspace,
38772
38916
  index,
38773
38917
  rowClass,
38774
38918
  onWorkspaceClick,
38775
- getMedalIcon,
38776
- getLineName
38919
+ getMedalIcon
38777
38920
  }) => /* @__PURE__ */ jsxRuntime.jsxs(
38778
38921
  "tr",
38779
38922
  {
38780
38923
  onClick: () => onWorkspaceClick(workspace, index + 1),
38781
- className: `${rowClass} hover:bg-gray-50/90 transition-colors cursor-pointer group`,
38924
+ className: `${rowClass} hover:bg-gray-50/90 transition-all duration-300 cursor-pointer group`,
38925
+ style: {
38926
+ willChange: "opacity, background-color",
38927
+ animation: "fadeIn 0.3s ease-in-out"
38928
+ },
38782
38929
  children: [
38783
38930
  /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap group-hover:font-medium", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
38784
38931
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: index + 1 }),
38785
38932
  getMedalIcon(index + 1)
38786
38933
  ] }) }),
38787
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id) }) }),
38788
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: getLineName(workspace.line_id) }) }),
38934
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: workspace.displayName }) }),
38935
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: workspace.lineName }) }),
38789
38936
  /* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base font-medium whitespace-nowrap", children: [
38790
38937
  (workspace.efficiency || 0).toFixed(1),
38791
38938
  "%"
@@ -38803,7 +38950,9 @@ var DesktopWorkspaceRow = React21.memo(({
38803
38950
  ] })
38804
38951
  ]
38805
38952
  }
38806
- ));
38953
+ ), (prevProps, nextProps) => {
38954
+ return prevProps.index === nextProps.index && prevProps.rowClass === nextProps.rowClass && prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.efficiency === nextProps.workspace.efficiency && prevProps.workspace.action_count === nextProps.workspace.action_count && prevProps.workspace.action_threshold === nextProps.workspace.action_threshold && prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.displayName === nextProps.workspace.displayName && prevProps.workspace.lineName === nextProps.workspace.lineName && prevProps.onWorkspaceClick === nextProps.onWorkspaceClick && prevProps.getMedalIcon === nextProps.getMedalIcon;
38955
+ });
38807
38956
  DesktopWorkspaceRow.displayName = "DesktopWorkspaceRow";
38808
38957
  var LeaderboardDetailView = React21.memo(({
38809
38958
  lineId,
@@ -38819,6 +38968,13 @@ var LeaderboardDetailView = React21.memo(({
38819
38968
  const navigation = useNavigation();
38820
38969
  const entityConfig = useEntityConfig();
38821
38970
  const [sortAscending, setSortAscending] = React21.useState(false);
38971
+ const [isMobile, setIsMobile] = React21.useState(false);
38972
+ React21__namespace.default.useEffect(() => {
38973
+ const checkMobile = () => setIsMobile(window.innerWidth < 640);
38974
+ checkMobile();
38975
+ window.addEventListener("resize", checkMobile);
38976
+ return () => window.removeEventListener("resize", checkMobile);
38977
+ }, []);
38822
38978
  const configuredLineNames = React21.useMemo(() => {
38823
38979
  return getAllLineDisplayNames(entityConfig);
38824
38980
  }, [entityConfig]);
@@ -38836,18 +38992,10 @@ var LeaderboardDetailView = React21.memo(({
38836
38992
  const handleSortToggle = React21.useCallback(() => {
38837
38993
  setSortAscending(!sortAscending);
38838
38994
  }, [sortAscending]);
38839
- const realtimeMetricsParams = React21.useMemo(() => ({
38840
- lineId: lineId || "",
38841
- date,
38842
- shiftId: typeof shift === "number" ? shift : typeof shift === "string" ? parseInt(shift) : void 0
38843
- }), [lineId, date, shift]);
38844
- const {
38845
- metrics: metrics2,
38846
- lineDetails,
38847
- loading: metricsLoading,
38848
- error: metricsError,
38849
- refreshMetrics
38850
- } = useRealtimeLineMetrics(realtimeMetricsParams);
38995
+ const shiftId = React21.useMemo(
38996
+ () => typeof shift === "number" ? shift : typeof shift === "string" ? parseInt(shift) : void 0,
38997
+ [shift]
38998
+ );
38851
38999
  const {
38852
39000
  workspaces,
38853
39001
  loading: workspacesLoading,
@@ -38857,12 +39005,12 @@ var LeaderboardDetailView = React21.memo(({
38857
39005
  initialDate: date,
38858
39006
  initialShiftId: typeof shift === "number" ? shift : typeof shift === "string" ? parseInt(shift) : void 0
38859
39007
  });
38860
- const getShiftName = React21.useCallback((shiftId) => {
38861
- if (shiftId === void 0) return "Day";
38862
- return shiftId === 0 ? "Day" : "Night";
39008
+ const getShiftName = React21.useCallback((shiftId2) => {
39009
+ if (shiftId2 === void 0) return "Day";
39010
+ return shiftId2 === 0 ? "Day" : "Night";
38863
39011
  }, []);
38864
- const getShiftIcon = React21.useCallback((shiftId) => {
38865
- const shift2 = getShiftName(shiftId);
39012
+ const getShiftIcon = React21.useCallback((shiftId2) => {
39013
+ const shift2 = getShiftName(shiftId2);
38866
39014
  if (shift2 === "Day") {
38867
39015
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" }) });
38868
39016
  } else {
@@ -38904,17 +39052,18 @@ var LeaderboardDetailView = React21.memo(({
38904
39052
  return null;
38905
39053
  }
38906
39054
  }, [sortAscending]);
39055
+ const workspacesLength = React21.useMemo(() => workspaces?.length || 0, [workspaces?.length]);
38907
39056
  const handleWorkspaceClick = React21.useCallback((workspace, rank) => {
38908
39057
  trackCoreEvent("Workspace from Leaderboard Clicked", {
38909
39058
  workspace_name: workspace.workspace_name,
38910
39059
  workspace_id: workspace.workspace_uuid,
38911
39060
  rank,
38912
- total_workspaces: workspaces?.length || 0,
39061
+ total_workspaces: workspacesLength,
38913
39062
  efficiency: workspace.efficiency,
38914
39063
  action_count: workspace.action_count,
38915
39064
  action_threshold: workspace.action_threshold
38916
39065
  });
38917
- const displayName = getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
39066
+ const displayName = workspace.displayName || getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
38918
39067
  const navParams = workspace.workspace_uuid ? getWorkspaceNavigationParams(workspace.workspace_uuid, displayName, workspace.line_id) : "";
38919
39068
  const returnToParam = `&returnTo=${encodeURIComponent(`/leaderboard`)}`;
38920
39069
  if (onWorkspaceClick) {
@@ -38922,20 +39071,33 @@ var LeaderboardDetailView = React21.memo(({
38922
39071
  } else {
38923
39072
  navigation.navigate(`/workspace/${workspace.workspace_uuid}${navParams}${returnToParam}`);
38924
39073
  }
38925
- }, [onWorkspaceClick, navigation, lineId, workspaces?.length]);
38926
- const sortedWorkspaces = React21.useMemo(() => {
39074
+ }, [onWorkspaceClick, navigation, lineId, workspacesLength]);
39075
+ const workspaceDisplayData = React21.useMemo(() => {
38927
39076
  if (!workspaces) return [];
38928
- return [...workspaces].sort((a, b) => {
39077
+ return workspaces.map((ws) => ({
39078
+ ...ws,
39079
+ displayName: getWorkspaceDisplayName(ws.workspace_name, ws.line_id),
39080
+ lineName: getLineName(ws.line_id)
39081
+ }));
39082
+ }, [workspaces, getLineName]);
39083
+ const sortedWorkspaces = React21.useMemo(() => {
39084
+ return [...workspaceDisplayData].sort((a, b) => {
38929
39085
  const effA = a.efficiency || 0;
38930
39086
  const effB = b.efficiency || 0;
38931
39087
  return sortAscending ? effA - effB : effB - effA;
38932
39088
  });
38933
- }, [workspaces, sortAscending]);
38934
- const loading = React21.useMemo(() => metricsLoading || workspacesLoading, [metricsLoading, workspacesLoading]);
38935
- const error = React21.useMemo(() => metricsError || workspacesError, [metricsError, workspacesError]);
38936
- const currentDateFormatted = React21.useMemo(() => formatDate(/* @__PURE__ */ new Date()), [formatDate]);
38937
- const currentMobileDateFormatted = React21.useMemo(() => formatMobileDate(/* @__PURE__ */ new Date()), [formatMobileDate]);
38938
- if (loading) {
39089
+ }, [workspaceDisplayData, sortAscending]);
39090
+ const loading = workspacesLoading;
39091
+ const error = workspacesError;
39092
+ const currentDateFormatted = React21.useMemo(() => {
39093
+ const dateStr = (/* @__PURE__ */ new Date()).toDateString();
39094
+ return formatDate(new Date(dateStr));
39095
+ }, [formatDate, date]);
39096
+ const currentMobileDateFormatted = React21.useMemo(() => {
39097
+ const dateStr = (/* @__PURE__ */ new Date()).toDateString();
39098
+ return formatMobileDate(new Date(dateStr));
39099
+ }, [formatMobileDate, date]);
39100
+ if (loading && (!workspaces || workspaces.length === 0)) {
38939
39101
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `h-[calc(100vh-64px)] flex items-center justify-center bg-slate-50 ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xl text-gray-600", children: "Loading workspaces..." }) });
38940
39102
  }
38941
39103
  if (error) {
@@ -38944,7 +39106,7 @@ var LeaderboardDetailView = React21.memo(({
38944
39106
  error.message
38945
39107
  ] }) });
38946
39108
  }
38947
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `min-h-screen bg-slate-50 flex flex-col ${className}`, children: [
39109
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `min-h-screen bg-slate-50 flex flex-col ${className}`, style: { willChange: "contents" }, children: [
38948
39110
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-0 z-20 bg-white shadow-sm border-b border-gray-200/80", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 sm:px-6 md:px-8 py-2 sm:py-2.5", children: [
38949
39111
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
38950
39112
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -39036,31 +39198,30 @@ var LeaderboardDetailView = React21.memo(({
39036
39198
  {
39037
39199
  currentDate: currentDateFormatted,
39038
39200
  currentMobileDate: currentMobileDateFormatted,
39039
- shiftId: metrics2?.shift_id,
39201
+ shiftId,
39040
39202
  getShiftIcon,
39041
39203
  getShiftName
39042
39204
  }
39043
39205
  )
39044
39206
  ] }) }),
39045
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 w-full mx-auto p-3 sm:p-4 md:p-6", children: [
39046
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden space-y-3", children: sortedWorkspaces.map((ws, index) => {
39047
- const rank = index + 1;
39048
- const isTopThree = index < 3;
39049
- const cardClass = sortAscending ? isTopThree ? "bg-red-50/90 border-red-200" : "bg-white" : isTopThree ? "bg-green-50/90 border-green-200" : "bg-white";
39050
- return /* @__PURE__ */ jsxRuntime.jsx(
39051
- MobileWorkspaceCard,
39052
- {
39053
- workspace: ws,
39054
- rank,
39055
- cardClass,
39056
- onWorkspaceClick: handleWorkspaceClick,
39057
- getMedalIcon,
39058
- getLineName
39059
- },
39060
- ws.workspace_uuid
39061
- );
39062
- }) }),
39063
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block bg-white rounded-lg shadow-md overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse table-auto", children: [
39207
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full mx-auto p-3 sm:p-4 md:p-6", children: isMobile ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: sortedWorkspaces.map((ws, index) => {
39208
+ const rank = index + 1;
39209
+ const isTopThree = index < 3;
39210
+ const cardClass = sortAscending ? isTopThree ? "bg-red-50/90 border-red-200" : "bg-white" : isTopThree ? "bg-green-50/90 border-green-200" : "bg-white";
39211
+ return /* @__PURE__ */ jsxRuntime.jsx(
39212
+ MobileWorkspaceCard,
39213
+ {
39214
+ workspace: ws,
39215
+ rank,
39216
+ cardClass,
39217
+ onWorkspaceClick: handleWorkspaceClick,
39218
+ getMedalIcon
39219
+ },
39220
+ ws.workspace_uuid
39221
+ );
39222
+ }) }) : (
39223
+ /* Desktop table view - only render on desktop */
39224
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white rounded-lg shadow-md overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse table-auto", children: [
39064
39225
  /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-gray-50 border-b border-gray-200 sticky top-0 z-10", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
39065
39226
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2.5 sm:p-4 text-left text-xs sm:text-sm font-semibold text-gray-600 whitespace-nowrap", children: "Rank" }),
39066
39227
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2.5 sm:p-4 text-left text-xs sm:text-sm font-semibold text-gray-600 whitespace-nowrap", children: "Workspace" }),
@@ -39079,17 +39240,16 @@ var LeaderboardDetailView = React21.memo(({
39079
39240
  index,
39080
39241
  rowClass,
39081
39242
  onWorkspaceClick: handleWorkspaceClick,
39082
- getMedalIcon,
39083
- getLineName
39243
+ getMedalIcon
39084
39244
  },
39085
39245
  ws.workspace_uuid
39086
39246
  );
39087
39247
  }) })
39088
39248
  ] }) }) })
39089
- ] })
39249
+ ) })
39090
39250
  ] });
39091
39251
  }, (prevProps, nextProps) => {
39092
- return prevProps.lineId === nextProps.lineId && prevProps.date === nextProps.date && prevProps.shift === nextProps.shift && prevProps.line1Id === nextProps.line1Id && prevProps.line2Id === nextProps.line2Id && JSON.stringify(prevProps.lineNames) === JSON.stringify(nextProps.lineNames) && prevProps.className === nextProps.className && prevProps.onBackClick === nextProps.onBackClick && prevProps.onWorkspaceClick === nextProps.onWorkspaceClick;
39252
+ return prevProps.lineId === nextProps.lineId && prevProps.date === nextProps.date && prevProps.shift === nextProps.shift && prevProps.line1Id === nextProps.line1Id && prevProps.line2Id === nextProps.line2Id && JSON.stringify(prevProps.lineNames) === JSON.stringify(nextProps.lineNames) && prevProps.className === nextProps.className;
39093
39253
  });
39094
39254
  LeaderboardDetailView.displayName = "LeaderboardDetailView";
39095
39255
  var LeaderboardDetailViewWithDisplayNames = withAllWorkspaceDisplayNames(LeaderboardDetailView);
@@ -40198,24 +40358,12 @@ var ACTION_NAMES = {
40198
40358
  // src/views/TargetsView.utils.ts
40199
40359
  var calculatePPH = (cycleTime, breaks = [], shiftHours = 0) => {
40200
40360
  if (cycleTime === "" || cycleTime === 0) return "";
40201
- const basicPPH = 3600 / cycleTime;
40202
- if (breaks.length === 0 || shiftHours === 0) {
40203
- return Number(basicPPH.toFixed(1));
40204
- }
40205
- const safeBreaks = Array.isArray(breaks) ? breaks : [];
40206
- const totalBreakMinutes = safeBreaks.reduce((total, breakItem) => total + breakItem.duration, 0);
40207
- const totalBreakHours = totalBreakMinutes / 60;
40208
- const realWorkHours = shiftHours - totalBreakHours;
40209
- const effectivePPH = basicPPH * (realWorkHours / shiftHours);
40210
- return Number(effectivePPH.toFixed(1));
40361
+ const pph = 3600 / cycleTime;
40362
+ return Number(pph.toFixed(1));
40211
40363
  };
40212
40364
  var calculateDayOutput = (pph, shiftHours, breaks = []) => {
40213
40365
  if (pph === "") return "";
40214
- const safeBreaks = Array.isArray(breaks) ? breaks : [];
40215
- const totalBreakMinutes = safeBreaks.reduce((total, breakItem) => total + breakItem.duration, 0);
40216
- const totalBreakHours = totalBreakMinutes / 60;
40217
- const realWorkHours = shiftHours - totalBreakHours;
40218
- return Math.round(pph * realWorkHours);
40366
+ return Math.round(pph * shiftHours);
40219
40367
  };
40220
40368
  var formatWorkspaceName = (name, lineId) => {
40221
40369
  return getWorkspaceDisplayName(name, lineId);
@@ -44263,6 +44411,7 @@ exports.AuthenticatedHomeView = AuthenticatedHomeView;
44263
44411
  exports.AuthenticatedShiftsView = AuthenticatedShiftsView;
44264
44412
  exports.AuthenticatedTargetsView = AuthenticatedTargetsView;
44265
44413
  exports.AuthenticatedWorkspaceHealthView = AuthenticatedWorkspaceHealthView;
44414
+ exports.AxelNotificationPopup = AxelNotificationPopup;
44266
44415
  exports.BackButton = BackButton;
44267
44416
  exports.BackButtonMinimal = BackButtonMinimal;
44268
44417
  exports.BarChart = BarChart;