@optifye/dashboard-core 6.9.0 → 6.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2793,60 +2793,135 @@ var authCoreService = {
2793
2793
  }
2794
2794
  };
2795
2795
 
2796
+ // src/lib/utils/apiClient.ts
2797
+ var ApiClient = class {
2798
+ // 5 minutes
2799
+ /**
2800
+ * Fetch with timeout, retry, and error handling
2801
+ *
2802
+ * @param url - URL to fetch
2803
+ * @param options - Fetch options plus ApiClient options
2804
+ * @returns Promise resolving to parsed JSON data
2805
+ */
2806
+ static async fetch(url, options = {}) {
2807
+ const {
2808
+ timeout = this.DEFAULT_TIMEOUT,
2809
+ retries = 1,
2810
+ retryDelay = 1e3,
2811
+ silentErrors = true,
2812
+ fallbackData = null,
2813
+ ...fetchOptions
2814
+ } = options;
2815
+ let lastError = null;
2816
+ for (let attempt = 0; attempt <= retries; attempt++) {
2817
+ const controller = new AbortController();
2818
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
2819
+ try {
2820
+ console.log(`[ApiClient] Request ${attempt > 0 ? `(retry ${attempt})` : ""}: ${url}`);
2821
+ const response = await fetch(url, {
2822
+ ...fetchOptions,
2823
+ signal: controller.signal
2824
+ });
2825
+ clearTimeout(timeoutId);
2826
+ if (!response.ok) {
2827
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
2828
+ }
2829
+ const data = await response.json();
2830
+ console.log(`[ApiClient] Success: ${url}`);
2831
+ return data;
2832
+ } catch (error) {
2833
+ clearTimeout(timeoutId);
2834
+ lastError = error;
2835
+ console.error(`[ApiClient] Error (attempt ${attempt + 1}/${retries + 1}):`, {
2836
+ url,
2837
+ error: error.message,
2838
+ isTimeout: error.name === "AbortError",
2839
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2840
+ });
2841
+ if (attempt < retries) {
2842
+ console.log(`[ApiClient] Retrying in ${retryDelay}ms...`);
2843
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
2844
+ continue;
2845
+ }
2846
+ if (silentErrors) {
2847
+ console.warn("[ApiClient] All retries exhausted, returning fallback data");
2848
+ return fallbackData;
2849
+ } else {
2850
+ throw lastError;
2851
+ }
2852
+ }
2853
+ }
2854
+ return fallbackData;
2855
+ }
2856
+ };
2857
+ ApiClient.DEFAULT_TIMEOUT = 3e5;
2858
+
2796
2859
  // src/lib/services/authService.ts
