@optifye/dashboard-core 6.10.53 → 6.11.0

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
@@ -1,22 +1,22 @@
1
- import * as React26 from 'react';
2
- import React26__default, { createContext, useRef, useCallback, useState, useMemo, useEffect, forwardRef, useImperativeHandle, useLayoutEffect, memo as memo$1, useContext, useId, Children, isValidElement, useInsertionEffect, Fragment as Fragment$1, createElement, Component } from 'react';
1
+ import * as React141 from 'react';
2
+ import React141__default, { createContext, useRef, useCallback, useState, useMemo, useEffect, forwardRef, useImperativeHandle, useLayoutEffect, memo as memo$1, useContext, useId, Children, isValidElement, useInsertionEffect, Fragment as Fragment$1, createElement, Component } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { useRouter } from 'next/router';
5
5
  import { fromZonedTime, formatInTimeZone, toZonedTime } from 'date-fns-tz';
6
- import { endOfDay, startOfDay, endOfMonth, startOfMonth, isSameDay, eachDayOfInterval, getDay, isWithinInterval, format, addDays, differenceInMinutes, addMinutes, subDays, subMonths, addMonths, parseISO, isValid, formatDistanceToNow, isToday, isFuture, isBefore } from 'date-fns';
6
+ import { endOfDay, startOfDay, startOfMonth, isSameDay, endOfMonth, eachDayOfInterval, getDay, isWithinInterval, format, addDays, differenceInMinutes, addMinutes, subDays, subMonths, addMonths, parseISO, isValid, formatDistanceToNow, isToday, isFuture, isBefore } from 'date-fns';
7
7
  import mixpanel from 'mixpanel-browser';
8
8
  import { EventEmitter } from 'events';
9
9
  import { createClient, REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js';
10
10
  import Hls, { Events, ErrorTypes } from 'hls.js';
11
11
  import useSWR from 'swr';
12
12
  import { memo, noop, warning, invariant, progress, secondsToMilliseconds, millisecondsToSeconds } from 'motion-utils';
13
- import { Camera, AlertTriangle, ChevronDown, ChevronUp, Check, Map as Map$1, Video, ShieldCheck, Star, Award, Filter, X, Coffee, Plus, ArrowLeft, Clock, Calendar, Save, AlertCircle, Loader2, Minus, ArrowDown, ArrowUp, ChevronLeft, ChevronRight, TrendingUp, Sparkles, Pause, Play, Wrench, XCircle, Package, UserX, Zap, HelpCircle, Tag, Palette, CheckCircle2, RefreshCw, TrendingDown, FolderOpen, Folder, Sliders, Activity, Layers, Search, Edit2, ArrowRight, CheckCircle, User, Users, Shield, Building2, Mail, Lock, Info, Share2, Trophy, Target, Download, Sun, Moon, MousePointer, UserPlus, UserCog, Trash2, Eye, MoreVertical, BarChart3, Pencil, UserCheck, LogOut, Film, MessageSquare, Menu, Send, Copy, Settings, LifeBuoy, EyeOff, UserCircle, Flame, Crown, Medal } from 'lucide-react';
13
+ import { Camera, AlertTriangle, ChevronDown, ChevronUp, Check, Map as Map$1, Video, ShieldCheck, Star, Award, Filter, X, Coffee, Plus, ArrowLeft, Clock, Calendar, Save, AlertCircle, Loader2, Minus, ArrowDown, ArrowUp, ChevronLeft, ChevronRight, TrendingUp, Sparkles, Pause, Play, Wrench, XCircle, Package, UserX, Zap, HelpCircle, Tag, Palette, CheckCircle2, RefreshCw, TrendingDown, FolderOpen, Folder, Sliders, Activity, Layers, Search, Edit2, ArrowRight, CheckCircle, User, Users, Shield, Building2, Mail, Lock, Info, Share2, Trophy, Target, Download, Sun, Moon, MousePointer, UserPlus, UserCog, Trash2, Eye, MoreVertical, BarChart3, Pencil, UserCheck, LogOut, Film, MessageSquare, Menu, Send, Copy, Bell, ArrowUpRight, Settings, LifeBuoy, EyeOff, Flame, Crown, Medal } from 'lucide-react';
14
14
  import { toast } from 'sonner';
15
15
  import { BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, ReferenceLine, Tooltip, Legend, Bar, LabelList, ResponsiveContainer, LineChart as LineChart$1, Line, PieChart, Pie, Cell, ComposedChart, Area, ScatterChart, Scatter } from 'recharts';
16
16
  import { Slot } from '@radix-ui/react-slot';
17
17
  import * as SelectPrimitive from '@radix-ui/react-select';
18
18
  import { DayPicker, useNavigation as useNavigation$1 } from 'react-day-picker';
19
- import { AdjustmentsHorizontalIcon, ClockIcon, UsersIcon, UserCircleIcon, TicketIcon, CurrencyDollarIcon, QuestionMarkCircleIcon, XMarkIcon, ArrowRightIcon, Bars3Icon, HomeIcon, TrophyIcon, ChartBarIcon, LightBulbIcon, CubeIcon, HeartIcon, Cog6ToothIcon, ChevronRightIcon, ArrowRightStartOnRectangleIcon, CalendarIcon, ChevronDownIcon, ChevronLeftIcon, ExclamationCircleIcon, EnvelopeIcon, DocumentTextIcon, ChevronUpIcon, ArrowDownTrayIcon, CheckCircleIcon, ChatBubbleLeftRightIcon, XCircleIcon, FunnelIcon, EyeIcon, InformationCircleIcon, ArrowLeftIcon, PlayCircleIcon } from '@heroicons/react/24/outline';
19
+ import { AdjustmentsHorizontalIcon, ClockIcon, UsersIcon, UserCircleIcon, TicketIcon, CurrencyDollarIcon, QuestionMarkCircleIcon, XMarkIcon, ArrowRightIcon, Bars3Icon, HomeIcon, VideoCameraIcon, TrophyIcon, ChartBarIcon, LightBulbIcon, CubeIcon, HeartIcon, BellIcon, Cog6ToothIcon, ChevronRightIcon, ArrowRightStartOnRectangleIcon, ExclamationCircleIcon, ExclamationTriangleIcon, CalendarIcon, ChevronDownIcon, ChevronLeftIcon, EnvelopeIcon, DocumentTextIcon, ChevronUpIcon, ArrowDownTrayIcon, CheckCircleIcon, ChatBubbleLeftRightIcon, XCircleIcon, FunnelIcon, EyeIcon, InformationCircleIcon, ArrowLeftIcon, PlayCircleIcon } from '@heroicons/react/24/outline';
20
20
  import { CheckIcon } from '@heroicons/react/24/solid';
21
21
  import html2canvas from 'html2canvas';
22
22
  import jsPDF, { jsPDF as jsPDF$1 } from 'jspdf';
@@ -400,14 +400,14 @@ var useIdleTimeVlmConfig = () => {
400
400
  }
401
401
  return context;
402
402
  };
