@optifye/dashboard-core 6.11.36 → 6.11.37

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.d.mts CHANGED
@@ -9530,7 +9530,7 @@ interface UserManagementTableProps {
9530
9530
  availableLines?: Line[];
9531
9531
  availableFactories?: Factory[];
9532
9532
  currentUserId?: string;
9533
- /** Weekly usage in milliseconds keyed by user_id (last 7 days total) */
9533
+ /** Average daily active usage in milliseconds keyed by user_id */
9534
9534
  avgDailyUsage?: Record<string, number>;
9535
9535
  /** Whether usage data is loading */
9536
9536
  isUsageLoading?: boolean;
package/dist/index.d.ts CHANGED
@@ -9530,7 +9530,7 @@ interface UserManagementTableProps {
9530
9530
  availableLines?: Line[];
9531
9531
  availableFactories?: Factory[];
9532
9532
  currentUserId?: string;
9533
- /** Weekly usage in milliseconds keyed by user_id (last 7 days total) */
9533
+ /** Average daily active usage in milliseconds keyed by user_id */
9534
9534
  avgDailyUsage?: Record<string, number>;
9535
9535
  /** Whether usage data is loading */
9536
9536
  isUsageLoading?: boolean;
package/dist/index.js CHANGED
@@ -58812,6 +58812,50 @@ var UserUsageStats = ({
58812
58812
  ] })
58813
58813
  ] });
58814
58814
  };
