@optifye/dashboard-core 6.9.0 → 6.9.2

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
@@ -11,7 +11,7 @@ import Hls2 from 'hls.js';
11
11
  import useSWR from 'swr';
12
12
  import { noop, warning, invariant, progress, secondsToMilliseconds, millisecondsToSeconds, memo as memo$1 } from 'motion-utils';
13
13
  import { getValueTransition, hover, press, isPrimaryPointer, GroupPlaybackControls, setDragLock, supportsLinearEasing, attachTimeline, isGenerator, calcGeneratorDuration, isWaapiSupportedEasing, mapEasingToNativeEasing, maxGeneratorDuration, generateLinearEasing, isBezierDefinition } from 'motion-dom';
14
- import { Camera, ChevronDown, ChevronUp, Check, Map as Map$1, Video, ShieldCheck, Star, Award, ArrowLeft, X, Coffee, Plus, Clock, Calendar, Save, AlertCircle, Loader2, Minus, ArrowDown, ArrowUp, Pause, Play, XCircle, ChevronLeft, ChevronRight, Sparkles, TrendingUp, Settings2, CheckCircle2, RefreshCw, TrendingDown, FolderOpen, Folder, HelpCircle, Sliders, Activity, Layers, Filter, Search, Edit2, AlertTriangle, CheckCircle, Building2, Mail, Users, User, Lock, ArrowRight, Info, Share2, Trophy, Target, Download, Sun, Moon, MousePointer, MessageSquare, Trash2, Menu, Send, Copy, UserCheck, LogOut, Package, UserPlus, Settings, LifeBuoy, EyeOff, Eye, MoreVertical, UserCog, Zap, Shield, UserCircle } from 'lucide-react';
14
+ import { Camera, ChevronDown, ChevronUp, Check, Map as Map$1, Video, ShieldCheck, Star, Award, ArrowLeft, X, Coffee, Plus, Clock, Calendar, Save, AlertCircle, Loader2, Minus, ArrowDown, ArrowUp, Pause, Play, XCircle, ChevronLeft, ChevronRight, Maximize2, Sparkles, TrendingUp, Settings2, CheckCircle2, RefreshCw, TrendingDown, FolderOpen, Folder, HelpCircle, Sliders, Activity, Layers, Filter, Search, Edit2, AlertTriangle, CheckCircle, Building2, Mail, Users, User, Lock, ArrowRight, Info, Share2, Trophy, Target, Download, Sun, Moon, MousePointer, MessageSquare, Trash2, Menu, Send, Copy, UserCheck, LogOut, Package, UserPlus, Settings, LifeBuoy, EyeOff, Eye, MoreVertical, UserCog, Zap, Shield, UserCircle } from 'lucide-react';
15
15
  import { toast } from 'sonner';
16
16
  import { BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, Tooltip, Legend, Bar, LabelList, ResponsiveContainer, LineChart as LineChart$1, Line, PieChart, Pie, Cell, ReferenceLine, ComposedChart, Area, ScatterChart, Scatter } from 'recharts';
17
17
  import { Slot } from '@radix-ui/react-slot';
@@ -198,7 +198,7 @@ var DEFAULT_DATE_TIME_CONFIG = {
198
198
  };
199
199
  var DEFAULT_ENDPOINTS_CONFIG = {
200
200
  whatsapp: "/api/send-whatsapp-direct",
201
- agnoApiUrl: process.env.NEXT_PUBLIC_AGNO_URL || "https://optifye-agent-production.up.railway.app",
201
+ agnoApiUrl: process.env.NEXT_PUBLIC_AGNO_URL || "https://fastapi-production-111f9.up.railway.app",
202
202
  // Default AGNO API URL
203
203
  // Use environment variable for Slack webhook URL for privacy/security
204
204
  // Note: SLACK_WEBHOOK_URL is server-side only, NEXT_PUBLIC_SLACK_WEBHOOK_URL works client-side but is less secure
@@ -2763,60 +2763,135 @@ var authCoreService = {
2763
2763
  }
2764
2764
  };
2765
2765
 
2766
+ // src/lib/utils/apiClient.ts
2767
+ var ApiClient = class {
2768
+ // 5 minutes
2769
+ /**
2770
+ * Fetch with timeout, retry, and error handling
2771
+ *
2772
+ * @param url - URL to fetch
2773
+ * @param options - Fetch options plus ApiClient options
2774
+ * @returns Promise resolving to parsed JSON data
2775
+ */
2776
+ static async fetch(url, options = {}) {
2777
+ const {
2778
+ timeout = this.DEFAULT_TIMEOUT,
2779
+ retries = 1,
2780
+ retryDelay = 1e3,
2781
+ silentErrors = true,
2782
+ fallbackData = null,
2783
+ ...fetchOptions
2784
+ } = options;
2785
+ let lastError = null;
2786
+ for (let attempt = 0; attempt <= retries; attempt++) {
2787
+ const controller = new AbortController();
2788
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
2789
+ try {
2790
+ console.log(`[ApiClient] Request ${attempt > 0 ? `(retry ${attempt})` : ""}: ${url}`);
2791
+ const response = await fetch(url, {
2792
+ ...fetchOptions,
2793
+ signal: controller.signal
2794
+ });
2795
+ clearTimeout(timeoutId);
2796
+ if (!response.ok) {
2797
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
2798
+ }
2799
+ const data = await response.json();
2800
+ console.log(`[ApiClient] Success: ${url}`);
2801
+ return data;
2802
+ } catch (error) {
2803
+ clearTimeout(timeoutId);
2804
+ lastError = error;
2805
+ console.error(`[ApiClient] Error (attempt ${attempt + 1}/${retries + 1}):`, {
2806
+ url,
2807
+ error: error.message,
2808
+ isTimeout: error.name === "AbortError",
2809
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2810
+ });
2811
+ if (attempt < retries) {
2812
+ console.log(`[ApiClient] Retrying in ${retryDelay}ms...`);
2813
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
2814
+ continue;
2815
+ }
2816
+ if (silentErrors) {
2817
+ console.warn("[ApiClient] All retries exhausted, returning fallback data");
2818
+ return fallbackData;
2819
+ } else {
2820
+ throw lastError;
2821
+ }
2822
+ }
2823
+ }
2824
+ return fallbackData;
2825
+ }
2826
+ };
2827
+ ApiClient.DEFAULT_TIMEOUT = 3e5;
2828
+
2766
2829
  // src/lib/services/authService.ts
