import { ColorScheme, ColorSchemeProvider, Container, MantineProvider, } from "@mantine/core"; import { useColorScheme } from "@mantine/hooks"; import { ModalsProvider } from "@mantine/modals"; import { Notifications } from "@mantine/notifications"; import axios from "axios"; import { getCookie, setCookie } from "cookies-next"; import moment from "moment"; import "moment/min/locales"; import { GetServerSidePropsContext } from "next"; import type { AppProps } from "next/app"; import Head from "next/head"; import { useRouter } from "next/router"; import { useEffect, useRef, useState } from "react"; import { IntlProvider } from "react-intl"; import Header from "../components/header/Header"; import { ConfigContext } from "../hooks/config.hook"; import { UserContext } from "../hooks/user.hook"; import { LOCALES } from "../i18n/locales"; import authService from "../services/auth.service"; import configService from "../services/config.service"; import userService from "../services/user.service"; import GlobalStyle from "../styles/global.style"; import globalStyle from "../styles/mantine.style"; import Config from "../types/config.type"; import { CurrentUser } from "../types/user.type"; import i18nUtil from "../utils/i18n.util"; import userPreferences from "../utils/userPreferences.util"; const excludeDefaultLayoutRoutes = ["/admin/config/[category]"]; function App({ Component, pageProps }: AppProps) { const systemTheme = useColorScheme(pageProps.colorScheme); const router = useRouter(); const [colorScheme, setColorScheme] = useState(systemTheme); const [user, setUser] = useState(pageProps.user); const [route, setRoute] = useState(pageProps.route); const [configVariables, setConfigVariables] = useState( pageProps.configVariables, ); useEffect(() => { setRoute(router.pathname); }, [router.pathname]); useEffect(() => { const interval = setInterval( async () => await authService.refreshAccessToken(), 2 * 60 * 1000, // 2 minutes ); return () => clearInterval(interval); }, []); useEffect(() => { if (!pageProps.language) return; const cookieLanguage = getCookie("language"); if (pageProps.language != cookieLanguage) { i18nUtil.setLanguageCookie(pageProps.language); if (cookieLanguage) location.reload(); } }, []); useEffect(() => { const colorScheme = userPreferences.get("colorScheme") == "system" ? systemTheme : userPreferences.get("colorScheme"); toggleColorScheme(colorScheme); }, [systemTheme]); const toggleColorScheme = (value: ColorScheme) => { setColorScheme(value ?? "light"); setCookie("mantine-color-scheme", value ?? "light", { sameSite: "lax", }); }; const language = useRef(pageProps.language); moment.locale(language.current); return ( <> { setConfigVariables(await configService.list()); }, }} > { const user = await userService.getCurrentUser(); setUser(user); return user; }, }} > {excludeDefaultLayoutRoutes.includes(route) ? ( ) : ( <>
)} ); } // Fetch user and config variables on server side when the first request is made // These will get passed as a page prop to the App component and stored in the contexts App.getInitialProps = async ({ ctx }: { ctx: GetServerSidePropsContext }) => { let pageProps: { user?: CurrentUser; configVariables?: Config[]; route?: string; colorScheme: ColorScheme; language?: string; } = { route: ctx.resolvedUrl, colorScheme: (getCookie("mantine-color-scheme", ctx) as ColorScheme) ?? "light", }; if (ctx.req) { const apiURL = process.env.API_URL || "http://localhost:8080"; const cookieHeader = ctx.req.headers.cookie; pageProps.user = await axios(`${apiURL}/api/users/me`, { headers: { cookie: cookieHeader }, }) .then((res) => res.data) .catch(() => null); pageProps.configVariables = (await axios(`${apiURL}/api/configs`)).data; pageProps.route = ctx.req.url; const requestLanguage = i18nUtil.getLanguageFromAcceptHeader( ctx.req.headers["accept-language"], ); pageProps.language = ctx.req.cookies["language"] ?? requestLanguage; } return { pageProps }; }; export default App;