@optifye/dashboard-core 6.10.50 → 6.10.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1029,6 +1029,44 @@ var fetchBackendJson = async (supabase, endpoint, options = {}) => {
1029
1029
  }
1030
1030
  };
1031
1031
 
1032
+ // src/lib/services/lineMetricsSelection.ts
1033
+ var toTimestamp = (value) => {
1034
+ if (typeof value !== "string") return 0;
1035
+ const parsed = Date.parse(value);
1036
+ return Number.isNaN(parsed) ? 0 : parsed;
1037
+ };
1038
+ var compareByLatestThenSku = (a, b) => {
1039
+ const timeDiff = toTimestamp(b.last_updated) - toTimestamp(a.last_updated);
1040
+ if (timeDiff !== 0) return timeDiff;
1041
+ const aSku = typeof a.sku_id === "string" ? a.sku_id : "";
1042
+ const bSku = typeof b.sku_id === "string" ? b.sku_id : "";
1043
+ return aSku.localeCompare(bSku);
1044
+ };
1045
+ var pickPreferredLineMetricsRow = async (supabase, lineId, rows, skuTable = "skus") => {
1046
+ if (!rows || rows.length === 0) {
1047
+ return null;
1048
+ }
1049
+ if (rows.length === 1) {
1050
+ return rows[0];
1051
+ }
1052
+ let dummySkuId = null;
1053
+ try {
1054
+ const { data } = await supabase.from(skuTable).select("id").eq("line_id", lineId).eq("sku_definition", "dummy_definition").eq("is_active", true).limit(1);
1055
+ if (Array.isArray(data) && data.length > 0) {
1056
+ dummySkuId = typeof data[0]?.id === "string" ? data[0].id : null;
1057
+ }
1058
+ } catch (error) {
1059
+ console.warn("[lineMetricsSelection] Failed dummy SKU lookup:", error);
1060
+ }
1061
+ if (dummySkuId) {
1062
+ const dummyRow = rows.find((row) => row.sku_id === dummySkuId);
1063
+ if (dummyRow) {
1064
+ return dummyRow;
1065
+ }
1066
+ }
1067
+ return rows.slice().sort(compareByLatestThenSku)[0] ?? null;
1068
+ };
1069
+
1032
1070
  // src/lib/services/dashboardService.ts