2767
2830
  var AuthService = class {
2768
2831
  /**
2769
- * Fetch enriched user session from backend
2832
+ * Fetch enriched user session from backend with 5-minute timeout
2770
2833
  * This is your SINGLE call to get ALL auth data
2771
- *
2834
+ *
2772
2835
  * @param accessToken - JWT token from Supabase
2773
2836
  * @returns Complete user session with profile, permissions, and assignments
2774
2837
  */
2775
2838
  static async getSession(accessToken) {
2776
2839
  console.log("[AuthService] Fetching session from backend...");
2777
- const response = await fetch(`${this.backendUrl}/api/auth/session`, {
2778
- headers: {
2779
- "Authorization": `Bearer ${accessToken}`,
2780
- "Content-Type": "application/json"
2781
- }
2782
- });
2783
- if (!response.ok) {
2784
- const errorText = await response.text();
2785
- console.error("[AuthService] Session fetch failed:", response.status, errorText);
2786
- throw new Error(`Failed to fetch session: ${response.statusText}`);
2840
+ try {
2841
+ const data = await ApiClient.fetch(
2842
+ `${this.backendUrl}/api/auth/session`,
2843
+ {
2844
+ headers: {
2845
+ "Authorization": `Bearer ${accessToken}`,
2846
+ "Content-Type": "application/json"
2847
+ },
2848
+ timeout: 3e5,
2849
+ // 5 minutes
2850
+ retries: 1,
2851
+ silentErrors: false
2852
+ // We want to know about auth errors
2853
+ }
2854
+ );
2855
+ console.log("[AuthService] Session loaded:", {
2856
+ user_id: data.user_id,
2857
+ role: data.role,
2858
+ company_id: data.company_id,
2859
+ has_profile: !!data.profile,
2860
+ has_permissions: !!data.permissions
2861
+ });
2862
+ return data;
2863
+ } catch (error) {
2864
+ console.error("[AuthService] Session fetch failed:", error);
2865
+ throw error;
2787
2866
  }
2788
- const data = await response.json();
2789
- console.log("[AuthService] Session loaded:", {
2790
- user_id: data.user_id,
2791
- role: data.role,
2792
- company_id: data.company_id,
2793
- has_profile: !!data.profile,
2794
- has_permissions: !!data.permissions
2795
- });
2796
- return data;
2797
2867
  }
2798
2868
  /**
2799
- * Quick validation check without full profile fetch
2869
+ * Quick validation check without full profile fetch with timeout
2800
2870
  * Use this for lightweight auth checks
2801
- *
2871
+ *
2802
2872
  * @param accessToken - JWT token from Supabase
2803
2873
  * @returns Boolean indicating if session is valid
2804
2874
  */
2805
2875
  static async validateSession(accessToken) {
2806
2876
  try {
2807
2877
  console.log("[AuthService] Validating session...");
2808
- const response = await fetch(`${this.backendUrl}/api/auth/validate`, {
2809
- method: "POST",
2810
- headers: {
2811
- "Authorization": `Bearer ${accessToken}`,
2812
- "Content-Type": "application/json"
2878
+ const data = await ApiClient.fetch(
2879
+ `${this.backendUrl}/api/auth/validate`,
2880
+ {
2881
+ method: "POST",
2882
+ headers: {
2883
+ "Authorization": `Bearer ${accessToken}`,
2884
+ "Content-Type": "application/json"
2885
+ },
2886
+ timeout: 3e5,
2887
+ // 5 minutes
2888
+ retries: 2,
2889
+ // More retries for validation
2890
+ silentErrors: true,
2891
+ fallbackData: { valid: false, user_id: "", email: "" }
2892
+ // Safe default
2813
2893
  }
2814
- });
2815
- if (!response.ok) {
2816
- console.log("[AuthService] Session validation failed:", response.status);
2817
- return false;
2818
- }
2819
- const data = await response.json();
2894
+ );
2820
2895
  const isValid3 = data.valid === true;
2821
2896
  console.log("[AuthService] Session validation result:", isValid3);
2822
2897
  return isValid3;
@@ -2826,26 +2901,27 @@ var AuthService = class {
2826
2901
  }
2827
2902
  }
2828
2903
  /**
2829
- * Get just permissions (lightweight call)
2904
+ * Get just permissions (lightweight call) with timeout
2830
2905
  * Faster than full session fetch
2831
- *
2906
+ *
2832
2907
  * @param accessToken - JWT token from Supabase
2833
2908
  * @returns User permissions and role
2834
2909
  */
2835
2910
  static async getPermissions(accessToken) {
2836
2911
  console.log("[AuthService] Fetching permissions...");
2837
- const response = await fetch(`${this.backendUrl}/api/auth/permissions`, {
2838
- headers: {
2839
- "Authorization": `Bearer ${accessToken}`,
2840
- "Content-Type": "application/json"
2912
+ const data = await ApiClient.fetch(
2913
+ `${this.backendUrl}/api/auth/permissions`,
2914
+ {
2915
+ headers: {
2916
+ "Authorization": `Bearer ${accessToken}`,
2917
+ "Content-Type": "application/json"
2918
+ },
2919
+ timeout: 3e5,
2920
+ // 5 minutes
2921
+ retries: 1,
2922
+ silentErrors: false
2841
2923
  }
2842
- });
2843
- if (!response.ok) {
2844
- const errorText = await response.text();
2845
- console.error("[AuthService] Permissions fetch failed:", response.status, errorText);
2846
- throw new Error(`Failed to fetch permissions: ${response.statusText}`);
2847
- }
2848
- const data = await response.json();
2924
+ );
2849
2925
  console.log("[AuthService] Permissions loaded for role:", data.role);
2850
2926
  return data;
2851
2927
  }
@@ -3140,7 +3216,7 @@ var SSEChatClient = class {
3140
3216
  user_id: userId,
3141
3217
  context
3142
3218
  });
3143
- const agnoApiUrl = this.baseUrl || "https://fastapi-production-111f9.up.railway.app";
3219
+ const agnoApiUrl = this.baseUrl || (process.env.NEXT_PUBLIC_AGNO_URL || "https://fastapi-production-111f9.up.railway.app");
3144
3220
  const endpoint = `${agnoApiUrl}/api/v2/chat`;
3145
3221
  console.log("[SSEClient] Posting directly to AGNO:", endpoint);
3146
3222
  const response = await fetch(endpoint, {
@@ -5777,6 +5853,67 @@ var UserManagementService = class {
5777
5853
  var createUserManagementService = (supabase) => {
5778
5854
  return new UserManagementService(supabase);
5779
5855
  };
5856
+ var SupabaseContext = createContext(void 0);
5857
+ var SupabaseProvider = ({ client, children }) => {
5858
+ _setSupabaseInstance(client);
5859
+ useEffect(() => {
5860
+ _setSupabaseInstance(client);
5861
+ }, [client]);
5862
+ const contextValue = useMemo(() => ({ supabase: client }), [client]);
5863
+ return /* @__PURE__ */ jsx(SupabaseContext.Provider, { value: contextValue, children });
5864
+ };
5865
+ var useSupabase = () => {
5866
+ const context = useContext(SupabaseContext);
5867
+ if (context === void 0) {
5868
+ throw new Error("useSupabase must be used within a SupabaseProvider.");
5869
+ }
5870
+ return context.supabase;
5871
+ };
5872
+
5873
+ // src/lib/hooks/useSessionKeepAlive.ts
5874
+ var useSessionKeepAlive = (options = {}) => {
5875
+ const {
5876
+ enabled = true,
5877
+ intervalMs = 3e5
5878
+ // 5 minutes
5879
+ } = options;
5880
+ const supabase = useSupabase();
5881
+ const intervalRef = useRef(null);
5882
+ useEffect(() => {
5883
+ if (!enabled || !supabase) {
5884
+ return;
5885
+ }
5886
+ const keepAlive = async () => {
5887
+ try {
5888
+ const {
5889
+ data: { session }
5890
+ } = await supabase.auth.getSession();
5891
+ if (!session) {
5892
+ console.log("[SessionKeepAlive] No session, skipping keep-alive");
5893
+ return;
5894
+ }
5895
+ console.log("[SessionKeepAlive] Pinging backend to keep session alive");
5896
+ const isValid3 = await AuthService.validateSession(session.access_token);
5897
+ if (!isValid3) {
5898
+ console.warn("[SessionKeepAlive] Session validation failed");
5899
+ } else {
5900
+ console.log("[SessionKeepAlive] Session still valid");
5901
+ }
5902
+ } catch (error) {
5903
+ console.error("[SessionKeepAlive] Error during keep-alive:", error);
5904
+ }
5905
+ };
5906
+ const initialTimeout = setTimeout(keepAlive, 1e3);
5907
+ intervalRef.current = setInterval(keepAlive, intervalMs);
5908
+ return () => {
5909
+ clearTimeout(initialTimeout);
5910
+ if (intervalRef.current) {
5911
+ clearInterval(intervalRef.current);
5912
+ intervalRef.current = null;
5913
+ }
5914
+ };
5915
+ }, [enabled, intervalMs, supabase]);
5916
+ };
5780
5917
  var AuthContext = createContext({
5781
5918
  session: null,
5782
5919
  user: null,
@@ -5803,14 +5940,17 @@ var AuthProvider = ({ children }) => {
5803
5940
  const router = useRouter();
5804
5941
  const isFetchingRef = useRef(false);
5805
5942
  const lastProcessedSessionRef = useRef(null);
5806
- const fetchSession = useCallback(async (supabaseSession) => {
5943
+ const hasAuthenticatedRef = useRef(false);
5944
+ const fetchSession = useCallback(async (supabaseSession, isReauth = false) => {
5807
5945
  if (isFetchingRef.current) {
5808
5946
  console.log("[AuthContext] Already fetching, skipping duplicate request");
5809
5947
  return;
5810
5948
  }
5811
- console.log("[AuthContext] Fetching session from backend");
5949
+ console.log("[AuthContext] Fetching session from backend", { isReauth });
5812
5950
  isFetchingRef.current = true;
5813
- setLoading(true);
5951
+ if (!isReauth) {
5952
+ setLoading(true);
5953
+ }
5814
5954
  try {
5815
5955
  const enrichedUser = await AuthService.getSession(supabaseSession.access_token);
5816
5956
  const authUser = AuthService.toAuthUser(enrichedUser);
@@ -5818,6 +5958,7 @@ var AuthProvider = ({ children }) => {
5818
5958
  setSession(supabaseSession);
5819
5959
  setError(null);
5820
5960
  lastProcessedSessionRef.current = supabaseSession.access_token.substring(0, 20);
5961
+ hasAuthenticatedRef.current = true;
5821
5962
  if (!authUser.first_login_completed) {
5822
5963
  setShowOnboarding(true);
5823
5964
  }
@@ -5837,6 +5978,15 @@ var AuthProvider = ({ children }) => {
5837
5978
  });
5838
5979
  } catch (err) {
5839
5980
  console.error("[AuthContext] Failed to fetch session:", err);
5981
+ if (err.message?.includes("JWT expired") || err.message?.includes("invalid token") || err.message?.includes("token") || err.message?.includes("401")) {
5982
+ console.log("[AuthContext] Token expired or invalid, clearing session and redirecting to login");
5983
+ setUser(null);
5984
+ setSession(null);
5985
+ setError(new Error("Your session has expired. Please log in again."));
5986
+ await supabase.auth.signOut();
5987
+ router.replace("/login");
5988
+ return;
5989
+ }
5840
5990
  setError(err);
5841
5991
  setUser(null);
5842
5992
  if (err.message?.includes("profile")) {
@@ -5847,11 +5997,13 @@ var AuthProvider = ({ children }) => {
5847
5997
  setUser(basicUser);
5848
5998
  }
5849
5999
  } finally {
5850
- setLoading(false);
6000
+ if (!isReauth) {
6001
+ setLoading(false);
6002
+ }
5851
6003
  isFetchingRef.current = false;
5852
- console.log("[AuthContext] Loading set to false");
6004
+ console.log("[AuthContext] Loading set to false", { isReauth });
5853
6005
  }
5854
- }, []);
6006
+ }, [supabase, router]);
5855
6007
  const markFirstLoginCompleted = useCallback(async () => {
5856
6008
  if (!user?.id || !supabase) return false;
5857
6009
  try {
@@ -5883,6 +6035,7 @@ var AuthProvider = ({ children }) => {
5883
6035
  setSession(null);
5884
6036
  setError(null);
5885
6037
  setShowOnboarding(false);
6038
+ hasAuthenticatedRef.current = false;
5886
6039
  router.push("/login");
5887
6040
  } catch (err) {
5888
6041
  console.error("[AuthContext] Sign out error:", err);
@@ -5891,6 +6044,48 @@ var AuthProvider = ({ children }) => {
5891
6044
  setLoading(false);
5892
6045
  }
5893
6046
  }, [supabase, router, authConfig]);
6047
+ useSessionKeepAlive({
6048
+ enabled: !!session,
6049
+ // Only when logged in
6050
+ intervalMs: 3e5
6051
+ // 5 minutes
6052
+ });
6053
+ useEffect(() => {
6054
+ if (!session || !supabase) {
6055
+ return;
6056
+ }
6057
+ const monitorTokenExpiry = () => {
6058
+ const expiresAt = session.expires_at;
6059
+ if (!expiresAt) {
6060
+ console.warn("[AuthContext] Session has no expiry time");
6061
+ return;
6062
+ }
6063
+ const expiryTime = expiresAt * 1e3;
6064
+ const now2 = Date.now();
6065
+ const timeUntilExpiry = expiryTime - now2;
6066
+ const minutesUntilExpiry = Math.floor(timeUntilExpiry / 6e4);
6067
+ console.log(`[AuthContext] Token expires in ${minutesUntilExpiry} minutes`);
6068
+ if (minutesUntilExpiry < 5 && minutesUntilExpiry > 0) {
6069
+ console.warn("[AuthContext] Token expiring soon, attempting refresh...");
6070
+ supabase.auth.refreshSession().then(({ data, error: error2 }) => {
6071
+ if (error2) {
6072
+ console.error("[AuthContext] Token refresh failed:", error2);
6073
+ } else {
6074
+ console.log("[AuthContext] Token refreshed successfully");
6075
+ }
6076
+ });
6077
+ }
6078
+ if (timeUntilExpiry < 0) {
6079
+ console.error("[AuthContext] Token has expired, logging out");
6080
+ signOut();
6081
+ }
6082
+ };
6083
+ monitorTokenExpiry();
6084
+ const intervalId = setInterval(monitorTokenExpiry, 6e4);
6085
+ return () => {
6086
+ clearInterval(intervalId);
6087
+ };
6088
+ }, [session, supabase, signOut]);
5894
6089
  useEffect(() => {
5895
6090
  if (!supabase) {
5896
6091
  console.log("[AuthContext] No Supabase client, skipping auth initialization");
@@ -5911,7 +6106,8 @@ var AuthProvider = ({ children }) => {
5911
6106
  }
5912
6107
  if (currentSession) {
5913
6108
  console.log("[AuthContext] Found existing session, fetching user data");
5914
- await fetchSession(currentSession);
6109
+ const isReauth = hasAuthenticatedRef.current;
6110
+ await fetchSession(currentSession, isReauth);
5915
6111
  } else {
5916
6112
  console.log("[AuthContext] No session found");
5917
6113
  setLoading(false);
@@ -5943,20 +6139,27 @@ var AuthProvider = ({ children }) => {
5943
6139
  }
5944
6140
  console.log("[AuthContext] Processing auth event, fetching session");
5945
6141
  lastProcessedSessionRef.current = sessionId;
5946
- await fetchSession(currentSession);
6142
+ const isReauth = hasAuthenticatedRef.current;
6143
+ await fetchSession(currentSession, isReauth);
5947
6144
  }
5948
6145
  } else if (event === "SIGNED_OUT") {
5949
6146
  console.log("[AuthContext] User signed out");
5950
6147
  lastProcessedSessionRef.current = null;
6148
+ hasAuthenticatedRef.current = false;
5951
6149
  setUser(null);
5952
6150
  setSession(null);
5953
6151
  setError(null);
5954
6152
  setShowOnboarding(false);
5955
6153
  setLoading(false);
5956
6154
  } else if (event === "TOKEN_REFRESHED") {
5957
- console.log("[AuthContext] Token refreshed");
6155
+ console.log("[AuthContext] Token refreshed automatically");
5958
6156
  if (currentSession) {
5959
6157
  setSession(currentSession);
6158
+ const expiresAt = currentSession.expires_at;
6159
+ if (expiresAt) {
6160
+ const minutesUntilExpiry = Math.floor((expiresAt * 1e3 - Date.now()) / 6e4);
6161
+ console.log(`[AuthContext] New token expires in ${minutesUntilExpiry} minutes`);
6162
+ }
5960
6163
  }
5961
6164
  }
5962
6165
  });
@@ -5964,7 +6167,7 @@ var AuthProvider = ({ children }) => {
5964
6167
  mounted = false;
5965
6168
  subscription?.unsubscribe();
5966
6169
  };
5967
- }, [supabase, fetchSession]);
6170
+ }, [supabase]);
5968
6171
  const value = {
5969
6172
  session,
5970
6173
  user,
@@ -6012,22 +6215,6 @@ function usePageOverride(key, Default) {
6012
6215
  function useOverrides() {
6013
6216
  return useContext(DashboardOverridesContext);
6014
6217
  }
6015
- var SupabaseContext = createContext(void 0);
6016
- var SupabaseProvider = ({ client, children }) => {
6017
- _setSupabaseInstance(client);
6018
- useEffect(() => {
6019
- _setSupabaseInstance(client);
6020
- }, [client]);
6021
- const contextValue = useMemo(() => ({ supabase: client }), [client]);
6022
- return /* @__PURE__ */ jsx(SupabaseContext.Provider, { value: contextValue, children });
6023
- };
6024
- var useSupabase = () => {
6025
- const context = useContext(SupabaseContext);
6026
- if (context === void 0) {
6027
- throw new Error("useSupabase must be used within a SupabaseProvider.");
6028
- }
6029
- return context.supabase;
6030
- };
6031
6218
  var SubscriptionManagerContext = createContext({
6032
6219
  subscriptionManager: null
6033
6220
  });
@@ -10507,6 +10694,153 @@ var useWorkspaceHealthById = (workspaceId, options) => {
10507
10694
  refetch: fetchWorkspaceHealth
10508
10695
  };
10509
10696
  };
10697
+
10698
+ // src/lib/utils/relativeTime.ts
10699
+ function formatRelativeTime(timestamp) {
10700
+ if (!timestamp) return "Never";
10701
+ try {
10702
+ const now2 = /* @__PURE__ */ new Date();
10703
+ const date = typeof timestamp === "string" ? new Date(timestamp) : timestamp;
10704
+ if (isNaN(date.getTime())) return "Invalid date";
10705
+ if (date > now2) return "Just now";
10706
+ const diffMs = now2.getTime() - date.getTime();
10707
+ const diffSeconds = Math.floor(diffMs / 1e3);
10708
+ const diffMinutes = Math.floor(diffSeconds / 60);
10709
+ const diffHours = Math.floor(diffMinutes / 60);
10710
+ const diffDays = Math.floor(diffHours / 24);
10711
+ if (diffSeconds < 60) {
10712
+ return "Less than a minute ago";
10713
+ }
10714
+ if (diffMinutes < 60) {
10715
+ const minuteLabel = diffMinutes === 1 ? "minute" : "minutes";
10716
+ return `${diffMinutes} ${minuteLabel} ago`;
10717
+ }
10718
+ if (diffHours < 24) {
10719
+ const hourLabel = diffHours === 1 ? "hour" : "hours";
10720
+ return `${diffHours} ${hourLabel} ago`;
10721
+ }
10722
+ const dayLabel = diffDays === 1 ? "day" : "days";
10723
+ return `${diffDays} ${dayLabel} ago`;
10724
+ } catch (error) {
10725
+ console.error("[formatRelativeTime] Error formatting timestamp:", error);
10726
+ return "Unknown";
10727
+ }
10728
+ }
10729
+ function getNextUpdateInterval(timestamp) {
10730
+ if (!timestamp) return 6e4;
10731
+ try {
10732
+ const now2 = /* @__PURE__ */ new Date();
10733
+ const date = typeof timestamp === "string" ? new Date(timestamp) : timestamp;
10734
+ if (isNaN(date.getTime())) return 6e4;
10735
+ const diffMs = now2.getTime() - date.getTime();
10736
+ const diffSeconds = Math.floor(diffMs / 1e3);
10737
+ const diffMinutes = Math.floor(diffSeconds / 60);
10738
+ const diffHours = Math.floor(diffMinutes / 60);
10739
+ if (diffSeconds < 60) return 1e4;
10740
+ if (diffMinutes < 60) return 6e4;
10741
+ if (diffHours < 24) return 6e4;
10742
+ return 36e5;
10743
+ } catch (error) {
10744
+ return 6e4;
10745
+ }
10746
+ }
10747
+
10748
+ // src/lib/hooks/useWorkspaceHealthStatus.ts
10749
+ var useWorkspaceHealthStatus = (workspaceId) => {
10750
+ const supabase = useSupabase();
10751
+ const [healthData, setHealthData] = useState(null);
10752
+ const [loading, setLoading] = useState(true);
10753
+ const [error, setError] = useState(null);
10754
+ const [timeSinceUpdate, setTimeSinceUpdate] = useState("Never");
10755
+ const isFetchingRef = useRef(false);
10756
+ const updateIntervalRef = useRef(null);
10757
+ const fetchHealthStatus = useCallback(async () => {
10758
+ if (!supabase || !workspaceId || isFetchingRef.current) return;
10759
+ try {
10760
+ isFetchingRef.current = true;
10761
+ setLoading(true);
10762
+ setError(null);
10763
+ const { data, error: fetchError } = await supabase.from("workspace_health_status").select("*").eq("workspace_id", workspaceId).maybeSingle();
10764
+ if (fetchError) throw fetchError;
10765
+ if (data) {
10766
+ setHealthData(data);
10767
+ setTimeSinceUpdate(formatRelativeTime(data.last_heartbeat));
10768
+ } else {
10769
+ setHealthData(null);
10770
+ setTimeSinceUpdate("Never");
10771
+ }
10772
+ } catch (err) {
10773
+ console.error("[useWorkspaceHealthStatus] Error fetching health status:", err);
10774
+ setError({ message: err.message, code: err.code || "FETCH_ERROR" });
10775
+ setHealthData(null);
10776
+ setTimeSinceUpdate("Unknown");
10777
+ } finally {
10778
+ setLoading(false);
10779
+ isFetchingRef.current = false;
10780
+ }
10781
+ }, [supabase, workspaceId]);
10782
+ const updateDisplayTime = useCallback(() => {
10783
+ if (healthData?.last_heartbeat) {
10784
+ setTimeSinceUpdate(formatRelativeTime(healthData.last_heartbeat));
10785
+ }
10786
+ }, [healthData?.last_heartbeat]);
10787
+ useEffect(() => {
10788
+ fetchHealthStatus();
10789
+ }, [fetchHealthStatus]);
10790
+ useEffect(() => {
10791
+ if (!supabase || !workspaceId) return;
10792
+ console.log("[useWorkspaceHealthStatus] Setting up real-time subscription for workspace:", workspaceId);
10793
+ const channel = supabase.channel(`workspace-health-status-${workspaceId}`).on(
10794
+ "postgres_changes",
10795
+ {
10796
+ event: "*",
10797
+ // Listen to all events (INSERT, UPDATE, DELETE)
10798
+ schema: "public",
10799
+ table: "workspace_health_status",
10800
+ filter: `workspace_id=eq.${workspaceId}`
10801
+ },
10802
+ (payload) => {
10803
+ console.log("[useWorkspaceHealthStatus] Real-time update received:", payload);
10804
+ if (payload.new && "last_heartbeat" in payload.new) {
10805
+ const newData = payload.new;
10806
+ setHealthData(newData);
10807
+ setTimeSinceUpdate(formatRelativeTime(newData.last_heartbeat));
10808
+ } else if (payload.eventType === "DELETE") {
10809
+ setHealthData(null);
10810
+ setTimeSinceUpdate("Never");
10811
+ }
10812
+ }
10813
+ ).subscribe((status) => {
10814
+ console.log("[useWorkspaceHealthStatus] Subscription status:", status);
10815
+ });
10816
+ return () => {
10817
+ console.log("[useWorkspaceHealthStatus] Cleaning up subscription");
10818
+ supabase.removeChannel(channel);
10819
+ };
10820
+ }, [supabase, workspaceId]);
10821
+ useEffect(() => {
10822
+ if (updateIntervalRef.current) {
10823
+ clearInterval(updateIntervalRef.current);
10824
+ }
10825
+ if (!healthData?.last_heartbeat) return;
10826
+ const intervalMs = getNextUpdateInterval(healthData.last_heartbeat);
10827
+ updateIntervalRef.current = setInterval(updateDisplayTime, intervalMs);
10828
+ return () => {
10829
+ if (updateIntervalRef.current) {
10830
+ clearInterval(updateIntervalRef.current);
10831
+ }
10832
+ };
10833
+ }, [healthData?.last_heartbeat, updateDisplayTime]);
10834
+ return {
10835
+ lastHeartbeat: healthData?.last_heartbeat || null,
10836
+ timeSinceUpdate,
10837
+ isHealthy: healthData?.is_healthy ?? false,
10838
+ healthData,
10839
+ loading,
10840
+ error,
10841
+ refetch: fetchHealthStatus
10842
+ };
10843
+ };
10510
10844
  function useDateFormatter() {
10511
10845
  const { defaultTimezone, defaultLocale, dateFormatOptions, timeFormatOptions, dateTimeFormatOptions } = useDateTimeConfig();
10512
10846
  const formatDate = useCallback(
@@ -10580,50 +10914,129 @@ function useAccessControl() {
10580
10914
  const userRole = useMemo(() => {
10581
10915
  if (!user?.role_level) return null;
10582
10916
  const roleLevel = user.role_level;
10583
- if (roleLevel === "owner" || roleLevel === "plant_head" || roleLevel === "supervisor") {
10917
+ if (roleLevel === "owner" || roleLevel === "plant_head" || roleLevel === "supervisor" || roleLevel === "optifye") {
10584
10918
  return roleLevel;
10585
10919
  }
10586
10920
  return "supervisor";
10587
10921
  }, [user?.role_level]);
10588
- const allPages = [
10589
- "/",
10590
- "/leaderboard",
10591
- "/kpis",
10592
- "/targets",
10593
- "/shifts",
10594
- "/supervisor-management",
10595
- "/skus",
10596
- "/ai-agent",
10597
- "/help",
10598
- "/health",
10599
- "/profile",
10600
- "/workspace",
10601
- "/factory-view"
10602
- ];
10922
+ const assignedLineIds = useMemo(() => {
10923
+ if (!user) return [];
10924
+ if (user.role_level === "supervisor") {
10925
+ const lines = user.properties?.line_id || user.properties?.line_ids || [];
10926
+ return Array.isArray(lines) ? lines : [];
10927
+ }
10928
+ return [];
10929
+ }, [user]);
10930
+ const assignedFactoryIds = useMemo(() => {
10931
+ if (!user) return [];
10932
+ if (user.role_level === "plant_head") {
10933
+ const factories = user.properties?.factory_id || user.properties?.factory_ids || [];
10934
+ return Array.isArray(factories) ? factories : [];
10935
+ }
10936
+ return [];
10937
+ }, [user]);
10938
+ const roleAccessMap = {
10939
+ optifye: [
10940
+ "/",
10941
+ "/leaderboard",
10942
+ "/kpis",
10943
+ "/targets",
10944
+ "/shifts",
10945
+ "/supervisor-management",
10946
+ "/skus",
10947
+ "/ai-agent",
10948
+ "/help",
10949
+ "/health",
10950
+ "/profile",
10951
+ "/workspace",
10952
+ "/factory-view",
10953
+ "/team-management"
10954
+ ],
10955
+ owner: [
10956
+ "/",
10957
+ "/leaderboard",
10958
+ "/kpis",
10959
+ "/targets",
10960
+ "/shifts",
10961
+ "/supervisor-management",
10962
+ "/skus",
10963
+ "/ai-agent",
10964
+ "/help",
10965
+ "/health",
10966
+ "/profile",
10967
+ "/workspace",
10968
+ "/factory-view",
10969
+ "/team-management"
10970
+ ],
10971
+ plant_head: [
10972
+ "/",
10973
+ "/leaderboard",
10974
+ "/kpis",
10975
+ "/targets",
10976
+ "/shifts",
10977
+ "/supervisor-management",
10978
+ "/skus",
10979
+ "/ai-agent",
10980
+ "/help",
10981
+ "/health",
10982
+ "/profile",
10983
+ "/workspace",
10984
+ "/factory-view",
10985
+ "/team-management"
10986
+ ],
10987
+ supervisor: [
10988
+ "/",
10989
+ "/leaderboard",
10990
+ "/kpis",
10991
+ "/targets",
10992
+ "/shifts",
10993
+ "/skus",
10994
+ "/ai-agent",
10995
+ "/help",
10996
+ "/health",
10997
+ "/profile",
10998
+ "/workspace"
10999
+ ]
11000
+ };
10603
11001
  const accessiblePages = useMemo(() => {
10604
- return allPages;
10605
- }, []);
11002
+ if (!userRole) return [];
11003
+ return roleAccessMap[userRole] || [];
11004
+ }, [userRole]);
10606
11005
  const hasAccess = useMemo(() => {
10607
11006
  return (path) => {
10608
- return true;
11007
+ if (!userRole) return false;
11008
+ const basePath = path.split("?")[0].split("/").slice(0, 2).join("/");
11009
+ const hasBaseAccess = accessiblePages.includes(basePath) || accessiblePages.includes("/");
11010
+ if (userRole === "supervisor" && assignedLineIds.length > 0) {
11011
+ if (path.includes("/kpis/") || path.includes("/workspace/")) {
11012
+ const lineIdMatch = path.match(/\/kpis\/([^/?]+)/);
11013
+ if (lineIdMatch) {
11014
+ const pathLineId = lineIdMatch[1];
11015
+ return assignedLineIds.includes(pathLineId);
11016
+ }
11017
+ }
11018
+ }
11019
+ return hasBaseAccess;
10609
11020
  };
10610
- }, []);
11021
+ }, [userRole, accessiblePages, assignedLineIds]);
10611
11022
  const isPageVisible = useMemo(() => {
10612
11023
  return (path) => {
10613
- return true;
11024
+ return hasAccess(path);
10614
11025
  };
10615
- }, []);
11026
+ }, [hasAccess]);
10616
11027
  const canAccessPage = useMemo(() => {
10617
11028
  return (path) => {
10618
- return true;
11029
+ return hasAccess(path);
10619
11030
  };
10620
- }, []);
11031
+ }, [hasAccess]);
10621
11032
  return {
10622
11033
  userRole,
10623
11034
  hasAccess,
10624
11035
  accessiblePages,
10625
11036
  isPageVisible,
10626
- canAccessPage
11037
+ canAccessPage,
11038
+ assignedLineIds,
11039
+ assignedFactoryIds
10627
11040
  };
10628
11041
  }
10629
11042
 
@@ -10787,45 +11200,51 @@ function useHasLineAccess(lineId, configLineIds) {
10787
11200
  function useLineSupervisor(lineId) {
10788
11201
  const supabase = useSupabase();
10789
11202
  const [supervisor, setSupervisor] = useState(null);
11203
+ const [supervisors, setSupervisors] = useState([]);
10790
11204
  const [isLoading, setIsLoading] = useState(true);
10791
11205
  const [error, setError] = useState(null);
10792
- console.log("[useLineSupervisor] Hook initialized for lineId:", lineId);
10793
11206
  const fetchSupervisor = useCallback(async () => {
10794
11207
  if (!lineId || !supabase) {
10795
- console.log("[useLineSupervisor] Skipping fetch - lineId or supabase missing:", { lineId, hasSupabase: !!supabase });
10796
11208
  setIsLoading(false);
10797
11209
  return;
10798
11210
  }
10799
11211
  try {
10800
11212
  setIsLoading(true);
10801
11213
  setError(null);
10802
- console.log("[useLineSupervisor] Fetching supervisor for lineId:", lineId);
10803
- const { data, error: fetchError } = await supabase.from("user_roles").select("user_id, email, properties").eq("role_level", "supervisor").filter("properties->line_id", "@>", `["${lineId}"]`).limit(1);
10804
- console.log("[useLineSupervisor] Query result:", { data, error: fetchError, lineId });
11214
+ const { data, error: fetchError } = await supabase.from("user_roles").select("user_id, email, properties").eq("role_level", "supervisor");
10805
11215
  if (fetchError) {
10806
11216
  console.error("[useLineSupervisor] Query error:", fetchError);
10807
11217
  throw fetchError;
10808
11218
  }
10809
11219
  if (data && data.length > 0) {
10810
- const supervisorData = data[0];
10811
- console.log("[useLineSupervisor] Found supervisor:", {
10812
- email: supervisorData.email,
10813
- properties: supervisorData.properties,
10814
- line_id_in_properties: supervisorData.properties?.line_id
10815
- });
10816
- const displayName = supervisorData.email.split("@")[0] || supervisorData.email;
10817
- setSupervisor({
10818
- userId: supervisorData.user_id,
10819
- email: supervisorData.email,
10820
- displayName
11220
+ const supervisorsForLine = data.filter((supervisorData) => {
11221
+ const lineIds = supervisorData.properties?.line_id || supervisorData.properties?.line_ids || [];
11222
+ const isAssigned = Array.isArray(lineIds) && lineIds.includes(lineId);
11223
+ return isAssigned;
10821
11224
  });
11225
+ if (supervisorsForLine.length > 0) {
11226
+ const allSupervisors = supervisorsForLine.map((supervisorData) => {
11227
+ const displayName = supervisorData.email.split("@")[0] || supervisorData.email;
11228
+ return {
11229
+ userId: supervisorData.user_id,
11230
+ email: supervisorData.email,
11231
+ displayName
11232
+ };
11233
+ });
11234
+ setSupervisors(allSupervisors);
11235
+ setSupervisor(allSupervisors[0]);
11236
+ } else {
11237
+ setSupervisors([]);
11238
+ setSupervisor(null);
11239
+ }
10822
11240
  } else {
10823
- console.log("[useLineSupervisor] No supervisor found for line:", lineId);
11241
+ setSupervisors([]);
10824
11242
  setSupervisor(null);
10825
11243
  }
10826
11244
  } catch (err) {
10827
- console.error("[useLineSupervisor] Error fetching supervisor:", err);
10828
- setError(err instanceof Error ? err : new Error("Failed to fetch supervisor"));
11245
+ console.error("[useLineSupervisor] Error fetching supervisors:", err);
11246
+ setError(err instanceof Error ? err : new Error("Failed to fetch supervisors"));
11247
+ setSupervisors([]);
10829
11248
  setSupervisor(null);
10830
11249
  } finally {
10831
11250
  setIsLoading(false);
@@ -10850,7 +11269,6 @@ function useLineSupervisor(lineId) {
10850
11269
  filter: `role_level=eq.supervisor`
10851
11270
  },
10852
11271
  (payload) => {
10853
- console.log("[useLineSupervisor] Real-time update received:", payload);
10854
11272
  fetchSupervisor();
10855
11273
  }
10856
11274
  ).subscribe();
@@ -10862,9 +11280,11 @@ function useLineSupervisor(lineId) {
10862
11280
  }
10863
11281
  };
10864
11282
  }, [lineId, supabase, fetchSupervisor]);
11283
+ const supervisorName = supervisors.length > 0 ? supervisors.map((s) => s.displayName).join(", ") : null;
10865
11284
  return {
10866
- supervisorName: supervisor?.displayName || null,
11285
+ supervisorName,
10867
11286
  supervisor,
11287
+ supervisors,
10868
11288
  isLoading,
10869
11289
  error
10870
11290
  };
@@ -13866,7 +14286,9 @@ var createSupabaseClient = (url, key) => createClient(url, key, {
13866
14286
  autoRefreshToken: true,
13867
14287
  persistSession: true,
13868
14288
  detectSessionInUrl: true,
13869
- flowType: "pkce"
14289
+ flowType: "pkce",
14290
+ // Enable debug logging in development
14291
+ debug: process.env.NODE_ENV === "development"
13870
14292
  },
13871
14293
  db: {
13872
14294
  schema: "public"
@@ -13875,6 +14297,22 @@ var createSupabaseClient = (url, key) => createClient(url, key, {
13875
14297
  global: {
13876
14298
  headers: {
13877
14299
  "x-application-name": "optifye-dashboard"
14300
+ },
14301
+ // Add global fetch timeout (5 minutes)
14302
+ fetch: async (url2, options = {}) => {
14303
+ const controller = new AbortController();
14304
+ const timeoutId = setTimeout(() => controller.abort(), 3e5);
14305
+ try {
14306
+ const response = await fetch(url2, {
14307
+ ...options,
14308
+ signal: controller.signal
14309
+ });
14310
+ clearTimeout(timeoutId);
14311
+ return response;
14312
+ } catch (error) {
14313
+ clearTimeout(timeoutId);
14314
+ throw error;
14315
+ }
13878
14316
  }
13879
14317
  }
13880
14318
  });
@@ -13889,7 +14327,29 @@ var getAnonClient = () => {
13889
14327
  autoRefreshToken: true,
13890
14328
  persistSession: true,
13891
14329
  detectSessionInUrl: true,
13892
- flowType: "pkce"
14330
+ flowType: "pkce",
14331
+ debug: process.env.NODE_ENV === "development"
14332
+ },
14333
+ global: {
14334
+ headers: {
14335
+ "x-application-name": "optifye-dashboard"
14336
+ },
14337
+ // Add global fetch timeout (5 minutes)
14338
+ fetch: async (url2, options = {}) => {
14339
+ const controller = new AbortController();
14340
+ const timeoutId = setTimeout(() => controller.abort(), 3e5);
14341
+ try {
14342
+ const response = await fetch(url2, {
14343
+ ...options,
14344
+ signal: controller.signal
14345
+ });
14346
+ clearTimeout(timeoutId);
14347
+ return response;
14348
+ } catch (error) {
14349
+ clearTimeout(timeoutId);
14350
+ throw error;
14351
+ }
14352
+ }
13893
14353
  }
13894
14354
  });
13895
14355
  };
@@ -21253,17 +21713,33 @@ var createMotionComponent = /* @__PURE__ */ createMotionComponentFactory({
21253
21713
 
21254
21714
  // ../../node_modules/framer-motion/dist/es/render/components/motion/proxy.mjs
21255
21715
  var motion = /* @__PURE__ */ createDOMMotionComponentProxy(createMotionComponent);
21716
+
21717
+ // src/assets/optifye-logo.png
21718
+ var optifye_logo_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAACFIAAASwCAYAAADSLPxEAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEyGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSfvu78nIGlkPSdXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQnPz4KPHg6eG1wbWV0YSB4bWxuczp4PSdhZG9iZTpuczptZXRhLyc+CjxyZGY6UkRGIHhtbG5zOnJkZj0naHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyc+CgogPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9JycKICB4bWxuczpBdHRyaWI9J2h0dHA6Ly9ucy5hdHRyaWJ1dGlvbi5jb20vYWRzLzEuMC8nPgogIDxBdHRyaWI6QWRzPgogICA8cmRmOlNlcT4KICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0nUmVzb3VyY2UnPgogICAgIDxBdHRyaWI6Q3JlYXRlZD4yMDI1LTAyLTE5PC9BdHRyaWI6Q3JlYXRlZD4KICAgICA8QXR0cmliOkV4dElkPmEwNzgwZWVmLWUxNjItNGE4MS1iY2I0LTgxODU3M2VkMmI5YjwvQXR0cmliOkV4dElkPgogICAgIDxBdHRyaWI6RmJJZD41MjUyNjU5MTQxNzk1ODA8L0F0dHJpYjpGYklkPgogICAgIDxBdHRyaWI6VG91Y2hUeXBlPjI8L0F0dHJpYjpUb3VjaFR5cGU+CiAgICA8L3JkZjpsaT4KICAgPC9yZGY6U2VxPgogIDwvQXR0cmliOkFkcz4KIDwvcmRmOkRlc2NyaXB0aW9uPgoKIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PScnCiAgeG1sbnM6ZGM9J2h0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvJz4KICA8ZGM6dGl0bGU+CiAgIDxyZGY6QWx0PgogICAgPHJkZjpsaSB4bWw6bGFuZz0neC1kZWZhdWx0Jz5vcHRpZnllIGxvZ28gc2V4eSAoMjEzMCB4IDEyMDAgcHgpIC0gMTwvcmRmOmxpPgogICA8L3JkZjpBbHQ+CiAgPC9kYzp0aXRsZT4KIDwvcmRmOkRlc2NyaXB0aW9u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";
21719
+ var Logo = ({
21720
+ className = "",
21721
+ alt = "Optifye"
21722
+ }) => {
21723
+ return /* @__PURE__ */ jsx(
21724
+ "img",
21725
+ {
21726
+ src: optifye_logo_default,
21727
+ alt,
21728
+ className
21729
+ }
21730
+ );
21731
+ };
21256
21732
  var OptifyeLogoLoader = ({
21257
21733
  size = "md",
21258
21734
  message,
21259
21735
  className
21260
21736
  }) => {
21261
21737
  const sizeClasses = {
21262
- sm: "w-10",
21738
+ sm: "w-10 h-10",
21263
21739
  // 40px
21264
- md: "w-16",
21740
+ md: "w-16 h-16",
21265
21741
  // 64px
21266
- lg: "w-24"
21742
+ lg: "w-24 h-24"
21267
21743
  // 96px
21268
21744
  };
21269
21745
  return /* @__PURE__ */ jsxs(
@@ -21274,11 +21750,10 @@ var OptifyeLogoLoader = ({
21274
21750
  className: `flex flex-col items-center justify-center p-4 ${className || ""}`.trim(),
21275
21751
  children: [
21276
21752
  /* @__PURE__ */ jsx(
21277
- "img",
21753
+ Logo,
21278
21754
  {
21279
- src: "/optifye-logo.png",
21280
- alt: "Optifye Logo",
21281
- className: `${sizeClasses[size]} h-auto animate-pulse select-none pointer-events-none`
21755
+ className: `${sizeClasses[size]} object-contain animate-pulse select-none pointer-events-none`,
21756
+ alt: "Optifye Logo"
21282
21757
  }
21283
21758
  ),
21284
21759
  message && /* @__PURE__ */ jsx("div", { className: "mt-3 text-gray-600 text-base sm:text-sm font-medium text-center", children: message })
@@ -21290,15 +21765,65 @@ var OptifyeLogoLoader_default = OptifyeLogoLoader;
21290
21765
  var LoadingPage = ({
21291
21766
  message = "Loading Dashboard...",
21292
21767
  subMessage = "Please wait while we prepare your data",
21293
- className
21768
+ className,
21769
+ onTimeout,
21770
+ timeoutMs = 3e5
21771
+ // 5 minutes default
21294
21772
  }) => {
21295
- React23__default.useEffect(() => {
21296
- console.log("LoadingPage rendered with message:", message);
21297
- const timeout = setTimeout(() => {
21298
- console.warn("LoadingPage has been visible for more than 8 seconds. This might indicate an issue.");
21299
- }, 8e3);
21300
- return () => clearTimeout(timeout);
21301
- }, [message]);
21773
+ const [showTimeoutWarning, setShowTimeoutWarning] = useState(false);
21774
+ const [timeoutReached, setTimeoutReached] = useState(false);
21775
+ const warningTime = timeoutMs * 0.8;
21776
+ useEffect(() => {
21777
+ console.log("[LoadingPage] Rendered with message:", message);
21778
+ const warningTimer = setTimeout(() => {
21779
+ console.warn("[LoadingPage] Loading taking longer than expected");
21780
+ setShowTimeoutWarning(true);
21781
+ }, warningTime);
21782
+ const timeoutTimer = setTimeout(() => {
21783
+ console.error("[LoadingPage] Loading timeout reached after", timeoutMs, "ms");
21784
+ setTimeoutReached(true);
21785
+ if (onTimeout) {
21786
+ onTimeout();
21787
+ }
21788
+ }, timeoutMs);
21789
+ return () => {
21790
+ clearTimeout(warningTimer);
21791
+ clearTimeout(timeoutTimer);
21792
+ };
21793
+ }, [message, timeoutMs, warningTime, onTimeout]);
21794
+ const handleResetAndTryAgain = useCallback(() => {
21795
+ console.log("[LoadingPage] User initiated reset");
21796
+ const hasLocalStorage = typeof window !== "undefined" && window.localStorage;
21797
+ const hasCachedData = hasLocalStorage && localStorage.getItem("sb-zmzewpwerpaupoaoeqhh-auth-token");
21798
+ if (hasCachedData) {
21799
+ console.log("[LoadingPage] Found cached session, attempting to use it");
21800
+ window.location.reload();
21801
+ } else {
21802
+ console.log("[LoadingPage] No cached session, redirecting to login");
21803
+ if (hasLocalStorage) {
21804
+ localStorage.clear();
21805
+ sessionStorage.clear();
21806
+ }
21807
+ window.location.href = "/login";
21808
+ }
21809
+ }, []);
21810
+ if (timeoutReached) {
21811
+ return /* @__PURE__ */ jsx("div", { className: `flex h-full w-full items-center justify-center bg-slate-50 ${className || ""}`, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center space-y-6 text-center max-w-md", children: [
21812
+ /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "lg", message: "Loading Dashboard..." }),
21813
+ /* @__PURE__ */ jsxs(motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "space-y-2", children: [
21814
+ /* @__PURE__ */ jsx("p", { className: "text-base text-gray-600", children: "This is taking longer than usual" }),
21815
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: "Your session might have timed out" })
21816
+ ] }),
21817
+ /* @__PURE__ */ jsx(
21818
+ "button",
21819
+ {
21820
+ onClick: handleResetAndTryAgain,
21821
+ className: "mt-4 px-4 py-2 text-sm text-gray-600 hover:text-gray-900 underline transition-colors",
21822
+ children: "Reset and try again"
21823
+ }
21824
+ )
21825
+ ] }) });
21826
+ }
21302
21827
  return /* @__PURE__ */ jsx("div", { className: `flex h-full w-full items-center justify-center bg-slate-50 ${className || ""}`, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center space-y-6 text-center", children: [
21303
21828
  /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "lg", message }),
21304
21829
  subMessage && /* @__PURE__ */ jsx(
@@ -21310,23 +21835,19 @@ var LoadingPage = ({
21310
21835
  transition: { delay: 0.2, duration: 0.3 },
21311
21836
  children: subMessage
21312
21837
  }
21838
+ ),
21839
+ showTimeoutWarning && !timeoutReached && /* @__PURE__ */ jsx(
21840
+ motion.p,
21841
+ {
21842
+ initial: { opacity: 0 },
21843
+ animate: { opacity: 1 },
21844
+ className: "text-sm text-gray-500 italic",
21845
+ children: "Still loading, please wait..."
21846
+ }
21313
21847
  )
21314
21848
  ] }) });
21315
21849
  };
21316
21850
  var LoadingPage_default = LoadingPage;
21317
- var AccessDeniedPage = () => /* @__PURE__ */ jsx("div", { className: "min-h-screen flex items-center justify-center bg-gray-50", children: /* @__PURE__ */ jsxs("div", { className: "max-w-md w-full bg-white shadow-lg rounded-lg p-6 text-center", children: [
21318
- /* @__PURE__ */ jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsx("svg", { className: "mx-auto h-12 w-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.962-.833-2.732 0L4.082 15.5c-.77.833.192 2.5 1.732 2.5z" }) }) }),
21319
- /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-gray-900 mb-2", children: "Access Denied" }),
21320
- /* @__PURE__ */ jsx("p", { className: "text-gray-600 mb-4", children: "You do not have access to this dashboard. Please contact your administrator for assistance." }),
21321
- /* @__PURE__ */ jsx(
21322
- "button",
21323
- {
21324
- onClick: () => window.location.href = "/login",
21325
- className: "bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-md transition-colors",
21326
- children: "Return to Login"
21327
- }
21328
- )
21329
- ] }) });
21330
21851
  var withAuth = (WrappedComponent2, options) => {
21331
21852
  const defaultOptions = {
21332
21853
  redirectTo: "/login",
@@ -21336,22 +21857,64 @@ var withAuth = (WrappedComponent2, options) => {
21336
21857
  const WithAuthComponent = React23.memo(function WithAuthComponent2(props) {
21337
21858
  const { session, loading, error } = useAuth();
21338
21859
  const router = useRouter();
21860
+ const [localLoading, setLocalLoading] = React23.useState(loading);
21861
+ const [loadingTimeoutReached, setLoadingTimeoutReached] = React23.useState(false);
21339
21862
  React23.useEffect(() => {
21340
21863
  if (process.env.NODE_ENV === "development" && process.env.DEBUG_AUTH === "true") {
21341
- console.log("withAuth state:", { loading, hasSession: !!session, requireAuth: defaultOptions.requireAuth });
21864
+ console.log("withAuth state:", {
21865
+ loading,
21866
+ hasSession: !!session,
21867
+ requireAuth: defaultOptions.requireAuth,
21868
+ hasError: !!error
21869
+ });
21342
21870
  }
21343
- }, [session, loading]);
21871
+ }, [session, loading, error]);
21872
+ const handleLoadingTimeout = React23.useCallback(() => {
21873
+ console.warn("[withAuth] Loading timeout reached");
21874
+ setLoadingTimeoutReached(true);
21875
+ if (typeof window !== "undefined" && localStorage.getItem("sb-zmzewpwerpaupoaoeqhh-auth-token")) {
21876
+ console.log("[withAuth] Found cached session, attempting to continue");
21877
+ setLocalLoading(false);
21878
+ } else {
21879
+ console.log("[withAuth] No cached session, redirecting to login");
21880
+ router.replace(defaultOptions.redirectTo);
21881
+ }
21882
+ }, [router]);
21344
21883
  React23.useEffect(() => {
21345
21884
  if (!loading && defaultOptions.requireAuth && !session && !error) {
21346
- console.log("Redirecting to login from withAuth");
21885
+ console.log("[withAuth] No session found, redirecting to login");
21347
21886
  router.replace(defaultOptions.redirectTo);
21348
21887
  }
21349
21888
  }, [session, loading, router, error]);
21350
- if (loading) {
21351
- return /* @__PURE__ */ jsx(LoadingPage, { message: "Authenticating..." });
21889
+ React23.useEffect(() => {
21890
+ setLocalLoading(loading);
21891
+ }, [loading]);
21892
+ if (loading || localLoading) {
21893
+ return /* @__PURE__ */ jsx(
21894
+ LoadingPage,
21895
+ {
21896
+ message: "Authenticating...",
21897
+ timeoutMs: 3e5,
21898
+ onTimeout: handleLoadingTimeout
21899
+ }
21900
+ );
21352
21901
  }
21353
- if (error && error.message.includes("You do not have access to this dashboard")) {
21354
- return /* @__PURE__ */ jsx(AccessDeniedPage, {});
21902
+ if (error) {
21903
+ console.error("[withAuth] Auth error:", {
21904
+ message: error.message,
21905
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
21906
+ });
21907
+ if (error.message.includes("You do not have access to this dashboard")) {
21908
+ return /* @__PURE__ */ jsx("div", { className: "min-h-screen flex items-center justify-center bg-slate-50", children: /* @__PURE__ */ jsxs("div", { className: "max-w-md text-center space-y-4", children: [
21909
+ /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "lg", message: "Checking Access..." }),
21910
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: "Verifying your permissions" }),
21911
+ /* @__PURE__ */ jsx("a", { href: "/login", className: "text-xs text-gray-400 hover:text-gray-600 underline", children: "Return to login" })
21912
+ ] }) });
21913
+ }
21914
+ if (defaultOptions.requireAuth) {
21915
+ router.replace(defaultOptions.redirectTo);
21916
+ return null;
21917
+ }
21355
21918
  }
21356
21919
  if (defaultOptions.requireAuth && !session) {
21357
21920
  return null;
@@ -21388,7 +21951,7 @@ function withAccessControl(WrappedComponent2, options = {}) {
21388
21951
  }
21389
21952
  var LoginPage = ({
21390
21953
  onRateLimitCheck,
21391
- logoSrc = "/optifye-logo.png",
21954
+ logoSrc = optifye_logo_default,
21392
21955
  logoAlt = "Optifye",
21393
21956
  brandName = "Optifye"
21394
21957
  }) => {
@@ -24997,13 +25560,37 @@ var WhatsAppShareButton = ({
24997
25560
  }
24998
25561
  );
24999
25562
  };
25563
+ var AxelOrb = ({
25564
+ className = "",
25565
+ size = "md",
25566
+ animate = false
25567
+ }) => {
25568
+ const sizeClasses = {
25569
+ sm: "w-8 h-8",
25570
+ md: "w-10 h-10",
25571
+ lg: "w-12 h-12",
25572
+ xl: "w-16 h-16",
25573
+ "2xl": "w-20 h-20"
25574
+ };
25575
+ return /* @__PURE__ */ jsx(
25576
+ "div",
25577
+ {
25578
+ className: `${sizeClasses[size]} rounded-full ${animate ? "animate-float" : ""} ${className}`,
25579
+ style: {
25580
+ background: "linear-gradient(to top, #078DDB 0%, #65ADD6 33%, #A3D0E6 66%, #C7E2EC 100%)",
25581
+ boxShadow: "0 4px 12px rgba(7, 141, 219, 0.4), 0 0 20px rgba(7, 141, 219, 0.2)"
25582
+ },
25583
+ "aria-label": "Axel AI",
25584
+ role: "img"
25585
+ }
25586
+ );
25587
+ };
25000
25588
  var BreakNotificationPopup = ({
25001
25589
  activeBreaks,
25002
25590
  onDismiss,
25003
25591
  isVisible = true,
25004
25592
  className = "",
25005
- lineNames = {},
25006
- axelImagePath = "/axel-profile.png"
25593
+ lineNames = {}
25007
25594
  }) => {
25008
25595
  const [isDismissed, setIsDismissed] = useState(false);
25009
25596
  const [currentTime, setCurrentTime] = useState(/* @__PURE__ */ new Date());
@@ -25039,22 +25626,7 @@ var BreakNotificationPopup = ({
25039
25626
  style: { top: `${6 + index * 12}rem` },
25040
25627
  children: /* @__PURE__ */ jsx("div", { className: "bg-white text-gray-900 rounded-lg border border-gray-200 shadow-lg overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "p-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between", children: [
25041
25628
  /* @__PURE__ */ jsxs("div", { className: "flex items-start space-x-3 flex-1", children: [
25042
- /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx(
25043
- "img",
25044
- {
25045
- src: axelImagePath,
25046
- alt: "Axel AI",
25047
- className: "w-10 h-10 rounded-full object-cover border-2 border-gray-200 shadow-sm",
25048
- onError: (e) => {
25049
- const target = e.currentTarget;
25050
- target.style.display = "none";
25051
- const fallback = document.createElement("div");
25052
- fallback.className = "w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold text-base shadow-sm border-2 border-gray-200";
25053
- fallback.textContent = "A";
25054
- target.parentElement?.appendChild(fallback);
25055
- }
25056
- }
25057
- ) }),
25629
+ /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx(AxelOrb, { size: "md" }) }),
25058
25630
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
25059
25631
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [
25060
25632
  /* @__PURE__ */ jsxs("h4", { className: "font-semibold text-sm text-gray-900", children: [
@@ -25254,8 +25826,7 @@ var AxelNotificationPopup = ({
25254
25826
  suggestion,
25255
25827
  isVisible = true,
25256
25828
  onDismiss,
25257
- className = "",
25258
- axelImagePath = "/axel-profile.png"
25829
+ className = ""
25259
25830
  }) => {
25260
25831
  const [isDismissed, setIsDismissed] = useState(false);
25261
25832
  useEffect(() => {
@@ -25301,22 +25872,7 @@ var AxelNotificationPopup = ({
25301
25872
  className: "p-3",
25302
25873
  children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between", children: [
25303
25874
  /* @__PURE__ */ jsxs("div", { className: "flex items-start space-x-3 flex-1", children: [
25304
- /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx(
25305
- "img",
25306
- {
25307
- src: axelImagePath,
25308
- alt: "Axel AI",
25309
- className: "w-10 h-10 rounded-full object-cover border-2 border-gray-200 shadow-sm",
25310
- onError: (e) => {
25311
- const target = e.currentTarget;
25312
- target.style.display = "none";
25313
- const fallback = document.createElement("div");
25314
- fallback.className = "w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold text-base shadow-sm border-2 border-gray-200";
25315
- fallback.textContent = "A";
25316
- target.parentElement?.appendChild(fallback);
25317
- }
25318
- }
25319
- ) }),
25875
+ /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx(AxelOrb, { size: "md" }) }),
25320
25876
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
25321
25877
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [
25322
25878
  /* @__PURE__ */ jsx("h4", { className: "font-semibold text-sm text-gray-900", children: suggestion.title }),
@@ -25767,6 +26323,140 @@ var TimePickerDropdown = ({
25767
26323
  ] })
25768
26324
  ] });
25769
26325
  };
26326
+ var SilentErrorBoundary = class extends React23__default.Component {
26327
+ constructor(props) {
26328
+ super(props);
26329
+ this.handleClearAndReload = () => {
26330
+ console.log("[ErrorBoundary] User initiated reset");
26331
+ if (typeof window !== "undefined") {
26332
+ try {
26333
+ localStorage.clear();
26334
+ sessionStorage.clear();
26335
+ console.log("[ErrorBoundary] Cleared all storage");
26336
+ } catch (error) {
26337
+ console.error("[ErrorBoundary] Failed to clear storage:", error);
26338
+ }
26339
+ }
26340
+ window.location.href = "/login";
26341
+ };
26342
+ this.state = {
26343
+ hasError: false,
26344
+ errorCount: 0,
26345
+ lastError: null,
26346
+ errorInfo: null
26347
+ };
26348
+ }
26349
+ static getDerivedStateFromError(error) {
26350
+ return { hasError: true };
26351
+ }
26352
+ componentDidCatch(error, errorInfo) {
26353
+ console.error("[ErrorBoundary] Caught render error:", {
26354
+ error: error.message,
26355
+ stack: error.stack,
26356
+ componentStack: errorInfo.componentStack,
26357
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
26358
+ });
26359
+ this.setState((prev) => ({
26360
+ errorCount: prev.errorCount + 1,
26361
+ lastError: error,
26362
+ errorInfo
26363
+ }));
26364
+ try {
26365
+ if (typeof window !== "undefined" && window.mixpanel) {
26366
+ window.mixpanel.track("React Render Error", {
26367
+ error: error.message,
26368
+ component: errorInfo.componentStack?.split("\n")[1] || "unknown",
26369
+ errorCount: this.state.errorCount + 1
26370
+ });
26371
+ }
26372
+ } catch (analyticsError) {
26373
+ console.warn("[ErrorBoundary] Analytics tracking failed:", analyticsError);
26374
+ }
26375
+ }
26376
+ render() {
26377
+ if (!this.state.hasError) {
26378
+ return this.props.children;
26379
+ }
26380
+ return /* @__PURE__ */ jsx("div", { className: "flex h-screen w-screen items-center justify-center bg-slate-50", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center space-y-6 text-center", children: [
26381
+ /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "lg", message: "Loading Dashboard..." }),
26382
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: "Taking longer than usual..." }),
26383
+ /* @__PURE__ */ jsx("div", { className: "pt-4", children: /* @__PURE__ */ jsx(
26384
+ "a",
26385
+ {
26386
+ href: "#",
26387
+ onClick: (e) => {
26388
+ e.preventDefault();
26389
+ this.handleClearAndReload();
26390
+ },
26391
+ className: "text-xs text-gray-400 hover:text-gray-600 underline transition-colors",
26392
+ children: "Reset and try again"
26393
+ }
26394
+ ) }),
26395
+ process.env.NODE_ENV === "development" && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-400 italic mt-4", children: "Check console for error details" })
26396
+ ] }) });
26397
+ }
26398
+ };
26399
+ var PlayPauseIndicator = ({
26400
+ show,
26401
+ isPlaying,
26402
+ duration = 600
26403
+ }) => {
26404
+ const [isVisible, setIsVisible] = useState(false);
26405
+ const [isFading, setIsFading] = useState(false);
26406
+ useEffect(() => {
26407
+ if (show) {
26408
+ setIsVisible(true);
26409
+ setIsFading(false);
26410
+ const fadeTimer = setTimeout(() => {
26411
+ setIsFading(true);
26412
+ }, 100);
26413
+ const hideTimer = setTimeout(() => {
26414
+ setIsVisible(false);
26415
+ setIsFading(false);
26416
+ }, duration);
26417
+ return () => {
26418
+ clearTimeout(fadeTimer);
26419
+ clearTimeout(hideTimer);
26420
+ };
26421
+ }
26422
+ }, [show, duration]);
26423
+ if (!isVisible) return null;
26424
+ return /* @__PURE__ */ jsx(
26425
+ "div",
26426
+ {
26427
+ className: "absolute inset-0 flex items-center justify-center pointer-events-none z-10",
26428
+ style: {
26429
+ opacity: isFading ? 0 : 1,
26430
+ transition: `opacity ${duration - 100}ms ease-out`
26431
+ },
26432
+ children: /* @__PURE__ */ jsx("div", { className: "bg-black/70 rounded-full p-6", children: isPlaying ? (
26433
+ // Play icon (triangle)
26434
+ /* @__PURE__ */ jsx(
26435
+ "svg",
26436
+ {
26437
+ xmlns: "http://www.w3.org/2000/svg",
26438
+ viewBox: "0 0 24 24",
26439
+ fill: "white",
26440
+ className: "w-16 h-16",
26441
+ children: /* @__PURE__ */ jsx("path", { d: "M8 5v14l11-7z" })
26442
+ }
26443
+ )
26444
+ ) : (
26445
+ // Pause icon (two bars)
26446
+ /* @__PURE__ */ jsx(
26447
+ "svg",
26448
+ {
26449
+ xmlns: "http://www.w3.org/2000/svg",
26450
+ viewBox: "0 0 24 24",
26451
+ fill: "white",
26452
+ className: "w-16 h-16",
26453
+ children: /* @__PURE__ */ jsx("path", { d: "M6 4h4v16H6V4zm8 0h4v16h-4V4z" })
26454
+ }
26455
+ )
26456
+ ) })
26457
+ }
26458
+ );
26459
+ };
25770
26460
  var ERROR_MAPPING = {
25771
26461
  1: {
25772
26462
  // MEDIA_ERR_ABORTED
@@ -25872,12 +26562,16 @@ var VideoPlayer = React23__default.forwardRef(({
25872
26562
  onLoadedMetadata,
25873
26563
  onLoadedData,
25874
26564
  onSeeking,
25875
- onSeeked
26565
+ onSeeked,
26566
+ onClick
25876
26567
  }, ref) => {
25877
26568
  const videoRef = useRef(null);
25878
26569
  const playerRef = useRef(null);
25879
26570
  const [isReady, setIsReady] = useState(false);
25880
26571
  const [isLoading, setIsLoading] = useState(true);
26572
+ const [showIndicator, setShowIndicator] = useState(false);
26573
+ const [indicatorIsPlaying, setIndicatorIsPlaying] = useState(false);
26574
+ const indicatorKeyRef = useRef(0);
25881
26575
  const defaultOptions = {
25882
26576
  controls: false,
25883
26577
  // Always disable Video.js controls - we use custom controls
@@ -26193,6 +26887,18 @@ var VideoPlayer = React23__default.forwardRef(({
26193
26887
  dispose,
26194
26888
  isReady
26195
26889
  }));
26890
+ const handleClickWithIndicator = useCallback(() => {
26891
+ if (!onClick || !playerRef.current) return;
26892
+ const player = playerRef.current;
26893
+ const willBePlaying = player.paused();
26894
+ setIndicatorIsPlaying(willBePlaying);
26895
+ setShowIndicator(false);
26896
+ setTimeout(() => {
26897
+ indicatorKeyRef.current += 1;
26898
+ setShowIndicator(true);
26899
+ }, 0);
26900
+ onClick();
26901
+ }, [onClick]);
26196
26902
  return /* @__PURE__ */ jsxs("div", { className: `video-player-wrapper ${className}`, style: { position: "relative", width: "100%", height: "100%" }, children: [
26197
26903
  /* @__PURE__ */ jsx(
26198
26904
  "div",
@@ -26202,7 +26908,31 @@ var VideoPlayer = React23__default.forwardRef(({
26202
26908
  "data-vjs-player": true
26203
26909
  }
26204
26910
  ),
26205
- isLoading && !externalLoadingControl && /* @__PURE__ */ jsx("div", { className: "video-player-loading", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) })
26911
+ isLoading && !externalLoadingControl && /* @__PURE__ */ jsx("div", { className: "video-player-loading", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
26912
+ onClick && /* @__PURE__ */ jsx(
26913
+ "div",
26914
+ {
26915
+ onClick: handleClickWithIndicator,
26916
+ style: {
26917
+ position: "absolute",
26918
+ top: 0,
26919
+ left: 0,
26920
+ right: 0,
26921
+ bottom: 0,
26922
+ zIndex: 1,
26923
+ cursor: "pointer"
26924
+ },
26925
+ "aria-label": "Click to play/pause"
26926
+ }
26927
+ ),
26928
+ onClick && /* @__PURE__ */ jsx(
26929
+ PlayPauseIndicator,
26930
+ {
26931
+ show: showIndicator,
26932
+ isPlaying: indicatorIsPlaying
26933
+ },
26934
+ indicatorKeyRef.current
26935
+ )
26206
26936
  ] });
26207
26937
  });
26208
26938
  VideoPlayer.displayName = "VideoPlayer";
@@ -26220,6 +26950,9 @@ var CroppedVideoPlayer = forwardRef(({
26220
26950
  const [isVideoReady, setIsVideoReady] = useState(false);
26221
26951
  const [canvasDimensions, setCanvasDimensions] = useState({ width: 0, height: 0 });
26222
26952
  const [isProcessing, setIsProcessing] = useState(false);
26953
+ const [showIndicator, setShowIndicator] = useState(false);
26954
+ const [indicatorIsPlaying, setIndicatorIsPlaying] = useState(false);
26955
+ const indicatorKeyRef = useRef(0);
26223
26956
  const stopCanvasRendering = useCallback(() => {
26224
26957
  if (animationFrameRef.current) {
26225
26958
  cancelAnimationFrame(animationFrameRef.current);
@@ -26398,14 +27131,26 @@ var CroppedVideoPlayer = forwardRef(({
26398
27131
  };
26399
27132
  }, [stopCanvasRendering]);
26400
27133
  if (!crop) {
26401
- return /* @__PURE__ */ jsx(VideoPlayer, { ref, ...videoProps });
26402
- }
27134
+ return /* @__PURE__ */ jsx(VideoPlayer, { ref, ...videoProps, onClick });
27135
+ }
27136
+ const handleClickWithIndicator = () => {
27137
+ if (!onClick || !hiddenVideoRef.current?.player) return;
27138
+ const player = hiddenVideoRef.current.player;
27139
+ const willBePlaying = player.paused();
27140
+ setIndicatorIsPlaying(willBePlaying);
27141
+ setShowIndicator(false);
27142
+ setTimeout(() => {
27143
+ indicatorKeyRef.current += 1;
27144
+ setShowIndicator(true);
27145
+ }, 0);
27146
+ onClick();
27147
+ };
26403
27148
  return /* @__PURE__ */ jsxs(
26404
27149
  "div",
26405
27150
  {
26406
27151
  ref: videoContainerRef,
26407
27152
  className: `relative w-full h-full flex items-center justify-center bg-black ${onClick ? "cursor-pointer" : ""} ${videoProps.className || ""}`,
26408
- onClick,
27153
+ onClick: handleClickWithIndicator,
26409
27154
  children: [
26410
27155
  /* @__PURE__ */ jsx("div", { className: "hidden", children: /* @__PURE__ */ jsx(
26411
27156
  VideoPlayer,
@@ -26462,7 +27207,15 @@ var CroppedVideoPlayer = forwardRef(({
26462
27207
  "Processing: ",
26463
27208
  isProcessing ? "Yes" : "No"
26464
27209
  ] })
26465
- ] })
27210
+ ] }),
27211
+ onClick && /* @__PURE__ */ jsx(
27212
+ PlayPauseIndicator,
27213
+ {
27214
+ show: showIndicator,
27215
+ isPlaying: indicatorIsPlaying
27216
+ },
27217
+ indicatorKeyRef.current
27218
+ )
26466
27219
  ]
26467
27220
  }
26468
27221
  );
@@ -28117,6 +28870,7 @@ var BottlenecksContent = ({
28117
28870
  const [metadataCache, setMetadataCache] = useState({});
28118
28871
  const [triageClips, setTriageClips] = useState([]);
28119
28872
  const [isLoadingTriageClips, setIsLoadingTriageClips] = useState(false);
28873
+ const [isFullscreen, setIsFullscreen] = useState(false);
28120
28874
  const categoryMetadataRef = useRef([]);
28121
28875
  const currentMetadataIndexRef = useRef(0);
28122
28876
  const {
@@ -29010,6 +29764,24 @@ var BottlenecksContent = ({
29010
29764
  player.pause();
29011
29765
  }
29012
29766
  };
29767
+ const toggleFullscreen = useCallback((e) => {
29768
+ e.stopPropagation();
29769
+ setIsFullscreen((prev) => !prev);
29770
+ }, []);
29771
+ const exitFullscreen = useCallback(() => {
29772
+ setIsFullscreen(false);
29773
+ }, []);
29774
+ useEffect(() => {
29775
+ const handleEscape = (e) => {
29776
+ if (e.key === "Escape" && isFullscreen) {
29777
+ exitFullscreen();
29778
+ }
29779
+ };
29780
+ if (isFullscreen) {
29781
+ window.addEventListener("keydown", handleEscape);
29782
+ return () => window.removeEventListener("keydown", handleEscape);
29783
+ }
29784
+ }, [isFullscreen, exitFullscreen]);
29013
29785
  const getClipTypeLabel = (video) => {
29014
29786
  if (!video) return "";
29015
29787
  const currentFilter = activeFilterRef.current;
@@ -29122,7 +29894,7 @@ var BottlenecksContent = ({
29122
29894
  )
29123
29895
  ] }) })
29124
29896
  ] }) }),
29125
- filteredVideos.length > 0 && currentVideo ? /* @__PURE__ */ jsx("div", { className: `p-4 ${triageMode ? "h-full" : "h-[calc(100%-4rem)]"}`, children: /* @__PURE__ */ jsx("div", { className: "relative h-full group", children: /* @__PURE__ */ jsxs("div", { className: "relative w-full h-full overflow-hidden rounded-md shadow-inner bg-gray-900", children: [
29897
+ filteredVideos.length > 0 && currentVideo && !isFullscreen ? /* @__PURE__ */ jsx("div", { className: `p-4 ${triageMode ? "h-full" : "h-[calc(100%-4rem)]"}`, children: /* @__PURE__ */ jsx("div", { className: "relative h-full group", children: /* @__PURE__ */ jsxs("div", { className: "relative w-full h-full overflow-hidden rounded-md shadow-inner bg-gray-900", children: [
29126
29898
  /* @__PURE__ */ jsx(
29127
29899
  "div",
29128
29900
  {
@@ -29222,22 +29994,24 @@ var BottlenecksContent = ({
29222
29994
  ] }) })
29223
29995
  ),
29224
29996
  /* @__PURE__ */ jsx("div", { className: "absolute bottom-0 left-0 right-0 p-3 bg-gradient-to-t from-black/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 z-10", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-white", children: [
29225
- /* @__PURE__ */ jsx(
29226
- "button",
29227
- {
29228
- onClick: (e) => {
29229
- e.stopPropagation();
29230
- togglePlayback();
29231
- },
29232
- className: "p-1.5 hover:bg-white/20 rounded-full focus:outline-none focus:ring-2 focus:ring-white/50",
29233
- "aria-label": isPlaying ? "Pause" : "Play",
29234
- children: isPlaying ? /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 00-1 1v2a1 1 0 102 0V9a1 1 0 00-1-1zm5 0a1 1 0 00-1 1v2a1 1 0 102 0V9a1 1 0 00-1-1z", clipRule: "evenodd" }) }) : /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8.118l-.001 3.764a1 1 0 001.555.832l3.196-1.882a1 1 0 000-1.664l-3.196-1.882z", clipRule: "evenodd" }) })
29235
- }
29236
- ),
29237
- /* @__PURE__ */ jsxs("span", { className: "text-xs font-mono px-2", children: [
29238
- formatTime2(currentTime),
29239
- " / ",
29240
- formatTime2(duration)
29997
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
29998
+ /* @__PURE__ */ jsx(
29999
+ "button",
30000
+ {
30001
+ onClick: (e) => {
30002
+ e.stopPropagation();
30003
+ togglePlayback();
30004
+ },
30005
+ className: "p-1.5 hover:bg-white/20 rounded-full focus:outline-none focus:ring-2 focus:ring-white/50",
30006
+ "aria-label": isPlaying ? "Pause" : "Play",
30007
+ children: isPlaying ? /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 00-1 1v2a1 1 0 102 0V9a1 1 0 00-1-1zm5 0a1 1 0 00-1 1v2a1 1 0 102 0V9a1 1 0 00-1-1z", clipRule: "evenodd" }) }) : /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8.118l-.001 3.764a1 1 0 001.555.832l3.196-1.882a1 1 0 000-1.664l-3.196-1.882z", clipRule: "evenodd" }) })
30008
+ }
30009
+ ),
30010
+ /* @__PURE__ */ jsxs("span", { className: "text-xs font-mono px-2", children: [
30011
+ formatTime2(currentTime),
30012
+ " / ",
30013
+ formatTime2(duration)
30014
+ ] })
29241
30015
  ] }),
29242
30016
  /* @__PURE__ */ jsx(
29243
30017
  "input",
@@ -29258,6 +30032,16 @@ var BottlenecksContent = ({
29258
30032
  },
29259
30033
  "aria-label": "Seek slider"
29260
30034
  }
30035
+ ),
30036
+ /* @__PURE__ */ jsx(
30037
+ "button",
30038
+ {
30039
+ onClick: toggleFullscreen,
30040
+ className: "p-1.5 hover:bg-white/20 rounded-full focus:outline-none focus:ring-2 focus:ring-white/50",
30041
+ "aria-label": "Fullscreen",
30042
+ title: "Expand to fullscreen",
30043
+ children: /* @__PURE__ */ jsx(Maximize2, { className: "h-5 w-5" })
30044
+ }
29261
30045
  )
29262
30046
  ] }) })
29263
30047
  ] }) }) }) : (
@@ -29394,6 +30178,147 @@ var BottlenecksContent = ({
29394
30178
  )
29395
30179
  ) })