403
- var DashboardConfigContext = React26.createContext(void 0);
403
+ var DashboardConfigContext = React141.createContext(void 0);
404
404
  var DashboardProvider = ({ config: userProvidedConfig, children }) => {
405
- const fullConfig = React26.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
405
+ const fullConfig = React141.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
406
406
  _setDashboardConfigInstance(fullConfig);
407
- React26.useEffect(() => {
407
+ React141.useEffect(() => {
408
408
  _setDashboardConfigInstance(fullConfig);
409
409
  }, [fullConfig]);
410
- React26.useEffect(() => {
410
+ React141.useEffect(() => {
411
411
  if (!fullConfig.theme) return;
412
412
  const styleId = "dashboard-core-theme-vars";
413
413
  let styleEl = document.getElementById(styleId);
@@ -433,7 +433,7 @@ var DashboardProvider = ({ config: userProvidedConfig, children }) => {
433
433
  return /* @__PURE__ */ jsx(DashboardConfigContext.Provider, { value: fullConfig, children: /* @__PURE__ */ jsx(IdleTimeVlmConfigProvider, { children }) });
434
434
  };
435
435
  var useDashboardConfig = () => {
436
- const ctx = React26.useContext(DashboardConfigContext);
436
+ const ctx = React141.useContext(DashboardConfigContext);
437
437
  if (!ctx) throw new Error("useDashboardConfig must be used within a DashboardProvider");
438
438
  return ctx;
439
439
  };
@@ -3857,6 +3857,208 @@ var ApiClient = class {
3857
3857
  };
3858
3858
  ApiClient.DEFAULT_TIMEOUT = 3e5;
3859
3859
 
3860
+ // src/lib/utils/roleMetadata.ts
3861
+ var FACTORY_SCOPED_ROLE_SET = /* @__PURE__ */ new Set(["plant_head", "industrial_engineer"]);
3862
+ var ROLE_ORDER = [
3863
+ "optifye",
3864
+ "owner",
3865
+ "it",
3866
+ "plant_head",
3867
+ "industrial_engineer",
3868
+ "supervisor"
3869
+ ];
3870
+ var FULL_DASHBOARD_PATHS = [
3871
+ "/",
3872
+ "/leaderboard",
3873
+ "/kpis",
3874
+ "/targets",
3875
+ "/shifts",
3876
+ "/supervisor-management",
3877
+ "/skus",
3878
+ "/help",
3879
+ "/health",
3880
+ "/profile",
3881
+ "/workspace",
3882
+ "/factory-view",
3883
+ "/team-management",
3884
+ "/tickets",
3885
+ "/improvement-center"
3886
+ ];
3887
+ var LIVE_MONITOR_DASHBOARD_PATHS = [
3888
+ "/",
3889
+ "/live-monitor",
3890
+ ...FULL_DASHBOARD_PATHS.filter((path) => path !== "/")
3891
+ ];
3892
+ var SUPERVISOR_PATHS = [
3893
+ "/",
3894
+ "/leaderboard",
3895
+ "/kpis",
3896
+ "/targets",
3897
+ "/shifts",
3898
+ "/skus",
3899
+ "/help",
3900
+ "/health",
3901
+ "/profile",
3902
+ "/workspace",
3903
+ "/tickets",
3904
+ "/improvement-center"
3905
+ ];
3906
+ var ROLE_METADATA = {
3907
+ optifye: {
3908
+ label: "Optifye",
3909
+ description: "Full platform access - Optifye team member",
3910
+ assignmentKind: "global",
3911
+ navPaths: LIVE_MONITOR_DASHBOARD_PATHS
3912
+ },
3913
+ owner: {
3914
+ label: "Owner",
3915
+ description: "Company-wide access - Can manage all users and settings",
3916
+ assignmentKind: "company",
3917
+ navPaths: LIVE_MONITOR_DASHBOARD_PATHS
3918
+ },
3919
+ it: {
3920
+ label: "IT",
3921
+ description: "Company-wide access - IT personnel with full company access",
3922
+ assignmentKind: "company",
3923
+ navPaths: FULL_DASHBOARD_PATHS
3924
+ },
3925
+ plant_head: {
3926
+ label: "Plant Head",
3927
+ description: "Factory-level access - Can manage supervisors and factory settings",
3928
+ assignmentKind: "factory",
3929
+ navPaths: LIVE_MONITOR_DASHBOARD_PATHS
3930
+ },
3931
+ industrial_engineer: {
3932
+ label: "Industrial Engineer",
3933
+ description: "Factory-level access - Can manage supervisors and factory performance scope",
3934
+ assignmentKind: "factory",
3935
+ navPaths: FULL_DASHBOARD_PATHS
3936
+ },
3937
+ supervisor: {
3938
+ label: "Supervisor",
3939
+ description: "Line-level access - Can monitor assigned production lines",
3940
+ assignmentKind: "line",
3941
+ navPaths: SUPERVISOR_PATHS
3942
+ }
3943
+ };
3944
+ var normalizeRoleLevel = (role) => {
3945
+ if (!role) return null;
3946
+ return Object.prototype.hasOwnProperty.call(ROLE_METADATA, role) ? role : null;
3947
+ };
3948
+ var getRoleMetadata = (role) => {
3949
+ const normalizedRole = normalizeRoleLevel(role);
3950
+ return normalizedRole ? ROLE_METADATA[normalizedRole] : null;
3951
+ };
3952
+ var getRoleLabel = (role) => {
3953
+ return getRoleMetadata(role)?.label || (role || "Unknown");
3954
+ };
3955
+ var getRoleDescription = (role) => {
3956
+ return getRoleMetadata(role)?.description || "";
3957
+ };
3958
+ var isFactoryScopedRole = (role) => {
3959
+ const normalizedRole = normalizeRoleLevel(role);
3960
+ return normalizedRole ? FACTORY_SCOPED_ROLE_SET.has(normalizedRole) : false;
3961
+ };
3962
+ var isSupervisorRole = (role) => normalizeRoleLevel(role) === "supervisor";
3963
+ var canRoleManageUsers = (role) => {
3964
+ const normalizedRole = normalizeRoleLevel(role);
3965
+ return normalizedRole === "optifye" || normalizedRole === "owner" || normalizedRole === "it" || isFactoryScopedRole(normalizedRole);
3966
+ };
3967
+ var canRoleManageTargets = (role) => {
3968
+ const normalizedRole = normalizeRoleLevel(role);
3969
+ return normalizedRole === "optifye" || normalizedRole === "owner" || normalizedRole === "it" || isFactoryScopedRole(normalizedRole);
3970
+ };
3971
+ var canRoleViewUsageStats = (role) => {
3972
+ const normalizedRole = normalizeRoleLevel(role);
3973
+ return normalizedRole === "optifye" || normalizedRole === "owner" || normalizedRole === "it";
3974
+ };
3975
+ var canRoleAccessTeamManagement = (role) => {
3976
+ return canRoleManageUsers(role);
3977
+ };
3978
+ var getRoleNavPaths = (role) => {
3979
+ return getRoleMetadata(role)?.navPaths || [];
3980
+ };
3981
+ var getVisibleRolesForCurrentUser = (currentRole) => {
3982
+ const normalizedRole = normalizeRoleLevel(currentRole);
3983
+ const visibleRolesByCurrentRole = {
3984
+ optifye: ROLE_ORDER,
3985
+ owner: ["owner", "it", "plant_head", "industrial_engineer", "supervisor"],
3986
+ it: ["it", "plant_head", "industrial_engineer", "supervisor"],
3987
+ plant_head: ["plant_head", "supervisor"],
3988
+ industrial_engineer: ["industrial_engineer", "supervisor"],
3989
+ supervisor: ["supervisor"]
3990
+ };
3991
+ return normalizedRole ? visibleRolesByCurrentRole[normalizedRole] : ["supervisor"];
3992
+ };
3993
+ var getAssignableRoles = (currentRole, options = {}) => {
3994
+ const normalizedRole = normalizeRoleLevel(currentRole);
3995
+ const isSuperAdminOptifye = !!options.isSuperAdminOptifye;
3996
+ if (!normalizedRole) return [];
3997
+ if (normalizedRole === "optifye") {
3998
+ return isSuperAdminOptifye ? ["owner", "it", "plant_head", "industrial_engineer", "supervisor"] : ["it", "plant_head", "industrial_engineer", "supervisor"];
3999
+ }
4000
+ if (normalizedRole === "owner") {
4001
+ return ["it", "plant_head", "industrial_engineer", "supervisor"];
4002
+ }
4003
+ if (normalizedRole === "it") {
4004
+ return ["plant_head", "industrial_engineer", "supervisor"];
4005
+ }
4006
+ if (isFactoryScopedRole(normalizedRole)) {
4007
+ return ["supervisor"];
4008
+ }
4009
+ return [];
4010
+ };
4011
+ var canRoleInviteRole = (currentRole, targetRole, options = {}) => {
4012
+ const normalizedTargetRole = normalizeRoleLevel(targetRole);
4013
+ if (!normalizedTargetRole) return false;
4014
+ return getAssignableRoles(currentRole, options).includes(normalizedTargetRole);
4015
+ };
4016
+ var canRoleAssignLines = (currentRole, targetRole) => {
4017
+ const normalizedCurrentRole = normalizeRoleLevel(currentRole);
4018
+ const normalizedTargetRole = normalizeRoleLevel(targetRole);
4019
+ if (normalizedTargetRole !== "supervisor") return false;
4020
+ return normalizedCurrentRole === "optifye" || normalizedCurrentRole === "owner" || normalizedCurrentRole === "it" || isFactoryScopedRole(normalizedCurrentRole);
4021
+ };
4022
+ var canRoleAssignFactories = (currentRole, targetRole) => {
4023
+ const normalizedCurrentRole = normalizeRoleLevel(currentRole);
4024
+ const normalizedTargetRole = normalizeRoleLevel(targetRole);
4025
+ if (!normalizedTargetRole || !isFactoryScopedRole(normalizedTargetRole)) return false;
4026
+ return normalizedCurrentRole === "optifye" || normalizedCurrentRole === "owner" || normalizedCurrentRole === "it";
4027
+ };
4028
+ var canRoleChangeRole = (currentRole, targetRole, options = {}) => {
4029
+ const normalizedCurrentRole = normalizeRoleLevel(currentRole);
4030
+ const normalizedTargetRole = normalizeRoleLevel(targetRole);
4031
+ const isSuperAdminOptifye = !!options.isSuperAdminOptifye;
4032
+ if (!normalizedCurrentRole || !normalizedTargetRole) return false;
4033
+ if (normalizedCurrentRole === "optifye") {
4034
+ if (isSuperAdminOptifye) return true;
4035
+ return ["it", "plant_head", "industrial_engineer", "supervisor"].includes(normalizedTargetRole);
4036
+ }
4037
+ if (normalizedCurrentRole === "owner") {
4038
+ return ["plant_head", "industrial_engineer", "supervisor"].includes(normalizedTargetRole);
4039
+ }
4040
+ if (normalizedCurrentRole === "it") {
4041
+ return ["plant_head", "industrial_engineer", "supervisor"].includes(normalizedTargetRole);
4042
+ }
4043
+ return false;
4044
+ };
4045
+ var canRoleRemoveUser = (currentRole, targetRole, options = {}) => {
4046
+ const normalizedCurrentRole = normalizeRoleLevel(currentRole);
4047
+ const normalizedTargetRole = normalizeRoleLevel(targetRole);
4048
+ const isSuperAdminOptifye = !!options.isSuperAdminOptifye;
4049
+ if (!normalizedCurrentRole || !normalizedTargetRole) return false;
4050
+ if (normalizedCurrentRole === "optifye") return isSuperAdminOptifye;
4051
+ if (normalizedCurrentRole === "owner" || normalizedCurrentRole === "it") {
4052
+ return ["plant_head", "industrial_engineer", "supervisor"].includes(normalizedTargetRole);
4053
+ }
4054
+ return false;
4055
+ };
4056
+ var getAssignmentColumnLabel = (role) => {
4057
+ if (isFactoryScopedRole(role)) return "Factories";
4058
+ if (isSupervisorRole(role)) return "Lines";
4059
+ return "Assignments";
4060
+ };
4061
+
3860
4062
  // src/lib/services/authService.ts
3861
4063
  var AuthService = class {
3862
4064
  /**
@@ -3976,7 +4178,7 @@ var AuthService = class {
3976
4178
  first_login_completed: enrichedUser.profile.first_login_completed,
3977
4179
  properties: {
3978
4180
  company_id: enrichedUser.company_id,
3979
- access_level: enrichedUser.permissions.is_owner || enrichedUser.permissions.is_optifye_admin ? "company" : enrichedUser.permissions.is_plant_head ? "factory" : "line",
4181
+ access_level: enrichedUser.permissions.is_owner || enrichedUser.permissions.is_optifye_admin ? "company" : isFactoryScopedRole(enrichedUser.role) ? "factory" : "line",
3980
4182
  line_ids: line_ids.length > 0 ? line_ids : void 0,
3981
4183
  factory_ids: factory_ids.length > 0 ? factory_ids : void 0,
3982
4184
  // Include permissions for easy access
@@ -6931,6 +7133,9 @@ var InvitationService = class {
6931
7133
  if (existingUser) {
6932
7134
  throw new Error("A user with this email address already exists in the system.");
6933
7135
  }
7136
+ if (input.role_level === "industrial_engineer" && (!input.factory_ids || input.factory_ids.length === 0)) {
7137
+ throw new Error("Industrial Engineer invitations require at least one factory assignment.");
7138
+ }
6934
7139
  const invitationData = {
6935
7140
  email: input.email.toLowerCase().trim(),
6936
7141
  company_id: input.company_id,
@@ -6941,7 +7146,7 @@ var InvitationService = class {
6941
7146
  if (input.role_level === "supervisor" && input.line_ids && input.line_ids.length > 0) {
6942
7147
  invitationData.line_ids = input.line_ids;
6943
7148
  }
6944
- if (input.role_level === "plant_head" && input.factory_ids && input.factory_ids.length > 0) {
7149
+ if ((input.role_level === "plant_head" || input.role_level === "industrial_engineer") && input.factory_ids && input.factory_ids.length > 0) {
6945
7150
  invitationData.factory_ids = input.factory_ids;
6946
7151
  }
6947
7152
  console.log("[InvitationService] Final invitationData being inserted:", invitationData);
@@ -7651,6 +7856,8 @@ async function fetchIdleTimeReasons(params) {
7651
7856
  data: {
7652
7857
  total_idle_time_seconds: 0,
7653
7858
  total_clips_analyzed: 0,
7859
+ scope_work_seconds: null,
7860
+ scope_workspace_count: 0,
7654
7861
  reasons: []
7655
7862
  },
7656
7863
  error: "Request failed"
@@ -7668,6 +7875,8 @@ async function fetchIdleTimeReasons(params) {
7668
7875
  return {
7669
7876
  total_idle_time_seconds: 0,
7670
7877
  total_clips_analyzed: 0,
7878
+ scope_work_seconds: null,
7879
+ scope_workspace_count: 0,
7671
7880
  reasons: []
7672
7881
  };
7673
7882
  }
@@ -7675,7 +7884,9 @@ async function fetchIdleTimeReasons(params) {
7675
7884
  function transformToChartData(data) {
7676
7885
  return data.reasons.map((reason) => ({
7677
7886
  name: formatReasonLabel(reason.reason),
7678
- value: reason.percentage
7887
+ value: reason.percentage,
7888
+ totalDurationSeconds: reason.total_duration_seconds,
7889
+ efficiencyLossPercentage: reason.efficiency_loss_percentage ?? null
7679
7890
  }));
7680
7891
  }
7681
7892
  function formatReasonLabel(reason) {
@@ -8083,6 +8294,18 @@ var lineLeaderboardService = {
8083
8294
  return data?.entries ?? [];
8084
8295
  }
8085
8296
  };
8297
+
8298
+ // src/lib/services/alertsService.ts
8299
+ var alertsService = {
8300
+ async getCurrentAlerts(supabase, companyId) {
8301
+ const query = `?company_id=${encodeURIComponent(companyId)}`;
8302
+ return fetchBackendJson(supabase, `/api/alerts/current${query}`);
8303
+ },
8304
+ async getSummary(supabase, companyId) {
8305
+ const query = `?company_id=${encodeURIComponent(companyId)}`;
8306
+ return fetchBackendJson(supabase, `/api/alerts/summary${query}`);
8307
+ }
8308
+ };
8086
8309
  var SupabaseContext = createContext(void 0);
8087
8310
  var SupabaseProvider = ({ client, children }) => {
8088
8311
  _setSupabaseInstance(client);
@@ -8858,7 +9081,7 @@ var useMobileMenu = () => {
8858
9081
  };
8859
9082
  var useHideMobileHeader = (shouldHide = true) => {
8860
9083
  const context = useMobileMenu();
8861
- React26__default.useEffect(() => {
9084
+ React141__default.useEffect(() => {
8862
9085
  if (context && shouldHide) {
8863
9086
  context.setHideMobileHeader(true);
8864
9087
  return () => {
@@ -14861,10 +15084,7 @@ var useSKUs = (companyId) => {
14861
15084
  // src/lib/hooks/useCanSaveTargets.ts
14862
15085
  var useCanSaveTargets = () => {
14863
15086
  const { user } = useAuth();
14864
- if (user?.role_level === "optifye") {
14865
- return true;
14866
- }
14867
- return user?.role_level === "owner" || user?.role_level === "plant_head";
15087
+ return canRoleManageTargets(user?.role_level);
14868
15088
  };
14869
15089
  function useTicketHistory(companyId) {
14870
15090
  const [tickets, setTickets] = useState([]);
@@ -16166,12 +16386,7 @@ var useFormatNumber = () => {
16166
16386
  function useAccessControl() {
16167
16387
  const { user } = useAuth();
16168
16388
  const userRole = useMemo(() => {
16169
- if (!user?.role_level) return null;
16170
- const roleLevel = user.role_level;
16171
- if (roleLevel === "owner" || roleLevel === "it" || roleLevel === "plant_head" || roleLevel === "supervisor" || roleLevel === "optifye") {
16172
- return roleLevel;
16173
- }
16174
- return "supervisor";
16389
+ return normalizeRoleLevel(user?.role_level) || null;
16175
16390
  }, [user?.role_level]);
16176
16391
  const assignedLineIds = useMemo(() => {
16177
16392
  if (!user) return [];
@@ -16183,89 +16398,15 @@ function useAccessControl() {
16183
16398
  }, [user]);
16184
16399
  const assignedFactoryIds = useMemo(() => {
16185
16400
  if (!user) return [];
16186
- if (user.role_level === "plant_head") {
16401
+ if (isFactoryScopedRole(user.role_level)) {
16187
16402
  const factories = user.properties?.factory_id || user.properties?.factory_ids || [];
16188
16403
  return Array.isArray(factories) ? factories : [];
16189
16404
  }
16190
16405
  return [];
16191
16406
  }, [user]);
16192
- const roleAccessMap = {
16193
- optifye: [
16194
- "/",
16195
- "/leaderboard",
16196
- "/kpis",
16197
- "/targets",
16198
- "/shifts",
16199
- "/supervisor-management",
16200
- "/skus",
16201
- "/help",
16202
- "/health",
16203
- "/profile",
16204
- "/workspace",
16205
- "/factory-view",
16206
- "/team-management"
16207
- ],
16208
- owner: [
16209
- "/",
16210
- "/leaderboard",
16211
- "/kpis",
16212
- "/targets",
16213
- "/shifts",
16214
- "/supervisor-management",
16215
- "/skus",
16216
- "/help",
16217
- "/health",
16218
- "/profile",
16219
- "/workspace",
16220
- "/factory-view",
16221
- "/team-management"
16222
- ],
16223
- it: [
16224
- "/",
16225
- "/leaderboard",
16226
- "/kpis",
16227
- "/targets",
16228
- "/shifts",
16229
- "/supervisor-management",
16230
- "/skus",
16231
- "/help",
16232
- "/health",
16233
- "/profile",
16234
- "/workspace",
16235
- "/factory-view",
16236
- "/team-management"
16237
- ],
16238
- plant_head: [
16239
- "/",
16240
- "/leaderboard",
16241
- "/kpis",
16242
- "/targets",
16243
- "/shifts",
16244
- "/supervisor-management",
16245
- "/skus",
16246
- "/help",
16247
- "/health",
16248
- "/profile",
16249
- "/workspace",
16250
- "/factory-view",
16251
- "/team-management"
16252
- ],
16253
- supervisor: [
16254
- "/",
16255
- "/leaderboard",
16256
- "/kpis",
16257
- "/targets",
16258
- "/shifts",
16259
- "/skus",
16260
- "/help",
16261
- "/health",
16262
- "/profile",
16263
- "/workspace"
16264
- ]
16265
- };
16266
16407
  const accessiblePages = useMemo(() => {
16267
16408
  if (!userRole) return [];
16268
- return roleAccessMap[userRole] || [];
16409
+ return getRoleNavPaths(userRole);
16269
16410
  }, [userRole]);
16270
16411
  const hasAccess = useMemo(() => {
16271
16412
  return (path) => {
@@ -16315,111 +16456,50 @@ function useTeamManagementPermissions() {
16315
16456
  * Can the current user assign lines to this user?
16316
16457
  */
16317
16458
  canAssignLines: (targetUser) => {
16318
- if (!currentRole) return false;
16319
- if (currentRole === "optifye") return true;
16320
- if ((currentRole === "owner" || currentRole === "it") && targetUser.role_level === "supervisor") {
16321
- return true;
16322
- }
16323
- if (currentRole === "plant_head" && targetUser.role_level === "supervisor") {
16324
- return true;
16325
- }
16326
- return false;
16459
+ return canRoleAssignLines(currentRole, targetUser.role_level);
16327
16460
  },
16328
16461
  /**
16329
16462
  * Can the current user assign factories to this user?
16330
16463
  */
16331
16464
  canAssignFactories: (targetUser) => {
16332
- if (!currentRole) return false;
16333
- if (currentRole === "optifye") return true;
16334
- if ((currentRole === "owner" || currentRole === "it") && targetUser.role_level === "plant_head") {
16335
- return true;
16336
- }
16337
- return false;
16465
+ return canRoleAssignFactories(currentRole, targetUser.role_level);
16338
16466
  },
16339
16467
  /**
16340
16468
  * Can the current user change this user's role?
16341
16469
  */
16342
16470
  canChangeRole: (targetUser) => {
16343
- if (!currentRole) return false;
16344
- if (currentRole === "optifye") return true;
16345
- if (currentRole === "owner" || currentRole === "it") {
16346
- return ["plant_head", "supervisor"].includes(targetUser.role_level);
16347
- }
16348
- return false;
16471
+ return canRoleChangeRole(currentRole, targetUser.role_level, { isSuperAdminOptifye });
16349
16472
  },
16350
16473
  /**
16351
16474
  * Can the current user remove this user?
16352
16475
  */
16353
16476
  canRemoveUser: (targetUser) => {
16354
- if (!currentRole) return false;
16355
- if (currentRole === "optifye") return true;
16356
- if (currentRole === "owner" || currentRole === "it") {
16357
- return ["plant_head", "supervisor"].includes(targetUser.role_level);
16358
- }
16359
- return false;
16477
+ return canRoleRemoveUser(currentRole, targetUser.role_level, { isSuperAdminOptifye });
16360
16478
  },
16361
16479
  /**
16362
16480
  * Get list of roles the current user can assign
16363
16481
  * NOTE: Optifye role can ONLY be assigned from database directly, never from frontend
16364
16482
  */
16365
16483
  availableRolesToAssign: () => {
16366
- if (!currentRole) return [];
16367
- if (currentRole === "optifye") {
16368
- if (isSuperAdminOptifye) {
16369
- return ["owner", "it", "plant_head", "supervisor"];
16370
- }
16371
- return ["it", "plant_head", "supervisor"];
16372
- }
16373
- if (currentRole === "owner") {
16374
- return ["it", "plant_head", "supervisor"];
16375
- }
16376
- if (currentRole === "it") {
16377
- return ["plant_head", "supervisor"];
16378
- }
16379
- if (currentRole === "plant_head") {
16380
- return ["supervisor"];
16381
- }
16382
- return [];
16484
+ return getAssignableRoles(currentRole, { isSuperAdminOptifye });
16383
16485
  },
16384
16486
  /**
16385
16487
  * Can the current user invite someone with this role?
16386
16488
  */
16387
16489
  canInviteRole: (role) => {
16388
- if (!currentRole) return false;
16389
- if (currentRole === "optifye") {
16390
- if (role === "owner") {
16391
- return isSuperAdminOptifye;
16392
- }
16393
- return true;
16394
- }
16395
- if (currentRole === "owner") {
16396
- return ["it", "plant_head", "supervisor"].includes(role);
16397
- }
16398
- if (currentRole === "it") {
16399
- return ["plant_head", "supervisor"].includes(role);
16400
- }
16401
- if (currentRole === "plant_head") {
16402
- return role === "supervisor";
16403
- }
16404
- return false;
16490
+ return canRoleInviteRole(currentRole, role, { isSuperAdminOptifye });
16405
16491
  },
16406
16492
  /**
16407
16493
  * Get the name of the assignment column for a user
16408
16494
  */
16409
16495
  getAssignmentColumnName: (targetUser) => {
16410
- if (targetUser.role_level === "plant_head") {
16411
- return "Factories";
16412
- }
16413
- if (targetUser.role_level === "supervisor") {
16414
- return "Lines";
16415
- }
16416
- return "Assignments";
16496
+ return getAssignmentColumnLabel(targetUser.role_level);
16417
16497
  },
16418
16498
  /**
16419
16499
  * Should the assignment column be shown?
16420
16500
  */
16421
16501
  showAssignmentColumn: () => {
16422
- return !!currentRole && ["optifye", "owner", "it", "plant_head"].includes(currentRole);
16502
+ return !!currentRole && (currentRole === "optifye" || currentRole === "owner" || currentRole === "it" || isFactoryScopedRole(currentRole));
16423
16503
  }
16424
16504
  };
16425
16505
  }
@@ -20274,7 +20354,7 @@ var getStoredWorkspaceMappings = () => {
20274
20354
  var getDefaultTabForWorkspace = (workspaceId, displayName) => {
20275
20355
  return "overview";
20276
20356
  };
20277
- var getWorkspaceNavigationParams = (workspaceId, displayName, lineId) => {
20357
+ var getWorkspaceNavigationParams = (workspaceId, displayName, lineId, returnTo) => {
20278
20358
  const defaultTab = getDefaultTabForWorkspace();
20279
20359
  const params = new URLSearchParams();
20280
20360
  params.set("displayName", displayName);
@@ -20282,6 +20362,9 @@ var getWorkspaceNavigationParams = (workspaceId, displayName, lineId) => {
20282
20362
  if (lineId) {
20283
20363
  params.set("lineId", lineId);
20284
20364
  }
20365
+ if (returnTo) {
20366
+ params.set("returnTo", returnTo);
20367
+ }
20285
20368
  return `?${params.toString()}`;
20286
20369
  };
20287
20370
 
@@ -20577,14 +20660,18 @@ var formatIdleTime = (idleTimeInSeconds) => {
20577
20660
  if (!idleTimeInSeconds || idleTimeInSeconds <= 0) {
20578
20661
  return "0s";
20579
20662
  }
20580
- const hours = Math.floor(idleTimeInSeconds / 3600);
20663
+ const days = Math.floor(idleTimeInSeconds / 86400);
20664
+ const hours = Math.floor(idleTimeInSeconds % 86400 / 3600);
20581
20665
  const minutes = Math.floor(idleTimeInSeconds % 3600 / 60);
20582
20666
  const seconds = Math.floor(idleTimeInSeconds % 60);
20583
20667
  const parts = [];
20668
+ if (days > 0) {
20669
+ parts.push(`${days}d`);
20670
+ }
20584
20671
  if (hours > 0) {
20585
20672
  parts.push(`${hours}h`);
20586
20673
  }
20587
- if (minutes > 0 || hours > 0) {
20674
+ if (minutes > 0 || hours > 0 || days > 0) {
20588
20675
  parts.push(`${minutes}m`);
20589
20676
  }
20590
20677
  parts.push(`${seconds}s`);
@@ -20631,7 +20718,7 @@ var MotionConfigContext = createContext({
20631
20718
  });
20632
20719
 
20633
20720
  // ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PopChild.mjs
20634
- var PopChildMeasure = class extends React26.Component {
20721
+ var PopChildMeasure = class extends React141.Component {
20635
20722
  getSnapshotBeforeUpdate(prevProps) {
20636
20723
  const element = this.props.childRef.current;
20637
20724
  if (element && prevProps.isPresent && !this.props.isPresent) {
@@ -20686,7 +20773,7 @@ function PopChild({ children, isPresent }) {
20686
20773
  document.head.removeChild(style);
20687
20774
  };
20688
20775
  }, [isPresent]);
20689
- return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React26.cloneElement(children, { ref }) });
20776
+ return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React141.cloneElement(children, { ref }) });
20690
20777
  }
20691
20778
 
20692
20779
  // ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PresenceChild.mjs
@@ -20723,7 +20810,7 @@ var PresenceChild = ({ children, initial, isPresent, onExitComplete, custom, pre
20723
20810
  useMemo(() => {
20724
20811
  presenceChildren.forEach((_, key) => presenceChildren.set(key, false));
20725
20812
  }, [isPresent]);
20726
- React26.useEffect(() => {
20813
+ React141.useEffect(() => {
20727
20814
  !isPresent && !presenceChildren.size && onExitComplete && onExitComplete();
20728
20815
  }, [isPresent]);
20729
20816
  if (mode === "popLayout") {
@@ -28557,12 +28644,12 @@ var withAuth = (WrappedComponent2, options) => {
28557
28644
  requireAuth: true,
28558
28645
  ...options
28559
28646
  };
28560
- const WithAuthComponent = React26.memo(function WithAuthComponent2(props) {
28647
+ const WithAuthComponent = React141.memo(function WithAuthComponent2(props) {
28561
28648
  const { session, loading, error } = useAuth();
28562
28649
  const router = useRouter();
28563
- const [localLoading, setLocalLoading] = React26.useState(loading);
28564
- const [loadingTimeoutReached, setLoadingTimeoutReached] = React26.useState(false);
28565
- React26.useEffect(() => {
28650
+ const [localLoading, setLocalLoading] = React141.useState(loading);
28651
+ const [loadingTimeoutReached, setLoadingTimeoutReached] = React141.useState(false);
28652
+ React141.useEffect(() => {
28566
28653
  if (process.env.NODE_ENV === "development" && process.env.DEBUG_AUTH === "true") {
28567
28654
  console.log("withAuth state:", {
28568
28655
  loading,
@@ -28572,7 +28659,7 @@ var withAuth = (WrappedComponent2, options) => {
28572
28659
  });
28573
28660
  }
28574
28661
  }, [session, loading, error]);
28575
- const handleLoadingTimeout = React26.useCallback(() => {
28662
+ const handleLoadingTimeout = React141.useCallback(() => {
28576
28663
  console.warn("[withAuth] Loading timeout reached");
28577
28664
  setLoadingTimeoutReached(true);
28578
28665
  if (typeof window !== "undefined" && localStorage.getItem("sb-zmzewpwerpaupoaoeqhh-auth-token")) {
@@ -28583,13 +28670,13 @@ var withAuth = (WrappedComponent2, options) => {
28583
28670
  router.replace(defaultOptions.redirectTo);
28584
28671
  }
28585
28672
  }, [router]);
28586
- React26.useEffect(() => {
28673
+ React141.useEffect(() => {
28587
28674
  if (!loading && defaultOptions.requireAuth && !session && !error) {
28588
28675
  console.log("[withAuth] No session found, redirecting to login");
28589
28676
  router.replace(defaultOptions.redirectTo);
28590
28677
  }
28591
28678
  }, [session, loading, router, error]);
28592
- React26.useEffect(() => {
28679
+ React141.useEffect(() => {
28593
28680
  setLocalLoading(loading);
28594
28681
  }, [loading]);
28595
28682
  if (loading || localLoading) {
@@ -28652,18 +28739,11 @@ function withAccessControl(WrappedComponent2, options = {}) {
28652
28739
  if (keyIndex >= 0 && keyIndex < segments.length - 1) return segments[keyIndex + 1];
28653
28740
  return null;
28654
28741
  };
28655
- const roleAccessMap = {
28656
- optifye: ["/", "/leaderboard", "/kpis", "/targets", "/shifts", "/supervisor-management", "/skus", "/help", "/health", "/profile", "/workspace", "/factory-view", "/team-management", "/improvement-center", "/tickets"],
28657
- owner: ["/", "/leaderboard", "/kpis", "/targets", "/shifts", "/supervisor-management", "/skus", "/help", "/health", "/profile", "/workspace", "/factory-view", "/team-management", "/improvement-center", "/tickets"],
28658
- it: ["/", "/leaderboard", "/kpis", "/targets", "/shifts", "/supervisor-management", "/skus", "/help", "/health", "/profile", "/workspace", "/factory-view", "/team-management", "/improvement-center", "/tickets"],
28659
- plant_head: ["/", "/leaderboard", "/kpis", "/targets", "/shifts", "/supervisor-management", "/skus", "/help", "/health", "/profile", "/workspace", "/factory-view", "/team-management", "/improvement-center", "/tickets"],
28660
- supervisor: ["/", "/leaderboard", "/kpis", "/targets", "/shifts", "/skus", "/help", "/health", "/profile", "/workspace", "/improvement-center", "/tickets"]
28661
- };
28662
28742
  const canAccessPath = (path) => {
28663
28743
  if (!user || !role) return false;
28664
28744
  if (isSuperAdmin) return true;
28665
28745
  const basePath = getBasePath(path);
28666
- const allowed = roleAccessMap[role] || [];
28746
+ const allowed = getRoleNavPaths(role);
28667
28747
  if (!allowed.includes(basePath)) {
28668
28748
  return false;
28669
28749
  }
@@ -29064,8 +29144,8 @@ function getRoleConfig(role) {
29064
29144
  switch (role) {
29065
29145
  case "optifye":
29066
29146
  return {
29067
- label: "Optifye",
29068
- description: "Full platform access - Optifye team member",
29147
+ label: getRoleLabel(role),
29148
+ description: getRoleDescription(role),
29069
29149
  icon: Star,
29070
29150
  bgColor: "bg-gradient-to-r from-purple-50 to-pink-50",
29071
29151
  textColor: "text-purple-700",
@@ -29073,8 +29153,8 @@ function getRoleConfig(role) {
29073
29153
  };
29074
29154
  case "owner":
29075
29155
  return {
29076
- label: "Owner",
29077
- description: "Company-wide access - Can manage all users and settings",
29156
+ label: getRoleLabel(role),
29157
+ description: getRoleDescription(role),
29078
29158
  icon: Shield,
29079
29159
  bgColor: "bg-blue-50",
29080
29160
  textColor: "text-blue-700",
@@ -29082,8 +29162,8 @@ function getRoleConfig(role) {
29082
29162
  };
29083
29163
  case "it":
29084
29164
  return {
29085
- label: "IT",
29086
- description: "Company-wide access - IT personnel with full company access",
29165
+ label: getRoleLabel(role),
29166
+ description: getRoleDescription(role),
29087
29167
  icon: Wrench,
29088
29168
  bgColor: "bg-teal-50",
29089
29169
  textColor: "text-teal-700",
@@ -29091,17 +29171,26 @@ function getRoleConfig(role) {
29091
29171
  };
29092
29172
  case "plant_head":
29093
29173
  return {
29094
- label: "Plant Head",
29095
- description: "Factory-level access - Can manage supervisors and factory settings",
29174
+ label: getRoleLabel(role),
29175
+ description: getRoleDescription(role),
29096
29176
  icon: Users,
29097
29177
  bgColor: "bg-blue-50",
29098
29178
  textColor: "text-blue-700",
29099
29179
  borderColor: "border-blue-200"
29100
29180
  };
29181
+ case "industrial_engineer":
29182
+ return {
29183
+ label: getRoleLabel(role),
29184
+ description: getRoleDescription(role),
29185
+ icon: Users,
29186
+ bgColor: "bg-amber-50",
29187
+ textColor: "text-amber-700",
29188
+ borderColor: "border-amber-200"
29189
+ };
29101
29190
  case "supervisor":
29102
29191
  return {
29103
- label: "Supervisor",
29104
- description: "Line-level access - Can monitor assigned production lines",
29192
+ label: getRoleLabel(role),
29193
+ description: getRoleDescription(role),
29105
29194
  icon: User,
29106
29195
  bgColor: "bg-blue-50",
29107
29196
  textColor: "text-blue-700",
@@ -29209,7 +29298,7 @@ var SignupWithInvitation = ({
29209
29298
  if (invitation.line_ids && invitation.line_ids.length > 0) {
29210
29299
  properties.line_id = invitation.line_ids;
29211
29300
  }
29212
- } else if (invitation.role_level === "plant_head") {
29301
+ } else if (invitation.role_level === "plant_head" || invitation.role_level === "industrial_engineer") {
29213
29302
  properties.access_level = "factory";
29214
29303
  if (invitation.factory_ids && invitation.factory_ids.length > 0) {
29215
29304
  properties.factory_ids = invitation.factory_ids;
@@ -29300,7 +29389,7 @@ var SignupWithInvitation = ({
29300
29389
  ] })
29301
29390
  ] })
29302
29391
  ] }),
29303
- invitation.role_level === "plant_head" && invitation.factory_ids && invitation.factory_ids.length > 0 && /* @__PURE__ */ jsxs("div", { className: "md:col-span-2", children: [
29392
+ (invitation.role_level === "plant_head" || invitation.role_level === "industrial_engineer") && invitation.factory_ids && invitation.factory_ids.length > 0 && /* @__PURE__ */ jsxs("div", { className: "md:col-span-2", children: [
29304
29393
  /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600 mb-1", children: "Assigned Factories" }),
29305
29394
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
29306
29395
  /* @__PURE__ */ jsx(Building2, { className: "w-4 h-4 text-indigo-600" }),
@@ -29522,11 +29611,11 @@ var BarChartComponent = ({
29522
29611
  aspect = 2,
29523
29612
  ...restOfChartProps
29524
29613
  }) => {
29525
- const containerRef = React26__default.useRef(null);
29526
- const [containerReady, setContainerReady] = React26__default.useState(false);
29614
+ const containerRef = React141__default.useRef(null);
29615
+ const [containerReady, setContainerReady] = React141__default.useState(false);
29527
29616
  const themeConfig = useThemeConfig();
29528
29617
  const { formatNumber } = useFormatNumber();
29529
- React26__default.useEffect(() => {
29618
+ React141__default.useEffect(() => {
29530
29619
  const checkContainerDimensions = () => {
29531
29620
  if (containerRef.current) {
29532
29621
  const rect = containerRef.current.getBoundingClientRect();
@@ -29640,7 +29729,7 @@ var BarChartComponent = ({
29640
29729
  }
29641
29730
  return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: chartContent });
29642
29731
  };
29643
- var BarChart = React26__default.memo(BarChartComponent, (prevProps, nextProps) => {
29732
+ var BarChart = React141__default.memo(BarChartComponent, (prevProps, nextProps) => {
29644
29733
  if (prevProps.xAxisDataKey !== nextProps.xAxisDataKey || prevProps.xAxisLabel !== nextProps.xAxisLabel || prevProps.yAxisLabel !== nextProps.yAxisLabel || prevProps.yAxisUnit !== nextProps.yAxisUnit || JSON.stringify(prevProps.referenceLines || []) !== JSON.stringify(nextProps.referenceLines || []) || prevProps.layout !== nextProps.layout || prevProps.className !== nextProps.className || prevProps.showGrid !== nextProps.showGrid || prevProps.showLegend !== nextProps.showLegend || prevProps.showTooltip !== nextProps.showTooltip || prevProps.responsive !== nextProps.responsive || prevProps.aspect !== nextProps.aspect) {
29645
29734
  return false;
29646
29735
  }
@@ -29686,13 +29775,14 @@ var LineChartComponent = ({
29686
29775
  showTooltip = true,
29687
29776
  responsive = true,
29688
29777
  aspect = 2,
29778
+ fillContainer = false,
29689
29779
  ...restOfChartProps
29690
29780
  }) => {
29691
- const containerRef = React26__default.useRef(null);
29692
- const [containerReady, setContainerReady] = React26__default.useState(false);
29781
+ const containerRef = React141__default.useRef(null);
29782
+ const [containerReady, setContainerReady] = React141__default.useState(false);
29693
29783
  const themeConfig = useThemeConfig();
29694
29784
  const { formatNumber } = useFormatNumber();
29695
- React26__default.useEffect(() => {
29785
+ React141__default.useEffect(() => {
29696
29786
  const checkContainerDimensions = () => {
29697
29787
  if (containerRef.current) {
29698
29788
  const rect = containerRef.current.getBoundingClientRect();
@@ -29720,8 +29810,8 @@ var LineChartComponent = ({
29720
29810
  const defaultTooltipFormatter = (value, name, props) => {
29721
29811
  const formattedValue = typeof value === "number" ? formatNumber(value) : value;
29722
29812
  return [
29723
- /* @__PURE__ */ jsx("span", { children: `${formattedValue}${yAxisUnit || ""}` }, `tt-val-${name}-${value}`),
29724
- name
29813
+ /* @__PURE__ */ jsx("span", { className: "text-gray-900", children: `${formattedValue}${yAxisUnit || ""}` }, `tt-val-${name}-${value}`),
29814
+ /* @__PURE__ */ jsx("span", { className: "text-gray-500", children: name }, `tt-name-${name}`)
29725
29815
  ];
29726
29816
  };
29727
29817
  const defaultColors = [
@@ -29757,7 +29847,7 @@ var LineChartComponent = ({
29757
29847
  stroke: axisStrokeColor
29758
29848
  }
29759
29849
  ),
29760
- showTooltip && /* @__PURE__ */ jsx(Tooltip, { formatter: tooltipFormatter || defaultTooltipFormatter, cursor: { strokeDasharray: "3 3" } }),
29850
+ showTooltip && /* @__PURE__ */ jsx(Tooltip, { formatter: tooltipFormatter || defaultTooltipFormatter, itemStyle: { color: "#111827" }, cursor: { strokeDasharray: "3 3" } }),
29761
29851
  showLegend && /* @__PURE__ */ jsx(Legend, { payload: legendPayload }),
29762
29852
  lines.map((lineConfig, index) => {
29763
29853
  const lineProps = {
@@ -29783,15 +29873,15 @@ var LineChartComponent = ({
29783
29873
  "div",
29784
29874
  {
29785
29875
  ref: containerRef,
29786
- className: clsx("w-full h-auto", className),
29787
- style: { aspectRatio: `${aspect}/1`, minHeight: "50px", minWidth: "100px" },
29876
+ className: clsx(fillContainer ? "w-full h-full" : "w-full h-auto", className),
29877
+ style: fillContainer ? { height: "100%", minHeight: "50px", minWidth: "100px" } : { aspectRatio: `${aspect}/1`, minHeight: "50px", minWidth: "100px" },
29788
29878
  children: containerReady ? /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: chartContent }) : /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center bg-gray-50 rounded-lg", children: /* @__PURE__ */ jsx("div", { className: "text-gray-500 text-sm", children: "Loading chart..." }) })
29789
29879
  }
29790
29880
  );
29791
29881
  }
29792
29882
  return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: chartContent });
29793
29883
  };
29794
- var LineChart = React26__default.memo(LineChartComponent, (prevProps, nextProps) => {
29884
+ var LineChart = React141__default.memo(LineChartComponent, (prevProps, nextProps) => {
29795
29885
  if (prevProps.xAxisDataKey !== nextProps.xAxisDataKey || prevProps.xAxisLabel !== nextProps.xAxisLabel || prevProps.yAxisLabel !== nextProps.yAxisLabel || prevProps.yAxisUnit !== nextProps.yAxisUnit || prevProps.className !== nextProps.className || prevProps.showGrid !== nextProps.showGrid || prevProps.showLegend !== nextProps.showLegend || prevProps.showTooltip !== nextProps.showTooltip || prevProps.responsive !== nextProps.responsive || prevProps.aspect !== nextProps.aspect || JSON.stringify(prevProps.yAxisDomain) !== JSON.stringify(nextProps.yAxisDomain)) {
29796
29886
  return false;
29797
29887
  }
@@ -29885,7 +29975,7 @@ var OutputProgressChartComponent = ({
29885
29975
  ] }) })
29886
29976
  ] }) });
29887
29977
  };
29888
- var OutputProgressChart = React26__default.memo(OutputProgressChartComponent);
29978
+ var OutputProgressChart = React141__default.memo(OutputProgressChartComponent);
29889
29979
  OutputProgressChart.displayName = "OutputProgressChart";
29890
29980
  var LargeOutputProgressChart = ({
29891
29981
  currentOutput,
@@ -30025,7 +30115,7 @@ var CycleTimeChartComponent = ({
30025
30115
  }
30026
30116
  ) }) });
30027
30117
  };
30028
- var CycleTimeChart = React26__default.memo(CycleTimeChartComponent, (prevProps, nextProps) => {
30118
+ var CycleTimeChart = React141__default.memo(CycleTimeChartComponent, (prevProps, nextProps) => {
30029
30119
  if (prevProps.className !== nextProps.className) {
30030
30120
  return false;
30031
30121
  }
@@ -30051,8 +30141,8 @@ var CycleTimeOverTimeChart = ({
30051
30141
  className = ""
30052
30142
  }) => {
30053
30143
  const MAX_DATA_POINTS = 40;
30054
- const containerRef = React26__default.useRef(null);
30055
- const [containerReady, setContainerReady] = React26__default.useState(false);
30144
+ const containerRef = React141__default.useRef(null);
30145
+ const [containerReady, setContainerReady] = React141__default.useState(false);
30056
30146
  const getHourFromTimeString = (timeStr) => {
30057
30147
  const [hours, minutes] = timeStr.split(":");
30058
30148
  return parseInt(hours);
@@ -30063,10 +30153,10 @@ var CycleTimeOverTimeChart = ({
30063
30153
  };
30064
30154
  const displayData = getDisplayData(data);
30065
30155
  const DURATION = displayData.length;
30066
- const [animatedData, setAnimatedData] = React26__default.useState(Array(DURATION).fill(0));
30067
- const prevDataRef = React26__default.useRef(Array(DURATION).fill(0));
30068
- const animationFrameRef = React26__default.useRef(null);
30069
- const animateToNewData = React26__default.useCallback((targetData) => {
30156
+ const [animatedData, setAnimatedData] = React141__default.useState(Array(DURATION).fill(0));
30157
+ const prevDataRef = React141__default.useRef(Array(DURATION).fill(0));
30158
+ const animationFrameRef = React141__default.useRef(null);
30159
+ const animateToNewData = React141__default.useCallback((targetData) => {
30070
30160
  const startData = [...prevDataRef.current];
30071
30161
  const startTime = performance.now();
30072
30162
  const duration = 1200;
@@ -30096,7 +30186,7 @@ var CycleTimeOverTimeChart = ({
30096
30186
  }
30097
30187
  animationFrameRef.current = requestAnimationFrame(animate);
30098
30188
  }, []);
30099
- React26__default.useEffect(() => {
30189
+ React141__default.useEffect(() => {
30100
30190
  if (JSON.stringify(data) !== JSON.stringify(prevDataRef.current)) {
30101
30191
  const processedData = getDisplayData(data);
30102
30192
  animateToNewData(processedData);
@@ -30107,7 +30197,7 @@ var CycleTimeOverTimeChart = ({
30107
30197
  }
30108
30198
  };
30109
30199
  }, [data, animateToNewData]);
30110
- React26__default.useEffect(() => {
30200
+ React141__default.useEffect(() => {
30111
30201
  const checkContainerDimensions = () => {
30112
30202
  if (containerRef.current) {
30113
30203
  const rect = containerRef.current.getBoundingClientRect();
@@ -30350,7 +30440,7 @@ var CycleTimeOverTimeChart = ({
30350
30440
  }
30351
30441
  );
30352
30442
  };
30353
- var Card = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
30443
+ var Card = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
30354
30444
  "div",
30355
30445
  {
30356
30446
  ref,
@@ -30362,7 +30452,7 @@ var Card = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
30362
30452
  }
30363
30453
  ));
30364
30454
  Card.displayName = "Card";
30365
- var CardHeader = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
30455
+ var CardHeader = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
30366
30456
  "div",
30367
30457
  {
30368
30458
  ref,
@@ -30371,7 +30461,7 @@ var CardHeader = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE
30371
30461
  }
30372
30462
  ));
30373
30463
  CardHeader.displayName = "CardHeader";
30374
- var CardTitle = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
30464
+ var CardTitle = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
30375
30465
  "h3",
30376
30466
  {
30377
30467
  ref,
@@ -30383,7 +30473,7 @@ var CardTitle = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE_
30383
30473
  }
30384
30474
  ));
30385
30475
  CardTitle.displayName = "CardTitle";
30386
- var CardDescription = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
30476
+ var CardDescription = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
30387
30477
  "p",
30388
30478
  {
30389
30479
  ref,
@@ -30392,9 +30482,9 @@ var CardDescription = React26.forwardRef(({ className, ...props }, ref) => /* @_
30392
30482
  }
30393
30483
  ));
30394
30484
  CardDescription.displayName = "CardDescription";
30395
- var CardContent = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
30485
+ var CardContent = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
30396
30486
  CardContent.displayName = "CardContent";
30397
- var CardFooter = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
30487
+ var CardFooter = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
30398
30488
  "div",
30399
30489
  {
30400
30490
  ref,
@@ -30470,7 +30560,7 @@ var buttonVariants = cva(
30470
30560
  }
30471
30561
  }
30472
30562
  );
30473
- var Button = React26.forwardRef(
30563
+ var Button = React141.forwardRef(
30474
30564
  ({ className, variant, size, asChild = false, ...props }, ref) => {
30475
30565
  const Comp = asChild ? Slot : "button";
30476
30566
  return /* @__PURE__ */ jsx(
@@ -30497,9 +30587,9 @@ var HourlyOutputChartComponent = ({
30497
30587
  timezone,
30498
30588
  className = ""
30499
30589
  }) => {
30500
- const containerRef = React26__default.useRef(null);
30501
- const [containerReady, setContainerReady] = React26__default.useState(false);
30502
- const [containerWidth, setContainerWidth] = React26__default.useState(0);
30590
+ const containerRef = React141__default.useRef(null);
30591
+ const [containerReady, setContainerReady] = React141__default.useState(false);
30592
+ const [containerWidth, setContainerWidth] = React141__default.useState(0);
30503
30593
  const getTimeFromTimeString2 = (timeStr) => {
30504
30594
  const [hours, minutes] = timeStr.split(":");
30505
30595
  const hour = parseInt(hours);
@@ -30508,13 +30598,13 @@ var HourlyOutputChartComponent = ({
30508
30598
  return { hour, minute, decimalHour };
30509
30599
  };
30510
30600
  const shiftStartTime = getTimeFromTimeString2(shiftStart);
30511
- React26__default.useMemo(() => {
30601
+ React141__default.useMemo(() => {
30512
30602
  if (!shiftDate || !timezone) return null;
30513
30603
  const hour = shiftStartTime.hour.toString().padStart(2, "0");
30514
30604
  const minute = shiftStartTime.minute.toString().padStart(2, "0");
30515
30605
  return fromZonedTime(`${shiftDate}T${hour}:${minute}:00`, timezone);
30516
30606
  }, [shiftDate, timezone, shiftStartTime.hour, shiftStartTime.minute]);
30517
- const idleClipRanges = React26__default.useMemo(() => {
30607
+ const idleClipRanges = React141__default.useMemo(() => {
30518
30608
  if (!idleTimeClips || idleTimeClips.length === 0) return [];
30519
30609
  return idleTimeClips.map((clip) => ({
30520
30610
  id: clip.id,
@@ -30522,7 +30612,7 @@ var HourlyOutputChartComponent = ({
30522
30612
  end: clip.idle_end_time ? new Date(clip.idle_end_time) : null
30523
30613
  })).filter((clip) => clip.start && clip.end);
30524
30614
  }, [idleTimeClips]);
30525
- React26__default.useCallback((rangeStart, rangeEnd) => {
30615
+ React141__default.useCallback((rangeStart, rangeEnd) => {
30526
30616
  if (!rangeStart || !rangeEnd || idleClipRanges.length === 0) {
30527
30617
  return "Reason unavailable";
30528
30618
  }
@@ -30539,7 +30629,7 @@ var HourlyOutputChartComponent = ({
30539
30629
  }
30540
30630
  return classification.label.replace(/_/g, " ");
30541
30631
  }, [idleClipRanges, idleTimeClipClassifications]);
30542
- const { shiftDuration, shiftEndTime, hasPartialLastHour } = React26__default.useMemo(() => {
30632
+ const { shiftDuration, shiftEndTime, hasPartialLastHour } = React141__default.useMemo(() => {
30543
30633
  console.log("[HourlyOutputChart] Calculating shift duration with:", {
30544
30634
  shiftStart,
30545
30635
  shiftEnd,
@@ -30574,12 +30664,12 @@ var HourlyOutputChartComponent = ({
30574
30664
  }, [shiftEnd, shiftStartTime.decimalHour]);
30575
30665
  const SHIFT_DURATION = shiftDuration;
30576
30666
  shiftEndTime ? shiftEndTime.hour : (shiftStartTime.hour + SHIFT_DURATION) % 24;
30577
- const [animatedData, setAnimatedData] = React26__default.useState(
30667
+ const [animatedData, setAnimatedData] = React141__default.useState(
30578
30668
  () => Array(SHIFT_DURATION).fill(0)
30579
30669
  );
30580
- const prevDataRef = React26__default.useRef(Array(SHIFT_DURATION).fill(0));
30581
- const animationFrameRef = React26__default.useRef(null);
30582
- React26__default.useEffect(() => {
30670
+ const prevDataRef = React141__default.useRef(Array(SHIFT_DURATION).fill(0));
30671
+ const animationFrameRef = React141__default.useRef(null);
30672
+ React141__default.useEffect(() => {
30583
30673
  setAnimatedData((prev) => {
30584
30674
  if (prev.length !== SHIFT_DURATION) {
30585
30675
  return Array(SHIFT_DURATION).fill(0);
@@ -30588,14 +30678,14 @@ var HourlyOutputChartComponent = ({
30588
30678
  });
30589
30679
  prevDataRef.current = Array(SHIFT_DURATION).fill(0);
30590
30680
  }, [SHIFT_DURATION]);
30591
- const [idleBarState, setIdleBarState] = React26__default.useState({
30681
+ const [idleBarState, setIdleBarState] = React141__default.useState({
30592
30682
  visible: showIdleTime,
30593
30683
  key: 0,
30594
30684
  shouldAnimate: false
30595
30685
  });
30596
- const prevShowIdleTimeRef = React26__default.useRef(showIdleTime);
30597
- const stateUpdateTimeoutRef = React26__default.useRef(null);
30598
- React26__default.useEffect(() => {
30686
+ const prevShowIdleTimeRef = React141__default.useRef(showIdleTime);
30687
+ const stateUpdateTimeoutRef = React141__default.useRef(null);
30688
+ React141__default.useEffect(() => {
30599
30689
  if (stateUpdateTimeoutRef.current) {
30600
30690
  clearTimeout(stateUpdateTimeoutRef.current);
30601
30691
  }
@@ -30620,7 +30710,7 @@ var HourlyOutputChartComponent = ({
30620
30710
  }
30621
30711
  };
30622
30712
  }, [showIdleTime]);
30623
- const animateToNewData = React26__default.useCallback((targetData) => {
30713
+ const animateToNewData = React141__default.useCallback((targetData) => {
30624
30714
  const startData = [...prevDataRef.current];
30625
30715
  const startTime = performance.now();
30626
30716
  const duration = 1200;
@@ -30650,7 +30740,7 @@ var HourlyOutputChartComponent = ({
30650
30740
  }
30651
30741
  animationFrameRef.current = requestAnimationFrame(animate);
30652
30742
  }, []);
30653
- React26__default.useEffect(() => {
30743
+ React141__default.useEffect(() => {
30654
30744
  if (JSON.stringify(data) !== JSON.stringify(prevDataRef.current)) {
30655
30745
  const shiftData = data.slice(0, SHIFT_DURATION);
30656
30746
  animateToNewData(shiftData);
@@ -30661,7 +30751,7 @@ var HourlyOutputChartComponent = ({
30661
30751
  }
30662
30752
  };
30663
30753
  }, [data, animateToNewData]);
30664
- React26__default.useEffect(() => {
30754
+ React141__default.useEffect(() => {
30665
30755
  const checkContainerDimensions = () => {
30666
30756
  if (containerRef.current) {
30667
30757
  const rect = containerRef.current.getBoundingClientRect();
@@ -30687,7 +30777,7 @@ var HourlyOutputChartComponent = ({
30687
30777
  clearTimeout(fallbackTimeout);
30688
30778
  };
30689
30779
  }, []);
30690
- const xAxisConfig = React26__default.useMemo(() => {
30780
+ const xAxisConfig = React141__default.useMemo(() => {
30691
30781
  if (containerWidth >= 960) {
30692
30782
  return { interval: 0, angle: -45, height: 92, tickFont: 10, tickMargin: 12 };
30693
30783
  }
@@ -30696,7 +30786,7 @@ var HourlyOutputChartComponent = ({
30696
30786
  }
30697
30787
  return { interval: 0, angle: -30, height: 64, tickFont: 9, tickMargin: 6 };
30698
30788
  }, [containerWidth]);
30699
- const formatHour = React26__default.useCallback((hourIndex) => {
30789
+ const formatHour = React141__default.useCallback((hourIndex) => {
30700
30790
  const isLastHour = hourIndex === SHIFT_DURATION - 1;
30701
30791
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
30702
30792
  const startHour = Math.floor(startDecimalHour) % 24;
@@ -30720,7 +30810,7 @@ var HourlyOutputChartComponent = ({
30720
30810
  };
30721
30811
  return `${formatTime5(startHour, startMinute)}-${formatTime5(endHour, endMinute)}`;
30722
30812
  }, [shiftStartTime.decimalHour, SHIFT_DURATION, shiftEndTime]);
30723
- const formatTimeRange2 = React26__default.useCallback((hourIndex) => {
30813
+ const formatTimeRange2 = React141__default.useCallback((hourIndex) => {
30724
30814
  const isLastHour = hourIndex === SHIFT_DURATION - 1;
30725
30815
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
30726
30816
  const startHour = Math.floor(startDecimalHour) % 24;
@@ -30741,7 +30831,7 @@ var HourlyOutputChartComponent = ({
30741
30831
  };
30742
30832
  return `${formatTime5(startHour, startMinute)} - ${formatTime5(endHour, endMinute)}`;
30743
30833
  }, [shiftStartTime.decimalHour, SHIFT_DURATION, shiftEndTime]);
30744
- const chartData = React26__default.useMemo(() => {
30834
+ const chartData = React141__default.useMemo(() => {
30745
30835
  return Array.from({ length: SHIFT_DURATION }, (_, i) => {
30746
30836
  const actualHour = (shiftStartTime.hour + i) % 24;
30747
30837
  const startMinute = shiftStartTime.minute;
@@ -30811,7 +30901,7 @@ var HourlyOutputChartComponent = ({
30811
30901
  };
30812
30902
  });
30813
30903
  }, [animatedData, data, pphThreshold, idleTimeHourly, shiftStartTime.hour, shiftStartTime.minute, shiftEndTime, formatHour, formatTimeRange2, SHIFT_DURATION]);
30814
- const IdleBar = React26__default.useMemo(() => {
30904
+ const IdleBar = React141__default.useMemo(() => {
30815
30905
  if (!idleBarState.visible) return null;
30816
30906
  return /* @__PURE__ */ jsx(
30817
30907
  Bar,
@@ -31139,7 +31229,7 @@ var HourlyOutputChartComponent = ({
31139
31229
  }
31140
31230
  );
31141
31231
  };
31142
- var HourlyOutputChart = React26__default.memo(HourlyOutputChartComponent, (prevProps, nextProps) => {
31232
+ var HourlyOutputChart = React141__default.memo(HourlyOutputChartComponent, (prevProps, nextProps) => {
31143
31233
  if (prevProps.pphThreshold !== nextProps.pphThreshold || prevProps.shiftStart !== nextProps.shiftStart || prevProps.shiftEnd !== nextProps.shiftEnd || prevProps.shiftDate !== nextProps.shiftDate || prevProps.timezone !== nextProps.timezone || prevProps.showIdleTime !== nextProps.showIdleTime || prevProps.className !== nextProps.className) {
31144
31234
  return false;
31145
31235
  }
@@ -31202,7 +31292,7 @@ function getTrendArrowAndColor(trend) {
31202
31292
  return { arrow: "\u2192", color: "text-gray-400" };
31203
31293
  }
31204
31294
  }
31205
- var VideoCard = React26__default.memo(({
31295
+ var VideoCard = React141__default.memo(({
31206
31296
  workspace,
31207
31297
  hlsUrl,
31208
31298
  shouldPlay,
@@ -31382,7 +31472,7 @@ var logDebug2 = (...args) => {
31382
31472
  if (!DEBUG_DASHBOARD_LOGS2) return;
31383
31473
  console.log(...args);
31384
31474
  };
31385
- var VideoGridView = React26__default.memo(({
31475
+ var VideoGridView = React141__default.memo(({
31386
31476
  workspaces,
31387
31477
  selectedLine,
31388
31478
  className = "",
@@ -31619,7 +31709,8 @@ var VideoGridView = React26__default.memo(({
31619
31709
  action_count: workspace.action_count
31620
31710
  });
31621
31711
  const displayName = getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
31622
- const navParams = getWorkspaceNavigationParams(workspaceId, displayName, workspace.line_id);
31712
+ const currentPath = (router.asPath || "/").split("#")[0];
31713
+ const navParams = getWorkspaceNavigationParams(workspaceId, displayName, workspace.line_id, currentPath);
31623
31714
  router.push(`/workspace/${workspaceId}${navParams}`);
31624
31715
  }, [router, prewarmClipsInit]);
31625
31716
  const handleStreamError = useCallback((workspaceId, options) => {
@@ -31751,7 +31842,7 @@ var VideoGridView = React26__default.memo(({
31751
31842
  ) }) });
31752
31843
  });
31753
31844
  VideoGridView.displayName = "VideoGridView";
31754
- var MapGridView = React26__default.memo(({
31845
+ var MapGridView = React141__default.memo(({
31755
31846
  workspaces,
31756
31847
  className = "",
31757
31848
  displayNames = {},
@@ -31826,7 +31917,8 @@ var MapGridView = React26__default.memo(({
31826
31917
  });
31827
31918
  const displayName = displayNames[`${workspace.line_id}_${workspace.workspace_name}`] || // Always pass line_id to fallback to ensure correct mapping per line
31828
31919
  getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
31829
- const navParams = getWorkspaceNavigationParams(workspaceId, displayName, workspace.line_id);
31920
+ const currentPath = (router.asPath || "/").split("#")[0];
31921
+ const navParams = getWorkspaceNavigationParams(workspaceId, displayName, workspace.line_id, currentPath);
31830
31922
  router.push(`/workspace/${workspaceId}${navParams}`);
31831
31923
  }, [router, displayNames, prewarmClipsInit]);
31832
31924
  const activePositions = useMemo(() => {
@@ -32572,7 +32664,7 @@ var UptimeLineChartComponent = ({ points, className = "" }) => {
32572
32664
  )
32573
32665
  ] }) }) });
32574
32666
  };
32575
- var UptimeLineChart = React26__default.memo(UptimeLineChartComponent);
32667
+ var UptimeLineChart = React141__default.memo(UptimeLineChartComponent);
32576
32668
  var padTime = (value) => value.toString().padStart(2, "0");
32577
32669
  var parseTime = (timeValue) => {
32578
32670
  if (!timeValue) return null;
@@ -32781,10 +32873,10 @@ var HourlyUptimeChartComponent = ({
32781
32873
  elapsedMinutes,
32782
32874
  className = ""
32783
32875
  }) => {
32784
- const containerRef = React26__default.useRef(null);
32785
- const [containerReady, setContainerReady] = React26__default.useState(false);
32786
- const [containerWidth, setContainerWidth] = React26__default.useState(0);
32787
- const uptimeSeries = React26__default.useMemo(() => buildUptimeSeries({
32876
+ const containerRef = React141__default.useRef(null);
32877
+ const [containerReady, setContainerReady] = React141__default.useState(false);
32878
+ const [containerWidth, setContainerWidth] = React141__default.useState(0);
32879
+ const uptimeSeries = React141__default.useMemo(() => buildUptimeSeries({
32788
32880
  idleTimeHourly,
32789
32881
  shiftStart,
32790
32882
  shiftEnd,
@@ -32793,11 +32885,11 @@ var HourlyUptimeChartComponent = ({
32793
32885
  elapsedMinutes
32794
32886
  }), [idleTimeHourly, shiftStart, shiftEnd, shiftDate, timezone, elapsedMinutes]);
32795
32887
  const hasAggregateData = Boolean(hourlyAggregates && hourlyAggregates.length > 0);
32796
- const shiftStartTime = React26__default.useMemo(
32888
+ const shiftStartTime = React141__default.useMemo(
32797
32889
  () => getTimeFromTimeString(shiftStart),
32798
32890
  [shiftStart]
32799
32891
  );
32800
- const { shiftDuration, shiftEndTime } = React26__default.useMemo(() => {
32892
+ const { shiftDuration, shiftEndTime } = React141__default.useMemo(() => {
32801
32893
  if (!shiftEnd) {
32802
32894
  const fallbackHours = uptimeSeries.shiftMinutes > 0 ? Math.ceil(uptimeSeries.shiftMinutes / 60) : 0;
32803
32895
  return { shiftDuration: fallbackHours, shiftEndTime: null };
@@ -32811,7 +32903,7 @@ var HourlyUptimeChartComponent = ({
32811
32903
  const hourCount = hasPartial ? Math.ceil(duration) : Math.round(duration);
32812
32904
  return { shiftDuration: hourCount, shiftEndTime: endTime };
32813
32905
  }, [shiftEnd, shiftStartTime.decimalHour, uptimeSeries.shiftMinutes]);
32814
- const formatHour = React26__default.useCallback((hourIndex) => {
32906
+ const formatHour = React141__default.useCallback((hourIndex) => {
32815
32907
  const isLastHour = hourIndex === shiftDuration - 1;
32816
32908
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
32817
32909
  const startHour = Math.floor(startDecimalHour) % 24;
@@ -32836,7 +32928,7 @@ var HourlyUptimeChartComponent = ({
32836
32928
  };
32837
32929
  return `${formatTime5(startHour, startMinute)}-${formatTime5(endHour, endMinute)}`;
32838
32930
  }, [shiftDuration, shiftStartTime.decimalHour, shiftEndTime]);
32839
- const formatTimeRange2 = React26__default.useCallback((hourIndex) => {
32931
+ const formatTimeRange2 = React141__default.useCallback((hourIndex) => {
32840
32932
  const isLastHour = hourIndex === shiftDuration - 1;
32841
32933
  const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
32842
32934
  const startHour = Math.floor(startDecimalHour) % 24;
@@ -32858,7 +32950,7 @@ var HourlyUptimeChartComponent = ({
32858
32950
  };
32859
32951
  return `${formatTime5(startHour, startMinute)} - ${formatTime5(endHour, endMinute)}`;
32860
32952
  }, [shiftDuration, shiftStartTime.decimalHour, shiftEndTime]);
32861
- const chartData = React26__default.useMemo(() => {
32953
+ const chartData = React141__default.useMemo(() => {
32862
32954
  if (shiftDuration <= 0) return [];
32863
32955
  if (hasAggregateData) {
32864
32956
  return hourlyAggregates.map((entry, hourIndex) => ({
@@ -32900,7 +32992,7 @@ var HourlyUptimeChartComponent = ({
32900
32992
  }, [hasAggregateData, hourlyAggregates, uptimeSeries.points, uptimeSeries.elapsedMinutes, uptimeSeries.shiftMinutes, shiftDuration, formatHour, formatTimeRange2]);
32901
32993
  const maxYValue = 100;
32902
32994
  const yAxisTicks = [0, 25, 50, 75, 100];
32903
- React26__default.useEffect(() => {
32995
+ React141__default.useEffect(() => {
32904
32996
  const checkContainerDimensions = () => {
32905
32997
  if (containerRef.current) {
32906
32998
  const rect = containerRef.current.getBoundingClientRect();
@@ -32926,7 +33018,7 @@ var HourlyUptimeChartComponent = ({
32926
33018
  clearTimeout(fallbackTimeout);
32927
33019
  };
32928
33020
  }, []);
32929
- const xAxisConfig = React26__default.useMemo(() => {
33021
+ const xAxisConfig = React141__default.useMemo(() => {
32930
33022
  if (containerWidth >= 960) {
32931
33023
  return { interval: 0, angle: -45, height: 92, tickFont: 10, tickMargin: 12, labelMode: "full" };
32932
33024
  }
@@ -32935,7 +33027,7 @@ var HourlyUptimeChartComponent = ({
32935
33027
  }
32936
33028
  return { interval: 0, angle: -30, height: 64, tickFont: 9, tickMargin: 6, labelMode: "start" };
32937
33029
  }, [containerWidth]);
32938
- const formatXAxisTick = React26__default.useCallback((raw) => {
33030
+ const formatXAxisTick = React141__default.useCallback((raw) => {
32939
33031
  const label = typeof raw === "string" ? raw : String(raw);
32940
33032
  if (xAxisConfig.labelMode === "full") return label;
32941
33033
  const parts = label.split("-");
@@ -33141,7 +33233,7 @@ var HourlyUptimeChartComponent = ({
33141
33233
  }
33142
33234
  );
33143
33235
  };
33144
- var HourlyUptimeChart = React26__default.memo(HourlyUptimeChartComponent);
33236
+ var HourlyUptimeChart = React141__default.memo(HourlyUptimeChartComponent);
33145
33237
  var DEFAULT_COLORS2 = ["#00AB45", "#ef4444"];
33146
33238
  var UptimeDonutChartComponent = ({
33147
33239
  data,
@@ -33211,7 +33303,7 @@ var UptimeDonutChartComponent = ({
33211
33303
  ] }) })
33212
33304
  ] }) });
33213
33305
  };
33214
- var UptimeDonutChart = React26__default.memo(UptimeDonutChartComponent);
33306
+ var UptimeDonutChart = React141__default.memo(UptimeDonutChartComponent);
33215
33307
  UptimeDonutChart.displayName = "UptimeDonutChart";
33216
33308
  var TrendIcon = ({ trend }) => {
33217
33309
  if (trend === "up") {
@@ -33330,7 +33422,7 @@ var EmptyStateMessage = ({
33330
33422
  iconClassName
33331
33423
  }) => {
33332
33424
  let IconContent = null;
33333
- if (React26__default.isValidElement(iconType)) {
33425
+ if (React141__default.isValidElement(iconType)) {
33334
33426
  IconContent = iconType;
33335
33427
  } else if (typeof iconType === "string") {
33336
33428
  const MappedIcon = IconMap[iconType];
@@ -35615,7 +35707,7 @@ function Skeleton({ className, ...props }) {
35615
35707
  var Select = SelectPrimitive.Root;
35616
35708
  var SelectGroup = SelectPrimitive.Group;
35617
35709
  var SelectValue = SelectPrimitive.Value;
35618
- var SelectTrigger = React26.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
35710
+ var SelectTrigger = React141.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
35619
35711
  SelectPrimitive.Trigger,
35620
35712
  {
35621
35713
  ref,
@@ -35631,7 +35723,7 @@ var SelectTrigger = React26.forwardRef(({ className, children, ...props }, ref)
35631
35723
  }
35632
35724
  ));
35633
35725
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
35634
- var SelectScrollUpButton = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
35726
+ var SelectScrollUpButton = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
35635
35727
  SelectPrimitive.ScrollUpButton,
35636
35728
  {
35637
35729
  ref,
@@ -35641,7 +35733,7 @@ var SelectScrollUpButton = React26.forwardRef(({ className, ...props }, ref) =>
35641
35733
  }
35642
35734
  ));
35643
35735
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
35644
- var SelectScrollDownButton = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
35736
+ var SelectScrollDownButton = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
35645
35737
  SelectPrimitive.ScrollDownButton,
35646
35738
  {
35647
35739
  ref,
@@ -35651,7 +35743,7 @@ var SelectScrollDownButton = React26.forwardRef(({ className, ...props }, ref) =
35651
35743
  }
35652
35744
  ));
35653
35745
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
35654
- var SelectContent = React26.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
35746
+ var SelectContent = React141.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
35655
35747
  SelectPrimitive.Content,
35656
35748
  {
35657
35749
  ref,
@@ -35679,7 +35771,7 @@ var SelectContent = React26.forwardRef(({ className, children, position = "poppe
35679
35771
  }
35680
35772
  ) }));
35681
35773
  SelectContent.displayName = SelectPrimitive.Content.displayName;
35682
- var SelectLabel = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
35774
+ var SelectLabel = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
35683
35775
  SelectPrimitive.Label,
35684
35776
  {
35685
35777
  ref,
@@ -35688,7 +35780,7 @@ var SelectLabel = React26.forwardRef(({ className, ...props }, ref) => /* @__PUR
35688
35780
  }
35689
35781
  ));
35690
35782
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
35691
- var SelectItem = React26.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
35783
+ var SelectItem = React141.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
35692
35784
  SelectPrimitive.Item,
35693
35785
  {
35694
35786
  ref,
@@ -35704,7 +35796,7 @@ var SelectItem = React26.forwardRef(({ className, children, ...props }, ref) =>
35704
35796
  }
35705
35797
  ));
35706
35798
  SelectItem.displayName = SelectPrimitive.Item.displayName;
35707
- var SelectSeparator = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
35799
+ var SelectSeparator = React141.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
35708
35800
  SelectPrimitive.Separator,
35709
35801
  {
35710
35802
  ref,
@@ -36003,7 +36095,7 @@ var TimePickerDropdown = ({
36003
36095
  ] })
36004
36096
  ] });
36005
36097
  };
36006
- var SilentErrorBoundary = class extends React26__default.Component {
36098
+ var SilentErrorBoundary = class extends React141__default.Component {
36007
36099
  constructor(props) {
36008
36100
  super(props);
36009
36101
  this.handleClearAndReload = () => {
@@ -42517,6 +42609,32 @@ var STATIC_COLORS = {
42517
42609
  };
42518
42610
  var PRODUCTIVE_COLOR = "#00AB45";
42519
42611
  var IDLE_COLOR = "#e5e7eb";
42612
+ var formatDuration = (seconds) => {
42613
+ if (seconds === null || seconds === void 0 || !Number.isFinite(seconds)) {
42614
+ return "--";
42615
+ }
42616
+ const wholeSeconds = Math.max(0, Math.round(seconds));
42617
+ const days = Math.floor(wholeSeconds / 86400);
42618
+ const hours = Math.floor(wholeSeconds % 86400 / 3600);
42619
+ const minutes = Math.floor(wholeSeconds % 3600 / 60);
42620
+ const remainingSeconds = wholeSeconds % 60;
42621
+ if (days > 0) {
42622
+ return `${days}d ${hours}h ${minutes}m ${remainingSeconds}s`;
42623
+ }
42624
+ if (hours > 0) {
42625
+ return `${hours}h ${minutes}m ${remainingSeconds}s`;
42626
+ }
42627
+ if (minutes > 0) {
42628
+ return `${minutes}m ${remainingSeconds}s`;
42629
+ }
42630
+ return `${remainingSeconds}s`;
42631
+ };
42632
+ var formatPercentage = (value) => {
42633
+ if (value === null || value === void 0 || !Number.isFinite(value)) {
42634
+ return "--";
42635
+ }
42636
+ return `${value.toFixed(1)}%`;
42637
+ };
42520
42638
  var getColorForEntry = (name, index) => {
42521
42639
  const normalized = name.trim().toLowerCase();
42522
42640
  if (normalized === "productive" || normalized === "productive time") {
@@ -42531,11 +42649,37 @@ var getColorForEntry = (name, index) => {
42531
42649
  const snakeCaseName = name.replace(/ /g, "_");
42532
42650
  return getReasonColor(snakeCaseName, index);
42533
42651
  };
42534
- var CustomTooltip = ({ active, payload }) => {
42652
+ var CustomTooltip = ({ active, payload, hideTotalDuration }) => {
42535
42653
  if (active && payload && payload.length) {
42536
- return /* @__PURE__ */ jsxs("div", { className: "bg-white p-2 border border-gray-200 shadow-md rounded-md text-xs z-50", children: [
42537
- /* @__PURE__ */ jsx("p", { className: "font-medium", children: payload[0].name }),
42538
- /* @__PURE__ */ jsx("p", { className: "text-gray-500", children: `${payload[0].value.toFixed(1)}%` })
42654
+ const datum = payload[0]?.payload;
42655
+ const contributors = datum?.contributors || [];
42656
+ const fill = payload[0]?.payload?.fill || payload[0]?.fill || getColorForEntry(payload[0].name, 0);
42657
+ return /* @__PURE__ */ jsxs("div", { className: "bg-white/95 backdrop-blur-sm p-3 border border-gray-200 shadow-xl rounded-lg z-50 min-w-[200px]", children: [
42658
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 mb-2 pb-1 border-b border-gray-100", children: [
42659
+ /* @__PURE__ */ jsx("div", { className: "w-2.5 h-2.5 rounded-full flex-shrink-0", style: { backgroundColor: fill } }),
42660
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-slate-800 text-sm", children: payload[0].name.replace(/_/g, " ") })
42661
+ ] }),
42662
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 text-xs", children: [
42663
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center gap-3", children: [
42664
+ /* @__PURE__ */ jsx("span", { className: "text-slate-500", children: "Share of idle time" }),
42665
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-slate-800", children: `${payload[0].value.toFixed(1)}%` })
42666
+ ] }),
42667
+ !hideTotalDuration && datum?.totalDurationSeconds !== void 0 ? /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center gap-3", children: [
42668
+ /* @__PURE__ */ jsx("span", { className: "text-slate-500", children: "Total Duration" }),
42669
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-slate-800", children: formatDuration(datum.totalDurationSeconds) })
42670
+ ] }) : null,
42671
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center gap-3", children: [
42672
+ /* @__PURE__ */ jsx("span", { className: "text-slate-500", children: "Efficiency Loss" }),
42673
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-slate-800", children: formatPercentage(datum?.efficiencyLossPercentage) })
42674
+ ] })
42675
+ ] }),
42676
+ contributors.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "mt-2 pt-2 border-t border-gray-100", children: [
42677
+ /* @__PURE__ */ jsx("p", { className: "text-[9px] font-semibold uppercase tracking-wider text-slate-400 mb-1.5", children: "Top Workstations" }),
42678
+ /* @__PURE__ */ jsx("div", { className: "space-y-1", children: contributors.slice(0, 3).map((contributor) => /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2 text-[10px]", children: [
42679
+ /* @__PURE__ */ jsx("span", { className: "text-slate-700 truncate max-w-[120px]", children: contributor.workspaceName }),
42680
+ /* @__PURE__ */ jsx("span", { className: "text-slate-500 text-right whitespace-nowrap", children: `${formatDuration(contributor.totalDurationSeconds)} \u2022 ${Number(contributor.percentageWithinReason || 0).toFixed(1)}%` })
42681
+ ] }, `${payload[0].name}-${contributor.workspaceId}`)) })
42682
+ ] }) : null
42539
42683
  ] });
42540
42684
  }
42541
42685
  return null;
@@ -42572,10 +42716,11 @@ var ErrorState = ({ error }) => /* @__PURE__ */ jsx("div", { className: "w-full
42572
42716
  var IdleTimeReasonChartComponent = ({
42573
42717
  data,
42574
42718
  isLoading = false,
42575
- error = null
42719
+ error = null,
42720
+ hideTotalDuration = false
42576
42721
  }) => {
42577
- const [activeData, setActiveData] = React26__default.useState([]);
42578
- React26__default.useEffect(() => {
42722
+ const [activeData, setActiveData] = React141__default.useState([]);
42723
+ React141__default.useEffect(() => {
42579
42724
  if (activeData.length > 0) {
42580
42725
  setActiveData([]);
42581
42726
  }
@@ -42590,7 +42735,7 @@ var IdleTimeReasonChartComponent = ({
42590
42735
  setActiveData([]);
42591
42736
  }
42592
42737
  }, [data]);
42593
- React26__default.useEffect(() => {
42738
+ React141__default.useEffect(() => {
42594
42739
  if (!data || data.length === 0) return;
42595
42740
  data.forEach((entry, index) => {
42596
42741
  if (entry.name.toLowerCase().includes("other")) {
@@ -42598,7 +42743,7 @@ var IdleTimeReasonChartComponent = ({
42598
42743
  }
42599
42744
  });
42600
42745
  }, [data]);
42601
- const pieKey = React26__default.useMemo(() => {
42746
+ const pieKey = React141__default.useMemo(() => {
42602
42747
  return activeData.map((d) => `${d.name}-${d.value}`).join("|");
42603
42748
  }, [activeData]);
42604
42749
  if (isLoading) {
@@ -42625,19 +42770,29 @@ var IdleTimeReasonChartComponent = ({
42625
42770
  }
42626
42771
  .recharts-wrapper {
42627
42772
  outline: none !important;
42773
+ overflow: visible !important;
42774
+ }
42775
+ .recharts-tooltip-wrapper {
42776
+ z-index: 1000 !important;
42777
+ }
42778
+ .recharts-responsive-container {
42779
+ overflow: visible !important;
42780
+ }
42781
+ .recharts-surface {
42782
+ overflow: visible !important;
42628
42783
  }
42629
42784
  ` }),
42630
42785
  /* @__PURE__ */ jsxs(
42631
42786
  "div",
42632
42787
  {
42633
- className: "w-full h-full flex items-center overflow-hidden focus:outline-none",
42788
+ className: "w-full h-full flex items-center overflow-visible focus:outline-none",
42634
42789
  tabIndex: -1,
42635
42790
  onFocus: (e) => e.currentTarget.blur(),
42636
42791
  children: [
42637
42792
  /* @__PURE__ */ jsx(
42638
42793
  "div",
42639
42794
  {
42640
- className: "flex-1 h-full min-w-0 relative focus:outline-none",
42795
+ className: "flex-1 h-full min-w-0 relative focus:outline-none overflow-visible",
42641
42796
  tabIndex: -1,
42642
42797
  onFocus: (e) => e.currentTarget.blur(),
42643
42798
  children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(PieChart, { margin: { top: 0, right: 0, bottom: 0, left: 0 }, children: [
@@ -42669,11 +42824,11 @@ var IdleTimeReasonChartComponent = ({
42669
42824
  },
42670
42825
  pieKey
42671
42826
  ),
42672
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip, {}) })
42827
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip, { hideTotalDuration }) })
42673
42828
  ] }) })
42674
42829
  }
42675
42830
  ),
42676
- /* @__PURE__ */ jsx("div", { className: "w-[45%] max-w-[140px] pl-2 flex flex-col justify-center h-full overflow-y-auto", children: /* @__PURE__ */ jsx("ul", { className: "text-xs space-y-1.5", children: data.map((entry, index) => /* @__PURE__ */ jsxs("li", { className: "flex items-start", children: [
42831
+ /* @__PURE__ */ jsx("div", { className: "w-[50%] max-w-[200px] pl-1 pr-1 flex flex-col justify-center h-full overflow-y-auto", children: /* @__PURE__ */ jsx("ul", { className: "text-xs space-y-1.5", children: data.map((entry, index) => /* @__PURE__ */ jsxs("li", { className: "flex items-start", children: [
42677
42832
  /* @__PURE__ */ jsx(
42678
42833
  "span",
42679
42834
  {
@@ -42681,14 +42836,14 @@ var IdleTimeReasonChartComponent = ({
42681
42836
  style: { backgroundColor: getColorForEntry(entry.name, index) }
42682
42837
  }
42683
42838
  ),
42684
- /* @__PURE__ */ jsx("span", { className: "text-gray-600 leading-tight text-[10px] sm:text-xs break-words", children: entry.name })
42839
+ /* @__PURE__ */ jsx("span", { className: "text-gray-600 leading-tight text-[11px] sm:text-xs break-words", children: entry.name.replace(/_/g, " ") })
42685
42840
  ] }, `item-${index}`)) }) })
42686
42841
  ]
42687
42842
  }
42688
42843
  )
42689
42844
  ] });
42690
42845
  };
42691
- var IdleTimeReasonChart = React26__default.memo(IdleTimeReasonChartComponent);
42846
+ var IdleTimeReasonChart = React141__default.memo(IdleTimeReasonChartComponent);
42692
42847
  IdleTimeReasonChart.displayName = "IdleTimeReasonChart";
42693
42848
  var IdleTimeReasonChart_default = IdleTimeReasonChart;
42694
42849
  var DEFAULT_PERFORMANCE_DATA = {
@@ -46910,11 +47065,11 @@ var getWorkspaceStyles = (position, isPlaceholder = false) => {
46910
47065
  ${isPlaceholder ? "cursor-default" : ""}`;
46911
47066
  };
46912
47067
  var formatPercentRange = (min, max) => {
46913
- const format7 = (value) => Number.isInteger(value) ? `${value}` : value.toFixed(1);
47068
+ const format8 = (value) => Number.isInteger(value) ? `${value}` : value.toFixed(1);
46914
47069
  if (min >= 100 || max >= 100) {
46915
- return `${format7(min)}+%`;
47070
+ return `${format8(min)}+%`;
46916
47071
  }
46917
- return `${format7(min)}-${format7(max)}%`;
47072
+ return `${format8(min)}-${format8(max)}%`;
46918
47073
  };
46919
47074
  var Legend6 = ({ useBottleneckLabel = false, legend }) => {
46920
47075
  const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
@@ -46948,7 +47103,7 @@ var arePropsEqual = (prevProps, nextProps) => {
46948
47103
  return prevProps.data.efficiency === nextProps.data.efficiency && prevProps.data.trend_score === nextProps.data.trend_score && prevProps.data.workspace_id === nextProps.data.workspace_id && prevProps.data.workspace_name === nextProps.data.workspace_name && prevProps.isBottleneck === nextProps.isBottleneck && prevProps.isLowEfficiency === nextProps.isLowEfficiency && prevProps.isVeryLowEfficiency === nextProps.isVeryLowEfficiency && prevLegend.green_min === nextLegend.green_min && prevLegend.green_max === nextLegend.green_max && prevLegend.yellow_min === nextLegend.yellow_min && prevLegend.yellow_max === nextLegend.yellow_max && prevLegend.red_min === nextLegend.red_min && prevLegend.red_max === nextLegend.red_max && prevLegend.critical_threshold === nextLegend.critical_threshold && // Position doesn't need deep equality check as it's generally static
46949
47104
  prevProps.position.id === nextProps.position.id;
46950
47105
  };
46951
- var WorkspaceGridItem = React26__default.memo(({
47106
+ var WorkspaceGridItem = React141__default.memo(({
46952
47107
  data,
46953
47108
  position,
46954
47109
  isBottleneck = false,
@@ -46977,7 +47132,8 @@ var WorkspaceGridItem = React26__default.memo(({
46977
47132
  e.preventDefault();
46978
47133
  if (isInactive) return;
46979
47134
  const displayName = getWorkspaceDisplayName(data.workspace_name, data.line_id);
46980
- const navParams = getWorkspaceNavigationParams(data.workspace_id, displayName, data.line_id);
47135
+ const currentPath = typeof window !== "undefined" ? `${window.location.pathname}${window.location.search}` : "/";
47136
+ const navParams = getWorkspaceNavigationParams(data.workspace_id, displayName, data.line_id, currentPath);
46981
47137
  navigate(`/workspace/${data.workspace_id}${navParams}`, {
46982
47138
  trackingEvent: {
46983
47139
  name: "Workspace Detail Clicked",
@@ -47042,7 +47198,7 @@ var WorkspaceGridItem = React26__default.memo(({
47042
47198
  );
47043
47199
  }, arePropsEqual);
47044
47200
  WorkspaceGridItem.displayName = "WorkspaceGridItem";
47045
- var WorkspaceGrid = React26__default.memo(({
47201
+ var WorkspaceGrid = React141__default.memo(({
47046
47202
  workspaces,
47047
47203
  isPdfMode = false,
47048
47204
  customWorkspacePositions,
@@ -47297,7 +47453,7 @@ var KPICard = ({
47297
47453
  }) => {
47298
47454
  useThemeConfig();
47299
47455
  const { formatNumber } = useFormatNumber();
47300
- const trendInfo = React26__default.useMemo(() => {
47456
+ const trendInfo = React141__default.useMemo(() => {
47301
47457
  let trendValue = trend || "neutral";
47302
47458
  if (change !== void 0 && trend === void 0) {
47303
47459
  trendValue = change > 0 ? "up" : change < 0 ? "down" : "neutral";
@@ -47324,7 +47480,7 @@ var KPICard = ({
47324
47480
  const shouldShowTrend = !(change === 0 && trend === void 0);
47325
47481
  return { trendValue, Icon: Icon2, colorClass, bgClass, shouldShowTrend };
47326
47482
  }, [trend, change]);
47327
- const formattedValue = React26__default.useMemo(() => {
47483
+ const formattedValue = React141__default.useMemo(() => {
47328
47484
  if (title === "Quality Compliance" && typeof value === "number") {
47329
47485
  return value.toFixed(1);
47330
47486
  }
@@ -47338,7 +47494,7 @@ var KPICard = ({
47338
47494
  }
47339
47495
  return value;
47340
47496
  }, [value, title]);
47341
- const formattedChange = React26__default.useMemo(() => {
47497
+ const formattedChange = React141__default.useMemo(() => {
47342
47498
  if (change === void 0 || change === 0 && !showZeroChange) return null;
47343
47499
  const absChange = Math.abs(change);
47344
47500
  return formatNumber(absChange, { minimumFractionDigits: 0, maximumFractionDigits: 1 });
@@ -47776,7 +47932,7 @@ var WorkspaceHealthCard = ({
47776
47932
  onClick(workspace);
47777
47933
  }
47778
47934
  };
47779
- const formatDuration4 = (minutes) => {
47935
+ const formatDuration5 = (minutes) => {
47780
47936
  if (!minutes || minutes <= 0) return "0 min";
47781
47937
  const rounded = Math.max(Math.round(minutes), 0);
47782
47938
  const days = Math.floor(rounded / 1440);
@@ -47842,7 +47998,7 @@ var WorkspaceHealthCard = ({
47842
47998
  };
47843
47999
  }
47844
48000
  return {
47845
- text: `${formatDuration4(downtimeMinutes)}`,
48001
+ text: `${formatDuration5(downtimeMinutes)}`,
47846
48002
  className: downtimeMinutes > 60 ? "text-rose-600 dark:text-rose-400" : "text-amber-600 dark:text-amber-400",
47847
48003
  label: "Total Downtime"
47848
48004
  };
@@ -48818,7 +48974,7 @@ var Breadcrumbs = ({ items }) => {
48818
48974
  }
48819
48975
  }
48820
48976
  };
48821
- return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "mb-1 flex items-center space-x-1 text-xs font-medium text-gray-500 dark:text-gray-400", children: items.map((item, index) => /* @__PURE__ */ jsxs(React26__default.Fragment, { children: [
48977
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "mb-1 flex items-center space-x-1 text-xs font-medium text-gray-500 dark:text-gray-400", children: items.map((item, index) => /* @__PURE__ */ jsxs(React141__default.Fragment, { children: [
48822
48978
  index > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "h-3 w-3 text-gray-400 dark:text-gray-500" }),
48823
48979
  /* @__PURE__ */ jsxs(
48824
48980
  "span",
@@ -48880,29 +49036,27 @@ var UserProfileDropdown = ({ config }) => {
48880
49036
  }
48881
49037
  }
48882
49038
  };
48883
- const defaultAvatar = /* @__PURE__ */ jsx(UserCircle, { className: "h-7 w-7 text-gray-500 dark:text-gray-400" });
49039
+ const fullName = user?.user_metadata?.full_name;
49040
+ const triggerLabel = config.showName !== false ? fullName || user.email || "Account" : "Account";
48884
49041
  return /* @__PURE__ */ jsxs("div", { className: "relative", ref: dropdownRef, children: [
48885
- /* @__PURE__ */ jsxs(
49042
+ /* @__PURE__ */ jsx(
48886
49043
  "button",
48887
49044
  {
48888
49045
  type: "button",
48889
- className: "flex items-center gap-2 rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800",
49046
+ className: "flex items-center rounded-md px-2 py-1.5 text-sm font-medium text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:text-gray-200 dark:hover:bg-gray-800 dark:focus:ring-offset-gray-800",
48890
49047
  onClick: () => setIsOpen(!isOpen),
48891
49048
  "aria-haspopup": "true",
48892
49049
  "aria-expanded": isOpen,
48893
49050
  "aria-label": "User menu",
48894
- children: [
48895
- config.customAvatar ? config.customAvatar : config.showAvatar !== false && user?.user_metadata?.avatar_url ? /* @__PURE__ */ jsx("img", { className: "h-8 w-8 rounded-full", src: user.user_metadata.avatar_url, alt: "User avatar" }) : defaultAvatar,
48896
- config.showName !== false && user?.user_metadata?.full_name && /* @__PURE__ */ jsx("span", { className: "hidden md:block text-sm font-medium text-gray-700 dark:text-gray-200", children: user.user_metadata.full_name })
48897
- ]
49051
+ children: /* @__PURE__ */ jsx("span", { className: "truncate max-w-[180px]", children: triggerLabel })
48898
49052
  }
48899
49053
  ),
48900
49054
  isOpen && /* @__PURE__ */ jsxs("div", { className: "origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg py-1 bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 dark:ring-gray-700 focus:outline-none z-50", children: [
48901
- config.showName !== false && user?.user_metadata?.full_name && /* @__PURE__ */ jsxs("div", { className: "px-4 py-2 md:hidden", children: [
48902
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-900 dark:text-white truncate", children: user.user_metadata.full_name }),
49055
+ config.showName !== false && fullName && /* @__PURE__ */ jsxs("div", { className: "px-4 py-2 md:hidden", children: [
49056
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-900 dark:text-white truncate", children: fullName }),
48903
49057
  user.email && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 truncate", children: user.email })
48904
49058
  ] }),
48905
- user?.user_metadata?.full_name && /* @__PURE__ */ jsx("div", { className: "md:hidden h-px bg-gray-200 dark:bg-gray-700 my-1" }),
49059
+ fullName && /* @__PURE__ */ jsx("div", { className: "md:hidden h-px bg-gray-200 dark:bg-gray-700 my-1" }),
48906
49060
  menuItems.map(
48907
49061
  (item) => item.isDivider ? /* @__PURE__ */ jsx("div", { className: "h-px bg-gray-200 dark:bg-gray-700 my-1" }, item.key) : /* @__PURE__ */ jsxs(
48908
49062
  "button",
@@ -49144,6 +49298,211 @@ var SettingsPopup = ({
49144
49298
  document.body
49145
49299
  );
49146
49300
  };
49301
+ var formatPercent = (value) => typeof value === "number" && Number.isFinite(value) ? `${value.toFixed(1)}%` : "N/A";
49302
+ var formatRelativeTime2 = (value) => {
49303
+ const parsed = new Date(value);
49304
+ if (Number.isNaN(parsed.getTime())) return "Just now";
49305
+ const diffMs = parsed.getTime() - Date.now();
49306
+ const absSeconds = Math.round(Math.abs(diffMs) / 1e3);
49307
+ const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
49308
+ if (absSeconds < 60) return rtf.format(Math.round(diffMs / 1e3), "second");
49309
+ if (absSeconds < 3600) return rtf.format(Math.round(diffMs / 6e4), "minute");
49310
+ if (absSeconds < 86400) return rtf.format(Math.round(diffMs / 36e5), "hour");
49311
+ return rtf.format(Math.round(diffMs / 864e5), "day");
49312
+ };
49313
+ var AlertsPopup = ({
49314
+ isOpen,
49315
+ onClose,
49316
+ triggerRef,
49317
+ companyId,
49318
+ alertsCount = 0,
49319
+ onAlertsLoaded
49320
+ }) => {
49321
+ const supabase = useSupabase();
49322
+ const popupRef = useRef(null);
49323
+ const [position, setPosition] = useState({ top: 0, left: 90, width: 360 });
49324
+ const [mounted, setMounted] = useState(false);
49325
+ const [alerts, setAlerts] = useState([]);
49326
+ const [isLoading, setIsLoading] = useState(false);
49327
+ const [error, setError] = useState(null);
49328
+ const loadAlerts = useCallback(async () => {
49329
+ if (!supabase || !companyId) {
49330
+ setAlerts([]);
49331
+ onAlertsLoaded?.(0);
49332
+ return;
49333
+ }
49334
+ try {
49335
+ setIsLoading(true);
49336
+ setError(null);
49337
+ const response = await alertsService.getCurrentAlerts(supabase, companyId);
49338
+ const nextAlerts = response?.alerts || [];
49339
+ setAlerts(nextAlerts);
49340
+ onAlertsLoaded?.(response?.total ?? nextAlerts.length);
49341
+ } catch (err) {
49342
+ const message = err instanceof Error ? err.message : "Failed to load alerts";
49343
+ setAlerts([]);
49344
+ setError(message);
49345
+ onAlertsLoaded?.(0);
49346
+ } finally {
49347
+ setIsLoading(false);
49348
+ }
49349
+ }, [companyId, onAlertsLoaded, supabase]);
49350
+ useEffect(() => {
49351
+ setMounted(true);
49352
+ }, []);
49353
+ useEffect(() => {
49354
+ if (!isOpen) return;
49355
+ void loadAlerts();
49356
+ }, [isOpen, loadAlerts]);
49357
+ const updatePosition = useCallback(() => {
49358
+ const viewportHeight = window.innerHeight;
49359
+ const viewportWidth = window.innerWidth;
49360
+ if (viewportWidth < 768) {
49361
+ const mobileWidth = Math.max(240, Math.min(360, viewportWidth - 32));
49362
+ setPosition({
49363
+ top: Math.max(16, (viewportHeight - 280) / 2),
49364
+ left: Math.max(16, (viewportWidth - mobileWidth) / 2),
49365
+ width: mobileWidth
49366
+ });
49367
+ return;
49368
+ }
49369
+ if (!triggerRef.current) return;
49370
+ const rect = triggerRef.current.getBoundingClientRect();
49371
+ const popupHeight = 280;
49372
+ let top = rect.bottom - popupHeight + 40;
49373
+ if (top < 16) top = 16;
49374
+ if (top + popupHeight > viewportHeight - 16) {
49375
+ top = viewportHeight - popupHeight - 16;
49376
+ }
49377
+ setPosition({
49378
+ top,
49379
+ left: 88,
49380
+ // Sidebar width (80px) + gap (8px)
49381
+ width: 360
49382
+ });
49383
+ }, [triggerRef]);
49384
+ useEffect(() => {
49385
+ if (isOpen) {
49386
+ updatePosition();
49387
+ window.addEventListener("resize", updatePosition);
49388
+ window.addEventListener("scroll", updatePosition);
49389
+ }
49390
+ return () => {
49391
+ window.removeEventListener("resize", updatePosition);
49392
+ window.removeEventListener("scroll", updatePosition);
49393
+ };
49394
+ }, [isOpen, updatePosition]);
49395
+ useEffect(() => {
49396
+ const handleClickOutside = (event) => {
49397
+ const target = event.target;
49398
+ const clickedTrigger = triggerRef.current?.contains(target) ?? false;
49399
+ if (popupRef.current && !popupRef.current.contains(target) && !clickedTrigger) {
49400
+ onClose();
49401
+ }
49402
+ };
49403
+ const handleEscape = (event) => {
49404
+ if (event.key === "Escape") {
49405
+ onClose();
49406
+ }
49407
+ };
49408
+ if (isOpen) {
49409
+ document.addEventListener("mousedown", handleClickOutside);
49410
+ document.addEventListener("keydown", handleEscape);
49411
+ }
49412
+ return () => {
49413
+ document.removeEventListener("mousedown", handleClickOutside);
49414
+ document.removeEventListener("keydown", handleEscape);
49415
+ };
49416
+ }, [isOpen, onClose, triggerRef]);
49417
+ if (!mounted) return null;
49418
+ return createPortal(
49419
+ /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsxs(
49420
+ motion.div,
49421
+ {
49422
+ ref: popupRef,
49423
+ initial: { opacity: 0, x: -12, scale: 0.95 },
49424
+ animate: { opacity: 1, x: 0, scale: 1 },
49425
+ exit: { opacity: 0, x: -12, scale: 0.95 },
49426
+ transition: {
49427
+ duration: 0.2,
49428
+ ease: [0.16, 1, 0.3, 1]
49429
+ },
49430
+ style: {
49431
+ position: "fixed",
49432
+ top: position.top,
49433
+ left: position.left,
49434
+ width: position.width,
49435
+ zIndex: 2147483647
49436
+ },
49437
+ className: "bg-white rounded-[16px] shadow-xl border border-gray-100 max-w-[calc(100vw-32px)] overflow-hidden flex flex-col",
49438
+ children: [
49439
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-4 border-b border-gray-50 bg-[#fafafa]", children: [
49440
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
49441
+ /* @__PURE__ */ jsx("h3", { className: "text-[14px] font-bold text-[#111827] uppercase tracking-wide", children: "Recent Alerts" }),
49442
+ alertsCount > 0 && /* @__PURE__ */ jsxs("span", { className: "bg-[#eff6ff] text-[#2563eb] text-[11px] font-bold px-2 py-0.5 rounded-full", children: [
49443
+ alertsCount,
49444
+ " Active"
49445
+ ] })
49446
+ ] }),
49447
+ /* @__PURE__ */ jsx(
49448
+ "button",
49449
+ {
49450
+ onClick: onClose,
49451
+ className: "text-gray-400 hover:text-gray-600 focus:outline-none p-1.5 -mr-1.5 rounded-lg hover:bg-gray-100 transition-colors",
49452
+ children: /* @__PURE__ */ jsx(XMarkIcon, { className: "w-[18px] h-[18px]", strokeWidth: 2 })
49453
+ }
49454
+ )
49455
+ ] }),
49456
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col max-h-[380px] overflow-y-auto", children: [
49457
+ isLoading && /* @__PURE__ */ jsx("div", { className: "px-5 py-10 text-sm text-gray-500", children: "Loading current shift alerts..." }),
49458
+ !isLoading && error && /* @__PURE__ */ jsx("div", { className: "px-5 py-10 text-sm text-red-600", children: error }),
49459
+ !isLoading && !error && alerts.length === 0 && /* @__PURE__ */ jsx("div", { className: "px-5 py-10 text-sm text-gray-500", children: "No active alerts for the current shift." }),
49460
+ !isLoading && !error && alerts.map((alert2, index) => {
49461
+ const isCritical = typeof alert2.delta_efficiency === "number" && alert2.delta_efficiency <= -10;
49462
+ const description = `${alert2.monitoring_mode === "uptime" ? "Uptime" : "Output"} efficiency is ${formatPercent(alert2.current_efficiency)} vs last week's ${formatPercent(alert2.baseline_efficiency)} average.`;
49463
+ return /* @__PURE__ */ jsx(
49464
+ motion.div,
49465
+ {
49466
+ initial: { opacity: 0, y: 10 },
49467
+ animate: { opacity: 1, y: 0 },
49468
+ transition: {
49469
+ duration: 0.2,
49470
+ delay: index * 0.05 + 0.1,
49471
+ ease: [0.16, 1, 0.3, 1]
49472
+ },
49473
+ className: "px-5 py-5 border-b border-gray-50 hover:bg-[#f8fafc] transition-colors",
49474
+ children: /* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
49475
+ /* @__PURE__ */ jsx("div", { className: `shrink-0 flex items-start pt-0.5 ${isCritical ? "text-[#ef4444]" : "text-[#f59e0b]"}`, children: isCritical ? /* @__PURE__ */ jsx(ExclamationCircleIcon, { className: "w-5 h-5", strokeWidth: 1.5 }) : /* @__PURE__ */ jsx(ExclamationTriangleIcon, { className: "w-5 h-5", strokeWidth: 1.5 }) }),
49476
+ /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
49477
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-start mb-1.5", children: [
49478
+ /* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold text-[#111827]", children: alert2.line_name }),
49479
+ /* @__PURE__ */ jsx("span", { className: "text-[12px] text-[#94a3b8] font-medium whitespace-nowrap ml-3", children: formatRelativeTime2(alert2.evaluated_at) })
49480
+ ] }),
49481
+ /* @__PURE__ */ jsxs("p", { className: "text-[12px] font-medium text-[#475569] uppercase tracking-wide", children: [
49482
+ alert2.monitoring_mode === "uptime" ? "Uptime" : "Output",
49483
+ " regression"
49484
+ ] }),
49485
+ /* @__PURE__ */ jsx("p", { className: "text-[13.5px] text-[#64748b] leading-[1.45] mt-1", children: description }),
49486
+ /* @__PURE__ */ jsxs("p", { className: "text-[12px] text-[#94a3b8] mt-2", children: [
49487
+ "Delta ",
49488
+ formatPercent(alert2.delta_efficiency),
49489
+ " across ",
49490
+ alert2.baseline_sample_size,
49491
+ " historical shifts"
49492
+ ] })
49493
+ ] })
49494
+ ] })
49495
+ },
49496
+ alert2.id
49497
+ );
49498
+ })
49499
+ ] })
49500
+ ]
49501
+ }
49502
+ ) }),
49503
+ document.body
49504
+ );
49505
+ };
49147
49506
  var SideNavBar = memo$1(({
49148
49507
  // These props are accepted but not used in this implementation
49149
49508
  navItems = [],
@@ -49157,17 +49516,13 @@ var SideNavBar = memo$1(({
49157
49516
  const router = useRouter();
49158
49517
  const { navigate } = useNavigation();
49159
49518
  const { signOut, user } = useAuth();
49519
+ const supabase = useSupabase();
49160
49520
  const entityConfig = useEntityConfig();
49161
49521
  const dashboardConfig = useDashboardConfig();
49162
49522
  const isSuperAdmin = user?.scope_mode === "SUPER_ADMIN" || !!user?.access_scope?.is_super_admin;
49163
49523
  const role = user?.role_level;
49164
- const roleAccessMap = {
49165
- optifye: ["/", "/leaderboard", "/kpis", "/targets", "/shifts", "/supervisor-management", "/skus", "/help", "/health", "/profile", "/workspace", "/factory-view", "/team-management", "/tickets", "/improvement-center"],
49166
- owner: ["/", "/leaderboard", "/kpis", "/targets", "/shifts", "/supervisor-management", "/skus", "/help", "/health", "/profile", "/workspace", "/factory-view", "/team-management", "/tickets", "/improvement-center"],
49167
- it: ["/", "/leaderboard", "/kpis", "/targets", "/shifts", "/supervisor-management", "/skus", "/help", "/health", "/profile", "/workspace", "/factory-view", "/team-management", "/tickets", "/improvement-center"],
49168
- plant_head: ["/", "/leaderboard", "/kpis", "/targets", "/shifts", "/supervisor-management", "/skus", "/help", "/health", "/profile", "/workspace", "/factory-view", "/team-management", "/tickets", "/improvement-center"],
49169
- supervisor: ["/", "/leaderboard", "/kpis", "/targets", "/shifts", "/skus", "/help", "/health", "/profile", "/workspace", "/tickets", "/improvement-center"]
49170
- };
49524
+ const roleNavPaths = useMemo(() => getRoleNavPaths(role), [role]);
49525
+ const showLiveMonitorLink = roleNavPaths.includes("/live-monitor");
49171
49526
  const getBasePath = useCallback((path) => {
49172
49527
  const firstSegment = path.split("?")[0].split("/").filter(Boolean)[0];
49173
49528
  return firstSegment ? `/${firstSegment}` : "/";
@@ -49176,9 +49531,8 @@ var SideNavBar = memo$1(({
49176
49531
  if (!role) return false;
49177
49532
  if (isSuperAdmin) return true;
49178
49533
  const basePath = getBasePath(path);
49179
- const allowedPaths = roleAccessMap[role] || [];
49180
- return allowedPaths.includes(basePath);
49181
- }, [role, isSuperAdmin, getBasePath]);
49534
+ return roleNavPaths.includes(basePath);
49535
+ }, [role, isSuperAdmin, getBasePath, roleNavPaths]);
49182
49536
  const lineId = entityConfig.defaultLineId || LINE_1_UUID;
49183
49537
  const skuEnabled = dashboardConfig?.skuConfig?.enabled || false;
49184
49538
  dashboardConfig?.supervisorConfig?.enabled || false;
@@ -49219,6 +49573,17 @@ var SideNavBar = memo$1(({
49219
49573
  });
49220
49574
  onMobileMenuClose?.();
49221
49575
  }, [navigate, onMobileMenuClose]);
49576
+ const handleLiveClick = useCallback(() => {
49577
+ navigate("/live-monitor", {
49578
+ trackingEvent: {
49579
+ name: "Live Monitor Clicked",
49580
+ properties: {
49581
+ source: "side_nav"
49582
+ }
49583
+ }
49584
+ });
49585
+ onMobileMenuClose?.();
49586
+ }, [navigate, onMobileMenuClose]);
49222
49587
  const handleKPIsClick = useCallback(() => {
49223
49588
  navigate(`/kpis`, {
49224
49589
  trackingEvent: {
@@ -49354,6 +49719,37 @@ var SideNavBar = memo$1(({
49354
49719
  }, [navigate, onMobileMenuClose]);
49355
49720
  const [isSettingsOpen, setIsSettingsOpen] = useState(false);
49356
49721
  const settingsTriggerRef = useRef(null);
49722
+ const [isAlertsOpen, setIsAlertsOpen] = useState(false);
49723
+ const [alertsCount, setAlertsCount] = useState(0);
49724
+ const alertsTriggerRef = useRef(null);
49725
+ const alertsCompanyId = entityConfig.companyId || user?.company_id;
49726
+ const showAlertsButton = (role === "supervisor" || role === "optifye") && !!alertsCompanyId && !!supabase;
49727
+ const refreshAlertsSummary = useCallback(async () => {
49728
+ if (!showAlertsButton || !supabase || !alertsCompanyId) {
49729
+ setAlertsCount(0);
49730
+ return;
49731
+ }
49732
+ try {
49733
+ const summary = await alertsService.getSummary(supabase, alertsCompanyId);
49734
+ setAlertsCount(summary?.total_current_alerts || 0);
49735
+ } catch (error) {
49736
+ console.error("Failed to fetch alerts summary:", error);
49737
+ setAlertsCount(0);
49738
+ }
49739
+ }, [alertsCompanyId, showAlertsButton, supabase]);
49740
+ useEffect(() => {
49741
+ if (!showAlertsButton) {
49742
+ setAlertsCount(0);
49743
+ return;
49744
+ }
49745
+ void refreshAlertsSummary();
49746
+ const intervalId = window.setInterval(() => {
49747
+ void refreshAlertsSummary();
49748
+ }, 5 * 60 * 1e3);
49749
+ return () => {
49750
+ window.clearInterval(intervalId);
49751
+ };
49752
+ }, [refreshAlertsSummary, showAlertsButton]);
49357
49753
  const settingsItems = useMemo(() => {
49358
49754
  const items = [
49359
49755
  ...canAccessPath("/targets") ? [{
@@ -49448,6 +49844,7 @@ var SideNavBar = memo$1(({
49448
49844
  onMobileMenuClose?.();
49449
49845
  }, [navigate, onMobileMenuClose]);
49450
49846
  const homeButtonClasses = useMemo(() => getButtonClasses("/"), [getButtonClasses, pathname]);
49847
+ const liveButtonClasses = useMemo(() => getButtonClasses("/live-monitor"), [getButtonClasses, pathname]);
49451
49848
  const leaderboardButtonClasses = useMemo(() => getButtonClasses("/leaderboard"), [getButtonClasses, pathname]);
49452
49849
  const kpisButtonClasses = useMemo(() => getButtonClasses("/kpis"), [getButtonClasses, pathname]);
49453
49850
  const improvementButtonClasses = useMemo(() => getButtonClasses("/improvement-center"), [getButtonClasses, pathname]);
@@ -49461,6 +49858,12 @@ var SideNavBar = memo$1(({
49461
49858
  ${isActive ? "bg-blue-50/80 text-blue-600 font-medium" : "hover:bg-gray-50 text-gray-500 hover:text-gray-700 font-medium active:bg-gray-100"}
49462
49859
  transition-all duration-200 ease-out focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2`;
49463
49860
  }, [isSettingsOpen, settingsItems]);
49861
+ const alertsButtonClasses = useMemo(() => {
49862
+ const isActive = isAlertsOpen;
49863
+ return `w-full flex flex-col items-center justify-center py-4 sm:py-3 px-2 sm:px-1 rounded-lg relative group min-h-[44px] sm:min-h-0
49864
+ ${isActive ? "bg-blue-50/80 text-blue-600 font-medium" : "hover:bg-gray-50 text-gray-500 hover:text-gray-700 font-medium active:bg-gray-100"}
49865
+ transition-all duration-200 ease-out focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2`;
49866
+ }, [isAlertsOpen]);
49464
49867
  const NavigationContent = () => /* @__PURE__ */ jsxs(Fragment, { children: [
49465
49868
  /* @__PURE__ */ jsx("div", { className: "w-full py-6 px-4 flex-shrink-0", children: /* @__PURE__ */ jsx(
49466
49869
  "button",
@@ -49472,21 +49875,38 @@ var SideNavBar = memo$1(({
49472
49875
  }
49473
49876
  ) }),
49474
49877
  /* @__PURE__ */ jsxs("div", { className: "flex-1 w-full py-6 px-4 overflow-y-auto", children: [
49475
- /* @__PURE__ */ jsx("div", { className: "mb-6", children: canAccessPath("/") && /* @__PURE__ */ jsxs(
49476
- "button",
49477
- {
49478
- onClick: handleHomeClick,
49479
- className: homeButtonClasses,
49480
- "aria-label": "Home",
49481
- tabIndex: 0,
49482
- role: "tab",
49483
- "aria-selected": pathname === "/" || pathname.startsWith("//"),
49484
- children: [
49485
- /* @__PURE__ */ jsx(HomeIcon, { className: "w-5 h-5 mb-1" }),
49486
- /* @__PURE__ */ jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Home" })
49487
- ]
49488
- }
49489
- ) }),
49878
+ /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
49879
+ canAccessPath("/") && /* @__PURE__ */ jsxs(
49880
+ "button",
49881
+ {
49882
+ onClick: handleHomeClick,
49883
+ className: homeButtonClasses,
49884
+ "aria-label": "Home",
49885
+ tabIndex: 0,
49886
+ role: "tab",
49887
+ "aria-selected": pathname === "/" || pathname.startsWith("//"),
49888
+ children: [
49889
+ /* @__PURE__ */ jsx(HomeIcon, { className: "w-5 h-5 mb-1" }),
49890
+ /* @__PURE__ */ jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Home" })
49891
+ ]
49892
+ }
49893
+ ),
49894
+ showLiveMonitorLink && canAccessPath("/live-monitor") && /* @__PURE__ */ jsxs(
49895
+ "button",
49896
+ {
49897
+ onClick: handleLiveClick,
49898
+ className: `${liveButtonClasses} mt-3`,
49899
+ "aria-label": "Monitor",
49900
+ tabIndex: 0,
49901
+ role: "tab",
49902
+ "aria-selected": pathname === "/live-monitor" || pathname.startsWith("/live-monitor/"),
49903
+ children: [
49904
+ /* @__PURE__ */ jsx(VideoCameraIcon, { className: "w-5 h-5 mb-1" }),
49905
+ /* @__PURE__ */ jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Monitor" })
49906
+ ]
49907
+ }
49908
+ )
49909
+ ] }),
49490
49910
  /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
49491
49911
  canAccessPath("/leaderboard") && /* @__PURE__ */ jsxs(
49492
49912
  "button",
@@ -49566,22 +49986,55 @@ var SideNavBar = memo$1(({
49566
49986
  )
49567
49987
  ] })
49568
49988
  ] }),
49569
- settingsItems.length > 0 && /* @__PURE__ */ jsx("div", { className: "w-full py-5 px-4 border-t border-gray-100 flex-shrink-0", children: /* @__PURE__ */ jsxs(
49570
- "button",
49571
- {
49572
- ref: settingsTriggerRef,
49573
- onClick: () => setIsSettingsOpen(!isSettingsOpen),
49574
- className: settingsButtonClasses,
49575
- "aria-label": "Settings",
49576
- tabIndex: 0,
49577
- role: "tab",
49578
- "aria-selected": isSettingsOpen || settingsItems.some((item) => item.isActive),
49579
- children: [
49580
- /* @__PURE__ */ jsx(Cog6ToothIcon, { className: "w-5 h-5 mb-1" }),
49581
- /* @__PURE__ */ jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Settings" })
49582
- ]
49583
- }
49584
- ) })
49989
+ /* @__PURE__ */ jsxs("div", { className: "w-full py-4 px-4 border-t border-gray-100 flex-shrink-0 flex flex-col gap-2", children: [
49990
+ showAlertsButton && /* @__PURE__ */ jsxs(
49991
+ "button",
49992
+ {
49993
+ ref: alertsTriggerRef,
49994
+ onClick: () => {
49995
+ setIsAlertsOpen(!isAlertsOpen);
49996
+ setIsSettingsOpen(false);
49997
+ if (!isAlertsOpen) {
49998
+ void refreshAlertsSummary();
49999
+ }
50000
+ },
50001
+ className: alertsButtonClasses,
50002
+ "aria-label": "Alerts",
50003
+ tabIndex: 0,
50004
+ role: "tab",
50005
+ "aria-selected": isAlertsOpen,
50006
+ children: [
50007
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
50008
+ /* @__PURE__ */ jsx(BellIcon, { className: "w-5 h-5 mb-1" }),
50009
+ alertsCount > 0 && /* @__PURE__ */ jsxs("span", { className: "absolute -top-1 -right-1 flex h-2.5 w-2.5", children: [
50010
+ /* @__PURE__ */ jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-red-400 opacity-75" }),
50011
+ /* @__PURE__ */ jsx("span", { className: "relative inline-flex rounded-full h-2.5 w-2.5 bg-red-500" })
50012
+ ] })
50013
+ ] }),
50014
+ /* @__PURE__ */ jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight mt-1", children: "Alerts" })
50015
+ ]
50016
+ }
50017
+ ),
50018
+ settingsItems.length > 0 && /* @__PURE__ */ jsxs(
50019
+ "button",
50020
+ {
50021
+ ref: settingsTriggerRef,
50022
+ onClick: () => {
50023
+ setIsSettingsOpen(!isSettingsOpen);
50024
+ setIsAlertsOpen(false);
50025
+ },
50026
+ className: settingsButtonClasses,
50027
+ "aria-label": "Settings",
50028
+ tabIndex: 0,
50029
+ role: "tab",
50030
+ "aria-selected": isSettingsOpen || settingsItems.some((item) => item.isActive),
50031
+ children: [
50032
+ /* @__PURE__ */ jsx(Cog6ToothIcon, { className: "w-5 h-5 mb-1" }),
50033
+ /* @__PURE__ */ jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Settings" })
50034
+ ]
50035
+ }
50036
+ )
50037
+ ] })
49585
50038
  ] });
49586
50039
  const MobileNavigationContent = () => {
49587
50040
  const isActive = (path) => {
@@ -49616,6 +50069,18 @@ var SideNavBar = memo$1(({
49616
50069
  ]
49617
50070
  }
49618
50071
  ),
50072
+ showLiveMonitorLink && canAccessPath("/live-monitor") && /* @__PURE__ */ jsxs(
50073
+ "button",
50074
+ {
50075
+ onClick: handleMobileNavClick(handleLiveClick),
50076
+ className: `${getMobileButtonClass("/live-monitor")} mt-2`,
50077
+ "aria-label": "Monitor",
50078
+ children: [
50079
+ /* @__PURE__ */ jsx(VideoCameraIcon, { className: getIconClass("/live-monitor") }),
50080
+ /* @__PURE__ */ jsx("span", { className: "text-base font-medium", children: "Monitor" })
50081
+ ]
50082
+ }
50083
+ ),
49619
50084
  /* @__PURE__ */ jsxs("div", { className: "mt-6 space-y-2", children: [
49620
50085
  canAccessPath("/leaderboard") && /* @__PURE__ */ jsxs(
49621
50086
  "button",
@@ -49679,9 +50144,31 @@ var SideNavBar = memo$1(({
49679
50144
  }
49680
50145
  )
49681
50146
  ] }),
49682
- settingsItems.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-8 pt-6 border-t border-gray-100", children: [
50147
+ /* @__PURE__ */ jsxs("div", { className: "mt-8 pt-6 border-t border-gray-100", children: [
49683
50148
  /* @__PURE__ */ jsx("h3", { className: "px-5 mb-3 text-[10px] font-bold text-gray-400 uppercase tracking-widest", children: "Settings & Support" }),
49684
50149
  /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
50150
+ showAlertsButton && /* @__PURE__ */ jsxs(
50151
+ "button",
50152
+ {
50153
+ onClick: () => {
50154
+ setIsAlertsOpen(true);
50155
+ void refreshAlertsSummary();
50156
+ onMobileMenuClose?.();
50157
+ },
50158
+ className: getMobileButtonClass("/alerts"),
50159
+ "aria-label": "Alerts",
50160
+ children: [
50161
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
50162
+ /* @__PURE__ */ jsx(BellIcon, { className: getIconClass("/alerts") }),
50163
+ alertsCount > 0 && /* @__PURE__ */ jsxs("span", { className: "absolute -top-1 -right-1 flex h-2.5 w-2.5", children: [
50164
+ /* @__PURE__ */ jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-red-400 opacity-75" }),
50165
+ /* @__PURE__ */ jsx("span", { className: "relative inline-flex rounded-full h-2.5 w-2.5 bg-red-500" })
50166
+ ] })
50167
+ ] }),
50168
+ /* @__PURE__ */ jsx("span", { className: "text-base font-medium ml-3", children: "Alerts" })
50169
+ ]
50170
+ }
50171
+ ),
49685
50172
  canAccessPath("/targets") && /* @__PURE__ */ jsxs(
49686
50173
  "button",
49687
50174
  {
@@ -49796,7 +50283,18 @@ var SideNavBar = memo$1(({
49796
50283
  ] }),
49797
50284
  /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ jsx(MobileNavigationContent, {}) })
49798
50285
  ] })
49799
- ] })
50286
+ ] }),
50287
+ /* @__PURE__ */ jsx(
50288
+ AlertsPopup,
50289
+ {
50290
+ isOpen: isAlertsOpen,
50291
+ onClose: () => setIsAlertsOpen(false),
50292
+ triggerRef: alertsTriggerRef,
50293
+ companyId: alertsCompanyId,
50294
+ alertsCount,
50295
+ onAlertsLoaded: setAlertsCount
50296
+ }
50297
+ )
49800
50298
  ] });
49801
50299
  });
49802
50300
  SideNavBar.displayName = "SideNavBar";
@@ -49973,7 +50471,7 @@ var AwardBadge = ({
49973
50471
  }) => {
49974
50472
  const styles2 = getBadgeStyles(type);
49975
50473
  const Icon2 = CustomIcon || getDefaultIcon(type);
49976
- const randomDelay = React26__default.useMemo(() => Math.random() * 2, []);
50474
+ const randomDelay = React141__default.useMemo(() => Math.random() * 2, []);
49977
50475
  const floatingAnimation = {
49978
50476
  animate: {
49979
50477
  y: [0, -10, 0],
@@ -52003,18 +52501,20 @@ var InviteUserDialog = ({
52003
52501
  const [isSubmitting, setIsSubmitting] = useState(false);
52004
52502
  const [error, setError] = useState(null);
52005
52503
  const isSuperAdminOptifye = user?.role_level === "optifye" && (user?.scope_mode === "SUPER_ADMIN" || !!user?.access_scope?.is_super_admin);
52006
- const canInviteOwner = isSuperAdminOptifye;
52007
- const canInviteIT = user?.role_level === "owner" || user?.role_level === "optifye";
52008
- const canInvitePlantHead = user?.role_level === "owner" || user?.role_level === "it" || user?.role_level === "optifye";
52009
- const canInviteSupervisor = ["owner", "it", "plant_head", "optifye"].includes(user?.role_level || "");
52504
+ const canInviteOwner = canRoleInviteRole(user?.role_level, "owner", { isSuperAdminOptifye });
52505
+ const canInviteIT = canRoleInviteRole(user?.role_level, "it", { isSuperAdminOptifye });
52506
+ const canInvitePlantHead = canRoleInviteRole(user?.role_level, "plant_head", { isSuperAdminOptifye });
52507
+ const canInviteIndustrialEngineer = canRoleInviteRole(user?.role_level, "industrial_engineer", { isSuperAdminOptifye });
52508
+ const canInviteSupervisor = canRoleInviteRole(user?.role_level, "supervisor", { isSuperAdminOptifye });
52010
52509
  const invitableRoles = useMemo(() => {
52011
52510
  const roles = [];
52012
52511
  if (canInviteOwner) roles.push("owner");
52013
52512
  if (canInviteIT) roles.push("it");
52014
52513
  if (canInvitePlantHead) roles.push("plant_head");
52514
+ if (canInviteIndustrialEngineer) roles.push("industrial_engineer");
52015
52515
  if (canInviteSupervisor) roles.push("supervisor");
52016
52516
  return roles;
52017
- }, [canInviteOwner, canInviteIT, canInvitePlantHead, canInviteSupervisor]);
52517
+ }, [canInviteOwner, canInviteIT, canInvitePlantHead, canInviteIndustrialEngineer, canInviteSupervisor]);
52018
52518
  const filteredLines = useMemo(() => {
52019
52519
  const search = lineSearch.trim().toLowerCase();
52020
52520
  if (!search) return availableLines;
@@ -52091,6 +52591,10 @@ var InviteUserDialog = ({
52091
52591
  setError("Only super-admin Optifye users can create owner users.");
52092
52592
  return;
52093
52593
  }
52594
+ if (selectedRole === "industrial_engineer" && selectedFactories.length === 0) {
52595
+ setError("Select at least one factory for an industrial engineer.");
52596
+ return;
52597
+ }
52094
52598
  const companyId = entityConfig?.companyId || user?.properties?.company_id;
52095
52599
  if (!companyId) {
52096
52600
  setError("Company ID not found. Please refresh and try again.");
@@ -52114,7 +52618,7 @@ var InviteUserDialog = ({
52114
52618
  role_level: selectedRole,
52115
52619
  company_id: companyId,
52116
52620
  line_ids: selectedRole === "supervisor" ? selectedLines : void 0,
52117
- factory_ids: selectedRole === "plant_head" ? selectedFactories : void 0,
52621
+ factory_ids: isFactoryScopedRole(selectedRole) ? selectedFactories : void 0,
52118
52622
  created_by: user?.id
52119
52623
  }
52120
52624
  });
@@ -52352,6 +52856,33 @@ var InviteUserDialog = ({
52352
52856
  ]
52353
52857
  }
52354
52858
  ),
52859
+ canInviteIndustrialEngineer && /* @__PURE__ */ jsxs(
52860
+ "label",
52861
+ {
52862
+ className: cn(
52863
+ "flex items-start gap-3 p-4 border-2 rounded-lg cursor-pointer transition-all duration-200",
52864
+ selectedRole === "industrial_engineer" ? "border-amber-500 bg-amber-50" : "border-gray-200 hover:border-gray-300 hover:bg-gray-50"
52865
+ ),
52866
+ children: [
52867
+ /* @__PURE__ */ jsx(
52868
+ "input",
52869
+ {
52870
+ type: "radio",
52871
+ name: "role",
52872
+ value: "industrial_engineer",
52873
+ checked: selectedRole === "industrial_engineer",
52874
+ onChange: (e) => setSelectedRole(e.target.value),
52875
+ className: "mt-1",
52876
+ disabled: isSubmitting
52877
+ }
52878
+ ),
52879
+ /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
52880
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 mb-1", children: /* @__PURE__ */ jsx(RoleBadge_default, { role: "industrial_engineer", size: "sm" }) }),
52881
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600", children: "Factory-level access. Can manage supervisors and factory performance scope." })
52882
+ ] })
52883
+ ]
52884
+ }
52885
+ ),
52355
52886
  canInviteSupervisor && /* @__PURE__ */ jsxs(
52356
52887
  "label",
52357
52888
  {
@@ -52381,14 +52912,18 @@ var InviteUserDialog = ({
52381
52912
  )
52382
52913
  ] })
52383
52914
  ] }),
52384
- selectedRole === "plant_head" && /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-slate-200 bg-slate-50 p-4 space-y-3", children: [
52915
+ isFactoryScopedRole(selectedRole) && /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-slate-200 bg-slate-50 p-4 space-y-3", children: [
52385
52916
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
52386
52917
  /* @__PURE__ */ jsxs("div", { children: [
52387
52918
  /* @__PURE__ */ jsxs("p", { className: "text-sm font-medium text-gray-800 flex items-center gap-1.5", children: [
52388
52919
  /* @__PURE__ */ jsx(Building2, { className: "w-4 h-4 text-blue-600" }),
52389
52920
  "Factory Access"
52390
52921
  ] }),
52391
- /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1", children: "Choose the factories this plant head will manage." })
52922
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-500 mt-1", children: [
52923
+ "Choose the factories this ",
52924
+ selectedRole === "industrial_engineer" ? "industrial engineer" : "plant head",
52925
+ " will manage."
52926
+ ] })
52392
52927
  ] }),
52393
52928
  /* @__PURE__ */ jsxs("span", { className: "text-xs font-medium bg-white border border-gray-200 text-gray-600 rounded-full px-2 py-1", children: [
52394
52929
  selectedFactories.length,
@@ -52613,16 +53148,6 @@ var InviteUserDialog = ({
52613
53148
  }
52614
53149
  );
52615
53150
  };
52616
- var getRoleLabel = (role) => {
52617
- const labels = {
52618
- "supervisor": "Supervisor",
52619
- "plant_head": "Plant Head",
52620
- "it": "IT",
52621
- "owner": "Owner",
52622
- "optifye": "Optifye Admin"
52623
- };
52624
- return labels[role] || role;
52625
- };
52626
53151
  var ChangeRoleDialog = ({
52627
53152
  user,
52628
53153
  availableRoles,
@@ -53574,7 +54099,7 @@ var FactoryAssignmentDropdown = ({
53574
54099
  )
53575
54100
  ] });
53576
54101
  };
53577
- function formatDuration(ms) {
54102
+ function formatDuration2(ms) {
53578
54103
  if (ms === void 0 || ms === null) return "No data";
53579
54104
  if (ms === 0) return "0m";
53580
54105
  const hours = Math.floor(ms / (1e3 * 60 * 60));
@@ -53618,7 +54143,7 @@ var UserUsageStats = ({
53618
54143
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
53619
54144
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-sm", children: [
53620
54145
  /* @__PURE__ */ jsx(Clock, { className: "w-3.5 h-3.5 text-gray-400" }),
53621
- /* @__PURE__ */ jsx("span", { className: hasUsage ? getUsageColorClass(todayUsage.total_ms) : "text-gray-400", children: formatDuration(todayUsage?.total_ms) })
54146
+ /* @__PURE__ */ jsx("span", { className: hasUsage ? getUsageColorClass(todayUsage.total_ms) : "text-gray-400", children: formatDuration2(todayUsage?.total_ms) })
53622
54147
  ] }),
53623
54148
  showViewButton && onViewDetails && /* @__PURE__ */ jsx(
53624
54149
  "button",
@@ -53634,14 +54159,14 @@ var UserUsageStats = ({
53634
54159
  /* @__PURE__ */ jsx(Activity, { className: "w-3 h-3 text-green-500" }),
53635
54160
  /* @__PURE__ */ jsxs("span", { children: [
53636
54161
  "Active: ",
53637
- formatDuration(todayUsage?.active_ms)
54162
+ formatDuration2(todayUsage?.active_ms)
53638
54163
  ] })
53639
54164
  ] }),
53640
54165
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
53641
54166
  /* @__PURE__ */ jsx(Eye, { className: "w-3 h-3 text-amber-500" }),
53642
54167
  /* @__PURE__ */ jsxs("span", { children: [
53643
54168
  "Passive: ",
53644
- formatDuration(todayUsage?.passive_ms)
54169
+ formatDuration2(todayUsage?.passive_ms)
53645
54170
  ] })
53646
54171
  ] })
53647
54172
  ] })
@@ -53836,7 +54361,7 @@ function DailyBarChart({
53836
54361
  /* @__PURE__ */ jsx("div", { className: "w-2 h-2 rounded-full bg-gray-300" }),
53837
54362
  /* @__PURE__ */ jsxs("span", { className: "text-sm font-medium text-gray-600", children: [
53838
54363
  "Average Daily usage: ",
53839
- /* @__PURE__ */ jsx("span", { className: "text-gray-900 font-semibold", children: avgDailyMs > 0 ? formatDuration(avgDailyMs) : "0m" })
54364
+ /* @__PURE__ */ jsx("span", { className: "text-gray-900 font-semibold", children: avgDailyMs > 0 ? formatDuration2(avgDailyMs) : "0m" })
53840
54365
  ] })
53841
54366
  ] }),
53842
54367
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-6 text-xs font-medium text-gray-500", children: [
@@ -53929,7 +54454,7 @@ function DailyBarChart({
53929
54454
  hasData ? /* @__PURE__ */ jsxs(Fragment, { children: [
53930
54455
  /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-2", children: [
53931
54456
  /* @__PURE__ */ jsx("span", { className: "text-gray-500 text-xs", children: "Total" }),
53932
- /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-900 text-sm", children: formatDuration(data.total_duration_ms) })
54457
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-900 text-sm", children: formatDuration2(data.total_duration_ms) })
53933
54458
  ] }),
53934
54459
  /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
53935
54460
  /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center text-xs", children: [
@@ -53937,14 +54462,14 @@ function DailyBarChart({
53937
54462
  /* @__PURE__ */ jsx("div", { className: "w-1.5 h-1.5 bg-green-500 rounded-full" }),
53938
54463
  "Active"
53939
54464
  ] }),
53940
- /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-700", children: formatDuration(data.active_duration_ms) })
54465
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-700", children: formatDuration2(data.active_duration_ms) })
53941
54466
  ] }),
53942
54467
  /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center text-xs", children: [
53943
54468
  /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-gray-500", children: [
53944
54469
  /* @__PURE__ */ jsx("div", { className: "w-1.5 h-1.5 bg-amber-400 rounded-full" }),
53945
54470
  "Passive"
53946
54471
  ] }),
53947
- /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-700", children: formatDuration(data.passive_duration_ms) })
54472
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-700", children: formatDuration2(data.passive_duration_ms) })
53948
54473
  ] })
53949
54474
  ] })
53950
54475
  ] }) : /* @__PURE__ */ jsx("div", { className: "text-gray-400 text-xs italic", children: "No data recorded" })
@@ -54075,15 +54600,7 @@ var UserManagementTable = ({
54075
54600
  const permissions = useTeamManagementPermissions();
54076
54601
  const { user: currentUser } = useAuth();
54077
54602
  const availableRoles = useMemo(() => {
54078
- const currentRole = currentUser?.role_level;
54079
- const roleHierarchy = {
54080
- "optifye": ["optifye", "owner", "it", "plant_head", "supervisor"],
54081
- "owner": ["owner", "it", "plant_head", "supervisor"],
54082
- "it": ["it", "plant_head", "supervisor"],
54083
- "plant_head": ["plant_head", "supervisor"],
54084
- "supervisor": ["supervisor"]
54085
- };
54086
- return roleHierarchy[currentRole] || ["supervisor"];
54603
+ return getVisibleRolesForCurrentUser(currentUser?.role_level);
54087
54604
  }, [currentUser]);
54088
54605
  const [searchTerm, setSearchTerm] = useState("");
54089
54606
  const [roleFilter, setRoleFilter] = useState("all");
@@ -54180,10 +54697,48 @@ var UserManagementTable = ({
54180
54697
  }
54181
54698
  return [];
54182
54699
  };
54700
+ const getLineIdsFromUser = (user) => {
54701
+ const properties = user.properties || {};
54702
+ const rawLineIds = properties.line_ids ?? properties.line_id;
54703
+ if (Array.isArray(rawLineIds)) {
54704
+ return rawLineIds.filter((lineId) => typeof lineId === "string" && lineId.length > 0);
54705
+ }
54706
+ if (typeof rawLineIds === "string" && rawLineIds.length > 0) {
54707
+ return [rawLineIds];
54708
+ }
54709
+ return [];
54710
+ };
54711
+ const canOfferIndustrialEngineerRole = (user) => {
54712
+ if (getFactoryIdsFromUser(user).length > 0) {
54713
+ return true;
54714
+ }
54715
+ const lineIds = getLineIdsFromUser(user);
54716
+ if (lineIds.length === 0) {
54717
+ return false;
54718
+ }
54719
+ const lineFactoryById = new Map(
54720
+ availableLines.map((line) => [line.id, line.factory_id])
54721
+ );
54722
+ return lineIds.some((lineId) => {
54723
+ const factoryId = lineFactoryById.get(lineId);
54724
+ return typeof factoryId === "string" && factoryId.length > 0;
54725
+ });
54726
+ };
54727
+ const getAvailableRolesForUser = (user) => {
54728
+ const baseRoles = permissions.availableRolesToAssign();
54729
+ let filteredRoles = baseRoles;
54730
+ if (baseRoles.includes("industrial_engineer") && !canOfferIndustrialEngineerRole(user)) {
54731
+ filteredRoles = baseRoles.filter((role) => role !== "industrial_engineer");
54732
+ }
54733
+ if (!filteredRoles.includes(user.role_level)) {
54734
+ return [user.role_level, ...filteredRoles];
54735
+ }
54736
+ return filteredRoles;
54737
+ };
54183
54738
  const formatAssignments = (user) => {
54184
54739
  if (user.role_level === "owner" || user.role_level === "it") return "Company-wide";
54185
54740
  if (user.role_level === "optifye") return "All companies";
54186
- if (user.role_level === "plant_head") {
54741
+ if (isFactoryScopedRole(user.role_level)) {
54187
54742
  if (user.assigned_factories && user.assigned_factories.length > 0) {
54188
54743
  return user.assigned_factories.join(", ");
54189
54744
  }
@@ -54264,11 +54819,12 @@ var UserManagementTable = ({
54264
54819
  className: "px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white",
54265
54820
  children: [
54266
54821
  /* @__PURE__ */ jsx("option", { value: "all", children: "All Roles" }),
54267
- availableRoles.includes("optifye") && /* @__PURE__ */ jsx("option", { value: "optifye", children: "Optifye" }),
54268
- availableRoles.includes("owner") && /* @__PURE__ */ jsx("option", { value: "owner", children: "Owner" }),
54269
- availableRoles.includes("it") && /* @__PURE__ */ jsx("option", { value: "it", children: "IT" }),
54270
- availableRoles.includes("plant_head") && /* @__PURE__ */ jsx("option", { value: "plant_head", children: "Plant Head" }),
54271
- availableRoles.includes("supervisor") && /* @__PURE__ */ jsx("option", { value: "supervisor", children: "Supervisor" })
54822
+ availableRoles.includes("optifye") && /* @__PURE__ */ jsx("option", { value: "optifye", children: getRoleLabel("optifye") }),
54823
+ availableRoles.includes("owner") && /* @__PURE__ */ jsx("option", { value: "owner", children: getRoleLabel("owner") }),
54824
+ availableRoles.includes("it") && /* @__PURE__ */ jsx("option", { value: "it", children: getRoleLabel("it") }),
54825
+ availableRoles.includes("plant_head") && /* @__PURE__ */ jsx("option", { value: "plant_head", children: getRoleLabel("plant_head") }),
54826
+ availableRoles.includes("industrial_engineer") && /* @__PURE__ */ jsx("option", { value: "industrial_engineer", children: getRoleLabel("industrial_engineer") }),
54827
+ availableRoles.includes("supervisor") && /* @__PURE__ */ jsx("option", { value: "supervisor", children: getRoleLabel("supervisor") })
54272
54828
  ]
54273
54829
  }
54274
54830
  )
@@ -54386,7 +54942,7 @@ var UserManagementTable = ({
54386
54942
  onUpdate: onLineAssignmentUpdate || (async () => {
54387
54943
  })
54388
54944
  }
54389
- ) : user.role_level === "plant_head" ? (() => {
54945
+ ) : isFactoryScopedRole(user.role_level) ? (() => {
54390
54946
  const canEditFactoryAssignments = permissions.canAssignFactories(user) && !!onFactoryAssignmentUpdate;
54391
54947
  if (!canEditFactoryAssignments) {
54392
54948
  return /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-900", children: formatAssignments(user) });
@@ -54416,7 +54972,7 @@ var UserManagementTable = ({
54416
54972
  setShowUsageDetailModal(true);
54417
54973
  },
54418
54974
  className: "group flex items-center gap-3 hover:bg-gray-50 -mx-2 px-2 py-1.5 rounded-lg transition-all duration-200",
54419
- children: isUsageLoading ? /* @__PURE__ */ jsx("div", { className: "animate-pulse bg-gray-200 h-5 w-20 rounded" }) : /* @__PURE__ */ jsx("span", { className: `text-base font-semibold ${avgDailyUsage?.[user.user_id] && avgDailyUsage[user.user_id] > 0 ? "text-gray-900 group-hover:text-blue-600" : "text-gray-400"} transition-colors`, children: formatDuration(avgDailyUsage?.[user.user_id] || 0) })
54975
+ children: isUsageLoading ? /* @__PURE__ */ jsx("div", { className: "animate-pulse bg-gray-200 h-5 w-20 rounded" }) : /* @__PURE__ */ jsx("span", { className: `text-base font-semibold ${avgDailyUsage?.[user.user_id] && avgDailyUsage[user.user_id] > 0 ? "text-gray-900 group-hover:text-blue-600" : "text-gray-400"} transition-colors`, children: formatDuration2(avgDailyUsage?.[user.user_id] || 0) })
54420
54976
  }
54421
54977
  ) : /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-400", children: "-" }) }),
54422
54978
  /* @__PURE__ */ jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right", children: hasActions && /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(
@@ -54566,7 +55122,7 @@ var UserManagementTable = ({
54566
55122
  ChangeRoleDialog,
54567
55123
  {
54568
55124
  user: selectedUser,
54569
- availableRoles: permissions.availableRolesToAssign(),
55125
+ availableRoles: getAvailableRolesForUser(selectedUser),
54570
55126
  onConfirm: handleRoleChangeConfirm,
54571
55127
  onClose: () => {
54572
55128
  setShowChangeRoleDialog(false);
@@ -56305,7 +56861,7 @@ function HomeView({
56305
56861
  animate: { opacity: 1, scale: 1 },
56306
56862
  transition: { duration: 0.3 },
56307
56863
  className: "h-full",
56308
- children: React26__default.createElement(WorkspaceGrid, {
56864
+ children: React141__default.createElement(WorkspaceGrid, {
56309
56865
  workspaces: workspaceMetrics,
56310
56866
  lineNames,
56311
56867
  factoryView: factoryViewId,
@@ -56336,7 +56892,7 @@ function HomeView({
56336
56892
  animate: { opacity: 1, scale: 1 },
56337
56893
  transition: { duration: 0.3 },
56338
56894
  className: "h-full",
56339
- children: React26__default.createElement(WorkspaceGrid, {
56895
+ children: React141__default.createElement(WorkspaceGrid, {
56340
56896
  workspaces: [],
56341
56897
  // Show empty grid while loading
56342
56898
  lineNames,
@@ -56403,7 +56959,7 @@ function HomeView({
56403
56959
  }
56404
56960
  );
56405
56961
  }
56406
- var AuthenticatedHomeView = withAuth(React26__default.memo(HomeView));
56962
+ var AuthenticatedHomeView = withAuth(React141__default.memo(HomeView));
56407
56963
  var HomeView_default = HomeView;
56408
56964
  function withWorkspaceDisplayNames(Component3, options = {}) {
56409
56965
  const {
@@ -56813,7 +57369,7 @@ var MonthlyRangeFilter = ({
56813
57369
  label: "This Month",
56814
57370
  getValue: () => ({
56815
57371
  start: startOfMonth(/* @__PURE__ */ new Date()),
56816
- end: endOfMonth(/* @__PURE__ */ new Date())
57372
+ end: endOfDay(/* @__PURE__ */ new Date())
56817
57373
  })
56818
57374
  }
56819
57375
  ];
@@ -56837,6 +57393,7 @@ var MonthlyRangeFilter = ({
56837
57393
  const [rangeEnd, setRangeEnd] = useState(parseDateKeyToDate(normalizedRange.endKey));
56838
57394
  const [selecting, setSelecting] = useState(false);
56839
57395
  const [activePreset, setActivePreset] = useState(null);
57396
+ const today = useMemo(() => endOfDay(/* @__PURE__ */ new Date()), []);
56840
57397
  useEffect(() => {
56841
57398
  setCalendarMonth(month);
56842
57399
  setCalendarYear(year);
@@ -56867,6 +57424,9 @@ var MonthlyRangeFilter = ({
56867
57424
  return () => document.removeEventListener("mousedown", handleClickOutside);
56868
57425
  }, []);
56869
57426
  const handleDayClick = (day) => {
57427
+ if (startOfDay(day) > startOfDay(today)) {
57428
+ return;
57429
+ }
56870
57430
  setActivePreset("Custom");
56871
57431
  if (!selecting || !rangeStart) {
56872
57432
  setRangeStart(day);
@@ -56899,9 +57459,13 @@ var MonthlyRangeFilter = ({
56899
57459
  };
56900
57460
  const handleApply = () => {
56901
57461
  if (rangeStart) {
56902
- const endDate = rangeEnd || rangeStart;
56903
- const startKey = format(rangeStart, "yyyy-MM-dd");
56904
- const endKey = format(endDate, "yyyy-MM-dd");
57462
+ const boundedStart = startOfDay(rangeStart) > startOfDay(today) ? startOfDay(today) : startOfDay(rangeStart);
57463
+ const candidateEnd = rangeEnd || rangeStart;
57464
+ const boundedEnd = startOfDay(candidateEnd) > startOfDay(today) ? startOfDay(today) : startOfDay(candidateEnd);
57465
+ const start = boundedStart <= boundedEnd ? boundedStart : boundedEnd;
57466
+ const end = boundedStart <= boundedEnd ? boundedEnd : boundedStart;
57467
+ const startKey = format(start, "yyyy-MM-dd");
57468
+ const endKey = format(end, "yyyy-MM-dd");
56905
57469
  onChange({ startKey, endKey });
56906
57470
  setIsOpen(false);
56907
57471
  }
@@ -57082,6 +57646,7 @@ var MonthlyRangeFilter = ({
57082
57646
  const isEnd = isRangeEnd(day);
57083
57647
  const isSingleDaySelection = isStart && (!rangeEnd || rangeEnd && isSameDay(rangeStart, rangeEnd));
57084
57648
  const dayNum = day.getDate();
57649
+ const isFutureDay = startOfDay(day) > startOfDay(today);
57085
57650
  return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
57086
57651
  inRange && !isStart && !isEnd && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 -inset-x-0.5 bg-[#EEF2FF] z-0" }),
57087
57652
  inRange && isStart && !isSingleDaySelection && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 left-1/2 bg-[#EEF2FF] z-0" }),
@@ -57091,10 +57656,12 @@ var MonthlyRangeFilter = ({
57091
57656
  {
57092
57657
  type: "button",
57093
57658
  onClick: () => handleDayClick(day),
57659
+ disabled: isFutureDay,
57094
57660
  className: clsx(
57095
57661
  "h-10 w-full flex items-center justify-center text-sm font-semibold transition-all duration-150 relative z-10",
57662
+ isFutureDay && "text-gray-200 cursor-not-allowed",
57096
57663
  // Not in range
57097
- !inRange && "text-gray-700 hover:bg-gray-50 rounded-lg",
57664
+ !isFutureDay && !inRange && "text-gray-700 hover:bg-gray-50 rounded-lg",
57098
57665
  // Middle of range
57099
57666
  inRange && !isStart && !isEnd && "text-[#4F46E5]",
57100
57667
  // Start/End of range or Single selection
@@ -57132,7 +57699,7 @@ var MetricCards = memo$1(({
57132
57699
  variants: containerVariants,
57133
57700
  initial: "initial",
57134
57701
  animate: "animate",
57135
- className: `grid grid-cols-1 sm:grid-cols-2 ${showIdleTime ? "lg:grid-cols-4" : "lg:grid-cols-3"} gap-3 sm:gap-4 mb-2 md:h-[35vh] h-auto`,
57702
+ className: `grid grid-cols-1 sm:grid-cols-2 ${showIdleTime ? "lg:grid-cols-4" : "lg:grid-cols-3"} gap-3 sm:gap-4 mb-2 h-auto lg:flex-[2] lg:min-h-[250px]`,
57136
57703
  children: [
57137
57704
  /* @__PURE__ */ jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
57138
57705
  /* @__PURE__ */ jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 mb-2 text-center", children: "Line Output" }),
@@ -57181,7 +57748,23 @@ var MetricCards = memo$1(({
57181
57748
  if (prevProps.efficiencyLegend !== nextProps.efficiencyLegend) return false;
57182
57749
  const prevMetrics = prevProps.lineInfo.metrics;
57183
57750
  const nextMetrics = nextProps.lineInfo.metrics;
57184
- const idleTimeChanged = prevProps.idleTimeData?.isLoading !== nextProps.idleTimeData?.isLoading || prevProps.idleTimeData?.error !== nextProps.idleTimeData?.error || prevProps.idleTimeData?.chartData?.length !== nextProps.idleTimeData?.chartData?.length || prevProps.idleTimeData?.data?.total_idle_time_seconds !== nextProps.idleTimeData?.data?.total_idle_time_seconds;
57751
+ const prevIdleChartSignature = JSON.stringify(
57752
+ (prevProps.idleTimeData?.chartData || []).map((entry) => ({
57753
+ name: entry.name,
57754
+ value: entry.value,
57755
+ totalDurationSeconds: entry.totalDurationSeconds ?? null,
57756
+ efficiencyLossPercentage: entry.efficiencyLossPercentage ?? null
57757
+ }))
57758
+ );
57759
+ const nextIdleChartSignature = JSON.stringify(
57760
+ (nextProps.idleTimeData?.chartData || []).map((entry) => ({
57761
+ name: entry.name,
57762
+ value: entry.value,
57763
+ totalDurationSeconds: entry.totalDurationSeconds ?? null,
57764
+ efficiencyLossPercentage: entry.efficiencyLossPercentage ?? null
57765
+ }))
57766
+ );
57767
+ const idleTimeChanged = prevProps.idleTimeData?.isLoading !== nextProps.idleTimeData?.isLoading || prevProps.idleTimeData?.error !== nextProps.idleTimeData?.error || prevIdleChartSignature !== nextIdleChartSignature || prevProps.idleTimeData?.data?.total_idle_time_seconds !== nextProps.idleTimeData?.data?.total_idle_time_seconds || prevProps.idleTimeData?.data?.scope_work_seconds !== nextProps.idleTimeData?.data?.scope_work_seconds;
57185
57768
  if (idleTimeChanged) return false;
57186
57769
  return prevMetrics.current_output === nextMetrics.current_output && prevMetrics.line_threshold === nextMetrics.line_threshold && prevMetrics.underperforming_workspaces === nextMetrics.underperforming_workspaces && prevMetrics.total_workspaces === nextMetrics.total_workspaces && prevMetrics.avg_efficiency === nextMetrics.avg_efficiency;
57187
57770
  });
@@ -57200,7 +57783,7 @@ var LineUptimeMetricCards = memo$1(({
57200
57783
  variants: containerVariants,
57201
57784
  initial: "initial",
57202
57785
  animate: "animate",
57203
- className: `grid grid-cols-1 sm:grid-cols-2 ${showIdleTime ? "lg:grid-cols-4" : "lg:grid-cols-3"} gap-3 sm:gap-4 mb-2 md:h-[35vh] h-auto`,
57786
+ className: `grid grid-cols-1 sm:grid-cols-2 ${showIdleTime ? "lg:grid-cols-4" : "lg:grid-cols-3"} gap-3 sm:gap-4 mb-2 h-auto lg:flex-[2] lg:min-h-[250px]`,
57204
57787
  children: [
57205
57788
  /* @__PURE__ */ jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
57206
57789
  /* @__PURE__ */ jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 mb-2 text-center", children: "Utilization" }),
@@ -57268,7 +57851,7 @@ var BottomSection = memo$1(({
57268
57851
  variants: containerVariants,
57269
57852
  initial: "initial",
57270
57853
  animate: "animate",
57271
- className: "grid grid-cols-1 lg:grid-cols-5 gap-3 sm:gap-4 md:h-[calc(57vh-4rem)] h-auto md:mt-0 mt-4",
57854
+ className: "grid grid-cols-1 lg:grid-cols-5 gap-3 sm:gap-4 h-auto mt-4 lg:mt-0 lg:flex-[3] lg:min-h-[300px]",
57272
57855
  children: [
57273
57856
  /* @__PURE__ */ jsxs(motion.div, { variants: itemVariants, className: "lg:col-span-2 bg-white rounded-xl shadow-sm p-3 sm:p-4 flex flex-col overflow-hidden h-[350px] sm:h-[400px] md:h-auto", children: [
57274
57857
  /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-2", children: [
@@ -57435,7 +58018,7 @@ var UptimeBottomSection = memo$1(({
57435
58018
  variants: containerVariants,
57436
58019
  initial: "initial",
57437
58020
  animate: "animate",
57438
- className: "grid grid-cols-1 lg:grid-cols-5 gap-3 sm:gap-4 md:h-[calc(57vh-4rem)] h-auto md:mt-0 mt-4",
58021
+ className: "grid grid-cols-1 lg:grid-cols-5 gap-3 sm:gap-4 h-auto mt-4 lg:mt-0 lg:flex-[3] lg:min-h-[300px]",
57439
58022
  children: [
57440
58023
  /* @__PURE__ */ jsxs(motion.div, { variants: itemVariants, className: "lg:col-span-2 bg-white rounded-xl shadow-sm p-3 sm:p-4 flex flex-col overflow-hidden h-[350px] sm:h-[400px] md:h-auto", children: [
57441
58024
  /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-2", children: [
@@ -58673,7 +59256,7 @@ var KPIDetailView = ({
58673
59256
  initial: "initial",
58674
59257
  animate: "animate",
58675
59258
  exit: "exit",
58676
- className: "space-y-6 md:space-y-0",
59259
+ className: "space-y-6 md:space-y-0 lg:h-[calc(100vh-12rem)] lg:min-h-0 lg:flex lg:flex-col lg:gap-3",
58677
59260
  children: resolvedLineInfo && /* @__PURE__ */ jsxs(Fragment, { children: [
58678
59261
  isUptimeMode ? /* @__PURE__ */ jsx(
58679
59262
  LineUptimeMetricCards,
@@ -58770,7 +59353,7 @@ var KPIDetailView = ({
58770
59353
  initial: "initial",
58771
59354
  animate: "animate",
58772
59355
  exit: "exit",
58773
- className: "space-y-6 md:space-y-0",
59356
+ className: "space-y-6 md:space-y-0 lg:h-[calc(100vh-12rem)] lg:min-h-0 lg:flex lg:flex-col lg:gap-3",
58774
59357
  children: resolvedLineInfo && /* @__PURE__ */ jsxs(Fragment, { children: [
58775
59358
  isUptimeMode ? /* @__PURE__ */ jsx(
58776
59359
  LineUptimeMetricCards,
@@ -58865,7 +59448,7 @@ var getMonthDateInfo = (timezone) => {
58865
59448
  const monthEndDate = fromZonedTime(`${monthEndKey}T23:59:59`, timezone);
58866
59449
  return { startDate, endDate, monthEndDate };
58867
59450
  };
58868
- var LeaderboardCountdown = ({ targetDate, format: format7, finishedLabel = "Finished", placeholder = "--", onFinished }) => {
59451
+ var LeaderboardCountdown = ({ targetDate, format: format8, finishedLabel = "Finished", placeholder = "--", onFinished }) => {
58869
59452
  const [time2, setTime] = useState("");
58870
59453
  const hasFinishedRef = useRef(false);
58871
59454
  useEffect(() => {
@@ -58887,7 +59470,7 @@ var LeaderboardCountdown = ({ targetDate, format: format7, finishedLabel = "Fini
58887
59470
  }
58888
59471
  return;
58889
59472
  }
58890
- if (format7 === "days") {
59473
+ if (format8 === "days") {
58891
59474
  const days = Math.floor(diff / (1e3 * 60 * 60 * 24));
58892
59475
  const hours = Math.floor(diff % (1e3 * 60 * 60 * 24) / (1e3 * 60 * 60));
58893
59476
  setTime(`${days} days ${hours} hours`);
@@ -58902,7 +59485,7 @@ var LeaderboardCountdown = ({ targetDate, format: format7, finishedLabel = "Fini
58902
59485
  tick();
58903
59486
  const interval = setInterval(tick, 1e3);
58904
59487
  return () => clearInterval(interval);
58905
- }, [targetDate, format7, finishedLabel, placeholder, onFinished]);
59488
+ }, [targetDate, format8, finishedLabel, placeholder, onFinished]);
58906
59489
  return /* @__PURE__ */ jsx(Fragment, { children: time2 });
58907
59490
  };
58908
59491
  var LinesLeaderboard = ({
@@ -58923,18 +59506,18 @@ var LinesLeaderboard = ({
58923
59506
  setViewType
58924
59507
  }) => {
58925
59508
  const formatEfficiency = (value) => typeof value === "number" && Number.isFinite(value) ? `${value.toFixed(1)}%` : "--";
58926
- const assignedLineIdSet = React26__default.useMemo(
59509
+ const assignedLineIdSet = React141__default.useMemo(
58927
59510
  () => new Set(assignedLineIds || []),
58928
59511
  [assignedLineIds]
58929
59512
  );
58930
- const canClickLine = React26__default.useCallback(
59513
+ const canClickLine = React141__default.useCallback(
58931
59514
  (lineId) => {
58932
59515
  if (!assignedLineIds) return true;
58933
59516
  return assignedLineIdSet.has(lineId);
58934
59517
  },
58935
59518
  [assignedLineIds, assignedLineIdSet]
58936
59519
  );
58937
- const handleTimeRangeChange = React26__default.useCallback((newRange) => {
59520
+ const handleTimeRangeChange = React141__default.useCallback((newRange) => {
58938
59521
  if (newRange === timeRange) return;
58939
59522
  trackCoreEvent("Leaderboard Time Range Changed", {
58940
59523
  from_range: timeRange,
@@ -58945,7 +59528,7 @@ var LinesLeaderboard = ({
58945
59528
  });
58946
59529
  setTimeRange(newRange);
58947
59530
  }, [timeRange, lines.length, monthlyEfficiencyByLineId, setTimeRange]);
58948
- const handleLeaderboardLineClick = React26__default.useCallback((item, clickSource) => {
59531
+ const handleLeaderboardLineClick = React141__default.useCallback((item, clickSource) => {
58949
59532
  if (!canClickLine(item.line.id)) return;
58950
59533
  trackCoreEvent("Leaderboard Line Clicked", {
58951
59534
  line_id: item.line.id,
@@ -58959,8 +59542,8 @@ var LinesLeaderboard = ({
58959
59542
  });
58960
59543
  onLineClick(item.line);
58961
59544
  }, [canClickLine, onLineClick, timeRange]);
58962
- const viewLoadedTrackedRef = React26__default.useRef(null);
58963
- const leaderboardData = React26__default.useMemo(() => {
59545
+ const viewLoadedTrackedRef = React141__default.useRef(null);
59546
+ const leaderboardData = React141__default.useMemo(() => {
58964
59547
  const loading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
58965
59548
  const efficiencyMap = timeRange === "today" ? todayEfficiencyByLineId : monthlyEfficiencyByLineId;
58966
59549
  return lines.map((line) => {
@@ -58991,7 +59574,7 @@ var LinesLeaderboard = ({
58991
59574
  isLoadingToday,
58992
59575
  isLoadingMonthly
58993
59576
  ]);
58994
- React26__default.useEffect(() => {
59577
+ React141__default.useEffect(() => {
58995
59578
  const isLoading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
58996
59579
  const trackingKey = `${timeRange}-${leaderboardData.length}`;
58997
59580
  if (leaderboardData.length > 0 && !isLoading && viewLoadedTrackedRef.current !== trackingKey) {
@@ -59017,7 +59600,7 @@ var LinesLeaderboard = ({
59017
59600
  const countdownTarget = timeRange === "monthly" ? monthEndDate : shiftEndDate;
59018
59601
  const countdownFormat = timeRange === "monthly" ? "days" : "clock";
59019
59602
  const countdownFinishedLabel = timeRange === "monthly" ? "Finished" : "Shift Ended";
59020
- const handleCountdownFinished = React26__default.useCallback(() => {
59603
+ const handleCountdownFinished = React141__default.useCallback(() => {
59021
59604
  trackCoreEvent("Leaderboard Countdown Finished", {
59022
59605
  countdown_type: timeRange === "monthly" ? "month_end" : "shift_end",
59023
59606
  time_range: timeRange,
@@ -59044,7 +59627,7 @@ var LinesLeaderboard = ({
59044
59627
  return "bg-white border-gray-100";
59045
59628
  }
59046
59629
  };
59047
- React26__default.useEffect(() => {
59630
+ React141__default.useEffect(() => {
59048
59631
  const style = document.createElement("style");
59049
59632
  style.innerHTML = `
59050
59633
  @keyframes float {
@@ -59231,7 +59814,7 @@ var LineCard = ({
59231
59814
  supervisors
59232
59815
  }) => {
59233
59816
  const isUptimeLine = (line.monitoring_mode ?? "output") === "uptime";
59234
- const isOnTrack = React26__default.useMemo(() => {
59817
+ const isOnTrack = React141__default.useMemo(() => {
59235
59818
  if (!kpis) return null;
59236
59819
  return isEfficiencyOnTrack(kpis.efficiency.value);
59237
59820
  }, [kpis]);
@@ -59422,46 +60005,46 @@ var KPIsOverviewView = ({
59422
60005
  const configuredTimezone = dbTimezone || dateTimeConfig.defaultTimezone || "UTC";
59423
60006
  const { startDate: monthStartDate, endDate: monthEndDateKey, monthEndDate } = getMonthDateInfo(configuredTimezone);
59424
60007
  const isSuperAdmin = user?.scope_mode === "SUPER_ADMIN" || !!user?.access_scope?.is_super_admin;
59425
- const scopedLineIds = React26__default.useMemo(
60008
+ const scopedLineIds = React141__default.useMemo(
59426
60009
  () => Array.isArray(user?.access_scope?.line_ids) ? user.access_scope.line_ids.filter((lineId) => typeof lineId === "string" && lineId.length > 0) : [],
59427
60010
  [user?.access_scope?.line_ids]
59428
60011
  );
59429
60012
  const hasCanonicalScope = !!user?.scope_mode || !!user?.access_scope;
59430
60013
  const scopeRole = (user?.role_level || user?.role || "").toLowerCase();
59431
- const isStrictLineScopedRole = scopeRole === "supervisor" || scopeRole === "plant_head";
59432
- const resolvedAssignedLineIds = React26__default.useMemo(() => {
60014
+ const isStrictLineScopedRole = scopeRole === "supervisor" || isFactoryScopedRole(scopeRole);
60015
+ const resolvedAssignedLineIds = React141__default.useMemo(() => {
59433
60016
  if (isSuperAdmin) return [];
59434
60017
  if (scopedLineIds.length > 0) return scopedLineIds;
59435
60018
  if (lineIds && lineIds.length > 0) return lineIds;
59436
60019
  if (isStrictLineScopedRole && hasCanonicalScope) return [];
59437
60020
  return [];
59438
60021
  }, [isSuperAdmin, scopedLineIds, lineIds, isStrictLineScopedRole, hasCanonicalScope]);
59439
- const assignedLineIdSet = React26__default.useMemo(
60022
+ const assignedLineIdSet = React141__default.useMemo(
59440
60023
  () => new Set(resolvedAssignedLineIds),
59441
60024
  [resolvedAssignedLineIds]
59442
60025
  );
59443
- const metricsLineIds = React26__default.useMemo(() => {
60026
+ const metricsLineIds = React141__default.useMemo(() => {
59444
60027
  if (isSuperAdmin) {
59445
60028
  return lineIds ?? [];
59446
60029
  }
59447
60030
  return resolvedAssignedLineIds;
59448
60031
  }, [isSuperAdmin, lineIds, resolvedAssignedLineIds]);
59449
60032
  const assignedLineIdsForLeaderboard = isSuperAdmin ? void 0 : resolvedAssignedLineIds;
59450
- const leaderboardLinesForView = React26__default.useMemo(() => {
60033
+ const leaderboardLinesForView = React141__default.useMemo(() => {
59451
60034
  const targetMode = viewType === "machine" ? "uptime" : "output";
59452
60035
  return leaderboardLines.filter((line) => (line.monitoring_mode ?? "output") === targetMode);
59453
60036
  }, [leaderboardLines, viewType]);
59454
- const linesForView = React26__default.useMemo(() => {
60037
+ const linesForView = React141__default.useMemo(() => {
59455
60038
  const targetMode = viewType === "machine" ? "uptime" : "output";
59456
60039
  return lines.filter((line) => (line.monitoring_mode ?? "output") === targetMode);
59457
60040
  }, [lines, viewType]);
59458
- const relevantLinesForMode = React26__default.useMemo(() => {
60041
+ const relevantLinesForMode = React141__default.useMemo(() => {
59459
60042
  if (activeTab === "leaderboard") {
59460
60043
  return leaderboardLines.length > 0 ? leaderboardLines : lines;
59461
60044
  }
59462
60045
  return lines;
59463
60046
  }, [activeTab, leaderboardLines, lines]);
59464
- const { hasUptime, hasOutput } = React26__default.useMemo(() => {
60047
+ const { hasUptime, hasOutput } = React141__default.useMemo(() => {
59465
60048
  let uptime = false;
59466
60049
  let output = false;
59467
60050
  for (const line of relevantLinesForMode) {
@@ -59486,7 +60069,7 @@ var KPIsOverviewView = ({
59486
60069
  const currentShiftDetails = getCurrentShift(configuredTimezone, shiftConfig);
59487
60070
  const currentShiftDate = currentShiftDetails.date;
59488
60071
  const currentShiftId = currentShiftDetails.shiftId;
59489
- const shiftEndDate = React26__default.useMemo(
60072
+ const shiftEndDate = React141__default.useMemo(
59490
60073
  () => getShiftEndDate(currentShiftDetails, configuredTimezone),
59491
60074
  [currentShiftDetails, configuredTimezone]
59492
60075
  );
@@ -59500,15 +60083,15 @@ var KPIsOverviewView = ({
59500
60083
  lineId: factoryViewId,
59501
60084
  userAccessibleLineIds: metricsLineIds
59502
60085
  });
59503
- const defaultKPIs = React26__default.useMemo(() => createDefaultKPIs(), []);
59504
- const kpisByLineId = React26__default.useMemo(() => {
60086
+ const defaultKPIs = React141__default.useMemo(() => createDefaultKPIs(), []);
60087
+ const kpisByLineId = React141__default.useMemo(() => {
59505
60088
  const map = /* @__PURE__ */ new Map();
59506
60089
  lineMetrics.forEach((row) => {
59507
60090
  if (row?.line_id) map.set(row.line_id, buildKPIsFromLineMetricsRow(row));
59508
60091
  });
59509
60092
  return map;
59510
60093
  }, [lineMetrics]);
59511
- const supervisorLineIds = React26__default.useMemo(
60094
+ const supervisorLineIds = React141__default.useMemo(
59512
60095
  () => (leaderboardLines.length > 0 ? leaderboardLines : lines).map((l) => l.id),
59513
60096
  [leaderboardLines, lines]
59514
60097
  );
@@ -60470,7 +61053,7 @@ var LeaderboardDetailView = memo$1(({
60470
61053
  return () => document.removeEventListener("mousedown", handleClickOutside);
60471
61054
  }, []);
60472
61055
  const [isMobile, setIsMobile] = useState(false);
60473
- React26__default.useEffect(() => {
61056
+ React141__default.useEffect(() => {
60474
61057
  const checkMobile = () => setIsMobile(window.innerWidth < 640);
60475
61058
  checkMobile();
60476
61059
  window.addEventListener("resize", checkMobile);
@@ -62729,7 +63312,7 @@ var ShiftsView = ({
62729
63312
  ] })
62730
63313
  ] });
62731
63314
  };
62732
- var AuthenticatedShiftsView = withAuth(React26__default.memo(ShiftsView));
63315
+ var AuthenticatedShiftsView = withAuth(React141__default.memo(ShiftsView));
62733
63316
  var ShiftsView_default = ShiftsView;
62734
63317
 
62735
63318
  // src/views/TargetsView.utils.ts
@@ -64419,7 +65002,7 @@ var TargetsView = ({
64419
65002
  };
64420
65003
  var TargetsViewWithDisplayNames = withAllWorkspaceDisplayNames(TargetsView);
64421
65004
  var TargetsView_default = TargetsViewWithDisplayNames;
64422
- var AuthenticatedTargetsView = withAuth(React26__default.memo(TargetsViewWithDisplayNames));
65005
+ var AuthenticatedTargetsView = withAuth(React141__default.memo(TargetsViewWithDisplayNames));
64423
65006
 
64424
65007
  // src/views/workspace-detail-view.utils.ts
64425
65008
  var formatDateInTimezone = (date = /* @__PURE__ */ new Date(), timezone, options) => {
@@ -64473,25 +65056,6 @@ var getInitialTab = (sourceType, defaultTab, fromMonthly, urlDate) => {
64473
65056
  return "overview";
64474
65057
  };
64475
65058
  var DEBUG_DASHBOARD2 = process.env.NEXT_PUBLIC_DEBUG_DASHBOARD === "true";
64476
- var SHORT_DESKTOP_QUERY = "(min-width: 1024px) and (max-height: 850px)";
64477
- var useMediaQuery = (query) => {
64478
- const [matches, setMatches] = useState(false);
64479
- useEffect(() => {
64480
- if (typeof window === "undefined" || !window.matchMedia) {
64481
- return;
64482
- }
64483
- const mediaQueryList = window.matchMedia(query);
64484
- const onChange = () => setMatches(mediaQueryList.matches);
64485
- onChange();
64486
- if (typeof mediaQueryList.addEventListener === "function") {
64487
- mediaQueryList.addEventListener("change", onChange);
64488
- return () => mediaQueryList.removeEventListener("change", onChange);
64489
- }
64490
- mediaQueryList.addListener(onChange);
64491
- return () => mediaQueryList.removeListener(onChange);
64492
- }, [query]);
64493
- return matches;
64494
- };
64495
65059
  var chartCardVariants = {
64496
65060
  initial: { opacity: 0, y: 10 },
64497
65061
  animate: {
@@ -64569,9 +65133,8 @@ var WorkspaceDetailView = ({
64569
65133
  const [usingFallbackData, setUsingFallbackData] = useState(false);
64570
65134
  const { isIdleTimeVlmEnabled } = useIdleTimeVlmConfig();
64571
65135
  const [showChartIdleTime, setShowChartIdleTime] = useState(false);
64572
- const isShortDesktop = useMediaQuery(SHORT_DESKTOP_QUERY);
64573
- const desktopTopSectionClass = isShortDesktop ? "flex-none min-h-[340px]" : "flex-[3] min-h-0";
64574
- const desktopBottomSectionClass = isShortDesktop ? "flex-none min-h-[300px]" : "flex-[2] min-h-0";
65136
+ const desktopTopSectionClass = "flex-[3] min-h-0";
65137
+ const desktopBottomSectionClass = "flex-[2] min-h-0";
64575
65138
  const dashboardConfig = useDashboardConfig();
64576
65139
  const { legend: efficiencyLegend } = useEfficiencyLegend();
64577
65140
  const prewarmedClipsRef = useRef(/* @__PURE__ */ new Set());
@@ -65159,19 +65722,13 @@ var WorkspaceDetailView = ({
65159
65722
  shiftId: idleClipShiftId,
65160
65723
  enabled: idleClipFetchEnabled
65161
65724
  });
65162
- const handleBackNavigation = () => {
65725
+ const fallbackReturnUrl = returnUrl || "/";
65726
+ const appendReturnUrl = useCallback((params) => {
65163
65727
  if (returnUrl) {
65164
- if (onNavigate) {
65165
- onNavigate(returnUrl);
65166
- }
65167
- return;
65168
- }
65169
- if (activeTab === "monthly_history") {
65170
- if (onNavigate) {
65171
- onNavigate("/");
65172
- }
65173
- return;
65728
+ params.set("returnTo", returnUrl);
65174
65729
  }
65730
+ }, [returnUrl]);
65731
+ const handleBackNavigation = () => {
65175
65732
  if (date || shift) {
65176
65733
  setActiveTab("monthly_history");
65177
65734
  if (onNavigate) {
@@ -65185,8 +65742,22 @@ var WorkspaceDetailView = ({
65185
65742
  if (effectiveLineId) {
65186
65743
  params.set("lineId", effectiveLineId);
65187
65744
  }
65745
+ appendReturnUrl(params);
65188
65746
  onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
65189
65747
  }
65748
+ return;
65749
+ }
65750
+ if (activeTab === "monthly_history") {
65751
+ if (onNavigate) {
65752
+ onNavigate(fallbackReturnUrl);
65753
+ }
65754
+ return;
65755
+ }
65756
+ if (returnUrl) {
65757
+ if (onNavigate) {
65758
+ onNavigate(returnUrl);
65759
+ }
65760
+ return;
65190
65761
  } else {
65191
65762
  if (previousView === "line_monthly_history") {
65192
65763
  setActiveTab("monthly_history");
@@ -65201,11 +65772,12 @@ var WorkspaceDetailView = ({
65201
65772
  if (effectiveLineId) {
65202
65773
  params.set("lineId", effectiveLineId);
65203
65774
  }
65775
+ appendReturnUrl(params);
65204
65776
  onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
65205
65777
  }
65206
65778
  } else {
65207
65779
  if (onNavigate) {
65208
- onNavigate("/");
65780
+ onNavigate(fallbackReturnUrl);
65209
65781
  }
65210
65782
  }
65211
65783
  }
@@ -65264,7 +65836,7 @@ var WorkspaceDetailView = ({
65264
65836
  /* @__PURE__ */ jsx(
65265
65837
  BackButton,
65266
65838
  {
65267
- onClick: () => onNavigate && onNavigate("/"),
65839
+ onClick: () => onNavigate && onNavigate(fallbackReturnUrl),
65268
65840
  text: "Return to Dashboard",
65269
65841
  size: "default",
65270
65842
  "aria-label": "Return to dashboard"
@@ -65278,7 +65850,7 @@ var WorkspaceDetailView = ({
65278
65850
  /* @__PURE__ */ jsx(
65279
65851
  BackButton,
65280
65852
  {
65281
- onClick: () => onNavigate && onNavigate("/"),
65853
+ onClick: () => onNavigate && onNavigate(fallbackReturnUrl),
65282
65854
  text: "Return to Dashboard",
65283
65855
  size: "default",
65284
65856
  "aria-label": "Return to dashboard"
@@ -65549,7 +66121,7 @@ var WorkspaceDetailView = ({
65549
66121
  ] })
65550
66122
  ] }),
65551
66123
  /* @__PURE__ */ jsxs("div", { className: "flex-grow p-1.5 sm:p-2 lg:p-4", children: [
65552
- activeTab === "overview" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full lg:h-[calc(100vh-10rem)] overflow-y-auto lg:min-h-0", children: [
66124
+ activeTab === "overview" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full lg:h-[calc(100vh-12rem)] overflow-y-auto lg:min-h-0 pb-4", children: [
65553
66125
  /* @__PURE__ */ jsxs("div", { className: "block lg:hidden space-y-6 pb-6", children: [
65554
66126
  !shouldShowCycleTimeChart && !isUptimeMode && /* @__PURE__ */ jsxs(
65555
66127
  motion.div,
@@ -65891,6 +66463,7 @@ var WorkspaceDetailView = ({
65891
66463
  if (effectiveLineId) {
65892
66464
  params.set("lineId", effectiveLineId);
65893
66465
  }
66466
+ appendReturnUrl(params);
65894
66467
  onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
65895
66468
  }
65896
66469
  },
@@ -66251,7 +66824,7 @@ var formatTime4 = (date, timezone) => new Intl.DateTimeFormat("en-IN", {
66251
66824
  hour12: true,
66252
66825
  timeZone: timezone
66253
66826
  }).format(date);
66254
- var formatDuration2 = (minutes) => {
66827
+ var formatDuration3 = (minutes) => {
66255
66828
  if (minutes < 1) return "<1 min";
66256
66829
  if (minutes < 60) return `${minutes} min`;
66257
66830
  const hours = Math.floor(minutes / 60);
@@ -66364,7 +66937,7 @@ var UptimeTimelineStrip = ({
66364
66937
  if (segment.length > 1) {
66365
66938
  endDate.setMinutes(endDate.getMinutes() + 1);
66366
66939
  }
66367
- const tooltip = `${STATUS_TITLES[segment.status]} \u2022 ${formatDuration2(segment.length)} (${formatTime4(
66940
+ const tooltip = `${STATUS_TITLES[segment.status]} \u2022 ${formatDuration3(segment.length)} (${formatTime4(
66368
66941
  startDate,
66369
66942
  timezone
66370
66943
  )} - ${formatTime4(endDate, timezone)})`;
@@ -66397,7 +66970,7 @@ var UptimeTimelineStrip = ({
66397
66970
  };
66398
66971
  var UptimeTimelineStrip_default = UptimeTimelineStrip;
66399
66972
  var SHORT_INTERRUPT_THRESHOLD_MINUTES = 3;
66400
- var formatDuration3 = (minutes) => {
66973
+ var formatDuration4 = (minutes) => {
66401
66974
  if (!minutes || minutes <= 0) return "0 min";
66402
66975
  const rounded = Math.max(Math.round(minutes), 0);
66403
66976
  const days = Math.floor(rounded / 1440);
@@ -66416,7 +66989,7 @@ var formatDowntimeLabel2 = (minutes, includeSuffix = true) => {
66416
66989
  if (!minutes || minutes <= 0) {
66417
66990
  return includeSuffix ? "No downtime" : "0 min";
66418
66991
  }
66419
- const label = formatDuration3(minutes);
66992
+ const label = formatDuration4(minutes);
66420
66993
  return includeSuffix ? `${label} down` : label;
66421
66994
  };
66422
66995
  var formatTimeRange = (start, end, timezone) => {
@@ -67172,6 +67745,7 @@ var TeamManagementView = ({
67172
67745
  owners: 0,
67173
67746
  it: 0,
67174
67747
  plantHeads: 0,
67748
+ industrialEngineers: 0,
67175
67749
  supervisors: 0,
67176
67750
  optifye: 0
67177
67751
  });
@@ -67185,8 +67759,8 @@ var TeamManagementView = ({
67185
67759
  }
67186
67760
  return [];
67187
67761
  }, []);
67188
- const plantHeadFactoryIds = useMemo(() => {
67189
- if (user?.role_level !== "plant_head") return [];
67762
+ const factoryScopedRoleFactoryIds = useMemo(() => {
67763
+ if (!isFactoryScopedRole(user?.role_level)) return [];
67190
67764
  const scopedFactoryIds = normalizeIds(user?.access_scope?.factory_ids);
67191
67765
  if (scopedFactoryIds.length > 0) {
67192
67766
  return Array.from(new Set(scopedFactoryIds));
@@ -67204,8 +67778,8 @@ var TeamManagementView = ({
67204
67778
  window.dispatchEvent(new Event("rbac:refresh-scope"));
67205
67779
  }
67206
67780
  }, []);
67207
- const canAddUsers = user?.role_level === "owner" || user?.role_level === "it" || user?.role_level === "plant_head" || user?.role_level === "optifye";
67208
- const canViewUsageStats = user?.role_level === "owner" || user?.role_level === "it" || user?.role_level === "optifye";
67781
+ const canAddUsers = canRoleManageUsers(user?.role_level);
67782
+ const canViewUsageStats = canRoleViewUsageStats(user?.role_level);
67209
67783
  const pageCompanyId = entityConfig?.companyId || user?.properties?.company_id;
67210
67784
  const companyIdForUsage = pageCompanyId;
67211
67785
  const usageDateRange = useMemo(() => {
@@ -67239,8 +67813,8 @@ var TeamManagementView = ({
67239
67813
  }, {});
67240
67814
  }, [usageData, usageDateRange.daysElapsed]);
67241
67815
  const pageTitle = "Team Management";
67242
- const pageDescription = user?.role_level === "owner" || user?.role_level === "it" || user?.role_level === "optifye" ? "Manage team members and view their daily usage" : "Manage supervisors in your factory";
67243
- const hasAccess = user ? user.role_level === void 0 || ["optifye", "owner", "it", "plant_head"].includes(user.role_level) : false;
67816
+ const pageDescription = canViewUsageStats ? "Manage team members and view their daily usage" : "Manage supervisors in your factory";
67817
+ const hasAccess = user ? user.role_level === void 0 || canRoleAccessTeamManagement(user.role_level) : false;
67244
67818
  const loadData = useCallback(async () => {
67245
67819
  if (!supabase) {
67246
67820
  setError("Supabase client not available. Please refresh the page.");
@@ -67287,8 +67861,8 @@ var TeamManagementView = ({
67287
67861
  setAvailableFactories(factories || []);
67288
67862
  setAvailableLines(lines);
67289
67863
  console.log("[TeamManagementView] Company-scoped team view - Company:", companyId, "Loaded factories:", factories?.length, "lines:", lines?.length);
67290
- } else if (user?.role_level === "plant_head") {
67291
- if (plantHeadFactoryIds.length > 0) {
67864
+ } else if (isFactoryScopedRole(user?.role_level)) {
67865
+ if (factoryScopedRoleFactoryIds.length > 0) {
67292
67866
  if (companyId) {
67293
67867
  const linesResponse = await fetch(`${backendUrl}/api/lines?company_id=${companyId}`, {
67294
67868
  headers: {
@@ -67301,9 +67875,9 @@ var TeamManagementView = ({
67301
67875
  }
67302
67876
  const linesData = await linesResponse.json();
67303
67877
  const allLines = linesData.lines || [];
67304
- const lines = allLines.filter((line) => plantHeadFactoryIds.includes(line.factory_id));
67878
+ const lines = allLines.filter((line) => factoryScopedRoleFactoryIds.includes(line.factory_id));
67305
67879
  setAvailableLines(lines);
67306
- console.log("[TeamManagementView] Plant Head - Factories:", plantHeadFactoryIds, "Loaded lines:", lines?.length);
67880
+ console.log("[TeamManagementView] Factory-scoped team view - Factories:", factoryScopedRoleFactoryIds, "Loaded lines:", lines?.length);
67307
67881
  }
67308
67882
  } else if (entityConfig?.factoryId) {
67309
67883
  const linesResponse = await fetch(`${backendUrl}/api/lines?factory_id=${entityConfig.factoryId}`, {
@@ -67340,12 +67914,12 @@ var TeamManagementView = ({
67340
67914
  setAvailableFactories([]);
67341
67915
  console.log("[TeamManagementView] Fallback - Company:", companyId, "Loaded lines:", lines?.length);
67342
67916
  }
67343
- const usersPromise = user?.role_level === "plant_head" ? (async () => {
67344
- if (plantHeadFactoryIds.length === 0) {
67917
+ const usersPromise = isFactoryScopedRole(user?.role_level) ? (async () => {
67918
+ if (factoryScopedRoleFactoryIds.length === 0) {
67345
67919
  return [];
67346
67920
  }
67347
67921
  const results = await Promise.allSettled(
67348
- plantHeadFactoryIds.map((factoryId) => userManagementService.getFactoryUsers(factoryId))
67922
+ factoryScopedRoleFactoryIds.map((factoryId) => userManagementService.getFactoryUsers(factoryId))
67349
67923
  );
67350
67924
  const successful = results.filter(
67351
67925
  (result) => result.status === "fulfilled"
@@ -67377,6 +67951,7 @@ var TeamManagementView = ({
67377
67951
  owners: userStats.owners,
67378
67952
  it: userStats.it,
67379
67953
  plantHeads: userStats.plant_heads,
67954
+ industrialEngineers: userStats.industrial_engineers,
67380
67955
  supervisors: userStats.supervisors,
67381
67956
  optifye: 0
67382
67957
  });
@@ -67387,7 +67962,7 @@ var TeamManagementView = ({
67387
67962
  } finally {
67388
67963
  setIsLoading(false);
67389
67964
  }
67390
- }, [supabase, user, pageCompanyId, entityConfig?.factoryId, plantHeadFactoryIds]);
67965
+ }, [supabase, user, pageCompanyId, entityConfig?.factoryId, factoryScopedRoleFactoryIds]);
67391
67966
  useEffect(() => {
67392
67967
  const companyId = pageCompanyId;
67393
67968
  const canLoad = hasAccess && user && !!companyId;
@@ -67493,7 +68068,7 @@ var TeamManagementView = ({
67493
68068
  {
67494
68069
  iconType: AlertCircle,
67495
68070
  title: "Access Denied",
67496
- message: "You don't have permission to view this page. Only owners, IT, plant heads, and Optifye users can access team management."
68071
+ message: `You don't have permission to view this page. Only ${getRoleLabel("owner")}, ${getRoleLabel("it")}, ${getRoleLabel("plant_head")}, ${getRoleLabel("industrial_engineer")}, and ${getRoleLabel("optifye")} users can access team management.`
67497
68072
  }
67498
68073
  ) });
67499
68074
  }
@@ -67660,7 +68235,7 @@ function BottleneckClipsView({
67660
68235
  ) })
67661
68236
  ] }) });
67662
68237
  }
67663
- var AuthenticatedBottleneckClipsView = withAuth(React26__default.memo(BottleneckClipsView));
68238
+ var AuthenticatedBottleneckClipsView = withAuth(React141__default.memo(BottleneckClipsView));
67664
68239
  var BottleneckClipsView_default = BottleneckClipsView;
67665
68240
 
67666
68241
  // src/lib/services/ticketService.ts
@@ -68491,7 +69066,7 @@ Please ensure:
68491
69066
  )
68492
69067
  ] });
68493
69068
  }
68494
- var AuthenticatedTicketsView = withAuth(React26__default.memo(TicketsView));
69069
+ var AuthenticatedTicketsView = withAuth(React141__default.memo(TicketsView));
68495
69070
  var TicketsView_default = TicketsView;
68496
69071
 
68497
69072
  // src/lib/api/s3-clips-parser.ts
@@ -68671,6 +69246,74 @@ var buildInitials = (name) => {
68671
69246
  const second = parts.length > 1 ? parts[1]?.[0] || "" : "";
68672
69247
  return `${first}${second}`.toUpperCase();
68673
69248
  };
69249
+ var MOCK_IE_TEAM_USER_ID = "mock-industrial-engineering-team";
69250
+ var MOCK_IE_TICKET_ID = "mock-ie-rack-too-far-away";
69251
+ var getRandomVideoGalleryClips = (recommendations, maxClips = 3) => {
69252
+ const seen = /* @__PURE__ */ new Set();
69253
+ const candidates = [];
69254
+ recommendations.forEach((rec) => {
69255
+ if (!Array.isArray(rec.evidence)) return;
69256
+ rec.evidence.forEach((evidenceItem) => {
69257
+ if (evidenceItem.type !== "video_gallery" || !Array.isArray(evidenceItem.clips)) return;
69258
+ evidenceItem.clips.forEach((rawClip) => {
69259
+ if (!rawClip || typeof rawClip.clip_id !== "string") return;
69260
+ const key = `${rawClip.clip_id}:${rawClip.workspace_id || ""}`;
69261
+ if (seen.has(key)) return;
69262
+ seen.add(key);
69263
+ candidates.push({
69264
+ clip_id: rawClip.clip_id,
69265
+ workspace_id: typeof rawClip.workspace_id === "string" ? rawClip.workspace_id : void 0,
69266
+ cycle_time_seconds: typeof rawClip.cycle_time_seconds === "number" ? rawClip.cycle_time_seconds : void 0,
69267
+ cycle_sec: typeof rawClip.cycle_sec === "number" ? rawClip.cycle_sec : void 0
69268
+ });
69269
+ });
69270
+ });
69271
+ });
69272
+ for (let i = candidates.length - 1; i > 0; i -= 1) {
69273
+ const j = Math.floor(Math.random() * (i + 1));
69274
+ [candidates[i], candidates[j]] = [candidates[j], candidates[i]];
69275
+ }
69276
+ return candidates.slice(0, Math.max(1, maxClips));
69277
+ };
69278
+ var buildIEMockRecommendation = (recommendations, lineNameById) => {
69279
+ const now4 = /* @__PURE__ */ new Date();
69280
+ const firstSeen = new Date(now4.getTime() - 3 * 24 * 60 * 60 * 1e3).toISOString();
69281
+ const sampleRec = recommendations.find((rec) => !!rec.line_id) || recommendations[0];
69282
+ const lineId = sampleRec?.line_id;
69283
+ const line = lineId ? lineNameById.get(lineId) || sampleRec?.line || "Line 1" : sampleRec?.line || "Line 1";
69284
+ const shiftLabel = sampleRec?.shift_label;
69285
+ const shiftId = sampleRec?.shift_id;
69286
+ const randomClips = getRandomVideoGalleryClips(recommendations, 3);
69287
+ return {
69288
+ id: MOCK_IE_TICKET_ID,
69289
+ issue_id: MOCK_IE_TICKET_ID,
69290
+ issue_number: 0,
69291
+ issue_status: "open",
69292
+ template_code: "ie_rack_too_far_away_mock",
69293
+ type: "cycle_time",
69294
+ title: "Rack too far away",
69295
+ location: "Industrial Engineering Review",
69296
+ line,
69297
+ line_id: lineId,
69298
+ description: "We analyzed 30 slow clips and saw that the top reason was the operator having to reach for the desk.",
69299
+ resolution_instructions: "Completion condition: Move the rack 3 inches closer to the operator for better ergonomic posture.",
69300
+ shift_id: shiftId,
69301
+ shift_label: shiftLabel,
69302
+ first_seen_at: firstSeen,
69303
+ visible_since: firstSeen,
69304
+ weeks_open: 1,
69305
+ ticket_status: "active",
69306
+ assigned_to_user_id: MOCK_IE_TEAM_USER_ID,
69307
+ assigned_user_ids: [MOCK_IE_TEAM_USER_ID],
69308
+ evidence: randomClips.length > 0 ? [
69309
+ {
69310
+ type: "video_gallery",
69311
+ title: "Slow clips analyzed",
69312
+ clips: randomClips
69313
+ }
69314
+ ] : []
69315
+ };
69316
+ };
68674
69317
  var ClipVideoCarousel = ({ clips, clipsService }) => {
68675
69318
  const [currentIndex, setCurrentIndex] = useState(0);
68676
69319
  const [videos, setVideos] = useState([]);
@@ -69093,12 +69736,12 @@ var ImprovementCenterView = () => {
69093
69736
  }, [user]);
69094
69737
  const assignedFactoryIds = useMemo(() => {
69095
69738
  if (!user) return [];
69096
- if (user.role_level !== "plant_head") return [];
69739
+ if (!isFactoryScopedRole(user.role_level)) return [];
69097
69740
  const factories = user.properties?.factory_id || user.properties?.factory_ids || [];
69098
69741
  return Array.isArray(factories) ? factories : [];
69099
69742
  }, [user]);
69100
69743
  const plantHeadLineIds = useMemo(() => {
69101
- if (user?.role_level !== "plant_head" || companyLines.length === 0) return [];
69744
+ if (!isFactoryScopedRole(user?.role_level) || companyLines.length === 0) return [];
69102
69745
  const factorySet = new Set(assignedFactoryIds);
69103
69746
  return companyLines.filter((line) => line.factoryId === void 0 || line.factoryId === null || factorySet.has(line.factoryId)).map((line) => line.id);
69104
69747
  }, [assignedFactoryIds, companyLines, user?.role_level]);
@@ -69106,7 +69749,7 @@ var ImprovementCenterView = () => {
69106
69749
  if (user?.role_level === "supervisor") {
69107
69750
  return assignedLineIds;
69108
69751
  }
69109
- if (user?.role_level === "plant_head") {
69752
+ if (isFactoryScopedRole(user?.role_level)) {
69110
69753
  if (plantHeadLineIds.length > 0) return plantHeadLineIds;
69111
69754
  return companyLineIds.length > 0 ? companyLineIds : configuredLineIds;
69112
69755
  }
@@ -69129,6 +69772,21 @@ var ImprovementCenterView = () => {
69129
69772
  return map;
69130
69773
  }, [companyLines, configuredLines]);
69131
69774
  const companyId = user?.company_id || entityConfig.companyId;
69775
+ const industrialEngineeringTeamMember = useMemo(
69776
+ () => ({
69777
+ id: MOCK_IE_TEAM_USER_ID,
69778
+ name: "Industrial Engineering Team",
69779
+ role: "industrial_engineering",
69780
+ initials: "IE"
69781
+ }),
69782
+ []
69783
+ );
69784
+ const teamMembersWithIETeam = useMemo(() => {
69785
+ if (teamMembers.some((member) => member.id === MOCK_IE_TEAM_USER_ID)) {
69786
+ return teamMembers;
69787
+ }
69788
+ return [...teamMembers, industrialEngineeringTeamMember];
69789
+ }, [teamMembers, industrialEngineeringTeamMember]);
69132
69790
  const clipsService = useMemo(() => {
69133
69791
  try {
69134
69792
  return new S3ClipsSupabaseService(dashboardConfig);
@@ -69142,24 +69800,42 @@ var ImprovementCenterView = () => {
69142
69800
  if (!supabase || !companyId) return;
69143
69801
  try {
69144
69802
  const userService2 = createUserManagementService(supabase);
69145
- const supervisors = await userService2.getCompanyUsers(companyId, "supervisor");
69803
+ const roleFilters = ["supervisor", "owner", "industrial_engineer"];
69804
+ const roleResults = await Promise.allSettled(
69805
+ roleFilters.map((role) => userService2.getCompanyUsers(companyId, role))
69806
+ );
69807
+ roleResults.forEach((result, index) => {
69808
+ if (result.status === "rejected") {
69809
+ console.warn(
69810
+ `[ImprovementCenterView] Failed to load ${roleFilters[index]} users`,
69811
+ result.reason
69812
+ );
69813
+ }
69814
+ });
69815
+ const users = roleResults.flatMap(
69816
+ (result) => result.status === "fulfilled" ? result.value : []
69817
+ );
69146
69818
  if (cancelled) return;
69147
- const members = supervisors.map((user2) => {
69819
+ const membersById = /* @__PURE__ */ new Map();
69820
+ users.forEach((user2) => {
69148
69821
  const rawName = user2.first_name ? `${user2.first_name}${user2.last_name ? " " + user2.last_name : ""}` : user2.properties?.full_name || user2.email?.split("@")[0] || "Unknown";
69149
- return {
69150
- id: user2.user_id,
69151
- name: rawName,
69152
- role: user2.role_level,
69153
- initials: buildInitials(rawName),
69154
- email: user2.email,
69155
- profilePhotoUrl: user2.profile_photo_url
69156
- };
69822
+ if (!membersById.has(user2.user_id)) {
69823
+ membersById.set(user2.user_id, {
69824
+ id: user2.user_id,
69825
+ name: rawName,
69826
+ role: user2.role_level,
69827
+ initials: buildInitials(rawName),
69828
+ email: user2.email,
69829
+ profilePhotoUrl: user2.profile_photo_url
69830
+ });
69831
+ }
69157
69832
  });
69833
+ const members = Array.from(membersById.values());
69158
69834
  members.sort((a, b) => a.name.localeCompare(b.name));
69159
69835
  setTeamMembers(members);
69160
69836
  } catch (error) {
69161
69837
  if (!cancelled) {
69162
- console.error("[ImprovementCenterView] Failed to load supervisors", error);
69838
+ console.error("[ImprovementCenterView] Failed to load assignee members", error);
69163
69839
  setTeamMembers([]);
69164
69840
  }
69165
69841
  }
@@ -69222,7 +69898,12 @@ var ImprovementCenterView = () => {
69222
69898
  };
69223
69899
  });
69224
69900
  const allowed = new Set(scopeLineIds);
69225
- setRecommendations(recs.filter((r2) => !r2.line_id || allowed.has(r2.line_id)));
69901
+ const scopedRecommendations = recs.filter((r2) => !r2.line_id || allowed.has(r2.line_id));
69902
+ const mockRecommendation = buildIEMockRecommendation(scopedRecommendations, lineNameById);
69903
+ setRecommendations([
69904
+ mockRecommendation,
69905
+ ...scopedRecommendations.filter((recommendation) => recommendation.id !== MOCK_IE_TICKET_ID)
69906
+ ]);
69226
69907
  } catch (err) {
69227
69908
  if (cancelled) return;
69228
69909
  setLoadError(err?.message || "Failed to load recommendations");
@@ -69235,10 +69916,10 @@ var ImprovementCenterView = () => {
69235
69916
  return () => {
69236
69917
  cancelled = true;
69237
69918
  };
69238
- }, [supabase, companyId, scopeLineIdsKey]);
69919
+ }, [supabase, companyId, scopeLineIdsKey, lineNameById]);
69239
69920
  const teamMembersById = useMemo(() => {
69240
- return new Map(teamMembers.map((member) => [member.id, member]));
69241
- }, [teamMembers]);
69921
+ return new Map(teamMembersWithIETeam.map((member) => [member.id, member]));
69922
+ }, [teamMembersWithIETeam]);
69242
69923
  const filteredRecommendations = useMemo(() => {
69243
69924
  return recommendations.filter((rec) => {
69244
69925
  if (selectedLineId !== "all" && rec.line_id !== selectedLineId) return false;
@@ -69253,7 +69934,12 @@ var ImprovementCenterView = () => {
69253
69934
  }
69254
69935
  if (selectedMemberId !== "all" && !(rec.assigned_user_ids?.includes(selectedMemberId) || rec.assigned_to_user_id === selectedMemberId)) return false;
69255
69936
  return true;
69256
- }).sort((a, b) => (a.issue_number || 0) - (b.issue_number || 0));
69937
+ }).sort((a, b) => {
69938
+ const aIndustrial = a.industrial_eng_bottleneck ? 1 : 0;
69939
+ const bIndustrial = b.industrial_eng_bottleneck ? 1 : 0;
69940
+ if (aIndustrial !== bIndustrial) return bIndustrial - aIndustrial;
69941
+ return (a.issue_number || 0) - (b.issue_number || 0);
69942
+ });
69257
69943
  }, [recommendations, selectedLineId, selectedStatus, selectedShift, selectedWeeksRange, selectedMemberId]);
69258
69944
  const stats = useMemo(() => {
69259
69945
  const baseFiltered = recommendations.filter((rec) => {
@@ -69351,7 +70037,7 @@ var ImprovementCenterView = () => {
69351
70037
  setSelectedWeeksRange(weeksRange);
69352
70038
  };
69353
70039
  const handleMemberFilterChange = (memberId) => {
69354
- const memberName = memberId === "all" ? "all" : teamMembers.find((m) => m.id === memberId)?.name || memberId;
70040
+ const memberName = memberId === "all" ? "all" : teamMembersWithIETeam.find((member) => member.id === memberId)?.name || memberId;
69355
70041
  trackCoreEvent("Improvement Center Filter Applied", {
69356
70042
  filter_type: "member",
69357
70043
  filter_value: memberName,
@@ -69433,7 +70119,7 @@ var ImprovementCenterView = () => {
69433
70119
  /* @__PURE__ */ jsx("div", { className: "space-y-3", children: [
69434
70120
  { value: selectedShift, onChange: handleShiftFilterChange, options: shiftOptions, label: "Shift" },
69435
70121
  { value: selectedWeeksRange, onChange: handleWeeksFilterChange, options: weekOptions.map((o) => o.id), labels: weekOptions, label: "Duration" },
69436
- { value: selectedMemberId, onChange: handleMemberFilterChange, options: ["all", ...teamMembers.map((m) => m.id)], labels: teamMembers, label: "Member" },
70122
+ { value: selectedMemberId, onChange: handleMemberFilterChange, options: ["all", ...teamMembersWithIETeam.map((m) => m.id)], labels: teamMembersWithIETeam, label: "Member" },
69437
70123
  { value: selectedLineId, onChange: handleLineFilterChange, options: lineOptions.map((o) => o.id), labels: lineOptions, label: "Line" }
69438
70124
  ].map((filter2, idx) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
69439
70125
  /* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide ml-1", children: filter2.label }),
@@ -69650,7 +70336,7 @@ var ThreadSidebar = ({
69650
70336
  ] }) })
69651
70337
  ] });
69652
70338
  };
69653
- var ProfilePicture = React26__default.memo(({
70339
+ var ProfilePicture = React141__default.memo(({
69654
70340
  alt = "Axel",
69655
70341
  className = "",
69656
70342
  size = "md",
@@ -71621,6 +72307,840 @@ var AIAgentView = () => {
71621
72307
  ] });
71622
72308
  };
71623
72309
  var AIAgentView_default = AIAgentView;
72310
+ var EMPTY_OVERVIEW = {
72311
+ scope: {
72312
+ current_range: { day_count: null },
72313
+ previous_range: { day_count: null },
72314
+ available_line_modes: { has_output: false, has_uptime: false }
72315
+ },
72316
+ summary: {
72317
+ plant_efficiency: { current: null, previous: null, delta_pp: null },
72318
+ avg_idle_per_workstation: { current_seconds: null, previous_seconds: null, delta_seconds: null }
72319
+ },
72320
+ poorest_lines: { output: [], uptime: [] },
72321
+ trend: { shift_mode: "all", points: [] },
72322
+ idle_reason_breakdown: []
72323
+ };
72324
+ var efficiencyLineConfig = [
72325
+ {
72326
+ dataKey: "efficiency",
72327
+ name: "Efficiency",
72328
+ stroke: "#00AB45",
72329
+ strokeWidth: 3,
72330
+ type: "monotone",
72331
+ dot: { r: 4, fill: "#00AB45", strokeWidth: 2, stroke: "#fff" },
72332
+ activeDot: { r: 6, strokeWidth: 0, fill: "#00AB45" }
72333
+ }
72334
+ ];
72335
+ var toNumber3 = (value) => {
72336
+ if (typeof value === "number" && Number.isFinite(value)) return value;
72337
+ if (typeof value === "string" && value.trim().length > 0) {
72338
+ const parsed = Number(value);
72339
+ return Number.isFinite(parsed) ? parsed : null;
72340
+ }
72341
+ return null;
72342
+ };
72343
+ var roundOne = (value) => Math.round(value * 10) / 10;
72344
+ var getLastSevenDayRange = (timezone) => {
72345
+ const todayKey = formatInTimeZone(/* @__PURE__ */ new Date(), timezone || "UTC", "yyyy-MM-dd");
72346
+ const endDate = parseISO(`${todayKey}T00:00:00`);
72347
+ const startDate = subDays(endDate, 6);
72348
+ return {
72349
+ startKey: format(startDate, "yyyy-MM-dd"),
72350
+ endKey: format(endDate, "yyyy-MM-dd")
72351
+ };
72352
+ };
72353
+ var formatIdleDuration = (seconds) => {
72354
+ if (seconds === null || seconds === void 0 || !Number.isFinite(seconds)) {
72355
+ return "--";
72356
+ }
72357
+ const wholeSeconds = Math.max(0, Math.round(seconds));
72358
+ const minutes = Math.floor(wholeSeconds / 60);
72359
+ const remainingSeconds = wholeSeconds % 60;
72360
+ if (minutes > 0) {
72361
+ return `${minutes}m ${remainingSeconds}s`;
72362
+ }
72363
+ return `${remainingSeconds}s`;
72364
+ };
72365
+ var formatSignedIdleDuration = (seconds) => {
72366
+ const sign = seconds > 0 ? "+" : "-";
72367
+ return `${sign}${formatIdleDuration(Math.abs(seconds))}`;
72368
+ };
72369
+ var formatComparisonWindow = (dayCount) => {
72370
+ if (!dayCount || !Number.isFinite(dayCount)) return "previous range";
72371
+ return `previous ${dayCount} ${dayCount === 1 ? "day" : "days"}`;
72372
+ };
72373
+ var shuffle = (items) => {
72374
+ const next = [...items];
72375
+ for (let i = next.length - 1; i > 0; i -= 1) {
72376
+ const swapIndex = Math.floor(Math.random() * (i + 1));
72377
+ [next[i], next[swapIndex]] = [next[swapIndex], next[i]];
72378
+ }
72379
+ return next;
72380
+ };
72381
+ var buildImprovementMetric = (recommendation) => {
72382
+ const metrics2 = recommendation.metrics || {};
72383
+ const efficiencyGain = toNumber3(metrics2.efficiency_gain_pct);
72384
+ if (efficiencyGain !== null) {
72385
+ return `+${roundOne(efficiencyGain)}% Efficiency`;
72386
+ }
72387
+ const outputGain = toNumber3(metrics2.output_gain);
72388
+ if (outputGain !== null) {
72389
+ return `+${Math.round(outputGain)} Units`;
72390
+ }
72391
+ const idleMinutes = toNumber3(metrics2.idle_minutes);
72392
+ if (idleMinutes !== null) {
72393
+ return `-${Math.round(idleMinutes)}m Idle`;
72394
+ }
72395
+ const impactText = recommendation.impact?.trim();
72396
+ if (impactText) {
72397
+ return impactText.length > 22 ? `${impactText.slice(0, 22).trim()}...` : impactText;
72398
+ }
72399
+ return "Review Issue";
72400
+ };
72401
+ var buildImprovementImpact = (recommendation) => {
72402
+ if (recommendation.issue_severity !== void 0 && recommendation.issue_severity !== null) {
72403
+ if (recommendation.issue_severity >= 3) return "High";
72404
+ if (recommendation.issue_severity >= 2) return "Medium";
72405
+ return "Low";
72406
+ }
72407
+ return "Medium";
72408
+ };
72409
+ var buildDeltaBadge = (delta, options) => {
72410
+ if (delta === null || delta === void 0 || !Number.isFinite(delta)) {
72411
+ return {
72412
+ icon: null,
72413
+ className: "bg-slate-100 text-slate-500",
72414
+ text: `No ${options.comparisonLabel} baseline`
72415
+ };
72416
+ }
72417
+ const direction = delta >= 0 ? "up" : "down";
72418
+ const isGood = options.positiveIsGood ? delta >= 0 : delta <= 0;
72419
+ return {
72420
+ icon: direction,
72421
+ className: isGood ? "bg-[#ecfdf5] text-[#059669]" : "bg-[#FEF2F2] text-[#DC2626]",
72422
+ text: `${options.formatter(delta)} vs ${options.comparisonLabel}`
72423
+ };
72424
+ };
72425
+ var buildLineDeltaTone = (delta, comparisonLabel) => {
72426
+ if (delta === null || delta === void 0 || !Number.isFinite(delta)) {
72427
+ return {
72428
+ className: "text-slate-400",
72429
+ text: `No ${comparisonLabel} baseline`
72430
+ };
72431
+ }
72432
+ return {
72433
+ className: delta >= 0 ? "text-[#059669]" : "text-[#DC2626]",
72434
+ text: `${delta >= 0 ? "+" : ""}${roundOne(delta)}% vs ${comparisonLabel}`
72435
+ };
72436
+ };
72437
+ var SectionPulse = ({ className }) => /* @__PURE__ */ jsx("div", { className: `animate-pulse rounded-md bg-slate-200/70 ${className || ""}` });
72438
+ var OverviewMetricCardSkeleton = () => /* @__PURE__ */ jsxs("div", { className: "mt-2 space-y-3", children: [
72439
+ /* @__PURE__ */ jsx(SectionPulse, { className: "h-8 w-32" }),
72440
+ /* @__PURE__ */ jsx(SectionPulse, { className: "h-6 w-44 rounded-full" })
72441
+ ] });
72442
+ var OverviewListSkeleton = ({ rows = 3 }) => /* @__PURE__ */ jsx("div", { className: "space-y-4 py-3", children: Array.from({ length: rows }).map((_, index) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
72443
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
72444
+ /* @__PURE__ */ jsx(SectionPulse, { className: "h-8 w-8 rounded-full" }),
72445
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
72446
+ /* @__PURE__ */ jsx(SectionPulse, { className: "h-3 w-28" }),
72447
+ /* @__PURE__ */ jsx(SectionPulse, { className: "h-2.5 w-20" })
72448
+ ] })
72449
+ ] }),
72450
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
72451
+ /* @__PURE__ */ jsx(SectionPulse, { className: "h-4 w-12" }),
72452
+ /* @__PURE__ */ jsx(SectionPulse, { className: "h-6 w-10 rounded-full" })
72453
+ ] })
72454
+ ] }, index)) });
72455
+ var OverviewChartSkeleton = () => /* @__PURE__ */ jsx("div", { className: "w-full h-full animate-pulse", children: /* @__PURE__ */ jsx("div", { className: "h-full rounded-xl bg-gradient-to-b from-slate-100 to-slate-50 p-4", children: /* @__PURE__ */ jsx("div", { className: "h-full rounded-lg border border-dashed border-slate-200 bg-white/70 px-3 py-4", children: /* @__PURE__ */ jsx("div", { className: "flex h-full items-end gap-3", children: Array.from({ length: 7 }).map((_, index) => /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-1 flex-col justify-end gap-2", children: [
72456
+ /* @__PURE__ */ jsx(SectionPulse, { className: `w-full rounded-md ${index % 3 === 0 ? "h-24" : index % 3 === 1 ? "h-32" : "h-20"}` }),
72457
+ /* @__PURE__ */ jsx(SectionPulse, { className: "h-2.5 w-8 self-center" })
72458
+ ] }, index)) }) }) }) });
72459
+ var OverviewIdleBreakdownSkeleton = () => /* @__PURE__ */ jsxs("div", { className: "w-full h-full flex items-center overflow-hidden animate-pulse", children: [
72460
+ /* @__PURE__ */ jsx("div", { className: "flex-1 h-full min-w-0 relative flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "w-32 h-32 rounded-full bg-slate-200" }) }),
72461
+ /* @__PURE__ */ jsx("div", { className: "w-[50%] max-w-[200px] pl-2 flex flex-col justify-center h-full space-y-2", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
72462
+ /* @__PURE__ */ jsx("div", { className: "w-2.5 h-2.5 rounded-full bg-slate-200 mr-1.5" }),
72463
+ /* @__PURE__ */ jsx("div", { className: "h-3 bg-slate-200 rounded w-20" })
72464
+ ] }, i)) })
72465
+ ] });
72466
+ var OverviewImprovementsSkeleton = () => /* @__PURE__ */ jsx("div", { className: "space-y-4 py-3", children: Array.from({ length: 3 }).map((_, index) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
72467
+ /* @__PURE__ */ jsx(SectionPulse, { className: "h-4 w-4 rounded-full" }),
72468
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-2", children: [
72469
+ /* @__PURE__ */ jsx(SectionPulse, { className: "h-3 w-40" }),
72470
+ /* @__PURE__ */ jsx(SectionPulse, { className: "h-2.5 w-24" })
72471
+ ] })
72472
+ ] }, index)) });
72473
+ var PlantHeadView = () => {
72474
+ const supabase = useSupabase();
72475
+ const entityConfig = useEntityConfig();
72476
+ const appTimezone = useAppTimezone() || "UTC";
72477
+ const { navigate } = useNavigation();
72478
+ const { accessibleLineIds } = useUserLineAccess();
72479
+ const mobileMenuContext = useMobileMenu();
72480
+ useHideMobileHeader(!!mobileMenuContext);
72481
+ const [dateRange, setDateRange] = React141__default.useState(() => getLastSevenDayRange("UTC"));
72482
+ const [trendMode, setTrendMode] = React141__default.useState("all");
72483
+ const [poorestLineMode, setPoorestLineMode] = React141__default.useState("output");
72484
+ const [overview, setOverview] = React141__default.useState(EMPTY_OVERVIEW);
72485
+ const [isSnapshotLoading, setIsSnapshotLoading] = React141__default.useState(false);
72486
+ const [isTrendLoading, setIsTrendLoading] = React141__default.useState(false);
72487
+ const [trendFetchNonce, setTrendFetchNonce] = React141__default.useState(0);
72488
+ const [trendViewOpenNonce] = React141__default.useState(() => Date.now());
72489
+ const [idleReasonBreakdown, setIdleReasonBreakdown] = React141__default.useState([]);
72490
+ const [isIdleReasonBreakdownLoading, setIsIdleReasonBreakdownLoading] = React141__default.useState(false);
72491
+ const [improvements, setImprovements] = React141__default.useState([]);
72492
+ const [isImprovementsLoading, setIsImprovementsLoading] = React141__default.useState(false);
72493
+ const [isFilterOpen, setIsFilterOpen] = React141__default.useState(false);
72494
+ const filterRef = React141__default.useRef(null);
72495
+ const filterButtonRef = React141__default.useRef(null);
72496
+ const mobileFilterButtonRef = React141__default.useRef(null);
72497
+ React141__default.useEffect(() => {
72498
+ function handleClickOutside(event) {
72499
+ if (filterRef.current && !filterRef.current.contains(event.target) && filterButtonRef.current && !filterButtonRef.current.contains(event.target) && mobileFilterButtonRef.current && !mobileFilterButtonRef.current.contains(event.target)) {
72500
+ setIsFilterOpen(false);
72501
+ }
72502
+ }
72503
+ document.addEventListener("mousedown", handleClickOutside);
72504
+ return () => {
72505
+ document.removeEventListener("mousedown", handleClickOutside);
72506
+ };
72507
+ }, []);
72508
+ const hasInitializedRangeRef = React141__default.useRef(false);
72509
+ React141__default.useEffect(() => {
72510
+ if (hasInitializedRangeRef.current) return;
72511
+ setDateRange(getLastSevenDayRange(appTimezone));
72512
+ hasInitializedRangeRef.current = true;
72513
+ }, [appTimezone]);
72514
+ const companyId = entityConfig.companyId;
72515
+ const scopedLineIds = React141__default.useMemo(
72516
+ () => Array.from(new Set((accessibleLineIds || []).filter(Boolean))),
72517
+ [accessibleLineIds]
72518
+ );
72519
+ const lineIdsKey = React141__default.useMemo(
72520
+ () => scopedLineIds.slice().sort().join(","),
72521
+ [scopedLineIds]
72522
+ );
72523
+ const { supervisorsByLineId } = useSupervisorsByLineIds(scopedLineIds, {
72524
+ enabled: !!companyId && scopedLineIds.length > 0,
72525
+ companyId,
72526
+ useBackend: true
72527
+ });
72528
+ React141__default.useEffect(() => {
72529
+ if (!supabase || !companyId) return void 0;
72530
+ if (scopedLineIds.length === 0) {
72531
+ setOverview(EMPTY_OVERVIEW);
72532
+ setIdleReasonBreakdown([]);
72533
+ setIsSnapshotLoading(false);
72534
+ return void 0;
72535
+ }
72536
+ let cancelled = false;
72537
+ setOverview((prev) => ({
72538
+ ...prev,
72539
+ scope: EMPTY_OVERVIEW.scope,
72540
+ summary: EMPTY_OVERVIEW.summary,
72541
+ poorest_lines: EMPTY_OVERVIEW.poorest_lines
72542
+ }));
72543
+ setIsSnapshotLoading(true);
72544
+ const fetchOverviewSnapshot = async () => {
72545
+ const params = new URLSearchParams({
72546
+ company_id: companyId,
72547
+ start_date: dateRange.startKey,
72548
+ end_date: dateRange.endKey,
72549
+ trend_shift_mode: trendMode,
72550
+ line_ids: scopedLineIds.join(",")
72551
+ });
72552
+ const response = await fetchBackendJson(
72553
+ supabase,
72554
+ `/api/dashboard/operations-overview/snapshot?${params.toString()}`
72555
+ );
72556
+ if (!cancelled) {
72557
+ setOverview((prev) => ({
72558
+ ...prev,
72559
+ scope: response.scope || EMPTY_OVERVIEW.scope,
72560
+ summary: response.summary || EMPTY_OVERVIEW.summary,
72561
+ poorest_lines: response.poorest_lines || EMPTY_OVERVIEW.poorest_lines
72562
+ }));
72563
+ }
72564
+ };
72565
+ fetchOverviewSnapshot().catch((error) => {
72566
+ console.error("[PlantHeadView] Failed to fetch operations overview snapshot", error);
72567
+ if (!cancelled) {
72568
+ setOverview((prev) => ({
72569
+ ...prev,
72570
+ scope: EMPTY_OVERVIEW.scope,
72571
+ summary: EMPTY_OVERVIEW.summary,
72572
+ poorest_lines: EMPTY_OVERVIEW.poorest_lines
72573
+ }));
72574
+ }
72575
+ }).finally(() => {
72576
+ if (!cancelled) {
72577
+ setIsSnapshotLoading(false);
72578
+ }
72579
+ });
72580
+ return () => {
72581
+ cancelled = true;
72582
+ };
72583
+ }, [
72584
+ companyId,
72585
+ dateRange.endKey,
72586
+ dateRange.startKey,
72587
+ lineIdsKey,
72588
+ scopedLineIds,
72589
+ supabase,
72590
+ trendMode
72591
+ ]);
72592
+ React141__default.useEffect(() => {
72593
+ if (!supabase || !companyId) return void 0;
72594
+ if (scopedLineIds.length === 0) {
72595
+ setOverview((prev) => ({
72596
+ ...prev,
72597
+ trend: EMPTY_OVERVIEW.trend
72598
+ }));
72599
+ setIsTrendLoading(false);
72600
+ return void 0;
72601
+ }
72602
+ let cancelled = false;
72603
+ setIsTrendLoading(true);
72604
+ const fetchOverviewTrend = async () => {
72605
+ const params = new URLSearchParams({
72606
+ company_id: companyId,
72607
+ start_date: dateRange.startKey,
72608
+ end_date: dateRange.endKey,
72609
+ trend_shift_mode: trendMode,
72610
+ line_ids: scopedLineIds.join(",")
72611
+ });
72612
+ const response = await fetchBackendJson(
72613
+ supabase,
72614
+ `/api/dashboard/operations-overview/trend?${params.toString()}`
72615
+ );
72616
+ if (!cancelled) {
72617
+ setOverview((prev) => ({
72618
+ ...prev,
72619
+ trend: response.trend || EMPTY_OVERVIEW.trend
72620
+ }));
72621
+ setTrendFetchNonce((prev) => prev + 1);
72622
+ }
72623
+ };
72624
+ fetchOverviewTrend().catch((error) => {
72625
+ console.error("[PlantHeadView] Failed to fetch operations overview trend", error);
72626
+ }).finally(() => {
72627
+ if (!cancelled) {
72628
+ setIsTrendLoading(false);
72629
+ }
72630
+ });
72631
+ return () => {
72632
+ cancelled = true;
72633
+ };
72634
+ }, [
72635
+ companyId,
72636
+ dateRange.endKey,
72637
+ dateRange.startKey,
72638
+ lineIdsKey,
72639
+ scopedLineIds,
72640
+ supabase,
72641
+ trendMode
72642
+ ]);
72643
+ React141__default.useEffect(() => {
72644
+ if (!supabase || !companyId) return void 0;
72645
+ if (scopedLineIds.length === 0) {
72646
+ setIdleReasonBreakdown([]);
72647
+ setIsIdleReasonBreakdownLoading(false);
72648
+ return void 0;
72649
+ }
72650
+ let cancelled = false;
72651
+ setIdleReasonBreakdown([]);
72652
+ setIsIdleReasonBreakdownLoading(true);
72653
+ const fetchIdleReasonBreakdown = async () => {
72654
+ const params = new URLSearchParams({
72655
+ company_id: companyId,
72656
+ start_date: dateRange.startKey,
72657
+ end_date: dateRange.endKey,
72658
+ trend_shift_mode: trendMode,
72659
+ line_ids: scopedLineIds.join(",")
72660
+ });
72661
+ const response = await fetchBackendJson(
72662
+ supabase,
72663
+ `/api/dashboard/operations-overview/idle-reason-breakdown?${params.toString()}`
72664
+ );
72665
+ if (!cancelled) {
72666
+ setIdleReasonBreakdown(response.idle_reason_breakdown || []);
72667
+ }
72668
+ };
72669
+ fetchIdleReasonBreakdown().catch((error) => {
72670
+ console.error("[PlantHeadView] Failed to fetch idle reason breakdown", error);
72671
+ if (!cancelled) {
72672
+ setIdleReasonBreakdown([]);
72673
+ }
72674
+ }).finally(() => {
72675
+ if (!cancelled) {
72676
+ setIsIdleReasonBreakdownLoading(false);
72677
+ }
72678
+ });
72679
+ return () => {
72680
+ cancelled = true;
72681
+ };
72682
+ }, [
72683
+ companyId,
72684
+ dateRange.endKey,
72685
+ dateRange.startKey,
72686
+ lineIdsKey,
72687
+ scopedLineIds,
72688
+ supabase,
72689
+ trendMode
72690
+ ]);
72691
+ React141__default.useEffect(() => {
72692
+ if (!supabase || !companyId) return void 0;
72693
+ if (scopedLineIds.length === 0) {
72694
+ setImprovements([]);
72695
+ setIsImprovementsLoading(false);
72696
+ return void 0;
72697
+ }
72698
+ let cancelled = false;
72699
+ setIsImprovementsLoading(true);
72700
+ const fetchImprovements = async () => {
72701
+ const params = new URLSearchParams({
72702
+ company_id: companyId,
72703
+ status: "open",
72704
+ limit: "200",
72705
+ line_ids: scopedLineIds.join(",")
72706
+ });
72707
+ const response = await fetchBackendJson(
72708
+ supabase,
72709
+ `/api/improvement-center/recommendations?${params.toString()}`
72710
+ );
72711
+ if (cancelled) return;
72712
+ const allowedLineIds = new Set(scopedLineIds);
72713
+ const scopedRecommendations = (response.recommendations || []).filter((recommendation) => {
72714
+ return !recommendation.line_id || allowedLineIds.has(recommendation.line_id);
72715
+ });
72716
+ const nextImprovements = shuffle(scopedRecommendations).slice(0, 3).map((recommendation) => ({
72717
+ id: recommendation.id,
72718
+ title: recommendation.title?.trim() || "Untitled issue",
72719
+ impact: buildImprovementImpact(recommendation),
72720
+ metric: buildImprovementMetric(recommendation)
72721
+ }));
72722
+ setImprovements(nextImprovements);
72723
+ };
72724
+ fetchImprovements().catch((error) => {
72725
+ console.error("[PlantHeadView] Failed to fetch improvements", error);
72726
+ if (!cancelled) {
72727
+ setImprovements([]);
72728
+ }
72729
+ }).finally(() => {
72730
+ if (!cancelled) {
72731
+ setIsImprovementsLoading(false);
72732
+ }
72733
+ });
72734
+ return () => {
72735
+ cancelled = true;
72736
+ };
72737
+ }, [companyId, lineIdsKey, scopedLineIds, supabase]);
72738
+ const availableLineModes = overview.scope?.available_line_modes;
72739
+ React141__default.useEffect(() => {
72740
+ const hasOutput = !!availableLineModes?.has_output;
72741
+ const hasUptime = !!availableLineModes?.has_uptime;
72742
+ if (hasOutput && !hasUptime && poorestLineMode !== "output") {
72743
+ setPoorestLineMode("output");
72744
+ } else if (hasUptime && !hasOutput && poorestLineMode !== "uptime") {
72745
+ setPoorestLineMode("uptime");
72746
+ }
72747
+ }, [availableLineModes?.has_output, availableLineModes?.has_uptime, poorestLineMode]);
72748
+ const comparisonLabel = React141__default.useMemo(
72749
+ () => formatComparisonWindow(overview.scope?.current_range?.day_count ?? null),
72750
+ [overview.scope?.current_range?.day_count]
72751
+ );
72752
+ const plantEfficiencyBadge = React141__default.useMemo(() => {
72753
+ return buildDeltaBadge(overview.summary?.plant_efficiency?.delta_pp, {
72754
+ positiveIsGood: true,
72755
+ formatter: (value) => `${value >= 0 ? "+" : ""}${roundOne(value)}%`,
72756
+ comparisonLabel
72757
+ });
72758
+ }, [comparisonLabel, overview.summary?.plant_efficiency?.delta_pp]);
72759
+ const idleBadge = React141__default.useMemo(() => {
72760
+ return buildDeltaBadge(overview.summary?.avg_idle_per_workstation?.delta_seconds, {
72761
+ positiveIsGood: false,
72762
+ formatter: (value) => formatSignedIdleDuration(value),
72763
+ comparisonLabel
72764
+ });
72765
+ }, [comparisonLabel, overview.summary?.avg_idle_per_workstation?.delta_seconds]);
72766
+ const trendData = React141__default.useMemo(() => {
72767
+ return (overview.trend?.points || []).map((point) => ({
72768
+ name: point.date ? format(parseDateKeyToDate(point.date), "MMM d") : "",
72769
+ efficiency: (() => {
72770
+ const value = toNumber3(point.avg_efficiency);
72771
+ return value === null ? void 0 : value;
72772
+ })()
72773
+ }));
72774
+ }, [overview.trend?.points]);
72775
+ const trendPlayKey = React141__default.useMemo(() => {
72776
+ return `${trendViewOpenNonce}:${trendFetchNonce}`;
72777
+ }, [trendFetchNonce, trendViewOpenNonce]);
72778
+ const idleBreakdown = React141__default.useMemo(() => {
72779
+ return idleReasonBreakdown.map((item) => ({
72780
+ name: item.reason?.trim() || "Unknown",
72781
+ value: toNumber3(item.percentage) || 0,
72782
+ totalDurationSeconds: toNumber3(item.total_duration_seconds),
72783
+ efficiencyLossPercentage: toNumber3(item.efficiency_loss_percentage),
72784
+ contributors: (item.contributors || []).map((contributor) => ({
72785
+ workspaceId: contributor.workspace_id || "",
72786
+ workspaceName: contributor.workspace_name?.trim() || "Unknown",
72787
+ totalDurationSeconds: toNumber3(contributor.total_duration_seconds),
72788
+ percentageWithinReason: toNumber3(contributor.percentage_within_reason)
72789
+ }))
72790
+ })).filter((item) => item.value > 0);
72791
+ }, [idleReasonBreakdown]);
72792
+ const mergedPoorestLines = React141__default.useMemo(() => {
72793
+ const rows = overview.poorest_lines?.[poorestLineMode] || [];
72794
+ return rows.slice(0, 3).map((line) => {
72795
+ const lineId = line.line_id || "";
72796
+ const supervisors = supervisorsByLineId.get(lineId) || [];
72797
+ const supervisor = supervisors[0];
72798
+ return {
72799
+ id: lineId,
72800
+ name: line.line_name?.trim() || "Unknown Line",
72801
+ efficiency: roundOne(toNumber3(line.avg_efficiency) || 0),
72802
+ previousEfficiency: toNumber3(line.previous_avg_efficiency),
72803
+ delta: toNumber3(line.delta_pp),
72804
+ supervisor: supervisor?.displayName || "Unassigned",
72805
+ supervisorImage: supervisor?.profilePhotoUrl ?? null
72806
+ };
72807
+ });
72808
+ }, [overview.poorest_lines, poorestLineMode, supervisorsByLineId]);
72809
+ const showPoorestModeToggle = !!availableLineModes?.has_output && !!availableLineModes?.has_uptime;
72810
+ availableLineModes?.has_uptime && !availableLineModes?.has_output ? "Uptime" : "Output";
72811
+ const poorestMetricLabel = poorestLineMode === "uptime" ? "Uptime" : "Efficiency";
72812
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col min-h-screen bg-slate-50 w-full font-sans", children: [
72813
+ /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-10 bg-white border-b flex-shrink-0 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3 relative", children: [
72814
+ /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
72815
+ mobileMenuContext ? /* @__PURE__ */ jsx(
72816
+ HamburgerButton,
72817
+ {
72818
+ onClick: mobileMenuContext.onMobileMenuOpen,
72819
+ className: "flex-shrink-0 -ml-1"
72820
+ }
72821
+ ) : /* @__PURE__ */ jsx("div", { className: "w-8 flex-shrink-0" }),
72822
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col items-center justify-center", children: [
72823
+ /* @__PURE__ */ jsx("h1", { className: "text-lg font-semibold text-gray-900 text-center px-1 truncate max-w-[200px]", children: "Operations Overview" }),
72824
+ /* @__PURE__ */ jsxs("span", { className: "text-[10px] font-medium text-slate-500 text-center mt-0.5", children: [
72825
+ format(parseDateKeyToDate(dateRange.startKey), "do MMM"),
72826
+ " - ",
72827
+ format(parseDateKeyToDate(dateRange.endKey), "do MMM, yyyy")
72828
+ ] })
72829
+ ] }),
72830
+ /* @__PURE__ */ jsxs("div", { className: "flex-shrink-0 flex items-center gap-1.5", children: [
72831
+ /* @__PURE__ */ jsx(
72832
+ MonthlyRangeFilter_default,
72833
+ {
72834
+ month: parseDateKeyToDate(dateRange.startKey).getMonth(),
72835
+ year: parseDateKeyToDate(dateRange.startKey).getFullYear(),
72836
+ timezone: appTimezone,
72837
+ value: dateRange,
72838
+ onChange: setDateRange,
72839
+ showLabel: false
72840
+ }
72841
+ ),
72842
+ /* @__PURE__ */ jsxs(
72843
+ "button",
72844
+ {
72845
+ ref: mobileFilterButtonRef,
72846
+ onClick: () => setIsFilterOpen(!isFilterOpen),
72847
+ className: `p-2 rounded-full transition-colors relative ${isFilterOpen || trendMode !== "all" ? "bg-blue-50" : "active:bg-gray-100"}`,
72848
+ "aria-label": "Open filters",
72849
+ children: [
72850
+ /* @__PURE__ */ jsx(Filter, { className: `w-5 h-5 ${trendMode !== "all" ? "text-blue-600" : "text-gray-700"}` }),
72851
+ trendMode !== "all" && /* @__PURE__ */ jsx("span", { className: "absolute -top-1 -right-1 flex items-center justify-center w-4 h-4 bg-blue-600 text-white text-[10px] rounded-full font-bold", children: "1" })
72852
+ ]
72853
+ }
72854
+ )
72855
+ ] })
72856
+ ] }) }),
72857
+ /* @__PURE__ */ jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center relative min-h-[56px]", children: [
72858
+ /* @__PURE__ */ jsxs("div", { className: "absolute left-1/2 -translate-x-1/2 flex flex-col items-center pointer-events-none", children: [
72859
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl md:text-3xl lg:text-4xl font-semibold text-gray-900 tracking-tight text-center pointer-events-auto leading-tight mb-0.5", children: "Operations Overview" }),
72860
+ /* @__PURE__ */ jsxs("span", { className: "text-xs sm:text-sm font-medium text-slate-500 text-center pointer-events-auto", children: [
72861
+ format(parseDateKeyToDate(dateRange.startKey), "do MMMM, yyyy"),
72862
+ " - ",
72863
+ format(parseDateKeyToDate(dateRange.endKey), "do MMMM, yyyy")
72864
+ ] })
72865
+ ] }),
72866
+ /* @__PURE__ */ jsxs("div", { className: "absolute right-0 flex items-center gap-3", children: [
72867
+ /* @__PURE__ */ jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsx(
72868
+ MonthlyRangeFilter_default,
72869
+ {
72870
+ month: parseDateKeyToDate(dateRange.startKey).getMonth(),
72871
+ year: parseDateKeyToDate(dateRange.startKey).getFullYear(),
72872
+ timezone: appTimezone,
72873
+ value: dateRange,
72874
+ onChange: setDateRange,
72875
+ showLabel: false
72876
+ }
72877
+ ) }),
72878
+ /* @__PURE__ */ jsxs(
72879
+ "button",
72880
+ {
72881
+ ref: filterButtonRef,
72882
+ onClick: () => setIsFilterOpen(!isFilterOpen),
72883
+ className: `flex items-center gap-2 px-3 py-1.5 rounded-lg border text-sm font-medium transition-all shadow-sm ${isFilterOpen || trendMode !== "all" ? "border-blue-500 bg-blue-50 text-blue-700 ring-1 ring-blue-500" : "border-slate-200 bg-white text-slate-700 hover:bg-slate-50"}`,
72884
+ "aria-label": "Open filters",
72885
+ children: [
72886
+ /* @__PURE__ */ jsx(Filter, { className: `w-[18px] h-[18px] ${trendMode !== "all" ? "text-blue-600" : "text-slate-500"}` }),
72887
+ "Filters",
72888
+ /* @__PURE__ */ jsx(ChevronDown, { className: `w-4 h-4 ml-0.5 transition-transform duration-200 ${isFilterOpen ? "rotate-180" : ""}` })
72889
+ ]
72890
+ }
72891
+ )
72892
+ ] })
72893
+ ] }) }),
72894
+ isFilterOpen && /* @__PURE__ */ jsxs("div", { ref: filterRef, className: "absolute right-3 sm:right-4 md:right-5 lg:right-6 top-full mt-2 w-72 bg-white rounded-xl shadow-xl border border-gray-100 p-4 z-50", children: [
72895
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
72896
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Filter View" }),
72897
+ trendMode !== "all" && /* @__PURE__ */ jsx(
72898
+ "button",
72899
+ {
72900
+ onClick: () => {
72901
+ setTrendMode("all");
72902
+ setIsFilterOpen(false);
72903
+ },
72904
+ className: "text-xs text-red-600 hover:text-red-700 font-medium",
72905
+ children: "Clear all"
72906
+ }
72907
+ )
72908
+ ] }),
72909
+ /* @__PURE__ */ jsx("div", { className: "space-y-3", children: /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
72910
+ /* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide ml-1", children: "Shift" }),
72911
+ /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsxs(
72912
+ "select",
72913
+ {
72914
+ value: trendMode,
72915
+ onChange: (e) => setTrendMode(e.target.value),
72916
+ className: "w-full appearance-none pl-3 pr-8 py-2 text-sm bg-gray-50 border border-gray-200 hover:border-gray-300 rounded-lg text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:bg-white transition-all cursor-pointer",
72917
+ style: { backgroundImage: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e")`, backgroundPosition: `right 0.75rem center`, backgroundRepeat: `no-repeat`, backgroundSize: `1.2em 1.2em` },
72918
+ children: [
72919
+ /* @__PURE__ */ jsx("option", { value: "all", children: "All Shifts" }),
72920
+ /* @__PURE__ */ jsx("option", { value: "day", children: "Day Shift" }),
72921
+ /* @__PURE__ */ jsx("option", { value: "night", children: "Night Shift" })
72922
+ ]
72923
+ }
72924
+ ) })
72925
+ ] }) })
72926
+ ] })
72927
+ ] }) }),
72928
+ /* @__PURE__ */ jsxs("div", { className: "p-4 sm:p-6 pb-6 max-w-[1800px] mx-auto w-full flex-1 min-h-0 overflow-y-auto flex flex-col gap-5", children: [
72929
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-5", children: [
72930
+ /* @__PURE__ */ jsxs(
72931
+ "div",
72932
+ {
72933
+ className: "bg-white rounded-xl shadow-sm border border-slate-100 p-4 md:p-5 flex flex-col justify-center min-h-[100px] text-left",
72934
+ children: [
72935
+ /* @__PURE__ */ jsx("div", { className: "flex justify-between items-center mb-1", children: /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-gray-700", children: "Overall Efficiency" }) }),
72936
+ isSnapshotLoading ? /* @__PURE__ */ jsx(OverviewMetricCardSkeleton, {}) : overview.summary?.plant_efficiency?.current !== null && overview.summary?.plant_efficiency?.current !== void 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 sm:gap-3 mt-1", children: [
72937
+ /* @__PURE__ */ jsxs("span", { className: "text-2xl sm:text-3xl font-bold text-slate-800 tracking-tight", children: [
72938
+ roundOne(overview.summary.plant_efficiency.current),
72939
+ "%"
72940
+ ] }),
72941
+ /* @__PURE__ */ jsxs("div", { className: `flex items-center gap-1 px-2.5 py-1 rounded-full ${plantEfficiencyBadge.className}`, children: [
72942
+ plantEfficiencyBadge.icon === "up" ? /* @__PURE__ */ jsx(ArrowUp, { className: "w-3.5 h-3.5", strokeWidth: 2.5 }) : plantEfficiencyBadge.icon === "down" ? /* @__PURE__ */ jsx(ArrowDown, { className: "w-3.5 h-3.5", strokeWidth: 2.5 }) : null,
72943
+ /* @__PURE__ */ jsx("span", { className: "text-xs sm:text-sm font-medium", children: plantEfficiencyBadge.text })
72944
+ ] })
72945
+ ] }) : /* @__PURE__ */ jsx("div", { className: "mt-2 text-sm text-slate-400", children: "No efficiency data available" })
72946
+ ]
72947
+ }
72948
+ ),
72949
+ /* @__PURE__ */ jsxs(
72950
+ "div",
72951
+ {
72952
+ className: "bg-white rounded-xl shadow-sm border border-slate-100 p-4 md:p-5 flex flex-col justify-center min-h-[100px] text-left",
72953
+ children: [
72954
+ /* @__PURE__ */ jsx("div", { className: "flex justify-between items-center mb-1", children: /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-gray-700", children: "Idle Time per Workstation" }) }),
72955
+ isSnapshotLoading ? /* @__PURE__ */ jsx(OverviewMetricCardSkeleton, {}) : overview.summary?.avg_idle_per_workstation?.current_seconds !== null && overview.summary?.avg_idle_per_workstation?.current_seconds !== void 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 sm:gap-3 mt-1", children: [
72956
+ /* @__PURE__ */ jsx("span", { className: "text-2xl sm:text-3xl font-bold text-slate-800 tracking-tight", children: formatIdleDuration(overview.summary.avg_idle_per_workstation.current_seconds) }),
72957
+ /* @__PURE__ */ jsxs("div", { className: `flex items-center gap-1 px-2.5 py-1 rounded-full ${idleBadge.className}`, children: [
72958
+ idleBadge.icon === "up" ? /* @__PURE__ */ jsx(ArrowUp, { className: "w-3.5 h-3.5", strokeWidth: 2.5 }) : idleBadge.icon === "down" ? /* @__PURE__ */ jsx(ArrowDown, { className: "w-3.5 h-3.5", strokeWidth: 2.5 }) : null,
72959
+ /* @__PURE__ */ jsx("span", { className: "text-xs sm:text-sm font-medium", children: idleBadge.text })
72960
+ ] })
72961
+ ] }) : /* @__PURE__ */ jsx("div", { className: "mt-2 text-sm text-slate-400", children: "No idle time data available" })
72962
+ ]
72963
+ }
72964
+ )
72965
+ ] }),
72966
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-h-0 grid grid-cols-1 xl:grid-cols-2 gap-5 auto-rows-fr", children: [
72967
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-rows-1 xl:grid-rows-2 gap-5 min-h-0", children: [
72968
+ /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl shadow-sm border border-slate-100 flex flex-col overflow-hidden", children: [
72969
+ /* @__PURE__ */ jsxs("div", { className: "px-5 py-4 border-b border-slate-50 flex justify-between items-center gap-3 flex-wrap", children: [
72970
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 flex-wrap", children: [
72971
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-gray-700", children: "Poorest Performers" }),
72972
+ showPoorestModeToggle && /* @__PURE__ */ jsxs("div", { className: "flex bg-slate-100 p-0.5 rounded-lg", children: [
72973
+ /* @__PURE__ */ jsx(
72974
+ "button",
72975
+ {
72976
+ type: "button",
72977
+ onClick: () => setPoorestLineMode("output"),
72978
+ className: `px-3 py-1 text-[11px] font-bold rounded-md ${poorestLineMode === "output" ? "bg-white text-slate-800 shadow-sm" : "text-slate-500 hover:text-slate-800"}`,
72979
+ children: "Output"
72980
+ }
72981
+ ),
72982
+ /* @__PURE__ */ jsx(
72983
+ "button",
72984
+ {
72985
+ type: "button",
72986
+ onClick: () => setPoorestLineMode("uptime"),
72987
+ className: `px-3 py-1 text-[11px] font-bold rounded-md ${poorestLineMode === "uptime" ? "bg-white text-slate-800 shadow-sm" : "text-slate-500 hover:text-slate-800"}`,
72988
+ children: "Uptime"
72989
+ }
72990
+ )
72991
+ ] })
72992
+ ] }),
72993
+ /* @__PURE__ */ jsx(
72994
+ "button",
72995
+ {
72996
+ type: "button",
72997
+ onClick: () => navigate("/kpis"),
72998
+ className: "text-[11px] font-bold text-slate-500 hover:text-slate-800 transition-colors",
72999
+ children: "View All"
73000
+ }
73001
+ )
73002
+ ] }),
73003
+ /* @__PURE__ */ jsx("div", { className: "flex-1 flex flex-col p-0 overflow-auto", children: /* @__PURE__ */ jsxs("div", { className: "divide-y divide-slate-50 flex-1 px-5", children: [
73004
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between py-2", children: [
73005
+ /* @__PURE__ */ jsx("div", { className: "font-semibold text-slate-400 text-[10px] uppercase tracking-wider min-w-[120px]", children: "Line" }),
73006
+ /* @__PURE__ */ jsx("div", { className: "font-semibold text-slate-400 text-[10px] uppercase tracking-wider text-left shrink-0 min-w-[110px] flex items-center gap-2", children: poorestMetricLabel })
73007
+ ] }),
73008
+ isSnapshotLoading ? /* @__PURE__ */ jsx(OverviewListSkeleton, {}) : mergedPoorestLines.length > 0 ? mergedPoorestLines.map((line) => {
73009
+ const lineDelta = buildLineDeltaTone(line.delta, comparisonLabel);
73010
+ return /* @__PURE__ */ jsx(
73011
+ "div",
73012
+ {
73013
+ onClick: () => navigate(`/kpis/${line.id}`),
73014
+ className: "block py-3 hover:bg-slate-50/50 transition-colors cursor-pointer group relative",
73015
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
73016
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
73017
+ /* @__PURE__ */ jsx("div", { className: "w-8 h-8 rounded-full bg-slate-100 border border-slate-200 overflow-hidden flex-shrink-0", children: line.supervisorImage ? /* @__PURE__ */ jsx(
73018
+ "img",
73019
+ {
73020
+ src: line.supervisorImage,
73021
+ alt: line.supervisor,
73022
+ className: "w-full h-full object-cover"
73023
+ }
73024
+ ) : /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-[10px] font-bold text-slate-500", children: line.supervisor.split(" ").map((part) => part[0]).join("").slice(0, 2) }) }),
73025
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
73026
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
73027
+ /* @__PURE__ */ jsx("div", { className: "font-bold text-slate-800 text-[13px] truncate group-hover:text-indigo-600 transition-colors", children: line.name }),
73028
+ /* @__PURE__ */ jsxs(
73029
+ "button",
73030
+ {
73031
+ type: "button",
73032
+ onClick: (event) => {
73033
+ event.stopPropagation();
73034
+ console.log(`Notify ${line.supervisor}`);
73035
+ },
73036
+ className: "flex items-center gap-1 text-[9px] font-bold text-slate-500 bg-slate-100 px-1.5 py-0.5 rounded transition-colors hover:bg-slate-200 hover:text-slate-700",
73037
+ children: [
73038
+ /* @__PURE__ */ jsx(Bell, { className: "w-2.5 h-2.5" }),
73039
+ "Notify"
73040
+ ]
73041
+ }
73042
+ )
73043
+ ] }),
73044
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 mt-0.5 flex-wrap", children: /* @__PURE__ */ jsx("span", { className: "text-[10px] text-slate-400 font-medium", children: line.supervisor }) })
73045
+ ] })
73046
+ ] }),
73047
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 shrink-0 justify-start min-w-[110px]", children: [
73048
+ /* @__PURE__ */ jsxs("div", { className: "text-[15px] font-bold text-slate-800", children: [
73049
+ line.efficiency,
73050
+ "%"
73051
+ ] }),
73052
+ line.delta !== null && line.delta !== void 0 && Number.isFinite(line.delta) ? /* @__PURE__ */ jsxs("div", { className: `flex items-center gap-0.5 px-2 py-0.5 rounded-full ${line.delta >= 0 ? "bg-[#ecfdf5] text-[#059669]" : "bg-[#FEF2F2] text-[#DC2626]"}`, children: [
73053
+ line.delta >= 0 ? /* @__PURE__ */ jsx(ArrowUp, { className: "w-3 h-3", strokeWidth: 2.5 }) : /* @__PURE__ */ jsx(ArrowDown, { className: "w-3 h-3", strokeWidth: 2.5 }),
73054
+ /* @__PURE__ */ jsx("span", { className: "text-[11px] font-bold", children: lineDelta.text.split(" vs ")[0].replace("+", "") })
73055
+ ] }) : /* @__PURE__ */ jsx("div", { className: "flex items-center gap-0.5 px-2 py-0.5 rounded-full bg-slate-50 text-slate-400", children: /* @__PURE__ */ jsx("span", { className: "text-[11px] font-bold", children: "\u2014" }) })
73056
+ ] })
73057
+ ] })
73058
+ },
73059
+ line.id
73060
+ );
73061
+ }) : /* @__PURE__ */ jsx("div", { className: "py-8 text-center text-sm text-slate-400", children: `No ${poorestLineMode} line data available` })
73062
+ ] }) })
73063
+ ] }),
73064
+ /* @__PURE__ */ jsxs(
73065
+ "div",
73066
+ {
73067
+ className: "bg-white rounded-xl shadow-sm border border-slate-100 flex flex-col overflow-hidden text-left",
73068
+ children: [
73069
+ /* @__PURE__ */ jsx("div", { className: "px-5 py-4 flex-none flex justify-between items-center border-b border-slate-50/50 relative", children: /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-gray-700", children: "Idle Time Breakdown" }) }),
73070
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 p-4 pt-2 relative", children: isIdleReasonBreakdownLoading ? /* @__PURE__ */ jsx(OverviewIdleBreakdownSkeleton, {}) : /* @__PURE__ */ jsx(
73071
+ IdleTimeReasonChart,
73072
+ {
73073
+ data: idleBreakdown,
73074
+ isLoading: false,
73075
+ hideTotalDuration: true
73076
+ }
73077
+ ) })
73078
+ ]
73079
+ }
73080
+ )
73081
+ ] }),
73082
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-rows-1 xl:grid-rows-2 gap-5 min-h-0", children: [
73083
+ /* @__PURE__ */ jsxs(
73084
+ "div",
73085
+ {
73086
+ className: "bg-white rounded-xl shadow-[0_2px_10px_-3px_rgba(6,81,237,0.1)] border border-slate-100 flex flex-col overflow-hidden text-left",
73087
+ children: [
73088
+ /* @__PURE__ */ jsx("div", { className: "px-6 py-5 flex-none flex justify-between items-center border-b border-slate-50/50", children: /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-gray-700", children: "Efficiency Trend" }) }),
73089
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 w-full p-4 pt-4 relative", children: isTrendLoading ? /* @__PURE__ */ jsx(OverviewChartSkeleton, {}) : /* @__PURE__ */ jsx("div", { className: "absolute inset-0 pb-2 pr-4 pl-1", children: /* @__PURE__ */ jsx(
73090
+ LineChart,
73091
+ {
73092
+ data: trendData,
73093
+ lines: efficiencyLineConfig,
73094
+ xAxisDataKey: "name",
73095
+ yAxisUnit: "%",
73096
+ yAxisDomain: [0, 100],
73097
+ showLegend: false,
73098
+ showGrid: true,
73099
+ fillContainer: true
73100
+ },
73101
+ trendPlayKey
73102
+ ) }) })
73103
+ ]
73104
+ }
73105
+ ),
73106
+ /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl shadow-sm border border-slate-100 flex flex-col overflow-hidden", children: [
73107
+ /* @__PURE__ */ jsxs("div", { className: "px-5 py-4 flex-none flex justify-between items-center border-b border-slate-50/50", children: [
73108
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-gray-700", children: "Improvements" }),
73109
+ /* @__PURE__ */ jsx(
73110
+ "button",
73111
+ {
73112
+ type: "button",
73113
+ onClick: () => navigate("/improvement-center"),
73114
+ className: "text-[11px] font-bold text-slate-500 hover:text-slate-800 transition-colors",
73115
+ children: "View All"
73116
+ }
73117
+ )
73118
+ ] }),
73119
+ /* @__PURE__ */ jsx("div", { className: "flex-1 p-0 flex flex-col px-5 py-2 justify-start overflow-auto", children: isImprovementsLoading ? /* @__PURE__ */ jsx(OverviewImprovementsSkeleton, {}) : improvements.length > 0 ? improvements.map((item) => /* @__PURE__ */ jsx(
73120
+ "div",
73121
+ {
73122
+ onClick: () => navigate("/improvement-center"),
73123
+ className: "flex items-center justify-between py-3 border-b border-slate-50 last:border-0 group cursor-pointer",
73124
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 flex-1 min-w-0 pr-4", children: [
73125
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx(ArrowUpRight, { className: "w-4 h-4 text-slate-400 group-hover:text-indigo-500 transition-colors" }) }),
73126
+ /* @__PURE__ */ jsxs("div", { children: [
73127
+ /* @__PURE__ */ jsx("h4", { className: "text-[13px] font-semibold text-slate-800 truncate transition-colors group-hover:text-indigo-600 mb-0.5", children: item.title }),
73128
+ /* @__PURE__ */ jsxs("p", { className: "text-[10px] font-medium text-slate-400", children: [
73129
+ "Impact: ",
73130
+ /* @__PURE__ */ jsx("span", { className: "text-slate-500 font-semibold", children: item.impact })
73131
+ ] })
73132
+ ] })
73133
+ ] })
73134
+ },
73135
+ item.id
73136
+ )) : /* @__PURE__ */ jsx("div", { className: "py-8 text-center text-sm text-slate-400", children: "No open improvement issues" }) })
73137
+ ] })
73138
+ ] })
73139
+ ] })
73140
+ ] })
73141
+ ] });
73142
+ };
73143
+ var PlantHeadView_default = PlantHeadView;
71624
73144
  var S3Service = class {
71625
73145
  constructor(config) {
71626
73146
  this.s3Client = null;
@@ -72097,4 +73617,4 @@ var streamProxyConfig = {
72097
73617
  }
72098
73618
  };
72099
73619
 
72100
- export { ACTION_NAMES, AIAgentView_default as AIAgentView, AcceptInvite, AcceptInviteView_default as AcceptInviteView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthService, AuthenticatedBottleneckClipsView, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedTicketsView, AuthenticatedWorkspaceHealthView, AvatarUpload, AxelNotificationPopup, AxelOrb, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottleneckClipsModal, BottleneckClipsView_default as BottleneckClipsView, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ChangeRoleDialog, ClipFilterProvider, ClipsCostView_default as ClipsCostView, CompactWorkspaceHealthCard, ConfirmRemoveUserDialog, CongratulationsOverlay, CroppedHlsVideoPlayer, CroppedVideoPlayer, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_HOME_VIEW_CONFIG, DEFAULT_MAP_VIEW_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_SHIFT_DATA, DEFAULT_THEME_CONFIG, DEFAULT_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, DetailedHealthStatus, DiagnosisVideoModal, EFFICIENCY_ON_TRACK_THRESHOLD, EmptyStateMessage, EncouragementOverlay, FactoryAssignmentDropdown, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, FittingTitle, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthDateShiftSelector, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HlsVideoPlayer, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, HourlyUptimeChart, ISTTimer_default as ISTTimer, IdleTimeVlmConfigProvider, ImprovementCenterView_default as ImprovementCenterView, InlineEditableText, InteractiveOnboardingTour, InvitationService, InvitationsTable, InviteUserDialog, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend6 as Legend, LineAssignmentDropdown, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LinesService, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, Logo, MainLayout, MapGridView, MetricCard_default as MetricCard, MinimalOnboardingPopup, MobileMenuProvider, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PlayPauseIndicator, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, RoleBadge, S3ClipsSupabaseService as S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SessionTracker, SessionTrackingContext, SessionTrackingProvider, SettingsPopup, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SignupWithInvitation, SilentErrorBoundary, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, TeamManagementView_default as TeamManagementView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TicketsView_default as TicketsView, TimeDisplay_default as TimeDisplay, TimePickerDropdown, Timer_default as Timer, TimezoneProvider, TimezoneService, UptimeDonutChart, UptimeLineChart, UptimeMetricCards, UserAvatar, UserManagementService, UserManagementTable, UserService, UserUsageDetailModal, UserUsageStats, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, aggregateKPIsFromLineMetricsRows, apiUtils, areAllLinesOnSameShift, authCoreService, authOTPService, authRateLimitService, awardsService, buildDateKey, buildKPIsFromLineMetricsRow, buildShiftGroupsKey, captureSentryException, captureSentryMessage, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearSentryContext, clearWorkspaceDisplayNamesCache, cn, createDefaultKPIs, createInvitationService, createLinesService, createSessionTracker, createStorageService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, fetchIdleTimeReasons, filterDataByDateKeyRange, forceRefreshWorkspaceDisplayNames, formatAwardMonth, formatDateInZone, formatDateKeyForDisplay, formatDateTimeInZone, formatDuration, formatISTDate, formatIdleTime, formatRangeLabel, formatReasonLabel, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAllWorkspaceDisplayNamesSnapshot, getAnonClient, getAvailableShiftIds, getAwardBadgeType, getAwardDescription, getAwardTitle, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentShiftForLine, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDateKeyFromDate, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getInitials, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getMonthKeyBounds, getMonthWeekRanges, getNextUpdateInterval, getOperationalDate, getReasonColor, getS3SignedUrl, getS3VideoSrc, getShiftData, getShiftNameById, getShiftWorkDurationSeconds, getShortShiftName, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUniformShiftGroup, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, groupLinesByShift, hasAnyShiftData, identifyCoreUser, initializeCoreMixpanel, isEfficiencyOnTrack, isFullMonthRange, isLegacyConfiguration, isPrefetchError, isSafari, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, lineLeaderboardService, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, normalizeDateKeyRange, optifyeAgentClient, parseDateKeyToDate, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, setSentryUserContext, setSentryWorkspaceContext, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, subscribeWorkspaceDisplayNames, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, transformToChartData, updateThreadTitle, upsertWorkspaceDisplayNameInCache, useAccessControl, useActiveBreaks, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useClipsInit, useCompanyClipsCost, useCompanyUsersUsage, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHideMobileHeader, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useIdleTimeClipClassifications, useIdleTimeReasons, useIdleTimeVlmConfig, useKpiTrends, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useLines, useMessages, useMetrics, useMobileMenu, useMonthlyTrend, useMultiLineShiftConfigs, useNavigation, useOperationalShiftKey, useOptionalSupabase, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useSessionTracking, useSessionTrackingContext, useShiftConfig, useShiftGroups, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useSupervisorsByLineIds, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useUserUsage, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthLastSeen, useWorkspaceHealthStatus, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, useWorkspaceUptimeTimeline, useWorkspaceVideoStreams, userService, videoPrefetchManager, videoPreloader, weeklyTopPerformerService, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };
73620
+ export { ACTION_NAMES, AIAgentView_default as AIAgentView, AcceptInvite, AcceptInviteView_default as AcceptInviteView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthService, AuthenticatedBottleneckClipsView, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedTicketsView, AuthenticatedWorkspaceHealthView, AvatarUpload, AxelNotificationPopup, AxelOrb, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottleneckClipsModal, BottleneckClipsView_default as BottleneckClipsView, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ChangeRoleDialog, ClipFilterProvider, ClipsCostView_default as ClipsCostView, CompactWorkspaceHealthCard, ConfirmRemoveUserDialog, CongratulationsOverlay, CroppedHlsVideoPlayer, CroppedVideoPlayer, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_HOME_VIEW_CONFIG, DEFAULT_MAP_VIEW_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_SHIFT_DATA, DEFAULT_THEME_CONFIG, DEFAULT_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, DetailedHealthStatus, DiagnosisVideoModal, EFFICIENCY_ON_TRACK_THRESHOLD, EmptyStateMessage, EncouragementOverlay, FactoryAssignmentDropdown, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, FittingTitle, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthDateShiftSelector, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HlsVideoPlayer, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, HourlyUptimeChart, ISTTimer_default as ISTTimer, IdleTimeVlmConfigProvider, ImprovementCenterView_default as ImprovementCenterView, InlineEditableText, InteractiveOnboardingTour, InvitationService, InvitationsTable, InviteUserDialog, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend6 as Legend, LineAssignmentDropdown, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LinesService, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, Logo, MainLayout, MapGridView, MetricCard_default as MetricCard, MinimalOnboardingPopup, MobileMenuProvider, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PlantHeadView_default as PlantHeadView, PlayPauseIndicator, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, RoleBadge, S3ClipsSupabaseService as S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SessionTracker, SessionTrackingContext, SessionTrackingProvider, SettingsPopup, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SignupWithInvitation, SilentErrorBoundary, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, TeamManagementView_default as TeamManagementView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TicketsView_default as TicketsView, TimeDisplay_default as TimeDisplay, TimePickerDropdown, Timer_default as Timer, TimezoneProvider, TimezoneService, UptimeDonutChart, UptimeLineChart, UptimeMetricCards, UserAvatar, UserManagementService, UserManagementTable, UserService, UserUsageDetailModal, UserUsageStats, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, aggregateKPIsFromLineMetricsRows, alertsService, apiUtils, areAllLinesOnSameShift, authCoreService, authOTPService, authRateLimitService, awardsService, buildDateKey, buildKPIsFromLineMetricsRow, buildShiftGroupsKey, captureSentryException, captureSentryMessage, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearSentryContext, clearWorkspaceDisplayNamesCache, cn, createDefaultKPIs, createInvitationService, createLinesService, createSessionTracker, createStorageService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, fetchIdleTimeReasons, filterDataByDateKeyRange, forceRefreshWorkspaceDisplayNames, formatAwardMonth, formatDateInZone, formatDateKeyForDisplay, formatDateTimeInZone, formatDuration2 as formatDuration, formatISTDate, formatIdleTime, formatRangeLabel, formatReasonLabel, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAllWorkspaceDisplayNamesSnapshot, getAnonClient, getAvailableShiftIds, getAwardBadgeType, getAwardDescription, getAwardTitle, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentShiftForLine, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDateKeyFromDate, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getInitials, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getMonthKeyBounds, getMonthWeekRanges, getNextUpdateInterval, getOperationalDate, getReasonColor, getS3SignedUrl, getS3VideoSrc, getShiftData, getShiftNameById, getShiftWorkDurationSeconds, getShortShiftName, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUniformShiftGroup, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, groupLinesByShift, hasAnyShiftData, identifyCoreUser, initializeCoreMixpanel, isEfficiencyOnTrack, isFullMonthRange, isLegacyConfiguration, isPrefetchError, isSafari, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, lineLeaderboardService, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, normalizeDateKeyRange, optifyeAgentClient, parseDateKeyToDate, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, setSentryUserContext, setSentryWorkspaceContext, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, subscribeWorkspaceDisplayNames, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, transformToChartData, updateThreadTitle, upsertWorkspaceDisplayNameInCache, useAccessControl, useActiveBreaks, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useClipsInit, useCompanyClipsCost, useCompanyUsersUsage, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHideMobileHeader, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useIdleTimeClipClassifications, useIdleTimeReasons, useIdleTimeVlmConfig, useKpiTrends, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useLines, useMessages, useMetrics, useMobileMenu, useMonthlyTrend, useMultiLineShiftConfigs, useNavigation, useOperationalShiftKey, useOptionalSupabase, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useSessionTracking, useSessionTrackingContext, useShiftConfig, useShiftGroups, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useSupervisorsByLineIds, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useUserUsage, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthLastSeen, useWorkspaceHealthStatus, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, useWorkspaceUptimeTimeline, useWorkspaceVideoStreams, userService, videoPrefetchManager, videoPreloader, weeklyTopPerformerService, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };