All files / app/pages _app.tsx

0% Statements 0/40
0% Branches 0/3
0% Functions 0/8
0% Lines 0/37

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98                                                                                                                                                                                                   
import "intersection-observer";
import "./main.css";
 
import {
  CssBaseline,
  StyledEngineProvider,
  ThemeProvider,
} from "@mui/material";
import { AppCacheProvider } from "@mui/material-nextjs/v15-pagesRouter";
import { LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { EnvironmentBanner } from "components/EnvironmentBanner";
import ErrorBoundary from "components/ErrorBoundary";
import HtmlMeta from "components/HtmlMeta";
import AuthProvider from "features/auth/AuthProvider";
import { ReactQueryClientProvider } from "features/reactQueryClient";
import StatsigProvider from "features/statsig/StatsigProvider";
import type { AppProps } from "next/app";
import { appWithTranslation } from "next-i18next";
import nextI18nextConfig from "next-i18next.config";
import React, { ReactNode, useEffect } from "react";
import TagManager from "react-gtm-module";
import { polyfill } from "seamless-scroll-polyfill";
import { theme } from "theme";
 
type AppWithLayoutProps = Omit<AppProps, "Component"> & {
  Component: AppProps["Component"] & {
    getLayout: (page: ReactNode) => ReactNode;
  };
};
 
function MyApp(props: AppWithLayoutProps) {
  const { Component, pageProps } = props;
  const getLayout = Component.getLayout ?? ((page: ReactNode) => page);
  useEffect(() => polyfill(), []);
 
  useEffect(() => {
    Iif (process.env.NEXT_PUBLIC_COUCHERS_ENV === "prod") {
      TagManager.initialize({ gtmId: "GTM-PXP3896" });
    }
  }, []);
 
  /**
   * Mobile viewport workaround (not Next.js related - this is a browser issue).
   * Mobile browsers include the address bar in 100vh, causing layout issues.
   * This sets a CSS variable --vh to the actual visible viewport height.
   * Use `calc(var(--vh, 1vh) * 100)` instead of `100vh` in CSS for consistent behavior.
   * The resetScroll helps recalibrate sticky positioning after keyboard closes. */
  useEffect(() => {
    const updateVH = () => {
      document.documentElement.style.setProperty(
        "--vh",
        `${window.innerHeight * 0.01}px`,
      );
    };
 
    const resetScroll = () => {
      // Scroll the page by a tiny amount to trigger recalibration
      window.scrollTo(0, window.scrollY + 1);
      window.scrollTo(0, window.scrollY - 1);
    };
 
    updateVH();
    window.addEventListener("resize", updateVH);
    window.addEventListener("focusout", resetScroll);
 
    return () => {
      window.removeEventListener("resize", updateVH);
      window.removeEventListener("focusout", resetScroll);
    };
  }, []);
 
  return (
    <AppCacheProvider {...props}>
      <StyledEngineProvider injectFirst>
        <LocalizationProvider dateAdapter={AdapterDayjs}>
          <ThemeProvider theme={theme}>
            <ErrorBoundary isFatal>
              <ReactQueryClientProvider>
                <AuthProvider>
                  <StatsigProvider>
                    <CssBaseline />
                    <EnvironmentBanner />
                    <HtmlMeta />
                    {getLayout(<Component {...pageProps} />)}
                  </StatsigProvider>
                </AuthProvider>
              </ReactQueryClientProvider>
            </ErrorBoundary>
          </ThemeProvider>
        </LocalizationProvider>
      </StyledEngineProvider>
    </AppCacheProvider>
  );
}
 
export default appWithTranslation(MyApp, nextI18nextConfig);