2797
2860
  var AuthService = class {
2798
2861
  /**
2799
- * Fetch enriched user session from backend
2862
+ * Fetch enriched user session from backend with 5-minute timeout
2800
2863
  * This is your SINGLE call to get ALL auth data
2801
- *
2864
+ *
2802
2865
  * @param accessToken - JWT token from Supabase
2803
2866
  * @returns Complete user session with profile, permissions, and assignments
2804
2867
  */
2805
2868
  static async getSession(accessToken) {
2806
2869
  console.log("[AuthService] Fetching session from backend...");
2807
- const response = await fetch(`${this.backendUrl}/api/auth/session`, {
2808
- headers: {
2809
- "Authorization": `Bearer ${accessToken}`,
2810
- "Content-Type": "application/json"
2811
- }
2812
- });
2813
- if (!response.ok) {
2814
- const errorText = await response.text();
2815
- console.error("[AuthService] Session fetch failed:", response.status, errorText);
2816
- throw new Error(`Failed to fetch session: ${response.statusText}`);
2870
+ try {
2871
+ const data = await ApiClient.fetch(
2872
+ `${this.backendUrl}/api/auth/session`,
2873
+ {
2874
+ headers: {
2875
+ "Authorization": `Bearer ${accessToken}`,
2876
+ "Content-Type": "application/json"
2877
+ },
2878
+ timeout: 3e5,
2879
+ // 5 minutes
2880
+ retries: 1,
2881
+ silentErrors: false
2882
+ // We want to know about auth errors
2883
+ }
2884
+ );
2885
+ console.log("[AuthService] Session loaded:", {
2886
+ user_id: data.user_id,
2887
+ role: data.role,
2888
+ company_id: data.company_id,
2889
+ has_profile: !!data.profile,
2890
+ has_permissions: !!data.permissions
2891
+ });
2892
+ return data;
2893
+ } catch (error) {
2894
+ console.error("[AuthService] Session fetch failed:", error);
2895
+ throw error;
2817
2896
  }
2818
- const data = await response.json();
2819
- console.log("[AuthService] Session loaded:", {
2820
- user_id: data.user_id,
2821
- role: data.role,
2822
- company_id: data.company_id,
2823
- has_profile: !!data.profile,
2824
- has_permissions: !!data.permissions
2825
- });
2826
- return data;
2827
2897
  }
2828
2898
  /**
2829
- * Quick validation check without full profile fetch
2899
+ * Quick validation check without full profile fetch with timeout
2830
2900
  * Use this for lightweight auth checks
2831
- *
2901
+ *
2832
2902
  * @param accessToken - JWT token from Supabase
2833
2903
  * @returns Boolean indicating if session is valid
2834
2904
  */
2835
2905
  static async validateSession(accessToken) {
2836
2906
  try {
2837
2907
  console.log("[AuthService] Validating session...");
2838
- const response = await fetch(`${this.backendUrl}/api/auth/validate`, {
2839
- method: "POST",
2840
- headers: {
2841
- "Authorization": `Bearer ${accessToken}`,
2842
- "Content-Type": "application/json"
2908
+ const data = await ApiClient.fetch(
2909
+ `${this.backendUrl}/api/auth/validate`,
2910
+ {
2911
+ method: "POST",
2912
+ headers: {
2913
+ "Authorization": `Bearer ${accessToken}`,
2914
+ "Content-Type": "application/json"
2915
+ },
2916
+ timeout: 3e5,
2917
+ // 5 minutes
2918
+ retries: 2,
2919
+ // More retries for validation
2920
+ silentErrors: true,
2921
+ fallbackData: { valid: false, user_id: "", email: "" }
2922
+ // Safe default
2843
2923
  }
2844
- });
2845
- if (!response.ok) {
2846
- console.log("[AuthService] Session validation failed:", response.status);
2847
- return false;
2848
- }
2849
- const data = await response.json();
2924
+ );
2850
2925
  const isValid3 = data.valid === true;
2851
2926
  console.log("[AuthService] Session validation result:", isValid3);
2852
2927
  return isValid3;
@@ -2856,26 +2931,27 @@ var AuthService = class {
2856
2931
  }
2857
2932
  }
2858
2933
  /**
2859
- * Get just permissions (lightweight call)
2934
+ * Get just permissions (lightweight call) with timeout
2860
2935
  * Faster than full session fetch
2861
- *
2936
+ *
2862
2937
  * @param accessToken - JWT token from Supabase
2863
2938
  * @returns User permissions and role
2864
2939
  */
2865
2940
  static async getPermissions(accessToken) {
2866
2941
  console.log("[AuthService] Fetching permissions...");
2867
- const response = await fetch(`${this.backendUrl}/api/auth/permissions`, {
2868
- headers: {
2869
- "Authorization": `Bearer ${accessToken}`,
2870
- "Content-Type": "application/json"
2942
+ const data = await ApiClient.fetch(
2943
+ `${this.backendUrl}/api/auth/permissions`,
2944
+ {
2945
+ headers: {
2946
+ "Authorization": `Bearer ${accessToken}`,
2947
+ "Content-Type": "application/json"
2948
+ },
2949
+ timeout: 3e5,
2950
+ // 5 minutes
2951
+ retries: 1,
2952
+ silentErrors: false
2871
2953
  }
2872
- });
2873
- if (!response.ok) {
2874
- const errorText = await response.text();
2875
- console.error("[AuthService] Permissions fetch failed:", response.status, errorText);
2876
- throw new Error(`Failed to fetch permissions: ${response.statusText}`);
2877
- }
2878
- const data = await response.json();
2954
+ );
2879
2955
  console.log("[AuthService] Permissions loaded for role:", data.role);
2880
2956
  return data;
2881
2957
  }
@@ -5807,6 +5883,67 @@ var UserManagementService = class {
5807
5883
  var createUserManagementService = (supabase) => {
5808
5884
  return new UserManagementService(supabase);
5809
5885
  };
5886
+ var SupabaseContext = React23.createContext(void 0);
5887
+ var SupabaseProvider = ({ client, children }) => {
5888
+ _setSupabaseInstance(client);
5889
+ React23.useEffect(() => {
5890
+ _setSupabaseInstance(client);
5891
+ }, [client]);
5892
+ const contextValue = React23.useMemo(() => ({ supabase: client }), [client]);
5893
+ return /* @__PURE__ */ jsxRuntime.jsx(SupabaseContext.Provider, { value: contextValue, children });
5894
+ };
5895
+ var useSupabase = () => {
5896
+ const context = React23.useContext(SupabaseContext);
5897
+ if (context === void 0) {
5898
+ throw new Error("useSupabase must be used within a SupabaseProvider.");
5899
+ }
5900
+ return context.supabase;
5901
+ };
5902
+
5903
+ // src/lib/hooks/useSessionKeepAlive.ts
5904
+ var useSessionKeepAlive = (options = {}) => {
5905
+ const {
5906
+ enabled = true,
5907
+ intervalMs = 3e5
5908
+ // 5 minutes
5909
+ } = options;
5910
+ const supabase = useSupabase();
5911
+ const intervalRef = React23.useRef(null);
5912
+ React23.useEffect(() => {
5913
+ if (!enabled || !supabase) {
5914
+ return;
5915
+ }
5916
+ const keepAlive = async () => {
5917
+ try {
5918
+ const {
5919
+ data: { session }
5920
+ } = await supabase.auth.getSession();
5921
+ if (!session) {
5922
+ console.log("[SessionKeepAlive] No session, skipping keep-alive");
5923
+ return;
5924
+ }
5925
+ console.log("[SessionKeepAlive] Pinging backend to keep session alive");
5926
+ const isValid3 = await AuthService.validateSession(session.access_token);
5927
+ if (!isValid3) {
5928
+ console.warn("[SessionKeepAlive] Session validation failed");
5929
+ } else {
5930
+ console.log("[SessionKeepAlive] Session still valid");
5931
+ }
5932
+ } catch (error) {
5933
+ console.error("[SessionKeepAlive] Error during keep-alive:", error);
5934
+ }
5935
+ };
5936
+ const initialTimeout = setTimeout(keepAlive, 1e3);
5937
+ intervalRef.current = setInterval(keepAlive, intervalMs);
5938
+ return () => {
5939
+ clearTimeout(initialTimeout);
5940
+ if (intervalRef.current) {
5941
+ clearInterval(intervalRef.current);
5942
+ intervalRef.current = null;
5943
+ }
5944
+ };
5945
+ }, [enabled, intervalMs, supabase]);
5946
+ };
5810
5947
  var AuthContext = React23.createContext({
5811
5948
  session: null,
5812
5949
  user: null,
@@ -5833,14 +5970,17 @@ var AuthProvider = ({ children }) => {
5833
5970
  const router$1 = router.useRouter();
5834
5971
  const isFetchingRef = React23.useRef(false);
5835
5972
  const lastProcessedSessionRef = React23.useRef(null);
5836
- const fetchSession = React23.useCallback(async (supabaseSession) => {
5973
+ const hasAuthenticatedRef = React23.useRef(false);
5974
+ const fetchSession = React23.useCallback(async (supabaseSession, isReauth = false) => {
5837
5975
  if (isFetchingRef.current) {
5838
5976
  console.log("[AuthContext] Already fetching, skipping duplicate request");
5839
5977
  return;
5840
5978
  }
5841
- console.log("[AuthContext] Fetching session from backend");
5979
+ console.log("[AuthContext] Fetching session from backend", { isReauth });
5842
5980
  isFetchingRef.current = true;
5843
- setLoading(true);
5981
+ if (!isReauth) {
5982
+ setLoading(true);
5983
+ }
5844
5984
  try {
5845
5985
  const enrichedUser = await AuthService.getSession(supabaseSession.access_token);
5846
5986
  const authUser = AuthService.toAuthUser(enrichedUser);
@@ -5848,6 +5988,7 @@ var AuthProvider = ({ children }) => {
5848
5988
  setSession(supabaseSession);
5849
5989
  setError(null);
5850
5990
  lastProcessedSessionRef.current = supabaseSession.access_token.substring(0, 20);
5991
+ hasAuthenticatedRef.current = true;
5851
5992
  if (!authUser.first_login_completed) {
5852
5993
  setShowOnboarding(true);
5853
5994
  }
@@ -5867,6 +6008,15 @@ var AuthProvider = ({ children }) => {
5867
6008
  });
5868
6009
  } catch (err) {
5869
6010
  console.error("[AuthContext] Failed to fetch session:", err);
6011
+ if (err.message?.includes("JWT expired") || err.message?.includes("invalid token") || err.message?.includes("token") || err.message?.includes("401")) {
6012
+ console.log("[AuthContext] Token expired or invalid, clearing session and redirecting to login");
6013
+ setUser(null);
6014
+ setSession(null);
6015
+ setError(new Error("Your session has expired. Please log in again."));
6016
+ await supabase.auth.signOut();
6017
+ router$1.replace("/login");
6018
+ return;
6019
+ }
5870
6020
  setError(err);
5871
6021
  setUser(null);
5872
6022
  if (err.message?.includes("profile")) {
@@ -5877,11 +6027,13 @@ var AuthProvider = ({ children }) => {
5877
6027
  setUser(basicUser);
5878
6028
  }
5879
6029
  } finally {
5880
- setLoading(false);
6030
+ if (!isReauth) {
6031
+ setLoading(false);
6032
+ }
5881
6033
  isFetchingRef.current = false;
5882
- console.log("[AuthContext] Loading set to false");
6034
+ console.log("[AuthContext] Loading set to false", { isReauth });
5883
6035
  }
5884
- }, []);
6036
+ }, [supabase, router$1]);
5885
6037
  const markFirstLoginCompleted = React23.useCallback(async () => {
5886
6038
  if (!user?.id || !supabase) return false;
5887
6039
  try {
@@ -5913,6 +6065,7 @@ var AuthProvider = ({ children }) => {
5913
6065
  setSession(null);
5914
6066
  setError(null);
5915
6067
  setShowOnboarding(false);
6068
+ hasAuthenticatedRef.current = false;
5916
6069
  router$1.push("/login");
5917
6070
  } catch (err) {
5918
6071
  console.error("[AuthContext] Sign out error:", err);
@@ -5921,6 +6074,48 @@ var AuthProvider = ({ children }) => {
5921
6074
  setLoading(false);
5922
6075
  }
5923
6076
  }, [supabase, router$1, authConfig]);
6077
+ useSessionKeepAlive({
6078
+ enabled: !!session,
6079
+ // Only when logged in
6080
+ intervalMs: 3e5
6081
+ // 5 minutes
6082
+ });
6083
+ React23.useEffect(() => {
6084
+ if (!session || !supabase) {
6085
+ return;
6086
+ }
6087
+ const monitorTokenExpiry = () => {
6088
+ const expiresAt = session.expires_at;
6089
+ if (!expiresAt) {
6090
+ console.warn("[AuthContext] Session has no expiry time");
6091
+ return;
6092
+ }
6093
+ const expiryTime = expiresAt * 1e3;
6094
+ const now2 = Date.now();
6095
+ const timeUntilExpiry = expiryTime - now2;
6096
+ const minutesUntilExpiry = Math.floor(timeUntilExpiry / 6e4);
6097
+ console.log(`[AuthContext] Token expires in ${minutesUntilExpiry} minutes`);
6098
+ if (minutesUntilExpiry < 5 && minutesUntilExpiry > 0) {
6099
+ console.warn("[AuthContext] Token expiring soon, attempting refresh...");
6100
+ supabase.auth.refreshSession().then(({ data, error: error2 }) => {
6101
+ if (error2) {
6102
+ console.error("[AuthContext] Token refresh failed:", error2);
6103
+ } else {
6104
+ console.log("[AuthContext] Token refreshed successfully");
6105
+ }
6106
+ });
6107
+ }
6108
+ if (timeUntilExpiry < 0) {
6109
+ console.error("[AuthContext] Token has expired, logging out");
6110
+ signOut();
6111
+ }
6112
+ };
6113
+ monitorTokenExpiry();
6114
+ const intervalId = setInterval(monitorTokenExpiry, 6e4);
6115
+ return () => {
6116
+ clearInterval(intervalId);
6117
+ };
6118
+ }, [session, supabase, signOut]);
5924
6119
  React23.useEffect(() => {
5925
6120
  if (!supabase) {
5926
6121
  console.log("[AuthContext] No Supabase client, skipping auth initialization");
@@ -5941,7 +6136,8 @@ var AuthProvider = ({ children }) => {
5941
6136
  }
5942
6137
  if (currentSession) {
5943
6138
  console.log("[AuthContext] Found existing session, fetching user data");
5944
- await fetchSession(currentSession);
6139
+ const isReauth = hasAuthenticatedRef.current;
6140
+ await fetchSession(currentSession, isReauth);
5945
6141
  } else {
5946
6142
  console.log("[AuthContext] No session found");
5947
6143
  setLoading(false);
@@ -5973,20 +6169,27 @@ var AuthProvider = ({ children }) => {
5973
6169
  }
5974
6170
  console.log("[AuthContext] Processing auth event, fetching session");
5975
6171
  lastProcessedSessionRef.current = sessionId;
5976
- await fetchSession(currentSession);
6172
+ const isReauth = hasAuthenticatedRef.current;
6173
+ await fetchSession(currentSession, isReauth);
5977
6174
  }
5978
6175
  } else if (event === "SIGNED_OUT") {
5979
6176
  console.log("[AuthContext] User signed out");
5980
6177
  lastProcessedSessionRef.current = null;
6178
+ hasAuthenticatedRef.current = false;
5981
6179
  setUser(null);
5982
6180
  setSession(null);
5983
6181
  setError(null);
5984
6182
  setShowOnboarding(false);
5985
6183
  setLoading(false);
5986
6184
  } else if (event === "TOKEN_REFRESHED") {
5987
- console.log("[AuthContext] Token refreshed");
6185
+ console.log("[AuthContext] Token refreshed automatically");
5988
6186
  if (currentSession) {
5989
6187
  setSession(currentSession);
6188
+ const expiresAt = currentSession.expires_at;
6189
+ if (expiresAt) {
6190
+ const minutesUntilExpiry = Math.floor((expiresAt * 1e3 - Date.now()) / 6e4);
6191
+ console.log(`[AuthContext] New token expires in ${minutesUntilExpiry} minutes`);
6192
+ }
5990
6193
  }
5991
6194
  }
5992
6195
  });
@@ -5994,7 +6197,7 @@ var AuthProvider = ({ children }) => {
5994
6197
  mounted = false;
5995
6198
  subscription?.unsubscribe();
5996
6199
  };
5997
- }, [supabase, fetchSession]);
6200
+ }, [supabase]);
5998
6201
  const value = {
5999
6202
  session,
6000
6203
  user,
@@ -6042,22 +6245,6 @@ function usePageOverride(key, Default) {
6042
6245
  function useOverrides() {
6043
6246
  return React23.useContext(DashboardOverridesContext);
6044
6247
  }
6045
- var SupabaseContext = React23.createContext(void 0);
6046
- var SupabaseProvider = ({ client, children }) => {
6047
- _setSupabaseInstance(client);
6048
- React23.useEffect(() => {
6049
- _setSupabaseInstance(client);
6050
- }, [client]);
6051
- const contextValue = React23.useMemo(() => ({ supabase: client }), [client]);
6052
- return /* @__PURE__ */ jsxRuntime.jsx(SupabaseContext.Provider, { value: contextValue, children });
6053
- };
6054
- var useSupabase = () => {
6055
- const context = React23.useContext(SupabaseContext);
6056
- if (context === void 0) {
6057
- throw new Error("useSupabase must be used within a SupabaseProvider.");
6058
- }
6059
- return context.supabase;
6060
- };
6061
6248
  var SubscriptionManagerContext = React23.createContext({
6062
6249
  subscriptionManager: null
6063
6250
  });
@@ -10537,6 +10724,158 @@ var useWorkspaceHealthById = (workspaceId, options) => {
10537
10724
  refetch: fetchWorkspaceHealth
10538
10725
  };
10539
10726
  };
10727
+
10728
+ // src/lib/utils/relativeTime.ts
10729
+ function formatRelativeTime(timestamp) {
10730
+ if (!timestamp) return "Never";
10731
+ try {
10732
+ const now2 = /* @__PURE__ */ new Date();
10733
+ const date = typeof timestamp === "string" ? new Date(timestamp) : timestamp;
10734
+ if (isNaN(date.getTime())) return "Invalid date";
10735
+ if (date > now2) return "Just now";
10736
+ const diffMs = now2.getTime() - date.getTime();
10737
+ const diffSeconds = Math.floor(diffMs / 1e3);
10738
+ const diffMinutes = Math.floor(diffSeconds / 60);
10739
+ const diffHours = Math.floor(diffMinutes / 60);
10740
+ const diffDays = Math.floor(diffHours / 24);
10741
+ if (diffSeconds < 60) {
10742
+ return `${diffSeconds}s ago`;
10743
+ }
10744
+ if (diffMinutes < 60) {
10745
+ const remainingSeconds = diffSeconds % 60;
10746
+ if (remainingSeconds === 0) {
10747
+ return `${diffMinutes}m ago`;
10748
+ }
10749
+ return `${diffMinutes}m ${remainingSeconds}s ago`;
10750
+ }
10751
+ if (diffHours < 24) {
10752
+ const remainingMinutes = diffMinutes % 60;
10753
+ if (remainingMinutes === 0) {
10754
+ return `${diffHours}h ago`;
10755
+ }
10756
+ return `${diffHours}h ${remainingMinutes}m ago`;
10757
+ }
10758
+ return `${diffDays}d ago`;
10759
+ } catch (error) {
10760
+ console.error("[formatRelativeTime] Error formatting timestamp:", error);
10761
+ return "Unknown";
10762
+ }
10763
+ }
10764
+ function getNextUpdateInterval(timestamp) {
10765
+ if (!timestamp) return 6e4;
10766
+ try {
10767
+ const now2 = /* @__PURE__ */ new Date();
10768
+ const date = typeof timestamp === "string" ? new Date(timestamp) : timestamp;
10769
+ if (isNaN(date.getTime())) return 6e4;
10770
+ const diffMs = now2.getTime() - date.getTime();
10771
+ const diffSeconds = Math.floor(diffMs / 1e3);
10772
+ const diffMinutes = Math.floor(diffSeconds / 60);
10773
+ const diffHours = Math.floor(diffMinutes / 60);
10774
+ if (diffSeconds < 60) return 1e3;
10775
+ if (diffMinutes < 60) return 1e3;
10776
+ if (diffHours < 24) return 6e4;
10777
+ return 36e5;
10778
+ } catch (error) {
10779
+ return 6e4;
10780
+ }
10781
+ }
10782
+
10783
+ // src/lib/hooks/useWorkspaceHealthStatus.ts
10784
+ var useWorkspaceHealthStatus = (workspaceId) => {
10785
+ const supabase = useSupabase();
10786
+ const [healthData, setHealthData] = React23.useState(null);
10787
+ const [loading, setLoading] = React23.useState(true);
10788
+ const [error, setError] = React23.useState(null);
10789
+ const [timeSinceUpdate, setTimeSinceUpdate] = React23.useState("Never");
10790
+ const isFetchingRef = React23.useRef(false);
10791
+ const updateIntervalRef = React23.useRef(null);
10792
+ const fetchHealthStatus = React23.useCallback(async () => {
10793
+ if (!supabase || !workspaceId || isFetchingRef.current) return;
10794
+ try {
10795
+ isFetchingRef.current = true;
10796
+ setLoading(true);
10797
+ setError(null);
10798
+ const { data, error: fetchError } = await supabase.from("workspace_health_status").select("*").eq("workspace_id", workspaceId).maybeSingle();
10799
+ if (fetchError) throw fetchError;
10800
+ if (data) {
10801
+ setHealthData(data);
10802
+ setTimeSinceUpdate(formatRelativeTime(data.last_heartbeat));
10803
+ } else {
10804
+ setHealthData(null);
10805
+ setTimeSinceUpdate("Never");
10806
+ }
10807
+ } catch (err) {
10808
+ console.error("[useWorkspaceHealthStatus] Error fetching health status:", err);
10809
+ setError({ message: err.message, code: err.code || "FETCH_ERROR" });
10810
+ setHealthData(null);
10811
+ setTimeSinceUpdate("Unknown");
10812
+ } finally {
10813
+ setLoading(false);
10814
+ isFetchingRef.current = false;
10815
+ }
10816
+ }, [supabase, workspaceId]);
10817
+ const updateDisplayTime = React23.useCallback(() => {
10818
+ if (healthData?.last_heartbeat) {
10819
+ setTimeSinceUpdate(formatRelativeTime(healthData.last_heartbeat));
10820
+ }
10821
+ }, [healthData?.last_heartbeat]);
10822
+ React23.useEffect(() => {
10823
+ fetchHealthStatus();
10824
+ }, [fetchHealthStatus]);
10825
+ React23.useEffect(() => {
10826
+ if (!supabase || !workspaceId) return;
10827
+ console.log("[useWorkspaceHealthStatus] Setting up real-time subscription for workspace:", workspaceId);
10828
+ const channel = supabase.channel(`workspace-health-status-${workspaceId}`).on(
10829
+ "postgres_changes",
10830
+ {
10831
+ event: "*",
10832
+ // Listen to all events (INSERT, UPDATE, DELETE)
10833
+ schema: "public",
10834
+ table: "workspace_health_status",
10835
+ filter: `workspace_id=eq.${workspaceId}`
10836
+ },
10837
+ (payload) => {
10838
+ console.log("[useWorkspaceHealthStatus] Real-time update received:", payload);
10839
+ if (payload.new && "last_heartbeat" in payload.new) {
10840
+ const newData = payload.new;
10841
+ setHealthData(newData);
10842
+ setTimeSinceUpdate(formatRelativeTime(newData.last_heartbeat));
10843
+ } else if (payload.eventType === "DELETE") {
10844
+ setHealthData(null);
10845
+ setTimeSinceUpdate("Never");
10846
+ }
10847
+ }
10848
+ ).subscribe((status) => {
10849
+ console.log("[useWorkspaceHealthStatus] Subscription status:", status);
10850
+ });
10851
+ return () => {
10852
+ console.log("[useWorkspaceHealthStatus] Cleaning up subscription");
10853
+ supabase.removeChannel(channel);
10854
+ };
10855
+ }, [supabase, workspaceId]);
10856
+ React23.useEffect(() => {
10857
+ if (updateIntervalRef.current) {
10858
+ clearInterval(updateIntervalRef.current);
10859
+ }
10860
+ if (!healthData?.last_heartbeat) return;
10861
+ const intervalMs = getNextUpdateInterval(healthData.last_heartbeat);
10862
+ updateIntervalRef.current = setInterval(updateDisplayTime, intervalMs);
10863
+ return () => {
10864
+ if (updateIntervalRef.current) {
10865
+ clearInterval(updateIntervalRef.current);
10866
+ }
10867
+ };
10868
+ }, [healthData?.last_heartbeat, updateDisplayTime]);
10869
+ return {
10870
+ lastHeartbeat: healthData?.last_heartbeat || null,
10871
+ timeSinceUpdate,
10872
+ isHealthy: healthData?.is_healthy ?? false,
10873
+ healthData,
10874
+ loading,
10875
+ error,
10876
+ refetch: fetchHealthStatus
10877
+ };
10878
+ };
10540
10879
  function useDateFormatter() {
10541
10880
  const { defaultTimezone, defaultLocale, dateFormatOptions, timeFormatOptions, dateTimeFormatOptions } = useDateTimeConfig();
10542
10881
  const formatDate = React23.useCallback(
@@ -13896,7 +14235,9 @@ var createSupabaseClient = (url, key) => supabaseJs.createClient(url, key, {
13896
14235
  autoRefreshToken: true,
13897
14236
  persistSession: true,
13898
14237
  detectSessionInUrl: true,
13899
- flowType: "pkce"
14238
+ flowType: "pkce",
14239
+ // Enable debug logging in development
14240
+ debug: process.env.NODE_ENV === "development"
13900
14241
  },
13901
14242
  db: {
13902
14243
  schema: "public"
@@ -13905,6 +14246,22 @@ var createSupabaseClient = (url, key) => supabaseJs.createClient(url, key, {
13905
14246
  global: {
13906
14247
  headers: {
13907
14248
  "x-application-name": "optifye-dashboard"
14249
+ },
14250
+ // Add global fetch timeout (5 minutes)
14251
+ fetch: async (url2, options = {}) => {
14252
+ const controller = new AbortController();
14253
+ const timeoutId = setTimeout(() => controller.abort(), 3e5);
14254
+ try {
14255
+ const response = await fetch(url2, {
14256
+ ...options,
14257
+ signal: controller.signal
14258
+ });
14259
+ clearTimeout(timeoutId);
14260
+ return response;
14261
+ } catch (error) {
14262
+ clearTimeout(timeoutId);
14263
+ throw error;
14264
+ }
13908
14265
  }
13909
14266
  }
13910
14267
  });
@@ -13919,7 +14276,29 @@ var getAnonClient = () => {
13919
14276
  autoRefreshToken: true,
13920
14277
  persistSession: true,
13921
14278
  detectSessionInUrl: true,
13922
- flowType: "pkce"
14279
+ flowType: "pkce",
14280
+ debug: process.env.NODE_ENV === "development"
14281
+ },
14282
+ global: {
14283
+ headers: {
14284
+ "x-application-name": "optifye-dashboard"
14285
+ },
14286
+ // Add global fetch timeout (5 minutes)
14287
+ fetch: async (url2, options = {}) => {
14288
+ const controller = new AbortController();
14289
+ const timeoutId = setTimeout(() => controller.abort(), 3e5);
14290
+ try {
14291
+ const response = await fetch(url2, {
14292
+ ...options,
14293
+ signal: controller.signal
14294
+ });
14295
+ clearTimeout(timeoutId);
14296
+ return response;
14297
+ } catch (error) {
14298
+ clearTimeout(timeoutId);
14299
+ throw error;
14300
+ }
14301
+ }
13923
14302
  }
13924
14303
  });
13925
14304
  };
@@ -21283,17 +21662,33 @@ var createMotionComponent = /* @__PURE__ */ createMotionComponentFactory({
21283
21662
 
21284
21663
  // ../../node_modules/framer-motion/dist/es/render/components/motion/proxy.mjs
21285
21664
  var motion = /* @__PURE__ */ createDOMMotionComponentProxy(createMotionComponent);
21665
+
21666
+ // src/assets/optifye-logo.png
21667
+ var optifye_logo_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAACFIAAASwCAYAAADSLPxEAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEyGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSfvu78nIGlkPSdXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQnPz4KPHg6eG1wbWV0YSB4bWxuczp4PSdhZG9iZTpuczptZXRhLyc+CjxyZGY6UkRGIHhtbG5zOnJkZj0naHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyc+CgogPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9JycKICB4bWxuczpBdHRyaWI9J2h0dHA6Ly9ucy5hdHRyaWJ1dGlvbi5jb20vYWRzLzEuMC8nPgogIDxBdHRyaWI6QWRzPgogICA8cmRmOlNlcT4KICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0nUmVzb3VyY2UnPgogICAgIDxBdHRyaWI6Q3JlYXRlZD4yMDI1LTAyLTE5PC9BdHRyaWI6Q3JlYXRlZD4KICAgICA8QXR0cmliOkV4dElkPmEwNzgwZWVmLWUxNjItNGE4MS1iY2I0LTgxODU3M2VkMmI5YjwvQXR0cmliOkV4dElkPgogICAgIDxBdHRyaWI6RmJJZD41MjUyNjU5MTQxNzk1ODA8L0F0dHJpYjpGYklkPgogICAgIDxBdHRyaWI6VG91Y2hUeXBlPjI8L0F0dHJpYjpUb3VjaFR5cGU+CiAgICA8L3JkZjpsaT4KICAgPC9yZGY6U2VxPgogIDwvQXR0cmliOkFkcz4KIDwvcmRmOkRlc2NyaXB0aW9uPgoKIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PScnCiAgeG1sbnM6ZGM9J2h0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvJz4KICA8ZGM6dGl0bGU+CiAgIDxyZGY6QWx0PgogICAgPHJkZjpsaSB4bWw6bGFuZz0neC1kZWZhdWx0Jz5vcHRpZnllIGxvZ28gc2V4eSAoMjEzMCB4IDEyMDAgcHgpIC0gMTwvcmRmOmxpPgogICA8L3JkZjpBbHQ+CiAgPC9kYzp0aXRsZT4KIDwvcmRmOkRlc2NyaXB0aW9u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";
21668
+ var Logo = ({
21669
+ className = "",
21670
+ alt = "Optifye"
21671
+ }) => {
21672
+ return /* @__PURE__ */ jsxRuntime.jsx(
21673
+ "img",
21674
+ {
21675
+ src: optifye_logo_default,
21676
+ alt,
21677
+ className
21678
+ }
21679
+ );
21680
+ };
21286
21681
  var OptifyeLogoLoader = ({
21287
21682
  size = "md",
21288
21683
  message,
21289
21684
  className
21290
21685
  }) => {
21291
21686
  const sizeClasses = {
21292
- sm: "w-10",
21687
+ sm: "w-10 h-10",
21293
21688
  // 40px
21294
- md: "w-16",
21689
+ md: "w-16 h-16",
21295
21690
  // 64px
21296
- lg: "w-24"
21691
+ lg: "w-24 h-24"
21297
21692
  // 96px
21298
21693
  };
21299
21694
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -21304,11 +21699,10 @@ var OptifyeLogoLoader = ({
21304
21699
  className: `flex flex-col items-center justify-center p-4 ${className || ""}`.trim(),
21305
21700
  children: [
21306
21701
  /* @__PURE__ */ jsxRuntime.jsx(
21307
- "img",
21702
+ Logo,
21308
21703
  {
21309
- src: "/optifye-logo.png",
21310
- alt: "Optifye Logo",
21311
- className: `${sizeClasses[size]} h-auto animate-pulse select-none pointer-events-none`
21704
+ className: `${sizeClasses[size]} object-contain animate-pulse select-none pointer-events-none`,
21705
+ alt: "Optifye Logo"
21312
21706
  }
21313
21707
  ),
21314
21708
  message && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 text-gray-600 text-base sm:text-sm font-medium text-center", children: message })
@@ -21320,15 +21714,65 @@ var OptifyeLogoLoader_default = OptifyeLogoLoader;
21320
21714
  var LoadingPage = ({
21321
21715
  message = "Loading Dashboard...",
21322
21716
  subMessage = "Please wait while we prepare your data",
21323
- className
21717
+ className,
21718
+ onTimeout,
21719
+ timeoutMs = 3e5
21720
+ // 5 minutes default
21324
21721
  }) => {
21325
- React23__namespace.default.useEffect(() => {
21326
- console.log("LoadingPage rendered with message:", message);
21327
- const timeout = setTimeout(() => {
21328
- console.warn("LoadingPage has been visible for more than 8 seconds. This might indicate an issue.");
21329
- }, 8e3);
21330
- return () => clearTimeout(timeout);
21331
- }, [message]);
21722
+ const [showTimeoutWarning, setShowTimeoutWarning] = React23.useState(false);
21723
+ const [timeoutReached, setTimeoutReached] = React23.useState(false);
21724
+ const warningTime = timeoutMs * 0.8;
21725
+ React23.useEffect(() => {
21726
+ console.log("[LoadingPage] Rendered with message:", message);
21727
+ const warningTimer = setTimeout(() => {
21728
+ console.warn("[LoadingPage] Loading taking longer than expected");
21729
+ setShowTimeoutWarning(true);
21730
+ }, warningTime);
21731
+ const timeoutTimer = setTimeout(() => {
21732
+ console.error("[LoadingPage] Loading timeout reached after", timeoutMs, "ms");
21733
+ setTimeoutReached(true);
21734
+ if (onTimeout) {
21735
+ onTimeout();
21736
+ }
21737
+ }, timeoutMs);
21738
+ return () => {
21739
+ clearTimeout(warningTimer);
21740
+ clearTimeout(timeoutTimer);
21741
+ };
21742
+ }, [message, timeoutMs, warningTime, onTimeout]);
21743
+ const handleResetAndTryAgain = React23.useCallback(() => {
21744
+ console.log("[LoadingPage] User initiated reset");
21745
+ const hasLocalStorage = typeof window !== "undefined" && window.localStorage;
21746
+ const hasCachedData = hasLocalStorage && localStorage.getItem("sb-zmzewpwerpaupoaoeqhh-auth-token");
21747
+ if (hasCachedData) {
21748
+ console.log("[LoadingPage] Found cached session, attempting to use it");
21749
+ window.location.reload();
21750
+ } else {
21751
+ console.log("[LoadingPage] No cached session, redirecting to login");
21752
+ if (hasLocalStorage) {
21753
+ localStorage.clear();
21754
+ sessionStorage.clear();
21755
+ }
21756
+ window.location.href = "/login";
21757
+ }
21758
+ }, []);
21759
+ if (timeoutReached) {
21760
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-full w-full items-center justify-center bg-slate-50 ${className || ""}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center space-y-6 text-center max-w-md", children: [
21761
+ /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "lg", message: "Loading Dashboard..." }),
21762
+ /* @__PURE__ */ jsxRuntime.jsxs(motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "space-y-2", children: [
21763
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base text-gray-600", children: "This is taking longer than usual" }),
21764
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "Your session might have timed out" })
21765
+ ] }),
21766
+ /* @__PURE__ */ jsxRuntime.jsx(
21767
+ "button",
21768
+ {
21769
+ onClick: handleResetAndTryAgain,
21770
+ className: "mt-4 px-4 py-2 text-sm text-gray-600 hover:text-gray-900 underline transition-colors",
21771
+ children: "Reset and try again"
21772
+ }
21773
+ )
21774
+ ] }) });
21775
+ }
21332
21776
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-full w-full items-center justify-center bg-slate-50 ${className || ""}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center space-y-6 text-center", children: [
21333
21777
  /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "lg", message }),
21334
21778
  subMessage && /* @__PURE__ */ jsxRuntime.jsx(
@@ -21340,23 +21784,19 @@ var LoadingPage = ({
21340
21784
  transition: { delay: 0.2, duration: 0.3 },
21341
21785
  children: subMessage
21342
21786
  }
21787
+ ),
21788
+ showTimeoutWarning && !timeoutReached && /* @__PURE__ */ jsxRuntime.jsx(
21789
+ motion.p,
21790
+ {
21791
+ initial: { opacity: 0 },
21792
+ animate: { opacity: 1 },
21793
+ className: "text-sm text-gray-500 italic",
21794
+ children: "Still loading, please wait..."
21795
+ }
21343
21796
  )
21344
21797
  ] }) });
21345
21798
  };