1033
1071
  var getTable = (dbConfig, tableName) => {
1034
1072
  const defaults2 = DEFAULT_DATABASE_CONFIG.tables;
@@ -1047,6 +1085,7 @@ var dashboardService = {
1047
1085
  const workspaceConfig = config.workspaceConfig ?? DEFAULT_WORKSPACE_CONFIG;
1048
1086
  const linesTable = getTable(dbConfig, "lines");
1049
1087
  const lineMetricsTable = getTable(dbConfig, "lineMetrics");
1088
+ const skuTable = dbConfig?.tables?.skus ?? "skus";
1050
1089
  const companyId = entityConfig.companyId;
1051
1090
  const metricsTablePrefixStr = getMetricsTablePrefix();
1052
1091
  `${metricsTablePrefixStr}_${companyId ? companyId.replace(/-/g, "_") : "unknown_company"}`;
@@ -1140,9 +1179,14 @@ var dashboardService = {
1140
1179
  if (!lineData) throw new Error(`Line with ID ${lineId} not found`);
1141
1180
  let metricsFromDb = null;
1142
1181
  try {
1143
- const { data: fetchedMetrics, error } = await supabase.from(lineMetricsTable).select("*").eq("line_id", lineId).eq("shift_id", shiftId).eq("date", date).maybeSingle();
1182
+ const { data: fetchedMetricsRows, error } = await supabase.from(lineMetricsTable).select("*").eq("line_id", lineId).eq("shift_id", shiftId).eq("date", date);
1144
1183
  if (error) throw error;
1145
- metricsFromDb = fetchedMetrics;
1184
+ metricsFromDb = await pickPreferredLineMetricsRow(
1185
+ supabase,
1186
+ lineId,
1187
+ fetchedMetricsRows,
1188
+ skuTable
1189
+ );
1146
1190
  } catch (err) {
1147
1191
  console.error(`Error fetching line metrics for ${lineId}:`, err);
1148
1192
  }
@@ -1553,6 +1597,7 @@ var dashboardService = {
1553
1597
  const workspaceConfig = config.workspaceConfig ?? DEFAULT_WORKSPACE_CONFIG;
1554
1598
  const linesTable = getTable(dbConfig, "lines");
1555
1599
  const lineMetricsTable = getTable(dbConfig, "lineMetrics");
1600
+ const skuTable = dbConfig?.tables?.skus ?? "skus";
1556
1601
  const companyId = entityConfig.companyId;
1557
1602
  const metricsTablePrefixStr = getMetricsTablePrefix();
1558
1603
  `${metricsTablePrefixStr}_${companyId ? companyId.replace(/-/g, "_") : "unknown_company"}`;
@@ -1651,7 +1696,7 @@ var dashboardService = {
1651
1696
  }
1652
1697
  const [lineResult, metricsResult] = await Promise.all([
1653
1698
  supabase.from(linesTable).select("id, line_name, factory_id, monitoring_mode, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", lineIdToQuery).single(),
1654
- supabase.from(lineMetricsTable).select("*").eq("line_id", lineIdToQuery).eq("shift_id", queryShiftId).eq("date", queryDate).maybeSingle()
1699
+ supabase.from(lineMetricsTable).select("*").eq("line_id", lineIdToQuery).eq("shift_id", queryShiftId).eq("date", queryDate)
1655
1700
  ]);
1656
1701
  if (lineResult.error) throw lineResult.error;
1657
1702
  if (!lineResult.data) {
@@ -1659,7 +1704,12 @@ var dashboardService = {
1659
1704
  }
1660
1705
  if (metricsResult.error) throw metricsResult.error;
1661
1706
  const lineData = lineResult.data;
1662
- const metrics2 = metricsResult.data;
1707
+ const metrics2 = await pickPreferredLineMetricsRow(
1708
+ supabase,
1709
+ lineIdToQuery,
1710
+ metricsResult.data,
1711
+ skuTable
1712
+ );
1663
1713
  return {
1664
1714
  line_id: lineData.id,
1665
1715
  line_name: lineData.line_name,
@@ -17330,6 +17380,7 @@ function useCompanyClipsCost() {
17330
17380
  const [data, setData] = useState(null);
17331
17381
  const [isLoading, setIsLoading] = useState(true);
17332
17382
  const [error, setError] = useState(null);
17383
+ const hasFetchedOnceRef = useRef(false);
17333
17384
  const canViewClipsCost = user?.role_level === "owner" || user?.role_level === "optifye";
17334
17385
  const companyId = user?.properties?.company_id || user?.company_id || entityConfig.companyId;
17335
17386
  const apiBaseUrl = config?.apiBaseUrl || process.env.NEXT_PUBLIC_API_BASE_URL || "";
@@ -17337,9 +17388,12 @@ function useCompanyClipsCost() {
17337
17388
  if (!canViewClipsCost || !companyId || !supabase || !apiBaseUrl || !session?.access_token) {
17338
17389
  setIsLoading(false);
17339
17390
  setData(null);
17391
+ hasFetchedOnceRef.current = false;
17340
17392
  return;
17341
17393
  }
17342
- setIsLoading(true);
17394
+ if (!hasFetchedOnceRef.current) {
17395
+ setIsLoading(true);
17396
+ }
17343
17397
  setError(null);
17344
17398
  try {
17345
17399
  const [statsResponse, linesResult] = await Promise.all([
@@ -17356,9 +17410,18 @@ function useCompanyClipsCost() {
17356
17410
  }
17357
17411
  const statsResult = await statsResponse.json();
17358
17412
  const totalClassifications = statsResult.total_classifications || 0;
17413
+ const monthlyClassifications = statsResult.monthly_classifications ?? totalClassifications;
17414
+ const monthStart = statsResult.month_start || null;
17415
+ const historicalMonthlyClassifications = Array.isArray(statsResult.historical_monthly_classifications) ? statsResult.historical_monthly_classifications.map((item) => ({
17416
+ monthStart: item?.month_start || "",
17417
+ classifications: Number(item?.classifications || 0)
17418
+ })).filter((item) => item.monthStart && item.classifications > 0) : [];
17359
17419
  const hasVlmEnabledLine = (linesResult.data?.length || 0) > 0;
17360
17420
  setData({
17361
17421
  totalClassifications,
17422
+ monthlyClassifications,
17423
+ monthStart,
17424
+ historicalMonthlyClassifications,
17362
17425
  hasVlmEnabledLine
17363
17426
  });
17364
17427
  } catch (err) {
@@ -17366,6 +17429,7 @@ function useCompanyClipsCost() {
17366
17429
  setError(err instanceof Error ? err.message : "Failed to load clips data");
17367
17430
  setData(null);
17368
17431
  } finally {
17432
+ hasFetchedOnceRef.current = true;
17369
17433
  setIsLoading(false);
17370
17434
  }
17371
17435
  }, [canViewClipsCost, companyId, supabase, apiBaseUrl, session?.access_token]);
@@ -36736,6 +36800,7 @@ var FileManagerFilters = ({
36736
36800
  const endInputRef = useRef(null);
36737
36801
  const [idleLabelFilter, setIdleLabelFilter] = useState(null);
36738
36802
  const [showIdleLabelFilterModal, setShowIdleLabelFilterModal] = useState(false);
36803
+ const [isLoadingIdleReasonOptions, setIsLoadingIdleReasonOptions] = useState(false);
36739
36804
  const timezone = useAppTimezone();
36740
36805
  const supabase = useSupabase();
36741
36806
  const [clipMetadata, setClipMetadata] = useState({});
@@ -36778,18 +36843,27 @@ var FileManagerFilters = ({
36778
36843
  iconColor: colorConfig.text
36779
36844
  };
36780
36845
  };
36781
- const ROOT_CAUSE_OPTIONS = [
36782
- "Operator Absent",
36783
- "Operator Idle",
36784
- "Machine Downtime",
36785
- "No Material"
36786
- ];
36846
+ const normalizeIdleReasonLabel = useCallback((label) => {
36847
+ return label.replace(/_/g, " ").trim();
36848
+ }, []);
36787
36849
  const getIdleTimeRootCause = useCallback((clipId) => {
36788
36850
  const classification = mergedClipClassifications[clipId];
36789
36851
  if (!classification) return "processing";
36790
36852
  if (classification.status === "processing") return "processing";
36791
36853
  return classification.label || "processing";
36792
36854
  }, [mergedClipClassifications]);
36855
+ const idleReasonOptions = useMemo(() => {
36856
+ const idleClips = clipMetadata["idle_time"] || [];
36857
+ const uniqueReasons = /* @__PURE__ */ new Set();
36858
+ idleClips.forEach((clip) => {
36859
+ const clipId = clip.clipId || clip.id;
36860
+ if (!clipId) return;
36861
+ const reason = getIdleTimeRootCause(clipId);
36862
+ if (!reason || reason === "processing") return;
36863
+ uniqueReasons.add(normalizeIdleReasonLabel(reason));
36864
+ });
36865
+ return Array.from(uniqueReasons).sort((a, b) => a.localeCompare(b));
36866
+ }, [clipMetadata, getIdleTimeRootCause, normalizeIdleReasonLabel]);
36793
36867
  const getClipBadge = useCallback((node) => {
36794
36868
  if (node.categoryId === "idle_time" || node.categoryId === "low_value") {
36795
36869
  return { text: "Idle", className: "bg-red-100 text-red-700" };
@@ -36817,6 +36891,79 @@ var FileManagerFilters = ({
36817
36891
  return null;
36818
36892
  }
36819
36893
  }, [supabase]);
36894
+ const fetchClipMetadataPage = useCallback(async (categoryId, page = 1) => {
36895
+ if (!workspaceId || !date || shift === void 0) {
36896
+ throw new Error("Missing required params for clip metadata fetch");
36897
+ }
36898
+ const response = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
36899
+ method: "POST",
36900
+ headers: {
36901
+ "Content-Type": "application/json"
36902
+ },
36903
+ body: JSON.stringify({
36904
+ action: "clip-metadata",
36905
+ workspaceId,
36906
+ date,
36907
+ shift: shift.toString(),
36908
+ category: categoryId,
36909
+ page,
36910
+ limit: 50,
36911
+ snapshotDateTime,
36912
+ snapshotClipId
36913
+ }),
36914
+ redirectReason: "session_expired"
36915
+ });
36916
+ if (!response.ok) {
36917
+ throw new Error(`API error: ${response.status}`);
36918
+ }
36919
+ return response.json();
36920
+ }, [workspaceId, date, shift, snapshotDateTime, snapshotClipId, supabase]);
36921
+ const seedIdleClassifications = useCallback(async (clips) => {
36922
+ if (!idleTimeVlmEnabled || clips.length === 0) {
36923
+ return;
36924
+ }
36925
+ const authToken = await getAuthToken3();
36926
+ if (!authToken) {
36927
+ return;
36928
+ }
36929
+ const seededClassifications = {};
36930
+ clips.forEach((clip) => {
36931
+ if (!clip.clipId) {
36932
+ return;
36933
+ }
36934
+ if (clip.classification_status) {
36935
+ seededClassifications[clip.clipId] = {
36936
+ status: clip.classification_status,
36937
+ label: clip.classification_label || void 0,
36938
+ confidence: clip.classification_confidence ?? void 0
36939
+ };
36940
+ }
36941
+ });
36942
+ if (Object.keys(seededClassifications).length > 0) {
36943
+ setLocalClipClassifications((prev) => ({
36944
+ ...prev,
36945
+ ...seededClassifications
36946
+ }));
36947
+ }
36948
+ const clipIdsToFetch = clips.map((clip) => clip.clipId || clip.id).filter(Boolean).filter((id3) => {
36949
+ if (!id3) return false;
36950
+ if (mergedClipClassifications[id3]?.status === "classified") return false;
36951
+ if (seededClassifications[id3]?.status === "classified") return false;
36952
+ return true;
36953
+ });
36954
+ if (clipIdsToFetch.length === 0) {
36955
+ return;
36956
+ }
36957
+ try {
36958
+ const classifications = await fetchClassifications(clipIdsToFetch, authToken);
36959
+ setLocalClipClassifications((prev) => ({
36960
+ ...prev,
36961
+ ...classifications
36962
+ }));
36963
+ } catch (error) {
36964
+ console.error("[FileManager] Error fetching idle classifications:", error);
36965
+ }
36966
+ }, [idleTimeVlmEnabled, getAuthToken3, mergedClipClassifications]);
36820
36967
  const fetchClipMetadata = useCallback(async (categoryId, page = 1) => {
36821
36968
  if (!workspaceId || !date || shift === void 0) {
36822
36969
  console.warn("[FileManager] Missing required params for clip metadata fetch");
@@ -36825,69 +36972,13 @@ var FileManagerFilters = ({
36825
36972
  const loadingKey = `${categoryId}-${page}`;
36826
36973
  setLoadingCategories((prev) => /* @__PURE__ */ new Set([...prev, loadingKey]));
36827
36974
  try {
36828
- const response = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
36829
- method: "POST",
36830
- headers: {
36831
- "Content-Type": "application/json"
36832
- },
36833
- body: JSON.stringify({
36834
- action: "clip-metadata",
36835
- workspaceId,
36836
- date,
36837
- shift: shift.toString(),
36838
- category: categoryId,
36839
- page,
36840
- limit: 50,
36841
- snapshotDateTime,
36842
- snapshotClipId
36843
- }),
36844
- redirectReason: "session_expired"
36845
- });
36846
- if (!response.ok) {
36847
- throw new Error(`API error: ${response.status}`);
36848
- }
36849
- const data = await response.json();
36975
+ const data = await fetchClipMetadataPage(categoryId, page);
36850
36976
  setClipMetadata((prev) => ({
36851
36977
  ...prev,
36852
36978
  [categoryId]: page === 1 ? data.clips : [...prev[categoryId] || [], ...data.clips]
36853
36979
  }));
36854
- const authToken = categoryId === "idle_time" && idleTimeVlmEnabled ? await getAuthToken3() : null;
36855
- if (categoryId === "idle_time" && idleTimeVlmEnabled && authToken) {
36856
- const seededClassifications = {};
36857
- (data.clips || []).forEach((clip) => {
36858
- if (!clip.clipId) {
36859
- return;
36860
- }
36861
- if (clip.classification_status) {
36862
- seededClassifications[clip.clipId] = {
36863
- status: clip.classification_status,
36864
- label: clip.classification_label || void 0,
36865
- confidence: clip.classification_confidence ?? void 0
36866
- };
36867
- }
36868
- });
36869
- if (Object.keys(seededClassifications).length > 0) {
36870
- setLocalClipClassifications((prev) => ({
36871
- ...prev,
36872
- ...seededClassifications
36873
- }));
36874
- }
36875
- const clipIds = (data.clips || []).map((clip) => clip.clipId || clip.id).filter(Boolean);
36876
- const newClipIds = clipIds.filter((id3) => {
36877
- if (mergedClipClassifications[id3]?.status === "classified") return false;
36878
- if (seededClassifications[id3]?.status === "classified") return false;
36879
- return true;
36880
- });
36881
- if (newClipIds.length > 0) {
36882
- fetchClassifications(newClipIds, authToken).then((classifications) => {
36883
- setLocalClipClassifications((prev) => ({
36884
- ...prev,
36885
- ...classifications
36886
- }));
36887
- }).catch((error) => {
36888
- console.error("[FileManager] Error fetching idle classifications:", error);
36889
- });
36890
- }
36980
+ if (categoryId === "idle_time" && idleTimeVlmEnabled) {
36981
+ await seedIdleClassifications(data.clips || []);
36891
36982
  }
36892
36983
  setCategoryPages((prev) => ({ ...prev, [categoryId]: page }));
36893
36984
  setCategoryHasMore((prev) => ({ ...prev, [categoryId]: data.hasMore }));
@@ -36901,7 +36992,64 @@ var FileManagerFilters = ({
36901
36992
  return newSet;
36902
36993
  });
36903
36994
  }
36904
- }, [workspaceId, date, shift, mergedClipClassifications, snapshotDateTime, snapshotClipId, supabase, getAuthToken3, idleTimeVlmEnabled]);
36995
+ }, [workspaceId, date, shift, fetchClipMetadataPage, idleTimeVlmEnabled, seedIdleClassifications]);
36996
+ const ensureAllIdleTimeClipMetadataLoaded = useCallback(async () => {
36997
+ if (!workspaceId || !date || shift === void 0) {
36998
+ return;
36999
+ }
37000
+ let accumulatedClips = [...clipMetadata["idle_time"] || []];
37001
+ let currentPage = categoryPages["idle_time"] || 0;
37002
+ let hasMore = categoryHasMore["idle_time"];
37003
+ if (currentPage === 0) {
37004
+ const firstPageData = await fetchClipMetadataPage("idle_time", 1);
37005
+ accumulatedClips = firstPageData.clips || [];
37006
+ currentPage = 1;
37007
+ hasMore = firstPageData.hasMore;
37008
+ } else if (hasMore === void 0) {
37009
+ hasMore = false;
37010
+ }
37011
+ while (hasMore) {
37012
+ const nextPage = currentPage + 1;
37013
+ const nextPageData = await fetchClipMetadataPage("idle_time", nextPage);
37014
+ accumulatedClips = [...accumulatedClips, ...nextPageData.clips || []];
37015
+ currentPage = nextPage;
37016
+ hasMore = nextPageData.hasMore;
37017
+ }
37018
+ const dedupedClips = accumulatedClips.filter((clip, index, arr) => {
37019
+ const clipKey = clip.clipId || clip.id;
37020
+ return arr.findIndex((item) => (item.clipId || item.id) === clipKey) === index;
37021
+ });
37022
+ setClipMetadata((prev) => ({
37023
+ ...prev,
37024
+ idle_time: dedupedClips
37025
+ }));
37026
+ setCategoryPages((prev) => ({ ...prev, idle_time: currentPage }));
37027
+ setCategoryHasMore((prev) => ({ ...prev, idle_time: false }));
37028
+ if (idleTimeVlmEnabled) {
37029
+ await seedIdleClassifications(dedupedClips);
37030
+ }
37031
+ }, [
37032
+ workspaceId,
37033
+ date,
37034
+ shift,
37035
+ clipMetadata,
37036
+ categoryPages,
37037
+ categoryHasMore,
37038
+ fetchClipMetadataPage,
37039
+ idleTimeVlmEnabled,
37040
+ seedIdleClassifications
37041
+ ]);
37042
+ const handleOpenIdleLabelFilterModal = useCallback(async () => {
37043
+ setShowIdleLabelFilterModal(true);
37044
+ setIsLoadingIdleReasonOptions(true);
37045
+ try {
37046
+ await ensureAllIdleTimeClipMetadataLoaded();
37047
+ } catch (error) {
37048
+ console.error("[FileManager] Error loading idle reason options:", error);
37049
+ } finally {
37050
+ setIsLoadingIdleReasonOptions(false);
37051
+ }
37052
+ }, [ensureAllIdleTimeClipMetadataLoaded]);
36905
37053
  const fetchPercentileClips = useCallback(async (type) => {
36906
37054
  if (!workspaceId || !date || shift === void 0) {
36907
37055
  console.warn("[FileManager] Missing required params for percentile clips fetch");
@@ -37572,7 +37720,7 @@ var FileManagerFilters = ({
37572
37720
  activeFilter === "idle_time" && idleTimeVlmEnabled && /* @__PURE__ */ jsx(
37573
37721
  "button",
37574
37722
  {
37575
- onClick: () => setShowIdleLabelFilterModal(true),
37723
+ onClick: handleOpenIdleLabelFilterModal,
37576
37724
  className: `p-2 rounded-xl transition-all duration-200 ${idleLabelFilter ? "bg-purple-100 text-purple-600 hover:bg-purple-200 shadow-sm" : "bg-slate-100 text-slate-600 hover:bg-slate-200"}`,
37577
37725
  title: "Filter by idle reason",
37578
37726
  children: /* @__PURE__ */ jsx(Tag, { className: "h-5 w-5" })
@@ -37660,7 +37808,10 @@ var FileManagerFilters = ({
37660
37808
  }
37661
37809
  )
37662
37810
  ] }),
37663
- /* @__PURE__ */ jsx("div", { className: "p-2 max-h-60 overflow-y-auto", children: ROOT_CAUSE_OPTIONS.map((reason) => {
37811
+ /* @__PURE__ */ jsx("div", { className: "p-2 max-h-60 overflow-y-auto", children: isLoadingIdleReasonOptions ? /* @__PURE__ */ jsxs("div", { className: "px-3 py-4 text-sm text-slate-500 flex items-center gap-2", children: [
37812
+ /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
37813
+ "Loading idle reasons..."
37814
+ ] }) : idleReasonOptions.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-3 py-4 text-sm text-slate-500", children: "No classified idle reasons found yet." }) : idleReasonOptions.map((reason) => {
37664
37815
  const config = getRootCauseConfig(reason);
37665
37816
  return /* @__PURE__ */ jsxs(
37666
37817
  "button",
@@ -49225,7 +49376,7 @@ var SideNavBar = memo$1(({
49225
49376
  if (hasClipsCostData) {
49226
49377
  items.push({
49227
49378
  key: "clips-analysis",
49228
- label: "Clips Analysis",
49379
+ label: "Billing",
49229
49380
  icon: CurrencyDollarIcon,
49230
49381
  onClick: () => {
49231
49382
  handleClipsCostClick();
@@ -61508,25 +61659,39 @@ var ProfileView = () => {
61508
61659
  var ProfileView_default = ProfileView;
61509
61660
  var REFRESH_INTERVAL_MS = 30 * 1e3;
61510
61661
  var ClipsCostView = () => {
61511
- const { data, isLoading, hasData, error, refetch } = useCompanyClipsCost();
61662
+ const { data, isLoading, error, refetch } = useCompanyClipsCost();
61512
61663
  const navigation = useNavigation();
61664
+ const refetchRef = useRef(refetch);
61665
+ useEffect(() => {
61666
+ refetchRef.current = refetch;
61667
+ }, [refetch]);
61513
61668
  useEffect(() => {
61514
61669
  const intervalId = setInterval(() => {
61515
- refetch();
61670
+ void refetchRef.current();
61516
61671
  }, REFRESH_INTERVAL_MS);
61517
61672
  return () => clearInterval(intervalId);
61518
- }, [refetch]);
61673
+ }, []);
61519
61674
  const mobileMenuContext = useMobileMenu();
61520
61675
  useHideMobileHeader(!!mobileMenuContext);
61521
61676
  const formatNumber = (num) => {
61522
61677
  return new Intl.NumberFormat("en-US").format(num);
61523
61678
  };
61679
+ const formatMonthLabel = (monthStart) => {
61680
+ if (!monthStart) {
61681
+ return "Current Month";
61682
+ }
61683
+ const parsed = /* @__PURE__ */ new Date(`${monthStart}T00:00:00`);
61684
+ if (Number.isNaN(parsed.getTime())) {
61685
+ return "Current Month";
61686
+ }
61687
+ return new Intl.DateTimeFormat("en-US", { month: "long", year: "numeric" }).format(parsed);
61688
+ };
61524
61689
  if (isLoading) {
61525
- return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "lg" }) });
61690
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-screen bg-gray-50", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "lg", message: "Loading usage data..." }) });
61526
61691
  }
61527
61692
  return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-gray-50 flex flex-col", children: [
61528
- /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-10 bg-white border-b flex-shrink-0", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3", children: [
61529
- /* @__PURE__ */ jsxs("div", { className: "sm:hidden flex items-center justify-between", children: [
61693
+ /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-10 bg-white border-b border-gray-200 shadow-sm flex-shrink-0", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-6 lg:px-8 py-3 sm:py-4 w-full", children: [
61694
+ /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
61530
61695
  /* @__PURE__ */ jsx("div", { className: "flex items-center", children: mobileMenuContext && /* @__PURE__ */ jsx(
61531
61696
  HamburgerButton,
61532
61697
  {
@@ -61534,46 +61699,57 @@ var ClipsCostView = () => {
61534
61699
  className: "flex-shrink-0 -ml-1"
61535
61700
  }
61536
61701
  ) }),
61537
- /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsx("h1", { className: "text-lg font-semibold text-gray-900", children: "Clips Analysis" }) }),
61538
- /* @__PURE__ */ jsx("div", { className: "w-8" }),
61539
- " "
61540
- ] }),
61541
- /* @__PURE__ */ jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between relative", children: [
61542
- /* @__PURE__ */ jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsx(
61702
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col items-center justify-center", children: [
61703
+ /* @__PURE__ */ jsx("h1", { className: "text-lg font-semibold text-gray-900", children: "Billing" }),
61704
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500", children: "Track your usage based features spend" })
61705
+ ] }),
61706
+ /* @__PURE__ */ jsx("div", { className: "w-9" })
61707
+ ] }) }),
61708
+ /* @__PURE__ */ jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
61709
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-4 min-w-[120px]", children: /* @__PURE__ */ jsx(
61543
61710
  BackButtonMinimal,
61544
61711
  {
61545
61712
  onClick: () => navigation.goToDashboard(),
61546
61713
  text: "Back",
61547
61714
  size: "default",
61548
- className: "bg-transparent border-transparent hover:bg-gray-100 pl-0"
61715
+ "aria-label": "Navigate back to dashboard"
61549
61716
  }
61550
61717
  ) }),
61551
- /* @__PURE__ */ jsx("h1", { className: "absolute left-1/2 -translate-x-1/2 text-xl md:text-2xl lg:text-3xl font-semibold text-gray-900", children: "Clips Analysis" }),
61552
- /* @__PURE__ */ jsx("div", { className: "w-10" }),
61553
- " "
61718
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col items-center", children: [
61719
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl lg:text-3xl font-semibold text-gray-900 text-center", children: "Billing" }),
61720
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mt-1 text-center", children: "Track your usage based features spend" })
61721
+ ] }),
61722
+ /* @__PURE__ */ jsx("div", { className: "min-w-[120px]" })
61554
61723
  ] }) })
61555
61724
  ] }) }),
61556
- /* @__PURE__ */ jsxs("main", { className: "flex-1 p-4 sm:p-6 lg:p-8 max-w-2xl mx-auto w-full", children: [
61557
- error && /* @__PURE__ */ jsx("div", { className: "mb-6 p-4 bg-red-50 border border-red-200 rounded-lg text-red-700", children: error }),
61558
- !hasData && !isLoading ? /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl shadow-sm border border-gray-200 p-8 text-center", children: [
61559
- /* @__PURE__ */ jsx(Film, { className: "h-12 w-12 text-gray-300 mx-auto mb-4" }),
61560
- /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-gray-900 mb-2", children: "No Data Available" }),
61561
- /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: "Clip analysis data will appear here once clips have been analyzed." })
61562
- ] }) : /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden", children: [
61563
- /* @__PURE__ */ jsx("div", { className: "p-6 border-b border-gray-100", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
61564
- /* @__PURE__ */ jsx("div", { className: "p-2 bg-blue-50 rounded-lg", children: /* @__PURE__ */ jsx(Film, { className: "h-5 w-5 text-blue-600" }) }),
61565
- /* @__PURE__ */ jsxs("div", { children: [
61566
- /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-gray-900", children: "Clips Analysis" }),
61567
- /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: "AI-powered clip classification usage" })
61568
- ] })
61569
- ] }) }),
61570
- /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs("div", { className: "text-center py-4", children: [
61571
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-500 mb-2", children: "Total Clips Analyzed" }),
61572
- /* @__PURE__ */ jsx("p", { className: "text-4xl font-bold text-gray-900", children: formatNumber(data?.totalClassifications || 0) }),
61573
- /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mt-2", children: "clips processed through AI classification" })
61574
- ] }) })
61725
+ /* @__PURE__ */ jsx("main", { className: "flex-1 p-4 sm:p-6 lg:p-8 max-w-7xl mx-auto w-full", children: error ? /* @__PURE__ */ jsxs("div", { className: "p-4 bg-red-50 border border-red-200 rounded-lg flex items-start gap-3 text-red-700 animate-in fade-in slide-in-from-top-2 max-w-2xl mx-auto", children: [
61726
+ /* @__PURE__ */ jsx(AlertCircle, { className: "h-5 w-5 flex-shrink-0 mt-0.5" }),
61727
+ /* @__PURE__ */ jsxs("div", { children: [
61728
+ /* @__PURE__ */ jsx("h3", { className: "font-medium", children: "Error loading usage data" }),
61729
+ /* @__PURE__ */ jsx("p", { className: "text-sm mt-1 text-red-600", children: error })
61575
61730
  ] })
61576
- ] })
61731
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "max-w-xl mt-8 animate-in fade-in slide-in-from-bottom-4 duration-500", children: [
61732
+ /* @__PURE__ */ jsx(Card2, { className: "overflow-hidden shadow-sm border-gray-200 bg-white", children: /* @__PURE__ */ jsx(CardContent2, { className: "p-8", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center text-center", children: [
61733
+ /* @__PURE__ */ jsx("div", { className: "p-3 bg-blue-50 rounded-full mb-4", children: /* @__PURE__ */ jsx(Film, { className: "h-8 w-8 text-blue-600" }) }),
61734
+ /* @__PURE__ */ jsx("h2", { className: "text-sm font-medium text-gray-500 uppercase tracking-wider mb-2", children: "Clips Analyzed" }),
61735
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mb-3", children: formatMonthLabel(data?.monthStart) }),
61736
+ /* @__PURE__ */ jsx("div", { className: "text-5xl font-bold text-gray-900 mb-2 tabular-nums tracking-tight", children: formatNumber(data?.monthlyClassifications || 0) })
61737
+ ] }) }) }),
61738
+ /* @__PURE__ */ jsx(Card2, { className: "mt-4 overflow-hidden shadow-sm border-gray-200 bg-white", children: /* @__PURE__ */ jsxs(CardContent2, { className: "p-6", children: [
61739
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900 mb-3 uppercase tracking-wider", children: "Previous Months" }),
61740
+ (data?.historicalMonthlyClassifications?.length || 0) === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: "No historical month usage yet." }) : /* @__PURE__ */ jsx("div", { className: "space-y-2", children: data?.historicalMonthlyClassifications.map((item) => /* @__PURE__ */ jsxs(
61741
+ "div",
61742
+ {
61743
+ className: "flex items-center justify-between rounded-md border border-gray-100 bg-gray-50 px-3 py-2",
61744
+ children: [
61745
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-700", children: formatMonthLabel(item.monthStart) }),
61746
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-gray-900 tabular-nums", children: formatNumber(item.classifications) })
61747
+ ]
61748
+ },
61749
+ item.monthStart
61750
+ )) })
61751
+ ] }) })
61752
+ ] }) })
61577
61753
  ] });
