import { ApolloProvider } from "@apollo/client/react"; import * as Sentry from "@sentry/react"; import { SplitFactoryProvider, useSplitClient } from "@splitsoftware/splitio-react"; import { ConfigProvider } from "antd"; import enLocale from "antd/es/locale/en_US"; import { useEffect } from "react"; import { CookiesProvider } from "react-cookie"; import { useTranslation } from "react-i18next"; import { useDispatch, useSelector } from "react-redux"; import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component"; import { setDarkMode } from "../redux/application/application.actions"; import { selectDarkMode } from "../redux/application/application.selectors"; import { selectCurrentUser } from "../redux/user/user.selectors.js"; import { signOutStart } from "../redux/user/user.actions"; import client from "../utils/GraphQLClient"; import App from "./App"; import getTheme from "./themeProvider"; // Base Split configuration const config = { core: { authorizationKey: import.meta.env.VITE_APP_SPLIT_API, key: "anon" } }; function SplitClientProvider({ children }) { const imexshopid = useSelector((state) => state.user.imexshopid); const splitClient = useSplitClient({ key: imexshopid || "anon" }); useEffect(() => { if (import.meta.env.DEV && splitClient && imexshopid) { console.log(`Split client initialized with key: ${imexshopid}, isReady: ${splitClient.isReady}`); } }, [splitClient, imexshopid]); return children; } function AppContainer() { const { t } = useTranslation(); const dispatch = useDispatch(); const currentUser = useSelector(selectCurrentUser); const isDarkMode = useSelector(selectDarkMode); const theme = () => getTheme(isDarkMode); const antdInput = () => ({ autoComplete: "new-password" }); const antdForm = () => ({ validateMessages: { required: t("general.validation.required", { label: "${label}" }) } }); // Global seamless logout listener with redirect to /signin useEffect(() => { const handleSeamlessLogout = (event) => { if (event.data?.type !== "seamlessLogoutRequest") return; // Only accept messages from the parent window if (event.source !== window.parent) return; const targetOrigin = event.origin || "*"; if (currentUser?.authorized !== true) { window.parent?.postMessage({ type: "seamlessLogoutResponse", status: "already_logged_out" }, targetOrigin); return; } dispatch(signOutStart()); window.parent?.postMessage({ type: "seamlessLogoutResponse", status: "logged_out" }, targetOrigin); }; window.addEventListener("message", handleSeamlessLogout); return () => { window.removeEventListener("message", handleSeamlessLogout); }; }, [dispatch, currentUser?.authorized]); // Update data-theme attribute (no cleanup to avoid transient style churn) useEffect(() => { document.documentElement.dataset.theme = isDarkMode ? "dark" : "light"; }, [isDarkMode]); // Sync darkMode with localStorage useEffect(() => { const uid = currentUser?.uid; if (!uid) { dispatch(setDarkMode(false)); return; } const key = `dark-mode-${uid}`; const raw = localStorage.getItem(key); if (raw == null) { dispatch(setDarkMode(false)); return; } try { dispatch(setDarkMode(Boolean(JSON.parse(raw)))); } catch { dispatch(setDarkMode(false)); } }, [currentUser?.uid, dispatch]); // Persist darkMode useEffect(() => { const uid = currentUser?.uid; if (!uid) return; localStorage.setItem(`dark-mode-${uid}`, JSON.stringify(isDarkMode)); }, [isDarkMode, currentUser?.uid]); return ( ); } export default Sentry.withProfiler(AppContainer);