21346
21799
  var LoadingPage_default = LoadingPage;
21347
- var AccessDeniedPage = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-screen flex items-center justify-center bg-gray-50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-md w-full bg-white shadow-lg rounded-lg p-6 text-center", children: [
21348
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "mx-auto h-12 w-12 text-red-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsxRuntime.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" }) }) }),
21349
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-gray-900 mb-2", children: "Access Denied" }),
21350
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 mb-4", children: "You do not have access to this dashboard. Please contact your administrator for assistance." }),
21351
- /* @__PURE__ */ jsxRuntime.jsx(
21352
- "button",
21353
- {
21354
- onClick: () => window.location.href = "/login",
21355
- className: "bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-md transition-colors",
21356
- children: "Return to Login"
21357
- }
21358
- )
21359
- ] }) });
21360
21800
  var withAuth = (WrappedComponent2, options) => {
21361
21801
  const defaultOptions = {
21362
21802
  redirectTo: "/login",
@@ -21366,22 +21806,64 @@ var withAuth = (WrappedComponent2, options) => {
21366
21806
  const WithAuthComponent = React23__namespace.memo(function WithAuthComponent2(props) {
21367
21807
  const { session, loading, error } = useAuth();
21368
21808
  const router$1 = router.useRouter();
21809
+ const [localLoading, setLocalLoading] = React23__namespace.useState(loading);
21810
+ const [loadingTimeoutReached, setLoadingTimeoutReached] = React23__namespace.useState(false);
21369
21811
  React23__namespace.useEffect(() => {
21370
21812
  if (process.env.NODE_ENV === "development" && process.env.DEBUG_AUTH === "true") {
21371
- console.log("withAuth state:", { loading, hasSession: !!session, requireAuth: defaultOptions.requireAuth });
21813
+ console.log("withAuth state:", {
21814
+ loading,
21815
+ hasSession: !!session,
21816
+ requireAuth: defaultOptions.requireAuth,
21817
+ hasError: !!error
21818
+ });
21372
21819
  }
21373
- }, [session, loading]);
21820
+ }, [session, loading, error]);
21821
+ const handleLoadingTimeout = React23__namespace.useCallback(() => {
21822
+ console.warn("[withAuth] Loading timeout reached");
21823
+ setLoadingTimeoutReached(true);
21824
+ if (typeof window !== "undefined" && localStorage.getItem("sb-zmzewpwerpaupoaoeqhh-auth-token")) {
21825
+ console.log("[withAuth] Found cached session, attempting to continue");
21826
+ setLocalLoading(false);
21827
+ } else {
21828
+ console.log("[withAuth] No cached session, redirecting to login");
21829
+ router$1.replace(defaultOptions.redirectTo);
21830
+ }
21831
+ }, [router$1]);
21374
21832
  React23__namespace.useEffect(() => {
21375
21833
  if (!loading && defaultOptions.requireAuth && !session && !error) {
21376
- console.log("Redirecting to login from withAuth");
21834
+ console.log("[withAuth] No session found, redirecting to login");
21377
21835
  router$1.replace(defaultOptions.redirectTo);
21378
21836
  }
21379
21837
  }, [session, loading, router$1, error]);
21380
- if (loading) {
21381
- return /* @__PURE__ */ jsxRuntime.jsx(LoadingPage, { message: "Authenticating..." });
21838
+ React23__namespace.useEffect(() => {
21839
+ setLocalLoading(loading);
21840
+ }, [loading]);
21841
+ if (loading || localLoading) {
21842
+ return /* @__PURE__ */ jsxRuntime.jsx(
21843
+ LoadingPage,
21844
+ {
21845
+ message: "Authenticating...",
21846
+ timeoutMs: 3e5,
21847
+ onTimeout: handleLoadingTimeout
21848
+ }
21849
+ );
21382
21850
  }
21383
- if (error && error.message.includes("You do not have access to this dashboard")) {
21384
- return /* @__PURE__ */ jsxRuntime.jsx(AccessDeniedPage, {});
21851
+ if (error) {
21852
+ console.error("[withAuth] Auth error:", {
21853
+ message: error.message,
21854
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
21855
+ });
21856
+ if (error.message.includes("You do not have access to this dashboard")) {
21857
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-screen flex items-center justify-center bg-slate-50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-md text-center space-y-4", children: [
21858
+ /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "lg", message: "Checking Access..." }),
21859
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "Verifying your permissions" }),
21860
+ /* @__PURE__ */ jsxRuntime.jsx("a", { href: "/login", className: "text-xs text-gray-400 hover:text-gray-600 underline", children: "Return to login" })
21861
+ ] }) });
21862
+ }
21863
+ if (defaultOptions.requireAuth) {
21864
+ router$1.replace(defaultOptions.redirectTo);
21865
+ return null;
21866
+ }
21385
21867
  }
21386
21868
  if (defaultOptions.requireAuth && !session) {
21387
21869
  return null;
@@ -21418,7 +21900,7 @@ function withAccessControl(WrappedComponent2, options = {}) {
21418
21900
  }
21419
21901
  var LoginPage = ({
21420
21902
  onRateLimitCheck,
21421
- logoSrc = "/optifye-logo.png",
21903
+ logoSrc = optifye_logo_default,
21422
21904
  logoAlt = "Optifye",
21423
21905
  brandName = "Optifye"
21424
21906
  }) => {
@@ -25027,13 +25509,37 @@ var WhatsAppShareButton = ({
25027
25509
  }
25028
25510
  );
25029
25511
  };
25512
+ var AxelOrb = ({
25513
+ className = "",
25514
+ size = "md",
25515
+ animate = false
25516
+ }) => {
25517
+ const sizeClasses = {
25518
+ sm: "w-8 h-8",
25519
+ md: "w-10 h-10",
25520
+ lg: "w-12 h-12",
25521
+ xl: "w-16 h-16",
25522
+ "2xl": "w-20 h-20"
25523
+ };
25524
+ return /* @__PURE__ */ jsxRuntime.jsx(
25525
+ "div",
25526
+ {
25527
+ className: `${sizeClasses[size]} rounded-full ${animate ? "animate-float" : ""} ${className}`,
25528
+ style: {
25529
+ background: "linear-gradient(to top, #078DDB 0%, #65ADD6 33%, #A3D0E6 66%, #C7E2EC 100%)",
25530
+ boxShadow: "0 4px 12px rgba(7, 141, 219, 0.4), 0 0 20px rgba(7, 141, 219, 0.2)"
25531
+ },
25532
+ "aria-label": "Axel AI",
25533
+ role: "img"
25534
+ }
25535
+ );
25536
+ };
25030
25537
  var BreakNotificationPopup = ({
25031
25538
  activeBreaks,
25032
25539
  onDismiss,
25033
25540
  isVisible = true,
25034
25541
  className = "",
25035
- lineNames = {},
25036
- axelImagePath = "/axel-profile.png"
25542
+ lineNames = {}
25037
25543
  }) => {
25038
25544
  const [isDismissed, setIsDismissed] = React23.useState(false);
25039
25545
  const [currentTime, setCurrentTime] = React23.useState(/* @__PURE__ */ new Date());
@@ -25069,22 +25575,7 @@ var BreakNotificationPopup = ({
25069
25575
  style: { top: `${6 + index * 12}rem` },
25070
25576
  children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white text-gray-900 rounded-lg border border-gray-200 shadow-lg overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
25071
25577
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start space-x-3 flex-1", children: [
25072
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
25073
- "img",
25074
- {
25075
- src: axelImagePath,
25076
- alt: "Axel AI",
25077
- className: "w-10 h-10 rounded-full object-cover border-2 border-gray-200 shadow-sm",
25078
- onError: (e) => {
25079
- const target = e.currentTarget;
25080
- target.style.display = "none";
25081
- const fallback = document.createElement("div");
25082
- 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";
25083
- fallback.textContent = "A";
25084
- target.parentElement?.appendChild(fallback);
25085
- }
25086
- }
25087
- ) }),
25578
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(AxelOrb, { size: "md" }) }),
25088
25579
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
25089
25580
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [
25090
25581
  /* @__PURE__ */ jsxRuntime.jsxs("h4", { className: "font-semibold text-sm text-gray-900", children: [
@@ -25284,8 +25775,7 @@ var AxelNotificationPopup = ({
25284
25775
  suggestion,
25285
25776
  isVisible = true,
25286
25777
  onDismiss,
25287
- className = "",
25288
- axelImagePath = "/axel-profile.png"
25778
+ className = ""
25289
25779
  }) => {
25290
25780
  const [isDismissed, setIsDismissed] = React23.useState(false);
25291
25781
  React23.useEffect(() => {
@@ -25331,22 +25821,7 @@ var AxelNotificationPopup = ({
25331
25821
  className: "p-3",
25332
25822
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
25333
25823
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start space-x-3 flex-1", children: [
25334
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
25335
- "img",
25336
- {
25337
- src: axelImagePath,
25338
- alt: "Axel AI",
25339
- className: "w-10 h-10 rounded-full object-cover border-2 border-gray-200 shadow-sm",
25340
- onError: (e) => {
25341
- const target = e.currentTarget;
25342
- target.style.display = "none";
25343
- const fallback = document.createElement("div");
25344
- 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";
25345
- fallback.textContent = "A";
25346
- target.parentElement?.appendChild(fallback);
25347
- }
25348
- }
25349
- ) }),
25824
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(AxelOrb, { size: "md" }) }),
25350
25825
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
25351
25826
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [
25352
25827
  /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-semibold text-sm text-gray-900", children: suggestion.title }),
@@ -25797,6 +26272,140 @@ var TimePickerDropdown = ({
25797
26272
  ] })
25798
26273
  ] });
25799
26274
  };
26275
+ var SilentErrorBoundary = class extends React23__namespace.default.Component {
26276
+ constructor(props) {
26277
+ super(props);
26278
+ this.handleClearAndReload = () => {
26279
+ console.log("[ErrorBoundary] User initiated reset");
26280
+ if (typeof window !== "undefined") {
26281
+ try {
26282
+ localStorage.clear();
26283
+ sessionStorage.clear();
26284
+ console.log("[ErrorBoundary] Cleared all storage");
26285
+ } catch (error) {
26286
+ console.error("[ErrorBoundary] Failed to clear storage:", error);
26287
+ }
26288
+ }
26289
+ window.location.href = "/login";
26290
+ };
26291
+ this.state = {
26292
+ hasError: false,
26293
+ errorCount: 0,
26294
+ lastError: null,
26295
+ errorInfo: null
26296
+ };
26297
+ }
26298
+ static getDerivedStateFromError(error) {
26299
+ return { hasError: true };
26300
+ }
26301
+ componentDidCatch(error, errorInfo) {
26302
+ console.error("[ErrorBoundary] Caught render error:", {
26303
+ error: error.message,
26304
+ stack: error.stack,
26305
+ componentStack: errorInfo.componentStack,
26306
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
26307
+ });
26308
+ this.setState((prev) => ({
26309
+ errorCount: prev.errorCount + 1,
26310
+ lastError: error,
26311
+ errorInfo
26312
+ }));
26313
+ try {
26314
+ if (typeof window !== "undefined" && window.mixpanel) {
26315
+ window.mixpanel.track("React Render Error", {
26316
+ error: error.message,
26317
+ component: errorInfo.componentStack?.split("\n")[1] || "unknown",
26318
+ errorCount: this.state.errorCount + 1
26319
+ });
26320
+ }
26321
+ } catch (analyticsError) {
26322
+ console.warn("[ErrorBoundary] Analytics tracking failed:", analyticsError);
26323
+ }
26324
+ }
26325
+ render() {
26326
+ if (!this.state.hasError) {
26327
+ return this.props.children;
26328
+ }
26329
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-screen w-screen items-center justify-center bg-slate-50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center space-y-6 text-center", children: [
26330
+ /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "lg", message: "Loading Dashboard..." }),
26331
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "Taking longer than usual..." }),
26332
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-4", children: /* @__PURE__ */ jsxRuntime.jsx(
26333
+ "a",
26334
+ {
26335
+ href: "#",
26336
+ onClick: (e) => {
26337
+ e.preventDefault();
26338
+ this.handleClearAndReload();
26339
+ },
26340
+ className: "text-xs text-gray-400 hover:text-gray-600 underline transition-colors",
26341
+ children: "Reset and try again"
26342
+ }
26343
+ ) }),
26344
+ process.env.NODE_ENV === "development" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400 italic mt-4", children: "Check console for error details" })
26345
+ ] }) });
26346
+ }
26347
+ };
26348
+ var PlayPauseIndicator = ({
26349
+ show,
26350
+ isPlaying,
26351
+ duration = 600
26352
+ }) => {
26353
+ const [isVisible, setIsVisible] = React23.useState(false);
26354
+ const [isFading, setIsFading] = React23.useState(false);
26355
+ React23.useEffect(() => {
26356
+ if (show) {
26357
+ setIsVisible(true);
26358
+ setIsFading(false);
26359
+ const fadeTimer = setTimeout(() => {
26360
+ setIsFading(true);
26361
+ }, 100);
26362
+ const hideTimer = setTimeout(() => {
26363
+ setIsVisible(false);
26364
+ setIsFading(false);
26365
+ }, duration);
26366
+ return () => {
26367
+ clearTimeout(fadeTimer);
26368
+ clearTimeout(hideTimer);
26369
+ };
26370
+ }
26371
+ }, [show, duration]);
26372
+ if (!isVisible) return null;
26373
+ return /* @__PURE__ */ jsxRuntime.jsx(
26374
+ "div",
26375
+ {
26376
+ className: "absolute inset-0 flex items-center justify-center pointer-events-none z-10",
26377
+ style: {
26378
+ opacity: isFading ? 0 : 1,
26379
+ transition: `opacity ${duration - 100}ms ease-out`
26380
+ },
26381
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-black/70 rounded-full p-6", children: isPlaying ? (
26382
+ // Play icon (triangle)
26383
+ /* @__PURE__ */ jsxRuntime.jsx(
26384
+ "svg",
26385
+ {
26386
+ xmlns: "http://www.w3.org/2000/svg",
26387
+ viewBox: "0 0 24 24",
26388
+ fill: "white",
26389
+ className: "w-16 h-16",
26390
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5v14l11-7z" })
26391
+ }
26392
+ )
26393
+ ) : (
26394
+ // Pause icon (two bars)
26395
+ /* @__PURE__ */ jsxRuntime.jsx(
26396
+ "svg",
26397
+ {
26398
+ xmlns: "http://www.w3.org/2000/svg",
26399
+ viewBox: "0 0 24 24",
26400
+ fill: "white",
26401
+ className: "w-16 h-16",
26402
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 4h4v16H6V4zm8 0h4v16h-4V4z" })
26403
+ }
26404
+ )
26405
+ ) })
26406
+ }
26407
+ );
26408
+ };
25800
26409
  var ERROR_MAPPING = {
25801
26410
  1: {
25802
26411
  // MEDIA_ERR_ABORTED
@@ -25902,12 +26511,16 @@ var VideoPlayer = React23__namespace.default.forwardRef(({
25902
26511
  onLoadedMetadata,
25903
26512
  onLoadedData,
25904
26513
  onSeeking,
25905
- onSeeked
26514
+ onSeeked,
26515
+ onClick
25906
26516
  }, ref) => {
25907
26517
  const videoRef = React23.useRef(null);
25908
26518
  const playerRef = React23.useRef(null);
25909
26519
  const [isReady, setIsReady] = React23.useState(false);
25910
26520
  const [isLoading, setIsLoading] = React23.useState(true);
26521
+ const [showIndicator, setShowIndicator] = React23.useState(false);
26522
+ const [indicatorIsPlaying, setIndicatorIsPlaying] = React23.useState(false);
26523
+ const indicatorKeyRef = React23.useRef(0);
25911
26524
  const defaultOptions = {
25912
26525
  controls: false,
25913
26526
  // Always disable Video.js controls - we use custom controls
@@ -26223,6 +26836,18 @@ var VideoPlayer = React23__namespace.default.forwardRef(({
26223
26836
  dispose,
26224
26837
  isReady
26225
26838
  }));
26839
+ const handleClickWithIndicator = React23.useCallback(() => {
26840
+ if (!onClick || !playerRef.current) return;
26841
+ const player = playerRef.current;
26842
+ const willBePlaying = player.paused();
26843
+ setIndicatorIsPlaying(willBePlaying);
26844
+ setShowIndicator(false);
26845
+ setTimeout(() => {
26846
+ indicatorKeyRef.current += 1;
26847
+ setShowIndicator(true);
26848
+ }, 0);
26849
+ onClick();
26850
+ }, [onClick]);
26226
26851
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `video-player-wrapper ${className}`, style: { position: "relative", width: "100%", height: "100%" }, children: [
26227
26852
  /* @__PURE__ */ jsxRuntime.jsx(
26228
26853
  "div",
@@ -26232,7 +26857,31 @@ var VideoPlayer = React23__namespace.default.forwardRef(({
26232
26857
  "data-vjs-player": true
26233
26858
  }
26234
26859
  ),
26235
- isLoading && !externalLoadingControl && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "video-player-loading", children: /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) })
26860
+ isLoading && !externalLoadingControl && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "video-player-loading", children: /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
26861
+ onClick && /* @__PURE__ */ jsxRuntime.jsx(
26862
+ "div",
26863
+ {
26864
+ onClick: handleClickWithIndicator,
26865
+ style: {
26866
+ position: "absolute",
26867
+ top: 0,
26868
+ left: 0,
26869
+ right: 0,
26870
+ bottom: 0,
26871
+ zIndex: 1,
26872
+ cursor: "pointer"
26873
+ },
26874
+ "aria-label": "Click to play/pause"
26875
+ }
26876
+ ),
26877
+ onClick && /* @__PURE__ */ jsxRuntime.jsx(
26878
+ PlayPauseIndicator,
26879
+ {
26880
+ show: showIndicator,
26881
+ isPlaying: indicatorIsPlaying
26882
+ },
26883
+ indicatorKeyRef.current
26884
+ )
26236
26885
  ] });
26237
26886
  });