61578
61754
  };
61579
61755
  var ClipsCostView_default = ClipsCostView;
@@ -64855,6 +65031,7 @@ var WorkspaceDetailView = ({
64855
65031
  }, [monthlyData, range]);
64856
65032
  const formattedWorkspaceName = displayName || formatWorkspaceName3(workspace?.workspace_name || "", effectiveLineId);
64857
65033
  const shouldShowCycleTimeChart = !isUptimeMode && (showCycleTimeChart ?? formattedWorkspaceName.startsWith("FINAL ASSY"));
65034
+ const showIdleBreakdownChart = !shouldShowCycleTimeChart && idleTimeVlmEnabled;
64858
65035
  const idleClipDate = date || workspace?.date || calculatedOperationalDate || getOperationalDate(timezone);
64859
65036
  const idleClipShiftId = parsedShiftId ?? workspace?.shift_id;
64860
65037
  const shiftDurationMinutes = useMemo(
@@ -65458,107 +65635,123 @@ var WorkspaceDetailView = ({
65458
65635
  ] }) : /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(WorkspaceMetricCards, { workspace, legend: efficiencyLegend, className: "flex-1" }) })
65459
65636
  ] }),
65460
65637
  /* @__PURE__ */ jsxs("div", { className: "hidden lg:flex lg:flex-col lg:h-full lg:min-h-0 gap-3", children: [
65461
- /* @__PURE__ */ jsxs("div", { className: clsx("grid grid-cols-1 lg:grid-cols-10 gap-3 min-h-0", desktopTopSectionClass), children: [
65462
- !shouldShowCycleTimeChart && !isUptimeMode && /* @__PURE__ */ jsxs(
65463
- motion.div,
65464
- {
65465
- className: "bg-white rounded-lg shadow-sm p-4 lg:col-span-2 flex flex-col min-h-0",
65466
- variants: chartCardVariants,
65467
- initial: "initial",
65468
- animate: "animate",
65469
- children: [
65470
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-700 mb-4 text-center", children: "Today's Output" }),
65471
- /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-[220px] min-w-0", children: /* @__PURE__ */ jsx(
65472
- OutputProgressChart,
65473
- {
65474
- currentOutput: workspace.total_actions || 0,
65475
- targetOutput: workspace.target_output || 0
65476
- }
65477
- ) })
65478
- ]
65479
- }
65480
- ),
65481
- /* @__PURE__ */ jsxs(
65482
- motion.div,
65483
- {
65484
- className: `bg-white rounded-lg shadow-sm p-4 flex flex-col min-h-0 ${shouldShowCycleTimeChart || isUptimeMode ? "lg:col-span-10" : idleTimeVlmEnabled ? "lg:col-span-6" : "lg:col-span-8"}`,
65485
- variants: chartCardVariants,
65486
- initial: "initial",
65487
- animate: "animate",
65488
- children: [
65489
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 mb-4 flex-none", children: [
65490
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-700", children: isUptimeMode ? "Machine Utilization" : shouldShowCycleTimeChart ? "Cycle Time (last 60 minutes)" : "Hourly Output" }),
65491
- !isUptimeMode && /* @__PURE__ */ jsx(
65492
- "button",
65493
- {
65494
- onClick: () => setShowChartIdleTime(!showChartIdleTime),
65495
- className: `inline-flex items-center px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${showChartIdleTime ? "bg-blue-50 text-blue-700 border border-blue-200" : "bg-white text-gray-700 border border-gray-300 hover:bg-gray-50"}`,
65496
- children: showChartIdleTime ? /* @__PURE__ */ jsxs(Fragment, { children: [
65497
- /* @__PURE__ */ jsx(EyeOff, { className: "w-4 h-4 mr-1.5" }),
65498
- "Hide Idle Time"
65499
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
65500
- /* @__PURE__ */ jsx(Eye, { className: "w-4 h-4 mr-1.5" }),
65501
- "Show Idle Time"
65502
- ] })
65503
- }
65504
- )
65505
- ] }),
65506
- /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-[220px] min-w-0", children: isUptimeMode ? /* @__PURE__ */ jsx(
65507
- HourlyUptimeChart,
65508
- {
65509
- idleTimeHourly: workspace.idle_time_hourly,
65510
- shiftStart: workspace.shift_start,
65511
- shiftEnd: workspace.shift_end,
65512
- shiftDate: idleClipDate,
65513
- timezone,
65514
- elapsedMinutes: elapsedShiftMinutes
65515
- }
65516
- ) : shouldShowCycleTimeChart ? /* @__PURE__ */ jsx(
65517
- CycleTimeOverTimeChart,
65518
- {
65519
- data: workspace.hourly_action_counts || [],
65520
- idealCycleTime: workspace.ideal_cycle_time || 0,
65521
- shiftStart: workspace.shift_start || ""
65522
- }
65523
- ) : /* @__PURE__ */ jsx(
65524
- HourlyOutputChart2,
65525
- {
65526
- data: workspace.hourly_action_counts || [],
65527
- pphThreshold: workspace.pph_threshold || 0,
65528
- shiftStart: workspace.shift_start || "06:00",
65529
- shiftEnd: workspace.shift_end,
65530
- showIdleTime: showChartIdleTime,
65531
- idleTimeHourly: workspace.idle_time_hourly,
65532
- idleTimeClips,
65533
- idleTimeClipClassifications,
65534
- shiftDate: idleClipDate,
65535
- timezone
65536
- }
65537
- ) })
65538
- ]
65539
- }
65540
- ),
65541
- !shouldShowCycleTimeChart && idleTimeVlmEnabled && /* @__PURE__ */ jsxs(
65542
- motion.div,
65543
- {
65544
- className: "bg-white rounded-lg shadow-sm p-4 lg:col-span-2 flex flex-col min-h-0",
65545
- variants: chartCardVariants,
65546
- initial: "initial",
65547
- animate: "animate",
65548
- children: [
65549
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-700 mb-4 text-center", children: "Idle Time Breakdown" }),
65550
- /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-[220px] min-w-0", children: /* @__PURE__ */ jsx(
65551
- IdleTimeReasonChart,
65552
- {
65553
- data: idleTimeData.chartData,
65554
- isLoading: idleTimeData.isLoading,
65555
- error: idleTimeData.error
65556
- }
65557
- ) })
65558
- ]
65559
- }
65560
- )
65561
- ] }),
65638
+ /* @__PURE__ */ jsxs(
65639
+ "div",
65640
+ {
65641
+ className: clsx(
65642
+ "grid grid-cols-1 gap-3 min-h-0",
65643
+ isUptimeMode && showIdleBreakdownChart ? "lg:grid-cols-3" : "lg:grid-cols-10",
65644
+ desktopTopSectionClass
65645
+ ),
65646
+ children: [
65647
+ !shouldShowCycleTimeChart && !isUptimeMode && /* @__PURE__ */ jsxs(
65648
+ motion.div,
65649
+ {
65650
+ className: "bg-white rounded-lg shadow-sm p-4 lg:col-span-2 flex flex-col min-h-0",
65651
+ variants: chartCardVariants,
65652
+ initial: "initial",
65653
+ animate: "animate",
65654
+ children: [
65655
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-700 mb-4 text-center", children: "Today's Output" }),
65656
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-[220px] min-w-0", children: /* @__PURE__ */ jsx(
65657
+ OutputProgressChart,
65658
+ {
65659
+ currentOutput: workspace.total_actions || 0,
65660
+ targetOutput: workspace.target_output || 0
65661
+ }
65662
+ ) })
65663
+ ]
65664
+ }
65665
+ ),
65666
+ /* @__PURE__ */ jsxs(
65667
+ motion.div,
65668
+ {
65669
+ className: clsx(
65670
+ "bg-white rounded-lg shadow-sm p-4 flex flex-col min-h-0",
65671
+ isUptimeMode && showIdleBreakdownChart ? "lg:col-span-2" : shouldShowCycleTimeChart || isUptimeMode ? "lg:col-span-10" : idleTimeVlmEnabled ? "lg:col-span-6" : "lg:col-span-8"
65672
+ ),
65673
+ variants: chartCardVariants,
65674
+ initial: "initial",
65675
+ animate: "animate",
65676
+ children: [
65677
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 mb-4 flex-none", children: [
65678
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-700", children: isUptimeMode ? "Machine Utilization" : shouldShowCycleTimeChart ? "Cycle Time (last 60 minutes)" : "Hourly Output" }),
65679
+ !isUptimeMode && /* @__PURE__ */ jsx(
65680
+ "button",
65681
+ {
65682
+ onClick: () => setShowChartIdleTime(!showChartIdleTime),
65683
+ className: `inline-flex items-center px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${showChartIdleTime ? "bg-blue-50 text-blue-700 border border-blue-200" : "bg-white text-gray-700 border border-gray-300 hover:bg-gray-50"}`,
65684
+ children: showChartIdleTime ? /* @__PURE__ */ jsxs(Fragment, { children: [
65685
+ /* @__PURE__ */ jsx(EyeOff, { className: "w-4 h-4 mr-1.5" }),
65686
+ "Hide Idle Time"
65687
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
65688
+ /* @__PURE__ */ jsx(Eye, { className: "w-4 h-4 mr-1.5" }),
65689
+ "Show Idle Time"
65690
+ ] })
65691
+ }
65692
+ )
65693
+ ] }),
65694
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-[220px] min-w-0", children: isUptimeMode ? /* @__PURE__ */ jsx(
65695
+ HourlyUptimeChart,
65696
+ {
65697
+ idleTimeHourly: workspace.idle_time_hourly,
65698
+ shiftStart: workspace.shift_start,
65699
+ shiftEnd: workspace.shift_end,
65700
+ shiftDate: idleClipDate,
65701
+ timezone,
65702
+ elapsedMinutes: elapsedShiftMinutes
65703
+ }
65704
+ ) : shouldShowCycleTimeChart ? /* @__PURE__ */ jsx(
65705
+ CycleTimeOverTimeChart,
65706
+ {
65707
+ data: workspace.hourly_action_counts || [],
65708
+ idealCycleTime: workspace.ideal_cycle_time || 0,
65709
+ shiftStart: workspace.shift_start || ""
65710
+ }
65711
+ ) : /* @__PURE__ */ jsx(
65712
+ HourlyOutputChart2,
65713
+ {
65714
+ data: workspace.hourly_action_counts || [],
65715
+ pphThreshold: workspace.pph_threshold || 0,
65716
+ shiftStart: workspace.shift_start || "06:00",
65717
+ shiftEnd: workspace.shift_end,
65718
+ showIdleTime: showChartIdleTime,
65719
+ idleTimeHourly: workspace.idle_time_hourly,
65720
+ idleTimeClips,
65721
+ idleTimeClipClassifications,
65722
+ shiftDate: idleClipDate,
65723
+ timezone
65724
+ }
65725
+ ) })
65726
+ ]
65727
+ }
65728
+ ),
65729
+ !shouldShowCycleTimeChart && idleTimeVlmEnabled && /* @__PURE__ */ jsxs(
65730
+ motion.div,
65731
+ {
65732
+ className: clsx(
65733
+ "bg-white rounded-lg shadow-sm p-4 flex flex-col min-h-0",
65734
+ isUptimeMode ? "lg:col-span-1" : "lg:col-span-2"
65735
+ ),
65736
+ variants: chartCardVariants,
65737
+ initial: "initial",
65738
+ animate: "animate",
65739
+ children: [
65740
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-700 mb-4 text-center", children: "Idle Time Breakdown" }),
65741
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-[220px] min-w-0", children: /* @__PURE__ */ jsx(
65742
+ IdleTimeReasonChart,
65743
+ {
65744
+ data: idleTimeData.chartData,
65745
+ isLoading: idleTimeData.isLoading,
65746
+ error: idleTimeData.error
65747
+ }
65748
+ ) })
65749
+ ]
65750
+ }
65751
+ )
65752
+ ]
65753
+ }
65754
+ ),
65562
65755
  isUptimeMode ? /* @__PURE__ */ jsx("div", { className: clsx("flex min-h-0", desktopBottomSectionClass), children: /* @__PURE__ */ jsx(UptimeMetricCards, { workspace, uptimePieData, className: "flex-1" }) }) : shouldShowCycleTimeChart ? /* @__PURE__ */ jsxs("div", { className: clsx("grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 min-h-0", desktopBottomSectionClass), children: [
65563
65756
  /* @__PURE__ */ jsxs(Card2, { children: [
65564
65757
  /* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Efficiency" }) }),