@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.css +25 -27
- package/dist/index.d.mts +175 -12
- package/dist/index.d.ts +175 -12
- package/dist/index.js +1660 -841
- package/dist/index.mjs +1654 -843
- package/package.json +1 -1
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
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
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
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
"
|
|
2842
|
-
|
|
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
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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+CiAgPC9kYzp0aXRsZT4KIDwvcmRmOkRlc2NyaXB0aW9uPgoKIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PScnCiAgeG1sbnM6cGRmPSdodHRwOi8vbnMuYWRvYmUuY29tL3BkZi8xLjMvJz4KICA8cGRmOkF1dGhvcj5WaXZhYW48L3BkZjpBdXRob3I+CiA8L3JkZjpEZXNjcmlwdGlvbj4KCiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0nJwogIHhtbG5zOnhtcD0naHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyc+CiAgPHhtcDpDcmVhdG9yVG9vbD5DYW52YSAoUmVuZGVyZXIpIGRvYz1EQUdmbHdrMzVUbyB1c2VyPVVBR1RVS3lPaE9ZIGJyYW5kPUJBR1RVSVZ0eFV3IHRlbXBsYXRlPTwveG1wOkNyZWF0b3JUb29sPgogPC9yZGY6RGVzY3JpcHRpb24+CjwvcmRmOlJERj4KPC94OnhtcG1ldGE+Cjw/eHBhY2tldCBlbmQ9J3InPz6q+hm6AAB8a0lEQVR4nOzaMQEAIADDsOHfNE89wJEoqICeAQAAAAAAAACwbTuvAwAAAAAAAAAAfmGkAAAAAAAAAACIkQIAAAAAAAAAIEYKAAAAAAAAAIAYKQAAAAAAAAAAYqQAAAAAAAAAAIiRAgAAAAAAAAAgRgoAAAAAAAAAgBgpAAAAAAAAAABipAAAAAAAAAAAiJECAAAAAAAAACBGCgAAAAAAAACAGCkAAAAAAAAAAGKkAAAAAAAAAACIkQIAAAAAAAAAIEYKAAAAAAAAAIAYKQAAAAAAAAAAYqQAAAAAAAAAAIiRAgAAAAAAAAAgRgoAAAAAAAAAgBgpAAAAAAAAAABipAAAAAAAAAAAiJECAAAAAAAAACBGCgAAAAAAAACAGCkAAAAAAAAAAGKkAAAAAAAAAACIkQIAAAAAAAAAIEYKAAAAAAAAAIAYKQAAAAAAAAAAcgEAAP//7NqxAAAAAMAgf+s9wyiORAoAAAAAAAAAgIkUAAAAAAAAAAATKQAAAAAAAAAAJlIAAAAAAAAAAEykAAAAAAAAAACYSAEAAAAAAAAAMJECAAAAAAAAAGAiBQAAAAAAAADARAoAAAAAAAAAgIkUAAAAAAAAAAATKQAAAAAAAAAAJlIAAAAAAAAAAEykAAAAAAAAAACYSAEAAAAAAAAAMJECAAAAAAAAAGAiBQAAAAAAAADARAoAAAAAAAAAgIkUAAAAAAAAAAATKQAAAAAAAAAAJlIAAAAAAAAAAEykAAAAAAAAAACYSAEAAAAAAAAAMJECAAAAAAAAAGAiBQAAAAAAAADARAoAAAAAAAAAgIkUAAAAAAAAAAATKQAAAAAAAAAAJlIAAAAAAAAAAEykAAAAAAAAAACYSAEAAAAAAAAAMJECAAAAAAAAAGABAAD//+zasQAAAADAIH/rPcMojkQKAAAAAAAAAICJFAAAAAAAAAAAEykAAAAAAAAAACZSAAAAAAAAAABMpAAAAAAAAAAAmEgBAAAAAAAAADCRAgAAAAAAAABgIgUAAAAAAAAAwEQKAAAAAAAAAICJFAAAAAAAAAAAEykAAAAAAAAAACZSAAAAAAAAAABMpAAAAAAAAAAAmEgBAAAAAAAAADCRAgAAAAAAAABgIgUAAAAAAAAAwEQKAAAAAAAAAICJFAAAAAAAAAAAEykAAAAAAAAAACZSAAAAAAAAAABMpAAAAAAAAAAAmEgBAAAAAAAAADCRAgAAAAAAAABgIgUAAAAAAAAAwEQKAAAAAAAAAICJFAAAAAAAAAAAEykAAAAAAAAAACZSAAAAAAAAAABMpAAAAAAAAAAAmEgBAAAAAAAAADCRAgAAAAAAAABgAQAA///s2rEAAAAAwCB/6z3DKI5ECgAAAAAAAACAiRQAAAAAAAAAABMpAAAAAAAAAAAmUgAAAAAAAAAATKQAAAAAAAAAAJhIAQAAAAAAAAAwkQIAAAAAAAAAYCIFAAAAAAAAAMBECgAAAAAAAACAiRQAAAAAAAAAABMpAAAAAAAAAAAmUgAAAAAAAAAATKQAAAAAAAAAAJhIAQAAAAAAAAAwkQIAAAAAAAAAYCIFAAAAAAAAAMBECgAAAAAAAACAiRQAAAAAAAAAABMpAAAAAAAAAAAmUgAAAAAAAAAATKQAAAAAAAAAAJhIAQAAAAAAAAAwkQIAAAAAAAAAYCIFAAAAAAAAAMBECgAAAAAAAACAiRQAAAAAAAAAABMpAAAAAAAAAAAmUgAAAAAAAAAATKQAAAAAAAAAAJhIAQAAAAAAAAAwkQIAAAAAAAAAYAEAAP//7N1fqKT3Xcfx9+n+SYxNd7ppmhBjm2ojNJvSKBJbRaV/7GgtahSM0CBUxApj50qvejGOoBRBELFgkVwoilXQQEBhWttqvdLSWlL/rFgTkrRJW7LjtGxpTNYeL57J7iYkaXbd7HPO7usFX54f5zxn5sO5O8/5zO+nSAEAAAAAAAAAsKVIAQAAAAAAAACwpUgBAAAA7Avr2XyneknD84xvup68/zd/ucOHj1W1u/vUy5x5FrK7e3p94tTXX3bq0KEntjfs7uzsdHpdu8N6p52d0+vdj534r7t/8b6/Ol59Yzttr7tnrc/++qnqic108cQF+HUAAAAAL5KDYwcAAAAALh/r2fy66trqmupoNamObK/PN0fO9b1OPfhQh47d8oLufUVXnuvL9xePfvbOc/6harJa1lC2eKJ6vDpZfaU6UX2xeqR6uHqw+txmuvjM+bwPAAAAcH4UKQAAAIDzsp7NX1K9oqEY8crt9fnWRxt2i2DYGeOK7Rypvu25bjyrePFk9fXqa9WmoXjxperRhtLFA9XnquN2vQAAAIDzp0gBAAAAPKf1bH6wurG6aTuvOWt9U0MB4MAY2S4zO9Xh7Rypbniee3cnq+WTDTtd/Hf15erz1f3Vf1T3VZ9VtgAAAIBnp0gBAAAAl7H1bH6goQxxU89elrgxzw/2m6dKF0e3853PdtO2bLGpvtBQsPh09YnqnzbTxTcuTlQAAADYezwIAQAAgEvYejbfqa7r6QWJs6+vavinO5efQ505duW26s6nvjFZLR+v1tVD1b9Vn6z+bjNdHB8hJwAAAFxUihQAAABwiVjP5oerW6pbq2Pb663Vqxt2KYAX6sqG40NuqN5Y/ULVZLU81XBcyAPVZ6p/qP5mM12sR8oJAAAAF5wiBQAAAOwz2+M4bu7pZYlbq9fmb31eXAc7s4vF7dUv1eljQk5U9zccEfLx6sOb6eLkSDkBAADgvHm4AgAAAHvYejY/WL2u+p7qu7fX26qrx8wFz3Coun4731/9StVktTxZPVh9qvpIde9muvjqWCEBAADghVCkAAAAgD1iPZtfUb2hp5cmXl9dMWYu+H94acPOKceqn6+arJaPV5+v7qs+Wt2zmS4eHS0hAAAAPIMiBQAAAIxkPZvfXH1f9cbt9Q0Nn+yHS9mVDcfQvLb66eoDk9Xyf6qHqn+s7m0oV5waLyIAAACXM0UKAAAAuAjWs/mR6k2dKU7cXh0dNRTsHVdUN2/nrmp3slpuquPVx6o/2UwXx0fMBwAAwGVEkQIAAAAusPVsfqC6rafvNvFdo4aC/WWnenlD+ehN1fsmq+Wp6pHqn6u/rv58M118dbyIAAAAXKoUKQAAAOACWM/m11ZvPWteM24iuOQcrF61nZ+sPjhZLR+rPl3dU/2ZYgUAAAAXgiIFAAAAnIf1bH5V9ebOFCde3/ApeuDi2Kmurabb+YPJavmV6l8adqz4w8108diI+QAAANinFCkAAADgBVjP5ger2xtKE29rOLLj8KihgGc6Uv3Adn5rslp+rfr3alV9cDNdPDxmOAAAAPYHRQoAAAB4DuvZ/FhDaeJt1Q9XV4+bCDhH31p973beN1kt19Unqz9tOArk1JjhAAAA2JsUKQAAAGBrPZtfX729oTjx1uqGcRMBF9jRzhwF8keT1fIL1d9Xd2+mi4+PmgwAAIA9Q5ECAACAy9Z6Nj9S/VBndp24ZdxEwEW0U91Yvat612S1/N/q/urD1e9vpovjY4YDAABgPIoUAAAAXFbWs/mrq3dW76jeXH3LuImAPeJAdfN2ZpPV8kT1ieoDm+nio6MmAwAA4KJSpAAAAOCStp7ND1U/2FCceEf1unETAfvENdUd1R2T1fLJ6l+rDzUUK06OmgwAAIAXlSIFAAAAl5z1bH5d9eMNxYkfqV42biJgnztU3bad909Wyy9Wf1v97ma6+NSoyQAAALjgFCkAAAC4JKxn8yPVz1R3Vm/J37zAi+f66q7qru0RIPdWi8108fC4sQAAALgQPFQCAABg31rP5i9t2Hr/zoadJw6Pmwi4DF1Tvbt692S1/HJ1T0Op4kvjxgIAAOB8KVIAAACwr6xn86uqn6h+tvqx6spxEwGc9srqPdV7JqvlI9VfVr+xmS4eGzcWAAAA50KRAgAAgD1vW5740YadJ95ZXTVuIoBv6obqvdV7J6vlw9WHqt9WqgAAANj7FCkAAADYk9az+aHq7Q3liZ+qrh43EcB5+/bq16pfnayWD1R/XP3OZro4OW4sAAAAno0iBQAAAHvGejY/UL2l+rnqjurl4yYCuKB2qu+ofr1aTFbL/6zurn5vM108PmYwAAAAzvg/AAAA///s3c/rZXUdx/HnjM2QMuqlhiijaFESMhRkC5NqI3GlRQRapjVJ6qh17cboUAMK1ytCWCAEFojhokU/JGjT5oLSSo0oyigwFxoEgS4Ot4hoIdHiDplU1ujM93x/PB5/wXN14VxevD+GFAAAAIxqmM33Vx9uc3ni6urwuEUAW2JfdXF1X/XVyWr5dPVg9a31dPHiqGUAAAB7nCEFAAAAoxhm88vbXJ74RPXmkXMAxrS/uqT6RnX/ZLV8ojq+ni5+MW4WAADA3mRIAQAAwJYZZvODbS5P3NTmCgUAL3dO9aHq55PV8oXq4Wrp6Q8AAICtY0gBAADAWTfM5pdUx6qj1RtHzgHYKd5Unay+PFktf1bdtZ4uHhu5CQAAYNczpAAAAOCsGGbzQ710feKykXMAdrL9bX5HH52sln+qvlfduZ4uhnGzAAAAdidDCgAAAM6oYTa/rM144prq0Mg5ALvNhdWt1S2T1fK31b3r6eIHIzcBAADsKoYUAAAAvGanrk98urq5et/IOQB7wb7qSPX9yWr5UPVImysVz4+bBQAAsPMZUgAAAPCqDbP5+9uMJ67N9QmAsZxf3VjdMFktf1fd7UoFAADAq2dIAQAAwGkZZvMLq8+2GVAcGTkHgJfsq97d5krFw9WPqjtcqQAAADg9hhQAAAD8X4bZ/PI244lPVueOnAPAKzuvzZNL17lSAQAAcHoMKQAAAPivhtl8X3VVdXv1gZFzADh9/3ql4oHq6+vp4msjNwEAAGxrhhQAAAD8m2E2P6+6vjpevWvkHADOjMPVfZPVcll9t/rierr468hNAAAA244hBQAAAP80zOYXVbdVt1RvGDkHgLPj9dUN1fWT1XJV3baeLp4buQkAAGDbMKQAAACgYTa/pDpZfao6MHIOAFvjnOqj1bOT1fLX1efX08UTIzcBAACMzpACAABgDxtm849Ud1TTsVsAGNV7qscnq+UfqnvW08W3xw4CAAAYiyEFAADAHjPM5geqq6oT1aUj5wCwvbytemiyWt5ffbO6cz1d/H3kJgAAgC1lSAEAALBHDLP5BdWt1bx668g5AGxv57d58un2yWr5SDVbTxd/HrkJAABgSxhSAAAA7HLDbH5Rdby6ubpg5BwAdpaD1Weq6yar5U+qY+vp4rmRmwAAAM4qQwoAAIBdapjNL6m+Ul1bHRg5B4CdbX91RfXsZLV8qrpjPV08NnITAADAWWFIAQAAsMsMs/kV1YnqyrFbANiV3ls9Olktf1/dZFABAADsNoYUAAAAu8SpCxT3Vh+v9o2cA8Du9442g4pnquvX08VPR+4BAAA4IwwpAAAAdrhTA4q7qmvanF4HgK10cfXkZLX8TXXMoAIAANjpDCkAAAB2qGE2f2d1TwYUAGwPR3ppUHF0PV38auwgAACAV8OQAgAAYIcZZvO3V3dXR/NdB8D2c6T65WS1/EV13Xq6eGbsIAAAgNPhDzcAAIAd4tSA4mR1Y3Vw5BwA+F8urZ6erJZPVp8zqAAAAHYKQwoAAIBtbpjND7cZUHyhOnfkHAA4Hfuqy9sMKh6vrl5PF8+P3AQAAPCKDCkAAAC2qWE2n1Qnqi9Vh0bOAYDXYl/1weqPk9Xyx20uVAwjNwEAAPxHhhQAAADbzDCbH2oznjhRTUbOAYAzaX/1seqFyWr5w+qm9XTxl5GbAAAAXsaQAgAAYJsYZvNz2zzfcbI6PHIOAJxN51TXVFdNVsvvVLP1dPG3kZsAAAAqQwoAAIDRDbP5wepYdWf1lpFzAGArva66oTo6WS0frI6vp4sXR24CAAD2uP1jBwAAAOxlw2x+ZfVU9UBGFADsXQeq26r1ZLW8dewYAABgb/sHAAAA///s3c+r5XUdx/HXHbU7jBhfhiBdhNAgGBK2aeVimAnnFEnMJrxpJJYk04c+hONCoTh927iomAijsI0uTBCiln036sZFEGM/SRkiiqQS+fDVZbhwMUIUJdPt3Pncc87j8Rc8t+fL67w/LlIAAAB00Eq9NcmFJB/v3QIAh8j1Sb4/TOMyybl5sfxp7yAAAGD7GFIAAABcRa3U40m+nuRc/CYDgP/mxiQ/GabxUpK758Xypd5BAADA9vDRDgAA4CpopR5JUnJ5RHG8bw0ArI1bklwcpvHFJJ+eF8u/9g4CAAA235HeAQAAAJuulXoyycUk340RBQDsxx1J/jJM4zPDNB7tHQMAAGw2QwoAAIAD0kr9YCv1x0leSHJ75xwAWHdHkuwlmYdpfLB3DAAAsLk87QEAALBirdRjSb6a5KEku51zAGDT7Cb5wTCN55N8cl4sL/UOAgAANouLFAAAACvUSt1L8nKSR2NEAQAH6ZYkrwzT+OQwjf4wBgAArIwhBQAAwAq0Um9vpb6Q5JkkH+icAwDbYifJfUneGKbxnt4xAADAZrDUBgAA+D+0Uo8neSzJAzFWB4BejiV5epjGR5J8Yl4sX+0dBAAArC8f+QAAAPahlXptK7UkuZTki/H7CgAOgw8n+fMwjY/3DgEAANaXD30AAAD/o1bqySS/SfJ4kuOdcwCAf3UkSRmm8c1hGk/1jgEAANaPpz0AAACuUCv1vUkuJLk/l99kBwAOrxuSPDdM4/NJzs6L5Zu9gwAAgPXgIgUAAMAVaKXuJXklyedjRAEA6+RUkteHaTzfOwQAAFgPLlIAAAC8i1bqiSRPJDnduwUA2LfrknxrmMYvJ/nUvFj+uncQAABweBlSAAAA/Aet1N0kjyZ5JMlu5xwAYDVuTvLLYRqfTfLZebF8q3cQAABw+HjaAwAA4N+0Uk8n+V2SZYwoAGDT7CS5O8kbwzTe0zsGAAA4fFykAAAAeEcr9cYkF5Ls9W4BAA7csSRPD9P4lSRn5sVy7h0EAAAcDi5SAAAAJGmlnk1yMUYUALBtPprk7+8MKgAAAFykAAAAtlsr9X1JfpjkbO8WAKCb9yS5MEzjA0lOz4vla72DAACAflykAAAAtlYrdS/J72NEAQBcdluSV4dp/FrvEAAAoB8XKQAAgK3TSr0pyZNJznROAQAOn2uTfGOYxvuSfGxeLP/UOwgAALi6XKQAAAC2Siv1C7l8hcKIAgB4NyeS/MF1CgAA2D4uUgAAAFuhlXpzkidiQAEAXLlr8s/rFHfNi+XLvYMAAICD5yIFAACw8VqpZ5O8FCMKAGB/TiT57TCND/cOAQAADp6LFAAAwMZqpR5N8p0kD/ZuAQDW3jVJvjlM471JTs2L5dw7CAAAOBguUgAAABuplXpbkl/EiAIAWK2PJPnbMI2f6R0CAAAcDBcpAACAjdJK3UlyLsm3kxztnAMAbKbdJD8apvH+JHfNi+U/egcBAACr4yIFAACwMVqp70/ysyTfixEFAHDw7kzy+jCNJ3uHAAAAq2NIAQAAbIRW6pkkv0pypncLALBVbkjy/DCNT/UOAQAAVsPTHgAAwFprpV6X5LEkDyXZ6ZwDAGynnSSfG6bxziR3zIvlH3sHAQAA++ciBQAAsLZaqR9K8vMk52NEAQD0d1OSS8M0fql3CAAAsH9vAwAA///s3c+L71Udx/HXOFPp5TZ8dOHiUi0ScVPghLgIyW5iU5DooriLCEyoRSdOGzchOhwJiRYRgUFBLlpJEFLR4hTWQoNSLCSIoDYRUhEcZhEt7iJaXKhEvMzI3Hu+Px6Pv+D5B7x4v12kAAAA1s4odSfJF5N8LcmNk3MAAP7fbpKnl94+meRjx4dHl2cHAQAAp+MiBQAAsFZGqbcm+VmSb8aIAgBYXReT/GPp7X2zQwAAgNMxpAAAANbGKPWBJL9Lct/sFgCAE9hP8urS25dnhwAAACfntQcAALDyRqnnk3w9yedmtwAAnNINSZ5aensoycXjw6N/zQ4CAACuzkUKAABgpY1SD5K8GiMKAGC93Z0rrz4uzg4BAACuzpACAABYWaPUh5P8Ksl7J6cAAJyFc0meX3p7fHYIAADw5rz2AAAAVs4o9aYk30ry8OQUAICztpPkyaW3jya57/jw6PLsIAAA4PVcpAAAAFbKKPX2JL+OEQUAsNnuSfL3pbfbZocAAACvZ0gBAACsjFHqx5O8kuT9s1sAAK6DJckflt4+OzsEAAD4H0MKAABgulHq7ij1K0l+kuSds3sAAK6jvSTPLL09OzsEAAC4wpACAACYapR6S5LnkzyWKz/DAQC20aWlt78svd0yOwQAALadIQUAADDNKPXuJL9Ncu/sFgCAFfCuJK8tvd0/OwQAALaZIQUAADDFKPVSkheSvGd2CwDACrkxSV96a7NDAABgW+3NDgAAALbLKHU3yVeTPDq7BQBgRe0keWLp7cNJ7j8+PLo8uQcAALaKixQAAMB1M0rdT/LTGFEAAJzEh5L8bent9tkhAACwTQwpAACA62KUekeSl5J8ZHYLAMAauTnJ75fePjU7BAAAtoUhBQAAcM2NUj+RKyOKO2a3AACsob0k3196+8bsEAAA2AaGFAAAwDU1Sn0iyY+S7M9uAQBYc19aentl6e387BAAANhkhhQAAMA1MUq9aZT6bJKWZGd2DwDAhvhAkr8uvd05OwQAADaVIQUAAHDmRqkXkvwyyaXZLQAAG+h8kpeW3h6YHQIAAJvIkAIAADhTo9SDJC8nOZjdAgCwwd6W5IdLb1+YHQIAAJvGkAIAADgzo9QHk7yY5MLsFgCALbCT5Omlt2/PDgEAgE1iSAEAAJyJUepjSZ5Lcm52CwDAlvn80tsLsyMAAGBT7M0OAAAA1tso9e1Jnkny6dktAABb7J6ltz8lufP48Oifs2MAAGCduUgBAAC8ZaPUC0l+ESMKAIBVcFuS15be3j07BAAA1pkhBQAA8JaMUg+SvJzkg7NbAAD4r/0kf1x6u3d2CAAArCtDCgAA4NRGqQ8meTHJhdktAAC8wTuS/Hzp7TOzQwAAYB0ZUgAAAKcySn0kyQ+SnJvdAgDAm7ohyfeW3h6fHQIAAOvGkAIAADixUWpL8t0ku7NbAAA4kSeX3p6bHQEAAOtkb3YAAACw+kapu0m+k+SR2S0AAJzaQ0tvv0ly1/Hh0b9nxwAAwKpzkQIAALiqUeq5JD+OEQUAwDo7SPLnpbf92SEAALDq/gMAAP//7N2/ih0FGMbhV11IwKgjIQghBkshjaCBYGGwkKAELI29Ww1MFVDLaVTY0ibEVmIlWwUzCKKFLNjGRoNewlyDxdmV+CeQzZ7db87M81zBWw7D75sRUgAAAI80tt2FJD8lebd6CwAAR3Yhq5ji5eohAAAwZUIKAADgf41tdynJXpI3qrcAALA2TZIHzdBfrh4CAABTJaQAAAD+Y2y7q0l+zupqEQCAeTmVZK8Z+verhwAAwBQJKQAAgH8Y2+56kiHJC9VbAAA4Ns8k2W2G/qPqIQAAMDVCCgAA4G9j291IspvVlSIAAPP2VJKvmqG/WT0EAACmREgBAAAkSca2205yJ8lW9RYAAE7UTjP0n1WPAACAqRBSAAAAGdvuZpLbWV0lAgCwPJ82Q/9N9QgAAJgCIQUAACzc2HY7SXaqdwAAUO5GM/T3qkcAAEA1IQUAACzU2HZbY9vdTuKf2AAAHLjWDP1e9QgAAKgkpAAAgAUa2+5Ukt0k29VbAACYnCvN0P/aDL33xwAALJIHYQAAWJix7Z5N8l2S69VbAACYrEtJ/miG/nT1EAAAOGlCCgAAWJCx7c5k9SWKt6u3AAAwea9ETAEAwAIJKQAAYCH2I4ohyTvVWwAA2BjnI6YAAGBhhBQAALAAD0UUb1ZvAQBg4xzEFM9XDwEAgJMgpAAAgJkTUQAAsAbnk/wppgAAYAmEFAAAMGNj270YEQUAAOtxNmIKAAAWQEgBAAAztR9R/BARBQAA6yOmAABg9oQUAAAwQw9FFK9VbwEAYHYOYoqXqocAAMBxEFIAAMDMiCgAADgBZ5M8EFMAADBHQgoAAJiRse3OJPk+IgoAAI7fc0nuN0PfVA8BAIB1ElIAAMBM7EcUd5O8Xr0FAIDFOJfk92boT1cPAQCAdRFSAADADIxtdzqriOKt6i0AACzOuSS/iSkAAJgLIQUAAGy4/Yji24goAACoczGrmGKreggAAByVkAIAADbY2HZbWUUU71VvAQBg8S4muV89AgAAjkpIAQAAG2psu6eTfB0RBQAA0/FqM/S/VI8AAICjEFIAAMAG2o8obiX5oHoLAAD8y+Vm6PeqRwAAwJMSUgAAwGa6lWS7egQAADzClWbof6weAQAAT0JIAQAAG2Zsuy8iogAAYPquNkN/r3oEAAAclpACAAA2yNh2nyT5uHoHAAA8pmvN0N+pHgEAAIchpAAAgA0xtt12ks+rdwAAwCF92Az9l9UjAADgcf0FAAD//+zcTctVZRiG4ctXDd9QWcg70miWUEgFDcpJgkFGA4MkokkRNIhWrByVk4JnoDTJSQRFgxAjUDBEEVoVFDSsSOh/rN/QIISIvsi9970/juMXnMOHm4vHkAIAAFbA1A8vJvm4ugMAAP6nN7uxteoIAAD4LwwpAABgyU398GySz+P9DgDAanuvG9vZ6ggAAPg3DrEAALDEpn54Msm1JHuqWwAAYAYudmN7pToCAAD+iSEFAAAsqakfHktyK8m+6hYAAJiRXUk+68b2XHUIAAD8HUMKAABYQlM/PJjk6yT7q1sAAGDGdiW51o3tRHUIAAD8FUMKAABYMlM/HE7ybZJD1S0AADAnu5N8043taHUIAAD8mSEFAAAskakfDiQZkxyubgEAgDnbm+TnbmwGxAAALBVDCgAAWBJTP+xLcj3JseoWAABYkP1Jfu3Gtqc6BAAA7jCkAACAJTD1w1aSK0lOVrcAAMCCHU7yU3UEAADcYUgBAADL4WKS09URAABQ5JFubN9XRwAAQGJIAQAA5aZ+OJvkreoOAAAodqIb26fVEQAAYEgBAACFpn44neSD6g4AAFgSr3Vje7s6AgCAzWZIAQAARaZ+OJnkSrzLAQDgj97vxvZ8dQQAAJvLwRYAAApM/XAsyfUk+6pbAABgyexKcrUb21PVIQAAbCZDCgAAWLCpH3aSfJnkQHULAAAsqd1JbnZjO1IdAgDA5jGkAACABZr6YW+SG0keqG4BAIAlt53kdje2PdUhAABsFkMKAABYrE+SHK+OAACAFbGT5IfqCAAANoshBQAALMjUD+eSvFrdAQAAK+aJbmyXqiMAANgchhQAALAAUz+cSXK+ugMAAFbUy93YXq+OAABgMxhSAADAnE398HCSy/H+BgCAu/FRN7anqyMAAFh/DrkAADBHUz/sJLmVZLu6BQAAVtxWkpvd2I5UhwAAsN4MKQAAYE6mfthOciPJfdUtAACwJu5Jcrsb273VIQAArC9DCgAAmJ/LSY5XRwAAwJrZSfJjdQQAAOvLkAIAAOZg6odzSc5UdwAAwJp6qBvbF9URAACsJ0MKAACYsakfTiU5X90BAABr7qVubG9URwAAsH4MKQAAYIamfjia5Gq8tQEAYBE+7Mb2eHUEAADrxXEXAABmZOqHg0luJjlY3QIAABtiK8l33dgOVYcAALA+DCkAAGAGpn7Yyu8/URytbgEAgA2zneSX6ggAANaHIQUAAMzGhSSnqiMAAGBD3d+N7avqCAAA1oMhBQAA3KWpH15I8k51BwAAbLhT3djerY4AAGD1GVIAAMBdmPrh0SSXqjsAAIAkSevG9kx1BAAAq+03AAAA///s3T2LHmUYhuFrw278CvIIKorNhnRBEiwWJI1YpdztRBC0FEaGbUyh1WghLGJhYburgkIsEkSEQbuAhT9mfoOFAT9Ysx9u3nte5jh+wVk+PFxwG1IAAMA5TV3fktzLnzeZAQCAehtJ7rdxeL46BACA9WVIAQAA53eUZLu4AQAA+KcnkvxeHQEAwPoypAAAgHOYun4/yW51BwAAcKyrbRzuVUcAALCeDCkAAOCMpq7fSXJQ3QEAADzSXhuHd6ojAABYP4YUAABwBlPXtyR3k2xVtwAAACc6bOPwanUEAADrxZACAADO5ijJdnEDAABwOptJHrRx2KwOAQBgfRhSAADAKU1dv59kt7oDAAA4k5bk1+oIAADWhyEFAACcwtT1O0kOqjsAAIBzeaONw6fVEQAArAdDCgAAOMHU9S3J3SRb1S0AAMC5fdzG4VZ1BAAA82dIAQAAJztKsl3cAAAA/D8bScY2DleqQwAAmDdDCgAAeISp6/eT7FZ3AAAAF+JKkl+qIwAAmDdDCgAA+A9T1+8kOajuAAAALtTrbRzuVEcAADBfhhQAAHCMqetbkrtJtqpbAACAC/dZG4er1REAAMyTIQUAABzvKMl2cQMAAPB4XEryoDoCAIB5MqQAAIB/mbp+P8ludQcAAPBYvdLG4V51BAAA82NIAQAAfzN1/fUkB9UdAADASuy1cdirjgAAYF4MKQAA4KGp659O8kOSreoWAABgZb5v4/BidQQAAPNhSAEAAH/5Ksn16ggAAGClnkzyW3UEAADzYUgBAABJpq5/L8m71R0AAECJa20cvqyOAABgHgwpAABYvKnrX07yRXUHAABQ6oM2Dq9VRwAAUM+QAgAAksMkz1VHAAAApTaS/FwdAQBAPUMKAAAWber695Pcru4AAABm4SUnPgAAMKQAAGCxpq6/luTz6g4AAGBWnPgAAFg4QwoAABZp6vpLSb5J8kx1CwAAMCsbScbqCAAA6hhSAACwVHeS3KqOAAAAZumFNg7fVUcAAFDDkAIAgMWZuv5GkqG6AwAAmLW32zi8WR0BAMDqGVIAALAoU9dfTvJtksvVLQAAwOzdb+OwWR0BAMBqGVIAALA0nyS5UR0BAACshWeT/FQdAQDAahlSAACwGFPX30zyYXUHAACwVm63cXirOgIAgNUxpAAAYBEenvT4Ot7AAADA2R22cXAeEABgIXwiAwCwFB8luVkdAQAArKWnkvxYHQEAwGr8AQAA///s3b+KFWccx+HvibJbRGXKBPxTCLEVLNYyEEjsTmuTOoQxA4IJajckkoBFJAZCIBeQtQiphLmpuYYUWqTQ9eyeOfx25jzPFXwu4Pu+P0MKAAAW7+1JjyfVHQAAwKx91Qz9F9URAADsniEFAACLNrbdR3lz0sM3vAAAwLb+ceIDAGD5DCkAAFi6H+KkBwAAMI0rSY6rIwAA2C1DCgAAFuvtSY++ugMAAFiUtRMfAADLZkgBAMAiOekBAADsyCpOfAAALJohBQAAS+WkBwAAsCtOfAAALJghBQAAizO23c046QEAAOzWuhn6o+oIAACmZ0gBAMAS/RUnPQAAgN1aJfm3OgIAgOkZUgAAsChj291P8nl1BwAAsBc+aYb+5+oIAACmZUgBAMBijG13Kcnz6g4AAGCvfN8M/afVEQAATMeQAgCAJfkpydXqCAAAYK9cSPK6OgIAgOkYUgAAsAhj291J8qC6AwAA2Eu3m6H/ujoCAIBpGFIAADB7Y9tdSPJn3rwEAwAAqPBHM/QH1REAAGzPkAIAgCX4Lsmd6ggAAGCvfZzkuDoCAIDtGVIAADBrY9tdTfJjdQcAAECSdTP0R9URAABsx5ACAIC5+z3JpeoIAACAJKskr6ojAADYjiEFAACzNbbdvSTr6g4AAID/ud4M/aPqCAAAzs6QAgCAWRrb7jDJi+oOAACAd3jWDP2V6ggAAM7GkAIAgLl6kuRWdQQAAMA7HMSJDwCA2TKkAABgdsa2u5bkcXUHAADACb5shv6oOgIAgNMzpAAAYI5eJjmsjgAAADjBKn6lAACYJUMKAABmZWy7e0nW1R0AAAAbuN4M/aPqCAAATseQAgCA2Rjb7jDJi+oOAACAU3jWDP1BdQQAAJszpAAAYE4eJrlVHQEAAHAKB0mOqyMAANicIQUAALMwtt21JE+rOwAAAM5g3Qz9Z9URAABsxpACAIC5eJnkcnUEAADAGaySvK6OAABgM4YUAACce2Pb3U2yru4AAADYws1m6L+pjgAA4MMMKQAAmINfqwMAAAAm8Lw6AACADzOkAADgXBvb7n6Su9UdAAAAE7jcDP1v1REAAJzMkAIAgHNrbLvDJL9UdwAAAEzo22bom+oIAADez5ACAIDz7GGSG9URAAAAE7qY5O/qCAAA3u8/AAAA///s3UGLF3Ucx/HPuiW7BDYEIV0ULx0EwUPH6FZ2SQUDvZQQgQsDo+LFLIJRKOngSYIOYh56EPOk5jF48LAsLuYuzHxn//N6PYL3cfjx4TuGFAAALNLYdp8m+aW6AwAAYALfNEN/sToCAIDDGVIAALBUT5KcqY4AAACYwFaS/6ojAAA4nCEFAACLM7bdxSQ/V3cAAABM6HIz9F9WRwAA8DZDCgAAluhZku3qCAAAgIm5SgEAsECGFAAALMrYdt8muVLdAQAAMINzzdDfqY4AAOAgQwoAAJbm1+oAAACAGT2tDgAA4CBDCgAAFmNsu+tJ/CMYAABYk6YZ+t+qIwAA2GdIAQDAkjyuDgAAACjwqDoAAIB9hhQAACzC2Ha3klyq7gAAACiw2wz9n9URAAC8YUgBAEC5se22k/xR3QEAAFDobjP0p6sjAAAwpAAAYBl+SHKhOgIAAKDQbpK/qyMAADCkAACg2Nh2O0l+r+4AAABYgB9dpQAAqGdIAQBAtb24RgEAAJAkHyb5tzoCAGDtDCkAACgztt3HSR5WdwAAACzIzWbom+oIAIA1M6QAAKDS/SRnqyMAAAAW5FSSl9URAABrZkgBAECJse2aJHerOwAAABboWjP056sjAADWypACAIAq95I4VwsAAPC2rSSvqiMAANbKkAIAgNm5RgEAAPC/vnKVAgCghiEFAAAVXKMAAAB4t60k/1RHAACskSEFAACzco0CAADgvX3dDP0n1REAAGtjSAEAwNxcowAAAHg/p5K8qI4AAFgbQwoAAGbjGgUAAMCRXXWVAgBgXoYUAADMyTUKAACAo3GVAgBgZoYUAADMwjUKAACAY3OVAgBgRoYUAADMZS+uUQAAAByHqxQAADMypAAAYHJj2+0m6ao7AAAATrDvXKUAAJiHIQUAAHO4neSz6ggAAIATbDvJ8+oIAIA1MKQAAGBSY9t9kOR+dQcAAMAGuNEM/U51BADApjOkAABgat8n+bw6AgAAYAOcTvJXdQQAwKYzpAAAYDJj220leVDdAQAAsEF+aobe2z4AwIR8bAEAMKUrSb6ojgAAANggHyV5VB0BALDJXgMAAP//7Ny/jhZlGMbhe+NXsGoxGGJDXItNtqCxMmy3hRaUJostYEAlGRzRisZi7DSxIfFg5qTmGOxokPD9mc3DvN91HcGvfJP3zmNIAQDATXpVHQAAANCgX6sDAABaZkgBAMCNmPvhMslVdQcAAECD7nTT+Lg6AgCgVYYUAADclJfVAQAAAA37szoAAKBVhhQAACxu7oeLJNfVHQAAAA0766bxQXUEAECLDCkAALgJvyfZVEcAAAA07p/qAACAFhlSAACwqLkfbid5VN0BAABwBO5103heHQEA0BpDCgAAlvZzktPqCAAAgCPxb3UAAEBrDCkAAFjM3A+bJC+qOwAAAI7It9003qqOAABoiSEFAABLepjkbnUEAADAEfkoyd/VEQAALTGkAABgSS+rAwAAAI7QD9UBAAAtMaQAAGARcz9cJrlf3QEAAHCEPu2m8Vl1BABAKwwpAABYimsUAAAAdf6oDgAAaIUhBQAAB5v74W6S6+oOAACAI3bWTePX1REAAC0wpAAAYAm/JNlURwAAABy519UBAAAtMKQAAOAgcz+cJvmpugMAAIDc76bxTnUEAMDaGVIAAHCox0luV0cAAACQk7hKAQBwMEMKAAAO9bw6AAAAgDe+qw4AAFg7QwoAAPY298Nlkq+qOwAAAHjjtJvGZ9URAABrZkgBAMAhXKMAAAD48LyqDgAAWDNDCgAA9jL3w2dJvq/uAAAA4C3n3TReVEcAAKyVIQUAAPt6lOTj6ggAAAD+11/VAQAAa2VIAQDAzuZ+OEnyY3UHAAAA7/Sgm0Z/AAAAe/CIAgBgH1dJ7lVHAAAA8E63kgzVEQAAa2RIAQDAPp5XBwAAAPBev1UHAACskSEFAAA7mfvhiyTX1R0AAAC811k3jRfVEQAAa2NIAQDArp4m2VRHAAAAsJXX1QEAAGtjSAEAwNbmfjhJ8qS6AwAAgK19002jvwAAgB14PAEAsIurJF9WRwAAALC1TZKhOgIAYE0MKQAA2MWT6gAAAAB29qI6AABgTQwpAADYytwPnyR5WN0BAADAzs67afy8OgIAYC3+AwAA///s3c1KVWEYhuFHwcBysAYRjpvkIEyaCAVNIjCbSBBKEUhNgg2bJkkEDdYZdDrrpPYxNNFQ8w/d2/eTfV1HcA8/WA/rNaQAAOCqPiR5UB0BAADAtfypDgAAuCsMKQAAuKpv1QEAAABc2051AADAXWFIAQDApSaj8UaSzeoOAAAArm25G/rd6ggAgLvAkAIAgKvYrw4AAADgxn5WBwAA3AWGFAAAXGgyGi8l+VTdAQAAwI2td0N/vzoCAKB1hhQAAFzmXZKH1REAAADc2GKS39URAACtM6QAAOAy+9UBAAAATM1+dQAAQOsMKQAAONdkNH6UZLu6AwAAgKlZ7Yb+aXUEAEDLDCkAALjI+yRL1REAAABM1a/qAACAlhlSAABwkb3qAAAAAKbubXUAAEDLDCkAADjT4VmPV9UdAAAATF3XDf3r6ggAgFYZUgAAcJ6PSRaqIwAAAJiJH9UBAACtMqQAAOA8+9UBAAAAzIw/EAIAnMOQAgCA/0xG47Ukz6o7AAAAmJnlbui3qyMAAFpkSAEAwFn2qgMAAACYuYPqAACAFhlSAABwwmQ0XkjyuboDAACAmXvRDb3vBAAAp3ggAQBw2maSx9URAAAAzNxSki/VEQAArTGkAADgNGc9AAAA5seoOgAAoDWGFAAA/HN41mO3ugMAAIBbs+68BwDASR5HAAAct5lktToCAACAW7MY5z0AAE4wpAAA4Lid6gAAAABu3dfqAACAlhhSAABwnCEFAADA/HleHQAA0BJDCgAAkiST0XgjyZPqDgAAAG7dvW7ot6sjAABaYUgBAMCRveoAAAAAyoyrAwAAWmFIAQDAEWc9AAAA5tfL6gAAgFYYUgAAkMlovBZnPQAAAObZSjf0W9URAAAtMKQAACBx1gMAAIDke3UAAEALDCkAAEgMKQAAAHDeAwAgiSEFAMDcc9YDAACAQyvd0G9URwAAVDOkAABgpzoAAACAZhxUBwAAVDOkAABgqzoAAACAZrypDgAAqPYXAAD//+zdsWrVABTH4VMsFUFoEKHQxUKRbgoO2sId0q06SFe3ok4Goq+Qx8pL5Rkc3HTQVm5OkvN9T/Abc5M/9xhSAAAUNnX9cURcZXcAAACwGM+bcXiaHQEAkMmQAgCgtvcRcZQdAQAAwKL8yA4AAMhkSAEAUJuzHgAAAPzuU3YAAEAmQwoAgKKmrj8It28BAAD400UzDr4fAABleRACAKjrXUScZkcAAACwOI8i4nN2BABAFkMKAIC6brMDAAAAWKwv2QEAAFkMKQAA6rrJDgAAAGCx3mQHAABkMaQAACho6vrTiHiV3QEAAMBiHTXjsMuOAADIYEgBAFDTx4g4yI4AAABg0b5lBwAAZDCkAACoyVkPAAAA/uY6OwAAIIMhBQBAMVPXP46INrsDAACAxTtpxqHJjgAAmJshBQBAPVcRcZwdAQAAwOIdRMRddgQAwNwMKQAA6mmzAwAAAFiN2+wAAIC5GVIAANRzkx0AAADAarzODgAAmJshBQBAIVPXH0fE2+wOAAAAVqNpxuE8OwIAYE6GFAAAtVzHrxu3AAAA8K++ZgcAAMzJkAIAoBZnPQAAALgvvyUBgFIMKQAAavHyCwAAgPu6yA4AAJiTIQUAQBFT159FxIvsDgAAAFbnSTMO59kRAABzMaQAAKjDv1EAAADwUN+zAwAA5mJIAQBQhyEFAAAAD/UhOwAAYC6GFAAAdVxmBwAAALBaTkUCAGUYUgAAFDB1/VlEnGR3AAAAsFqHzTjssiMAAOZgSAEAUEObHQAAAMDq3WUHAADMwZACAKCGNjsAAACA1WuzAwAA5mBIAQBQQ5sdAAAAwOq9yA4AAJiDIQUAwMZNXX8WXnYBAADw/w6bcdhlRwAA7JshBQDA9rXZAQAAAGzGXXYAAMC+GVIAAGxfmx0AAADAZrTZAQAA+2ZIAQCwfZfZAQAAAGyG05EAwOYZUgAAbNjU9c8i4mV2BwAAAJtx2IzDLjsCAGCffgIAAP//7N1BatVgFIbhQymFCw5CEe9FEB0UsQq3HZUOriLOLdJBNxHIHrKsbCprcBP/nwMnz7OCd5iEjxxDCgCA2n6FZz4AAADaessOAADoyUd1AIDafmcHAAAAUM7P7AAAgJ4MKQAAanvODgAAAKCcu+wAAICeDCkAAIpax+kQEefsDgAAAMp5NyzzbXYEAEAvhhQAAHU9RMQhOwIAAICSXrMDAAB6MaQAAKjLWQ8AAAB6+ZMdAADQiyEFAEBdhhQAAAD08pQdAADQiyEFAEBdhhQAAAD08ik7AACgF0MKAICC1nE6RcTn7A4AAADKuhmW+Xt2BABAD4YUAAA1+RsFAAAAvb1mBwAA9GBIAQBQkyEFAAAAvV2yAwAAejCkAACoyZACAACA3h6yAwAAejCkAAAoZh2nq4h4yu4AAACgvA/ZAQAAPRhSAADU8zUiDtkRAAAAlHc1LPM5OwIAoDVDCgCAeh6zAwAAANiNl+wAAIDWDCkAAOoxpAAAAGArl+wAAIDWDCkAAOoxpAAAAGAr99kBAACtGVIAANRjSAEAAMBWPmYHAAC0ZkgBAFDIOk6niDhmdwAAALAb18Myn7MjAABaMqQAAKjF3ygAAADY2kt2AABAS4YUAAC1GFIAAACwtUt2AABAS4YUAAC1PGcHAAAAsDv32QEAAC0ZUgAA1GJIAQAAwNZO2QEAAC0ZUgAAFLGO0ykijtkdAAAA7M7NsMzvsyMAAFoxpAAAqONLdgAAAAC79S87AACgFUMKAIA6HrMDAAAA2C2nJgGAMgwpAADq+JYdAAAAwG79yA4AAGjFkAIAoA5DCgAAALLcZQcAALRiSAEAUIfTHgAAAGQZsgMAAFoxpAAAKGAdpyEijtkdAAAA7Nb1sMzeSwGAEgwpAABqcNYDAACAbH+zAwAAWvgPAAD//+zdS2obQRiF0TLOw4RAmmQQEwyuQRwM3oAngZDtCLQHLUub0ho86UFo6Em14OpXzlnBN63mdpUhBQDAdfCsBwAAAGmv6QAAgHMwpAAAuA5upAAAACDtJR0AAHAOhhQAANfBkAIAAIC0ng4AADgHQwoAgOvgaQ8AAADSvqYDAADOwZACAKC4024/tda+pzsAAAD4732YjgfnUwCgPEMKAID6ejoAAAAAZn/SAQAAWxlSAADU19MBAAAAMPP0JABQniEFAEB9z+kAAAAAmDmjAgDlGVIAANTnIxUAAACX4lc6AABgK0MKAID6ejoAAAAAZj/SAQAAWxlSAADU19MBAAAAMPucDgAA2MqQAgCgsNNuf9tae0h3AAAAwOzddDzcpSMAALYwpAAAqO2ptXabjgAAAIB//E0HAABsYUgBAFDbczoAAAAAFn6nAwAAtjCkAACoracDAAAAYMHoHwAozZACAKC2ng4AAACAhZ4OAADYwpACAKC2ng4AAACAhft0AADAFoYUAAC19XQAAAAALHxJBwAAbGFIAQBQW08HAAAAwMJdOgAAYAtDCgCAok67/dT85QMAAMDluZmOh8d0BADAKEMKAIC6ejoAAAAAVrymAwAARhlSAADUdZ8OAAAAgBVP6QAAgFGGFAAAdRlSAAAAcKl6OgAAYJQhBQBAXT0dAAAAACt+pgMAAEYZUgAA1NXTAQAAALDiIR0AADDKkAIAoK6eDgAAAIAV39IBAACjDCkAAOrq6QAAAABY8SkdAAAwypACAKCu+3QAAAAArHifDgAAGGVIAQBQ0Gm3n1prH9MdAAAAsOJmOh4e0xEAACMMKQAAanIbBQAAAJfuJR0AADDiDQAA///s3U1OAkEUhVGMRvxBbIlx5sSBceDOSNgDy2JTrMElwKvJq2vOWcEdNvRX1UIKAIBMQgoAAABm9909AABghJACACCTkAIAAIDZfXUPAAAYIaQAAMgkpAAAAGB2n90DAABGCCkAADIJKQAAAJid364AQCQhBQBAJn9GAQAAMLtt9wAAgBFCCgCATEIKAAAAZrfrHgAAMEJIAQCQSUgBAADA7DbdAwAARggpAAAyCSkAAACY3UP3AACAEUIKAIBMS/cAAAAAuOCuewAAwAghBQBAmPP+sKxWq3X3DgAAALhkOR0dBAAA4ggpAADy+KwHAAAAKX67BwAAVAkpAADyOM0DAABAip/uAQAAVUIKAIA8QgoAAABSuFURAIgjpAAAyCOkAAAAIMVH9wAAgCohBQBAHiEFAAAAKd67BwAAVAkpAADyCCkAAABIseseAABQJaQAAMgjpAAAACDFa/cAAIAqIQUAQB4hBQAAACm23QMAAKqEFAAAeYQUAAAApNh0DwAAqBJSAADkEVIAAACQ4ql7AABAlZACACCPkAIAAIAUD90DAACqhBQAAHmEFAAAAKS47x4AAFAlpAAAyPPSPQAAAACudNs9AACgSkgBAJDnuXsAAAAAXMl7CAAgjgcYAIA8vi8LAABAipvuAQAAVUIKAIA86+4BAAAAAADwXwkpAACCnPcHJ3kAAACIspyOblYEAKIIKQAAsggpAAAASPPWPQAAoEJIAQCQRUgBAABAGjdSAABRhBQAAFmEFAAAAKR57B4AAFAhpAAAyCKkAAAAIM26ewAAQMUfAAAA///s3bFpAwAMRUHcOGX2HzOl3diNFlARxIO7Cf4AD0lIAQDQIqQAAACgRkgBAKQIKQAAWoQUAAAA1HjtAQCkCCkAAFqEFAAAANS4SAEApAgpAABahBQAAADU/F4PAADYEFIAAAAAAAD/6Xk9AABgQ0gBAAAAAAAAADCEFAAAAAAAAAAAQ0gBAAAAAAAAADCEFAAALY/rAQAAALD0cz0AAGBDSAEA0CKkAAAAoEZIAQCkCCkAAAAAAAAAAIaQAgAAAAAAAABgCCkAAAAAAAAAAIaQAgCg5XE9AAAAAJae1wMAADaEFAAALUIKAAAAaoQUAECKkAIAAAAAAAAAYAgpAAAAAAAAAACGkAIAAAAAAAAAYAgpAABaPtcDAAAAYOl9PQAAYENIAQDQIqQAAACgRkgBAKQIKQAAAAAAAAAAhpACAAAAAAAAAGAIKQAAAAAAAAAAhpACAKDlcz0AAAAAll7XAwAANoQUAAAtQgoAAABqhBQAQIqQAgAAAAAAAABgCCkAAAAAAAAAAIaQAgAAAAAAAABgCCkAAFo+1wMAAABg6X09AABgQ0gBANAipAAAAKDm73oAAMCGkAIAoEVIAQAAQM3regAAwMYXAAD//+zd0UkkURRF0YrBpAzLHASTmy8/ZHAGx+4W6ZFGxBC6boGcOrBWBCeA/e4TUgAAdBFSAAAA0OZ/egAAwISQAgAAAAAA+EkuUgAAVYQUAABdXKQAAACgjZACAKgipAAA6PKVHgAAAABDh/QAAIAJIQUAAAAAAPCTXKQAAKoIKQAAuvjaAwAAgDbn9AAAgAkhBQBAkZuHeyEFAAAAVY63dx/pDQAAE0IKAIA+TqICAADQwoMAAKCOkAIAoM8xPQAAAABWElIAAHWEFAAAfU7pAQAAALDSZ3oAAMCUkAIAoM8hPQAAAABWuqQHAABMCSkAAPr42gMAAIAWH+kBAABTQgoAgD5CCgAAAFqc0wMAAKaEFAAAfYQUAAAAtHhPDwAAmBJSAAD0EVIAAADQ4i09AABgSkgBANBHSAEAAECLU3oAAMCUkAIAoI+QAgAAgBav6QEAAFNCCgCAPkIKAAAAWrykBwAATAkpAAD6CCkAAABo8Tc9AABgSkgBANBHSAEAAECL5/QAAIApIQUAQB8hBQAAAC1+pwcAAEwJKQAA+pzSAwAAAGAlIQUAUEdIAQDQ59+yLJf0CAAAAFjhV3oAAMCUkAIAoMzNw/1lWZZDegcAAABc8XW8vTunRwAATAkpAAA6HdMDAAAA4IrP9AAAgC2EFAAAnZ7TAwAAAOAK1ygAgEpCCgCATkIKAAAA9u4tPQAAYAshBQBAJyEFAAAAe/eaHgAAsIWQAgCgk5ACAACAvfuTHgAAsIWQAgCgk5ACAACAvXtKDwAA2EJIAQDQSUgBAADA3j2mBwAAbPENAAD//+zdQYpTQRSF4VpDNpVlZQ+BbMexgx5JiwFbKFod9MjXkEGE2DrJ6GEQXjWcd9vvW8G/gFO3DCkAAGqa0gEAAADwD5/TAQAASxhSAADU5CIFAAAAa/cpHQAAsIQhBQBATYYUAAAArN1jOgAAYAlDCgCAgjaH/bm19pTuAAAAgBtepu3Ot5QAQEmGFAAAdblKAQAAwFr9TAcAACxlSAEAUFdPBwAAAMANz+kAAIClDCkAAOrq6QAAAAC4wRVFAKAsQwoAgLp6OgAAAABu6OkAAIClDCkAAOryugcAAIC1OqYDAACWMqQAAKjLkAIAAIC1+pIOAABYypACAKCung4AAACAG1ykAADKMqQAAKjrW2vtko4AAACAv7hLBwAALGVIAQBQ1Oawv7TWvqc7AAAAYOYybXfndAQAwFKGFAAAtfV0AAAAAMyc0gEAACMMKQAAauvpAAAAAJj5kQ4AABhhSAEAUFtPBwAAAMDMYzoAAGCEIQUAQG09HQAAAAAzD+kAAIARhhQAALUd0wEAAAAwc58OAAAYYUgBAFCbIQUAAABr8y4dAAAwwpACAKCwzWE/tdae0x0AAABw9Xva7j6kIwAARhhSAADU19MBAAAAcHVOBwAAjDKkAACor6cDAAAA4MrVRACgPEMKAID6jukAAAAAuOrpAACAUYYUAAD1GVIAAACwFh/TAQAAowwpAADq6+kAAAAAuLpPBwAAjDKkAACor6cDAAAA4OouHQAAMMqQAgCgvq+ttVM6AgAAAFpr79MBAACjDCkAAIrbHPa/mj9oAQAAyDtN290lHQEAMMqQAgDgbTimAwAAAPjvPaUDAABegyEFAMDbYEgBAABA2kM6AADgNfwBAAD//+zdTWqTYRSG4bOGbCrLyh4C2YSDzhwJRbBgUZSknVisAzvxZ1AyCHVgDW7iffvA+a5rBfcCHs4xpAAA6MGQAgAAgLSrdAAAwAiGFAAAPRhSAAAAkPY2HQAAMIIhBQBAD1+r6pSOAAAAYNGu0wEAACMYUgAANLDabf9V1bd0BwAAAIt1Oq43z+kIAIARDCkAAPrw3gMAAICUX+kAAIBRDCkAAPrYpwMAAABYrPt0AADAKIYUAAB9uEgBAABAylU6AABgFEMKAIA+7tIBAAAALNabdAAAwCiGFAAAfdxV1VM6AgAAgEX6lA4AABjFkAIAoInVbnuuqtt0BwAAAItzOq43z+kIAIBRDCkAAHrZpwMAAABYnId0AADASIYUAAC9GFIAAADw0g7pAACAkQwpAAB6uU4HAAAAsDiX6QAAgJEMKQAAermpqqd0BAAAAItykQ4AABjJkAIAoJHVbnuuqtt0BwAAAItxOq43j+kIAICRDCkAAPrZpwMAAABYjId0AADAaIYUAAD9GFIAAADwUg7pAACA0QwpAAD6MaQAAADgpVymAwAARjOkAADo56aqzukIAAAAFuEiHQAAMJohBQBAM6vd9qmqvqQ7AAAAaO/vcb15TEcAAIxmSAEA0NPHdAAAAADt/UgHAADMYEgBANDTdToAAACA9j6nAwAAZjCkAADoyZACAACA2V6nAwAAZjCkAADo6aaq/qQjAAAAaO0iHQAAMIMhBQBAQ6vd9lxVH9IdAAAAtHU6rjeP6QgAgBkMKQAA+vLeAwAAgFnu0wEAALMYUgAA9GVIAQAAwCzv0gEAALMYUgAA9GVIAQAAwCyv0gEAALMYUgAANLXabX9W1fd0BwAAAO2cj+vNVToCAGAWQwoAgN5cpQAAAGC03+kAAICZDCkAAHp7nw4AAACgnUM6AABgpv8AAAD//+zcsWoUYRiF4e8a5qb2sra2k4FtZUtBkAQEVwi6gpJVLEzEXqIWFsIoKRLBrIWdYLlzduZ/nit4L+BwDCkAAObtZToAAACA2dmkAwAADsmQAgBg3i6r6ns6AgAAgFlZpwMAAA7JkAIAYMa6VX9XVe/SHQAAAMzGMCyWQzoCAOCQDCkAAOZvlw4AAABgNi7SAQAAh2ZIAQAwf9t0AAAAALNxkg4AADg0QwoAgPnbVdVNOgIAAIBZWKcDAAAOzZACAGDmulV/U1Vv0h0AAABM3jAslkM6AgDg0AwpAADasE0HAAAAMHkX6QAAgDEYUgAAtGGbDgAAAGDyTtIBAABjMKQAAGjDrqru0hEAAABM2jodAAAwBkMKAIAGdKv+pqo+pDsAAACYrGFYLId0BADAGAwpAADa8SwdAAAAwGS9TwcAAIzFkAIAoB1P0wEAAABM1mk6AABgLIYUAADtOK+q23QEAAAAk7OvqgfpCACAsRhSAAA0olv1t1W1TXcAAAAwOd+GxfJnOgIAYCyGFAAAbdmkAwAAAJicXToAAGBMhhQAAG3ZpgMAAACYnIfpAACAMRlSAAC05aKqrtIRAAAATMbvqnqUjgAAGJMhBQBAQ7pVv6+qF+kOAAAAJuPTsFjepSMAAMZkSAEA0J5tOgAAAIDJ2KYDAADGZkgBANCe51W1T0cAAAAwCet0AADA2AwpAAAa0636q6q6THcAAABw9H4Ni+WrdAQAwNgMKQAA2nSWDgAAAODofUwHAAAkGFIAALTpSToAAACAo/c4HQAAkGBIAQDQpvOq+pGOAAAA4Gjtq+p+OgIAIMGQAgCgQd2qv62qTboDAACAo/V5WCyv0xEAAAmGFAAA7TKkAAAA4H9O0wEAACmGFAAA7Tqrv1etAAAA8K976QAAgBRDCgCARnWr/ktVvU13AAAAcHSuh8XyazoCACDFkAIAoG0n6QAAAACOzut0AABAkiEFAEDbNukAAAAAjk6fDgAASPoDAAD//+zdz0pVURjG4fcazk3te2qyJ0WziA1nFIhBUBBFDTSiImgQjYIm0aQaFPSHBhvNBgraoBQtTUmP39LzPFfwu4B3rc+QAgBgvr1K8rE6AgAAgGasj12/XB0BAFDJkAIAYI5NpsNWkqXqDgAAAJrxsjoAAKCaIQUAAIYUAAAAbLtZHQAAUM2QAgCAh0lWqiMAAAAot5lkoToCAKCaIQUAwJybTIf1JA+qOwAAACj3Zuz679URAADVDCkAAEiSe9UBAAAAlHPWAwAghhQAAPyyHOc9AAAA5tlWkqvVEQAALTCkAAAgk+mwEuc9AAAA5tkHZz0AAH4xpAAAYJvzHgAAAPPrfnUAAEArDCkAANi2nGS9OgIAAIASl6sDAABaYUgBAECSnfMeT6s7AAAAOHWfx67/VB0BANAKQwoAAHa7VR0AAADAqbtdHQAA0BJDCgAAdrsb5z0AAADmjbMeAAC7GFIAALDj93mPx9UdAAAAnJpvznoAAOxlSAEAwJ986QoAADA/HlUHAAC0xpACAIA/3UmyUR0BAADAqbhYHQAA0BpDCgAA9phMh9Uky9UdAAAAzNznsetfV0cAALTGkAIAgP0sVgcAAAAwc047AgDsw5ACAID9LCVZrY4AAABgZraSXKqOAABokSEFAAB/mUyHjSR3qzsAAACYmXdj13+pjgAAaJEhBQAAB7lVHQAAAMDMLFYHAAC0ypACAICDPEnidRIAAMD5s5nkSnUEAECrDCkAANjX7/MefqUAAAA4f96MXf+jOgIAoFWGFAAA/IshBQAAwPlzrToAAKBlhhQAABxoMh1eJPlQ3QEAAMCJ2UgyVEcAALTMkAIAgMMsVAcAAABwYp6PXb9ZHQEA0DJDCgAADnM9yVZ1BAAAACfiQnUAAEDrDCkAAPinyXR4n+RZdQcAAADHNo5d/7w6AgCgdYYUAAAcxWJ1AAAAAMd2pzoAAOAsMKQAAOAobidZq44AAADgWJz1AAA4AkMKAAAONZkOa0luVHcAAADw396OXf+1OgIA4Cz4CQAA///s3bGKHgUUhuHvGuam5kKsRDtFK5nOSk0cHI0SVDAWgSWNoKuk0U60UAQFYRFFJWBIpoi6Idldu4AE9Z9/ZznOzPNcwXsBH+cYUgAAsKsr1QEAAADs7bXqAACApTCkAABgJ83Qf5Xk6+oOAAAAJjtO0ldHAAAshSEFAABTvFsdAAAAwGSHY9udVkcAACyFIQUAAFO8n+RBdQQAAACTPF8dAACwJIYUAADsrBn635J8WN0BAADAzn4d2+776ggAgCUxpAAAYKor1QEAAADs7I3qAACApTGkAABgqo+T/FgdAQAAwH86SfJidQQAwNIYUgAAMEkz9GdxlQIAAGAJbo5td1odAQCwNIYUAADs42qSB9URAAAA/KunqgMAAJbIkAIAgMmaob+d5EZ1BwAAAP/op7HtjqojAACWyJACAIB9ee8BAADw/3WpOgAAYKkMKQAA2NenSb6pjgAAAOAx95P01REAAEtlSAEAwF6aoT9L8nZ1BwAAAI/5aGy70+oIAIClMqQAAOA8riX5vToCAACAv3m2OgAAYMkMKQAA2Fsz9LeTHFR3AAAA8MjR2HZH1REAAEtmSAEAwHkN1QEAAAA88kp1AADA0hlSAABwLs3Qf5Hk8+oOAAAAcm9su9erIwAAls6QAgCAOVyuDgAAACDvVAcAAKyBIQUAAHM4SPJzdQQAAMCGnSR5rjoCAGANDCkAADi3ZugfJhmqOwAAADbs5th2x9URAABrYEgBAMBc3kryR3UEAADARj1ZHQAAsBaGFAAAzKIZ+jtJ3qvuAAAA2KBvx7b7oToCAGAtDCkAAJjTq0nOqiMAAAA25pnqAACANTGkAABgNs3Qf5fkk+oOAACADbk1tt1hdQQAwJoYUgAAMLfL1QEAAAAb8kJ1AADA2hhSAAAwq2boD5N8Wd0BAACwAffGtrtaHQEAsDaGFAAAXISXqwMAAAA24Hp1AADAGhlSAABwEQ6S/FIdAQAAsGInSZ6ujgAAWCNDCgAAZtcM/cMkL1V3AAAArNgHY9sdV0cAAKyRIQUAABflzSR3qyMAAABW6CzJE9URAABrZUgBAMCFaIb+zyR9dQcAAMAKfTa23Z3qCACAtfoLAAD//+zdv4oWBxTG4fca5qbmEiyCoLapUqRSnI1aCEHUgRH802mTQmFbK902EAyInQkIC4uFjjYmoq6FARERjfDNmW/mea7gdwEv5xhSAACwSZeTvKqOAAAAWJjj1QEAAEtmSAEAwMY0Q/88ybXqDgAAgAV5NLbd39URAABLZkgBAMCm/ZrkTXUEAADAQvxUHQAAsHSGFAAAbFQz9PtJbld3AAAALMCTse3uVkcAACydIQUAAFO4kOSwOgIAAGDLnaoOAABYA0MKAAA2rhn635PsVncAAABssWdj292sjgAAWANDCgAApnI2rlIAAAB8r7PVAQAAa2FIAQDAJJqh/yOJX74AAAD/3zi23aXqCACAtTCkAABgSuerAwAAALbQL9UBAABrYkgBAMBkmqG/l+R+dQcAAMAWcY0CAGBihhQAAExtpzoAAABgi7hGAQAwMUMKAAAm5SoFAADAN3ONAgCggCEFAAAVdqoDAAAAtoBrFAAABQwpAACYnKsUAAAAX+UaBQBAEUMKAACq7FQHAAAAzJhrFAAARQwpAAAo4SoFAADAF7lGAQBQyJACAIBKp6sDAAAAZuhkdQAAwJoZUgAAUKYZ+r0ku9UdAAAAM3Iwtt2V6ggAgDUzpAAAoFqX5G11BAAAwEz8WB0AALB2hhQAAJRqhv7PJLeqOwAAAGbg8dh2d6ojAADWzpACAIA5OBNXKQAAAE5UBwAAYEgBAMAMNEP/V5Ib1R0AAACFHo1tt1cdAQCAIQUAAPOxk+Sf6ggAAIAiR6oDAAD4wJACAIBZaIb+IMnV6g4AAIACD8a2e1gdAQDAB4YUAADMyfkkL6ojAAAAJnSY5Gh1BAAAHxlSAAAwG/9dpbhY3QEAADChPdcoAADmxZACAIC5uZjkaXUEAADABN4l+aE6AgCATxlSAAAwK83Qv0zSVXcAAABM4Lex7farIwAA+JQhBQAAc3Q9idO2AADAkv2b5Fh1BAAAnzOkAABgdpqhf5vk5+oOAACADTo3tt3r6ggAAD73HgAA///s3b2KHQUcxuH3GuamBlOIKAqmU7YRPxCM2GimEROwiYODTTApLRWbjSBBsEuzhUiCWgkGZEOGTWNCNrFNkd2cPTvL/8yc57mC3wW88BpSAACwkZqh301yo7oDAADgDOyPbfd5dQQAAM9nSAEAwCa7kOSwOgIAAGBib1cHAABwNEMKAAA2VjP0vyW5Wt0BAAAwod/HtvuxOgIAgKMZUgAAsOkuJvmvOgIAAGACT5O8Vh0BAMDxDCkAANhozdD/m+Sr6g4AAIAJ/DS23e3qCAAAjmdIAQDAHHyR5J/qCAAAgFN4nOSN6ggAAF7MkAIAgI3XDP1Bko+qOwAAAE7hm7HtDqojAAB4MUMKAABmoRn675L8XN0BAACwhvtj231QHQEAwGoMKQAAmJP3khxWRwAAAJzQ+eoAAABWZ0gBAMBsNEN/O8nX1R0AAAAnsDe23W51BAAAqzOkAABgbj5Lsl8dAQAAsIInSc5VRwAAcDKGFAAAzEoz9A+SfFzdAQAAsIJrY9vdrY4AAOBkDCkAAJidZuivJ7lV3QEAAHCM+2Pb7VRHAABwcoYUAADM1btJDqsjAAAAjnC+OgAAgPUYUgAAMEvN0N9KcrW6AwAA4Dn2xrbbrY4AAGA9hhQAAMzZp0nuVUcAAAA840mSc9URAACsz5ACAIDZaoZ+P8mF6g4AAIBnXBvb7m51BAAA6zOkAABg1pqhv57kZnUHAABAknFsu53qCAAATseQAgCAJXgnycPqCAAAYOu9WR0AAMDpGVIAADB7zdDfSXK5ugMAANhqv4xtt1sdAQDA6RlSAACwFJeS3KmOAAAAttKjJC9XRwAAMA1DCgAAFqEZ+odJPqzuAAAAttInY9sdVEcAADANQwoAABajGfrdJD9UdwAAAFvlr7HtrlRHAAAwHUMKAACW5v0kD6ojAACArfA0yUvVEQAATMuQAgCARWmG/u8kF6s7AACArfDt2HZ/VEcAADAtQwoAABanGforSX6t7gAAABZtHNtupzoCAIDpGVIAALBUbyV5VB0BAAAs1qvVAQAAnA1DCgAAFqkZ+j+TdNUdAADAIn0/tt3N6ggAAM6GIQUAAEv2ZZK96ggAAGBRDpK8Xh0BAMDZMaQAAGCxmqE/jIsPAABgWq+Mbfe4OgIAgLNjSAEAwKI1Q7+X5FJ1BwAAsAg3XHoAACzf/wAAAP//7N2/ih51HMXhcw1zLQr2ImMhiDZLFIVEm4ikjJ0jCVioTYb8SsFOA8JiIywINhYxlchiIYhBiwQJ7KAm4hbvWphC4ibuZv9853We5wo+F3DgGFIAALAE78bFBwAAcDS/JnmuOgIAgJNnSAEAwP9e18bduPgAAACOxqUHAMBCGFIAALAILj4AAIAjcOkBALAghhQAACxG18Z3kmxXdwAAAGvlj7j0AABYFEMKAACW5uW4+AAAAA7uVZceAADLYkgBAMCidG38NslQ3QEAAKyFrakfPq2OAADgdBlSAACwRO8l2aqOAAAAZu23uPQAAFgkQwoAABana+MqydkkO9UtAADAbD3v0gMAYJkMKQAAWKSujbeSvFHdAQAAzNLHUz98WR0BAEANQwoAABara+MnSa5VdwAAALNyZ+qHl6ojAACoY0gBAMDSnU9yqzoCAACYhb0kz1RHAABQy5ACAIBF69q4k+RsklV1CwAAUO7q1A/fVEcAAFDLkAIAgMXr2riV5P3qDgAAoNRPUz9cqI4AAKCeIQUAAPzt7STb1REAAECJVVx6AABwnyEFAAAk6dq4m+RMkrvVLQAAwKl7a+qH76sjAACYB0MKAAC4r2vjdpI3qzsAAIBTdX3qhw+qIwAAmA9DCgAA+IeujR8luVbdAQAAnIq7cekBAMADDCkAAODfzif5sToCAAA4UXtJnp364ffqEAAA5sWQAgAAHtC1cSfJmSSr6hYAAODEXJ364avqCAAA5seQAgAA9tG18eskl6s7AACAE/HD1A8XqiMAAJgnQwoAAHi4S0m+qI4AAACO1Z9JnqqOAABgvgwpAADgIbo2rpK8kmSnugUAADg2G1M/3KmOAABgvgwpAADgEbo23k7yWnUHAABwLDanfvisOgIAgHkzpAAAgP/QtXEzyZXqDgAA4Eh+mfrhxeoIAADmz5ACAAAO5mKSG9URAADAY9lN8kR1BAAA68GQAgAADqBr426SjSRTdQsAAHBoL0z98HN1BAAA68GQAgAADqhr480k56o7AACAQ/lw6ofPqyMAAFgfhhQAAHAIXRs3k1yp7gAAAA7ku6kfXq+OAABgvRhSAADA4V1McqM6AgAAeKR7SZ6sjgAAYP0YUgAAwCF1bdxNspFkqm4BAAD2tZfk6akf7lWHAACwfgwpAADgMXRtvJnkXHUHAACwr0tTP1yvjgAAYD39BQAA///s3TuLXXUUxuH3M+xPoRZeULG1CRsLE6JEtBEkpIhlJIUX2FaioGA2bEghSCoRBFMIogRMQCuLiIEgWkkYECLydyQanMmMRRBUjIVzzlnn8jyf4Feu4oVlSAEAAP9TN40fJjlT3QEAAPzNxdYPr1ZHAACwugwpAADgYE4n+bw6AgAASJL8mORQdQQAAKvNkAIAAA6gm8adJE8kuVbdAgAAG+73JPe3ftitDgEAYLUZUgAAwAF103g9yZEkP1e3AADAhtpP8njrh63qEAAAVp8hBQAAzEA3jZeTPJNkr7oFAAA20CutHz6tjgAAYD0YUgAAwIx00/hxkperOwAAYMOcb/3wWnUEAADrw5ACAABmqJvG15O8X90BAAAb4mrrh6PVEQAArBdDCgAAmL3nklyujgAAgDW3neTh6ggAANaPIQUAAMxYN42/JTmS5Hp1CwAArKlbSR5p/fBrdQgAAOvHkAIAAOagm8ZrSY5VdwAAwJo63vrhm+oIAADWkyEFAADMSTeNl5KcrO4AAIA182brh3PVEQAArC9DCgAAmKNuGs8mOVPdAQAAa+JS64fT1REAAKw3QwoAAJi/U0k+qY4AAIAVt9X64dHqCAAA1p8hBQAAzFk3jXtJnkryVXULAACsqF+S3FsdAQDAZjCkAACABeimcTvJ4STXq1sAAGDF3EryUOuHn6pDAADYDIYUAACwIN00XktyNMlOdQsAAKyI/SRPt374tjoEAIDNYUgBAAAL1E3jF0mer+4AAIAV8WLrhw+qIwAA2CyGFAAAsGDdNL6T5I3qDgAAWHLnWz+4mwEAWDhDCgAAqPFSknPVEQAAsKS+bv1wtDoCAIDNZEgBAAAFumncS3IiyYXqFgAAWDI/JHmwOgIAgM1lSAEAAEW6adxJ8mSSK9UtAACwJG4kubv1w251CAAAm8uQAgAACnXTuJ3ksSRb1S0AAFBsJ8kDrR9adQgAAJvNkAIAAIp107iV22OK7eoWAAAosp+kb/3wXXUIAAAYUgAAwBLopvFKbr/52KluAQCABdtPcrz1w2fVIQAAkBhSAADA0uim8UKSE0n2qlsAAGCBTrd+eLc6AgAA/mRIAQAAS6SbxnNJXqjuAACABTnb+uGt6ggAAPgrQwoAAFgy3TS+neRMdQcAAMzZhdYPJ6sjAADgnwwpAABgOZ1K8l51BAAAzMnV1g+HqiMAAODfGFIAAMAS6qZxL8mzST6qbgEAgBn7Psl91REAAHAnhhQAALCkumncTXIsycXiFAAAmJWW5K7WD7vVIQAAcCeGFAAAsMS6abyZ5HCSL6tbAADggG4kuaf1w83qEAAA+C9/AAAA///s3L2KHnUYxuG78AjmCNTKUmuVBUkcRbCJjWCjomivkCYMgk3ANAP/wg8US0EEm3QpTKWFTSAqLARMEWVBHdRAIFnXYlcR/Npd8u7zvjPXdQT3Afy4hRQAALDmujb+kuTJJFertwAAwDHdTvLQ1A/fVQ8BAID/I6QAAIAN0LXxhySPJ7lWvQUAAI5oN8npqR+2q4cAAMBhCCkAAGBDdG28keR0khvVWwAA4JD2kpyZ+uGz6iEAAHBYQgoAANggXRuvZf+Z4vvqLQAAcAjPT/3wafUIAAA4CiEFAABsmK6NV5M8luTH6i0AAPAfzk398GH1CAAAOCohBQAAbKCujV9n/5ni1+otAADwD85N/fBm9QgAADgOIQUAAGyoro1fJnkqYgoAANaLiAIAgI0mpAAAgA3WtfFy9mOKW9VbAAAgIgoAAGZASAEAABvuIKY4k+RO9RYAABbtgogCAIA5EFIAAMAMdG28mOS5iCkAAKhxYeqH16pHAADA3SCkAACAmeja+FH2Y4rfqrcAALAoIgoAAGZFSAEAADNyEFO8EjEFAAAnQ0QBAMDsCCkAAGBmuja+m+SliCkAAFitt0QUAADMkZACAABmqGvj+xFTAACwOuenfni9egQAAKyCkAIAAGZKTAEAwIqcnfrhbPUIAABYFSEFAADM2F9iijvVWwAAmIWzUz+crx4BAACrJKQAAICZO4gpno2YAgCA49uLiAIAgIUQUgAAwAJ0bfw4YgoAAI5nL8mrIgoAAJZCSAEAAAshpgAA4Bj+iCjerh4CAAAnRUgBAAALIqYAAOAIRBQAACySkAIAABbmIKZ4IsnN6i0AAKytvSQviygAAFgiIQUAACxQ18ZLSU4lmaq3AACwdnaTPDP1w3vVQwAAoIKQAgAAFqpr4+dJtpLsVG8BAGBt3E7y8NQPn1QPAQCAKkIKAABYsK6NV5I8kuR69RYAAMrdSvLg1A9fVA8BAIBKQgoAAFi4ro3bSR5Nsl29BQCAMjeTPDD1w1fVQwAAoJqQAgAASNfG69l/prhSvQUAgBP3U5L7p374tnoIAACsAyEFAACQJOnauJNkK8ml6i0AAJyY60nunfphp3oIAACsCyEFAADwp66NU9fGU0kuVm8BAGDlvkly39QPP1cPAQCAdXJP9QAAAGAtPZ3knSQvVA8BAGAlLk/9sFU9AgAA1pFHCgAA4G+6Nu52bXwxyRvVWwAAuOs+EFEAAMC/+x0AAP//7N3Pq+ZlGcfxD+QmaHVDIIgIwUA7MZVBrYUUfIU2SSAuSpTaxMCIq9BivsFAQ63irhvcFJK1yYhyIYqBzCLxBzJlCEI/kBzclIevluaMzZwWQwuhGc+M55zreZ7zev0F7z/gw3UZUgAAABfVRv9Okq8lOVOcAgDA7ji2TLOrYwAAcAmGFAAAwCW10X+SZEryVnULAABX7HySe5ZpPl4dAgAAq86QAgAA+FBt9JNJbktyuroFAIDLdibJF5ZpfrQ6BAAA1oEhBQAAsCNt9FeS3JLkleoWAAB2bElyaJnmZ6pDAABgXRhSAAAAO9ZGP50LlylOVrcAAPChTie5bpnm16tDAABgnRhSAAAAl6WN/laSO5I8UpwCAMDFnVqm+dplmt+uDgEAgHVjSAEAAFy2Nvp7bfT7kjyUZLu6BwCAD3hsmebPVEcAAMC6MqQAAACuWBv9RJI7k7xb3QIAQJLkW8s031UdAQAA68yQAgAA+Eja6L9J8tkkb1S3AAAcYOeSfHWZ5u9WhwAAwLozpAAAAD6yNvqpJDcneba6BQDgADqT5PAyzT+rDgEAgE1gSAEAAOyKNvobSW5P8vPqFgCAA+QfSQ4t0/xSdQgAAGwKQwoAAGDXtNHPttG/kuShJNvVPQAAG+7lJNcs0/x6dQgAAGwSQwoAAGDXtdFPJLk7yb+rWwAANtRjyzRfv0zz2eoQAADYNIYUAADAnmij/yLJbUleK04BANgk20mOLdN8V3UIAABsKkMKAABgz7TRTyW5Kcmz1S0AABvgvSTTMs3Hq0MAAGCTGVIAAAB7qo3+ZpLbkzxc3QIAsMZOJ7lmmeanq0MAAGDTXVUdAAAAbL42+tkk39g6cvQPSX6U5GPFSQAA6+SJZZq/WB0BAAAHhYsUAADAvmmjP5zkjiRvVrcAAKyB7ST3G1EAAMD+MqQAAAD2VRv9t0luSvJqdQsAwAp7J8mtyzT36hAAADhoDCkAAIB910Z/LcnhJI8XpwAArKI/J7l6mebnqkMAAOAgMqQAAABKtNHfTvKlJN9Mcq44BwBgVfx4meZDyzT/qzoEAAAOKkMKAACgTBt9u43+/SSfT7JV3QMAUOg/Sb68TPPXq0MAAOCgM6QAAADKtdFPJrkhyQvVLQAABf6e5NPLNP+qOgQAADCkAAAAVkQb/W9JPpfkB9UtAAD76KkkVy/T/JfqEAAA4IKrqgMAAAD+p41+NskDW0eO/i7JT5N8vDgJAGCvnE/ywDLNvToEAAD4IBcpAACAldNG/2WSw0n+VN0CALAH3klygxEFAACsJkMKAABgJbXR/5jkxiS/rm4BANhFv8+FVx4vV4cAAAD/n9ceAADAymqj/zPJnVtHjt6b5IdJPlFbBABwxbaTfG+Z5gerQwAAgEtzkQIAAFh5bfRHklyf5FRxCgDAlXg3yS1GFAAAsB4MKQAAgLXQRv9rksNJjic5V5wDALBTLyb55DLNz1eHAAAAO+O1BwAAsDba6O8nObZ15OiTSR5N8qniJACAizmf5NvLNJ+oDgEAAC7PfwEAAP//7N3fq6VVHcfxj+AfYIuSufBKLwxRhq6CCu2XPt40aubFMBQIKtKOTV3H8MCgI17pLFhYWpOhwgQRxiShISHKgDdREEhFXkheTDG7R5oGxTNzuhghMUM9nnPW2Xu/Xn/B+w/4rO9ykQIAAFg6pdVTufjVx4neLQAA7+NMkv1GFAAAsJwMKQAAgKVUWj1bWj2Y5GCSqXcPAMA7fpXk8mkY/9g7BAAA2BpDCgAAYKmVVk8kuTbJ871bAIC1tpHkm9Mwfm0axgu9YwAAgK0zpAAAAJZeafX1JDcm+W6SNzvnAADr589JrpiG8cneIQAAwMd3ae8AAACA7VBa3UxybDGbP5fkqSSf6ZwEAKy+C0mOTsN4uHcIAACwfVykAAAAVkpp9ZUkn01yNMn5zjkAwOo6neQ6IwoAAFg9LlIAAAArp7T6dpLvL2bzZ5I8keTKzkkAwOrYTPLkNIzf6h0CAADsDBcpAACAlVVaPZVkf5If9W4BAFbCIsmXjCgAAGC1GVIAAAArrbR6trR6d5IDSf7RuwcAWFpPJ/nUNIwv9A4BAAB2liEFAACwFkqrJ5Ncm+RE7xYAYKn8O8mt0zDeNg3jhd4xAADAzjOkAAAA1kZp9e+l1YNJDiaZevcAAHves0kum4bxl71DAACA3WNIAQAArJ3S6olcvE5xsncLALAnvZHkpmkYb56GcaN3DAAAsLsMKQAAgLVUWn29tHogyT1JzvbuAQD2jJ8nKdMw/qZ3CAAA0IchBQAAsNZKq48l2Z/kVO8WAKCrN5J8fhrGO6ZhvNA7BgAA6MeQAgAAWHul1VeTXJ/ke0ne7JwDAOyuzSQ/zcUrFIaVAABALu0dAAAAsBeUVs8neXgxm/86yfEkn+ucBADsvNNJbp6G8fe9QwAAgL3DRQoAAIB3Ka3+KckXktyZ5EznHABgZ5xPcmQaxn1GFAAAwHsZUgAAALxHaXWztPp4kquT/DgXT34DAKvh5ST7pmEce4cAAAB7k689AAAA/o/S6pkkdy1m8+NJHktyTeckAGDr/pXk0DSMJ3uHAAAAe5uLFAAAAB+gtHoqyf4kY5K3OucAAB/NZpKfJLnMiAIAAPgwXKQAAAD4EEqrG0mOLGbzp5I8muTLnZMAgA/2WpKvTsP4l94hAADA8jCkAAAA+AhKq39N8pXFbP71JMeSXNE5CQD4X28nOTwN44O9QwAAgOXjaw8AAIAtKK3+IsnVSQ4nOdc5BwD4r2eTfNKIAgAA2CoXKQAAALaotHouyX2L2fzxJA8l+UbfIgBYa6eT3DIN48u9QwAAgOVmSAEAAPAxlVb/luSOxWx+Q5IfJPl05yQAWCfnk9w/DePYOwQAAFgNvvYAAADYJqXVF5Jcl+TbSRadcwBgHbyYZJ8RBQAAsJ1cpAAAANhGpdWNJI8sZvOfJTma5O4YsQPAdvtnktunYfxt7xAAAGD1GFIAAADsgNLqIsm9i9n8kSTHktzQOQkAVsFGkh9Ow/id3iEAAMDq8ioKAABgB5VW/1Ba/WKS25K82jkHAJbVZpKTST5hRAEAAOw0QwoAAIBdUFp9Osk1ScYk5zrnAMAy+V2Sq6ZhPDAN49neMQAAwOrztQcAAMAuKa2+leTIYjY/nuSBJIeSXNK3CgD2rNeSHJqG8aXeIQAAwHr5DwAAAP//7N1NyGUFHcfxrwqBFBR3IYGRtMhVmzYl0SqQy7TIKEJLM21SFzcP+TL4AnmV1EjF8NItMEUiaJXhQskwoYWFRWkEtsgMFC00uV5KBKfRafFM9EKh07yc+zzP5wNn/92ew4//MaQAAAA4zibLxbPVZ1ez4RvVHdUHR04CgE3yl+qL6+n8u2OHAAAAu5MhBQAAwEgmy8XPqzNWs+EzbV2oePfISQAwpv3V7evp/JqxQwAAgN3txLEDAAAAdrvJcvG96r3VFdWfR84BgOPtQPWd6u1GFAAAwCZwkQIAAGADTJaL/dXtq9lwZzVU+6p3jFsFAMfU69X3q73r6fzlsWMAAAD+wZACAABgg0yWi5erm1ez4ZttXaj4UvW2casA4Kh6vXqgumA9na/GjgEAAPhPhhQAAAAbaLJcrKsvr2bDHdVV1aw6edwqADgiB6uHq/PW0/nzY8cAAAD8L4YUAAAAG2yyXLxY7VvNhtura6uLq7eMWwUAh+Vg9bPq3PV0/vTYMQAAAG/EkAIAAGAbmCwXf6ouXc2GW6t5dX7e6QDYfI9Vn15P578bOwQAAODN8tENAABgG5ksF89Ue1ez4avVNRlUALCZHqv2rqfzX48dAgAAcLh8bAMAANiGJsvF7/vnoOKG6pzqxHGrAKAnqvMMKAAAgO3MkAIAAGAbOzSoOHc1G26qbqw+Xp0wbhUAu9AT1RfW0/mjY4cAAAAcKUMKAACAHWCyXPy2+sRqNry/uqnaM3ISALvDk9X5BhQAAMBOYkgBAACwg0yWi8erj65mwweqy6uzR04CYGd6qrpkPZ0/PHYIAADA0WZIAQAAsANNlotfVOesZsNV1RXV56u3jlsFwDZ3sPplWwOKx8eOAQAAOFYMKQAAAHawyXLxdDWsZsO8mlWXVqeMWwXANvNa9aPq4vV0/tzYMQAAAMeaIQUAAMAuMFkuXqpuXM2GW6vPtXWl4vRxqwDYcK9Ud1dXr6fzV8aOAQAAOF4MKQAAAHaRyXLxanXnajZ8uzqr2ld9aNwqADbMi9XX1tP5bWOHAAAAjMGQAgAAYBeaLBcHq/uq+1az4YzqsuqT1UmjhgEwpj9U+9bT+Q/GDgEAABiTIQUAAMAuN1kuHq3OXs2G06orqwurt45bBcBxcrB6tJqtp/PHx44BAADYBIYUAAAAVDVZLp6uLl3Nhuuqi6qhOnXcKgCOkQPV/dVF6+n8xbFjAAAANokhBQAAAP9msly8VN2ymg1fr86rLq/eN24VAEfJX6s7q2vX0/n+sWMAAAA2kSEFAAAA/9VkufhbdU91z2o2nFldVu0ZtwqA/9Oz1Q3r6fyusUMAAAA2nSEFAAAAb2iyXDxUPbSaDadVl1QXVu8ctwqAN/Ba9dPq8vV0/quxYwAAALYLQwoAAADetMly8XR17Wo2XFedVV1cnVmdMGoYAP/qheru6nq/7wAAADh8hhQAAAActslycaC6t7r30JWKC6u91btGDQPYvQ5UP6mudn0CAADgyBhSAAAAcEQOXam4fjUbvlLtaevXH3uqk0YNA9gd/lh9q7p5PZ2/PnYMAADATmBIAQAAwFExWS5eq+6v7l/NhlOrC9q6UvGeMbsAdqD91Y+ra9bT+W/GjgEAANhpDCkAAAA46ibLxXPVTavZcHM1rS6qPpb3UIAj8Uy1XE/nt4wdAgAAsJP5gAUAAMAxM1kuDlYPVg+uZsMp1fltjSpOHzUMYPt4tfphdeV6On9q7BgAAIDdwJACAACA42KyXLxQ3VbdtpoNH25rUPGp6uRRwwA2z8HqyerW9XR+19gxAAAAu40hBQAAAMfdZLl4pHpkNRuG6uxDz0fGrQIY3bp6oLpiPZ0/P3YMAADAbvV3AAAA///s3c+v7Hddx/HntCkhkAAOv+6CaguhASSQWxQIsjBWnAgrQlDhX5hkFrgxIWFIgAXEkDg6AatGMZAYEBCBVKIoGKHSQi4UUwoBWihoW+xkWsCW/jjDYqae20urLb33fM+55/FI3vmemfkuXiezm3nN561IAQAAwGDGy8Ud1ZXVlavp7ET1uur3ql+rRkNmAzggd1afqt66nsyvHzoMAAAAihQAAAAcEuPl4pZqWS1X09nF1RvalipODhoM4Oy7q/pM9eb1ZH5q4CwAAACcQZECAACAQ2e8XNxcvat612o6u6x6fdtSxQsHDQbw8/tJ9bnq7evJ/F+GDgMAAMDDU6QAAADgUBsvF9+o3lG9YzWdPa96Y/W71WWDBgP4/91bXVO9cz2Zf3zoMAAAADwyihQAAAAcGePl4obqLdVbVtPZybaFit+pLh00GMC+B8oT715P5h8ZOgwAAACPniIFAAAAR9J4uThVnar+YDWdvbT9UsWzBg0GHEf3VV+q/mQ9mb9/6DAAAAA8NooUAAAAHHnj5eKatr8A//3VdPaytqWK11aXDJkLOK/dX32les96Mv/zocMAAABw9ihSAAAAcF4ZLxdfqL5QvWk1nT2/ek316uqV1UVDZgOOvB9V11Z/WX1gPZnvDZwHAACAc0CRAgAAgPPWeLn4WvW16g9X09mTqle1LVb8dnViyGzAkbCpbq6uqt69nsy/MXAeAAAADoAiBQAAAMfCeLm4s/pw9eHVdDaqLm97UsVrql+tLhgwHnB43F19uXp/9WfryfyegfMAAABwwBQpAAAAOHbGy8Wm+tJu3raazsbVFdVv7ubZA8YDDtZe9b3qH6s/XU/m1w6cBwAAgIEpUgAAAHDsjZeLVfWh3bSazi6pfqttqeI3qqcOFg442zbVbdXV1fuqv19P5nvDRgIAAOAwUaQAAACAM4yXi5uqK6srV9PZBdXJ9k+reGX1+OHSAT+HO9uu6/hg9RfryfzugfMAAABwiClSAAAAwP9hvFzstb8G5J2r6ezx1SvaXwXykurC4RICD+GH1fXVVdV715P5rQPnAQAA4AhRpAAAAIBHYbxc3F39827evJrOnlz9ettixRXVC4ZLB8fW7dVXqo9Xf7WezNcD5wEAAOAIU6QAAACAx2C8XNxRfWw3raazE+2fVnFFdfFw6eC8tKluq75Y/V311+vJ/J5hIwEAAHA+UaQAAACAs2i8XNxSfWA3raazS6uXVS/fzcnqcYMFhKPnrurG6urqo9VV68l8b9hIAAAAnM8UKQAAAOAcGi8XN7b9EvhvqlbT2eOqF7dfrHh59ezBAsLhstf2tInrqn+o3reezFfDRgIAAOC4UaQAAACAAzReLu6prt3NH1etprNx9YrqpdWvVJdXzxwqIxyQTbWuvlV9rvrb9WT+b8NGAgAAAEUKAAAAGNx4uVhVn9hNVavp7ET1kralisvbrgT5pUECwmN3f/Xf1derz1cfW0/m/z5sJAAAAHhoihQAAABwCI2Xi1uqT+6m+t+TK062X654fts1IXCY3NN2Pcf11Werj6wn8xuGjQQAAACPnCIFAAAAHBG7kys+vZuqVtPZRdVzqxfu5pd31+dUFw4Qk+Pjvur26sbqy9W/Vp9cT+Z3DpoKAAAAHiNFCgAAADjCxsvFvW1/+X999cHTX1tNZyd7cMHiudVlB52RI+++6o7qO9VX2xYmPrGezG8bNBUAAACcI4oUAAAAcJ4aLxenqlOnP7eazkbVierS3VxyxvXi6qKDzMmhsFf9qO1Kjm9X11VXV//khAkAAACOG0UKAAAAOEbGy8Wm+q/dfP6h7llNZ7/YtljxwFx6xmOOnk31k7ZliVXb9/+G6prqU+vJ/PsDZgMAAIBDRZECAAAAeJDxcvHd6rttVzj8jNV0dkk/W7C4uO1JF0+vnnbuU7Kzqe6t7mq7fuMH1ffbruH4evUf68n8s8PFAwAAgKNHkQIAAAB4VMbLxU3VTdVnHu6e1XT2zLalimeccX3g7/FunrKbJ53DyEfJ6cWIH1fr6vbq1ranSHynurH65noyv26okAAAAHA+U6QAAAAAzrrxcnFr2y//H7HVdPYL7RcrzpwnV0/czRMe5nrmcwdl8xCzd8bcV/1PDy5G/Gd1c4oRAAAAcKiMhg4AAAAAcC5sNptZ9aI2m9M//xi12Zx20/azkbv37r2oCy+8f3tDjRptqkaj0Wa0LUZ0QaNGozYPvFb90Wg0+uq5/08AAACAg6RIAQAAAAAAAACw81MAAAD//+zasQAAAADAIH/rPcMojkQKAAAAAAAAAICJFAAAAAAAAAAAEykAAAAAAAAAACZSAAAAAAAAAABMpAAAAAAAAAAAmEgBAAAAAAAAADCRAgAAAAAAAABgIgUAAAAAAAAAwEQKAAAAAAAAAICJFAAAAAAAAAAAEykAAAAAAAAAACZSAAAAAAAAAABMpAAAAAAAAAAAmEgBAAAAAAAAADCRAgAAAAAAAABgIgUAAAAAAAAAwEQKAAAAAAAAAICJFAAAAAAAAAAAEykAAAAAAAAAACZSAAAAAAAAAABMpAAAAAAAAAAAmEgBAAAAAAAAADCRAgAAAAAAAABgIgUAAAAAAAAAwEQKAAAAAAAAAICJFAAAAAAAAAAAEykAAAAAAAAAACZSAAAAAAAAAABMpAAAAAAAAAAAmEgBAAAAAAAAADCRAgAAAAAAAABgAQAA///s2rEAAAAAwCB/6z3DKI5ECgAAAAAAAACAiRQAAAAAAAAAABMpAAAAAAAAAAAmUgAAAAAAAAAATKQAAAAAAAAAAJhIAQAAAAAAAAAwkQIAAAAAAAAAYCIFAAAAAAAAAMBECgAAAAAAAACAiRQAAAAAAAAAABMpAAAAAAAAAAAmUgAAAAAAAAAATKQAAAAAAAAAAJhIAQAAAAAAAAAwkQIAAAAAAAAAYCIFAAAAAAAAAMBECgAAAAAAAACAiRQAAAAAAAAAABMpAAAAAAAAAAAmUgAAAAAAAAAATKQAAAAAAAAAAJhIAQAAAAAAAAAwkQIAAAAAAAAAYCIFAAAAAAAAAMBECgAAAAAAAACAiRQAAAAAAAAAABMpAAAAAAAAAAAmUgAAAAAAAAAATKQAAAAAAAAAAJhIAQAAAAAAAAAwkQIAAAAAAAAAYAEAAP//7NqxAAAAAMAgf+s9wyiORAoAAAAAAAAAgIkUAAAAAAAAAAATKQAAAAAAAAAAJlIAAAAAAAAAAEykAAAAAAAAAACYSAEAAAAAAAAAMJECAAAAAAAAAGAiBQAAAAAAAADARAoAAAAAAAAAgIkUAAAAAAAAAAATKQAAAAAAAAAAJlIAAAAAAAAAAEykAAAAAAAAAACYSAEAAAAAAAAAMJECAAAAAAAAAGAiBQAAAAAAAADARAoAAAAAAAAAgIkUAAAAAAAAAAATKQAAAAAAAAAAJlIAAAAAAAAAAEykAAAAAAAAAACYSAEAAAAAAAAAMJECAAAAAAAAAGAiBQAAAAAAAADARAoAAAAAAAAAgIkUAAAAAAAAAAATKQAAAAAAAAAAJlIAAAAAAAAAAEykAAAAAAAAAACYSAEAAAAAAAAAMJECAAAAAAAAAGABAAD//+3asQAAAADAIH/rPcMojkQKAAAAAAAAAICJFAAAAAAAAAAAEykAAAAAAAAAACZSAAAAAAAAAABMpAAAAAAAAAAAmEgBAAAAAAAAADCRAgAAAAAAAABgIgUAAAAAAAAAwEQKAAAAAAAAAICJFAAAAAAAAAAAEykAAAAAAAAAACZSAAAAAAAAAABMpAAAAAAAAAAAmEgBAAAAAAAAADCRAgAAAAAAAABgIgUAAAAAAAAAwEQKAAAAAAAAAICJFAAAAAAAAAAAEykAAAAAAAAAACZSAAAAAAAAAABMpAAAAAAAAAAAmEgBAAAAAAAAADCRAgAAAAAAAABgIgUAAAAAAAAAwEQKAAAAAAAAAICJFAAAAAAAAAAAEykAAAAAAAAAACZSAAAAAAAAAABMpAAAAAAAAAAAmEgBAAAAAAAAADCRAgAAAAAAAABgARLqJEsAaBXPAAAAAElFTkSuQmCC";
|
|
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
|
-
|
|
21702
|
+
Logo,
|
|
21308
21703
|
{
|
|
21309
|
-
|
|
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
|
-
|
|
21326
|
-
|
|
21327
|
-
|
|
21328
|
-
|
|
21329
|
-
|
|
21330
|
-
|
|
21331
|
-
|
|
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:", {
|
|
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("
|
|
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
|
-
|
|
21381
|
-
|
|
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
|
|
21384
|
-
|
|
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 =
|
|
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.
|
|
29256
|
-
|
|
29257
|
-
|
|
29258
|
-
|
|
29259
|
-
e
|
|
29260
|
-
|
|
29261
|
-
|
|
29262
|
-
|
|
29263
|
-
|
|
29264
|
-
|
|
29265
|
-
|
|
29266
|
-
|
|
29267
|
-
|
|
29268
|
-
|
|
29269
|
-
|
|
29270
|
-
|
|
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
|
|
37901
|
-
|
|
37902
|
-
|
|
37903
|
-
|
|
37904
|
-
|
|
37905
|
-
|
|
37906
|
-
|
|
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
|
|
37915
|
-
|
|
37916
|
-
|
|
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 <
|
|
38101
|
-
setTypedText(
|
|
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",
|
|
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 <
|
|
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 =
|
|
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.
|
|
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("
|
|
46456
|
-
/* @__PURE__ */ jsxRuntime.
|
|
46457
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
46458
|
-
|
|
46459
|
-
|
|
46460
|
-
|
|
46461
|
-
|
|
46462
|
-
|
|
46463
|
-
|
|
46464
|
-
|
|
46465
|
-
|
|
46466
|
-
|
|
46467
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex
|
|
46468
|
-
/* @__PURE__ */ jsxRuntime.
|
|
46469
|
-
|
|
46470
|
-
workspaceHealth
|
|
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
|
|
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
|
-
|
|
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(
|
|
46521
|
-
|
|
46522
|
-
|
|
46523
|
-
|
|
46524
|
-
|
|
46525
|
-
|
|
46526
|
-
|
|
46527
|
-
|
|
46528
|
-
|
|
46529
|
-
|
|
46530
|
-
|
|
46531
|
-
|
|
46532
|
-
|
|
46533
|
-
|
|
46534
|
-
|
|
46535
|
-
|
|
46536
|
-
|
|
46537
|
-
|
|
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.
|
|
46540
|
-
|
|
46541
|
-
|
|
46542
|
-
|
|
46543
|
-
|
|
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
|
-
|
|
46549
|
-
|
|
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: `
|
|
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: `
|
|
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: `
|
|
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.
|
|
46576
|
-
|
|
46577
|
-
|
|
46578
|
-
|
|
46579
|
-
|
|
46580
|
-
|
|
46581
|
-
|
|
46582
|
-
|
|
46583
|
-
|
|
46584
|
-
|
|
46585
|
-
|
|
46586
|
-
|
|
46587
|
-
|
|
46588
|
-
|
|
46589
|
-
|
|
46590
|
-
|
|
46591
|
-
|
|
46592
|
-
|
|
46593
|
-
|
|
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: () =>
|
|
46597
|
-
className: `
|
|
46598
|
-
|
|
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
|
-
|
|
46603
|
-
|
|
46604
|
-
WorkspaceMonthlyPdfGenerator,
|
|
47449
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
47450
|
+
"div",
|
|
46605
47451
|
{
|
|
46606
|
-
|
|
46607
|
-
|
|
46608
|
-
|
|
46609
|
-
|
|
46610
|
-
|
|
46611
|
-
|
|
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
|
-
|
|
46618
|
-
|
|
46619
|
-
|
|
46620
|
-
|
|
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:
|
|
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
|
-
|
|
46666
|
-
|
|
46667
|
-
|
|
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-[
|
|
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: "
|
|
46738
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
46739
|
-
|
|
46740
|
-
|
|
46741
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
46742
|
-
|
|
46743
|
-
|
|
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
|
-
|
|
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
|
-
|
|
46824
|
-
/* @__PURE__ */ jsxRuntime.
|
|
46825
|
-
|
|
46826
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
46827
|
-
|
|
46828
|
-
|
|
46829
|
-
|
|
46830
|
-
|
|
46831
|
-
|
|
46832
|
-
|
|
46833
|
-
|
|
46834
|
-
|
|
46835
|
-
|
|
46836
|
-
|
|
46837
|
-
|
|
46838
|
-
|
|
46839
|
-
|
|
46840
|
-
|
|
46841
|
-
|
|
46842
|
-
|
|
46843
|
-
|
|
46844
|
-
|
|
46845
|
-
|
|
46846
|
-
|
|
46847
|
-
|
|
46848
|
-
|
|
46849
|
-
|
|
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
|
-
|
|
46910
|
-
|
|
46911
|
-
|
|
46912
|
-
|
|
46913
|
-
className: "h-[calc(100vh-10rem)]"
|
|
47635
|
+
selectedMonth,
|
|
47636
|
+
selectedYear,
|
|
47637
|
+
onDataLoaded: handleMonthlyDataLoaded,
|
|
47638
|
+
onLoadingChange: setMonthlyDataLoading
|
|
46914
47639
|
}
|
|
46915
|
-
)
|
|
46916
|
-
|
|
46917
|
-
|
|
46918
|
-
|
|
46919
|
-
|
|
46920
|
-
|
|
46921
|
-
|
|
46922
|
-
|
|
46923
|
-
|
|
46924
|
-
|
|
46925
|
-
|
|
46926
|
-
|
|
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
|
-
|
|
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
|
-
|
|
48064
|
-
|
|
48065
|
-
|
|
48066
|
-
|
|
48067
|
-
|
|
48068
|
-
|
|
48069
|
-
|
|
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(
|
|
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-
|
|
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 &&
|
|
48157
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
48158
|
-
/* @__PURE__ */ jsxRuntime.
|
|
48159
|
-
|
|
48160
|
-
|
|
48161
|
-
|
|
48162
|
-
|
|
48163
|
-
|
|
48164
|
-
|
|
48165
|
-
|
|
48166
|
-
|
|
48167
|
-
|
|
48168
|
-
|
|
48169
|
-
|
|
48170
|
-
|
|
48171
|
-
|
|
48172
|
-
|
|
48173
|
-
|
|
48174
|
-
|
|
48175
|
-
|
|
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
|
-
|
|
48220
|
-
|
|
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(
|
|
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-
|
|
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 &&
|
|
48329
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
48330
|
-
/* @__PURE__ */ jsxRuntime.
|
|
48331
|
-
|
|
48332
|
-
|
|
48333
|
-
|
|
48334
|
-
|
|
48335
|
-
|
|
48336
|
-
|
|
48337
|
-
|
|
48338
|
-
|
|
48339
|
-
|
|
48340
|
-
|
|
48341
|
-
|
|
48342
|
-
|
|
48343
|
-
|
|
48344
|
-
|
|
48345
|
-
|
|
48346
|
-
|
|
48347
|
-
|
|
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
|
-
|
|
48389
|
-
|
|
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
|
|
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
|
|
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
|
|
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;
|