26238
26887
  VideoPlayer.displayName = "VideoPlayer";
@@ -26250,6 +26899,9 @@ var CroppedVideoPlayer = React23.forwardRef(({
26250
26899
  const [isVideoReady, setIsVideoReady] = React23.useState(false);
26251
26900
  const [canvasDimensions, setCanvasDimensions] = React23.useState({ width: 0, height: 0 });
26252
26901
  const [isProcessing, setIsProcessing] = React23.useState(false);
26902
+ const [showIndicator, setShowIndicator] = React23.useState(false);
26903
+ const [indicatorIsPlaying, setIndicatorIsPlaying] = React23.useState(false);
26904
+ const indicatorKeyRef = React23.useRef(0);
26253
26905
  const stopCanvasRendering = React23.useCallback(() => {
26254
26906
  if (animationFrameRef.current) {
26255
26907
  cancelAnimationFrame(animationFrameRef.current);
@@ -26428,14 +27080,26 @@ var CroppedVideoPlayer = React23.forwardRef(({
26428
27080
  };
26429
27081
  }, [stopCanvasRendering]);
26430
27082
  if (!crop) {
26431
- return /* @__PURE__ */ jsxRuntime.jsx(VideoPlayer, { ref, ...videoProps });
26432
- }
27083
+ return /* @__PURE__ */ jsxRuntime.jsx(VideoPlayer, { ref, ...videoProps, onClick });
27084
+ }
27085
+ const handleClickWithIndicator = () => {
27086
+ if (!onClick || !hiddenVideoRef.current?.player) return;
27087
+ const player = hiddenVideoRef.current.player;
27088
+ const willBePlaying = player.paused();
27089
+ setIndicatorIsPlaying(willBePlaying);
27090
+ setShowIndicator(false);
27091
+ setTimeout(() => {
27092
+ indicatorKeyRef.current += 1;
27093
+ setShowIndicator(true);
27094
+ }, 0);
27095
+ onClick();
27096
+ };
26433
27097
  return /* @__PURE__ */ jsxRuntime.jsxs(
26434
27098
  "div",
26435
27099
  {
26436
27100
  ref: videoContainerRef,
26437
27101
  className: `relative w-full h-full flex items-center justify-center bg-black ${onClick ? "cursor-pointer" : ""} ${videoProps.className || ""}`,
26438
- onClick,
27102
+ onClick: handleClickWithIndicator,
26439
27103
  children: [
26440
27104
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
26441
27105
  VideoPlayer,
@@ -26492,7 +27156,15 @@ var CroppedVideoPlayer = React23.forwardRef(({
26492
27156
  "Processing: ",
26493
27157
  isProcessing ? "Yes" : "No"
26494
27158
  ] })
26495
- ] })
27159
+ ] }),
27160
+ onClick && /* @__PURE__ */ jsxRuntime.jsx(
27161
+ PlayPauseIndicator,
27162
+ {
27163
+ show: showIndicator,
27164
+ isPlaying: indicatorIsPlaying
27165
+ },
27166
+ indicatorKeyRef.current
27167
+ )
26496
27168
  ]
26497
27169
  }
26498
27170
  );
@@ -28147,6 +28819,7 @@ var BottlenecksContent = ({
28147
28819
  const [metadataCache, setMetadataCache] = React23.useState({});
28148
28820
  const [triageClips, setTriageClips] = React23.useState([]);
28149
28821
  const [isLoadingTriageClips, setIsLoadingTriageClips] = React23.useState(false);
28822
+ const [isFullscreen, setIsFullscreen] = React23.useState(false);
28150
28823
  const categoryMetadataRef = React23.useRef([]);
28151
28824
  const currentMetadataIndexRef = React23.useRef(0);
28152
28825
  const {
@@ -29040,6 +29713,24 @@ var BottlenecksContent = ({
29040
29713
  player.pause();
29041
29714
  }
29042
29715
  };
29716
+ const toggleFullscreen = React23.useCallback((e) => {
29717
+ e.stopPropagation();
29718
+ setIsFullscreen((prev) => !prev);
29719
+ }, []);
29720
+ const exitFullscreen = React23.useCallback(() => {
29721
+ setIsFullscreen(false);
29722
+ }, []);
29723
+ React23.useEffect(() => {
29724
+ const handleEscape = (e) => {
29725
+ if (e.key === "Escape" && isFullscreen) {
29726
+ exitFullscreen();
29727
+ }
29728
+ };
29729
+ if (isFullscreen) {
29730
+ window.addEventListener("keydown", handleEscape);
29731
+ return () => window.removeEventListener("keydown", handleEscape);
29732
+ }
29733
+ }, [isFullscreen, exitFullscreen]);
29043
29734
  const getClipTypeLabel = (video) => {
29044
29735
  if (!video) return "";
29045
29736
  const currentFilter = activeFilterRef.current;
@@ -29152,7 +29843,7 @@ var BottlenecksContent = ({
29152
29843
  )
29153
29844
  ] }) })
29154
29845
  ] }) }),
29155
- filteredVideos.length > 0 && currentVideo ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: `p-4 ${triageMode ? "h-full" : "h-[calc(100%-4rem)]"}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative h-full group", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full h-full overflow-hidden rounded-md shadow-inner bg-gray-900", children: [
29846
+ filteredVideos.length > 0 && currentVideo && !isFullscreen ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: `p-4 ${triageMode ? "h-full" : "h-[calc(100%-4rem)]"}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative h-full group", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full h-full overflow-hidden rounded-md shadow-inner bg-gray-900", children: [
29156
29847
  /* @__PURE__ */ jsxRuntime.jsx(
29157
29848
  "div",
29158
29849
  {
@@ -29252,22 +29943,24 @@ var BottlenecksContent = ({
29252
29943
  ] }) })
29253
29944
  ),
29254
29945
  /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-white", children: [
29255
- /* @__PURE__ */ jsxRuntime.jsx(
29256
- "button",
29257
- {
29258
- onClick: (e) => {
29259
- e.stopPropagation();
29260
- togglePlayback();
29261
- },
29262
- className: "p-1.5 hover:bg-white/20 rounded-full focus:outline-none focus:ring-2 focus:ring-white/50",
29263
- "aria-label": isPlaying ? "Pause" : "Play",
29264
- children: isPlaying ? /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.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" }) })
29265
- }
29266
- ),
29267
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-mono px-2", children: [
29268
- formatTime2(currentTime),
29269
- " / ",
29270
- formatTime2(duration)
29946
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
29947
+ /* @__PURE__ */ jsxRuntime.jsx(
29948
+ "button",
29949
+ {
29950
+ onClick: (e) => {
29951
+ e.stopPropagation();
29952
+ togglePlayback();
29953
+ },
29954
+ className: "p-1.5 hover:bg-white/20 rounded-full focus:outline-none focus:ring-2 focus:ring-white/50",
29955
+ "aria-label": isPlaying ? "Pause" : "Play",
29956
+ children: isPlaying ? /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.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" }) })
29957
+ }
29958
+ ),
29959
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-mono px-2", children: [
29960
+ formatTime2(currentTime),
29961
+ " / ",
29962
+ formatTime2(duration)
29963
+ ] })
29271
29964
  ] }),
29272
29965
  /* @__PURE__ */ jsxRuntime.jsx(
29273
29966
  "input",
@@ -29288,6 +29981,16 @@ var BottlenecksContent = ({
29288
29981
  },
29289
29982
  "aria-label": "Seek slider"
29290
29983
  }
29984
+ ),
29985
+ /* @__PURE__ */ jsxRuntime.jsx(
29986
+ "button",
29987
+ {
29988
+ onClick: toggleFullscreen,
29989
+ className: "p-1.5 hover:bg-white/20 rounded-full focus:outline-none focus:ring-2 focus:ring-white/50",
29990
+ "aria-label": "Fullscreen",
29991
+ title: "Expand to fullscreen",
29992
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize2, { className: "h-5 w-5" })
29993
+ }
29291
29994
  )
29292
29995
  ] }) })
29293
29996
  ] }) }) }) : (
@@ -29424,6 +30127,147 @@ var BottlenecksContent = ({
29424
30127
  )
29425
30128
  ) })
29426
30129
  ] }),
30130
+ isFullscreen && currentVideo && /* @__PURE__ */ jsxRuntime.jsxs(
30131
+ "div",
30132
+ {
30133
+ className: "fixed inset-0 z-50 bg-black flex items-center justify-center",
30134
+ style: { margin: 0 },
30135
+ children: [
30136
+ /* @__PURE__ */ jsxRuntime.jsx(
30137
+ "button",
30138
+ {
30139
+ onClick: exitFullscreen,
30140
+ 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",
30141
+ "aria-label": "Exit fullscreen",
30142
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-6 w-6" })
30143
+ }
30144
+ ),
30145
+ (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__ */ jsxRuntime.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__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
30146
+ /* @__PURE__ */ jsxRuntime.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` }),
30147
+ (currentVideo.type === "cycle_completion" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "opacity-90 font-mono bg-black/30 px-2 py-1 rounded", children: [
30148
+ "Cycle time: ",
30149
+ currentVideo.cycle_time_seconds.toFixed(1),
30150
+ "s"
30151
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
30152
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium mr-2", children: getClipTypeLabel(currentVideo) }),
30153
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-80", children: currentVideo.description })
30154
+ ] })
30155
+ ] }) }) : /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
30156
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-shrink-0 h-3 w-3 rounded-full ${getSeverityColor(currentVideo.severity)} mr-2 animate-pulse` }),
30157
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium mr-2", children: getClipTypeLabel(currentVideo) }),
30158
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-80", children: currentVideo.description })
30159
+ ] }) }),
30160
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center p-8", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full h-full max-w-7xl group", children: [
30161
+ /* @__PURE__ */ jsxRuntime.jsx(
30162
+ "div",
30163
+ {
30164
+ className: "w-full h-full",
30165
+ style: {
30166
+ opacity: isTransitioning ? 0 : 1,
30167
+ transition: "opacity 0.1s ease-in-out"
30168
+ },
30169
+ children: /* @__PURE__ */ jsxRuntime.jsx(
30170
+ CroppedVideoPlayer,
30171
+ {
30172
+ ref: videoRef,
30173
+ src: currentVideo.src,
30174
+ poster: "",
30175
+ className: "w-full h-full",
30176
+ crop: workspaceCrop?.crop,
30177
+ onClick: togglePlayback,
30178
+ autoplay: true,
30179
+ playsInline: true,
30180
+ loop: false,
30181
+ externalLoadingControl: true,
30182
+ onReady: handleVideoReady,
30183
+ onPlay: handleVideoPlay,
30184
+ onPause: handleVideoPause,
30185
+ onTimeUpdate: handleTimeUpdate,
30186
+ onDurationChange: handleDurationChange,
30187
+ onEnded: handleVideoEnded,
30188
+ onError: handleVideoError,
30189
+ onLoadedData: handleLoadedData,
30190
+ onPlaying: handleVideoPlaying,
30191
+ onLoadingChange: handleVideoLoadingChange,
30192
+ options: {
30193
+ fluid: false,
30194
+ responsive: false,
30195
+ fill: false
30196
+ }
30197
+ }
30198
+ )
30199
+ }
30200
+ ),
30201
+ (isTransitioning || isVideoBuffering && isInitialLoading) && !error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black", children: /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
30202
+ !isTransitioning && isVideoBuffering && !isInitialLoading && !error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
30203
+ /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-white", children: [
30204
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
30205
+ /* @__PURE__ */ jsxRuntime.jsx(
30206
+ "button",
30207
+ {
30208
+ onClick: (e) => {
30209
+ e.stopPropagation();
30210
+ togglePlayback();
30211
+ },
30212
+ className: "p-2 hover:bg-white/20 rounded-full focus:outline-none focus:ring-2 focus:ring-white/50",
30213
+ "aria-label": isPlaying ? "Pause" : "Play",
30214
+ children: isPlaying ? /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-6 w-6", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-6 w-6", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.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" }) })
30215
+ }
30216
+ ),
30217
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-mono px-2", children: [
30218
+ formatTime2(currentTime),
30219
+ " / ",
30220
+ formatTime2(duration)
30221
+ ] })
30222
+ ] }),
30223
+ /* @__PURE__ */ jsxRuntime.jsx(
30224
+ "input",
30225
+ {
30226
+ type: "range",
30227
+ min: "0",
30228
+ max: duration || 0,
30229
+ value: currentTime,
30230
+ onChange: (e) => {
30231
+ if (videoRef.current) {
30232
+ videoRef.current.currentTime(Number(e.target.value));
30233
+ }
30234
+ },
30235
+ 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",
30236
+ style: {
30237
+ WebkitAppearance: "none",
30238
+ appearance: "none"
30239
+ },
30240
+ "aria-label": "Seek slider"
30241
+ }
30242
+ ),
30243
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
30244
+ /* @__PURE__ */ jsxRuntime.jsx(
30245
+ "button",
30246
+ {
30247
+ onClick: handlePrevious,
30248
+ disabled: currentMetadataIndex <= 0,
30249
+ className: `p-2 rounded-full transition-colors ${currentMetadataIndex <= 0 ? "text-gray-500 cursor-not-allowed" : "text-white hover:bg-white/20"}`,
30250
+ "aria-label": "Previous clip",
30251
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "h-5 w-5" })
30252
+ }
30253
+ ),
30254
+ /* @__PURE__ */ jsxRuntime.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" }),
30255
+ /* @__PURE__ */ jsxRuntime.jsx(
30256
+ "button",
30257
+ {
30258
+ onClick: handleNext,
30259
+ disabled: currentMetadataIndex >= categoryMetadata.length - 1,
30260
+ className: `p-2 rounded-full transition-colors ${currentMetadataIndex >= categoryMetadata.length - 1 ? "text-gray-500 cursor-not-allowed" : "text-white hover:bg-white/20"}`,
30261
+ "aria-label": "Next clip",
30262
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-5 w-5" })
30263
+ }
30264
+ )
30265
+ ] })
30266
+ ] }) })
30267
+ ] }) })
30268
+ ]
30269
+ }
30270
+ ),
29427
30271
  !triageMode && /* @__PURE__ */ jsxRuntime.jsx(
29428
30272
  AdvancedFilterDialog,
29429
30273
  {
@@ -35761,20 +36605,7 @@ var SideNavBar = React23.memo(({
35761
36605
  onClick: handleLogoClick,
35762
36606
  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",
35763
36607
  "aria-label": "Go to home page",
35764
- children: /* @__PURE__ */ jsxRuntime.jsx(
35765
- "img",
35766
- {
35767
- src: "/optifye-logo.png",
35768
- alt: "Optifye",
35769
- className: "w-12 h-12 object-contain cursor-pointer",
35770
- onError: (e) => {
35771
- e.currentTarget.style.display = "none";
35772
- if (e.currentTarget.parentElement) {
35773
- e.currentTarget.parentElement.innerHTML = '<span class="text-blue-600 font-bold text-lg cursor-pointer">OP</span>';
35774
- }
35775
- }
35776
- }
35777
- )
36608
+ children: /* @__PURE__ */ jsxRuntime.jsx(Logo, { className: "w-12 h-12 object-contain cursor-pointer" })
35778
36609
  }
35779
36610
  ) }),
35780
36611
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 w-full py-6 px-4 overflow-y-auto", children: [
@@ -36152,20 +36983,7 @@ var SideNavBar = React23.memo(({
36152
36983
  ),
36153
36984
  /* @__PURE__ */ jsxRuntime.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: [
36154
36985
  /* @__PURE__ */ jsxRuntime.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: [
36155
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
36156
- "img",
36157
- {
36158
- src: "/optifye-logo.png",
36159
- alt: "Optifye",
36160
- className: "w-11 h-11 object-contain",
36161
- onError: (e) => {
36162
- e.currentTarget.style.display = "none";
36163
- if (e.currentTarget.parentElement) {
36164
- e.currentTarget.parentElement.innerHTML = '<span class="text-blue-600 font-bold text-xl">Optifye</span>';
36165
- }
36166
- }
36167
- }
36168
- ) }),
36986
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(Logo, { className: "w-11 h-11 object-contain" }) }),
36169
36987
  /* @__PURE__ */ jsxRuntime.jsx(
36170
36988
  "button",
36171
36989
  {
@@ -36274,20 +37092,7 @@ var MainLayout = ({
36274
37092
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `min-h-screen ${className}`, children: [
36275
37093
  /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
36276
37094
  /* @__PURE__ */ jsxRuntime.jsx(HamburgerButton, { onClick: handleMobileMenuOpen }),
36277
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(
36278
- "img",
36279
- {
36280
- src: "/optifye-logo.png",
36281
- alt: "Optifye",
36282
- className: "h-9 w-9 object-contain",
36283
- onError: (e) => {
36284
- e.currentTarget.style.display = "none";
36285
- if (e.currentTarget.parentElement) {
36286
- e.currentTarget.parentElement.innerHTML = '<span class="text-blue-600 font-bold text-lg">Optifye</span>';
36287
- }
36288
- }
36289
- }
36290
- ) })
37095
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(Logo, { className: "h-9 w-9 object-contain" }) })
36291
37096
  ] }) }),
36292
37097
  /* @__PURE__ */ jsxRuntime.jsx(
36293
37098
  SideNavBar,
@@ -37897,23 +38702,29 @@ var ThreadSidebar = ({
37897
38702
  ] }) })
