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