29396
30180
  ] }),
30181
+ isFullscreen && currentVideo && /* @__PURE__ */ jsxs(
30182
+ "div",
30183
+ {
30184
+ className: "fixed inset-0 z-50 bg-black flex items-center justify-center",
30185
+ style: { margin: 0 },
30186
+ children: [
30187
+ /* @__PURE__ */ jsx(
30188
+ "button",
30189
+ {
30190
+ onClick: exitFullscreen,
30191
+ className: "absolute top-4 right-4 z-50 p-2 bg-black/60 hover:bg-black/80 rounded-full text-white transition-colors focus:outline-none focus:ring-2 focus:ring-white/50",
30192
+ "aria-label": "Exit fullscreen",
30193
+ children: /* @__PURE__ */ jsx(X, { className: "h-6 w-6" })
30194
+ }
30195
+ ),
30196
+ (currentVideo.type === "cycle_completion" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "idle_time" || currentVideo.type === "low_value" ? /* @__PURE__ */ jsx("div", { className: "absolute top-4 left-4 z-50 bg-black/60 backdrop-blur-sm px-4 py-2 rounded-lg text-white shadow-lg", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
30197
+ /* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-3 w-3 rounded-full ${currentVideo.type === "low_value" || currentVideo.type === "idle_time" ? "bg-purple-400" : isPercentileCategory(activeFilterRef.current) ? activeFilterRef.current === "fast-cycles" ? "bg-green-600" : activeFilterRef.current === "slow-cycles" ? "bg-red-700" : "bg-orange-500" : currentVideo.type === "cycle_completion" ? "bg-blue-600" : "bg-gray-500"} mr-2 animate-pulse` }),
30198
+ (currentVideo.type === "cycle_completion" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds ? /* @__PURE__ */ jsxs("span", { className: "opacity-90 font-mono bg-black/30 px-2 py-1 rounded", children: [
30199
+ "Cycle time: ",
30200
+ currentVideo.cycle_time_seconds.toFixed(1),
30201
+ "s"
30202
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
30203
+ /* @__PURE__ */ jsx("span", { className: "font-medium mr-2", children: getClipTypeLabel(currentVideo) }),
30204
+ /* @__PURE__ */ jsx("span", { className: "opacity-80", children: currentVideo.description })
30205
+ ] })
30206
+ ] }) }) : /* @__PURE__ */ jsx("div", { className: "absolute top-4 right-20 z-50 bg-black/60 backdrop-blur-sm px-4 py-2 rounded-lg text-white shadow-lg", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
30207
+ /* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-3 w-3 rounded-full ${getSeverityColor(currentVideo.severity)} mr-2 animate-pulse` }),
30208
+ /* @__PURE__ */ jsx("span", { className: "font-medium mr-2", children: getClipTypeLabel(currentVideo) }),
30209
+ /* @__PURE__ */ jsx("span", { className: "opacity-80", children: currentVideo.description })
30210
+ ] }) }),
30211
+ /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center p-8", children: /* @__PURE__ */ jsxs("div", { className: "relative w-full h-full max-w-7xl group", children: [
30212
+ /* @__PURE__ */ jsx(
30213
+ "div",
30214
+ {
30215
+ className: "w-full h-full",
30216
+ style: {
30217
+ opacity: isTransitioning ? 0 : 1,
30218
+ transition: "opacity 0.1s ease-in-out"
30219
+ },
30220
+ children: /* @__PURE__ */ jsx(
30221
+ CroppedVideoPlayer,
30222
+ {
30223
+ ref: videoRef,
30224
+ src: currentVideo.src,
30225
+ poster: "",
30226
+ className: "w-full h-full",
30227
+ crop: workspaceCrop?.crop,
30228
+ onClick: togglePlayback,
30229
+ autoplay: true,
30230
+ playsInline: true,
30231
+ loop: false,
30232
+ externalLoadingControl: true,
30233
+ onReady: handleVideoReady,
30234
+ onPlay: handleVideoPlay,
30235
+ onPause: handleVideoPause,
30236
+ onTimeUpdate: handleTimeUpdate,
30237
+ onDurationChange: handleDurationChange,
30238
+ onEnded: handleVideoEnded,
30239
+ onError: handleVideoError,
30240
+ onLoadedData: handleLoadedData,
30241
+ onPlaying: handleVideoPlaying,
30242
+ onLoadingChange: handleVideoLoadingChange,
30243
+ options: {
30244
+ fluid: false,
30245
+ responsive: false,
30246
+ fill: false
30247
+ }
30248
+ }
30249
+ )
30250
+ }
30251
+ ),
30252
+ (isTransitioning || isVideoBuffering && isInitialLoading) && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
30253
+ !isTransitioning && isVideoBuffering && !isInitialLoading && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
30254
+ /* @__PURE__ */ jsx("div", { className: "absolute bottom-0 left-0 right-0 p-4 bg-gradient-to-t from-black/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 z-10", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-white", children: [
30255
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
30256
+ /* @__PURE__ */ jsx(
30257
+ "button",
30258
+ {
30259
+ onClick: (e) => {
30260
+ e.stopPropagation();
30261
+ togglePlayback();
30262
+ },
30263
+ className: "p-2 hover:bg-white/20 rounded-full focus:outline-none focus:ring-2 focus:ring-white/50",
30264
+ "aria-label": isPlaying ? "Pause" : "Play",
30265
+ children: isPlaying ? /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-6 w-6", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 00-1 1v2a1 1 0 102 0V9a1 1 0 00-1-1zm5 0a1 1 0 00-1 1v2a1 1 0 102 0V9a1 1 0 00-1-1z", clipRule: "evenodd" }) }) : /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-6 w-6", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8.118l-.001 3.764a1 1 0 001.555.832l3.196-1.882a1 1 0 000-1.664l-3.196-1.882z", clipRule: "evenodd" }) })
30266
+ }
30267
+ ),
30268
+ /* @__PURE__ */ jsxs("span", { className: "text-sm font-mono px-2", children: [
30269
+ formatTime2(currentTime),
30270
+ " / ",
30271
+ formatTime2(duration)
30272
+ ] })
30273
+ ] }),
30274
+ /* @__PURE__ */ jsx(
30275
+ "input",
30276
+ {
30277
+ type: "range",
30278
+ min: "0",
30279
+ max: duration || 0,
30280
+ value: currentTime,
30281
+ onChange: (e) => {
30282
+ if (videoRef.current) {
30283
+ videoRef.current.currentTime(Number(e.target.value));
30284
+ }
30285
+ },
30286
+ className: "flex-grow mx-4 h-2.5 bg-white/30 rounded-full appearance-none cursor-pointer focus:outline-none focus:ring-2 focus:ring-white/50 touch-manipulation",
30287
+ style: {
30288
+ WebkitAppearance: "none",
30289
+ appearance: "none"
30290
+ },
30291
+ "aria-label": "Seek slider"
30292
+ }
30293
+ ),
30294
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
30295
+ /* @__PURE__ */ jsx(
30296
+ "button",
30297
+ {
30298
+ onClick: handlePrevious,
30299
+ disabled: currentMetadataIndex <= 0,
30300
+ className: `p-2 rounded-full transition-colors ${currentMetadataIndex <= 0 ? "text-gray-500 cursor-not-allowed" : "text-white hover:bg-white/20"}`,
30301
+ "aria-label": "Previous clip",
30302
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-5 w-5" })
30303
+ }
30304
+ ),
30305
+ /* @__PURE__ */ jsx("span", { className: "text-sm px-3 py-1 bg-blue-600 text-white rounded-full font-medium tabular-nums", children: categoryMetadata.length > 0 ? `${currentMetadataIndex + 1} / ${categoryMetadata.length}` : "0 / 0" }),
30306
+ /* @__PURE__ */ jsx(
30307
+ "button",
30308
+ {
30309
+ onClick: handleNext,
30310
+ disabled: currentMetadataIndex >= categoryMetadata.length - 1,
30311
+ className: `p-2 rounded-full transition-colors ${currentMetadataIndex >= categoryMetadata.length - 1 ? "text-gray-500 cursor-not-allowed" : "text-white hover:bg-white/20"}`,
30312
+ "aria-label": "Next clip",
30313
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-5 w-5" })
30314
+ }
30315
+ )
30316
+ ] })
30317
+ ] }) })
30318
+ ] }) })
30319
+ ]
30320
+ }
30321
+ ),
29397
30322
  !triageMode && /* @__PURE__ */ jsx(
29398
30323
  AdvancedFilterDialog,
29399
30324
  {
@@ -33230,14 +34155,16 @@ var WorkspaceWhatsAppShareButton = ({
33230
34155
  };
33231
34156
  var WorkspacePdfGenerator = ({ workspace, className }) => {
33232
34157
  const [isGenerating, setIsGenerating] = useState(false);
34158
+ const entityConfig = useEntityConfig();
33233
34159
  const generatePDF = async () => {
33234
34160
  setIsGenerating(true);
33235
34161
  try {
34162
+ const lineName = workspace.line_name || getLineDisplayName(entityConfig, workspace.line_id);
33236
34163
  trackCoreEvent("Workspace PDF Export Clicked", {
33237
34164
  workspace_id: workspace.workspace_id,
33238
34165
  line_id: workspace.line_id,
33239
34166
  workspace_name: workspace.workspace_name,
33240
- line_name: workspace.line_name
34167
+ line_name: lineName
33241
34168
  });
33242
34169
  const doc = new jsPDF$1();
33243
34170
  doc.setFontSize(14);
@@ -33258,7 +34185,7 @@ var WorkspacePdfGenerator = ({ workspace, className }) => {
33258
34185
  doc.setFontSize(32);
33259
34186
  doc.setFont("helvetica", "bold");
33260
34187
  doc.setTextColor(0, 0, 0);
33261
- doc.text("Line 1", 20, 40);
34188
+ doc.text(lineName, 20, 40);
33262
34189
  doc.setFontSize(22);
33263
34190
  doc.setFont("helvetica", "normal");
33264
34191
  doc.setTextColor(40, 40, 40);
@@ -35731,20 +36658,7 @@ var SideNavBar = memo(({
35731
36658
  onClick: handleLogoClick,
35732
36659
  className: "mx-auto flex items-center justify-center w-full hover:opacity-80 transition-opacity focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 rounded-lg",
35733
36660
  "aria-label": "Go to home page",
35734
- children: /* @__PURE__ */ jsx(
35735
- "img",
35736
- {
35737
- src: "/optifye-logo.png",
35738
- alt: "Optifye",
35739
- className: "w-12 h-12 object-contain cursor-pointer",
35740
- onError: (e) => {
35741
- e.currentTarget.style.display = "none";
35742
- if (e.currentTarget.parentElement) {
35743
- e.currentTarget.parentElement.innerHTML = '<span class="text-blue-600 font-bold text-lg cursor-pointer">OP</span>';
35744
- }
35745
- }
35746
- }
35747
- )
36661
+ children: /* @__PURE__ */ jsx(Logo, { className: "w-12 h-12 object-contain cursor-pointer" })
35748
36662
  }
35749
36663
  ) }),
35750
36664
  /* @__PURE__ */ jsxs("div", { className: "flex-1 w-full py-6 px-4 overflow-y-auto", children: [
@@ -36122,20 +37036,7 @@ var SideNavBar = memo(({
36122
37036
  ),
36123
37037
  /* @__PURE__ */ jsxs("aside", { className: `md:hidden fixed inset-y-0 left-0 w-72 xs:w-80 bg-white shadow-2xl flex flex-col z-50 transform transition-transform duration-300 ease-in-out ${isMobileMenuOpen ? "translate-x-0" : "-translate-x-full"}`, children: [
36124
37038
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-4 border-b border-gray-200 bg-gradient-to-r from-blue-50 to-white", children: [
36125
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(
36126
- "img",
36127
- {
36128
- src: "/optifye-logo.png",
36129
- alt: "Optifye",
36130
- className: "w-11 h-11 object-contain",
36131
- onError: (e) => {
36132
- e.currentTarget.style.display = "none";
36133
- if (e.currentTarget.parentElement) {
36134
- e.currentTarget.parentElement.innerHTML = '<span class="text-blue-600 font-bold text-xl">Optifye</span>';
36135
- }
36136
- }
36137
- }
36138
- ) }),
37039
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(Logo, { className: "w-11 h-11 object-contain" }) }),
36139
37040
  /* @__PURE__ */ jsx(
36140
37041
  "button",
36141
37042
  {
@@ -36244,20 +37145,7 @@ var MainLayout = ({
36244
37145
  return /* @__PURE__ */ jsxs("div", { className: `min-h-screen ${className}`, children: [
36245
37146
  /* @__PURE__ */ jsx("header", { className: "md:hidden bg-white border-b border-gray-200 shadow-sm px-5 py-3.5 flex items-center justify-between sticky top-0 z-40", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
36246
37147
  /* @__PURE__ */ jsx(HamburgerButton, { onClick: handleMobileMenuOpen }),
36247
- /* @__PURE__ */ jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsx(
36248
- "img",
36249
- {
36250
- src: "/optifye-logo.png",
36251
- alt: "Optifye",
36252
- className: "h-9 w-9 object-contain",
36253
- onError: (e) => {
36254
- e.currentTarget.style.display = "none";
36255
- if (e.currentTarget.parentElement) {
36256
- e.currentTarget.parentElement.innerHTML = '<span class="text-blue-600 font-bold text-lg">Optifye</span>';
36257
- }
36258
- }
36259
- }
36260
- ) })
37148
+ /* @__PURE__ */ jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsx(Logo, { className: "h-9 w-9 object-contain" }) })
36261
37149
  ] }) }),
36262
37150
  /* @__PURE__ */ jsx(
36263
37151
  SideNavBar,
@@ -37867,23 +38755,29 @@ var ThreadSidebar = ({
37867
38755
  ] }) })
37868
38756
  ] });
37869
38757
  };
37870
- var axelProfilePng = "/axel-profile.png";
37871
- var ProfilePicture = React23__default.memo(({ alt = "Axel", className = "w-8 h-8 sm:w-10 sm:h-10 md:w-12 md:h-12" }) => {
37872
- return /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx("div", { className: `${className} rounded-xl overflow-hidden shadow-sm`, children: /* @__PURE__ */ jsx(
37873
- "img",
37874
- {
37875
- src: axelProfilePng,
37876
- alt,
37877
- className: "w-full h-full object-cover",
37878
- loading: "eager",
37879
- decoding: "async"
37880
- }
37881
- ) }) });
38758
+ var ProfilePicture = React23__default.memo(({
38759
+ alt = "Axel",
38760
+ className = "",
38761
+ size = "md",
38762
+ animate = false
38763
+ }) => {
38764
+ return /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx(AxelOrb, { size, animate }) });
37882
38765
  });
37883
38766
  ProfilePicture.displayName = "ProfilePicture";
37884
- var preloadImage = (src) => {
37885
- const img = new Image();
37886
- img.src = src;
38767
+ var GREETING_MESSAGES = [
38768
+ "How can I help you today?",
38769
+ "What would you like to know?",
38770
+ "Ready to optimize your operations?",
38771
+ "How can I assist you today?"
38772
+ ];
38773
+ var getDailyGreeting = () => {
38774
+ const now2 = /* @__PURE__ */ new Date();
38775
+ const startOfYear = new Date(now2.getFullYear(), 0, 0);
38776
+ const diff = now2.getTime() - startOfYear.getTime();
38777
+ const oneDay = 1e3 * 60 * 60 * 24;
38778
+ const dayOfYear = Math.floor(diff / oneDay);
38779
+ const index = dayOfYear % GREETING_MESSAGES.length;
38780
+ return GREETING_MESSAGES[index];
37887
38781
  };
37888
38782
  var AIAgentView = () => {
37889
38783
  const { navigate, pathname } = useNavigation();
@@ -37910,6 +38804,7 @@ var AIAgentView = () => {
37910
38804
  const [lastTypingTime, setLastTypingTime] = useState(null);
37911
38805
  const [characterCount, setCharacterCount] = useState(0);
37912
38806
  const typingTimeoutRef = useRef(null);
38807
+ const currentGreeting = useMemo(() => getDailyGreeting(), [greetingReset]);
37913
38808
  const isThreadLoading = (threadId) => {
37914
38809
  return threadId ? loadingThreads.has(threadId) : false;
37915
38810
  };
@@ -37990,7 +38885,7 @@ var AIAgentView = () => {
37990
38885
  const renderedContentCache = useRef(/* @__PURE__ */ new Map());
37991
38886
  const { createThread, mutate: mutateThreads } = useThreads();
37992
38887
  const { messages, addMessage, setMessages } = useMessages(activeThreadId);
37993
- const agnoApiUrl = config.endpoints?.agnoApiUrl || "https://optifye-agent-production.up.railway.app";
38888
+ const agnoApiUrl = config.endpoints?.agnoApiUrl || "https://fastapi-production-111f9.up.railway.app";
37994
38889
  const sseClient = useMemo(() => {
37995
38890
  console.log("[AIAgentView] Using AGNO API URL:", agnoApiUrl);
37996
38891
  return new SSEChatClient(agnoApiUrl);
@@ -38063,12 +38958,11 @@ var AIAgentView = () => {
38063
38958
  }, [activeThreadId]);
38064
38959
  useEffect(() => {
38065
38960
  if (messages.length === 0 && !isTransitioning) {
38066
- const fullText = "Hi, I'm Axel - Your AI Supervisor";
38067
38961
  let index = 0;
38068
38962
  setTypedText("");
38069
38963
  const typeInterval = setInterval(() => {
38070
- if (index < fullText.length) {
38071
- setTypedText(fullText.substring(0, index + 1));
38964
+ if (index < currentGreeting.length) {
38965
+ setTypedText(currentGreeting.substring(0, index + 1));
38072
38966
  index++;
38073
38967
  } else {
38074
38968
  clearInterval(typeInterval);
@@ -38076,7 +38970,7 @@ var AIAgentView = () => {
38076
38970
  }, 50);
38077
38971
  return () => clearInterval(typeInterval);
38078
38972
  }
38079
- }, [messages.length, isTransitioning, greetingReset]);
38973
+ }, [messages.length, isTransitioning, greetingReset, currentGreeting]);
38080
38974
  useEffect(() => {
38081
38975
  if (isSidebarOpen) {
38082
38976
  setNewChatCount(0);
@@ -38102,9 +38996,6 @@ var AIAgentView = () => {
38102
38996
  localStorage.removeItem(ACTIVE_THREAD_STORAGE_KEY);
38103
38997
  textareaRef.current?.focus();
38104
38998
  };
38105
- useEffect(() => {
38106
- preloadImage(axelProfilePng);
38107
- }, []);
38108
38999
  useEffect(() => {
38109
39000
  return () => {
38110
39001
  if (typingTimeoutRef.current) {
@@ -39579,10 +40470,10 @@ var AIAgentView = () => {
39579
40470
  /* Centered welcome and input for new chat */
39580
40471
  /* @__PURE__ */ jsxs("div", { className: "w-full max-w-3xl mx-auto px-3 sm:px-4 md:px-6 flex flex-col items-center justify-center space-y-8 sm:space-y-12 -mt-8 sm:-mt-16", children: [
39581
40472
  /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
39582
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center mb-4 sm:mb-6 md:mb-8", children: /* @__PURE__ */ jsx(ProfilePicture, { alt: "Axel - AI Manufacturing Expert", className: "w-16 h-16 sm:w-20 sm:h-20 md:w-24 md:h-24" }) }),
40473
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center mb-4 sm:mb-6 md:mb-8", children: /* @__PURE__ */ jsx(ProfilePicture, { alt: "Axel - AI Manufacturing Expert", size: "2xl", animate: true }) }),
39583
40474
  /* @__PURE__ */ jsxs("h2", { className: "text-lg sm:text-xl md:text-2xl lg:text-3xl font-semibold text-gray-900 px-2 sm:px-4", children: [
39584
40475
  typedText,
39585
- typedText.length < "Hi, I'm Axel - Your AI Supervisor".length && /* @__PURE__ */ jsx("span", { className: "animate-pulse", children: "|" })
40476
+ typedText.length < currentGreeting.length && /* @__PURE__ */ jsx("span", { className: "animate-pulse", children: "|" })
39586
40477
  ] })
39587
40478
  ] }),
39588
40479
  /* @__PURE__ */ jsx("div", { className: "w-full max-w-2xl", children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
@@ -42949,7 +43840,7 @@ LeaderboardDetailView.displayName = "LeaderboardDetailView";
42949
43840
  var LeaderboardDetailViewWithDisplayNames = withAllWorkspaceDisplayNames(LeaderboardDetailView);
42950
43841
  var LeaderboardDetailView_default = LeaderboardDetailViewWithDisplayNames;
42951
43842
  function LoginView({
42952
- logoSrc = "/optifye-logo.png",
43843
+ logoSrc = optifye_logo_default,
42953
43844
  logoAlt = "Optifye",
42954
43845
  brandName = "Optifye",
42955
43846
  onRateLimitCheck
@@ -46029,6 +46920,26 @@ var getInitialTab = (sourceType, defaultTab, fromMonthly, urlDate) => {
46029
46920
  }
46030
46921
  return "overview";
46031
46922
  };
46923
+ var WorkspaceHealthStatusBadge = ({
46924
+ workspaceId,
46925
+ mode = "full",
46926
+ className = "",
46927
+ showHealthDot = false
46928
+ }) => {
46929
+ const { timeSinceUpdate, isHealthy, loading, error } = useWorkspaceHealthStatus(workspaceId);
46930
+ if (loading || error) {
46931
+ return null;
46932
+ }
46933
+ return /* @__PURE__ */ jsxs("div", { className: `flex items-center gap-2 ${className}`, children: [
46934
+ showHealthDot && /* @__PURE__ */ jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsx(
46935
+ "div",
46936
+ {
46937
+ className: `h-2 w-2 rounded-full ${isHealthy ? "bg-green-500 animate-pulse" : "bg-red-500"}`
46938
+ }
46939
+ ) }),
46940
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-500", children: mode === "full" ? `Last updated: ${timeSinceUpdate}` : timeSinceUpdate })
46941
+ ] });
46942
+ };
46032
46943
  var WorkspaceDetailView = ({
46033
46944
  workspaceId,
46034
46945
  date,
@@ -46080,6 +46991,7 @@ var WorkspaceDetailView = ({
46080
46991
  const [showIdleTime, setShowIdleTime] = useState(false);
46081
46992
  const dashboardConfig = useDashboardConfig();
46082
46993
  const isClipsEnabled = dashboardConfig?.clipsConfig?.enabled ?? true;
46994
+ dashboardConfig?.supervisorConfig?.enabled || false;
46083
46995
  const {
46084
46996
  workspace: workspaceHealth,
46085
46997
  loading: healthLoading,
@@ -46088,6 +47000,36 @@ var WorkspaceDetailView = ({
46088
47000
  enableRealtime: true,
46089
47001
  refreshInterval: 3e4
46090
47002
  });
47003
+ const {
47004
+ isHealthy: isWorkspaceHealthy,
47005
+ timeSinceUpdate,
47006
+ lastHeartbeat,
47007
+ loading: healthStatusLoading,
47008
+ error: healthStatusError
47009
+ } = useWorkspaceHealthStatus(workspaceId);
47010
+ const isLive = useMemo(() => {
47011
+ if (!lastHeartbeat) return false;
47012
+ const now2 = /* @__PURE__ */ new Date();
47013
+ const heartbeat = new Date(lastHeartbeat);
47014
+ const minutesSince = (now2.getTime() - heartbeat.getTime()) / 6e4;
47015
+ return minutesSince < 5;
47016
+ }, [lastHeartbeat]);
47017
+ useEffect(() => {
47018
+ console.log("[WorkspaceDetailView] Workspace Health Status:", {
47019
+ workspaceId,
47020
+ // Old workspace_health table
47021
+ oldStatus: workspaceHealth?.status,
47022
+ oldLastHeartbeat: workspaceHealth?.last_heartbeat,
47023
+ oldTimeSinceLastUpdate: workspaceHealth?.timeSinceLastUpdate,
47024
+ // New workspace_health_status table
47025
+ isHealthy: isWorkspaceHealthy,
47026
+ isLive,
47027
+ lastHeartbeat,
47028
+ timeSinceUpdate,
47029
+ loading: healthLoading || healthStatusLoading,
47030
+ error: healthError || healthStatusError
47031
+ });
47032
+ }, [workspaceId, workspaceHealth, isWorkspaceHealthy, isLive, lastHeartbeat, timeSinceUpdate, healthLoading, healthStatusLoading, healthError, healthStatusError]);
46091
47033
  const {
46092
47034
  status: prefetchStatus,
46093
47035
  data: prefetchData,
@@ -46124,82 +47066,7 @@ var WorkspaceDetailView = ({
46124
47066
  const workspace = isHistoricView ? historicMetrics : liveMetrics;
46125
47067
  const loading = isHistoricView ? historicLoading : liveLoading;
46126
47068
  const error = isHistoricView ? historicError : liveError;
46127
- const audioService = useAudioService();
46128
- const { latestAchievement, hasNewAchievements } = useHourlyTargetAchievements({
46129
- hourlyData: workspace?.hourly_action_counts || [],
46130
- targetThreshold: workspace?.pph_threshold || 0,
46131
- shiftStart: workspace?.shift_start || "06:00",
46132
- enabled: !isHistoricView && Boolean(workspace)
46133
- // Only for live data
46134
- });
46135
- const { latestMiss, hasNewMiss } = useHourlyTargetMisses({
46136
- hourlyData: workspace?.hourly_action_counts || [],
46137
- targetThreshold: workspace?.pph_threshold || 0,
46138
- shiftStart: workspace?.shift_start || "06:00",
46139
- enabled: !isHistoricView && Boolean(workspace)
46140
- // Only for live data
46141
- });
46142
- const [showCongratulations, setShowCongratulations] = useState(false);
46143
- const [currentAchievement, setCurrentAchievement] = useState(null);
46144
- const [showEncouragement, setShowEncouragement] = useState(false);
46145
- const [currentMiss, setCurrentMiss] = useState(null);
46146
- const [audioReady, setAudioReady] = useState(false);
46147
- useEffect(() => {
46148
- if (hasNewAchievements && latestAchievement && !isHistoricView) {
46149
- console.log("[\u{1F389} ACHIEVEMENT UNLOCKED! \u{1F389}] Target reached!", latestAchievement);
46150
- const startCelebration = async () => {
46151
- setCurrentAchievement(latestAchievement);
46152
- setShowCongratulations(true);
46153
- setTimeout(async () => {
46154
- try {
46155
- console.log("[\u{1F3B5} CELEBRATION FANFARE] Playing victory audio...");
46156
- await audioService.playCongratsSound();
46157
- console.log("[\u2705 AUDIO SUCCESS] Celebration fanfare completed!");
46158
- } catch (err) {
46159
- console.warn("[\u274C AUDIO ERROR] Failed to play congratulations sound:", err);
46160
- }
46161
- }, 300);
46162
- console.log(`[\u{1F4CA} ACHIEVEMENT ANALYTICS] Worker hit target: ${latestAchievement.currentValue}/${latestAchievement.targetValue} during ${latestAchievement.timeRange}`);
46163
- };
46164
- startCelebration();
46165
- }
46166
- }, [hasNewAchievements, latestAchievement, isHistoricView, audioService]);
46167
- useEffect(() => {
46168
- if (hasNewMiss && latestMiss && !isHistoricView) {
46169
- console.log("[\u{1F499} ENCOURAGEMENT NEEDED] Target not reached, showing support", latestMiss);
46170
- const startEncouragement = async () => {
46171
- setCurrentMiss(latestMiss);
46172
- setShowEncouragement(true);
46173
- setTimeout(async () => {
46174
- try {
46175
- console.log("[\u{1F3B5} GENTLE ENCOURAGEMENT] Playing supportive audio...");
46176
- await audioService.playEncouragementSound();
46177
- console.log("[\u2705 AUDIO SUCCESS] Encouragement audio completed!");
46178
- } catch (err) {
46179
- console.warn("[\u274C AUDIO ERROR] Failed to play encouragement sound:", err);
46180
- }
46181
- }, 300);
46182
- console.log(`[\u{1F4CA} ENCOURAGEMENT ANALYTICS] Target missed: ${latestMiss.actualValue}/${latestMiss.targetValue} (${Math.round(latestMiss.actualValue / latestMiss.targetValue * 100)}% achieved)`);
46183
- };
46184
- startEncouragement();
46185
- }
46186
- }, [hasNewMiss, latestMiss, isHistoricView, audioService]);
46187
- useEffect(() => {
46188
- const handleUserInteraction = () => {
46189
- console.log("[\u{1F50A} AUDIO ENABLED] User interaction detected - celebration sounds ready!");
46190
- audioService.markUserInteraction();
46191
- setAudioReady(true);
46192
- };
46193
- console.log("[\u{1F3A7} AUDIO SETUP] Setting up celebration audio listeners...");
46194
- document.addEventListener("click", handleUserInteraction);
46195
- document.addEventListener("touchstart", handleUserInteraction);
46196
- document.addEventListener("keydown", handleUserInteraction);
46197
- return () => {
46198
- document.removeEventListener("click", handleUserInteraction);
46199
- document.removeEventListener("touchstart", handleUserInteraction);
46200
- document.removeEventListener("keydown", handleUserInteraction);
46201
- };
46202
- }, [audioService]);
47069
+ const { supervisorName } = useLineSupervisor(workspace?.line_id || lineId);
46203
47070
  useEffect(() => {
46204
47071
  if (onTabChange) {
46205
47072
  onTabChange(activeTab);
@@ -46415,113 +47282,157 @@ var WorkspaceDetailView = ({
46415
47282
  )
46416
47283
  ] });
46417
47284
  }
46418
- return /* @__PURE__ */ jsxs(
47285
+ return /* @__PURE__ */ jsx(
46419
47286
  motion.div,
46420
47287
  {
46421
47288
  className: `min-h-screen bg-slate-50 ${className}`,
46422
47289
  initial: { opacity: 1 },
46423
47290
  animate: { opacity: 1 },
46424
- children: [
46425
- /* @__PURE__ */ jsxs("div", { className: "min-h-screen w-full flex flex-col bg-slate-50", children: [
46426
- /* @__PURE__ */ jsxs("header", { className: "sticky top-0 z-10 px-3 sm:px-4 md:px-5 lg:px-6 py-2 sm:py-2.5 lg:py-3 flex flex-col shadow-sm bg-white", children: [
46427
- /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
47291
+ children: /* @__PURE__ */ jsxs("div", { className: "min-h-screen w-full flex flex-col bg-slate-50", children: [
47292
+ /* @__PURE__ */ jsxs("header", { className: "sticky top-0 z-10 px-3 sm:px-4 md:px-5 lg:px-6 py-3 sm:py-3 lg:py-3.5 flex flex-col shadow-sm bg-white", children: [
47293
+ /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
47294
+ /* @__PURE__ */ jsx(
47295
+ "button",
47296
+ {
47297
+ onClick: handleBackNavigation,
47298
+ className: "p-2 -ml-2 rounded-full active:bg-gray-100 transition-colors",
47299
+ "aria-label": "Navigate back",
47300
+ children: /* @__PURE__ */ jsx(ArrowLeft, { className: "w-5 h-5 text-gray-700" })
47301
+ }
47302
+ ),
47303
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col items-center justify-center", children: [
47304
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
47305
+ /* @__PURE__ */ jsx("h1", { className: "text-base font-semibold text-gray-900 truncate max-w-[220px]", children: formattedWorkspaceName }),
47306
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsxs("div", { className: "relative flex h-2 w-2", children: [
47307
+ isLive && /* @__PURE__ */ jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" }),
47308
+ /* @__PURE__ */ jsx("span", { className: clsx(
47309
+ "relative inline-flex rounded-full h-2 w-2",
47310
+ isLive ? "bg-green-500" : "bg-red-500"
47311
+ ) })
47312
+ ] }) })
47313
+ ] }),
47314
+ activeTab !== "monthly_history" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-0.5 mt-1", children: [
47315
+ workspaceHealth && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-500", children: workspaceHealth.timeSinceLastUpdate }),
47316
+ /* @__PURE__ */ jsx(
47317
+ WorkspaceHealthStatusBadge,
47318
+ {
47319
+ workspaceId,
47320
+ mode: "compact",
47321
+ showHealthDot: false,
47322
+ className: "text-[10px]"
47323
+ }
47324
+ )
47325
+ ] })
47326
+ ] }),
47327
+ /* @__PURE__ */ jsx("div", { className: "w-9" })
47328
+ ] }) }),
47329
+ /* @__PURE__ */ jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsxs("div", { className: "relative flex items-center", children: [
47330
+ /* @__PURE__ */ jsx("div", { className: "absolute left-0 z-10", children: /* @__PURE__ */ jsx(
47331
+ BackButtonMinimal,
47332
+ {
47333
+ onClick: handleBackNavigation,
47334
+ text: previousView === "line_monthly_history" ? "Back to Line History" : returnUrl && returnUrl.includes("monthly_history") ? "Back to Line History" : returnUrl && returnUrl.includes("/kpis/") ? "Back to KPIs" : returnUrl && returnUrl.includes("/leaderboard/") ? "Back to Leaderboard" : (date || shift) && activeTab !== "monthly_history" ? "Back to Monthly History" : "Back",
47335
+ size: "default",
47336
+ "aria-label": "Navigate back to previous page"
47337
+ }
47338
+ ) }),
47339
+ /* @__PURE__ */ jsx("div", { className: "absolute left-1/2 transform -translate-x-1/2 max-w-[calc(100%-200px)]", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
47340
+ /* @__PURE__ */ jsx("h1", { className: "text-lg md:text-xl lg:text-2xl xl:text-3xl font-semibold text-gray-900 truncate", children: formattedWorkspaceName }),
47341
+ /* @__PURE__ */ jsxs("div", { className: "relative flex h-2.5 w-2.5", children: [
47342
+ isLive && /* @__PURE__ */ jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" }),
47343
+ /* @__PURE__ */ jsx("span", { className: clsx(
47344
+ "relative inline-flex rounded-full h-2.5 w-2.5",
47345
+ isLive ? "bg-green-500" : "bg-red-500"
47346
+ ) })
47347
+ ] })
47348
+ ] }) }),
47349
+ activeTab !== "monthly_history" && /* @__PURE__ */ jsxs("div", { className: "absolute right-0 top-0 flex flex-col items-end gap-1", children: [
47350
+ workspaceHealth && /* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-500", children: [
47351
+ "Last update: ",
47352
+ workspaceHealth.timeSinceLastUpdate
47353
+ ] }),
46428
47354
  /* @__PURE__ */ jsx(
46429
- "button",
47355
+ WorkspaceHealthStatusBadge,
46430
47356
  {
46431
- onClick: handleBackNavigation,
46432
- className: "p-2 -ml-2 rounded-full active:bg-gray-100 transition-colors",
46433
- "aria-label": "Navigate back",
46434
- children: /* @__PURE__ */ jsx(ArrowLeft, { className: "w-5 h-5 text-gray-700" })
47357
+ workspaceId,
47358
+ mode: "full",
47359
+ showHealthDot: false
46435
47360
  }
46436
- ),
46437
- /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col items-center justify-center", children: [
46438
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
46439
- /* @__PURE__ */ jsx("h1", { className: "text-base font-semibold text-gray-900 truncate max-w-[220px]", children: formattedWorkspaceName }),
46440
- workspaceHealth && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsxs("div", { className: "relative flex h-2 w-2", children: [
46441
- workspaceHealth.status === "healthy" && /* @__PURE__ */ jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" }),
46442
- /* @__PURE__ */ jsx("span", { className: clsx(
46443
- "relative inline-flex rounded-full h-2 w-2",
46444
- workspaceHealth.status === "healthy" ? "bg-green-500" : "bg-red-500"
46445
- ) })
46446
- ] }) })
47361
+ )
47362
+ ] }),
47363
+ /* @__PURE__ */ jsx("div", { className: "w-full h-8" })
47364
+ ] }) }),
47365
+ activeTab !== "monthly_history" && /* @__PURE__ */ jsxs(Fragment, { children: [
47366
+ /* @__PURE__ */ jsxs("div", { className: "sm:hidden mt-3 flex items-center justify-center gap-2", children: [
47367
+ /* @__PURE__ */ jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-gray-100 rounded-full", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-700", children: formatISTDate2(new Date(workspace.date)) }) }),
47368
+ /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-1 px-2.5 py-1 bg-gray-100 rounded-full", children: [
47369
+ /* @__PURE__ */ jsx("div", { className: "text-gray-700 scale-90", children: getShiftIcon(workspace.shift_type) }),
47370
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-700", children: workspace.shift_type })
47371
+ ] }),
47372
+ !date && !shift && !usingFallbackData ? /* @__PURE__ */ jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-green-100 rounded-full", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-green-700", children: /* @__PURE__ */ jsx(LiveTimer, {}) }) }) : date ? /* @__PURE__ */ jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-blue-100 rounded-full", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-blue-700", children: getDaysDifference(workspace.date, timezone, dashboardConfig?.shiftConfig?.dayShift?.startTime || "06:00") }) }) : usingFallbackData ? /* @__PURE__ */ jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-amber-100 rounded-full", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-amber-700", children: getDaysDifference(workspace.date, timezone, dashboardConfig?.shiftConfig?.dayShift?.startTime || "06:00") }) }) : null
47373
+ ] }),
47374
+ /* @__PURE__ */ jsx("div", { className: "hidden sm:block mt-3 bg-blue-50 px-3 py-2 rounded-lg", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-3 md:gap-4", children: [
47375
+ !date && !shift && !usingFallbackData && /* @__PURE__ */ jsxs(Fragment, { children: [
47376
+ /* @__PURE__ */ jsx("div", { className: "text-base md:text-lg font-medium text-blue-600", children: /* @__PURE__ */ jsx(LiveTimer, {}) }),
47377
+ /* @__PURE__ */ jsx("div", { className: "w-px h-4 bg-blue-300" })
47378
+ ] }),
47379
+ /* @__PURE__ */ jsx("span", { className: "text-sm md:text-base font-medium text-blue-600", children: formatISTDate2(new Date(workspace.date)) }),
47380
+ /* @__PURE__ */ jsx("div", { className: "w-px h-4 bg-blue-300" }),
47381
+ date && /* @__PURE__ */ jsxs(Fragment, { children: [
47382
+ /* @__PURE__ */ jsx("span", { className: "px-2 py-1 text-xs font-medium bg-blue-200 text-blue-800 rounded-md", children: getDaysDifference(workspace.date, timezone, dashboardConfig?.shiftConfig?.dayShift?.startTime || "06:00") }),
47383
+ /* @__PURE__ */ jsx("div", { className: "w-px h-4 bg-blue-300" })
47384
+ ] }),
47385
+ !date && !shift && usingFallbackData && /* @__PURE__ */ jsxs(Fragment, { children: [
47386
+ /* @__PURE__ */ jsxs("span", { className: "px-2 py-1 text-xs font-medium bg-amber-100 text-amber-700 rounded-md", children: [
47387
+ "Latest available data (",
47388
+ getDaysDifference(workspace.date, timezone, dashboardConfig?.shiftConfig?.dayShift?.startTime || "06:00"),
47389
+ ")"
46447
47390
  ] }),
46448
- workspaceHealth && activeTab !== "monthly_history" && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-500 mt-0.5", children: workspaceHealth.timeSinceLastUpdate })
47391
+ /* @__PURE__ */ jsx("div", { className: "w-px h-4 bg-blue-300" })
46449
47392
  ] }),
46450
- /* @__PURE__ */ jsx("div", { className: "w-9" })
46451
- ] }) }),
46452
- /* @__PURE__ */ jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsxs("div", { className: "relative flex items-center", children: [
46453
- /* @__PURE__ */ jsx("div", { className: "absolute left-0 z-10", children: /* @__PURE__ */ jsx(
46454
- BackButtonMinimal,
47393
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
47394
+ /* @__PURE__ */ jsx("div", { className: "text-blue-600", children: getShiftIcon(workspace.shift_type) }),
47395
+ /* @__PURE__ */ jsxs("span", { className: "text-sm md:text-base font-medium text-blue-600", children: [
47396
+ workspace.shift_type,
47397
+ " Shift"
47398
+ ] })
47399
+ ] })
47400
+ ] }) })
47401
+ ] }),
47402
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 sm:mt-1.5 lg:mt-2", children: [
47403
+ /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex bg-gray-100 rounded-lg p-0.5", children: [
47404
+ /* @__PURE__ */ jsx(
47405
+ "button",
46455
47406
  {
46456
- onClick: handleBackNavigation,
46457
- text: previousView === "line_monthly_history" ? "Back to Line History" : returnUrl && returnUrl.includes("monthly_history") ? "Back to Line History" : returnUrl && returnUrl.includes("/kpis/") ? "Back to KPIs" : returnUrl && returnUrl.includes("/leaderboard/") ? "Back to Leaderboard" : (date || shift) && activeTab !== "monthly_history" ? "Back to Monthly History" : "Back",
46458
- size: "default",
46459
- "aria-label": "Navigate back to previous page"
47407
+ onClick: () => setActiveTab("overview"),
47408
+ className: `flex-1 px-2 py-1.5 text-xs font-medium rounded-md transition-all duration-200 ${activeTab === "overview" ? "bg-white text-gray-900 shadow-sm" : "text-gray-600"}`,
47409
+ children: "Efficiency"
46460
47410
  }
46461
- ) }),
46462
- /* @__PURE__ */ jsx("div", { className: "absolute left-1/2 transform -translate-x-1/2 max-w-[calc(100%-200px)]", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
46463
- /* @__PURE__ */ jsx("h1", { className: "text-lg md:text-xl lg:text-2xl xl:text-3xl font-semibold text-gray-900 truncate", children: formattedWorkspaceName }),
46464
- workspaceHealth && /* @__PURE__ */ jsxs("div", { className: "relative flex h-2.5 w-2.5", children: [
46465
- /* @__PURE__ */ jsx("span", { className: clsx(
46466
- "animate-ping absolute inline-flex h-full w-full rounded-full opacity-75",
46467
- workspaceHealth.status === "healthy" ? "bg-green-400" : "bg-red-400"
46468
- ) }),
46469
- /* @__PURE__ */ jsx("span", { className: clsx(
46470
- "relative inline-flex rounded-full h-2.5 w-2.5",
46471
- workspaceHealth.status === "healthy" ? "bg-green-500" : "bg-red-500"
46472
- ) })
46473
- ] })
46474
- ] }) }),
46475
- workspaceHealth && activeTab !== "monthly_history" && /* @__PURE__ */ jsx("div", { className: "absolute right-0 top-0 flex items-center h-8", children: /* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-500", children: [
46476
- "Last update: ",
46477
- workspaceHealth.timeSinceLastUpdate
46478
- ] }) }),
46479
- /* @__PURE__ */ jsx("div", { className: "w-full h-8" })
47411
+ ),
47412
+ isClipsEnabled && /* @__PURE__ */ jsx(
47413
+ "button",
47414
+ {
47415
+ onClick: () => setActiveTab("bottlenecks"),
47416
+ className: `flex-1 px-2 py-1.5 text-xs font-medium rounded-md transition-all duration-200 ${activeTab === "bottlenecks" ? "bg-white text-gray-900 shadow-sm" : "text-gray-600"}`,
47417
+ children: "Clips"
47418
+ }
47419
+ ),
47420
+ /* @__PURE__ */ jsx(
47421
+ "button",
47422
+ {
47423
+ onClick: () => setActiveTab("monthly_history"),
47424
+ className: `flex-1 px-2 py-1.5 text-xs font-medium rounded-md transition-all duration-200 ${activeTab === "monthly_history" ? "bg-white text-gray-900 shadow-sm" : "text-gray-600"}`,
47425
+ children: "History"
47426
+ }
47427
+ )
46480
47428
  ] }) }),