37898
38703
  ] });
37899
38704
  };
37900
- var axelProfilePng = "/axel-profile.png";
37901
- var ProfilePicture = React23__namespace.default.memo(({ alt = "Axel", className = "w-8 h-8 sm:w-10 sm:h-10 md:w-12 md:h-12" }) => {
37902
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${className} rounded-xl overflow-hidden shadow-sm`, children: /* @__PURE__ */ jsxRuntime.jsx(
37903
- "img",
37904
- {
37905
- src: axelProfilePng,
37906
- alt,
37907
- className: "w-full h-full object-cover",
37908
- loading: "eager",
37909
- decoding: "async"
37910
- }
37911
- ) }) });
38705
+ var ProfilePicture = React23__namespace.default.memo(({
38706
+ alt = "Axel",
38707
+ className = "",
38708
+ size = "md",
38709
+ animate = false
38710
+ }) => {
38711
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(AxelOrb, { size, animate }) });
37912
38712
  });
37913
38713
  ProfilePicture.displayName = "ProfilePicture";
37914
- var preloadImage = (src) => {
37915
- const img = new Image();
37916
- img.src = src;
38714
+ var GREETING_MESSAGES = [
38715
+ "How can I help you today?",
38716
+ "What would you like to know?",
38717
+ "Ready to optimize your operations?",
38718
+ "How can I assist you today?"
38719
+ ];
38720
+ var getDailyGreeting = () => {
38721
+ const now2 = /* @__PURE__ */ new Date();
38722
+ const startOfYear = new Date(now2.getFullYear(), 0, 0);
38723
+ const diff = now2.getTime() - startOfYear.getTime();
38724
+ const oneDay = 1e3 * 60 * 60 * 24;
38725
+ const dayOfYear = Math.floor(diff / oneDay);
38726
+ const index = dayOfYear % GREETING_MESSAGES.length;
38727
+ return GREETING_MESSAGES[index];
37917
38728
  };
37918
38729
  var AIAgentView = () => {
37919
38730
  const { navigate, pathname } = useNavigation();
@@ -37940,6 +38751,7 @@ var AIAgentView = () => {
37940
38751
  const [lastTypingTime, setLastTypingTime] = React23.useState(null);
37941
38752
  const [characterCount, setCharacterCount] = React23.useState(0);
37942
38753
  const typingTimeoutRef = React23.useRef(null);
38754
+ const currentGreeting = React23.useMemo(() => getDailyGreeting(), [greetingReset]);
37943
38755
  const isThreadLoading = (threadId) => {
37944
38756
  return threadId ? loadingThreads.has(threadId) : false;
37945
38757
  };
@@ -38093,12 +38905,11 @@ var AIAgentView = () => {
38093
38905
  }, [activeThreadId]);
38094
38906
  React23.useEffect(() => {
38095
38907
  if (messages.length === 0 && !isTransitioning) {
38096
- const fullText = "Hi, I'm Axel - Your AI Supervisor";
38097
38908
  let index = 0;
38098
38909
  setTypedText("");
38099
38910
  const typeInterval = setInterval(() => {
38100
- if (index < fullText.length) {
38101
- setTypedText(fullText.substring(0, index + 1));
38911
+ if (index < currentGreeting.length) {
38912
+ setTypedText(currentGreeting.substring(0, index + 1));
38102
38913
  index++;
38103
38914
  } else {
38104
38915
  clearInterval(typeInterval);
@@ -38106,7 +38917,7 @@ var AIAgentView = () => {
38106
38917
  }, 50);
38107
38918
  return () => clearInterval(typeInterval);
38108
38919
  }
38109
- }, [messages.length, isTransitioning, greetingReset]);
38920
+ }, [messages.length, isTransitioning, greetingReset, currentGreeting]);
38110
38921
  React23.useEffect(() => {
38111
38922
  if (isSidebarOpen) {
38112
38923
  setNewChatCount(0);
@@ -38132,9 +38943,6 @@ var AIAgentView = () => {
38132
38943
  localStorage.removeItem(ACTIVE_THREAD_STORAGE_KEY);
38133
38944
  textareaRef.current?.focus();
38134
38945
  };
38135
- React23.useEffect(() => {
38136
- preloadImage(axelProfilePng);
38137
- }, []);
38138
38946
  React23.useEffect(() => {
38139
38947
  return () => {
38140
38948
  if (typingTimeoutRef.current) {
@@ -39609,10 +40417,10 @@ var AIAgentView = () => {
39609
40417
  /* Centered welcome and input for new chat */
39610
40418
  /* @__PURE__ */ jsxRuntime.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: [
39611
40419
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
39612
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center mb-4 sm:mb-6 md:mb-8", children: /* @__PURE__ */ jsxRuntime.jsx(ProfilePicture, { alt: "Axel - AI Manufacturing Expert", className: "w-16 h-16 sm:w-20 sm:h-20 md:w-24 md:h-24" }) }),
40420
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center mb-4 sm:mb-6 md:mb-8", children: /* @__PURE__ */ jsxRuntime.jsx(ProfilePicture, { alt: "Axel - AI Manufacturing Expert", size: "2xl", animate: true }) }),
39613
40421
  /* @__PURE__ */ jsxRuntime.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: [
39614
40422
  typedText,
39615
- typedText.length < "Hi, I'm Axel - Your AI Supervisor".length && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "animate-pulse", children: "|" })
40423
+ typedText.length < currentGreeting.length && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "animate-pulse", children: "|" })
39616
40424
  ] })
39617
40425
  ] }),
39618
40426
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full max-w-2xl", children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, children: [
@@ -42979,7 +43787,7 @@ LeaderboardDetailView.displayName = "LeaderboardDetailView";
42979
43787
  var LeaderboardDetailViewWithDisplayNames = withAllWorkspaceDisplayNames(LeaderboardDetailView);
42980
43788
  var LeaderboardDetailView_default = LeaderboardDetailViewWithDisplayNames;
42981
43789
  function LoginView({
42982
- logoSrc = "/optifye-logo.png",
43790
+ logoSrc = optifye_logo_default,
42983
43791
  logoAlt = "Optifye",
42984
43792
  brandName = "Optifye",
42985
43793
  onRateLimitCheck
@@ -46059,6 +46867,26 @@ var getInitialTab = (sourceType, defaultTab, fromMonthly, urlDate) => {
46059
46867
  }
46060
46868
  return "overview";
46061
46869
  };
46870
+ var WorkspaceHealthStatusBadge = ({
46871
+ workspaceId,
46872
+ mode = "full",
46873
+ className = "",
46874
+ showHealthDot = false
46875
+ }) => {
46876
+ const { timeSinceUpdate, isHealthy, loading, error } = useWorkspaceHealthStatus(workspaceId);
46877
+ if (loading || error) {
46878
+ return null;
46879
+ }
46880
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center gap-2 ${className}`, children: [
46881
+ showHealthDot && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(
46882
+ "div",
46883
+ {
46884
+ className: `h-2 w-2 rounded-full ${isHealthy ? "bg-green-500 animate-pulse" : "bg-red-500"}`
46885
+ }
46886
+ ) }),
46887
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-500", children: mode === "full" ? `Last updated: ${timeSinceUpdate}` : timeSinceUpdate })
46888
+ ] });
46889
+ };
46062
46890
  var WorkspaceDetailView = ({
46063
46891
  workspaceId,
46064
46892
  date,
@@ -46154,82 +46982,6 @@ var WorkspaceDetailView = ({
46154
46982
  const workspace = isHistoricView ? historicMetrics : liveMetrics;
46155
46983
  const loading = isHistoricView ? historicLoading : liveLoading;
46156
46984
  const error = isHistoricView ? historicError : liveError;
46157
- const audioService = useAudioService();
46158
- const { latestAchievement, hasNewAchievements } = useHourlyTargetAchievements({
46159
- hourlyData: workspace?.hourly_action_counts || [],
46160
- targetThreshold: workspace?.pph_threshold || 0,
46161
- shiftStart: workspace?.shift_start || "06:00",
46162
- enabled: !isHistoricView && Boolean(workspace)
46163
- // Only for live data
46164
- });
46165
- const { latestMiss, hasNewMiss } = useHourlyTargetMisses({
46166
- hourlyData: workspace?.hourly_action_counts || [],
46167
- targetThreshold: workspace?.pph_threshold || 0,
46168
- shiftStart: workspace?.shift_start || "06:00",
46169
- enabled: !isHistoricView && Boolean(workspace)
46170
- // Only for live data
46171
- });
46172
- const [showCongratulations, setShowCongratulations] = React23.useState(false);
46173
- const [currentAchievement, setCurrentAchievement] = React23.useState(null);
46174
- const [showEncouragement, setShowEncouragement] = React23.useState(false);
46175
- const [currentMiss, setCurrentMiss] = React23.useState(null);
46176
- const [audioReady, setAudioReady] = React23.useState(false);
46177
- React23.useEffect(() => {
46178
- if (hasNewAchievements && latestAchievement && !isHistoricView) {
46179
- console.log("[\u{1F389} ACHIEVEMENT UNLOCKED! \u{1F389}] Target reached!", latestAchievement);
46180
- const startCelebration = async () => {
46181
- setCurrentAchievement(latestAchievement);
46182
- setShowCongratulations(true);
46183
- setTimeout(async () => {
46184
- try {
46185
- console.log("[\u{1F3B5} CELEBRATION FANFARE] Playing victory audio...");
46186
- await audioService.playCongratsSound();
46187
- console.log("[\u2705 AUDIO SUCCESS] Celebration fanfare completed!");
46188
- } catch (err) {
46189
- console.warn("[\u274C AUDIO ERROR] Failed to play congratulations sound:", err);
46190
- }
46191
- }, 300);
46192
- console.log(`[\u{1F4CA} ACHIEVEMENT ANALYTICS] Worker hit target: ${latestAchievement.currentValue}/${latestAchievement.targetValue} during ${latestAchievement.timeRange}`);
46193
- };
46194
- startCelebration();
46195
- }
46196
- }, [hasNewAchievements, latestAchievement, isHistoricView, audioService]);
46197
- React23.useEffect(() => {
46198
- if (hasNewMiss && latestMiss && !isHistoricView) {
46199
- console.log("[\u{1F499} ENCOURAGEMENT NEEDED] Target not reached, showing support", latestMiss);
46200
- const startEncouragement = async () => {
46201
- setCurrentMiss(latestMiss);
46202
- setShowEncouragement(true);
46203
- setTimeout(async () => {
46204
- try {
46205
- console.log("[\u{1F3B5} GENTLE ENCOURAGEMENT] Playing supportive audio...");
46206
- await audioService.playEncouragementSound();
46207
- console.log("[\u2705 AUDIO SUCCESS] Encouragement audio completed!");
46208
- } catch (err) {
46209
- console.warn("[\u274C AUDIO ERROR] Failed to play encouragement sound:", err);
46210
- }
46211
- }, 300);
46212
- console.log(`[\u{1F4CA} ENCOURAGEMENT ANALYTICS] Target missed: ${latestMiss.actualValue}/${latestMiss.targetValue} (${Math.round(latestMiss.actualValue / latestMiss.targetValue * 100)}% achieved)`);
46213
- };
46214
- startEncouragement();
46215
- }
46216
- }, [hasNewMiss, latestMiss, isHistoricView, audioService]);
46217
- React23.useEffect(() => {
46218
- const handleUserInteraction = () => {
46219
- console.log("[\u{1F50A} AUDIO ENABLED] User interaction detected - celebration sounds ready!");
46220
- audioService.markUserInteraction();
46221
- setAudioReady(true);
46222
- };
46223
- console.log("[\u{1F3A7} AUDIO SETUP] Setting up celebration audio listeners...");
46224
- document.addEventListener("click", handleUserInteraction);
46225
- document.addEventListener("touchstart", handleUserInteraction);
46226
- document.addEventListener("keydown", handleUserInteraction);
46227
- return () => {
46228
- document.removeEventListener("click", handleUserInteraction);
46229
- document.removeEventListener("touchstart", handleUserInteraction);
46230
- document.removeEventListener("keydown", handleUserInteraction);
46231
- };
46232
- }, [audioService]);
46233
46985
  React23.useEffect(() => {
46234
46986
  if (onTabChange) {
46235
46987
  onTabChange(activeTab);
@@ -46445,113 +47197,160 @@ var WorkspaceDetailView = ({
46445
47197
  )
46446
47198
  ] });
46447
47199
  }
46448
- return /* @__PURE__ */ jsxRuntime.jsxs(
47200
+ return /* @__PURE__ */ jsxRuntime.jsx(
46449
47201
  motion.div,
46450
47202
  {
46451
47203
  className: `min-h-screen bg-slate-50 ${className}`,
46452
47204
  initial: { opacity: 1 },
46453
47205
  animate: { opacity: 1 },
46454
- children: [
46455
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-h-screen w-full flex flex-col bg-slate-50", children: [
46456
- /* @__PURE__ */ jsxRuntime.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: [
46457
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
46458
- /* @__PURE__ */ jsxRuntime.jsx(
46459
- "button",
46460
- {
46461
- onClick: handleBackNavigation,
46462
- className: "p-2 -ml-2 rounded-full active:bg-gray-100 transition-colors",
46463
- "aria-label": "Navigate back",
46464
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { className: "w-5 h-5 text-gray-700" })
46465
- }
46466
- ),
46467
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col items-center justify-center", children: [
46468
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
46469
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-base font-semibold text-gray-900 truncate max-w-[220px]", children: formattedWorkspaceName }),
46470
- workspaceHealth && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex h-2 w-2", children: [
46471
- workspaceHealth.status === "healthy" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" }),
46472
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx(
46473
- "relative inline-flex rounded-full h-2 w-2",
46474
- workspaceHealth.status === "healthy" ? "bg-green-500" : "bg-red-500"
46475
- ) })
46476
- ] }) })
46477
- ] }),
46478
- workspaceHealth && activeTab !== "monthly_history" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-gray-500 mt-0.5", children: workspaceHealth.timeSinceLastUpdate })
46479
- ] }),
46480
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-9" })
46481
- ] }) }),
46482
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center", children: [
46483
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-0 z-10", children: /* @__PURE__ */ jsxRuntime.jsx(
46484
- BackButtonMinimal,
46485
- {
46486
- onClick: handleBackNavigation,
46487
- 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",
46488
- size: "default",
46489
- "aria-label": "Navigate back to previous page"
46490
- }
46491
- ) }),
46492
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-1/2 transform -translate-x-1/2 max-w-[calc(100%-200px)]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
46493
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-lg md:text-xl lg:text-2xl xl:text-3xl font-semibold text-gray-900 truncate", children: formattedWorkspaceName }),
46494
- workspaceHealth && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex h-2.5 w-2.5", children: [
46495
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx(
46496
- "animate-ping absolute inline-flex h-full w-full rounded-full opacity-75",
46497
- workspaceHealth.status === "healthy" ? "bg-green-400" : "bg-red-400"
46498
- ) }),
47206
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-h-screen w-full flex flex-col bg-slate-50", children: [
47207
+ /* @__PURE__ */ jsxRuntime.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: [
47208
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
47209
+ /* @__PURE__ */ jsxRuntime.jsx(
47210
+ "button",
47211
+ {
47212
+ onClick: handleBackNavigation,
47213
+ className: "p-2 -ml-2 rounded-full active:bg-gray-100 transition-colors",
47214
+ "aria-label": "Navigate back",
47215
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { className: "w-5 h-5 text-gray-700" })
47216
+ }
47217
+ ),
47218
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col items-center justify-center", children: [
47219
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
47220
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-base font-semibold text-gray-900 truncate max-w-[220px]", children: formattedWorkspaceName }),
47221
+ workspaceHealth && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex h-2 w-2", children: [
47222
+ workspaceHealth.status === "healthy" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" }),
46499
47223
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx(
46500
- "relative inline-flex rounded-full h-2.5 w-2.5",
47224
+ "relative inline-flex rounded-full h-2 w-2",
46501
47225
  workspaceHealth.status === "healthy" ? "bg-green-500" : "bg-red-500"
46502
47226
  ) })
46503
- ] })
46504
- ] }) }),
46505
- workspaceHealth && activeTab !== "monthly_history" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-0 top-0 flex items-center h-8", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-500", children: [
47227
+ ] }) })
47228
+ ] }),
47229
+ activeTab !== "monthly_history" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-0.5", children: [
47230
+ workspaceHealth && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-gray-500", children: workspaceHealth.timeSinceLastUpdate }),
47231
+ /* @__PURE__ */ jsxRuntime.jsx(
47232
+ WorkspaceHealthStatusBadge,
47233
+ {
47234
+ workspaceId,
47235
+ mode: "compact",
47236
+ showHealthDot: false,
47237
+ className: "text-[10px]"
47238
+ }
47239
+ )
47240
+ ] })
47241
+ ] }),
47242
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-9" })
47243
+ ] }) }),
47244
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center", children: [
47245
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-0 z-10", children: /* @__PURE__ */ jsxRuntime.jsx(
47246
+ BackButtonMinimal,
47247
+ {
47248
+ onClick: handleBackNavigation,
47249
+ 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",
47250
+ size: "default",
47251
+ "aria-label": "Navigate back to previous page"
47252
+ }
47253
+ ) }),
47254
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-1/2 transform -translate-x-1/2 max-w-[calc(100%-200px)]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
47255
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-lg md:text-xl lg:text-2xl xl:text-3xl font-semibold text-gray-900 truncate", children: formattedWorkspaceName }),
47256
+ workspaceHealth && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex h-2.5 w-2.5", children: [
47257
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx(
47258
+ "animate-ping absolute inline-flex h-full w-full rounded-full opacity-75",
47259
+ workspaceHealth.status === "healthy" ? "bg-green-400" : "bg-red-400"
47260
+ ) }),
47261
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx(
47262
+ "relative inline-flex rounded-full h-2.5 w-2.5",
47263
+ workspaceHealth.status === "healthy" ? "bg-green-500" : "bg-red-500"
47264
+ ) })
47265
+ ] })
47266
+ ] }) }),
47267
+ activeTab !== "monthly_history" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute right-0 top-0 flex flex-col items-end gap-1", children: [
47268
+ workspaceHealth && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-500", children: [
46506
47269
  "Last update: ",
46507
47270
  workspaceHealth.timeSinceLastUpdate
