@optifye/dashboard-core 6.11.33 → 6.11.34

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
@@ -4574,6 +4574,49 @@ var dashboardService = {
4574
4574
  throw err;
4575
4575
  }
4576
4576
  },
4577
+ async getAssemblyMonthlyPoorestPerformers(lineIdInput, month, year, options) {
4578
+ const supabase = _getSupabaseInstance();
4579
+ const config = _getDashboardConfigInstance();
4580
+ const entityConfig = config.entityConfig ?? DEFAULT_ENTITY_CONFIG;
4581
+ const configuredLineIds = getConfiguredLineIds(entityConfig);
4582
+ const factoryViewId = entityConfig.factoryViewId ?? "factory";
4583
+ const startDate = options?.startDate ? new Date(options.startDate) : new Date(year, month, 1);
4584
+ const endDate = options?.endDate ? new Date(options.endDate) : new Date(year, month + 1, 0);
4585
+ const formatDate2 = (date) => {
4586
+ const year2 = date.getFullYear();
4587
+ const month2 = String(date.getMonth() + 1).padStart(2, "0");
4588
+ const day = String(date.getDate()).padStart(2, "0");
4589
+ return `${year2}-${month2}-${day}`;
4590
+ };
4591
+ const formattedStartDate = formatDate2(startDate);
4592
+ const formattedEndDate = formatDate2(endDate);
4593
+ const params = new URLSearchParams({
4594
+ start_date: formattedStartDate,
4595
+ end_date: formattedEndDate,
4596
+ company_id: entityConfig.companyId || ""
4597
+ });
4598
+ if (lineIdInput === factoryViewId) {
4599
+ if (!isValidFactoryViewConfiguration(entityConfig)) {
4600
+ throw new Error("Factory View requires at least one configured line for monthly data.");
4601
+ }
4602
+ params.set("line_ids", configuredLineIds.join(","));
4603
+ } else {
4604
+ params.set("line_id", lineIdInput);
4605
+ }
4606
+ if (options?.shiftIds && options.shiftIds.length > 0) {
4607
+ params.set("shift_ids", options.shiftIds.join(","));
4608
+ }
4609
+ try {
4610
+ const response = await fetchBackendJson(
4611
+ supabase,
4612
+ `/api/dashboard/line-monthly-assembly-poorest-performers?${params.toString()}`
4613
+ );
4614
+ return response || {};
4615
+ } catch (err) {
4616
+ console.error("Exception in getAssemblyMonthlyPoorestPerformers:", err);
4617
+ throw err;
4618
+ }
4619
+ },
4577
4620
  async getUnderperformingWorkspaces(lineIdInput, monthInput, yearInput, shiftIds, startDate, endDate) {
4578
4621
  _getSupabaseInstance();
4579
4622
  const config = _getDashboardConfigInstance();
@@ -16714,6 +16757,7 @@ var runtimeWorkspaceDisplayNames = {};
16714
16757
  var isInitialized = false;
16715
16758
  var isInitializing = false;
16716
16759
  var initializedWithLineIds = [];
16760
+ var missingLineContextWarnings = /* @__PURE__ */ new Set();
16717
16761
  var initializationPromise = null;
16718
16762
  var workspaceDisplayNamesListeners = /* @__PURE__ */ new Set();
16719
16763
  var notifyWorkspaceDisplayNamesListeners = (changedLineId) => {
@@ -16883,6 +16927,9 @@ var forceRefreshWorkspaceDisplayNames = async (lineId) => {
16883
16927
  };
16884
16928
  console.log("\u{1F504} Module loaded, will initialize lazily when first function is called");
16885
16929
  var getWorkspaceDisplayName = (workspaceId, lineId) => {
16930
+ if (!workspaceId) {
16931
+ return workspaceId;
16932
+ }
16886
16933
  if (!isInitialized && !isInitializing) {
16887
16934
  console.log(`\u{1F504} [DEBUG] getWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) - Not initialized, triggering lazy init...`);
16888
16935
  } else if (isInitializing) {
@@ -16914,7 +16961,11 @@ var getWorkspaceDisplayName = (workspaceId, lineId) => {
16914
16961
  for (const cachedLineId of Object.keys(runtimeWorkspaceDisplayNames)) {
16915
16962
  if (runtimeWorkspaceDisplayNames[cachedLineId][workspaceId]) {
16916
16963
  displayName = runtimeWorkspaceDisplayNames[cachedLineId][workspaceId];
16917
- console.warn(`\u26A0\uFE0F No lineId provided for ${workspaceId}, found in line ${cachedLineId}`);
16964
+ const warningKey = `${workspaceId}:${cachedLineId}:full`;
16965
+ if (!missingLineContextWarnings.has(warningKey)) {
16966
+ missingLineContextWarnings.add(warningKey);
16967
+ console.warn(`\u26A0\uFE0F No lineId provided for ${workspaceId}, found in line ${cachedLineId}`);
16968
+ }
16918
16969
  break;
16919
16970
  }
16920
16971
  }
@@ -16929,6 +16980,9 @@ var getWorkspaceDisplayName = (workspaceId, lineId) => {
16929
16980
  }
16930
16981
  };
16931
16982
  var getShortWorkspaceDisplayName = (workspaceId, lineId) => {
16983
+ if (!workspaceId) {
16984
+ return workspaceId;
16985
+ }
16932
16986
  if (!isInitialized && !isInitializing) {
16933
16987
  console.log("\u{1F504} Lazy initialization triggered by getShortWorkspaceDisplayName with lineId:", lineId);
16934
16988
  initializeWorkspaceDisplayNames(lineId).catch((error) => {
@@ -16955,7 +17009,11 @@ var getShortWorkspaceDisplayName = (workspaceId, lineId) => {
16955
17009
  for (const cachedLineId of Object.keys(runtimeWorkspaceDisplayNames)) {
16956
17010
  if (runtimeWorkspaceDisplayNames[cachedLineId][workspaceId]) {
16957
17011
  displayName = runtimeWorkspaceDisplayNames[cachedLineId][workspaceId];
16958
- console.warn(`\u26A0\uFE0F No lineId provided for ${workspaceId}, found in line ${cachedLineId}`);
17012
+ const warningKey = `${workspaceId}:${cachedLineId}:short`;
17013
+ if (!missingLineContextWarnings.has(warningKey)) {
17014
+ missingLineContextWarnings.add(warningKey);
17015
+ console.warn(`\u26A0\uFE0F No lineId provided for ${workspaceId}, found in line ${cachedLineId}`);
17016
+ }
16959
17017
  break;
16960
17018
  }
16961
17019
  }
@@ -17827,7 +17885,6 @@ var usePrefetchClipCounts = ({
17827
17885
  subscriberId
17828
17886
  }) => {
17829
17887
  const [status] = React143.useState("idle" /* IDLE */);
17830
- console.log("[usePrefetchClipCounts] DISABLED - Returning empty state");
17831
17888
  return {
17832
17889
  status,
17833
17890
  data: null,
@@ -17836,7 +17893,6 @@ var usePrefetchClipCounts = ({
17836
17893
  isFullyIndexed: false,
17837
17894
  isLoading: false,
17838
17895
  prefetchClipCounts: async () => {
17839
- console.log("[usePrefetchClipCounts] DISABLED - Not prefetching");
17840
17896
  return null;
17841
17897
  },
17842
17898
  cacheKey: `disabled:${workspaceId}:${date}:${shift}`
@@ -37336,37 +37392,101 @@ var getSeverityColor = (severity) => {
37336
37392
  return "bg-gray-500";
37337
37393
  }
37338
37394
  };
37339
- var formatIdleTimeRange = (startTime, endTime, timezone) => {
37340
- const roundToNearestMinute = (date) => {
37341
- const rounded = new Date(date.getTime());
37342
- const seconds = rounded.getSeconds();
37343
- if (seconds > 30) {
37344
- rounded.setMinutes(rounded.getMinutes() + 1);
37345
- }
37346
- rounded.setSeconds(0);
37347
- rounded.setMilliseconds(0);
37348
- return rounded;
37349
- };
37350
- const startDate = roundToNearestMinute(new Date(startTime));
37351
- const endDate = roundToNearestMinute(new Date(endTime));
37352
- const formatTimeWithoutPeriod = (date, tz) => {
37353
- return date.toLocaleTimeString("en-US", {
37354
- hour: "numeric",
37355
- minute: "2-digit",
37356
- timeZone: tz
37357
- }).replace(/\s?(AM|PM)$/i, "");
37358
- };
37359
- const formatTimeWithPeriod = (date, tz) => {
37360
- return date.toLocaleTimeString("en-US", {
37361
- hour: "numeric",
37362
- minute: "2-digit",
37363
- timeZone: tz
37364
- });
37365
- };
37366
- const startFormatted = formatTimeWithoutPeriod(startDate, timezone);
37367
- const endFormatted = formatTimeWithPeriod(endDate, timezone);
37395
+ var IDLE_RANGE_CATEGORY_IDS = /* @__PURE__ */ new Set(["idle_time", "low_value", "longest-idles"]);
37396
+ var CYCLE_RANGE_CATEGORY_IDS = /* @__PURE__ */ new Set([
37397
+ "cycle_completion",
37398
+ "best_cycle_time",
37399
+ "worst_cycle_time",
37400
+ "long_cycle_time",
37401
+ "fast-cycles",
37402
+ "slow-cycles"
37403
+ ]);
37404
+ var roundToNearestMinute = (date) => {
37405
+ const rounded = new Date(date.getTime());
37406
+ const seconds = rounded.getSeconds();
37407
+ if (seconds > 30) {
37408
+ rounded.setMinutes(rounded.getMinutes() + 1);
37409
+ }
37410
+ rounded.setSeconds(0);
37411
+ rounded.setMilliseconds(0);
37412
+ return rounded;
37413
+ };
37414
+ var parseTimestamp = (value) => {
37415
+ if (!value) return null;
37416
+ const parsed = new Date(value);
37417
+ return Number.isNaN(parsed.getTime()) ? null : parsed;
37418
+ };
37419
+ var formatTimeWithoutPeriod = (date, timezone) => date.toLocaleTimeString("en-US", {
37420
+ hour: "numeric",
37421
+ minute: "2-digit",
37422
+ timeZone: timezone
37423
+ }).replace(/\s?(AM|PM)$/i, "");
37424
+ var formatClipExplorerSingleTime = (timestamp, timezone) => {
37425
+ const parsed = parseTimestamp(timestamp);
37426
+ if (!parsed) return "";
37427
+ return parsed.toLocaleTimeString("en-US", {
37428
+ hour12: true,
37429
+ hour: "numeric",
37430
+ minute: "2-digit",
37431
+ timeZone: timezone
37432
+ });
37433
+ };
37434
+ var formatTimestampRange = (startTime, endTime, timezone) => {
37435
+ const startDate = parseTimestamp(startTime);
37436
+ const endDate = parseTimestamp(endTime);
37437
+ if (!startDate || !endDate) {
37438
+ return formatClipExplorerSingleTime(endTime, timezone);
37439
+ }
37440
+ const roundedStart = roundToNearestMinute(startDate);
37441
+ const roundedEnd = roundToNearestMinute(endDate);
37442
+ const startFormatted = formatTimeWithoutPeriod(roundedStart, timezone);
37443
+ const endFormatted = roundedEnd.toLocaleTimeString("en-US", {
37444
+ hour: "numeric",
37445
+ minute: "2-digit",
37446
+ timeZone: timezone
37447
+ });
37368
37448
  return `${startFormatted} - ${endFormatted}`;
37369
37449
  };
37450
+ var getSecondsBetweenTimestamps = (startTime, endTime) => {
37451
+ const startDate = parseTimestamp(startTime);
37452
+ const endDate = parseTimestamp(endTime);
37453
+ if (!startDate || !endDate) return null;
37454
+ return Math.max(0, (endDate.getTime() - startDate.getTime()) / 1e3);
37455
+ };
37456
+ var formatClipExplorerTimeLabel = ({
37457
+ categoryId,
37458
+ clipTimestamp,
37459
+ timezone,
37460
+ durationSeconds,
37461
+ idleStartTime,
37462
+ idleEndTime
37463
+ }) => {
37464
+ if (IDLE_RANGE_CATEGORY_IDS.has(categoryId)) {
37465
+ const idleDurationSeconds = getSecondsBetweenTimestamps(idleStartTime, idleEndTime);
37466
+ const idleEndTimestamp = idleEndTime || clipTimestamp;
37467
+ if (idleDurationSeconds !== null && idleDurationSeconds >= 60 && idleStartTime && idleEndTime) {
37468
+ return formatTimestampRange(idleStartTime, idleEndTime, timezone);
37469
+ }
37470
+ if (idleDurationSeconds === null && typeof durationSeconds === "number" && Number.isFinite(durationSeconds) && durationSeconds >= 60) {
37471
+ const endDate = parseTimestamp(idleEndTimestamp);
37472
+ if (endDate) {
37473
+ const startDate = new Date(endDate.getTime() - durationSeconds * 1e3);
37474
+ return formatTimestampRange(startDate.toISOString(), idleEndTimestamp, timezone);
37475
+ }
37476
+ }
37477
+ return formatClipExplorerSingleTime(idleEndTimestamp, timezone);
37478
+ }
37479
+ const singleTime = formatClipExplorerSingleTime(clipTimestamp, timezone);
37480
+ if (CYCLE_RANGE_CATEGORY_IDS.has(categoryId) && typeof durationSeconds === "number" && Number.isFinite(durationSeconds) && durationSeconds > 60) {
37481
+ const endDate = parseTimestamp(clipTimestamp);
37482
+ if (endDate) {
37483
+ const startDate = new Date(endDate.getTime() - durationSeconds * 1e3);
37484
+ return formatTimestampRange(startDate.toISOString(), clipTimestamp, timezone);
37485
+ }
37486
+ }
37487
+ return singleTime;
37488
+ };
37489
+ var formatIdleTimeRange = (startTime, endTime, timezone) => formatTimestampRange(startTime, endTime, timezone);
37370
37490
  var formatTime2 = (seconds) => {
37371
37491
  if (!seconds || isNaN(seconds)) return "0:00";
37372
37492
  const h = Math.floor(seconds / 3600);
@@ -41333,15 +41453,16 @@ var FileManagerFilters = ({
41333
41453
  if ((displayCount > 0 || shouldShowEmptyIdleTime) && shouldShowCategory(category.id)) {
41334
41454
  const colorClasses = getColorClasses(category.color);
41335
41455
  const clipNodes = filteredClips.map((clip, index) => {
41336
- const timeString = new Date(clip.clip_timestamp).toLocaleTimeString("en-US", {
41337
- hour12: true,
41338
- hour: "numeric",
41339
- minute: "2-digit",
41340
- timeZone: timezone
41341
- // Use database timezone for display
41342
- });
41343
41456
  const cycleTime = extractCycleTimeSeconds(clip);
41344
- const displayLabel = category.id === "idle_time" && clip.idle_start_time && clip.idle_end_time ? formatIdleTimeRange(clip.idle_start_time, clip.idle_end_time, timezone) : `${timeString}${clip.duration && category.id !== "idle_time" ? ` - (${clip.duration.toFixed(1)}s)` : ""}`;
41457
+ const baseTimeLabel = formatClipExplorerTimeLabel({
41458
+ categoryId: category.id,
41459
+ clipTimestamp: clip.clip_timestamp,
41460
+ timezone,
41461
+ durationSeconds: clip.duration,
41462
+ idleStartTime: clip.idle_start_time,
41463
+ idleEndTime: clip.idle_end_time
41464
+ });
41465
+ const displayLabel = `${baseTimeLabel}${clip.duration && category.id !== "idle_time" && category.id !== "low_value" ? ` - (${clip.duration.toFixed(1)}s)` : ""}`;
41345
41466
  return {
41346
41467
  id: clip.id,
41347
41468
  label: displayLabel,
@@ -41392,16 +41513,15 @@ var FileManagerFilters = ({
41392
41513
  percentileType: "fast-cycles",
41393
41514
  isPercentile: true,
41394
41515
  children: filteredFastCycles.map((clip, index) => {
41395
- const timeString = new Date(clip.creation_timestamp || clip.timestamp || "").toLocaleTimeString("en-US", {
41396
- hour12: true,
41397
- hour: "numeric",
41398
- minute: "2-digit",
41399
- timeZone: timezone
41400
- });
41401
41516
  const cycleTime = extractCycleTimeSeconds(clip);
41402
41517
  return {
41403
41518
  id: clip.id,
41404
- label: `${timeString}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
41519
+ label: `${formatClipExplorerTimeLabel({
41520
+ categoryId: "fast-cycles",
41521
+ clipTimestamp: clip.creation_timestamp || clip.timestamp || "",
41522
+ timezone,
41523
+ durationSeconds: cycleTime
41524
+ })}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
41405
41525
  type: "video",
41406
41526
  icon: getSeverityIcon(clip.severity, "fast-cycles", cycleTime, resolvedTargetCycleTime),
41407
41527
  timestamp: clip.creation_timestamp,
@@ -41424,16 +41544,15 @@ var FileManagerFilters = ({
41424
41544
  percentileType: "slow-cycles",
41425
41545
  isPercentile: true,
41426
41546
  children: filteredSlowCycles.map((clip, index) => {
41427
- const timeString = new Date(clip.creation_timestamp || clip.timestamp || "").toLocaleTimeString("en-US", {
41428
- hour12: true,
41429
- hour: "numeric",
41430
- minute: "2-digit",
41431
- timeZone: timezone
41432
- });
41433
41547
  const cycleTime = extractCycleTimeSeconds(clip);
41434
41548
  return {
41435
41549
  id: clip.id,
41436
- label: `${timeString}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
41550
+ label: `${formatClipExplorerTimeLabel({
41551
+ categoryId: "slow-cycles",
41552
+ clipTimestamp: clip.creation_timestamp || clip.timestamp || "",
41553
+ timezone,
41554
+ durationSeconds: cycleTime
41555
+ })}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
41437
41556
  type: "video",
41438
41557
  icon: getSeverityIcon(clip.severity, "slow-cycles", cycleTime, resolvedTargetCycleTime),
41439
41558
  timestamp: clip.creation_timestamp,
@@ -46907,6 +47026,41 @@ var IdleTimeReasonChartComponent = ({
46907
47026
  var IdleTimeReasonChart = React143__namespace.default.memo(IdleTimeReasonChartComponent);
46908
47027
  IdleTimeReasonChart.displayName = "IdleTimeReasonChart";
46909
47028
  var IdleTimeReasonChart_default = IdleTimeReasonChart;
47029
+
47030
+ // src/lib/utils/cycleTime.ts
47031
+ var toFiniteNumber = (value) => {
47032
+ if (typeof value === "number" && Number.isFinite(value)) return value;
47033
+ if (typeof value === "string" && value.trim() !== "") {
47034
+ const parsed = Number(value);
47035
+ return Number.isFinite(parsed) ? parsed : null;
47036
+ }
47037
+ return null;
47038
+ };
47039
+ var getCycleRatio = (workspace) => {
47040
+ const idealCycleTime = toFiniteNumber(workspace.ideal_cycle_time);
47041
+ const avgCycleTime = toFiniteNumber(workspace.avg_cycle_time);
47042
+ if (idealCycleTime === null || avgCycleTime === null || idealCycleTime <= 0 || avgCycleTime <= 0) {
47043
+ return null;
47044
+ }
47045
+ return idealCycleTime / avgCycleTime;
47046
+ };
47047
+ var formatCycleTimeValue = (value) => {
47048
+ const numericValue = toFiniteNumber(value);
47049
+ if (numericValue === null || numericValue <= 0) return "--";
47050
+ return `${numericValue.toFixed(1)}s`;
47051
+ };
47052
+ var CycleTimeComparison = React143.memo(({
47053
+ workspace
47054
+ }) => {
47055
+ const averageValue = formatCycleTimeValue(workspace.avg_cycle_time);
47056
+ const standardValue = formatCycleTimeValue(workspace.ideal_cycle_time);
47057
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 tabular-nums", children: [
47058
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-gray-900", children: averageValue }),
47059
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400 font-normal", children: "/" }),
47060
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-gray-500", children: standardValue })
47061
+ ] });
47062
+ }, (prevProps, nextProps) => prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.ideal_cycle_time === nextProps.workspace.ideal_cycle_time);
47063
+ CycleTimeComparison.displayName = "CycleTimeComparison";
46910
47064
  var DEFAULT_PERFORMANCE_DATA = {
46911
47065
  avg_efficiency: 0,
46912
47066
  underperforming_workspaces: 0,
@@ -47005,6 +47159,7 @@ var LineMonthlyHistory = ({
47005
47159
  timezone,
47006
47160
  legend,
47007
47161
  monitoringMode,
47162
+ lineAssembly = false,
47008
47163
  underperformingWorkspaces = {},
47009
47164
  lineId,
47010
47165
  selectedShiftId = 0,
@@ -47294,7 +47449,7 @@ var LineMonthlyHistory = ({
47294
47449
  "div",
47295
47450
  {
47296
47451
  className: `w-3 h-3 sm:w-4 sm:h-4 rounded ${getColorClass(performance2.performance_score)}`,
47297
- title: `${getPerformanceText(performance2.performance_score)} performance on ${new Date(performance2.date).toLocaleDateString()}${performance2.efficiency !== void 0 ? ` (${performance2.efficiency.toFixed(1)}% efficiency)` : ""}`
47452
+ title: `${getPerformanceText(performance2.performance_score)} performance on ${new Date(performance2.date).toLocaleDateString()}${performance2.efficiency !== void 0 ? ` (${performance2.efficiency.toFixed(1)}% efficiency)` : performance2.avg_cycle_time !== void 0 && performance2.avg_cycle_time !== null && performance2.ideal_cycle_time !== void 0 && performance2.ideal_cycle_time !== null ? ` (${performance2.avg_cycle_time.toFixed(1)}s / ${performance2.ideal_cycle_time.toFixed(1)}s cycle time)` : ""}`
47298
47453
  },
47299
47454
  `${performance2.date}-${index}`
47300
47455
  )) });
@@ -47540,13 +47695,20 @@ var LineMonthlyHistory = ({
47540
47695
  onClick: () => handleWorkspaceClick(workspace),
47541
47696
  className: "block hover:bg-gray-50 transition-colors rounded-lg w-full text-left group",
47542
47697
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between py-1 sm:py-1.5 lg:py-2 px-1 sm:px-2 border-b border-gray-50 group-last:border-b-0", children: [
47543
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "font-medium text-gray-900 text-[10px] sm:text-xs", children: [
47544
- getWorkspaceDisplayName(workspace.workspace_name, lineId),
47545
- workspace.avg_efficiency !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-0.5 sm:ml-1 text-[8px] sm:text-[10px] text-gray-500", children: [
47546
- "(",
47698
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
47699
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-gray-900 text-[10px] sm:text-xs truncate", children: getWorkspaceDisplayName(workspace.workspace_name, lineId) }),
47700
+ lineAssembly && workspace.metric_mode === "cycle_time" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-0.5 text-[9px] sm:text-[11px]", children: /* @__PURE__ */ jsxRuntime.jsx(
47701
+ CycleTimeComparison,
47702
+ {
47703
+ workspace: {
47704
+ avg_cycle_time: workspace.avg_cycle_time ?? 0,
47705
+ ideal_cycle_time: workspace.ideal_cycle_time ?? void 0
47706
+ }
47707
+ }
47708
+ ) }) : workspace.avg_efficiency !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-0.5 text-[8px] sm:text-[10px] text-gray-500", children: [
47547
47709
  (workspace.avg_efficiency || 0).toFixed(1),
47548
- "%)"
47549
- ] })
47710
+ "%"
47711
+ ] }) : null
47550
47712
  ] }),
47551
47713
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5 sm:gap-1 lg:gap-1.5", children: renderPerformanceSquares(workspace.last_5_days) })
47552
47714
  ] })
@@ -49916,7 +50078,7 @@ var WorkspaceMonthlyHistory = ({
49916
50078
  Math.round(shiftData.efficiency || 0),
49917
50079
  "%"
49918
50080
  ] }),
49919
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
50081
+ !isAssemblyWorkspace && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
49920
50082
  "Output: ",
49921
50083
  shiftData.output || 0,
49922
50084
  " units"
@@ -62059,41 +62221,6 @@ function useEfficiencyLegend(companyId) {
62059
62221
  };
62060
62222
  }
62061
62223
 
62062
- // src/lib/utils/cycleTime.ts
62063
- var toFiniteNumber = (value) => {
62064
- if (typeof value === "number" && Number.isFinite(value)) return value;
62065
- if (typeof value === "string" && value.trim() !== "") {
62066
- const parsed = Number(value);
62067
- return Number.isFinite(parsed) ? parsed : null;
62068
- }
62069
- return null;
62070
- };
62071
- var getCycleRatio = (workspace) => {
62072
- const idealCycleTime = toFiniteNumber(workspace.ideal_cycle_time);
62073
- const avgCycleTime = toFiniteNumber(workspace.avg_cycle_time);
62074
- if (idealCycleTime === null || avgCycleTime === null || idealCycleTime <= 0 || avgCycleTime <= 0) {
62075
- return null;
62076
- }
62077
- return idealCycleTime / avgCycleTime;
62078
- };
62079
- var formatCycleTimeValue = (value) => {
62080
- const numericValue = toFiniteNumber(value);
62081
- if (numericValue === null || numericValue <= 0) return "--";
62082
- return `${numericValue.toFixed(1)}s`;
62083
- };
62084
- var CycleTimeComparison = React143.memo(({
62085
- workspace
62086
- }) => {
62087
- const averageValue = formatCycleTimeValue(workspace.avg_cycle_time);
62088
- const standardValue = formatCycleTimeValue(workspace.ideal_cycle_time);
62089
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 tabular-nums", children: [
62090
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-gray-900", children: averageValue }),
62091
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400 font-normal", children: "/" }),
62092
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-gray-500", children: standardValue })
62093
- ] });
62094
- }, (prevProps, nextProps) => prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.ideal_cycle_time === nextProps.workspace.ideal_cycle_time);
62095
- CycleTimeComparison.displayName = "CycleTimeComparison";
62096
-
62097
62224
  // src/lib/utils/kpiPoorestPerformers.ts
62098
62225
  var getWorstAssemblyCycleTimeWorkspaces = (workspaces, limit = 5) => {
62099
62226
  return workspaces.map((workspace, index) => ({
@@ -63281,27 +63408,33 @@ var KPIDetailView = ({
63281
63408
  error: idleTimeError
63282
63409
  }), [idleTimeRawData, idleTimeChartData, idleTimeLoading, idleTimeError]);
63283
63410
  React143.useEffect(() => {
63284
- if (activeTab === "monthly_history" && lineId) {
63411
+ if (activeTab === "monthly_history" && lineId && lineDetails) {
63285
63412
  if (!supabase || !dashboardConfig || !dashboardConfig.supabaseUrl || !dashboardConfig.supabaseKey) {
63286
63413
  console.error("Supabase client or required config not available in KPIsPage for monthly data");
63287
63414
  return;
63288
63415
  }
63289
63416
  setMonthlyDataLoading(true);
63417
+ const monthlyShiftIds = shiftConfig?.shifts?.map((s) => s.shiftId);
63418
+ const monthlyHistoryAssemblyMode = lineDetails.assembly === true && !isUptimeMode;
63419
+ const underperformingPromise = monthlyHistoryAssemblyMode ? dashboardService.getAssemblyMonthlyPoorestPerformers(lineId, currentMonth, currentYear, {
63420
+ startDate: isFullRange ? void 0 : range.startKey,
63421
+ endDate: isFullRange ? void 0 : range.endKey,
63422
+ shiftIds: monthlyShiftIds
63423
+ }) : dashboardService.getUnderperformingWorkspaces(
63424
+ lineId,
63425
+ currentMonth,
63426
+ currentYear,
63427
+ monthlyShiftIds,
63428
+ isFullRange ? void 0 : range.startKey,
63429
+ isFullRange ? void 0 : range.endKey
63430
+ );
63290
63431
  Promise.all([
63291
63432
  dashboardService.getLineMonthlyData(lineId, currentMonth, currentYear, {
63292
63433
  startDate: isFullRange ? void 0 : range.startKey,
63293
63434
  endDate: isFullRange ? void 0 : range.endKey,
63294
- shiftIds: shiftConfig?.shifts?.map((s) => s.shiftId)
63435
+ shiftIds: monthlyShiftIds
63295
63436
  }),
63296
- dashboardService.getUnderperformingWorkspaces(
63297
- lineId,
63298
- currentMonth,
63299
- currentYear,
63300
- shiftConfig?.shifts?.map((s) => s.shiftId),
63301
- // Pass dynamic shift IDs
63302
- isFullRange ? void 0 : range.startKey,
63303
- isFullRange ? void 0 : range.endKey
63304
- )
63437
+ underperformingPromise
63305
63438
  ]).then(([monthlyMetrics, underperformingData]) => {
63306
63439
  console.log("Fetched monthly metrics data:", monthlyMetrics);
63307
63440
  const dayDataMap = /* @__PURE__ */ new Map();
@@ -63365,11 +63498,17 @@ var KPIDetailView = ({
63365
63498
  const mapWorkspaces = (workspaces2) => (workspaces2 || []).map((ws) => ({
63366
63499
  workspace_name: ws.workspace_name || "Unknown Workspace",
63367
63500
  workspace_uuid: ws.workspace_uuid || ws.workspace_name || `unknown-${Math.random()}`,
63368
- avg_efficiency: ws.avg_efficiency || 0,
63501
+ avg_efficiency: ws.avg_efficiency ?? 0,
63502
+ avg_cycle_time: ws.avg_cycle_time ?? null,
63503
+ ideal_cycle_time: ws.ideal_cycle_time ?? null,
63504
+ cycle_ratio: ws.cycle_ratio ?? null,
63505
+ metric_mode: ws.metric_mode ?? "efficiency",
63369
63506
  last_5_days: (ws.last_5_days || []).map((day) => ({
63370
63507
  date: day.date,
63371
63508
  efficiency: day.efficiency ?? 0,
63372
- performance_score: day.performance_score
63509
+ performance_score: day.performance_score,
63510
+ avg_cycle_time: day.avg_cycle_time ?? null,
63511
+ ideal_cycle_time: day.ideal_cycle_time ?? null
63373
63512
  }))
63374
63513
  }));
63375
63514
  const mappedData = {};
@@ -63394,7 +63533,7 @@ var KPIDetailView = ({
63394
63533
  setMonthlyDataLoading(false);
63395
63534
  });
63396
63535
  }
63397
- }, [activeTab, lineId, currentMonth, currentYear, supabase, dashboardConfig, shiftConfig, range.startKey, range.endKey, isFullRange, configuredTimezone, isUptimeMode, resolveShiftTimes]);
63536
+ }, [activeTab, lineId, lineDetails, currentMonth, currentYear, supabase, dashboardConfig, shiftConfig, range.startKey, range.endKey, isFullRange, configuredTimezone, isUptimeMode, resolveShiftTimes]);
63398
63537
  const analysisMonthlyData = React143.useMemo(() => {
63399
63538
  return filterDataByDateKeyRange(monthlyData, range);
63400
63539
  }, [monthlyData, range]);
@@ -64300,6 +64439,7 @@ var KPIDetailView = ({
64300
64439
  timezone: configuredTimezone,
64301
64440
  legend: efficiencyLegend,
64302
64441
  monitoringMode: resolvedMonitoringMode,
64442
+ lineAssembly: resolvedLineInfo?.assembly === true,
64303
64443
  shiftConfig,
64304
64444
  selectedShiftId,
64305
64445
  onShiftChange: setSelectedShiftId,
@@ -70626,7 +70766,20 @@ var WorkspaceDetailView = ({
70626
70766
  } = useCompanyFastSlowClipFiltersEnabled();
70627
70767
  const isClipsEnabled = dashboardConfig?.clipsConfig?.enabled ?? true;
70628
70768
  dashboardConfig?.supervisorConfig?.enabled || false;
70629
- const effectiveLineId = lineId || selectedLineId;
70769
+ const routedLineId = lineId || selectedLineId;
70770
+ const latestCachedDetailedMetrics = React143.useMemo(() => {
70771
+ if (!workspaceId) {
70772
+ return null;
70773
+ }
70774
+ return workspaceMetricsStore.getLatestDetailed(workspaceId);
70775
+ }, [workspaceId]);
70776
+ const latestCachedOverviewMetrics = React143.useMemo(() => {
70777
+ if (!workspaceId) {
70778
+ return null;
70779
+ }
70780
+ return workspaceMetricsStore.getLatestOverview(workspaceId);
70781
+ }, [workspaceId]);
70782
+ const effectiveLineId = routedLineId || latestCachedDetailedMetrics?.line_id || latestCachedOverviewMetrics?.line_id;
70630
70783
  const { shiftConfig, isLoading: isShiftConfigLoading, isFromDatabase: isShiftConfigFromDatabase } = useDynamicShiftConfig(effectiveLineId);
70631
70784
  const currentShiftDetails = React143.useMemo(() => {
70632
70785
  if (isShiftConfigLoading || !shiftConfig) return null;
@@ -70903,8 +71056,9 @@ var WorkspaceDetailView = ({
70903
71056
  }, [cachedOverviewMetrics, shiftConfig?.shifts]);
70904
71057
  const authoritativeCycleMetrics = isHistoricView ? historicMetrics : liveMetrics;
70905
71058
  const workspace = authoritativeCycleMetrics || cachedDetailedMetrics || overviewFallback;
71059
+ const resolvedLineId = effectiveLineId || workspace?.line_id || cachedDetailedMetrics?.line_id || cachedOverviewMetrics?.line_id || overviewFallback?.line_id;
70906
71060
  const { timezone: cycleTimeTimezone } = useTimezone({
70907
- lineId: effectiveLineId || workspace?.line_id || void 0,
71061
+ lineId: resolvedLineId || void 0,
70908
71062
  workspaceId: workspaceId || void 0
70909
71063
  });
70910
71064
  const effectiveCycleTimeTimezone = cycleTimeTimezone || timezone;
@@ -70949,7 +71103,7 @@ var WorkspaceDetailView = ({
70949
71103
  const error = isHistoricView ? historicError : liveError;
70950
71104
  const monitoringMode = workspace?.monitoring_mode ?? "output";
70951
71105
  const isUptimeMode = monitoringMode === "uptime";
70952
- const idleTimeVlmEnabled = isIdleTimeVlmEnabled(effectiveLineId || workspace?.line_id);
71106
+ const idleTimeVlmEnabled = isIdleTimeVlmEnabled(resolvedLineId);
70953
71107
  React143.useEffect(() => {
70954
71108
  if (!isClipsEnabled || !dashboardConfig?.s3Config || !workspaceId) {
70955
71109
  return;
@@ -71184,7 +71338,7 @@ var WorkspaceDetailView = ({
71184
71338
  const analysisMonthlyData = React143.useMemo(() => {
71185
71339
  return filterDataByDateKeyRange(monthlyData, range);
71186
71340
  }, [monthlyData, range]);
71187
- const formattedWorkspaceName = displayName || formatWorkspaceName3(workspace?.workspace_name || "", effectiveLineId);
71341
+ const formattedWorkspaceName = displayName || formatWorkspaceName3(workspace?.workspace_name || "", resolvedLineId);
71188
71342
  const workspaceCycleTimeEligibility = workspace ? {
71189
71343
  line_assembly_enabled: workspace.line_assembly_enabled,
71190
71344
  action_family: workspace.action_family,
@@ -71361,8 +71515,8 @@ var WorkspaceDetailView = ({
71361
71515
  params.set("rangeStart", range.startKey);
71362
71516
  params.set("rangeEnd", range.endKey);
71363
71517
  }
71364
- if (effectiveLineId) {
71365
- params.set("lineId", effectiveLineId);
71518
+ if (resolvedLineId) {
71519
+ params.set("lineId", resolvedLineId);
71366
71520
  }
71367
71521
  appendReturnUrl(params);
71368
71522
  onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
@@ -71391,8 +71545,8 @@ var WorkspaceDetailView = ({
71391
71545
  params.set("rangeStart", range.startKey);
71392
71546
  params.set("rangeEnd", range.endKey);
71393
71547
  }
71394
- if (effectiveLineId) {
71395
- params.set("lineId", effectiveLineId);
71548
+ if (resolvedLineId) {
71549
+ params.set("lineId", resolvedLineId);
71396
71550
  }
71397
71551
  appendReturnUrl(params);
71398
71552
  onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
@@ -72016,7 +72170,7 @@ var WorkspaceDetailView = ({
72016
72170
  month: selectedMonth,
72017
72171
  year: selectedYear,
72018
72172
  workspaceId,
72019
- lineId: effectiveLineId || workspace?.line_id,
72173
+ lineId: resolvedLineId,
72020
72174
  monitoringMode: workspace?.monitoring_mode,
72021
72175
  selectedShiftId: selectedShift,
72022
72176
  rangeStart,
@@ -72041,8 +72195,8 @@ var WorkspaceDetailView = ({
72041
72195
  params.set("rangeStart", range.startKey);
72042
72196
  params.set("rangeEnd", range.endKey);
72043
72197
  }
72044
- if (effectiveLineId) {
72045
- params.set("lineId", effectiveLineId);
72198
+ if (resolvedLineId) {
72199
+ params.set("lineId", resolvedLineId);
72046
72200
  }
72047
72201
  appendReturnUrl(params);
72048
72202
  onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
@@ -72070,7 +72224,7 @@ var WorkspaceDetailView = ({
72070
72224
  workspaceId,
72071
72225
  workspaceName: formattedWorkspaceName,
72072
72226
  date,
72073
- lineId: effectiveLineId,
72227
+ lineId: resolvedLineId,
72074
72228
  shift,
72075
72229
  totalOutput: workspace?.total_actions,
72076
72230
  workspaceMetrics: detailedWorkspaceMetrics || void 0,