46481
- activeTab !== "monthly_history" && /* @__PURE__ */ jsxs(Fragment, { children: [
46482
- /* @__PURE__ */ jsxs("div", { className: "sm:hidden mt-3 flex items-center justify-center gap-2", children: [
46483
- /* @__PURE__ */ jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-gray-100 rounded-full", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-700", children: formatISTDate2(new Date(workspace.date)) }) }),
46484
- /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-1 px-2.5 py-1 bg-gray-100 rounded-full", children: [
46485
- /* @__PURE__ */ jsx("div", { className: "text-gray-700 scale-90", children: getShiftIcon(workspace.shift_type) }),
46486
- /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-700", children: workspace.shift_type })
46487
- ] }),
46488
- !date && !shift && !usingFallbackData ? /* @__PURE__ */ jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-green-100 rounded-full", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-green-700", children: /* @__PURE__ */ jsx(LiveTimer, {}) }) }) : date ? /* @__PURE__ */ jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-blue-100 rounded-full", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-blue-700", children: getDaysDifference(workspace.date, timezone, dashboardConfig?.shiftConfig?.dayShift?.startTime || "06:00") }) }) : usingFallbackData ? /* @__PURE__ */ jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-amber-100 rounded-full", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-amber-700", children: getDaysDifference(workspace.date, timezone, dashboardConfig?.shiftConfig?.dayShift?.startTime || "06:00") }) }) : null
46489
- ] }),
46490
- /* @__PURE__ */ jsx("div", { className: "hidden sm:block mt-3 bg-blue-50 px-3 py-2 rounded-lg", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-3 md:gap-4", children: [
46491
- !date && !shift && !usingFallbackData && /* @__PURE__ */ jsxs(Fragment, { children: [
46492
- /* @__PURE__ */ jsx("div", { className: "text-base md:text-lg font-medium text-blue-600", children: /* @__PURE__ */ jsx(LiveTimer, {}) }),
46493
- /* @__PURE__ */ jsx("div", { className: "w-px h-4 bg-blue-300" })
46494
- ] }),
46495
- /* @__PURE__ */ jsx("span", { className: "text-sm md:text-base font-medium text-blue-600", children: formatISTDate2(new Date(workspace.date)) }),
46496
- /* @__PURE__ */ jsx("div", { className: "w-px h-4 bg-blue-300" }),
46497
- date && /* @__PURE__ */ jsxs(Fragment, { children: [
46498
- /* @__PURE__ */ jsx("span", { className: "px-2 py-1 text-xs font-medium bg-blue-200 text-blue-800 rounded-md", children: getDaysDifference(workspace.date, timezone, dashboardConfig?.shiftConfig?.dayShift?.startTime || "06:00") }),
46499
- /* @__PURE__ */ jsx("div", { className: "w-px h-4 bg-blue-300" })
46500
- ] }),
46501
- !date && !shift && usingFallbackData && /* @__PURE__ */ jsxs(Fragment, { children: [
46502
- /* @__PURE__ */ jsxs("span", { className: "px-2 py-1 text-xs font-medium bg-amber-100 text-amber-700 rounded-md", children: [
46503
- "Latest available data (",
46504
- getDaysDifference(workspace.date, timezone, dashboardConfig?.shiftConfig?.dayShift?.startTime || "06:00"),
46505
- ")"
46506
- ] }),
46507
- /* @__PURE__ */ jsx("div", { className: "w-px h-4 bg-blue-300" })
46508
- ] }),
46509
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
46510
- /* @__PURE__ */ jsx("div", { className: "text-blue-600", children: getShiftIcon(workspace.shift_type) }),
46511
- /* @__PURE__ */ jsxs("span", { className: "text-sm md:text-base font-medium text-blue-600", children: [
46512
- workspace.shift_type,
46513
- " Shift"
46514
- ] })
46515
- ] })
46516
- ] }) })
46517
- ] }),
46518
- /* @__PURE__ */ jsxs("div", { className: "mt-2 sm:mt-1.5 lg:mt-2", children: [
46519
- /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex bg-gray-100 rounded-lg p-0.5", children: [
47429
+ /* @__PURE__ */ jsxs("div", { className: "hidden sm:flex items-center justify-between", children: [
47430
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 lg:gap-2", children: [
46520
47431
  /* @__PURE__ */ jsx(
46521
47432
  "button",
46522
47433
  {
46523
47434
  onClick: () => setActiveTab("overview"),
46524
- className: `flex-1 px-2 py-1.5 text-xs font-medium rounded-md transition-all duration-200 ${activeTab === "overview" ? "bg-white text-gray-900 shadow-sm" : "text-gray-600"}`,
47435
+ className: `px-2 lg:px-3 py-1 lg:py-1.5 text-sm lg:text-base font-medium rounded-lg transition-colors whitespace-nowrap ${activeTab === "overview" ? "bg-blue-50 text-blue-600" : "text-gray-600 hover:bg-gray-50"}`,
46525
47436
  children: "Efficiency"
46526
47437
  }
46527
47438
  ),
@@ -46529,7 +47440,7 @@ var WorkspaceDetailView = ({
46529
47440
  "button",
46530
47441
  {
46531
47442
  onClick: () => setActiveTab("bottlenecks"),
46532
- className: `flex-1 px-2 py-1.5 text-xs font-medium rounded-md transition-all duration-200 ${activeTab === "bottlenecks" ? "bg-white text-gray-900 shadow-sm" : "text-gray-600"}`,
47443
+ className: `px-2 lg:px-3 py-1 lg:py-1.5 text-sm lg:text-base font-medium rounded-lg transition-colors whitespace-nowrap ${activeTab === "bottlenecks" ? "bg-blue-50 text-blue-600" : "text-gray-600 hover:bg-gray-50"}`,
46533
47444
  children: "Clips"
46534
47445
  }
46535
47446
  ),
@@ -46537,59 +47448,151 @@ var WorkspaceDetailView = ({
46537
47448
  "button",
46538
47449
  {
46539
47450
  onClick: () => setActiveTab("monthly_history"),
46540
- className: `flex-1 px-2 py-1.5 text-xs font-medium rounded-md transition-all duration-200 ${activeTab === "monthly_history" ? "bg-white text-gray-900 shadow-sm" : "text-gray-600"}`,
46541
- children: "History"
47451
+ className: `px-2 lg:px-3 py-1 lg:py-1.5 text-sm lg:text-base font-medium rounded-lg transition-colors whitespace-nowrap ${activeTab === "monthly_history" ? "bg-blue-50 text-blue-600" : "text-gray-600 hover:bg-gray-50"}`,
47452
+ children: "Monthly History"
46542
47453
  }
46543
47454
  )
46544
- ] }) }),
46545
- /* @__PURE__ */ jsxs("div", { className: "hidden sm:flex items-center justify-between", children: [
46546
- /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 lg:gap-2", children: [
46547
- /* @__PURE__ */ jsx(
46548
- "button",
46549
- {
46550
- onClick: () => setActiveTab("overview"),
46551
- className: `px-2 lg:px-3 py-1 lg:py-1.5 text-sm lg:text-base font-medium rounded-lg transition-colors whitespace-nowrap ${activeTab === "overview" ? "bg-blue-50 text-blue-600" : "text-gray-600 hover:bg-gray-50"}`,
46552
- children: "Efficiency"
46553
- }
46554
- ),
46555
- isClipsEnabled && /* @__PURE__ */ jsx(
46556
- "button",
46557
- {
46558
- onClick: () => setActiveTab("bottlenecks"),
46559
- className: `px-2 lg:px-3 py-1 lg:py-1.5 text-sm lg:text-base font-medium rounded-lg transition-colors whitespace-nowrap ${activeTab === "bottlenecks" ? "bg-blue-50 text-blue-600" : "text-gray-600 hover:bg-gray-50"}`,
46560
- children: "Clips"
46561
- }
46562
- ),
46563
- /* @__PURE__ */ jsx(
47455
+ ] }),
47456
+ activeTab === "overview" && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 lg:gap-2", children: renderHeaderActions ? renderHeaderActions(workspace) : /* @__PURE__ */ jsx(WorkspacePdfGenerator, { workspace }) }),
47457
+ activeTab === "monthly_history" && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 lg:gap-2", children: /* @__PURE__ */ jsx(
47458
+ WorkspaceMonthlyPdfGenerator,
47459
+ {
47460
+ workspaceId,
47461
+ workspaceName: workspace?.workspace_name || "",
47462
+ monthlyData,
47463
+ selectedMonth,
47464
+ selectedYear,
47465
+ selectedShift
47466
+ }
47467
+ ) })
47468
+ ] })
47469
+ ] })
47470
+ ] }),
47471
+ /* @__PURE__ */ jsxs("div", { className: "flex-grow p-1.5 sm:p-2 lg:p-4", children: [
47472
+ activeTab === "overview" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full lg:h-[calc(100vh-10rem)] overflow-y-auto lg:overflow-hidden", children: [
47473
+ /* @__PURE__ */ jsxs("div", { className: "block lg:hidden space-y-6 pb-6", children: [
47474
+ !shouldShowCycleTimeChart && /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-sm p-6", children: [
47475
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-700 mb-8", children: "Daily Progress" }),
47476
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col justify-center space-y-8", children: [
47477
+ /* @__PURE__ */ jsxs("div", { className: "text-center space-y-1", children: [
47478
+ /* @__PURE__ */ jsxs("p", { className: "text-7xl font-bold tracking-tight", children: [
47479
+ (workspace.total_actions / workspace.target_output * 100).toFixed(1),
47480
+ "%"
47481
+ ] }),
47482
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center gap-2 text-gray-500", children: /* @__PURE__ */ jsx("span", { className: "text-base font-medium", children: "of today's target" }) })
47483
+ ] }),
47484
+ /* @__PURE__ */ jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
47485
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center", children: [
47486
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-600", children: "Overall Progress" }),
47487
+ /* @__PURE__ */ jsxs("p", { className: "text-lg font-semibold text-gray-700", children: [
47488
+ workspace.total_actions,
47489
+ " / ",
47490
+ workspace.target_output
47491
+ ] })
47492
+ ] }),
47493
+ /* @__PURE__ */ jsx("div", { className: "w-full bg-gray-100 rounded-full h-2.5", children: /* @__PURE__ */ jsx(
47494
+ motion.div,
47495
+ {
47496
+ initial: { width: 0 },
47497
+ animate: {
47498
+ width: `${Math.min(100, workspace.total_actions / workspace.target_output * 100)}%`
47499
+ },
47500
+ transition: {
47501
+ duration: 1,
47502
+ ease: "easeOut",
47503
+ delay: 0.2
47504
+ },
47505
+ className: "bg-green-500 h-2.5 rounded-full"
47506
+ }
47507
+ ) })
47508
+ ] }) })
47509
+ ] })
47510
+ ] }),
47511
+ /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-sm p-4", children: [
47512
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-4", children: [
47513
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-700", children: shouldShowCycleTimeChart ? "Cycle Time (last 60 minutes)" : "Hourly Output" }),
47514
+ !shouldShowCycleTimeChart && /* @__PURE__ */ jsxs(
46564
47515
  "button",
46565
47516
  {
46566
- onClick: () => setActiveTab("monthly_history"),
46567
- className: `px-2 lg:px-3 py-1 lg:py-1.5 text-sm lg:text-base font-medium rounded-lg transition-colors whitespace-nowrap ${activeTab === "monthly_history" ? "bg-blue-50 text-blue-600" : "text-gray-600 hover:bg-gray-50"}`,
46568
- children: "Monthly History"
47517
+ onClick: () => setShowIdleTime(!showIdleTime),
47518
+ className: `
47519
+ flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded
47520
+ transition-all duration-200 border
47521
+ ${showIdleTime ? "bg-gray-100 text-gray-700 border-gray-300 hover:bg-gray-200" : "bg-white text-gray-500 border-gray-200 hover:bg-gray-50 hover:text-gray-700"}
47522
+ `,
47523
+ "aria-label": showIdleTime ? "Hide idle time bars from chart" : "Show idle time bars on chart",
47524
+ children: [
47525
+ showIdleTime ? /* @__PURE__ */ jsx(EyeOff, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ jsx(Eye, { className: "w-3.5 h-3.5" }),
47526
+ /* @__PURE__ */ jsx("span", { children: showIdleTime ? "Hide Idle Time" : "Show Idle Time" })
47527
+ ]
46569
47528
  }
46570
47529
  )
46571
47530
  ] }),