46508
- ] }) }),
46509
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-8" })
46510
- ] }) }),
46511
- activeTab !== "monthly_history" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
46512
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sm:hidden mt-3 flex items-center justify-center gap-2", children: [
46513
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-gray-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-700", children: formatISTDate2(new Date(workspace.date)) }) }),
46514
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-1 px-2.5 py-1 bg-gray-100 rounded-full", children: [
46515
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-700 scale-90", children: getShiftIcon(workspace.shift_type) }),
46516
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-700", children: workspace.shift_type })
46517
- ] }),
46518
- !date && !shift && !usingFallbackData ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-green-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-green-700", children: /* @__PURE__ */ jsxRuntime.jsx(LiveTimer, {}) }) }) : date ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-blue-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-blue-700", children: getDaysDifference(workspace.date, timezone, dashboardConfig?.shiftConfig?.dayShift?.startTime || "06:00") }) }) : usingFallbackData ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-amber-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-amber-700", children: getDaysDifference(workspace.date, timezone, dashboardConfig?.shiftConfig?.dayShift?.startTime || "06:00") }) }) : null
46519
47271
  ] }),
46520
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block mt-3 bg-blue-50 px-3 py-2 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-3 md:gap-4", children: [
46521
- !date && !shift && !usingFallbackData && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
46522
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base md:text-lg font-medium text-blue-600", children: /* @__PURE__ */ jsxRuntime.jsx(LiveTimer, {}) }),
46523
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-300" })
46524
- ] }),
46525
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm md:text-base font-medium text-blue-600", children: formatISTDate2(new Date(workspace.date)) }),
46526
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-300" }),
46527
- date && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
46528
- /* @__PURE__ */ jsxRuntime.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") }),
46529
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-300" })
46530
- ] }),
46531
- !date && !shift && usingFallbackData && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
46532
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-2 py-1 text-xs font-medium bg-amber-100 text-amber-700 rounded-md", children: [
46533
- "Latest available data (",
46534
- getDaysDifference(workspace.date, timezone, dashboardConfig?.shiftConfig?.dayShift?.startTime || "06:00"),
46535
- ")"
46536
- ] }),
46537
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-300" })
47272
+ /* @__PURE__ */ jsxRuntime.jsx(
47273
+ WorkspaceHealthStatusBadge,
47274
+ {
47275
+ workspaceId,
47276
+ mode: "full",
47277
+ showHealthDot: false
47278
+ }
47279
+ )
47280
+ ] }),
47281
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-8" })
47282
+ ] }) }),
47283
+ activeTab !== "monthly_history" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
47284
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sm:hidden mt-3 flex items-center justify-center gap-2", children: [
47285
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-gray-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-700", children: formatISTDate2(new Date(workspace.date)) }) }),
47286
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-1 px-2.5 py-1 bg-gray-100 rounded-full", children: [
47287
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-700 scale-90", children: getShiftIcon(workspace.shift_type) }),
47288
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-700", children: workspace.shift_type })
47289
+ ] }),
47290
+ !date && !shift && !usingFallbackData ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-green-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-green-700", children: /* @__PURE__ */ jsxRuntime.jsx(LiveTimer, {}) }) }) : date ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-blue-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-blue-700", children: getDaysDifference(workspace.date, timezone, dashboardConfig?.shiftConfig?.dayShift?.startTime || "06:00") }) }) : usingFallbackData ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-amber-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-amber-700", children: getDaysDifference(workspace.date, timezone, dashboardConfig?.shiftConfig?.dayShift?.startTime || "06:00") }) }) : null
47291
+ ] }),
47292
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block mt-3 bg-blue-50 px-3 py-2 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-3 md:gap-4", children: [
47293
+ !date && !shift && !usingFallbackData && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
47294
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base md:text-lg font-medium text-blue-600", children: /* @__PURE__ */ jsxRuntime.jsx(LiveTimer, {}) }),
47295
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-300" })
47296
+ ] }),
47297
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm md:text-base font-medium text-blue-600", children: formatISTDate2(new Date(workspace.date)) }),
47298
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-300" }),
47299
+ date && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
47300
+ /* @__PURE__ */ jsxRuntime.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") }),
47301
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-300" })
47302
+ ] }),
47303
+ !date && !shift && usingFallbackData && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
47304
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-2 py-1 text-xs font-medium bg-amber-100 text-amber-700 rounded-md", children: [
47305
+ "Latest available data (",
47306
+ getDaysDifference(workspace.date, timezone, dashboardConfig?.shiftConfig?.dayShift?.startTime || "06:00"),
47307
+ ")"
46538
47308
  ] }),
46539
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
46540
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-blue-600", children: getShiftIcon(workspace.shift_type) }),
46541
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm md:text-base font-medium text-blue-600", children: [
46542
- workspace.shift_type,
46543
- " Shift"
46544
- ] })
47309
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-300" })
47310
+ ] }),
47311
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
47312
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-blue-600", children: getShiftIcon(workspace.shift_type) }),
47313
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm md:text-base font-medium text-blue-600", children: [
47314
+ workspace.shift_type,
47315
+ " Shift"
46545
47316
  ] })
46546
- ] }) })
46547
- ] }),
46548
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 sm:mt-1.5 lg:mt-2", children: [
46549
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex bg-gray-100 rounded-lg p-0.5", children: [
47317
+ ] })
47318
+ ] }) })
47319
+ ] }),
47320
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 sm:mt-1.5 lg:mt-2", children: [
47321
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex bg-gray-100 rounded-lg p-0.5", children: [
47322
+ /* @__PURE__ */ jsxRuntime.jsx(
47323
+ "button",
47324
+ {
47325
+ onClick: () => setActiveTab("overview"),
47326
+ 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"}`,
47327
+ children: "Efficiency"
47328
+ }
47329
+ ),
47330
+ isClipsEnabled && /* @__PURE__ */ jsxRuntime.jsx(
47331
+ "button",
47332
+ {
47333
+ onClick: () => setActiveTab("bottlenecks"),
47334
+ 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"}`,
47335
+ children: "Clips"
47336
+ }
47337
+ ),
47338
+ /* @__PURE__ */ jsxRuntime.jsx(
47339
+ "button",
47340
+ {
47341
+ onClick: () => setActiveTab("monthly_history"),
47342
+ 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"}`,
47343
+ children: "History"
47344
+ }
47345
+ )
47346
+ ] }) }),
47347
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden sm:flex items-center justify-between", children: [
47348
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1.5 lg:gap-2", children: [
46550
47349
  /* @__PURE__ */ jsxRuntime.jsx(
46551
47350
  "button",
46552
47351
  {
46553
47352
  onClick: () => setActiveTab("overview"),
46554
- 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"}`,
47353
+ 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"}`,
46555
47354
  children: "Efficiency"
46556
47355
  }
46557
47356
  ),
@@ -46559,7 +47358,7 @@ var WorkspaceDetailView = ({
46559
47358
  "button",
46560
47359
  {
46561
47360
  onClick: () => setActiveTab("bottlenecks"),
46562
- 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"}`,
47361
+ 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"}`,
46563
47362
  children: "Clips"
46564
47363
  }
46565
47364
  ),
@@ -46567,59 +47366,151 @@ var WorkspaceDetailView = ({
46567
47366
  "button",
46568
47367
  {
46569
47368
  onClick: () => setActiveTab("monthly_history"),
46570
- 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"}`,
46571
- children: "History"
47369
+ 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"}`,
47370
+ children: "Monthly History"
46572
47371
  }
46573
47372
  )
46574
- ] }) }),
46575
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden sm:flex items-center justify-between", children: [
46576
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1.5 lg:gap-2", children: [
46577
- /* @__PURE__ */ jsxRuntime.jsx(
46578
- "button",
46579
- {
46580
- onClick: () => setActiveTab("overview"),
46581
- 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"}`,
46582
- children: "Efficiency"
46583
- }
46584
- ),
46585
- isClipsEnabled && /* @__PURE__ */ jsxRuntime.jsx(
46586
- "button",
46587
- {
46588
- onClick: () => setActiveTab("bottlenecks"),
46589
- 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"}`,
46590
- children: "Clips"
46591
- }
46592
- ),
46593
- /* @__PURE__ */ jsxRuntime.jsx(
47373
+ ] }),
47374
+ activeTab === "overview" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1.5 lg:gap-2", children: renderHeaderActions ? renderHeaderActions(workspace) : /* @__PURE__ */ jsxRuntime.jsx(WorkspacePdfGenerator, { workspace }) }),
47375
+ activeTab === "monthly_history" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1.5 lg:gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
47376
+ WorkspaceMonthlyPdfGenerator,
47377
+ {
47378
+ workspaceId,
47379
+ workspaceName: workspace?.workspace_name || "",
47380
+ monthlyData,
47381
+ selectedMonth,
47382
+ selectedYear,
47383
+ selectedShift
47384
+ }
47385
+ ) })
47386
+ ] })
47387
+ ] })
47388
+ ] }),
47389
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-grow p-1.5 sm:p-2 lg:p-4", children: [
47390
+ activeTab === "overview" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full lg:h-[calc(100vh-10rem)] overflow-y-auto lg:overflow-hidden", children: [
47391
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "block lg:hidden space-y-6 pb-6", children: [
47392
+ !shouldShowCycleTimeChart && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm p-6", children: [
47393
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-700 mb-8", children: "Daily Progress" }),
47394
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center space-y-8", children: [
47395
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center space-y-1", children: [
47396
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-7xl font-bold tracking-tight", children: [
47397
+ (workspace.total_actions / workspace.target_output * 100).toFixed(1),
47398
+ "%"
47399
+ ] }),
47400
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center gap-2 text-gray-500", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-medium", children: "of today's target" }) })
47401
+ ] }),
47402
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
47403
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
47404
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-600", children: "Overall Progress" }),
47405
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-lg font-semibold text-gray-700", children: [
47406
+ workspace.total_actions,
47407
+ " / ",
47408
+ workspace.target_output
47409
+ ] })
47410
+ ] }),
47411
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full bg-gray-100 rounded-full h-2.5", children: /* @__PURE__ */ jsxRuntime.jsx(
47412
+ motion.div,
47413
+ {
47414
+ initial: { width: 0 },
47415
+ animate: {
47416
+ width: `${Math.min(100, workspace.total_actions / workspace.target_output * 100)}%`
47417
+ },
47418
+ transition: {
47419
+ duration: 1,
47420
+ ease: "easeOut",
47421
+ delay: 0.2
47422
+ },
47423
+ className: "bg-green-500 h-2.5 rounded-full"
47424
+ }
47425
+ ) })
47426
+ ] }) })
47427
+ ] })
47428
+ ] }),
47429
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm p-4", children: [
47430
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center mb-4", children: [
47431
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-700", children: shouldShowCycleTimeChart ? "Cycle Time (last 60 minutes)" : "Hourly Output" }),
47432
+ !shouldShowCycleTimeChart && /* @__PURE__ */ jsxRuntime.jsxs(
46594
47433
  "button",
46595
47434
  {
46596
- onClick: () => setActiveTab("monthly_history"),
46597
- 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"}`,
46598
- children: "Monthly History"
47435
+ onClick: () => setShowIdleTime(!showIdleTime),
47436
+ className: `
47437
+ flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded
47438
+ transition-all duration-200 border
47439
+ ${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"}
47440
+ `,
47441
+ "aria-label": showIdleTime ? "Hide idle time bars from chart" : "Show idle time bars on chart",
47442
+ children: [
47443
+ showIdleTime ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { className: "w-3.5 h-3.5" }),
47444
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: showIdleTime ? "Hide Idle Time" : "Show Idle Time" })
47445
+ ]
46599
47446
  }
46600
47447
  )
46601
47448
  ] }),
46602
- activeTab === "overview" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1.5 lg:gap-2", children: renderHeaderActions ? renderHeaderActions(workspace) : /* @__PURE__ */ jsxRuntime.jsx(WorkspacePdfGenerator, { workspace }) }),
46603
- activeTab === "monthly_history" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1.5 lg:gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
46604
- WorkspaceMonthlyPdfGenerator,
47449
+ /* @__PURE__ */ jsxRuntime.jsx(
47450
+ "div",
46605
47451
  {
46606
- workspaceId,
46607
- workspaceName: workspace?.workspace_name || "",
46608
- monthlyData,
46609
- selectedMonth,
46610
- selectedYear,
46611
- selectedShift
47452
+ className: "h-[300px]",
47453
+ style: { minHeight: "200px", minWidth: "300px" },
47454
+ children: shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsx(
47455
+ CycleTimeOverTimeChart,
47456
+ {
47457
+ data: workspace.hourly_action_counts || [],
47458
+ idealCycleTime: workspace.ideal_cycle_time || 0,
47459
+ shiftStart: workspace.shift_start || ""
47460
+ }
47461
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
47462
+ HourlyOutputChart2,
47463
+ {
47464
+ data: workspace.hourly_action_counts || [],
47465
+ pphThreshold: workspace.pph_threshold || 0,
47466
+ shiftStart: workspace.shift_start || "",
47467
+ shiftEnd: workspace.shift_end,
47468
+ showIdleTime,
47469
+ idleTimeHourly: workspace.idle_time_hourly
47470
+ }
47471
+ )
46612
47472
  }
46613
- ) })
46614
- ] })
46615
- ] })
46616
- ] }),
46617
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-grow p-1.5 sm:p-2 lg:p-4", children: [
46618
- activeTab === "overview" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full lg:h-[calc(100vh-10rem)] overflow-y-auto lg:overflow-hidden", children: [
46619
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "block lg:hidden space-y-6 pb-6", children: [
46620
- !shouldShowCycleTimeChart && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm p-6", children: [
47473
+ )
47474
+ ] }),
47475
+ shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
47476
+ /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
47477
+ /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Efficiency" }) }),
47478
+ /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
47479
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: `text-5xl font-bold ${(workspace.avg_efficiency || 0) >= 80 ? "text-green-500" : "text-red-500"}`, children: [
47480
+ (workspace.avg_efficiency || 0).toFixed(1),
47481
+ "%"
47482
+ ] }),
47483
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Target: 80%" })
47484
+ ] }) })
47485
+ ] }),
47486
+ /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
47487
+ /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
47488
+ /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
47489
+ /* @__PURE__ */ jsxRuntime.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) }),
47490
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
47491
+ "Standard: ",
47492
+ workspace.ideal_cycle_time?.toFixed(1) || 0,
47493
+ "s"
47494
+ ] })
47495
+ ] }) })
47496
+ ] }),
47497
+ /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
47498
+ /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Idle Time" }) }),
47499
+ /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
47500
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-4xl font-bold ${!workspace.idle_time || workspace.idle_time <= 0 ? "text-green-500" : workspace.idle_time <= 300 ? "text-yellow-500" : (
47501
+ // 5 minutes or less
47502
+ "text-red-500"
47503
+ )}`, children: formatIdleTime(workspace.idle_time) }),
47504
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Total idle time" })
47505
+ ] }) })
47506
+ ] })
47507
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(WorkspaceMetricCards, { workspace, className: "flex-1" }) })
47508
+ ] }),
47509
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden lg:flex lg:flex-col lg:h-full", children: [
47510
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-[60%] grid grid-cols-1 lg:grid-cols-5 gap-3 mb-3", children: [
47511
+ !shouldShowCycleTimeChart && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm p-6 lg:col-span-2", children: [
46621
47512
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-700 mb-8", children: "Daily Progress" }),
46622
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center space-y-8", children: [
47513
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-[calc(100%-6rem)] justify-center space-y-8", children: [
46623
47514
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center space-y-1", children: [
46624
47515
  /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-7xl font-bold tracking-tight", children: [
46625
47516
  (workspace.total_actions / workspace.target_output * 100).toFixed(1),
@@ -46654,7 +47545,7 @@ var WorkspaceDetailView = ({
46654
47545
  ] }) })
46655
47546
  ] })
46656
47547
  ] }),
46657
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm p-4", children: [
47548
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `bg-white rounded-lg shadow-sm p-4 ${shouldShowCycleTimeChart ? "lg:col-span-5" : "lg:col-span-3"}`, children: [
46658
47549
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center mb-4", children: [
46659
47550
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-700", children: shouldShowCycleTimeChart ? "Cycle Time (last 60 minutes)" : "Hourly Output" }),
46660
47551
  !shouldShowCycleTimeChart && /* @__PURE__ */ jsxRuntime.jsxs(
@@ -46662,10 +47553,10 @@ var WorkspaceDetailView = ({
46662
47553
  {
46663
47554
  onClick: () => setShowIdleTime(!showIdleTime),
46664
47555
  className: `
