@optifye/dashboard-core 6.11.33 → 6.11.35

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,109 @@ 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 buildPrefetchedExplorerMetadata = (activeFilter, metadataCategoryId, categoryMetadata) => {
37451
+ if (!activeFilter || !metadataCategoryId || metadataCategoryId !== activeFilter || categoryMetadata.length === 0) {
37452
+ return void 0;
37453
+ }
37454
+ return {
37455
+ [activeFilter]: categoryMetadata
37456
+ };
37457
+ };
37458
+ var getSecondsBetweenTimestamps = (startTime, endTime) => {
37459
+ const startDate = parseTimestamp(startTime);
37460
+ const endDate = parseTimestamp(endTime);
37461
+ if (!startDate || !endDate) return null;
37462
+ return Math.max(0, (endDate.getTime() - startDate.getTime()) / 1e3);
37463
+ };
37464
+ var formatClipExplorerTimeLabel = ({
37465
+ categoryId,
37466
+ clipTimestamp,
37467
+ timezone,
37468
+ durationSeconds,
37469
+ idleStartTime,
37470
+ idleEndTime
37471
+ }) => {
37472
+ if (IDLE_RANGE_CATEGORY_IDS.has(categoryId)) {
37473
+ const idleDurationSeconds = getSecondsBetweenTimestamps(idleStartTime, idleEndTime);
37474
+ const idleEndTimestamp = idleEndTime || clipTimestamp;
37475
+ if (idleDurationSeconds !== null && idleDurationSeconds >= 60 && idleStartTime && idleEndTime) {
37476
+ return formatTimestampRange(idleStartTime, idleEndTime, timezone);
37477
+ }
37478
+ if (idleDurationSeconds === null && typeof durationSeconds === "number" && Number.isFinite(durationSeconds) && durationSeconds >= 60) {
37479
+ const endDate = parseTimestamp(idleEndTimestamp);
37480
+ if (endDate) {
37481
+ const startDate = new Date(endDate.getTime() - durationSeconds * 1e3);
37482
+ return formatTimestampRange(startDate.toISOString(), idleEndTimestamp, timezone);
37483
+ }
37484
+ }
37485
+ return formatClipExplorerSingleTime(idleEndTimestamp, timezone);
37486
+ }
37487
+ const singleTime = formatClipExplorerSingleTime(clipTimestamp, timezone);
37488
+ if (CYCLE_RANGE_CATEGORY_IDS.has(categoryId) && typeof durationSeconds === "number" && Number.isFinite(durationSeconds) && durationSeconds > 60) {
37489
+ const endDate = parseTimestamp(clipTimestamp);
37490
+ if (endDate) {
37491
+ const startDate = new Date(endDate.getTime() - durationSeconds * 1e3);
37492
+ return formatTimestampRange(startDate.toISOString(), clipTimestamp, timezone);
37493
+ }
37494
+ }
37495
+ return singleTime;
37496
+ };
37497
+ var formatIdleTimeRange = (startTime, endTime, timezone) => formatTimestampRange(startTime, endTime, timezone);
37370
37498
  var formatTime2 = (seconds) => {
37371
37499
  if (!seconds || isNaN(seconds)) return "0:00";
37372
37500
  const h = Math.floor(seconds / 3600);
@@ -41333,15 +41461,16 @@ var FileManagerFilters = ({
41333
41461
  if ((displayCount > 0 || shouldShowEmptyIdleTime) && shouldShowCategory(category.id)) {
41334
41462
  const colorClasses = getColorClasses(category.color);
41335
41463
  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
41464
  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)` : ""}`;
41465
+ const baseTimeLabel = formatClipExplorerTimeLabel({
41466
+ categoryId: category.id,
41467
+ clipTimestamp: clip.clip_timestamp,
41468
+ timezone,
41469
+ durationSeconds: clip.duration,
41470
+ idleStartTime: clip.idle_start_time,
41471
+ idleEndTime: clip.idle_end_time
41472
+ });
41473
+ const displayLabel = `${baseTimeLabel}${clip.duration && category.id !== "idle_time" && category.id !== "low_value" ? ` - (${clip.duration.toFixed(1)}s)` : ""}`;
41345
41474
  return {
41346
41475
  id: clip.id,
41347
41476
  label: displayLabel,
@@ -41392,16 +41521,15 @@ var FileManagerFilters = ({
41392
41521
  percentileType: "fast-cycles",
41393
41522
  isPercentile: true,
41394
41523
  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
41524
  const cycleTime = extractCycleTimeSeconds(clip);
41402
41525
  return {
41403
41526
  id: clip.id,
41404
- label: `${timeString}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
41527
+ label: `${formatClipExplorerTimeLabel({
41528
+ categoryId: "fast-cycles",
41529
+ clipTimestamp: clip.creation_timestamp || clip.timestamp || "",
41530
+ timezone,
41531
+ durationSeconds: cycleTime
41532
+ })}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
41405
41533
  type: "video",
41406
41534
  icon: getSeverityIcon(clip.severity, "fast-cycles", cycleTime, resolvedTargetCycleTime),
41407
41535
  timestamp: clip.creation_timestamp,
@@ -41424,16 +41552,15 @@ var FileManagerFilters = ({
41424
41552
  percentileType: "slow-cycles",
41425
41553
  isPercentile: true,
41426
41554
  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
41555
  const cycleTime = extractCycleTimeSeconds(clip);
41434
41556
  return {
41435
41557
  id: clip.id,
41436
- label: `${timeString}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
41558
+ label: `${formatClipExplorerTimeLabel({
41559
+ categoryId: "slow-cycles",
41560
+ clipTimestamp: clip.creation_timestamp || clip.timestamp || "",
41561
+ timezone,
41562
+ durationSeconds: cycleTime
41563
+ })}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
41437
41564
  type: "video",
41438
41565
  icon: getSeverityIcon(clip.severity, "slow-cycles", cycleTime, resolvedTargetCycleTime),
41439
41566
  timestamp: clip.creation_timestamp,
@@ -42525,6 +42652,7 @@ var BottlenecksContent = ({
42525
42652
  const [error, setError] = React143.useState(null);
42526
42653
  const [clipClassifications, setClipClassifications] = React143.useState({});
42527
42654
  const [categoryMetadata, setCategoryMetadata] = React143.useState([]);
42655
+ const [categoryMetadataCategoryId, setCategoryMetadataCategoryId] = React143.useState(null);
42528
42656
  const [currentMetadataIndex, setCurrentMetadataIndex] = React143.useState(0);
42529
42657
  const [metadataCache, setMetadataCache] = React143.useState({});
42530
42658
  const invalidateMetadataCache = React143.useCallback((categories) => {
@@ -42996,6 +43124,15 @@ var BottlenecksContent = ({
42996
43124
  const getMetadataCacheKey = React143.useCallback((categoryId) => {
42997
43125
  return `${categoryId}-${effectiveDateString}-${effectiveShiftId}-${snapshotDateTime ?? "nosnap"}-${snapshotClipId ?? "nosnap"}`;
42998
43126
  }, [effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId]);
43127
+ const setVisibleCategoryMetadata = React143.useCallback((categoryId, clips) => {
43128
+ if (activeFilterRef.current !== categoryId) {
43129
+ return false;
43130
+ }
43131
+ categoryMetadataRef.current = clips;
43132
+ setCategoryMetadata(clips);
43133
+ setCategoryMetadataCategoryId(clips.length > 0 ? categoryId : null);
43134
+ return true;
43135
+ }, []);
42999
43136
  const applyMetadataSnapshot = React143.useCallback((categoryId, clips, total) => {
43000
43137
  if (!clips || clips.length === 0) {
43001
43138
  return;
@@ -43005,13 +43142,12 @@ var BottlenecksContent = ({
43005
43142
  ...prev,
43006
43143
  [cacheKey]: clips
43007
43144
  }));
43008
- categoryMetadataRef.current = clips;
43009
- setCategoryMetadata(clips);
43145
+ setVisibleCategoryMetadata(categoryId, clips);
43010
43146
  if (!isPercentileCategory(categoryId) && typeof total === "number") {
43011
43147
  currentTotalRef.current = total;
43012
43148
  setCurrentTotal(total);
43013
43149
  }
43014
- }, [getMetadataCacheKey, isPercentileCategory]);
43150
+ }, [getMetadataCacheKey, isPercentileCategory, setVisibleCategoryMetadata]);
43015
43151
  const getClipTypesForPercentileCategory = React143.useCallback((categoryId) => {
43016
43152
  switch (categoryId) {
43017
43153
  case "fast-cycles":
@@ -43036,6 +43172,7 @@ var BottlenecksContent = ({
43036
43172
  return;
43037
43173
  }
43038
43174
  setCategoryMetadata([]);
43175
+ setCategoryMetadataCategoryId(null);
43039
43176
  categoryMetadataRef.current = [];
43040
43177
  updateActiveFilter(fallbackFilter);
43041
43178
  }, [isFastSlowClipFiltersEnabled, activeFilter, dynamicCounts, clipTypes, updateActiveFilter]);
@@ -43082,6 +43219,7 @@ var BottlenecksContent = ({
43082
43219
  }
43083
43220
  if (!isFastSlowClipFiltersEnabled && (categoryId === "fast-cycles" || categoryId === "slow-cycles")) {
43084
43221
  setCategoryMetadata([]);
43222
+ setCategoryMetadataCategoryId(null);
43085
43223
  categoryMetadataRef.current = [];
43086
43224
  return;
43087
43225
  }
@@ -43095,8 +43233,7 @@ var BottlenecksContent = ({
43095
43233
  try {
43096
43234
  if (cachedMetadata) {
43097
43235
  console.log(`[BottlenecksContent] Using cached metadata for ${categoryId}`);
43098
- setCategoryMetadata(cachedMetadata);
43099
- categoryMetadataRef.current = cachedMetadata;
43236
+ setVisibleCategoryMetadata(categoryId, cachedMetadata);
43100
43237
  if (autoLoadFirstVideo && cachedMetadata.length > 0 && s3ClipsService) {
43101
43238
  const firstClipMeta = cachedMetadata[0];
43102
43239
  try {
@@ -43210,8 +43347,7 @@ var BottlenecksContent = ({
43210
43347
  ...prev,
43211
43348
  [cacheKey]: metadataClips
43212
43349
  }));
43213
- setCategoryMetadata(metadataClips);
43214
- categoryMetadataRef.current = metadataClips;
43350
+ setVisibleCategoryMetadata(categoryId, metadataClips);
43215
43351
  console.log(`[BottlenecksContent] Loaded metadata for ${categoryId}: ${metadataClips.length} clips`);
43216
43352
  if (autoLoadFirstVideo && metadataClips.length > 0 && s3ClipsService) {
43217
43353
  const firstClipMeta = metadataClips[0];
@@ -43230,15 +43366,18 @@ var BottlenecksContent = ({
43230
43366
  }
43231
43367
  }
43232
43368
  } else {
43233
- setCategoryMetadata([]);
43234
- categoryMetadataRef.current = [];
43369
+ if (activeFilterRef.current === categoryId) {
43370
+ setCategoryMetadata([]);
43371
+ setCategoryMetadataCategoryId(null);
43372
+ categoryMetadataRef.current = [];
43373
+ }
43235
43374
  }
43236
43375
  } catch (error2) {
43237
43376
  console.error(`[BottlenecksContent] Error loading category metadata:`, error2);
43238
43377
  } finally {
43239
43378
  setIsCategoryLoading(false);
43240
43379
  }
43241
- }, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, supabase]);
43380
+ }, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, supabase, setVisibleCategoryMetadata]);
43242
43381
  React143.useEffect(() => {
43243
43382
  if (previousFilterRef.current !== activeFilter) {
43244
43383
  console.log(`Filter changed from ${previousFilterRef.current} to ${activeFilter} - resetting to first video`);
@@ -43248,6 +43387,7 @@ var BottlenecksContent = ({
43248
43387
  setIsNavigating(false);
43249
43388
  loadingCategoryRef.current = null;
43250
43389
  setCategoryMetadata([]);
43390
+ setCategoryMetadataCategoryId(null);
43251
43391
  setCurrentMetadataIndex(0);
43252
43392
  categoryMetadataRef.current = [];
43253
43393
  currentMetadataIndexRef.current = 0;
@@ -43806,14 +43946,11 @@ var BottlenecksContent = ({
43806
43946
  }
43807
43947
  return currentPosition;
43808
43948
  }, [activeFilter, categoryMetadata.length, currentMetadataIndex, currentPosition, isPercentileCategory]);
43809
- const prefetchedExplorerMetadata = React143.useMemo(() => {
43810
- if (!activeFilter || categoryMetadata.length === 0) {
43811
- return void 0;
43812
- }
43813
- return {
43814
- [activeFilter]: categoryMetadata
43815
- };
43816
- }, [activeFilter, categoryMetadata]);
43949
+ const prefetchedExplorerMetadata = React143.useMemo(() => buildPrefetchedExplorerMetadata(
43950
+ activeFilter,
43951
+ categoryMetadataCategoryId,
43952
+ categoryMetadata
43953
+ ), [activeFilter, categoryMetadata, categoryMetadataCategoryId]);
43817
43954
  const classificationClipIds = React143.useMemo(() => {
43818
43955
  if (!idleTimeVlmEnabled) {
43819
43956
  return [];
@@ -46907,6 +47044,41 @@ var IdleTimeReasonChartComponent = ({
46907
47044
  var IdleTimeReasonChart = React143__namespace.default.memo(IdleTimeReasonChartComponent);
46908
47045
  IdleTimeReasonChart.displayName = "IdleTimeReasonChart";
46909
47046
  var IdleTimeReasonChart_default = IdleTimeReasonChart;
47047
+
47048
+ // src/lib/utils/cycleTime.ts
47049
+ var toFiniteNumber = (value) => {
47050
+ if (typeof value === "number" && Number.isFinite(value)) return value;
47051
+ if (typeof value === "string" && value.trim() !== "") {
47052
+ const parsed = Number(value);
47053
+ return Number.isFinite(parsed) ? parsed : null;
47054
+ }
47055
+ return null;
47056
+ };
47057
+ var getCycleRatio = (workspace) => {
47058
+ const idealCycleTime = toFiniteNumber(workspace.ideal_cycle_time);
47059
+ const avgCycleTime = toFiniteNumber(workspace.avg_cycle_time);
47060
+ if (idealCycleTime === null || avgCycleTime === null || idealCycleTime <= 0 || avgCycleTime <= 0) {
47061
+ return null;
47062
+ }
47063
+ return idealCycleTime / avgCycleTime;
47064
+ };
47065
+ var formatCycleTimeValue = (value) => {
47066
+ const numericValue = toFiniteNumber(value);
47067
+ if (numericValue === null || numericValue <= 0) return "--";
47068
+ return `${numericValue.toFixed(1)}s`;
47069
+ };
47070
+ var CycleTimeComparison = React143.memo(({
47071
+ workspace
47072
+ }) => {
47073
+ const averageValue = formatCycleTimeValue(workspace.avg_cycle_time);
47074
+ const standardValue = formatCycleTimeValue(workspace.ideal_cycle_time);
47075
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 tabular-nums", children: [
47076
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-gray-900", children: averageValue }),
47077
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400 font-normal", children: "/" }),
47078
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-gray-500", children: standardValue })
47079
+ ] });
47080
+ }, (prevProps, nextProps) => prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.ideal_cycle_time === nextProps.workspace.ideal_cycle_time);
47081
+ CycleTimeComparison.displayName = "CycleTimeComparison";
46910
47082
  var DEFAULT_PERFORMANCE_DATA = {
46911
47083
  avg_efficiency: 0,
46912
47084
  underperforming_workspaces: 0,
@@ -47005,6 +47177,7 @@ var LineMonthlyHistory = ({
47005
47177
  timezone,
47006
47178
  legend,
47007
47179
  monitoringMode,
47180
+ lineAssembly = false,
47008
47181
  underperformingWorkspaces = {},
47009
47182
  lineId,
47010
47183
  selectedShiftId = 0,
@@ -47294,7 +47467,7 @@ var LineMonthlyHistory = ({
47294
47467
  "div",
47295
47468
  {
47296
47469
  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)` : ""}`
47470
+ 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
47471
  },
47299
47472
  `${performance2.date}-${index}`
47300
47473
  )) });
@@ -47540,13 +47713,20 @@ var LineMonthlyHistory = ({
47540
47713
  onClick: () => handleWorkspaceClick(workspace),
47541
47714
  className: "block hover:bg-gray-50 transition-colors rounded-lg w-full text-left group",
47542
47715
  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
- "(",
47716
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
47717
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-gray-900 text-[10px] sm:text-xs truncate", children: getWorkspaceDisplayName(workspace.workspace_name, lineId) }),
47718
+ lineAssembly && workspace.metric_mode === "cycle_time" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-0.5 text-[9px] sm:text-[11px]", children: /* @__PURE__ */ jsxRuntime.jsx(
47719
+ CycleTimeComparison,
47720
+ {
47721
+ workspace: {
47722
+ avg_cycle_time: workspace.avg_cycle_time ?? 0,
47723
+ ideal_cycle_time: workspace.ideal_cycle_time ?? void 0
47724
+ }
47725
+ }
47726
+ ) }) : workspace.avg_efficiency !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-0.5 text-[8px] sm:text-[10px] text-gray-500", children: [
47547
47727
  (workspace.avg_efficiency || 0).toFixed(1),
47548
- "%)"
47549
- ] })
47728
+ "%"
47729
+ ] }) : null
47550
47730
  ] }),
47551
47731
  /* @__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
47732
  ] })
@@ -49916,7 +50096,7 @@ var WorkspaceMonthlyHistory = ({
49916
50096
  Math.round(shiftData.efficiency || 0),
49917
50097
  "%"
49918
50098
  ] }),
49919
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
50099
+ !isAssemblyWorkspace && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
49920
50100
  "Output: ",
49921
50101
  shiftData.output || 0,
49922
50102
  " units"
@@ -62059,41 +62239,6 @@ function useEfficiencyLegend(companyId) {
62059
62239
  };
62060
62240
  }
62061
62241
 
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
62242
  // src/lib/utils/kpiPoorestPerformers.ts
62098
62243
  var getWorstAssemblyCycleTimeWorkspaces = (workspaces, limit = 5) => {
62099
62244
  return workspaces.map((workspace, index) => ({
@@ -63281,27 +63426,33 @@ var KPIDetailView = ({
63281
63426
  error: idleTimeError
63282
63427
  }), [idleTimeRawData, idleTimeChartData, idleTimeLoading, idleTimeError]);
63283
63428
  React143.useEffect(() => {
63284
- if (activeTab === "monthly_history" && lineId) {
63429
+ if (activeTab === "monthly_history" && lineId && lineDetails) {
63285
63430
  if (!supabase || !dashboardConfig || !dashboardConfig.supabaseUrl || !dashboardConfig.supabaseKey) {
63286
63431
  console.error("Supabase client or required config not available in KPIsPage for monthly data");
63287
63432
  return;
63288
63433
  }
63289
63434
  setMonthlyDataLoading(true);
63435
+ const monthlyShiftIds = shiftConfig?.shifts?.map((s) => s.shiftId);
63436
+ const monthlyHistoryAssemblyMode = lineDetails.assembly === true && !isUptimeMode;
63437
+ const underperformingPromise = monthlyHistoryAssemblyMode ? dashboardService.getAssemblyMonthlyPoorestPerformers(lineId, currentMonth, currentYear, {
63438
+ startDate: isFullRange ? void 0 : range.startKey,
63439
+ endDate: isFullRange ? void 0 : range.endKey,
63440
+ shiftIds: monthlyShiftIds
63441
+ }) : dashboardService.getUnderperformingWorkspaces(
63442
+ lineId,
63443
+ currentMonth,
63444
+ currentYear,
63445
+ monthlyShiftIds,
63446
+ isFullRange ? void 0 : range.startKey,
63447
+ isFullRange ? void 0 : range.endKey
63448
+ );
63290
63449
  Promise.all([
63291
63450
  dashboardService.getLineMonthlyData(lineId, currentMonth, currentYear, {
63292
63451
  startDate: isFullRange ? void 0 : range.startKey,
63293
63452
  endDate: isFullRange ? void 0 : range.endKey,
63294
- shiftIds: shiftConfig?.shifts?.map((s) => s.shiftId)
63453
+ shiftIds: monthlyShiftIds
63295
63454
  }),
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
- )
63455
+ underperformingPromise
63305
63456
  ]).then(([monthlyMetrics, underperformingData]) => {
63306
63457
  console.log("Fetched monthly metrics data:", monthlyMetrics);
63307
63458
  const dayDataMap = /* @__PURE__ */ new Map();
@@ -63365,11 +63516,17 @@ var KPIDetailView = ({
63365
63516
  const mapWorkspaces = (workspaces2) => (workspaces2 || []).map((ws) => ({
63366
63517
  workspace_name: ws.workspace_name || "Unknown Workspace",
63367
63518
  workspace_uuid: ws.workspace_uuid || ws.workspace_name || `unknown-${Math.random()}`,
63368
- avg_efficiency: ws.avg_efficiency || 0,
63519
+ avg_efficiency: ws.avg_efficiency ?? 0,
63520
+ avg_cycle_time: ws.avg_cycle_time ?? null,
63521
+ ideal_cycle_time: ws.ideal_cycle_time ?? null,
63522
+ cycle_ratio: ws.cycle_ratio ?? null,
63523
+ metric_mode: ws.metric_mode ?? "efficiency",
63369
63524
  last_5_days: (ws.last_5_days || []).map((day) => ({
63370
63525
  date: day.date,
63371
63526
  efficiency: day.efficiency ?? 0,
63372
- performance_score: day.performance_score
63527
+ performance_score: day.performance_score,
63528
+ avg_cycle_time: day.avg_cycle_time ?? null,
63529
+ ideal_cycle_time: day.ideal_cycle_time ?? null
63373
63530
  }))
63374
63531
  }));
63375
63532
  const mappedData = {};
@@ -63394,7 +63551,7 @@ var KPIDetailView = ({
63394
63551
  setMonthlyDataLoading(false);
63395
63552
  });
63396
63553
  }
63397
- }, [activeTab, lineId, currentMonth, currentYear, supabase, dashboardConfig, shiftConfig, range.startKey, range.endKey, isFullRange, configuredTimezone, isUptimeMode, resolveShiftTimes]);
63554
+ }, [activeTab, lineId, lineDetails, currentMonth, currentYear, supabase, dashboardConfig, shiftConfig, range.startKey, range.endKey, isFullRange, configuredTimezone, isUptimeMode, resolveShiftTimes]);
63398
63555
  const analysisMonthlyData = React143.useMemo(() => {
63399
63556
  return filterDataByDateKeyRange(monthlyData, range);
63400
63557
  }, [monthlyData, range]);
@@ -64300,6 +64457,7 @@ var KPIDetailView = ({
64300
64457
  timezone: configuredTimezone,
64301
64458
  legend: efficiencyLegend,
64302
64459
  monitoringMode: resolvedMonitoringMode,
64460
+ lineAssembly: resolvedLineInfo?.assembly === true,
64303
64461
  shiftConfig,
64304
64462
  selectedShiftId,
64305
64463
  onShiftChange: setSelectedShiftId,
@@ -70626,7 +70784,20 @@ var WorkspaceDetailView = ({
70626
70784
  } = useCompanyFastSlowClipFiltersEnabled();
70627
70785
  const isClipsEnabled = dashboardConfig?.clipsConfig?.enabled ?? true;
70628
70786
  dashboardConfig?.supervisorConfig?.enabled || false;
70629
- const effectiveLineId = lineId || selectedLineId;
70787
+ const routedLineId = lineId || selectedLineId;
70788
+ const latestCachedDetailedMetrics = React143.useMemo(() => {
70789
+ if (!workspaceId) {
70790
+ return null;
70791
+ }
70792
+ return workspaceMetricsStore.getLatestDetailed(workspaceId);
70793
+ }, [workspaceId]);
70794
+ const latestCachedOverviewMetrics = React143.useMemo(() => {
70795
+ if (!workspaceId) {
70796
+ return null;
70797
+ }
70798
+ return workspaceMetricsStore.getLatestOverview(workspaceId);
70799
+ }, [workspaceId]);
70800
+ const effectiveLineId = routedLineId || latestCachedDetailedMetrics?.line_id || latestCachedOverviewMetrics?.line_id;
70630
70801
  const { shiftConfig, isLoading: isShiftConfigLoading, isFromDatabase: isShiftConfigFromDatabase } = useDynamicShiftConfig(effectiveLineId);
70631
70802
  const currentShiftDetails = React143.useMemo(() => {
70632
70803
  if (isShiftConfigLoading || !shiftConfig) return null;
@@ -70903,8 +71074,9 @@ var WorkspaceDetailView = ({
70903
71074
  }, [cachedOverviewMetrics, shiftConfig?.shifts]);
70904
71075
  const authoritativeCycleMetrics = isHistoricView ? historicMetrics : liveMetrics;
70905
71076
  const workspace = authoritativeCycleMetrics || cachedDetailedMetrics || overviewFallback;
71077
+ const resolvedLineId = effectiveLineId || workspace?.line_id || cachedDetailedMetrics?.line_id || cachedOverviewMetrics?.line_id || overviewFallback?.line_id;
70906
71078
  const { timezone: cycleTimeTimezone } = useTimezone({
70907
- lineId: effectiveLineId || workspace?.line_id || void 0,
71079
+ lineId: resolvedLineId || void 0,
70908
71080
  workspaceId: workspaceId || void 0
70909
71081
  });
70910
71082
  const effectiveCycleTimeTimezone = cycleTimeTimezone || timezone;
@@ -70949,7 +71121,7 @@ var WorkspaceDetailView = ({
70949
71121
  const error = isHistoricView ? historicError : liveError;
70950
71122
  const monitoringMode = workspace?.monitoring_mode ?? "output";
70951
71123
  const isUptimeMode = monitoringMode === "uptime";
70952
- const idleTimeVlmEnabled = isIdleTimeVlmEnabled(effectiveLineId || workspace?.line_id);
71124
+ const idleTimeVlmEnabled = isIdleTimeVlmEnabled(resolvedLineId);
70953
71125
  React143.useEffect(() => {
70954
71126
  if (!isClipsEnabled || !dashboardConfig?.s3Config || !workspaceId) {
70955
71127
  return;
@@ -71184,7 +71356,7 @@ var WorkspaceDetailView = ({
71184
71356
  const analysisMonthlyData = React143.useMemo(() => {
71185
71357
  return filterDataByDateKeyRange(monthlyData, range);
71186
71358
  }, [monthlyData, range]);
71187
- const formattedWorkspaceName = displayName || formatWorkspaceName3(workspace?.workspace_name || "", effectiveLineId);
71359
+ const formattedWorkspaceName = displayName || formatWorkspaceName3(workspace?.workspace_name || "", resolvedLineId);
71188
71360
  const workspaceCycleTimeEligibility = workspace ? {
71189
71361
  line_assembly_enabled: workspace.line_assembly_enabled,
71190
71362
  action_family: workspace.action_family,
@@ -71361,8 +71533,8 @@ var WorkspaceDetailView = ({
71361
71533
  params.set("rangeStart", range.startKey);
71362
71534
  params.set("rangeEnd", range.endKey);
71363
71535
  }
71364
- if (effectiveLineId) {
71365
- params.set("lineId", effectiveLineId);
71536
+ if (resolvedLineId) {
71537
+ params.set("lineId", resolvedLineId);
71366
71538
  }
71367
71539
  appendReturnUrl(params);
71368
71540
  onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
@@ -71391,8 +71563,8 @@ var WorkspaceDetailView = ({
71391
71563
  params.set("rangeStart", range.startKey);
71392
71564
  params.set("rangeEnd", range.endKey);
71393
71565
  }
71394
- if (effectiveLineId) {
71395
- params.set("lineId", effectiveLineId);
71566
+ if (resolvedLineId) {
71567
+ params.set("lineId", resolvedLineId);
71396
71568
  }
71397
71569
  appendReturnUrl(params);
71398
71570
  onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
@@ -72016,7 +72188,7 @@ var WorkspaceDetailView = ({
72016
72188
  month: selectedMonth,
72017
72189
  year: selectedYear,
72018
72190
  workspaceId,
72019
- lineId: effectiveLineId || workspace?.line_id,
72191
+ lineId: resolvedLineId,
72020
72192
  monitoringMode: workspace?.monitoring_mode,
72021
72193
  selectedShiftId: selectedShift,
72022
72194
  rangeStart,
@@ -72041,8 +72213,8 @@ var WorkspaceDetailView = ({
72041
72213
  params.set("rangeStart", range.startKey);
72042
72214
  params.set("rangeEnd", range.endKey);
72043
72215
  }
72044
- if (effectiveLineId) {
72045
- params.set("lineId", effectiveLineId);
72216
+ if (resolvedLineId) {
72217
+ params.set("lineId", resolvedLineId);
72046
72218
  }
72047
72219
  appendReturnUrl(params);
72048
72220
  onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
@@ -72070,7 +72242,7 @@ var WorkspaceDetailView = ({
72070
72242
  workspaceId,
72071
72243
  workspaceName: formattedWorkspaceName,
72072
72244
  date,
72073
- lineId: effectiveLineId,
72245
+ lineId: resolvedLineId,
72074
72246
  shift,
72075
72247
  totalOutput: workspace?.total_actions,
72076
72248
  workspaceMetrics: detailedWorkspaceMetrics || void 0,