46572
- activeTab === "overview" && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 lg:gap-2", children: renderHeaderActions ? renderHeaderActions(workspace) : /* @__PURE__ */ jsx(WorkspacePdfGenerator, { workspace }) }),
46573
- activeTab === "monthly_history" && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 lg:gap-2", children: /* @__PURE__ */ jsx(
46574
- WorkspaceMonthlyPdfGenerator,
47531
+ /* @__PURE__ */ jsx(
47532
+ "div",
46575
47533
  {
46576
- workspaceId,
46577
- workspaceName: workspace?.workspace_name || "",
46578
- monthlyData,
46579
- selectedMonth,
46580
- selectedYear,
46581
- selectedShift
47534
+ className: "h-[300px]",
47535
+ style: { minHeight: "200px", minWidth: "300px" },
47536
+ children: shouldShowCycleTimeChart ? /* @__PURE__ */ jsx(
47537
+ CycleTimeOverTimeChart,
47538
+ {
47539
+ data: workspace.hourly_action_counts || [],
47540
+ idealCycleTime: workspace.ideal_cycle_time || 0,
47541
+ shiftStart: workspace.shift_start || ""
47542
+ }
47543
+ ) : /* @__PURE__ */ jsx(
47544
+ HourlyOutputChart2,
47545
+ {
47546
+ data: workspace.hourly_action_counts || [],
47547
+ pphThreshold: workspace.pph_threshold || 0,
47548
+ shiftStart: workspace.shift_start || "",
47549
+ shiftEnd: workspace.shift_end,
47550
+ showIdleTime,
47551
+ idleTimeHourly: workspace.idle_time_hourly
47552
+ }
47553
+ )
46582
47554
  }
46583
- ) })
46584
- ] })
46585
- ] })
46586
- ] }),
46587
- /* @__PURE__ */ jsxs("div", { className: "flex-grow p-1.5 sm:p-2 lg:p-4", children: [
46588
- activeTab === "overview" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full lg:h-[calc(100vh-10rem)] overflow-y-auto lg:overflow-hidden", children: [
46589
- /* @__PURE__ */ jsxs("div", { className: "block lg:hidden space-y-6 pb-6", children: [
46590
- !shouldShowCycleTimeChart && /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-sm p-6", children: [
47555
+ )
47556
+ ] }),
47557
+ shouldShowCycleTimeChart ? /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
47558
+ /* @__PURE__ */ jsxs(Card2, { children: [
47559
+ /* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Efficiency" }) }),
47560
+ /* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
47561
+ /* @__PURE__ */ jsxs("p", { className: `text-5xl font-bold ${(workspace.avg_efficiency || 0) >= 80 ? "text-green-500" : "text-red-500"}`, children: [
47562
+ (workspace.avg_efficiency || 0).toFixed(1),
47563
+ "%"
47564
+ ] }),
47565
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Target: 80%" })
47566
+ ] }) })
47567
+ ] }),
47568
+ /* @__PURE__ */ jsxs(Card2, { children: [
47569
+ /* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
47570
+ /* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
47571
+ /* @__PURE__ */ jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-green-500"}`, children: workspace.avg_cycle_time.toFixed(1) }),
47572
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
47573
+ "Standard: ",
47574
+ workspace.ideal_cycle_time?.toFixed(1) || 0,
47575
+ "s"
47576
+ ] })
47577
+ ] }) })
47578
+ ] }),
47579
+ /* @__PURE__ */ jsxs(Card2, { children: [
47580
+ /* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Idle Time" }) }),
47581
+ /* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
47582
+ /* @__PURE__ */ jsx("p", { className: `text-4xl font-bold ${!workspace.idle_time || workspace.idle_time <= 0 ? "text-green-500" : workspace.idle_time <= 300 ? "text-yellow-500" : (
47583
+ // 5 minutes or less
47584
+ "text-red-500"
47585
+ )}`, children: formatIdleTime(workspace.idle_time) }),
47586
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Total idle time" })
47587
+ ] }) })
47588
+ ] })
47589
+ ] }) : /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(WorkspaceMetricCards, { workspace, className: "flex-1" }) })
47590
+ ] }),
47591
+ /* @__PURE__ */ jsxs("div", { className: "hidden lg:flex lg:flex-col lg:h-full", children: [
47592
+ /* @__PURE__ */ jsxs("div", { className: "h-[60%] grid grid-cols-1 lg:grid-cols-5 gap-3 mb-3", children: [
47593
+ !shouldShowCycleTimeChart && /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-sm p-6 lg:col-span-2", children: [
46591
47594
  /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-700 mb-8", children: "Daily Progress" }),
46592
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col justify-center space-y-8", children: [
47595
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-[calc(100%-6rem)] justify-center space-y-8", children: [
46593
47596
  /* @__PURE__ */ jsxs("div", { className: "text-center space-y-1", children: [
46594
47597
  /* @__PURE__ */ jsxs("p", { className: "text-7xl font-bold tracking-tight", children: [
46595
47598
  (workspace.total_actions / workspace.target_output * 100).toFixed(1),
@@ -46624,7 +47627,7 @@ var WorkspaceDetailView = ({
46624
47627
  ] }) })
46625
47628
  ] })
46626
47629
  ] }),
46627
- /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-sm p-4", children: [
47630
+ /* @__PURE__ */ jsxs("div", { className: `bg-white rounded-lg shadow-sm p-4 ${shouldShowCycleTimeChart ? "lg:col-span-5" : "lg:col-span-3"}`, children: [
46628
47631
  /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-4", children: [
46629
47632
  /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-700", children: shouldShowCycleTimeChart ? "Cycle Time (last 60 minutes)" : "Hourly Output" }),
46630
47633
  !shouldShowCycleTimeChart && /* @__PURE__ */ jsxs(
@@ -46632,10 +47635,10 @@ var WorkspaceDetailView = ({
46632
47635
  {
46633
47636
  onClick: () => setShowIdleTime(!showIdleTime),
46634
47637
  className: `
46635
- flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded
46636
- transition-all duration-200 border
46637
- ${showIdleTime ? "bg-gray-100 text-gray-700 border-gray-300 hover:bg-gray-200" : "bg-white text-gray-500 border-gray-200 hover:bg-gray-50 hover:text-gray-700"}
46638
- `,
47638
+ flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded
47639
+ transition-all duration-200 border
47640
+ ${showIdleTime ? "bg-gray-100 text-gray-700 border-gray-300 hover:bg-gray-200" : "bg-white text-gray-500 border-gray-200 hover:bg-gray-50 hover:text-gray-700"}
47641
+ `,
46639
47642
  "aria-label": showIdleTime ? "Hide idle time bars from chart" : "Show idle time bars on chart",
46640
47643
  children: [
46641
47644
  showIdleTime ? /* @__PURE__ */ jsx(EyeOff, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ jsx(Eye, { className: "w-3.5 h-3.5" }),
@@ -46647,7 +47650,7 @@ var WorkspaceDetailView = ({
46647
47650
  /* @__PURE__ */ jsx(
46648
47651
  "div",
46649
47652
  {
46650
- className: "h-[300px]",
47653
+ className: "h-[calc(100%-3rem)]",
46651
47654
  style: { minHeight: "200px", minWidth: "300px" },
46652
47655
  children: shouldShowCycleTimeChart ? /* @__PURE__ */ jsx(
46653
47656
  CycleTimeOverTimeChart,
@@ -46669,248 +47672,103 @@ var WorkspaceDetailView = ({
46669
47672
  )
46670
47673
  }
46671
47674
  )
46672
- ] }),
46673
- shouldShowCycleTimeChart ? /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
46674
- /* @__PURE__ */ jsxs(Card2, { children: [
46675
- /* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Efficiency" }) }),
46676
- /* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
46677
- /* @__PURE__ */ jsxs("p", { className: `text-5xl font-bold ${(workspace.avg_efficiency || 0) >= 80 ? "text-green-500" : "text-red-500"}`, children: [
46678
- (workspace.avg_efficiency || 0).toFixed(1),
46679
- "%"
46680
- ] }),
46681
- /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Target: 80%" })
46682
- ] }) })
46683
- ] }),
46684
- /* @__PURE__ */ jsxs(Card2, { children: [
46685
- /* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
46686
- /* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
46687
- /* @__PURE__ */ jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-green-500"}`, children: workspace.avg_cycle_time.toFixed(1) }),
46688
- /* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
46689
- "Standard: ",
46690
- workspace.ideal_cycle_time?.toFixed(1) || 0,
46691
- "s"
46692
- ] })
46693
- ] }) })
46694
- ] }),
46695
- /* @__PURE__ */ jsxs(Card2, { children: [
46696
- /* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Idle Time" }) }),
46697
- /* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
46698
- /* @__PURE__ */ jsx("p", { className: `text-4xl font-bold ${!workspace.idle_time || workspace.idle_time <= 0 ? "text-green-500" : workspace.idle_time <= 300 ? "text-yellow-500" : (
46699
- // 5 minutes or less
46700
- "text-red-500"
46701
- )}`, children: formatIdleTime(workspace.idle_time) }),
46702
- /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Total idle time" })
46703
- ] }) })
46704
- ] })
46705
- ] }) : /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(WorkspaceMetricCards, { workspace, className: "flex-1" }) })
47675
+ ] })
46706
47676
  ] }),