46665
- flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded
46666
- transition-all duration-200 border
46667
- ${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"}
46668
- `,
47556
+ flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded
47557
+ transition-all duration-200 border
47558
+ ${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"}
47559
+ `,
46669
47560
  "aria-label": showIdleTime ? "Hide idle time bars from chart" : "Show idle time bars on chart",
46670
47561
  children: [
46671
47562
  showIdleTime ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { className: "w-3.5 h-3.5" }),
@@ -46677,7 +47568,7 @@ var WorkspaceDetailView = ({
46677
47568
  /* @__PURE__ */ jsxRuntime.jsx(
46678
47569
  "div",
46679
47570
  {
46680
- className: "h-[300px]",
47571
+ className: "h-[calc(100%-3rem)]",
46681
47572
  style: { minHeight: "200px", minWidth: "300px" },
46682
47573
  children: shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsx(
46683
47574
  CycleTimeOverTimeChart,
@@ -46699,248 +47590,103 @@ var WorkspaceDetailView = ({
46699
47590
  )
46700
47591
  }
46701
47592
  )
46702
- ] }),
46703
- shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
46704
- /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
46705
- /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Efficiency" }) }),
46706
- /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
46707
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: `text-5xl font-bold ${(workspace.avg_efficiency || 0) >= 80 ? "text-green-500" : "text-red-500"}`, children: [
46708
- (workspace.avg_efficiency || 0).toFixed(1),
46709
- "%"
46710
- ] }),
46711
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Target: 80%" })
46712
- ] }) })
46713
- ] }),
46714
- /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
46715
- /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
46716
- /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
46717
- /* @__PURE__ */ jsxRuntime.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) }),
46718
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
46719
- "Standard: ",
46720
- workspace.ideal_cycle_time?.toFixed(1) || 0,
46721
- "s"
46722
- ] })
46723
- ] }) })
46724
- ] }),
46725
- /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
46726
- /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Idle Time" }) }),
46727
- /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
46728
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-4xl font-bold ${!workspace.idle_time || workspace.idle_time <= 0 ? "text-green-500" : workspace.idle_time <= 300 ? "text-yellow-500" : (
46729
- // 5 minutes or less
46730
- "text-red-500"
46731
- )}`, children: formatIdleTime(workspace.idle_time) }),
46732
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Total idle time" })
46733
- ] }) })
46734
- ] })
46735
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(WorkspaceMetricCards, { workspace, className: "flex-1" }) })
47593
+ ] })
46736
47594
  ] }),
46737
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden lg:flex lg:flex-col lg:h-full", children: [
46738
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-[60%] grid grid-cols-1 lg:grid-cols-5 gap-3 mb-3", children: [
46739
- !shouldShowCycleTimeChart && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm p-6 lg:col-span-2", children: [
46740
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-700 mb-8", children: "Daily Progress" }),
46741
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-[calc(100%-6rem)] justify-center space-y-8", children: [
46742
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center space-y-1", children: [
46743
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-7xl font-bold tracking-tight", children: [
46744
- (workspace.total_actions / workspace.target_output * 100).toFixed(1),
46745
- "%"
46746
- ] }),
46747
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center gap-2 text-gray-500", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-medium", children: "of today's target" }) })
46748
- ] }),
46749
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
46750
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
46751
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-600", children: "Overall Progress" }),
46752
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-lg font-semibold text-gray-700", children: [
46753
- workspace.total_actions,
46754
- " / ",
46755
- workspace.target_output
46756
- ] })
46757
- ] }),
46758
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full bg-gray-100 rounded-full h-2.5", children: /* @__PURE__ */ jsxRuntime.jsx(
46759
- motion.div,
46760
- {
46761
- initial: { width: 0 },
46762
- animate: {
46763
- width: `${Math.min(100, workspace.total_actions / workspace.target_output * 100)}%`
46764
- },
46765
- transition: {
46766
- duration: 1,
46767
- ease: "easeOut",
46768
- delay: 0.2
46769
- },
46770
- className: "bg-green-500 h-2.5 rounded-full"
46771
- }
46772
- ) })
46773
- ] }) })
46774
- ] })
46775
- ] }),
46776
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `bg-white rounded-lg shadow-sm p-4 ${shouldShowCycleTimeChart ? "lg:col-span-5" : "lg:col-span-3"}`, children: [
46777
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center mb-4", children: [
46778
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-700", children: shouldShowCycleTimeChart ? "Cycle Time (last 60 minutes)" : "Hourly Output" }),
46779
- !shouldShowCycleTimeChart && /* @__PURE__ */ jsxRuntime.jsxs(
46780
- "button",
46781
- {
46782
- onClick: () => setShowIdleTime(!showIdleTime),
46783
- className: `
46784
- flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded
46785
- transition-all duration-200 border
46786
- ${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"}
46787
- `,
46788
- "aria-label": showIdleTime ? "Hide idle time bars from chart" : "Show idle time bars on chart",
46789
- children: [
46790
- showIdleTime ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { className: "w-3.5 h-3.5" }),
46791
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: showIdleTime ? "Hide Idle Time" : "Show Idle Time" })
46792
- ]
46793
- }
46794
- )
47595
+ shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-[40%] grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3", children: [
47596
+ /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
47597
+ /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Efficiency" }) }),
47598
+ /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
47599
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: `text-5xl font-bold ${(workspace.avg_efficiency || 0) >= 80 ? "text-green-500" : "text-red-500"}`, children: [
47600
+ (workspace.avg_efficiency || 0).toFixed(1),
47601
+ "%"
46795
47602
  ] }),
46796
- /* @__PURE__ */ jsxRuntime.jsx(
46797
- "div",
46798
- {
46799
- className: "h-[calc(100%-3rem)]",
46800
- style: { minHeight: "200px", minWidth: "300px" },
46801
- children: shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsx(
46802
- CycleTimeOverTimeChart,
46803
- {
46804
- data: workspace.hourly_action_counts || [],
46805
- idealCycleTime: workspace.ideal_cycle_time || 0,
46806
- shiftStart: workspace.shift_start || ""
46807
- }
46808
- ) : /* @__PURE__ */ jsxRuntime.jsx(
46809
- HourlyOutputChart2,
46810
- {
46811
- data: workspace.hourly_action_counts || [],
46812
- pphThreshold: workspace.pph_threshold || 0,
46813
- shiftStart: workspace.shift_start || "",
46814
- shiftEnd: workspace.shift_end,
46815
- showIdleTime,
46816
- idleTimeHourly: workspace.idle_time_hourly
46817
- }
46818
- )
46819
- }
46820
- )
46821
- ] })
47603
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Target: 80%" })
47604
+ ] }) })
46822
47605
  ] }),
46823
- shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-[40%] grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3", children: [
46824
- /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
46825
- /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Efficiency" }) }),
46826
- /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
46827
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: `text-5xl font-bold ${(workspace.avg_efficiency || 0) >= 80 ? "text-green-500" : "text-red-500"}`, children: [
46828
- (workspace.avg_efficiency || 0).toFixed(1),
46829
- "%"
46830
- ] }),
46831
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Target: 80%" })
46832
- ] }) })
46833
- ] }),
46834
- /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
46835
- /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
46836
- /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
46837
- /* @__PURE__ */ jsxRuntime.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) }),
46838
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
46839
- "Standard: ",
46840
- workspace.ideal_cycle_time?.toFixed(1) || 0,
46841
- "s"
46842
- ] })
46843
- ] }) })
46844
- ] }),
46845
- /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
46846
- /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Idle Time" }) }),
46847
- /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
46848
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-4xl font-bold ${!workspace.idle_time || workspace.idle_time <= 0 ? "text-green-500" : workspace.idle_time <= 300 ? "text-yellow-500" : (
46849
- // 5 minutes or less
46850
- "text-red-500"
46851
- )}`, children: formatIdleTime(workspace.idle_time) }),
46852
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Total idle time" })
46853
- ] }) })
46854
- ] })
46855
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[40%] flex", children: /* @__PURE__ */ jsxRuntime.jsx(WorkspaceMetricCards, { workspace, className: "flex-1" }) })
46856
- ] })
46857
- ] }),
46858
- activeTab === "monthly_history" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-[calc(100vh-10rem)] overflow-y-auto px-2 sm:px-4 lg:px-0", children: [
46859
- workspaceId && activeTab === "monthly_history" && /* @__PURE__ */ jsxRuntime.jsx(
46860
- WorkspaceMonthlyDataFetcher,
46861
- {
46862
- workspaceId,
46863
- selectedMonth,
46864
- selectedYear,
46865
- onDataLoaded: handleMonthlyDataLoaded,
46866
- onLoadingChange: setMonthlyDataLoading
46867
- }
46868
- ),
46869
- usingFallbackData && !date && !shift && /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs("p", { className: "text-xs sm:text-sm font-medium flex items-center", children: [
46870
- /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.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" }) }),
46871
- "No current data available for today. Showing monthly history instead."
46872
- ] }) }),
46873
- /* @__PURE__ */ jsxRuntime.jsx(
46874
- WorkspaceMonthlyHistory,
46875
- {
46876
- data: monthlyData,
46877
- month: selectedMonth,
46878
- year: selectedYear,
46879
- workspaceId,
46880
- selectedShift,
46881
- monthlyDataLoading,
46882
- onDateSelect: (selectedDate, shift2) => {
46883
- if (onDateSelect) {
46884
- onDateSelect(selectedDate, shift2);
46885
- } else if (onNavigate) {
46886
- const params = new URLSearchParams();
46887
- params.set("date", selectedDate);
46888
- params.set("shift", shift2 === "day" ? "0" : "1");
46889
- params.set("fromMonthly", "true");
46890
- if (effectiveLineId) {
46891
- params.set("lineId", effectiveLineId);
46892
- }
46893
- onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
46894
- }
46895
- },
46896
- onMonthNavigate: (newMonth, newYear) => {
46897
- setSelectedMonth(newMonth);
46898
- setSelectedYear(newYear);
46899
- },
46900
- onShiftChange: setSelectedShift,
46901
- className: "w-full"
46902
- }
46903
- )
46904
- ] }),
46905
- activeTab === "bottlenecks" && /* @__PURE__ */ jsxRuntime.jsx(ClipFilterProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
46906
- BottlenecksContent,
47606
+ /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
47607
+ /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
47608
+ /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
47609
+ /* @__PURE__ */ jsxRuntime.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) }),
47610
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
47611
+ "Standard: ",
47612
+ workspace.ideal_cycle_time?.toFixed(1) || 0,
47613
+ "s"
47614
+ ] })
47615
+ ] }) })
47616
+ ] }),
47617
+ /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
47618
+ /* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Idle Time" }) }),
47619
+ /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
47620
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-4xl font-bold ${!workspace.idle_time || workspace.idle_time <= 0 ? "text-green-500" : workspace.idle_time <= 300 ? "text-yellow-500" : (
47621
+ // 5 minutes or less
47622
+ "text-red-500"
47623
+ )}`, children: formatIdleTime(workspace.idle_time) }),
47624
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Total idle time" })
47625
+ ] }) })
47626
+ ] })
47627
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[40%] flex", children: /* @__PURE__ */ jsxRuntime.jsx(WorkspaceMetricCards, { workspace, className: "flex-1" }) })
47628
+ ] })
47629
+ ] }),
47630
+ activeTab === "monthly_history" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-[calc(100vh-10rem)] overflow-y-auto px-2 sm:px-4 lg:px-0", children: [
47631
+ workspaceId && activeTab === "monthly_history" && /* @__PURE__ */ jsxRuntime.jsx(
47632
+ WorkspaceMonthlyDataFetcher,
46907
47633
  {
46908
47634
  workspaceId,
46909
- workspaceName: formattedWorkspaceName,
46910
- date,
46911
- shift,
46912
- totalOutput: workspace?.total_actions,
46913
- className: "h-[calc(100vh-10rem)]"
47635
+ selectedMonth,
47636
+ selectedYear,
47637
+ onDataLoaded: handleMonthlyDataLoaded,
47638
+ onLoadingChange: setMonthlyDataLoading
46914
47639
  }
46915
- ) })
46916
- ] })
46917
- ] }),
46918
- /* @__PURE__ */ jsxRuntime.jsx(
46919
- CongratulationsOverlay,
46920
- {
46921
- achievement: currentAchievement,
46922
- isVisible: showCongratulations,
46923
- duration: 6e4,
46924
- onDismiss: () => {
46925
- setShowCongratulations(false);
46926
- setCurrentAchievement(null);
47640
+ ),
47641
+ usingFallbackData && !date && !shift && /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs("p", { className: "text-xs sm:text-sm font-medium flex items-center", children: [
47642
+ /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.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" }) }),
47643
+ "No current data available for today. Showing monthly history instead."
47644
+ ] }) }),
47645
+ /* @__PURE__ */ jsxRuntime.jsx(
47646
+ WorkspaceMonthlyHistory,
47647
+ {
47648
+ data: monthlyData,
47649
+ month: selectedMonth,
47650
+ year: selectedYear,
47651
+ workspaceId,
47652
+ selectedShift,
47653
+ monthlyDataLoading,
47654
+ onDateSelect: (selectedDate, shift2) => {
47655
+ if (onDateSelect) {
47656
+ onDateSelect(selectedDate, shift2);
47657
+ } else if (onNavigate) {
47658
+ const params = new URLSearchParams();
47659
+ params.set("date", selectedDate);
47660
+ params.set("shift", shift2 === "day" ? "0" : "1");
47661
+ params.set("fromMonthly", "true");
47662
+ if (effectiveLineId) {
47663
+ params.set("lineId", effectiveLineId);
47664
+ }
47665
+ onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
47666
+ }
47667
+ },
47668
+ onMonthNavigate: (newMonth, newYear) => {
47669
+ setSelectedMonth(newMonth);
47670
+ setSelectedYear(newYear);
47671
+ },
47672
+ onShiftChange: setSelectedShift,
47673
+ className: "w-full"
47674
+ }
47675
+ )
47676
+ ] }),
47677
+ activeTab === "bottlenecks" && /* @__PURE__ */ jsxRuntime.jsx(ClipFilterProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
47678
+ BottlenecksContent,
47679
+ {
47680
+ workspaceId,
47681
+ workspaceName: formattedWorkspaceName,
47682
+ date,
47683
+ shift,
47684
+ totalOutput: workspace?.total_actions,
47685
+ className: "h-[calc(100vh-10rem)]"
46927
47686
  }
46928
- }
46929
- ),
46930
- /* @__PURE__ */ jsxRuntime.jsx(
46931
- EncouragementOverlay,
46932
- {
46933
- isVisible: showEncouragement,
46934
- onClose: () => {
46935
- setShowEncouragement(false);
46936
- setCurrentMiss(null);
46937
- },
46938
- targetValue: currentMiss?.targetValue || 0,
46939
- actualValue: currentMiss?.actualValue || 0,
46940
- metricName: currentMiss?.metricName || "Target"
46941
- }
46942
- )
46943
- ]
47687
+ ) })
47688
+ ] })
47689
+ ] })
46944
47690
  }
46945
47691
  );
46946
47692
  };
@@ -48055,21 +48801,36 @@ var LineAssignmentDropdown = ({
48055
48801
  const [isOpen, setIsOpen] = React23.useState(false);
48056
48802
  const [selectedIds, setSelectedIds] = React23.useState(currentLineIds);
48057
48803
  const [isSaving, setIsSaving] = React23.useState(false);
48804
+ const [position, setPosition] = React23.useState({ top: 0, left: 0, width: 0 });
48805
+ const buttonRef = React23.useRef(null);
48058
48806
  const dropdownRef = React23.useRef(null);
48059
48807
  React23.useEffect(() => {
48060
48808
  setSelectedIds(currentLineIds);
48061
48809
  }, [currentLineIds]);
48062
48810
  React23.useEffect(() => {
48063
- console.log("[LineAssignmentDropdown] Available lines updated:", {
48064
- userId,
48065
- count: availableLines.length,
48066
- lines: availableLines,
48067
- hasCompanyId: availableLines.every((l) => l.company_id)
48068
- });
48069
- }, [availableLines, userId]);
48811
+ const updatePosition = () => {
48812
+ if (isOpen && buttonRef.current) {
48813
+ const rect = buttonRef.current.getBoundingClientRect();
48814
+ setPosition({
48815
+ top: rect.bottom,
48816
+ left: rect.left,
48817
+ width: rect.width
48818
+ });
48819
+ }
48820
+ };
48821
+ if (isOpen) {
48822
+ updatePosition();
48823
+ window.addEventListener("scroll", updatePosition, true);
48824
+ window.addEventListener("resize", updatePosition);
48825
+ }
48826
+ return () => {
48827
+ window.removeEventListener("scroll", updatePosition, true);
48828
+ window.removeEventListener("resize", updatePosition);
48829
+ };
48830
+ }, [isOpen]);
48070
48831
  React23.useEffect(() => {
48071
48832
  const handleClickOutside = (event) => {
48072
- if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
48833
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target) && buttonRef.current && !buttonRef.current.contains(event.target)) {
48073
48834
  setIsOpen(false);
48074
48835
  setSelectedIds(currentLineIds);
48075
48836
  }
@@ -48135,94 +48896,106 @@ var LineAssignmentDropdown = ({
48135
48896
  if (!canEdit) {
48136
48897
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm", children: getDisplayText() });
48137
48898
  }
48138
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", ref: dropdownRef, children: [
48899
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
48139
48900
  /* @__PURE__ */ jsxRuntime.jsxs(
48140
48901
  "button",
48141
48902
  {
48903
+ ref: buttonRef,
48142
48904
  onClick: () => setIsOpen(!isOpen),
48143
48905
  className: cn(
48144
- "flex items-center gap-2 px-3 py-1.5 text-sm border rounded-lg transition-colors",
48906
+ "flex items-center gap-2 px-3 py-2 text-sm border rounded-lg transition-colors min-w-[200px]",
48145
48907
  currentLineIds.length === 0 ? "border-blue-300 bg-blue-50 hover:bg-blue-100" : "border-gray-300 bg-white hover:bg-gray-50"
48146
48908
  ),
48147
48909
  children: [
48148
48910
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-left", children: getDisplayText() }),
48149
48911
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn(
48150
- "w-4 h-4 text-gray-400 transition-transform",
48912
+ "w-4 h-4 text-gray-400 transition-transform flex-shrink-0",
48151
48913
  isOpen && "rotate-180"
48152
48914
  ) })
48153
48915
  ]
48154
48916
  }
48155
48917
  ),
48156
- isOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute z-[10000] mt-2 w-72 bg-white rounded-lg shadow-lg border border-gray-200 left-0", children: [
48157
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3 border-b border-gray-200", children: [
48158
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
48159
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Assign Lines" }),
48160
- /* @__PURE__ */ jsxRuntime.jsx(
48161
- "button",
48162
- {
48163
- onClick: handleCancel,
48164
- className: "text-gray-400 hover:text-gray-600",
48165
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4" })
48166
- }
48167
- )
48168
- ] }),
48169
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 mt-1", children: "Select one or more lines to assign" })
48170
- ] }),
48171
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-64 overflow-y-auto", children: availableLines.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-8 text-center", children: [
48172
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mb-2", children: "No lines available" }),
48173
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400", children: "Check console (F12) for filtering details" })
48174
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2", children: availableLines.map((line) => /* @__PURE__ */ jsxRuntime.jsxs(
48175
- "label",
48176
- {
48177
- className: "flex items-center gap-3 px-4 py-2.5 hover:bg-gray-50 cursor-pointer transition-colors",
48178
- children: [
48179
- /* @__PURE__ */ jsxRuntime.jsx(
48180
- "input",
48181
- {
48182
- type: "checkbox",
48183
- checked: selectedIds.includes(line.id),
48184
- onChange: () => handleToggleLine(line.id),
48185
- className: "h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
48186
- }
48187
- ),
48188
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-900", children: line.line_name }) }),
48189
- selectedIds.includes(line.id) && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-4 h-4 text-blue-600" })
48190
- ]
48191
- },
48192
- line.id
48193
- )) }) }),
48194
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3 border-t border-gray-200 bg-gray-50 flex items-center justify-between", children: [
48195
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-600", children: [
48196
- selectedIds.length,
48197
- " selected"
48198
- ] }),
48199
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
48200
- /* @__PURE__ */ jsxRuntime.jsx(
48201
- "button",
48202
- {
48203
- onClick: handleCancel,
48204
- 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",
48205
- children: "Cancel"
48206
- }
48207
- ),
48208
- /* @__PURE__ */ jsxRuntime.jsx(
48209
- "button",
48210
- {
48211
- onClick: handleSave,
48212
- disabled: !hasChanges || isSaving,
48213
- 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",
48214
- children: isSaving ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
48215
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "animate-spin h-3 w-3", viewBox: "0 0 24 24", children: [
48216
- /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", fill: "none" }),
48217
- /* @__PURE__ */ jsxRuntime.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" })
48918
+ isOpen && reactDom.createPortal(
48919
+ /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
48920
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-[9998]" }),
48921
+ /* @__PURE__ */ jsxRuntime.jsxs(
48922
+ "div",
48923
+ {
48924
+ ref: dropdownRef,
48925
+ className: "fixed z-[9999] bg-white rounded-lg shadow-2xl border border-gray-200",
48926
+ style: {
48927
+ top: `${position.top + 4}px`,
48928
+ left: `${position.left}px`,
48929
+ minWidth: `${Math.max(position.width, 300)}px`,
48930
+ maxWidth: "400px",
48931
+ maxHeight: "calc(100vh - 100px)"
48932
+ },
48933
+ children: [
48934
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-3 border-b border-gray-200 bg-gray-50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
48935
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
48936
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Assign Lines" }),
48937
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 mt-0.5", children: "Select one or more lines" })
48218
48938
  ] }),
48219
- "Saving..."
48220
- ] }) : "Save"
48221
- }
48222
- )
48223
- ] })
48224
- ] })
48225
- ] })
48939
+ /* @__PURE__ */ jsxRuntime.jsx(
48940
+ "button",
48941
+ {
48942
+ onClick: handleCancel,
48943
+ className: "text-gray-400 hover:text-gray-600 transition-colors",
48944
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4" })
48945
+ }
48946
+ )
48947
+ ] }) }),
48948
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-80 overflow-y-auto", children: availableLines.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-8 text-center", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "No lines available" }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-1", children: availableLines.map((line) => /* @__PURE__ */ jsxRuntime.jsxs(
48949
+ "label",
48950
+ {
48951
+ className: "flex items-center gap-3 px-4 py-2.5 hover:bg-gray-50 cursor-pointer transition-colors",
48952
+ children: [
48953
+ /* @__PURE__ */ jsxRuntime.jsx(
48954
+ "input",
48955
+ {
48956
+ type: "checkbox",
48957
+ checked: selectedIds.includes(line.id),
48958
+ onChange: () => handleToggleLine(line.id),
48959
+ className: "h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
48960
+ }
48961
+ ),
48962
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-900 truncate", children: line.line_name }) }),
48963
+ selectedIds.includes(line.id) && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-4 h-4 text-blue-600 flex-shrink-0" })
48964
+ ]
48965
+ },
48966
+ line.id
48967
+ )) }) }),
48968
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3 border-t border-gray-200 bg-gray-50 flex items-center justify-between", children: [
48969
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-600", children: [
48970
+ selectedIds.length,
48971
+ " selected"
48972
+ ] }),
48973
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
48974
+ /* @__PURE__ */ jsxRuntime.jsx(
48975
+ "button",
48976
+ {
48977
+ onClick: handleCancel,
48978
+ 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",
48979
+ children: "Cancel"
48980
+ }
48981
+ ),
48982
+ /* @__PURE__ */ jsxRuntime.jsx(
48983
+ "button",
48984
+ {
48985
+ onClick: handleSave,
48986
+ disabled: !hasChanges || isSaving,
48987
+ 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",
48988
+ children: isSaving ? "Saving..." : "Save"
48989
+ }
48990
+ )
48991
+ ] })
48992
+ ] })
48993
+ ]
48994
+ }
48995
+ )
48996
+ ] }),
48997
+ document.body
48998
+ )
48226
48999
  ] });
