import { useRouter } from "next/router"; import { createContext, useContext, useEffect, type FC, type ReactNode, } from "react"; import type { Session, ValidSession } from "~/server/api/trpc"; import { api } from "~/utils/api"; type SessionStatus = "pending" | "success" | "error"; export type SessionContextType = { user: Session | null; status: SessionStatus; }; const SessionContext = createContext({ user: null, status: "pending", }); export const SessionProvider: FC<{ children: ReactNode }> = ({ children }) => { const router = useRouter(); const utils = api.useUtils(); const { data: user, status, isLoading, isError, error, } = api.auth.getSession.useQuery(undefined, { refetchOnWindowFocus: true, refetchOnReconnect: true, refetchOnMount: true, staleTime: 0, refetchInterval: 30000, }); if (isError && error) { console.error("Session fetch error: ", error); } // Invalidate session on route change useEffect(() => { const handleRouteChange = () => { if (isLoading) return; utils.auth.getSession.invalidate().catch((error: Error) => { console.error("Error invalidating session on route change:", error); }); }; router.events.on("routeChangeComplete", handleRouteChange); return () => { router.events.off("routeChangeComplete", handleRouteChange); }; }, [router, utils]); // Invalidate session if user is null useEffect(() => { if (!user) { utils.auth.getSession.invalidate().catch((error: Error) => { console.error("Error during session invalidation:", error); }); } }, [user]); return ( {children} ); }; export const useSession = () => useContext(SessionContext); export const EnforcedSessionContext = createContext( undefined, ); /** * AreaRiservata specific session context. It ensures that the session is valid. */ export const useEnforcedSession = () => { const session = useContext(EnforcedSessionContext); if (!session) { throw new Error( "useValidSession must be used within a ValidSessionProvider", ); } return session; };