46707
- /* @__PURE__ */ jsxs("div", { className: "hidden lg:flex lg:flex-col lg:h-full", children: [
46708
- /* @__PURE__ */ jsxs("div", { className: "h-[60%] grid grid-cols-1 lg:grid-cols-5 gap-3 mb-3", children: [
46709
- !shouldShowCycleTimeChart && /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-sm p-6 lg:col-span-2", children: [
46710
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-700 mb-8", children: "Daily Progress" }),
46711
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-[calc(100%-6rem)] justify-center space-y-8", children: [
46712
- /* @__PURE__ */ jsxs("div", { className: "text-center space-y-1", children: [
46713
- /* @__PURE__ */ jsxs("p", { className: "text-7xl font-bold tracking-tight", children: [
46714
- (workspace.total_actions / workspace.target_output * 100).toFixed(1),
46715
- "%"
46716
- ] }),
46717
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center gap-2 text-gray-500", children: /* @__PURE__ */ jsx("span", { className: "text-base font-medium", children: "of today's target" }) })
46718
- ] }),
46719
- /* @__PURE__ */ jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
46720
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center", children: [
46721
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-600", children: "Overall Progress" }),
46722
- /* @__PURE__ */ jsxs("p", { className: "text-lg font-semibold text-gray-700", children: [
46723
- workspace.total_actions,
46724
- " / ",
46725
- workspace.target_output
46726
- ] })
46727
- ] }),
46728
- /* @__PURE__ */ jsx("div", { className: "w-full bg-gray-100 rounded-full h-2.5", children: /* @__PURE__ */ jsx(
46729
- motion.div,
46730
- {
46731
- initial: { width: 0 },
46732
- animate: {
46733
- width: `${Math.min(100, workspace.total_actions / workspace.target_output * 100)}%`
46734
- },
46735
- transition: {
46736
- duration: 1,
46737
- ease: "easeOut",
46738
- delay: 0.2
46739
- },
46740
- className: "bg-green-500 h-2.5 rounded-full"
46741
- }
46742
- ) })
46743
- ] }) })
46744
- ] })
46745
- ] }),
46746
- /* @__PURE__ */ jsxs("div", { className: `bg-white rounded-lg shadow-sm p-4 ${shouldShowCycleTimeChart ? "lg:col-span-5" : "lg:col-span-3"}`, children: [
46747
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-4", children: [
46748
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-700", children: shouldShowCycleTimeChart ? "Cycle Time (last 60 minutes)" : "Hourly Output" }),
46749
- !shouldShowCycleTimeChart && /* @__PURE__ */ jsxs(
46750
- "button",
46751
- {
46752
- onClick: () => setShowIdleTime(!showIdleTime),
46753
- className: `
46754
- flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded
46755
- transition-all duration-200 border
46756
- ${showIdleTime ? "bg-gray-100 text-gray-700 border-gray-300 hover:bg-gray-200" : "bg-white text-gray-500 border-gray-200 hover:bg-gray-50 hover:text-gray-700"}
46757
- `,
46758
- "aria-label": showIdleTime ? "Hide idle time bars from chart" : "Show idle time bars on chart",
46759
- children: [
46760
- showIdleTime ? /* @__PURE__ */ jsx(EyeOff, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ jsx(Eye, { className: "w-3.5 h-3.5" }),
46761
- /* @__PURE__ */ jsx("span", { children: showIdleTime ? "Hide Idle Time" : "Show Idle Time" })
46762
- ]
46763
- }
46764
- )
47677
+ shouldShowCycleTimeChart ? /* @__PURE__ */ jsxs("div", { className: "h-[40%] grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3", children: [
47678
+ /* @__PURE__ */ jsxs(Card2, { children: [
47679
+ /* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Efficiency" }) }),
47680
+ /* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
47681
+ /* @__PURE__ */ jsxs("p", { className: `text-5xl font-bold ${(workspace.avg_efficiency || 0) >= 80 ? "text-green-500" : "text-red-500"}`, children: [
47682
+ (workspace.avg_efficiency || 0).toFixed(1),
47683
+ "%"
46765
47684
  ] }),
46766
- /* @__PURE__ */ jsx(
46767
- "div",
46768
- {
46769
- className: "h-[calc(100%-3rem)]",
46770
- style: { minHeight: "200px", minWidth: "300px" },
46771
- children: shouldShowCycleTimeChart ? /* @__PURE__ */ jsx(
46772
- CycleTimeOverTimeChart,
46773
- {
46774
- data: workspace.hourly_action_counts || [],
46775
- idealCycleTime: workspace.ideal_cycle_time || 0,
46776
- shiftStart: workspace.shift_start || ""
46777
- }
46778
- ) : /* @__PURE__ */ jsx(
46779
- HourlyOutputChart2,
46780
- {
46781
- data: workspace.hourly_action_counts || [],
46782
- pphThreshold: workspace.pph_threshold || 0,
46783
- shiftStart: workspace.shift_start || "",
46784
- shiftEnd: workspace.shift_end,
46785
- showIdleTime,
46786
- idleTimeHourly: workspace.idle_time_hourly
46787
- }
46788
- )
46789
- }
46790
- )
46791
- ] })
47685
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Target: 80%" })
47686
+ ] }) })
46792
47687
  ] }),