48227
49000
  };
48228
49001
  var FactoryAssignmentDropdown = ({
@@ -48235,13 +49008,36 @@ var FactoryAssignmentDropdown = ({
48235
49008
  const [isOpen, setIsOpen] = React23.useState(false);
48236
49009
  const [selectedIds, setSelectedIds] = React23.useState(currentFactoryIds);
48237
49010
  const [isSaving, setIsSaving] = React23.useState(false);
49011
+ const [position, setPosition] = React23.useState({ top: 0, left: 0, width: 0 });
49012
+ const buttonRef = React23.useRef(null);
48238
49013
  const dropdownRef = React23.useRef(null);
48239
49014
  React23.useEffect(() => {
48240
49015
  setSelectedIds(currentFactoryIds);
48241
49016
  }, [currentFactoryIds]);
49017
+ React23.useEffect(() => {
49018
+ const updatePosition = () => {
49019
+ if (isOpen && buttonRef.current) {
49020
+ const rect = buttonRef.current.getBoundingClientRect();
49021
+ setPosition({
49022
+ top: rect.bottom,
49023
+ left: rect.left,
49024
+ width: rect.width
49025
+ });
49026
+ }
49027
+ };
49028
+ if (isOpen) {
49029
+ updatePosition();
49030
+ window.addEventListener("scroll", updatePosition, true);
49031
+ window.addEventListener("resize", updatePosition);
49032
+ }
49033
+ return () => {
49034
+ window.removeEventListener("scroll", updatePosition, true);
49035
+ window.removeEventListener("resize", updatePosition);
49036
+ };
49037
+ }, [isOpen]);
48242
49038
  React23.useEffect(() => {
48243
49039
  const handleClickOutside = (event) => {
48244
- if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
49040
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target) && buttonRef.current && !buttonRef.current.contains(event.target)) {
48245
49041
  setIsOpen(false);
48246
49042
  setSelectedIds(currentFactoryIds);
48247
49043
  }
@@ -48307,91 +49103,106 @@ var FactoryAssignmentDropdown = ({
48307
49103
  if (!canEdit) {
48308
49104
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm", children: getDisplayText() });
48309
49105
  }
48310
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", ref: dropdownRef, children: [
49106
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
48311
49107
  /* @__PURE__ */ jsxRuntime.jsxs(
48312
49108
  "button",
48313
49109
  {
49110
+ ref: buttonRef,
48314
49111
  onClick: () => setIsOpen(!isOpen),
48315
49112
  className: cn(
48316
- "flex items-center gap-2 px-3 py-1.5 text-sm border rounded-lg transition-colors",
49113
+ "flex items-center gap-2 px-3 py-2 text-sm border rounded-lg transition-colors min-w-[200px]",
48317
49114
  currentFactoryIds.length === 0 ? "border-blue-300 bg-blue-50 hover:bg-blue-100" : "border-gray-300 bg-white hover:bg-gray-50"
48318
49115
  ),
48319
49116
  children: [
48320
49117
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-left", children: getDisplayText() }),
48321
49118
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn(
48322
- "w-4 h-4 text-gray-400 transition-transform",
49119
+ "w-4 h-4 text-gray-400 transition-transform flex-shrink-0",
48323
49120
  isOpen && "rotate-180"
48324
49121
  ) })
48325
49122
  ]
48326
49123
  }
48327
49124
  ),
48328
- isOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute z-[10000] mt-2 w-72 bg-white rounded-lg shadow-lg border border-gray-200 left-0", children: [
48329
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3 border-b border-gray-200", children: [
48330
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
48331
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Assign Factories" }),
48332
- /* @__PURE__ */ jsxRuntime.jsx(
48333
- "button",
48334
- {
48335
- onClick: handleCancel,
48336
- className: "text-gray-400 hover:text-gray-600",
48337
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4" })
48338
- }
48339
- )
48340
- ] }),
48341
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 mt-1", children: "Select one or more factories to assign" })
48342
- ] }),
48343
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-64 overflow-y-auto", children: availableFactories.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-8 text-center text-sm text-gray-500", children: "No factories available" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2", children: availableFactories.map((factory) => /* @__PURE__ */ jsxRuntime.jsxs(
48344
- "label",
48345
- {
48346
- className: "flex items-center gap-3 px-4 py-2.5 hover:bg-gray-50 cursor-pointer transition-colors",
48347
- children: [
48348
- /* @__PURE__ */ jsxRuntime.jsx(
48349
- "input",
48350
- {
48351
- type: "checkbox",
48352
- checked: selectedIds.includes(factory.id),
48353
- onChange: () => handleToggleFactory(factory.id),
48354
- className: "h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
48355
- }
48356
- ),
48357
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-900", children: factory.factory_name }) }),
48358
- selectedIds.includes(factory.id) && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-4 h-4 text-blue-600" })
48359
- ]
48360
- },
48361
- factory.id
48362
- )) }) }),
48363
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3 border-t border-gray-200 bg-gray-50 flex items-center justify-between", children: [
48364
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-600", children: [
48365
- selectedIds.length,
48366
- " selected"
48367
- ] }),
48368
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
48369
- /* @__PURE__ */ jsxRuntime.jsx(
48370
- "button",
48371
- {
48372
- onClick: handleCancel,
48373
- 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",
48374
- children: "Cancel"
48375
- }
48376
- ),
48377
- /* @__PURE__ */ jsxRuntime.jsx(
48378
- "button",
48379
- {
48380
- onClick: handleSave,
48381
- disabled: !hasChanges || isSaving,
48382
- 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",
48383
- children: isSaving ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
48384
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "animate-spin h-3 w-3", viewBox: "0 0 24 24", children: [
48385
- /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", fill: "none" }),
48386
- /* @__PURE__ */ jsxRuntime.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" })
49125
+ isOpen && reactDom.createPortal(
49126
+ /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
49127
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-[9998]" }),
49128
+ /* @__PURE__ */ jsxRuntime.jsxs(
49129
+ "div",
49130
+ {
49131
+ ref: dropdownRef,
49132
+ className: "fixed z-[9999] bg-white rounded-lg shadow-2xl border border-gray-200",
49133
+ style: {
49134
+ top: `${position.top + 4}px`,
49135
+ left: `${position.left}px`,
49136
+ minWidth: `${Math.max(position.width, 300)}px`,
49137
+ maxWidth: "400px",
49138
+ maxHeight: "calc(100vh - 100px)"
49139
+ },
49140
+ children: [
49141
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-3 border-b border-gray-200 bg-gray-50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
49142
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
49143
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold text-gray-900", children: "Assign Factories" }),
49144
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 mt-0.5", children: "Select one or more factories" })
48387
49145
  ] }),
48388
- "Saving..."
48389
- ] }) : "Save"
48390
- }
48391
- )
48392
- ] })
48393
- ] })
48394
- ] })
49146
+ /* @__PURE__ */ jsxRuntime.jsx(
49147
+ "button",
49148
+ {
49149
+ onClick: handleCancel,
49150
+ className: "text-gray-400 hover:text-gray-600 transition-colors",
49151
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4" })
49152
+ }
49153
+ )
49154
+ ] }) }),
49155
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-80 overflow-y-auto", children: availableFactories.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-8 text-center", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "No factories available" }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-1", children: availableFactories.map((factory) => /* @__PURE__ */ jsxRuntime.jsxs(
49156
+ "label",
49157
+ {
49158
+ className: "flex items-center gap-3 px-4 py-2.5 hover:bg-gray-50 cursor-pointer transition-colors",
49159
+ children: [
49160
+ /* @__PURE__ */ jsxRuntime.jsx(
49161
+ "input",
49162
+ {
49163
+ type: "checkbox",
49164
+ checked: selectedIds.includes(factory.id),
49165
+ onChange: () => handleToggleFactory(factory.id),
49166
+ className: "h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
49167
+ }
49168
+ ),
49169
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-900 truncate", children: factory.factory_name }) }),
49170
+ selectedIds.includes(factory.id) && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-4 h-4 text-blue-600 flex-shrink-0" })
49171
+ ]
49172
+ },
49173
+ factory.id
49174
+ )) }) }),
49175
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3 border-t border-gray-200 bg-gray-50 flex items-center justify-between", children: [
49176
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-600", children: [
49177
+ selectedIds.length,
49178
+ " selected"
49179
+ ] }),
49180
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
49181
+ /* @__PURE__ */ jsxRuntime.jsx(
49182
+ "button",
49183
+ {
49184
+ onClick: handleCancel,
49185
+ 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",
49186
+ children: "Cancel"
49187
+ }
49188
+ ),
49189
+ /* @__PURE__ */ jsxRuntime.jsx(
49190
+ "button",
49191
+ {
49192
+ onClick: handleSave,
49193
+ disabled: !hasChanges || isSaving,
49194
+ 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",
49195
+ children: isSaving ? "Saving..." : "Save"
49196
+ }
49197
+ )
49198
+ ] })
49199
+ ] })
49200
+ ]
49201
+ }
49202
+ )
49203
+ ] }),
49204
+ document.body
49205
+ )
48395
49206
  ] });
48396
49207
  };
48397
49208
  var UserManagementTable = ({
@@ -48543,7 +49354,7 @@ var UserManagementTable = ({
48543
49354
  }
48544
49355
  )
48545
49356
  ] }),
48546
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white rounded-lg border border-gray-200 overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-visible relative", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-gray-200", children: [
49357
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white rounded-lg border border-gray-200", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-gray-200", children: [
48547
49358
  /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-gray-50", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
48548
49359
  /* @__PURE__ */ jsxRuntime.jsx(
48549
49360
  "th",
@@ -48612,7 +49423,7 @@ var UserManagementTable = ({
48612
49423
  ] })
48613
49424
  ] }) }),
48614
49425
  /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx(RoleBadge, { role: user.role_level, size: "sm" }) }),
48615
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-4 relative overflow-visible z-10", children: user.role_level === "supervisor" ? /* @__PURE__ */ jsxRuntime.jsx(
49426
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-4", children: user.role_level === "supervisor" ? /* @__PURE__ */ jsxRuntime.jsx(
48616
49427
  LineAssignmentDropdown,
48617
49428
  {
48618
49429
  userId: user.user_id,
@@ -48654,7 +49465,7 @@ var UserManagementTable = ({
48654
49465
  }
48655
49466
  ) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-900", children: formatAssignments(user) }) }),
48656
49467
  /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: formatDate(user.created_at) }) }),
48657
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right relative overflow-visible", children: hasActions && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative overflow-visible", children: [
49468
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-4 whitespace-nowrap text-right", children: hasActions && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
48658
49469
  /* @__PURE__ */ jsxRuntime.jsx(
48659
49470
  "button",
48660
49471
  {
@@ -51036,6 +51847,7 @@ exports.AuthenticatedTargetsView = AuthenticatedTargetsView;
51036
51847
  exports.AuthenticatedTicketsView = AuthenticatedTicketsView;
51037
51848
  exports.AuthenticatedWorkspaceHealthView = AuthenticatedWorkspaceHealthView;
51038
51849
  exports.AxelNotificationPopup = AxelNotificationPopup;
51850
+ exports.AxelOrb = AxelOrb;
51039
51851
  exports.BackButton = BackButton;
51040
51852
  exports.BackButtonMinimal = BackButtonMinimal;
51041
51853
  exports.BarChart = BarChart;
@@ -51127,6 +51939,7 @@ exports.LoadingSkeleton = LoadingSkeleton;
51127
51939
  exports.LoadingState = LoadingState;
51128
51940
  exports.LoginPage = LoginPage;
51129
51941
  exports.LoginView = LoginView_default;
51942
+ exports.Logo = Logo;
51130
51943
  exports.MainLayout = MainLayout;
51131
51944
  exports.MapGridView = MapGridView;
51132
51945
  exports.MetricCard = MetricCard_default;
@@ -51140,6 +51953,7 @@ exports.OptifyeLogoLoader = OptifyeLogoLoader_default;
51140
51953
  exports.OutputProgressChart = OutputProgressChart;
51141
51954
  exports.PageHeader = PageHeader;
51142
51955
  exports.PieChart = PieChart4;
51956
+ exports.PlayPauseIndicator = PlayPauseIndicator;
51143
51957
  exports.PrefetchConfigurationError = PrefetchConfigurationError;
51144
51958
  exports.PrefetchError = PrefetchError;
51145
51959
  exports.PrefetchEvents = PrefetchEvents;
@@ -51166,6 +51980,7 @@ exports.ShiftDisplay = ShiftDisplay_default;
51166
51980
  exports.ShiftsView = ShiftsView_default;
51167
51981
  exports.SideNavBar = SideNavBar;
51168
51982
  exports.SignupWithInvitation = SignupWithInvitation;
51983
+ exports.SilentErrorBoundary = SilentErrorBoundary;
51169
51984
  exports.SimpleOnboardingPopup = SimpleOnboardingPopup;
51170
51985
  exports.SingleVideoStream = SingleVideoStream_default;
51171
51986
  exports.Skeleton = Skeleton;
@@ -51238,6 +52053,7 @@ exports.formatDateInZone = formatDateInZone;
51238
52053
  exports.formatDateTimeInZone = formatDateTimeInZone;
51239
52054
  exports.formatISTDate = formatISTDate;
51240
52055
  exports.formatIdleTime = formatIdleTime;
52056
+ exports.formatRelativeTime = formatRelativeTime;
51241
52057
  exports.formatTimeInZone = formatTimeInZone;
51242
52058
  exports.fromUrlFriendlyName = fromUrlFriendlyName;
51243
52059
  exports.getAllLineDisplayNames = getAllLineDisplayNames;
@@ -51262,6 +52078,7 @@ exports.getDefaultTabForWorkspace = getDefaultTabForWorkspace;
51262
52078
  exports.getLineDisplayName = getLineDisplayName;
51263
52079
  exports.getManufacturingInsights = getManufacturingInsights;
51264
52080
  exports.getMetricsTablePrefix = getMetricsTablePrefix;
52081
+ exports.getNextUpdateInterval = getNextUpdateInterval;
51265
52082
  exports.getOperationalDate = getOperationalDate;
51266
52083
  exports.getS3SignedUrl = getS3SignedUrl;
51267
52084
  exports.getS3VideoSrc = getS3VideoSrc;
@@ -51373,6 +52190,7 @@ exports.usePrefetchClipCounts = usePrefetchClipCounts;
51373
52190
  exports.useRealtimeLineMetrics = useRealtimeLineMetrics;
51374
52191
  exports.useRegistry = useRegistry;
51375
52192
  exports.useSKUs = useSKUs;
52193
+ exports.useSessionKeepAlive = useSessionKeepAlive;
51376
52194
  exports.useShiftConfig = useShiftConfig;
51377
52195
  exports.useShifts = useShifts;
51378
52196
  exports.useSubscriptionManager = useSubscriptionManager;
@@ -51394,6 +52212,7 @@ exports.useWorkspaceDisplayName = useWorkspaceDisplayName;
51394
52212
  exports.useWorkspaceDisplayNames = useWorkspaceDisplayNames;
51395
52213
  exports.useWorkspaceDisplayNamesMap = useWorkspaceDisplayNamesMap;
51396
52214
  exports.useWorkspaceHealthById = useWorkspaceHealthById;
52215
+ exports.useWorkspaceHealthStatus = useWorkspaceHealthStatus;
51397
52216
  exports.useWorkspaceMetrics = useWorkspaceMetrics;
51398
52217
  exports.useWorkspaceNavigation = useWorkspaceNavigation;
51399
52218
  exports.useWorkspaceOperators = useWorkspaceOperators;