58815
+
58816
+ // src/lib/utils/teamUsage.ts
58817
+ var ISO_DATE_KEY_REGEX = /^\d{4}-\d{2}-\d{2}$/;
58818
+ function formatLocalDateKey(date) {
58819
+ const year = date.getFullYear();
58820
+ const month = String(date.getMonth() + 1).padStart(2, "0");
58821
+ const day = String(date.getDate()).padStart(2, "0");
58822
+ return `${year}-${month}-${day}`;
58823
+ }
58824
+ function parseUsageDate(dateLike) {
58825
+ if (ISO_DATE_KEY_REGEX.test(dateLike)) {
58826
+ const [year, month, day] = dateLike.split("-").map(Number);
58827
+ return new Date(year, month - 1, day);
58828
+ }
58829
+ return new Date(dateLike);
58830
+ }
58831
+ function normalizeUsageDateKey(dateLike) {
58832
+ if (!dateLike) return void 0;
58833
+ if (ISO_DATE_KEY_REGEX.test(dateLike)) return dateLike;
58834
+ const parsed = parseUsageDate(dateLike);
58835
+ if (Number.isNaN(parsed.getTime())) {
58836
+ return dateLike.split("T")[0] || dateLike;
58837
+ }
58838
+ return formatLocalDateKey(parsed);
58839
+ }
58840
+ function getCurrentWeekToDateUsageRange(today = /* @__PURE__ */ new Date()) {
58841
+ const normalizedToday = new Date(today);
58842
+ normalizedToday.setHours(0, 0, 0, 0);
58843
+ const dayOfWeek = normalizedToday.getDay();
58844
+ const daysSinceMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
58845
+ const monday = new Date(normalizedToday);
58846
+ monday.setDate(normalizedToday.getDate() - daysSinceMonday);
58847
+ return {
58848
+ startDate: formatLocalDateKey(monday),
58849
+ endDate: formatLocalDateKey(normalizedToday),
58850
+ daysElapsed: daysSinceMonday + 1
58851
+ };
58852
+ }
58853
+ function calculateAverageDailyDuration(durationMs, dayCount) {
58854
+ if (!Number.isFinite(durationMs) || dayCount <= 0) {
58855
+ return 0;
58856
+ }
58857
+ return Math.round(durationMs / dayCount);
58858
+ }
58815
58859
  var UserUsageDetailModal = ({
58816
58860
  userId,
58817
58861
  userName,
@@ -58821,7 +58865,7 @@ var UserUsageDetailModal = ({
58821
58865
  endDate
58822
58866
  }) => {
58823
58867
  const [currentWeekStart, setCurrentWeekStart] = React143.useState(() => {
58824
- if (startDate) return new Date(startDate);
58868
+ if (startDate) return parseUsageDate(startDate);
58825
58869
  const { start } = getCurrentWeekRange();
58826
58870
  return start;
58827
58871
  });
@@ -58831,8 +58875,8 @@ var UserUsageDetailModal = ({
58831
58875
  return end;
58832
58876
  }, [currentWeekStart]);
58833
58877
  const { data, isLoading, error } = useUserUsage(userId, {
58834
- startDate: currentWeekStart.toISOString().slice(0, 10),
58835
- endDate: currentWeekEnd.toISOString().slice(0, 10)
58878
+ startDate: formatLocalDateKey(currentWeekStart),
58879
+ endDate: formatLocalDateKey(currentWeekEnd)
58836
58880
  });
58837
58881
  const handlePrevWeek = () => {
58838
58882
  setCurrentWeekStart((prev) => {
@@ -58925,8 +58969,8 @@ function UsageContent({
58925
58969
  } else {
58926
58970
  daysToCount = 7;
58927
58971
  }
58928
- const weekTotalMs = weekData.reduce((sum, d) => sum + d.total_duration_ms, 0);
58929
- const weekAvgMs = daysToCount > 0 ? weekTotalMs / daysToCount : 0;
58972
+ const weekActiveMs = weekData.reduce((sum, d) => sum + d.active_duration_ms, 0);
58973
+ const weekAvgMs = calculateAverageDailyDuration(weekActiveMs, daysToCount);
58930
58974
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
58931
58975
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center mb-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 bg-gray-50 rounded-lg p-1 border border-gray-100", children: [
58932
58976
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -58938,7 +58982,7 @@ function UsageContent({
58938
58982
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "w-4 h-4" })
58939
58983
  }
58940
58984
  ),
58941
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-gray-700 min-w-[140px] text-center", children: formatDateRange(currentWeekStart.toISOString().slice(0, 10), currentWeekEnd.toISOString().slice(0, 10)) }),
58985
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-gray-700 min-w-[140px] text-center", children: formatDateRange(formatLocalDateKey(currentWeekStart), formatLocalDateKey(currentWeekEnd)) }),
58942
58986
  /* @__PURE__ */ jsxRuntime.jsx(
58943
58987
  "button",
58944
58988
  {
@@ -58970,7 +59014,7 @@ function DailyBarChart({
58970
59014
  const weekData = React143.useMemo(() => buildWeekData(dailyData, getDateStringsInRange(weekStart, weekEnd)), [dailyData, weekStart, weekEnd]);
58971
59015
  const chartData = React143.useMemo(() => {
58972
59016
  return weekData.map((day, index) => {
58973
- const date = new Date(day.date);
59017
+ const date = parseUsageDate(day.date);
58974
59018
  return {
58975
59019
  ...day,
58976
59020
  index,
@@ -58980,7 +59024,7 @@ function DailyBarChart({
58980
59024
  // green-500
58981
59025
  passiveColor: "#fbbf24",
58982
59026
  // amber-400
58983
- isToday: day.date === (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
59027
+ isToday: day.date === formatLocalDateKey(/* @__PURE__ */ new Date())
58984
59028
  };
58985
59029
  });
58986
59030
  }, [weekData]);
@@ -59000,7 +59044,7 @@ function DailyBarChart({
59000
59044
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
59001
59045
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 rounded-full bg-gray-300" }),
59002
59046
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-medium text-gray-600", children: [
59003
- "Average Daily usage: ",
59047
+ "Average Daily active usage: ",
59004
59048
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-900 font-semibold", children: avgDailyMs > 0 ? formatDuration2(avgDailyMs) : "0m" })
59005
59049
  ] })
59006
59050
  ] }),
@@ -59165,17 +59209,14 @@ function getCurrentWeekRange() {
59165
59209
  function getDateStringsInRange(start, end) {
59166
59210
  const result = [];
59167
59211
  for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
59168
- const year = d.getFullYear();
59169
- const month = String(d.getMonth() + 1).padStart(2, "0");
59170
- const day = String(d.getDate()).padStart(2, "0");
59171
- result.push(`${year}-${month}-${day}`);
59212
+ result.push(formatLocalDateKey(d));
59172
59213
  }
59173
59214
  return result;
59174
59215
  }
59175
59216
  function buildWeekData(dailyData, weekDates) {
59176
59217
  const dataMap = new Map(
59177
59218
  (dailyData || []).map((d) => {
59178
- const key = normalizeDateKey(d.date);
59219
+ const key = normalizeUsageDateKey(d.date);
59179
59220
  return [key, { ...d, date: key }];
59180
59221
  })
59181
59222
  );
@@ -59190,22 +59231,10 @@ function buildWeekData(dailyData, weekDates) {
59190
59231
  };
59191
59232
  });
59192
59233
  }
59193
- function normalizeDateKey(dateLike) {
59194
- if (!dateLike) return void 0;
59195
- try {
59196
- const date = new Date(dateLike);
59197
- const year = date.getFullYear();
59198
- const month = String(date.getMonth() + 1).padStart(2, "0");
59199
- const day = String(date.getDate()).padStart(2, "0");
59200
- return `${year}-${month}-${day}`;
59201
- } catch {
59202
- return dateLike.split("T")[0] || dateLike;
59203
- }
59204
- }
59205
59234
  function formatDateRange(startDate, endDate) {
59206
59235
  try {
59207
- const start = new Date(startDate);
59208
- const end = new Date(endDate);
59236
+ const start = parseUsageDate(startDate);
59237
+ const end = parseUsageDate(endDate);
59209
59238
  const opts = { month: "short", day: "numeric" };
59210
59239
  const yearOpts = { year: "numeric" };
59211
59240
  return `${start.toLocaleDateString("en-US", opts)} - ${end.toLocaleDateString("en-US", opts)}, ${end.toLocaleDateString("en-US", yearOpts)}`;
@@ -59216,7 +59245,7 @@ function formatDateRange(startDate, endDate) {
59216
59245
  function formatDate(dateStr) {
59217
59246
  if (!dateStr) return "";
59218
59247
  try {
59219
- const date = new Date(dateStr);
59248
+ const date = parseUsageDate(dateStr);
59220
59249
  return date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
59221
59250
  } catch {
59222
59251
  return dateStr;
@@ -59494,7 +59523,7 @@ var UserManagementTable = ({
59494
59523
  }
59495
59524
  ),
59496
59525
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Assignments" }),
59497
- showUsageStats && /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Average Daily usage" }),
59526
+ showUsageStats && /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Average Daily Active Usage" }),
59498
59527
  /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Actions" })
59499
59528
  ] }) }),
59500
59529
  /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: filteredAndSortedUsers.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: showUsageStats ? 5 : 4, className: "px-6 py-12", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center text-gray-400 gap-2", children: [
@@ -73791,39 +73820,8 @@ var TeamManagementView = ({
73791
73820
  const [users, setUsers] = React143.useState([]);
73792
73821
  const [availableLines, setAvailableLines] = React143.useState([]);
73793
73822
  const [availableFactories, setAvailableFactories] = React143.useState([]);
73794
- const [stats, setStats] = React143.useState({
73795
- totalUsers: 0,
73796
- owners: 0,
73797
- it: 0,
73798
- plantHeads: 0,
73799
- industrialEngineers: 0,
73800
- supervisors: 0,
73801
- optifye: 0
73802
- });
73823
+ const [usageSummaryByUser, setUsageSummaryByUser] = React143.useState({});
73803
73824
  const [isAddUserDialogOpen, setIsAddUserDialogOpen] = React143.useState(false);
73804
- const normalizeIds = React143.useCallback((value) => {
73805
- if (Array.isArray(value)) {
73806
- return value.filter((id3) => typeof id3 === "string" && id3.length > 0);
73807
- }
73808
- if (typeof value === "string" && value.length > 0) {
73809
- return [value];
73810
- }
73811
- return [];
73812
- }, []);
73813
- const factoryScopedRoleFactoryIds = React143.useMemo(() => {
73814
- if (!isFactoryScopedRole(user?.role_level)) return [];
73815
- const scopedFactoryIds = normalizeIds(user?.access_scope?.factory_ids);
73816
- if (scopedFactoryIds.length > 0) {
73817
- return Array.from(new Set(scopedFactoryIds));
73818
- }
73819
- const propertyFactoryIds = normalizeIds(
73820
- user?.properties?.factory_ids ?? user?.properties?.factory_id
73821
- );
73822
- if (propertyFactoryIds.length > 0) {
73823
- return Array.from(new Set(propertyFactoryIds));
73824
- }
73825
- return entityConfig?.factoryId ? [entityConfig.factoryId] : [];
73826
- }, [user, entityConfig?.factoryId, normalizeIds]);
73827
73825
  const notifyScopeRefresh = React143.useCallback(() => {
73828
73826
  if (typeof window !== "undefined") {
73829
73827
  window.dispatchEvent(new Event("rbac:refresh-scope"));
@@ -73832,37 +73830,17 @@ var TeamManagementView = ({
73832
73830
  const canAddUsers = canRoleManageUsers(user?.role_level);
73833
73831
  const canViewUsageStats = canRoleViewUsageStats(user?.role_level);
73834
73832
  const pageCompanyId = entityConfig?.companyId || user?.properties?.company_id;
73835
- const companyIdForUsage = pageCompanyId;
73836
- const usageDateRange = React143.useMemo(() => {
73837
- const today = /* @__PURE__ */ new Date();
73838
- const dayOfWeek = today.getDay();
73839
- const daysSinceMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
73840
- const monday = new Date(today);
73841
- monday.setDate(today.getDate() - daysSinceMonday);
73842
- return {
73843
- startDate: monday.toISOString().slice(0, 10),
73844
- endDate: today.toISOString().slice(0, 10),
73845
- daysElapsed: daysSinceMonday + 1
73846
- // Include today
73847
- };
73848
- }, []);
73849
- const {
73850
- data: usageData,
73851
- isLoading: isUsageLoading
73852
- } = useCompanyUsersUsage(canViewUsageStats ? companyIdForUsage : void 0, {
73853
- startDate: usageDateRange.startDate,
73854
- endDate: usageDateRange.endDate
73855
- });
73833
+ const usageDateRange = React143.useMemo(() => getCurrentWeekToDateUsageRange(), []);
73856
73834
  const avgDailyUsageMap = React143.useMemo(() => {
73857
- if (!usageData?.users) {
73835
+ if (!canViewUsageStats) {
73858
73836
  return {};
73859
73837
  }
73860
73838
  const daysElapsed = usageDateRange.daysElapsed;
73861
- return usageData.users.reduce((acc, user2) => {
73862
- acc[user2.user_id] = Math.round(user2.total_duration_ms / daysElapsed);
73839
+ return Object.entries(usageSummaryByUser).reduce((acc, [userId, usage]) => {
73840
+ acc[userId] = calculateAverageDailyDuration(usage.active_duration_ms, daysElapsed);
73863
73841
  return acc;
73864
73842
  }, {});
73865
- }, [usageData, usageDateRange.daysElapsed]);
73843
+ }, [canViewUsageStats, usageSummaryByUser, usageDateRange.daysElapsed]);
73866
73844
  const pageTitle = "Team Management";
73867
73845
  const pageDescription = canViewUsageStats ? "Manage team members and view their daily usage" : "Manage supervisors in your factory";
73868
73846
  const hasAccess = user ? user.role_level === void 0 || canRoleAccessTeamManagement(user.role_level) : false;
@@ -73886,7 +73864,6 @@ var TeamManagementView = ({
73886
73864
  setIsLoading(true);
73887
73865
  setError(void 0);
73888
73866
  try {
73889
- const userManagementService = createUserManagementService(supabase);
73890
73867
  const { data: { session } } = await supabase.auth.getSession();
73891
73868
  if (!session?.access_token) {
73892
73869
  throw new Error("No authentication token available");
@@ -73896,116 +73873,31 @@ var TeamManagementView = ({
73896
73873
  if (!backendUrl) {
73897
73874
  throw new Error("Backend URL is not configured. Please set NEXT_PUBLIC_BACKEND_URL in your environment.");
73898
73875
  }
73899
- if ((user?.role_level === "optifye" || user?.role_level === "owner" || user?.role_level === "it") && companyId) {
73900
- const { data: factories } = await supabase.from("factories").select("id, factory_name, company_id").eq("company_id", companyId).order("factory_name");
73901
- const linesResponse = await fetch(`${backendUrl}/api/lines?company_id=${companyId}`, {
73902
- headers: {
73903
- "Authorization": `Bearer ${token}`,
73904
- "Content-Type": "application/json"
73905
- }
73906
- });
73907
- if (!linesResponse.ok) {
73908
- throw new Error(`Failed to fetch lines: ${linesResponse.statusText}`);
73909
- }
73910
- const linesData = await linesResponse.json();
73911
- const lines = linesData.lines || [];
73912
- setAvailableFactories(factories || []);
73913
- setAvailableLines(lines);
73914
- console.log("[TeamManagementView] Company-scoped team view - Company:", companyId, "Loaded factories:", factories?.length, "lines:", lines?.length);
73915
- } else if (isFactoryScopedRole(user?.role_level)) {
73916
- if (factoryScopedRoleFactoryIds.length > 0) {
73917
- if (companyId) {
73918
- const linesResponse = await fetch(`${backendUrl}/api/lines?company_id=${companyId}`, {
73919
- headers: {
73920
- "Authorization": `Bearer ${token}`,
73921
- "Content-Type": "application/json"
73922
- }
73923
- });
73924
- if (!linesResponse.ok) {
73925
- throw new Error(`Failed to fetch lines: ${linesResponse.statusText}`);
73926
- }
73927
- const linesData = await linesResponse.json();
73928
- const allLines = linesData.lines || [];
73929
- const lines = allLines.filter((line) => factoryScopedRoleFactoryIds.includes(line.factory_id));
73930
- setAvailableLines(lines);
73931
- console.log("[TeamManagementView] Factory-scoped team view - Factories:", factoryScopedRoleFactoryIds, "Loaded lines:", lines?.length);
73932
- }
73933
- } else if (entityConfig?.factoryId) {
73934
- const linesResponse = await fetch(`${backendUrl}/api/lines?factory_id=${entityConfig.factoryId}`, {
73935
- headers: {
73936
- "Authorization": `Bearer ${token}`,
73937
- "Content-Type": "application/json"
73938
- }
73939
- });
73940
- if (!linesResponse.ok) {
73941
- throw new Error(`Failed to fetch lines: ${linesResponse.statusText}`);
73942
- }
73943
- const linesData = await linesResponse.json();
73944
- const lines = linesData.lines || [];
73945
- setAvailableLines(lines);
73946
- console.log("[TeamManagementView] Plant Head - Using entityConfig factory:", entityConfig.factoryId, "Loaded lines:", lines?.length);
73947
- } else {
73948
- setAvailableLines([]);
73949
- console.warn("[TeamManagementView] Plant Head has no factory assignments");
73950
- }
73951
- setAvailableFactories([]);
73952
- } else if (companyId) {
73953
- const linesResponse = await fetch(`${backendUrl}/api/lines?company_id=${companyId}`, {
73876
+ const params = new URLSearchParams({
73877
+ start_date: usageDateRange.startDate,
73878
+ end_date: usageDateRange.endDate
73879
+ });
73880
+ const bootstrapResponse = await fetch(
73881
+ `${backendUrl}/api/users/company/${companyId}/bootstrap?${params.toString()}`,
73882
+ {
73954
73883
  headers: {
73955
73884
  "Authorization": `Bearer ${token}`,
73956
73885
  "Content-Type": "application/json"
73957
73886
  }
73958
- });
73959
- if (!linesResponse.ok) {
73960
- throw new Error(`Failed to fetch lines: ${linesResponse.statusText}`);
73961
73887
  }
73962
- const linesData = await linesResponse.json();
73963
- const lines = linesData.lines || [];
73964
- setAvailableLines(lines);
73965
- setAvailableFactories([]);
73966
- console.log("[TeamManagementView] Fallback - Company:", companyId, "Loaded lines:", lines?.length);
73967
- }
73968
- const usersPromise = isFactoryScopedRole(user?.role_level) ? (async () => {
73969
- if (factoryScopedRoleFactoryIds.length === 0) {
73970
- return [];
73971
- }
73972
- const results = await Promise.allSettled(
73973
- factoryScopedRoleFactoryIds.map((factoryId) => userManagementService.getFactoryUsers(factoryId))
73974
- );
73975
- const successful = results.filter(
73976
- (result) => result.status === "fulfilled"
73977
- ).flatMap((result) => result.value || []);
73978
- if (successful.length > 0) {
73979
- const byUserId = /* @__PURE__ */ new Map();
73980
- successful.forEach((u) => {
73981
- if (u?.user_id) {
73982
- byUserId.set(u.user_id, u);
73983
- }
73984
- });
73985
- return Array.from(byUserId.values());
73986
- }
73987
- const firstRejected = results.find(
73988
- (result) => result.status === "rejected"
73989
- );
73990
- if (firstRejected) {
73991
- throw firstRejected.reason;
73992
- }
73993
- return [];
73994
- })() : userManagementService.getCompanyUsers(companyId);
73995
- const [usersData, userStats] = await Promise.all([
73996
- usersPromise,
73997
- userManagementService.getUserStats(companyId)
73998
- ]);
73999
- setUsers(usersData);
74000
- setStats({
74001
- totalUsers: userStats.total,
74002
- owners: userStats.owners,
74003
- it: userStats.it,
74004
- plantHeads: userStats.plant_heads,
74005
- industrialEngineers: userStats.industrial_engineers,
74006
- supervisors: userStats.supervisors,
74007
- optifye: 0
74008
- });
73888
+ );
73889
+ if (!bootstrapResponse.ok) {
73890
+ const errorData = await bootstrapResponse.json().catch(() => ({}));
73891
+ throw new Error(errorData.detail || `Failed to fetch team bootstrap: ${bootstrapResponse.statusText}`);
73892
+ }
73893
+ const bootstrapData = await bootstrapResponse.json();
73894
+ setAvailableFactories((bootstrapData.factories || []).map((factory) => ({
73895
+ id: factory.id,
73896
+ factory_name: factory.factory_name
73897
+ })));
73898
+ setAvailableLines(bootstrapData.lines || []);
73899
+ setUsers(bootstrapData.users || []);
73900
+ setUsageSummaryByUser(bootstrapData.usage_summary_by_user || {});
74009
73901
  } catch (err) {
74010
73902
  console.error("Error loading team management data:", err);
74011
73903
  setError(err instanceof Error ? err.message : "Failed to load data");
@@ -74013,7 +73905,7 @@ var TeamManagementView = ({
74013
73905
  } finally {
74014
73906
  setIsLoading(false);
74015
73907
  }
74016
- }, [supabase, user, pageCompanyId, entityConfig?.factoryId, factoryScopedRoleFactoryIds]);
73908
+ }, [supabase, user, pageCompanyId, usageDateRange.endDate, usageDateRange.startDate]);
74017
73909
  React143.useEffect(() => {
74018
73910
  const companyId = pageCompanyId;
74019
73911
  const canLoad = hasAccess && user && !!companyId;
@@ -74194,7 +74086,7 @@ var TeamManagementView = ({
74194
74086
  availableLines,
74195
74087
  availableFactories,
74196
74088
  avgDailyUsage: avgDailyUsageMap,
74197
- isUsageLoading,
74089
+ isUsageLoading: false,
74198
74090
  showUsageStats: canViewUsageStats
74199
74091
  }
74200
74092
  ) }),
package/dist/index.mjs CHANGED
@@ -58783,6 +58783,50 @@ var UserUsageStats = ({
58783
58783
  ] })
58784
58784
  ] });
58785
58785
  };
58786
+
58787
+ // src/lib/utils/teamUsage.ts
58788
+ var ISO_DATE_KEY_REGEX = /^\d{4}-\d{2}-\d{2}$/;
58789
+ function formatLocalDateKey(date) {
58790
+ const year = date.getFullYear();
58791
+ const month = String(date.getMonth() + 1).padStart(2, "0");
58792
+ const day = String(date.getDate()).padStart(2, "0");
58793
+ return `${year}-${month}-${day}`;
58794
+ }
58795
+ function parseUsageDate(dateLike) {
58796
+ if (ISO_DATE_KEY_REGEX.test(dateLike)) {
58797
+ const [year, month, day] = dateLike.split("-").map(Number);
58798
+ return new Date(year, month - 1, day);
58799
+ }
58800
+ return new Date(dateLike);
58801
+ }
58802
+ function normalizeUsageDateKey(dateLike) {
58803
+ if (!dateLike) return void 0;
58804
+ if (ISO_DATE_KEY_REGEX.test(dateLike)) return dateLike;
58805
+ const parsed = parseUsageDate(dateLike);
58806
+ if (Number.isNaN(parsed.getTime())) {
58807
+ return dateLike.split("T")[0] || dateLike;
58808
+ }
58809
+ return formatLocalDateKey(parsed);
58810
+ }
58811
+ function getCurrentWeekToDateUsageRange(today = /* @__PURE__ */ new Date()) {
58812
+ const normalizedToday = new Date(today);
58813
+ normalizedToday.setHours(0, 0, 0, 0);
58814
+ const dayOfWeek = normalizedToday.getDay();
58815
+ const daysSinceMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
58816
+ const monday = new Date(normalizedToday);
58817
+ monday.setDate(normalizedToday.getDate() - daysSinceMonday);
58818
+ return {
58819
+ startDate: formatLocalDateKey(monday),
58820
+ endDate: formatLocalDateKey(normalizedToday),
58821
+ daysElapsed: daysSinceMonday + 1
58822
+ };
58823
+ }
58824
+ function calculateAverageDailyDuration(durationMs, dayCount) {
58825
+ if (!Number.isFinite(durationMs) || dayCount <= 0) {
58826
+ return 0;
58827
+ }
58828
+ return Math.round(durationMs / dayCount);
58829
+ }
58786
58830
  var UserUsageDetailModal = ({
58787
58831
  userId,
58788
58832
  userName,
@@ -58792,7 +58836,7 @@ var UserUsageDetailModal = ({
58792
58836
  endDate
58793
58837
  }) => {
58794
58838
  const [currentWeekStart, setCurrentWeekStart] = useState(() => {
58795
- if (startDate) return new Date(startDate);
58839
+ if (startDate) return parseUsageDate(startDate);
58796
58840
  const { start } = getCurrentWeekRange();
58797
58841
  return start;
58798
58842
  });
@@ -58802,8 +58846,8 @@ var UserUsageDetailModal = ({
58802
58846
  return end;
58803
58847
  }, [currentWeekStart]);
58804
58848
  const { data, isLoading, error } = useUserUsage(userId, {
58805
- startDate: currentWeekStart.toISOString().slice(0, 10),
58806
- endDate: currentWeekEnd.toISOString().slice(0, 10)
58849
+ startDate: formatLocalDateKey(currentWeekStart),
58850
+ endDate: formatLocalDateKey(currentWeekEnd)
58807
58851
  });
58808
58852
  const handlePrevWeek = () => {
58809
58853
  setCurrentWeekStart((prev) => {
@@ -58896,8 +58940,8 @@ function UsageContent({
58896
58940
  } else {
58897
58941
  daysToCount = 7;
58898
58942
  }
58899
- const weekTotalMs = weekData.reduce((sum, d) => sum + d.total_duration_ms, 0);
58900
- const weekAvgMs = daysToCount > 0 ? weekTotalMs / daysToCount : 0;
58943
+ const weekActiveMs = weekData.reduce((sum, d) => sum + d.active_duration_ms, 0);
58944
+ const weekAvgMs = calculateAverageDailyDuration(weekActiveMs, daysToCount);
58901
58945
  return /* @__PURE__ */ jsxs("div", { children: [
58902
58946
  /* @__PURE__ */ jsx("div", { className: "flex justify-center mb-6", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 bg-gray-50 rounded-lg p-1 border border-gray-100", children: [
58903
58947
  /* @__PURE__ */ jsx(
@@ -58909,7 +58953,7 @@ function UsageContent({
58909
58953
  children: /* @__PURE__ */ jsx(ChevronLeft, { className: "w-4 h-4" })
58910
58954
  }
58911
58955
  ),
58912
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-700 min-w-[140px] text-center", children: formatDateRange(currentWeekStart.toISOString().slice(0, 10), currentWeekEnd.toISOString().slice(0, 10)) }),
58956
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-700 min-w-[140px] text-center", children: formatDateRange(formatLocalDateKey(currentWeekStart), formatLocalDateKey(currentWeekEnd)) }),
58913
58957
  /* @__PURE__ */ jsx(
58914
58958
  "button",
58915
58959
  {
@@ -58941,7 +58985,7 @@ function DailyBarChart({
58941
58985
  const weekData = useMemo(() => buildWeekData(dailyData, getDateStringsInRange(weekStart, weekEnd)), [dailyData, weekStart, weekEnd]);
58942
58986
  const chartData = useMemo(() => {
58943
58987
  return weekData.map((day, index) => {
58944
- const date = new Date(day.date);
58988
+ const date = parseUsageDate(day.date);
58945
58989
  return {
58946
58990
  ...day,
58947
58991
  index,
@@ -58951,7 +58995,7 @@ function DailyBarChart({
58951
58995
  // green-500
58952
58996
  passiveColor: "#fbbf24",
58953
58997
  // amber-400
58954
- isToday: day.date === (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
58998
+ isToday: day.date === formatLocalDateKey(/* @__PURE__ */ new Date())
58955
58999
  };
58956
59000
  });
58957
59001
  }, [weekData]);
@@ -58971,7 +59015,7 @@ function DailyBarChart({
58971
59015
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
58972
59016
  /* @__PURE__ */ jsx("div", { className: "w-2 h-2 rounded-full bg-gray-300" }),
58973
59017
  /* @__PURE__ */ jsxs("span", { className: "text-sm font-medium text-gray-600", children: [
58974
- "Average Daily usage: ",
59018
+ "Average Daily active usage: ",
58975
59019
  /* @__PURE__ */ jsx("span", { className: "text-gray-900 font-semibold", children: avgDailyMs > 0 ? formatDuration2(avgDailyMs) : "0m" })
58976
59020
  ] })
58977
59021
  ] }),
@@ -59136,17 +59180,14 @@ function getCurrentWeekRange() {
59136
59180
  function getDateStringsInRange(start, end) {
59137
59181
  const result = [];
59138
59182
  for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
59139
- const year = d.getFullYear();
59140
- const month = String(d.getMonth() + 1).padStart(2, "0");
59141
- const day = String(d.getDate()).padStart(2, "0");
59142
- result.push(`${year}-${month}-${day}`);
59183
+ result.push(formatLocalDateKey(d));
59143
59184
  }
59144
59185
  return result;
59145
59186
  }
59146
59187
  function buildWeekData(dailyData, weekDates) {
59147
59188
  const dataMap = new Map(
59148
59189
  (dailyData || []).map((d) => {
59149
- const key = normalizeDateKey(d.date);
59190
+ const key = normalizeUsageDateKey(d.date);
59150
59191
  return [key, { ...d, date: key }];
59151
59192
  })
59152
59193
  );
@@ -59161,22 +59202,10 @@ function buildWeekData(dailyData, weekDates) {
59161
59202
  };
59162
59203
  });
59163
59204
  }
59164
- function normalizeDateKey(dateLike) {
59165
- if (!dateLike) return void 0;
59166
- try {
59167
- const date = new Date(dateLike);
59168
- const year = date.getFullYear();
59169
- const month = String(date.getMonth() + 1).padStart(2, "0");
59170
- const day = String(date.getDate()).padStart(2, "0");
59171
- return `${year}-${month}-${day}`;
59172
- } catch {
59173
- return dateLike.split("T")[0] || dateLike;
59174
- }
59175
- }
59176
59205
  function formatDateRange(startDate, endDate) {
59177
59206
  try {
59178
- const start = new Date(startDate);
59179
- const end = new Date(endDate);
59207
+ const start = parseUsageDate(startDate);
59208
+ const end = parseUsageDate(endDate);
59180
59209
  const opts = { month: "short", day: "numeric" };
59181
59210
  const yearOpts = { year: "numeric" };
59182
59211
  return `${start.toLocaleDateString("en-US", opts)} - ${end.toLocaleDateString("en-US", opts)}, ${end.toLocaleDateString("en-US", yearOpts)}`;
@@ -59187,7 +59216,7 @@ function formatDateRange(startDate, endDate) {
59187
59216
  function formatDate(dateStr) {
59188
59217
  if (!dateStr) return "";
59189
59218
  try {
59190
- const date = new Date(dateStr);
59219
+ const date = parseUsageDate(dateStr);
59191
59220
  return date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
59192
59221
  } catch {
59193
59222
  return dateStr;
@@ -59465,7 +59494,7 @@ var UserManagementTable = ({
59465
59494
  }
59466
59495
  ),
59467
59496
  /* @__PURE__ */ jsx("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Assignments" }),
59468
- showUsageStats && /* @__PURE__ */ jsx("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Average Daily usage" }),
59497
+ showUsageStats && /* @__PURE__ */ jsx("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Average Daily Active Usage" }),
59469
59498
  /* @__PURE__ */ jsx("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider", children: "Actions" })
59470
59499
  ] }) }),
59471
59500
  /* @__PURE__ */ jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: filteredAndSortedUsers.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: showUsageStats ? 5 : 4, className: "px-6 py-12", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center text-gray-400 gap-2", children: [
@@ -73762,39 +73791,8 @@ var TeamManagementView = ({
73762
73791
  const [users, setUsers] = useState([]);
73763
73792
  const [availableLines, setAvailableLines] = useState([]);
73764
73793
  const [availableFactories, setAvailableFactories] = useState([]);
73765
- const [stats, setStats] = useState({
73766
- totalUsers: 0,
73767
- owners: 0,
73768
- it: 0,
73769
- plantHeads: 0,
73770
- industrialEngineers: 0,
73771
- supervisors: 0,
73772
- optifye: 0
73773
- });
73794
+ const [usageSummaryByUser, setUsageSummaryByUser] = useState({});
73774
73795
  const [isAddUserDialogOpen, setIsAddUserDialogOpen] = useState(false);
73775
- const normalizeIds = useCallback((value) => {
73776
- if (Array.isArray(value)) {
73777
- return value.filter((id3) => typeof id3 === "string" && id3.length > 0);
73778
- }
73779
- if (typeof value === "string" && value.length > 0) {
73780
- return [value];
73781
- }
73782
- return [];
73783
- }, []);
73784
- const factoryScopedRoleFactoryIds = useMemo(() => {
73785
- if (!isFactoryScopedRole(user?.role_level)) return [];
73786
- const scopedFactoryIds = normalizeIds(user?.access_scope?.factory_ids);
73787
- if (scopedFactoryIds.length > 0) {
73788
- return Array.from(new Set(scopedFactoryIds));
73789
- }
73790
- const propertyFactoryIds = normalizeIds(
73791
- user?.properties?.factory_ids ?? user?.properties?.factory_id
73792
- );
73793
- if (propertyFactoryIds.length > 0) {
73794
- return Array.from(new Set(propertyFactoryIds));
73795
- }
73796
- return entityConfig?.factoryId ? [entityConfig.factoryId] : [];
73797
- }, [user, entityConfig?.factoryId, normalizeIds]);
73798
73796
  const notifyScopeRefresh = useCallback(() => {
73799
73797
  if (typeof window !== "undefined") {
73800
73798
  window.dispatchEvent(new Event("rbac:refresh-scope"));
@@ -73803,37 +73801,17 @@ var TeamManagementView = ({
73803
73801
  const canAddUsers = canRoleManageUsers(user?.role_level);
73804
73802
  const canViewUsageStats = canRoleViewUsageStats(user?.role_level);
73805
73803
  const pageCompanyId = entityConfig?.companyId || user?.properties?.company_id;
73806
- const companyIdForUsage = pageCompanyId;
73807
- const usageDateRange = useMemo(() => {
73808
- const today = /* @__PURE__ */ new Date();
73809
- const dayOfWeek = today.getDay();
73810
- const daysSinceMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
73811
- const monday = new Date(today);
73812
- monday.setDate(today.getDate() - daysSinceMonday);
73813
- return {
73814
- startDate: monday.toISOString().slice(0, 10),
73815
- endDate: today.toISOString().slice(0, 10),
73816
- daysElapsed: daysSinceMonday + 1
73817
- // Include today
73818
- };
73819
- }, []);
73820
- const {
73821
- data: usageData,
73822
- isLoading: isUsageLoading
73823
- } = useCompanyUsersUsage(canViewUsageStats ? companyIdForUsage : void 0, {
73824
- startDate: usageDateRange.startDate,
73825
- endDate: usageDateRange.endDate
73826
- });
73804
+ const usageDateRange = useMemo(() => getCurrentWeekToDateUsageRange(), []);
73827
73805
  const avgDailyUsageMap = useMemo(() => {
73828
- if (!usageData?.users) {
73806
+ if (!canViewUsageStats) {
73829
73807
  return {};
73830
73808
  }
73831
73809
  const daysElapsed = usageDateRange.daysElapsed;
73832
- return usageData.users.reduce((acc, user2) => {
73833
- acc[user2.user_id] = Math.round(user2.total_duration_ms / daysElapsed);
73810
+ return Object.entries(usageSummaryByUser).reduce((acc, [userId, usage]) => {
73811
+ acc[userId] = calculateAverageDailyDuration(usage.active_duration_ms, daysElapsed);
73834
73812
  return acc;
73835
73813
  }, {});
73836
- }, [usageData, usageDateRange.daysElapsed]);
73814
+ }, [canViewUsageStats, usageSummaryByUser, usageDateRange.daysElapsed]);
73837
73815
  const pageTitle = "Team Management";
73838
73816
  const pageDescription = canViewUsageStats ? "Manage team members and view their daily usage" : "Manage supervisors in your factory";
73839
73817
  const hasAccess = user ? user.role_level === void 0 || canRoleAccessTeamManagement(user.role_level) : false;
@@ -73857,7 +73835,6 @@ var TeamManagementView = ({
73857
73835
  setIsLoading(true);
73858
73836
  setError(void 0);
73859
73837
  try {
73860
- const userManagementService = createUserManagementService(supabase);
73861
73838
  const { data: { session } } = await supabase.auth.getSession();
73862
73839
  if (!session?.access_token) {
73863
73840
  throw new Error("No authentication token available");
@@ -73867,116 +73844,31 @@ var TeamManagementView = ({
73867
73844
  if (!backendUrl) {
73868
73845
  throw new Error("Backend URL is not configured. Please set NEXT_PUBLIC_BACKEND_URL in your environment.");
73869
73846
  }
73870
- if ((user?.role_level === "optifye" || user?.role_level === "owner" || user?.role_level === "it") && companyId) {
73871
- const { data: factories } = await supabase.from("factories").select("id, factory_name, company_id").eq("company_id", companyId).order("factory_name");
73872
- const linesResponse = await fetch(`${backendUrl}/api/lines?company_id=${companyId}`, {
73873
- headers: {
73874
- "Authorization": `Bearer ${token}`,
73875
- "Content-Type": "application/json"
73876
- }
73877
- });
73878
- if (!linesResponse.ok) {
73879
- throw new Error(`Failed to fetch lines: ${linesResponse.statusText}`);
73880
- }
73881
- const linesData = await linesResponse.json();
73882
- const lines = linesData.lines || [];
73883
- setAvailableFactories(factories || []);
73884
- setAvailableLines(lines);
73885
- console.log("[TeamManagementView] Company-scoped team view - Company:", companyId, "Loaded factories:", factories?.length, "lines:", lines?.length);
73886
- } else if (isFactoryScopedRole(user?.role_level)) {
73887
- if (factoryScopedRoleFactoryIds.length > 0) {
73888
- if (companyId) {
73889
- const linesResponse = await fetch(`${backendUrl}/api/lines?company_id=${companyId}`, {
73890
- headers: {
73891
- "Authorization": `Bearer ${token}`,
73892
- "Content-Type": "application/json"
73893
- }
73894
- });
73895
- if (!linesResponse.ok) {
73896
- throw new Error(`Failed to fetch lines: ${linesResponse.statusText}`);
73897
- }
73898
- const linesData = await linesResponse.json();
73899
- const allLines = linesData.lines || [];
73900
- const lines = allLines.filter((line) => factoryScopedRoleFactoryIds.includes(line.factory_id));
73901
- setAvailableLines(lines);
73902
- console.log("[TeamManagementView] Factory-scoped team view - Factories:", factoryScopedRoleFactoryIds, "Loaded lines:", lines?.length);
73903
- }
73904
- } else if (entityConfig?.factoryId) {
73905
- const linesResponse = await fetch(`${backendUrl}/api/lines?factory_id=${entityConfig.factoryId}`, {
73906
- headers: {
73907
- "Authorization": `Bearer ${token}`,
73908
- "Content-Type": "application/json"
73909
- }
73910
- });
73911
- if (!linesResponse.ok) {
73912
- throw new Error(`Failed to fetch lines: ${linesResponse.statusText}`);
73913
- }
73914
- const linesData = await linesResponse.json();
73915
- const lines = linesData.lines || [];
73916
- setAvailableLines(lines);
73917
- console.log("[TeamManagementView] Plant Head - Using entityConfig factory:", entityConfig.factoryId, "Loaded lines:", lines?.length);
73918
- } else {
73919
- setAvailableLines([]);
73920
- console.warn("[TeamManagementView] Plant Head has no factory assignments");
73921
- }
73922
- setAvailableFactories([]);
73923
- } else if (companyId) {
73924
- const linesResponse = await fetch(`${backendUrl}/api/lines?company_id=${companyId}`, {
73847
+ const params = new URLSearchParams({
73848
+ start_date: usageDateRange.startDate,
73849
+ end_date: usageDateRange.endDate
73850
+ });
73851
+ const bootstrapResponse = await fetch(
73852
+ `${backendUrl}/api/users/company/${companyId}/bootstrap?${params.toString()}`,
73853
+ {
73925
73854
  headers: {
73926
73855
  "Authorization": `Bearer ${token}`,
73927
73856
  "Content-Type": "application/json"
73928
73857
  }
73929
- });
73930
- if (!linesResponse.ok) {
73931
- throw new Error(`Failed to fetch lines: ${linesResponse.statusText}`);
73932
73858
  }
73933
- const linesData = await linesResponse.json();
73934
- const lines = linesData.lines || [];
73935
- setAvailableLines(lines);
73936
- setAvailableFactories([]);
73937
- console.log("[TeamManagementView] Fallback - Company:", companyId, "Loaded lines:", lines?.length);
73938
- }
73939
- const usersPromise = isFactoryScopedRole(user?.role_level) ? (async () => {
73940
- if (factoryScopedRoleFactoryIds.length === 0) {
73941
- return [];
73942
- }
73943
- const results = await Promise.allSettled(
73944
- factoryScopedRoleFactoryIds.map((factoryId) => userManagementService.getFactoryUsers(factoryId))
73945
- );
73946
- const successful = results.filter(
73947
- (result) => result.status === "fulfilled"
73948
- ).flatMap((result) => result.value || []);
73949
- if (successful.length > 0) {
73950
- const byUserId = /* @__PURE__ */ new Map();
73951
- successful.forEach((u) => {
73952
- if (u?.user_id) {
73953
- byUserId.set(u.user_id, u);
73954
- }
73955
- });
73956
- return Array.from(byUserId.values());
73957
- }
73958
- const firstRejected = results.find(
73959
- (result) => result.status === "rejected"
73960
- );
73961
- if (firstRejected) {
73962
- throw firstRejected.reason;
73963
- }
73964
- return [];
73965
- })() : userManagementService.getCompanyUsers(companyId);
73966
- const [usersData, userStats] = await Promise.all([
73967
- usersPromise,
73968
- userManagementService.getUserStats(companyId)
73969
- ]);
73970
- setUsers(usersData);
73971
- setStats({
73972
- totalUsers: userStats.total,
73973
- owners: userStats.owners,
73974
- it: userStats.it,
73975
- plantHeads: userStats.plant_heads,
73976
- industrialEngineers: userStats.industrial_engineers,
73977
- supervisors: userStats.supervisors,
73978
- optifye: 0
73979
- });
73859
+ );
73860
+ if (!bootstrapResponse.ok) {
73861
+ const errorData = await bootstrapResponse.json().catch(() => ({}));
73862
+ throw new Error(errorData.detail || `Failed to fetch team bootstrap: ${bootstrapResponse.statusText}`);
73863
+ }
73864
+ const bootstrapData = await bootstrapResponse.json();
73865
+ setAvailableFactories((bootstrapData.factories || []).map((factory) => ({
73866
+ id: factory.id,
73867
+ factory_name: factory.factory_name
73868
+ })));
73869
+ setAvailableLines(bootstrapData.lines || []);
73870
+ setUsers(bootstrapData.users || []);
73871
+ setUsageSummaryByUser(bootstrapData.usage_summary_by_user || {});
73980
73872
  } catch (err) {
73981
73873
  console.error("Error loading team management data:", err);
73982
73874
  setError(err instanceof Error ? err.message : "Failed to load data");
@@ -73984,7 +73876,7 @@ var TeamManagementView = ({
73984
73876
  } finally {
73985
73877
  setIsLoading(false);
73986
73878
  }
73987
- }, [supabase, user, pageCompanyId, entityConfig?.factoryId, factoryScopedRoleFactoryIds]);
73879
+ }, [supabase, user, pageCompanyId, usageDateRange.endDate, usageDateRange.startDate]);
73988
73880
  useEffect(() => {
73989
73881
  const companyId = pageCompanyId;
73990
73882
  const canLoad = hasAccess && user && !!companyId;
@@ -74165,7 +74057,7 @@ var TeamManagementView = ({
74165
74057
  availableLines,
74166
74058
  availableFactories,
74167
74059
  avgDailyUsage: avgDailyUsageMap,
74168
- isUsageLoading,
74060
+ isUsageLoading: false,
74169
74061
  showUsageStats: canViewUsageStats
74170
74062
  }
74171
74063
  ) }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optifye/dashboard-core",
3
- "version": "6.11.36",
3
+ "version": "6.11.37",
4
4
  "description": "Reusable UI & logic for Optifye dashboard",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",