46793
- shouldShowCycleTimeChart ? /* @__PURE__ */ jsxs("div", { className: "h-[40%] grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3", children: [
46794
- /* @__PURE__ */ jsxs(Card2, { children: [
46795
- /* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Efficiency" }) }),
46796
- /* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
46797
- /* @__PURE__ */ jsxs("p", { className: `text-5xl font-bold ${(workspace.avg_efficiency || 0) >= 80 ? "text-green-500" : "text-red-500"}`, children: [
46798
- (workspace.avg_efficiency || 0).toFixed(1),
46799
- "%"
46800
- ] }),
46801
- /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Target: 80%" })
46802
- ] }) })
46803
- ] }),
46804
- /* @__PURE__ */ jsxs(Card2, { children: [
46805
- /* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
46806
- /* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
46807
- /* @__PURE__ */ jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-green-500"}`, children: workspace.avg_cycle_time.toFixed(1) }),
46808
- /* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
46809
- "Standard: ",
46810
- workspace.ideal_cycle_time?.toFixed(1) || 0,
46811
- "s"
46812
- ] })
46813
- ] }) })
46814
- ] }),
46815
- /* @__PURE__ */ jsxs(Card2, { children: [
46816
- /* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Idle Time" }) }),
46817
- /* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
46818
- /* @__PURE__ */ jsx("p", { className: `text-4xl font-bold ${!workspace.idle_time || workspace.idle_time <= 0 ? "text-green-500" : workspace.idle_time <= 300 ? "text-yellow-500" : (
46819
- // 5 minutes or less
46820
- "text-red-500"
46821
- )}`, children: formatIdleTime(workspace.idle_time) }),
46822
- /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Total idle time" })
46823
- ] }) })
46824
- ] })
46825
- ] }) : /* @__PURE__ */ jsx("div", { className: "h-[40%] flex", children: /* @__PURE__ */ jsx(WorkspaceMetricCards, { workspace, className: "flex-1" }) })
46826
- ] })
46827
- ] }),
46828
- activeTab === "monthly_history" && /* @__PURE__ */ jsxs("div", { className: "h-[calc(100vh-10rem)] overflow-y-auto px-2 sm:px-4 lg:px-0", children: [
46829
- workspaceId && activeTab === "monthly_history" && /* @__PURE__ */ jsx(
46830
- WorkspaceMonthlyDataFetcher,
46831
- {
46832
- workspaceId,
46833
- selectedMonth,
46834
- selectedYear,
46835
- onDataLoaded: handleMonthlyDataLoaded,
46836
- onLoadingChange: setMonthlyDataLoading
46837
- }
46838
- ),
46839
- usingFallbackData && !date && !shift && /* @__PURE__ */ jsx("div", { className: "mb-3 sm:mb-4 bg-amber-50 border border-amber-200 rounded-lg px-3 sm:px-4 py-2 sm:py-3 text-amber-800", children: /* @__PURE__ */ jsxs("p", { className: "text-xs sm:text-sm font-medium flex items-center", children: [
46840
- /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-4 w-4 sm:h-5 sm:w-5 mr-2", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z", clipRule: "evenodd" }) }),
46841
- "No current data available for today. Showing monthly history instead."
46842
- ] }) }),
46843
- /* @__PURE__ */ jsx(
46844
- WorkspaceMonthlyHistory,
46845
- {
46846
- data: monthlyData,
46847
- month: selectedMonth,
46848
- year: selectedYear,
46849
- workspaceId,
46850
- selectedShift,
46851
- monthlyDataLoading,
46852
- onDateSelect: (selectedDate, shift2) => {
46853
- if (onDateSelect) {
46854
- onDateSelect(selectedDate, shift2);
46855
- } else if (onNavigate) {
46856
- const params = new URLSearchParams();
46857
- params.set("date", selectedDate);
46858
- params.set("shift", shift2 === "day" ? "0" : "1");
46859
- params.set("fromMonthly", "true");
46860
- if (effectiveLineId) {
46861
- params.set("lineId", effectiveLineId);
46862
- }
46863
- onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
46864
- }
46865
- },
46866
- onMonthNavigate: (newMonth, newYear) => {
46867
- setSelectedMonth(newMonth);
46868
- setSelectedYear(newYear);
46869
- },
46870
- onShiftChange: setSelectedShift,
46871
- className: "w-full"
46872
- }
46873
- )
46874
- ] }),
46875
- activeTab === "bottlenecks" && /* @__PURE__ */ jsx(ClipFilterProvider, { children: /* @__PURE__ */ jsx(
46876
- BottlenecksContent,
47688
+ /* @__PURE__ */ jsxs(Card2, { children: [
47689
+ /* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
47690
+ /* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
47691
+ /* @__PURE__ */ jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-green-500"}`, children: workspace.avg_cycle_time.toFixed(1) }),
47692
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
47693
+ "Standard: ",
47694
+ workspace.ideal_cycle_time?.toFixed(1) || 0,
47695
+ "s"
47696
+ ] })
47697
+ ] }) })
47698
+ ] }),
47699
+ /* @__PURE__ */ jsxs(Card2, { children: [
47700
+ /* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Idle Time" }) }),
47701
+ /* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
47702
+ /* @__PURE__ */ jsx("p", { className: `text-4xl font-bold ${!workspace.idle_time || workspace.idle_time <= 0 ? "text-green-500" : workspace.idle_time <= 300 ? "text-yellow-500" : (
47703
+ // 5 minutes or less
47704
+ "text-red-500"
47705
+ )}`, children: formatIdleTime(workspace.idle_time) }),
47706
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Total idle time" })
47707
+ ] }) })
47708
+ ] })
47709
+ ] }) : /* @__PURE__ */ jsx("div", { className: "h-[40%] flex", children: /* @__PURE__ */ jsx(WorkspaceMetricCards, { workspace, className: "flex-1" }) })
47710
+ ] })
47711
+ ] }),
47712
+ activeTab === "monthly_history" && /* @__PURE__ */ jsxs("div", { className: "h-[calc(100vh-10rem)] overflow-y-auto px-2 sm:px-4 lg:px-0", children: [
47713
+ workspaceId && activeTab === "monthly_history" && /* @__PURE__ */ jsx(
47714
+ WorkspaceMonthlyDataFetcher,
46877
47715
  {
46878
47716
  workspaceId,
46879
- workspaceName: formattedWorkspaceName,
46880
- date,
46881
- shift,
46882
- totalOutput: workspace?.total_actions,
46883
- className: "h-[calc(100vh-10rem)]"
47717
+ selectedMonth,
47718
+ selectedYear,
47719
+ onDataLoaded: handleMonthlyDataLoaded,
47720
+ onLoadingChange: setMonthlyDataLoading
46884
47721
  }
46885
- ) })
46886
- ] })
46887
- ] }),
46888
- /* @__PURE__ */ jsx(
46889
- CongratulationsOverlay,
46890
- {
46891
- achievement: currentAchievement,
46892
- isVisible: showCongratulations,
46893
- duration: 6e4,
46894
- onDismiss: () => {
46895
- setShowCongratulations(false);
46896
- setCurrentAchievement(null);
47722
+ ),
47723
+ usingFallbackData && !date && !shift && /* @__PURE__ */ jsx("div", { className: "mb-3 sm:mb-4 bg-amber-50 border border-amber-200 rounded-lg px-3 sm:px-4 py-2 sm:py-3 text-amber-800", children: /* @__PURE__ */ jsxs("p", { className: "text-xs sm:text-sm font-medium flex items-center", children: [
47724
+ /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-4 w-4 sm:h-5 sm:w-5 mr-2", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z", clipRule: "evenodd" }) }),
47725
+ "No current data available for today. Showing monthly history instead."
47726
+ ] }) }),
47727
+ /* @__PURE__ */ jsx(
47728
+ WorkspaceMonthlyHistory,
47729
+ {
47730
+ data: monthlyData,
47731
+ month: selectedMonth,
47732
+ year: selectedYear,
47733
+ workspaceId,
47734
+ selectedShift,
47735
+ monthlyDataLoading,
47736
+ onDateSelect: (selectedDate, shift2) => {
47737
+ if (onDateSelect) {
47738
+ onDateSelect(selectedDate, shift2);
47739
+ } else if (onNavigate) {
47740
+ const params = new URLSearchParams();
47741
+ params.set("date", selectedDate);
47742
+ params.set("shift", shift2 === "day" ? "0" : "1");
47743
+ params.set("fromMonthly", "true");
47744
+ if (effectiveLineId) {
47745
+ params.set("lineId", effectiveLineId);
47746
+ }
47747
+ onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
47748
+ }
47749
+ },
47750
+ onMonthNavigate: (newMonth, newYear) => {
47751
+ setSelectedMonth(newMonth);
47752
+ setSelectedYear(newYear);
47753
+ },
47754
+ onShiftChange: setSelectedShift,
47755
+ className: "w-full"
47756
+ }
47757
+ )
47758
+ ] }),
47759
+ activeTab === "bottlenecks" && /* @__PURE__ */ jsx(ClipFilterProvider, { children: /* @__PURE__ */ jsx(
47760
+ BottlenecksContent,
47761
+ {
47762
+ workspaceId,
47763
+ workspaceName: formattedWorkspaceName,
47764
+ date,
47765
+ shift,
47766
+ totalOutput: workspace?.total_actions,
47767
+ className: "h-[calc(100vh-10rem)]"
46897
47768
  }
46898
- }
46899
- ),
46900
- /* @__PURE__ */ jsx(
46901
- EncouragementOverlay,
46902
- {
46903
- isVisible: showEncouragement,
46904
- onClose: () => {
46905
- setShowEncouragement(false);
46906
- setCurrentMiss(null);
46907
- },
46908
- targetValue: currentMiss?.targetValue || 0,
46909
- actualValue: currentMiss?.actualValue || 0,
46910
- metricName: currentMiss?.metricName || "Target"
46911
- }
46912
- )
46913
- ]
47769
+ ) })
47770
+ ] })
47771
+ ] })
46914
47772
  }
46915
47773
  );
46916
47774
  };
@@ -48025,21 +48883,36 @@ var LineAssignmentDropdown = ({
48025
48883
  const [isOpen, setIsOpen] = useState(false);
48026
48884
  const [selectedIds, setSelectedIds] = useState(currentLineIds);
48027
48885
  const [isSaving, setIsSaving] = useState(false);
48886
+ const [position, setPosition] = useState({ top: 0, left: 0, width: 0 });
48887
+ const buttonRef = useRef(null);
48028
48888
  const dropdownRef = useRef(null);
48029
48889
  useEffect(() => {
48030
48890
  setSelectedIds(currentLineIds);
48031
48891
  }, [currentLineIds]);
48032
48892
  useEffect(() => {
48033
- console.log("[LineAssignmentDropdown] Available lines updated:", {
48034
- userId,
48035
- count: availableLines.length,
48036
- lines: availableLines,
48037
- hasCompanyId: availableLines.every((l) => l.company_id)
48038
- });
48039
- }, [availableLines, userId]);
48893
+ const updatePosition = () => {
48894
+ if (isOpen && buttonRef.current) {
48895
+ const rect = buttonRef.current.getBoundingClientRect();
48896
+ setPosition({
48897
+ top: rect.bottom,
48898
+ left: rect.left,
48899
+ width: rect.width
48900
+ });
48901
+ }
48902
+ };
48903
+ if (isOpen) {
48904
+ updatePosition();
48905
+ window.addEventListener("scroll", updatePosition, true);
48906
+ window.addEventListener("resize", updatePosition);
48907
+ }
48908
+ return () => {
48909
+ window.removeEventListener("scroll", updatePosition, true);
48910
+ window.removeEventListener("resize", updatePosition);
48911
+ };
48912
+ }, [isOpen]);
48040
48913
  useEffect(() => {
48041
48914
  const handleClickOutside = (event) => {
48042
- if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
48915
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target) && buttonRef.current && !buttonRef.current.contains(event.target)) {
48043
48916
  setIsOpen(false);
48044
48917
  setSelectedIds(currentLineIds);
48045
48918
  }
@@ -48105,94 +48978,106 @@ var LineAssignmentDropdown = ({
48105
48978
  if (!canEdit) {
48106
48979
  return /* @__PURE__ */ jsx("div", { className: "text-sm", children: getDisplayText() });
48107
48980
  }
48108
- return /* @__PURE__ */ jsxs("div", { className: "relative", ref: dropdownRef, children: [
48981
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
48109
48982
  /* @__PURE__ */ jsxs(
48110
48983
  "button",
48111
48984
  {
48985
+ ref: buttonRef,
48112
48986
  onClick: () => setIsOpen(!isOpen),
48113
48987
  className: cn(
48114
- "flex items-center gap-2 px-3 py-1.5 text-sm border rounded-lg transition-colors",
48988
+ "flex items-center gap-2 px-3 py-2 text-sm border rounded-lg transition-colors min-w-[200px]",
48115
48989
  currentLineIds.length === 0 ? "border-blue-300 bg-blue-50 hover:bg-blue-100" : "border-gray-300 bg-white hover:bg-gray-50"
48116
48990
  ),
48117
48991
  children: [
48118
48992
  /* @__PURE__ */ jsx("span", { className: "flex-1 text-left", children: getDisplayText() }),
48119
48993
  /* @__PURE__ */ jsx(ChevronDown, { className: cn(
48120
- "w-4 h-4 text-gray-400 transition-transform",
48994
+ "w-4 h-4 text-gray-400 transition-transform flex-shrink-0",
48121
48995
  isOpen && "rotate-180"
48122
48996
  ) })
48123
48997
  ]
48124
48998
  }
48125
48999
  ),
48126
- isOpen && /* @__PURE__ */ jsxs("div", { className: "absolute z-[10000] mt-2 w-72 bg-white rounded-lg shadow-lg border border-gray-200 left-0", children: [
48127
- /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 border-b border-gray-200", children: [
48128
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
48129
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Assign Lines" }),
48130
- /* @__PURE__ */ jsx(
48131
- "button",
48132
- {
48133
- onClick: handleCancel,
48134
- className: "text-gray-400 hover:text-gray-600",
48135
- children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
48136
- }
48137
- )
48138
- ] }),
48139
- /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1", children: "Select one or more lines to assign" })
48140
- ] }),
48141
- /* @__PURE__ */ jsx("div", { className: "max-h-64 overflow-y-auto", children: availableLines.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "px-4 py-8 text-center", children: [
48142
- /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mb-2", children: "No lines available" }),
48143
- /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-400", children: "Check console (F12) for filtering details" })
48144
- ] }) : /* @__PURE__ */ jsx("div", { className: "py-2", children: availableLines.map((line) => /* @__PURE__ */ jsxs(
48145
- "label",
48146
- {
48147
- className: "flex items-center gap-3 px-4 py-2.5 hover:bg-gray-50 cursor-pointer transition-colors",
48148
- children: [
48149
- /* @__PURE__ */ jsx(
48150
- "input",
48151
- {
48152
- type: "checkbox",
48153
- checked: selectedIds.includes(line.id),
48154
- onChange: () => handleToggleLine(line.id),
48155
- className: "h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
48156
- }
48157
- ),
48158
- /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-900", children: line.line_name }) }),
48159
- selectedIds.includes(line.id) && /* @__PURE__ */ jsx(Check, { className: "w-4 h-4 text-blue-600" })
48160
- ]
48161
- },
48162
- line.id
48163
- )) }) }),
48164
- /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 border-t border-gray-200 bg-gray-50 flex items-center justify-between", children: [
48165
- /* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-600", children: [
48166
- selectedIds.length,
48167
- " selected"
48168
- ] }),
48169
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
48170
- /* @__PURE__ */ jsx(
48171
- "button",
48172
- {
48173
- onClick: handleCancel,
48174
- className: "px-3 py-1.5 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors",
48175
- children: "Cancel"
48176
- }
48177
- ),
48178
- /* @__PURE__ */ jsx(
48179
- "button",
48180
- {
48181
- onClick: handleSave,
48182
- disabled: !hasChanges || isSaving,
48183
- className: "px-3 py-1.5 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
48184
- children: isSaving ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
48185
- /* @__PURE__ */ jsxs("svg", { className: "animate-spin h-3 w-3", viewBox: "0 0 24 24", children: [
48186
- /* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", fill: "none" }),
48187
- /* @__PURE__ */ jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
49000
+ isOpen && createPortal(
49001
+ /* @__PURE__ */ jsxs(Fragment, { children: [
49002
+ /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-[9998]" }),
49003
+ /* @__PURE__ */ jsxs(
49004
+ "div",
49005
+ {
49006
+ ref: dropdownRef,
49007
+ className: "fixed z-[9999] bg-white rounded-lg shadow-2xl border border-gray-200",
49008
+ style: {
49009
+ top: `${position.top + 4}px`,
49010
+ left: `${position.left}px`,
49011
+ minWidth: `${Math.max(position.width, 300)}px`,
49012
+ maxWidth: "400px",
49013
+ maxHeight: "calc(100vh - 100px)"
49014
+ },
49015
+ children: [
49016
+ /* @__PURE__ */ jsx("div", { className: "px-4 py-3 border-b border-gray-200 bg-gray-50", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
49017
+ /* @__PURE__ */ jsxs("div", { children: [
49018
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Assign Lines" }),
49019
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-0.5", children: "Select one or more lines" })
48188
49020
  ] }),
48189
- "Saving..."
48190
- ] }) : "Save"
48191
- }
48192
- )
48193
- ] })
48194
- ] })
48195
- ] })
49021
+ /* @__PURE__ */ jsx(
49022
+ "button",
49023
+ {
49024
+ onClick: handleCancel,
49025
+ className: "text-gray-400 hover:text-gray-600 transition-colors",
49026
+ children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
49027
+ }
49028
+ )
49029
+ ] }) }),
49030
+ /* @__PURE__ */ jsx("div", { className: "max-h-80 overflow-y-auto", children: availableLines.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-4 py-8 text-center", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: "No lines available" }) }) : /* @__PURE__ */ jsx("div", { className: "py-1", children: availableLines.map((line) => /* @__PURE__ */ jsxs(
49031
+ "label",
49032
+ {
49033
+ className: "flex items-center gap-3 px-4 py-2.5 hover:bg-gray-50 cursor-pointer transition-colors",
49034
+ children: [
49035
+ /* @__PURE__ */ jsx(
49036
+ "input",
49037
+ {
49038
+ type: "checkbox",
49039
+ checked: selectedIds.includes(line.id),
49040
+ onChange: () => handleToggleLine(line.id),
49041
+ className: "h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
49042
+ }
49043
+ ),
49044
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-900 truncate", children: line.line_name }) }),
49045
+ selectedIds.includes(line.id) && /* @__PURE__ */ jsx(Check, { className: "w-4 h-4 text-blue-600 flex-shrink-0" })
49046
+ ]
49047
+ },
49048
+ line.id
49049
+ )) }) }),
49050
+ /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 border-t border-gray-200 bg-gray-50 flex items-center justify-between", children: [
49051
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-600", children: [
49052
+ selectedIds.length,
49053
+ " selected"
49054
+ ] }),
49055
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
49056
+ /* @__PURE__ */ jsx(
49057
+ "button",
49058
+ {
49059
+ onClick: handleCancel,
49060
+ className: "px-3 py-1.5 text-xs font-medium text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50 transition-colors",
49061
+ children: "Cancel"
49062
+ }
49063
+ ),
49064
+ /* @__PURE__ */ jsx(
49065
+ "button",
49066
+ {
49067
+ onClick: handleSave,
49068
+ disabled: !hasChanges || isSaving,
49069
+ className: "px-3 py-1.5 text-xs font-medium text-white bg-blue-600 rounded hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
49070
+ children: isSaving ? "Saving..." : "Save"
49071
+ }
49072
+ )
49073
+ ] })
49074
+ ] })
49075
+ ]
49076
+ }
49077
+ )
49078
+ ] }),
49079
+ document.body
49080
+ )
48196
49081
  ] });
48197
49082
  };
48198
49083
  var FactoryAssignmentDropdown = ({
@@ -48205,13 +49090,36 @@ var FactoryAssignmentDropdown = ({
48205
49090
  const [isOpen, setIsOpen] = useState(false);
48206
49091
  const [selectedIds, setSelectedIds] = useState(currentFactoryIds);
48207
49092
  const [isSaving, setIsSaving] = useState(false);
49093
+ const [position, setPosition] = useState({ top: 0, left: 0, width: 0 });
49094
+ const buttonRef = useRef(null);
48208
49095
  const dropdownRef = useRef(null);
48209
49096
  useEffect(() => {
48210
49097
  setSelectedIds(currentFactoryIds);
48211
49098
  }, [currentFactoryIds]);
49099
+ useEffect(() => {
49100
+ const updatePosition = () => {
49101
+ if (isOpen && buttonRef.current) {
49102
+ const rect = buttonRef.current.getBoundingClientRect();
49103
+ setPosition({
49104
+ top: rect.bottom,
49105
+ left: rect.left,
49106
+ width: rect.width
49107
+ });
49108
+ }
49109
+ };
49110
+ if (isOpen) {
49111
+ updatePosition();
49112
+ window.addEventListener("scroll", updatePosition, true);
49113
+ window.addEventListener("resize", updatePosition);
49114
+ }
49115
+ return () => {
49116
+ window.removeEventListener("scroll", updatePosition, true);
49117
+ window.removeEventListener("resize", updatePosition);
49118
+ };
49119
+ }, [isOpen]);
48212
49120
  useEffect(() => {
48213
49121
  const handleClickOutside = (event) => {
48214
- if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
49122
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target) && buttonRef.current && !buttonRef.current.contains(event.target)) {
48215
49123
  setIsOpen(false);
48216
49124
  setSelectedIds(currentFactoryIds);
48217
49125
  }
@@ -48277,91 +49185,106 @@ var FactoryAssignmentDropdown = ({
48277
49185
  if (!canEdit) {
48278
49186
  return /* @__PURE__ */ jsx("div", { className: "text-sm", children: getDisplayText() });
48279
49187
  }
48280
- return /* @__PURE__ */ jsxs("div", { className: "relative", ref: dropdownRef, children: [
49188
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
48281
49189
  /* @__PURE__ */ jsxs(
48282
49190
  "button",
48283
49191
  {
49192
+ ref: buttonRef,
48284
49193
  onClick: () => setIsOpen(!isOpen),
48285
49194
  className: cn(
48286
- "flex items-center gap-2 px-3 py-1.5 text-sm border rounded-lg transition-colors",
49195
+ "flex items-center gap-2 px-3 py-2 text-sm border rounded-lg transition-colors min-w-[200px]",
48287
49196
  currentFactoryIds.length === 0 ? "border-blue-300 bg-blue-50 hover:bg-blue-100" : "border-gray-300 bg-white hover:bg-gray-50"
48288
49197
  ),
48289
49198
  children: [
48290
49199
  /* @__PURE__ */ jsx("span", { className: "flex-1 text-left", children: getDisplayText() }),
48291
49200
  /* @__PURE__ */ jsx(ChevronDown, { className: cn(
48292
- "w-4 h-4 text-gray-400 transition-transform",
49201
+ "w-4 h-4 text-gray-400 transition-transform flex-shrink-0",
48293
49202
  isOpen && "rotate-180"
48294
49203
  ) })
48295
49204
  ]
48296
49205
  }
48297
49206
  ),
48298
- isOpen && /* @__PURE__ */ jsxs("div", { className: "absolute z-[10000] mt-2 w-72 bg-white rounded-lg shadow-lg border border-gray-200 left-0", children: [
48299
- /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 border-b border-gray-200", children: [
48300
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
48301
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Assign Factories" }),
48302
- /* @__PURE__ */ jsx(
48303
- "button",
48304
- {
48305
- onClick: handleCancel,
48306
- className: "text-gray-400 hover:text-gray-600",
48307
- children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
48308
- }
48309
- )
48310
- ] }),
48311
- /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1", children: "Select one or more factories to assign" })
48312
- ] }),
48313
- /* @__PURE__ */ jsx("div", { className: "max-h-64 overflow-y-auto", children: availableFactories.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-4 py-8 text-center text-sm text-gray-500", children: "No factories available" }) : /* @__PURE__ */ jsx("div", { className: "py-2", children: availableFactories.map((factory) => /* @__PURE__ */ jsxs(
48314
- "label",
48315
- {
48316
- className: "flex items-center gap-3 px-4 py-2.5 hover:bg-gray-50 cursor-pointer transition-colors",
48317
- children: [
48318
- /* @__PURE__ */ jsx(
48319
- "input",
48320
- {
48321
- type: "checkbox",
48322
- checked: selectedIds.includes(factory.id),
48323
- onChange: () => handleToggleFactory(factory.id),
48324
- className: "h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
48325
- }
48326
- ),
48327
- /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-900", children: factory.factory_name }) }),
48328
- selectedIds.includes(factory.id) && /* @__PURE__ */ jsx(Check, { className: "w-4 h-4 text-blue-600" })
48329
- ]
48330
- },
48331
- factory.id
48332
- )) }) }),
48333
- /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 border-t border-gray-200 bg-gray-50 flex items-center justify-between", children: [
48334
- /* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-600", children: [
48335
- selectedIds.length,
48336
- " selected"
48337
- ] }),
48338
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
48339
- /* @__PURE__ */ jsx(
48340
- "button",
48341
- {
48342
- onClick: handleCancel,
48343
- className: "px-3 py-1.5 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors",
48344
- children: "Cancel"
48345
- }
48346
- ),
48347
- /* @__PURE__ */ jsx(
48348
- "button",
48349
- {
48350
- onClick: handleSave,
48351
- disabled: !hasChanges || isSaving,
48352
- className: "px-3 py-1.5 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
48353
- children: isSaving ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
48354
- /* @__PURE__ */ jsxs("svg", { className: "animate-spin h-3 w-3", viewBox: "0 0 24 24", children: [
48355
- /* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", fill: "none" }),
48356
- /* @__PURE__ */ jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
49207
+ isOpen && createPortal(
49208
+ /* @__PURE__ */ jsxs(Fragment, { children: [
49209
+ /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-[9998]" }),
49210
+ /* @__PURE__ */ jsxs(
49211
+ "div",
49212
+ {
49213
+ ref: dropdownRef,
49214
+ className: "fixed z-[9999] bg-white rounded-lg shadow-2xl border border-gray-200",
49215
+ style: {
49216
+ top: `${position.top + 4}px`,
49217
+ left: `${position.left}px`,
49218
+ minWidth: `${Math.max(position.width, 300)}px`,
49219
+ maxWidth: "400px",
49220
+ maxHeight: "calc(100vh - 100px)"
49221
+ },
49222
+ children: [
49223
+ /* @__PURE__ */ jsx("div", { className: "px-4 py-3 border-b border-gray-200 bg-gray-50", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
49224
+ /* @__PURE__ */ jsxs("div", { children: [
49225
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Assign Factories" }),
49226
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-0.5", children: "Select one or more factories" })
48357
49227
  ] }),
48358
- "Saving..."
48359
- ] }) : "Save"
48360
- }
48361
- )
48362
- ] })
48363
- ] })
48364
- ] })
49228
+ /* @__PURE__ */ jsx(
49229
+ "button",
49230
+ {
49231
+ onClick: handleCancel,
49232
+ className: "text-gray-400 hover:text-gray-600 transition-colors",
49233
+ children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
49234
+ }
49235
+ )
49236
+ ] }) }),
49237
+ /* @__PURE__ */ jsx("div", { className: "max-h-80 overflow-y-auto", children: availableFactories.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-4 py-8 text-center", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: "No factories available" }) }) : /* @__PURE__ */ jsx("div", { className: "py-1", children: availableFactories.map((factory) => /* @__PURE__ */ jsxs(
49238
+ "label",
49239
+ {
49240
+ className: "flex items-center gap-3 px-4 py-2.5 hover:bg-gray-50 cursor-pointer transition-colors",
49241
+ children: [
49242
+ /* @__PURE__ */ jsx(
49243
+ "input",
49244
+ {
49245
+ type: "checkbox",
49246
+ checked: selectedIds.includes(factory.id),
49247
+ onChange: () => handleToggleFactory(factory.id),
49248
+ className: "h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
49249
+ }
49250
+ ),
49251
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-900 truncate", children: factory.factory_name }) }),
49252
+ selectedIds.includes(factory.id) && /* @__PURE__ */ jsx(Check, { className: "w-4 h-4 text-blue-600 flex-shrink-0" })
49253
+ ]
49254
+ },
49255
+ factory.id
49256
+ )) }) }),
49257
+ /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 border-t border-gray-200 bg-gray-50 flex items-center justify-between", children: [
49258
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-600", children: [
49259
+ selectedIds.length,
49260
+ " selected"
49261
+ ] }),
49262
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
49263
+ /* @__PURE__ */ jsx(
49264
+ "button",
49265
+ {
49266
+ onClick: handleCancel,
49267
+ className: "px-3 py-1.5 text-xs font-medium text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50 transition-colors",
49268
+ children: "Cancel"
49269
+ }
49270
+ ),
49271
+ /* @__PURE__ */ jsx(
49272
+ "button",
49273
+ {
49274
+ onClick: handleSave,
49275
+ disabled: !hasChanges || isSaving,
49276
+ className: "px-3 py-1.5 text-xs font-medium text-white bg-blue-600 rounded hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
49277
+ children: isSaving ? "Saving..." : "Save"
49278
+ }
49279
+ )
49280
+ ] })
49281
+ ] })
49282
+ ]
49283
+ }
49284
+ )
49285
+ ] }),
49286
+ document.body
49287
+ )
48365
49288
  ] });
48366
49289
  };
48367
49290
  var UserManagementTable = ({
@@ -48513,7 +49436,7 @@ var UserManagementTable = ({
48513
49436
  }
48514
49437
  )
48515
49438
  ] }),
48516
- /* @__PURE__ */ jsx("div", { className: "bg-white rounded-lg border border-gray-200 overflow-x-auto", children: /* @__PURE__ */ jsx("div", { className: "overflow-visible relative", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-gray-200", children: [
49439
+ /* @__PURE__ */ jsx("div", { className: "bg-white rounded-lg border border-gray-200", children: /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-gray-200", children: [
48517
49440
  /* @__PURE__ */ jsx("thead", { className: "bg-gray-50", children: /* @__PURE__ */ jsxs("tr", { children: [
48518
49441
  /* @__PURE__ */ jsx(
48519
49442
  "th",
@@ -48582,7 +49505,7 @@ var UserManagementTable = ({
48582
49505
  ] })
48583
49506
  ] }) }),
48584
49507
  /* @__PURE__ */ jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: /* @__PURE__ */ jsx(RoleBadge, { role: user.role_level, size: "sm" }) }),
48585
- /* @__PURE__ */ jsx("td", { className: "px-6 py-4 relative overflow-visible z-10", children: user.role_level === "supervisor" ? /* @__PURE__ */ jsx(
49508
+ /* @__PURE__ */ jsx("td", { className: "px-6 py-4", children: user.role_level === "supervisor" ? /* @__PURE__ */ jsx(
48586
49509
  LineAssignmentDropdown,
48587
49510
  {
48588
49511
  userId: user.user_id,
@@ -48624,7 +49547,7 @@ var UserManagementTable = ({
48624
49547
  }
48625
49548
  ) : /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-900", children: formatAssignments(user) }) }),
48626
49549
  /* @__PURE__ */ jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: formatDate(user.created_at) }) }),
48627
- /* @__PURE__ */ jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right relative overflow-visible", children: hasActions && /* @__PURE__ */ jsxs("div", { className: "relative overflow-visible", children: [
49550
+ /* @__PURE__ */ jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right", children: hasActions && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
48628
49551
  /* @__PURE__ */ jsx(
48629
49552
  "button",
48630
49553
  {
@@ -48807,6 +49730,34 @@ var InviteUserDialog = ({
48807
49730
  throw new Error(data.error);
48808
49731
  }
48809
49732
  toast.success(data?.message || "User added successfully!");
49733
+ try {
49734
+ const dashboardUrl = typeof window !== "undefined" ? window.location.origin : "";
49735
+ if (dashboardUrl) {
49736
+ console.log("Sending welcome email to:", email.trim());
49737
+ const { data: emailData, error: emailError } = await supabase.functions.invoke("hyper-service", {
49738
+ body: {
49739
+ action: "send-welcome-email",
49740
+ email: email.trim(),
49741
+ company_id: companyId,
49742
+ dashboard_url: dashboardUrl
49743
+ }
49744
+ });
49745
+ if (emailError) {
49746
+ console.error("Failed to send welcome email:", emailError);
49747
+ toast.warning("User added successfully, but welcome email could not be sent");
49748
+ } else if (emailData?.success) {
49749
+ console.log("Welcome email sent successfully:", emailData);
49750
+ toast.success("User added and welcome email sent!");
49751
+ } else {
49752
+ console.log("Welcome email response:", emailData);
49753
+ }
49754
+ } else {
49755
+ console.warn("Dashboard URL not available, skipping welcome email");
49756
+ }
49757
+ } catch (emailErr) {
49758
+ console.error("Error sending welcome email:", emailErr);
49759
+ toast.info("User added successfully (email service unavailable)");
49760
+ }
48810
49761
  onInviteSent?.();
48811
49762
  onClose();
48812
49763
  } catch (err) {
@@ -50599,7 +51550,7 @@ var S3Service = class {
50599
51550
  };
50600
51551
 
50601
51552
  // src/lib/api/optifye-agent.ts
50602
- var OPTIFYE_API_URL = "https://optifye-agent-production.up.railway.app";
51553
+ var OPTIFYE_API_URL = process.env.NEXT_PUBLIC_AGNO_URL || "https://fastapi-production-111f9.up.railway.app";
50603
51554
  var OptifyeAgentClient = class {
50604
51555
  constructor(apiUrl = OPTIFYE_API_URL) {
50605
51556
  this.apiUrl = apiUrl;
@@ -50986,4 +51937,4 @@ function shuffleArray(array) {
50986
51937
  return shuffled;
50987
51938
  }
50988
51939
 
50989
- 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, AxelNotificationPopup, 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, ClipFilterProvider, CompactWorkspaceHealthCard, CongratulationsOverlay, 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_MAP_VIEW_CONFIG, DEFAULT_SHIFT_CONFIG, 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, EmptyStateMessage, EncouragementOverlay, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, InlineEditableText, InteractiveOnboardingTour, InvitationService, 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, 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, MainLayout, MapGridView, MetricCard_default as MetricCard, MinimalOnboardingPopup, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, S3ClipsSupabaseService as S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SignupWithInvitation, 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, UserManagementService, UserService, 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, apiUtils, authCoreService, authOTPService, authRateLimitService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createInvitationService, createLinesService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isLegacyConfiguration, isPrefetchError, isSafari, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, optifyeAgentClient, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useAccessControl, useActiveBreaks, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, userService, videoPrefetchManager, videoPreloader, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };
51940
+ 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, 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, ClipFilterProvider, CompactWorkspaceHealthCard, CongratulationsOverlay, 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_MAP_VIEW_CONFIG, DEFAULT_SHIFT_CONFIG, 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, EmptyStateMessage, EncouragementOverlay, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, InlineEditableText, InteractiveOnboardingTour, InvitationService, 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, 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, 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, S3ClipsSupabaseService as S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, 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, UserManagementService, UserService, 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, apiUtils, authCoreService, authOTPService, authRateLimitService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createInvitationService, createLinesService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getNextUpdateInterval, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isLegacyConfiguration, isPrefetchError, isSafari, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, optifyeAgentClient, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useAccessControl, useActiveBreaks, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthStatus, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, userService, videoPrefetchManager, videoPreloader, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };