2025-08-04 17:45:44 +02:00
|
|
|
import { useRouter } from "next/router";
|
|
|
|
|
import {
|
2025-08-28 18:27:07 +02:00
|
|
|
createContext,
|
|
|
|
|
type FC,
|
|
|
|
|
type ReactNode,
|
|
|
|
|
useContext,
|
|
|
|
|
useEffect,
|
2025-08-04 17:45:44 +02:00
|
|
|
} from "react";
|
2025-08-20 14:04:23 +02:00
|
|
|
import type { Session, ValidSession } from "~/server/api/trpc";
|
2025-08-04 17:45:44 +02:00
|
|
|
import { api } from "~/utils/api";
|
2025-08-28 18:27:07 +02:00
|
|
|
|
2025-08-04 17:45:44 +02:00
|
|
|
type SessionStatus = "pending" | "success" | "error";
|
|
|
|
|
export type SessionContextType = {
|
2025-08-28 18:27:07 +02:00
|
|
|
user: Session | null;
|
|
|
|
|
status: SessionStatus;
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const SessionContext = createContext<SessionContextType>({
|
2025-08-28 18:27:07 +02:00
|
|
|
status: "pending",
|
2025-08-29 16:18:32 +02:00
|
|
|
user: null,
|
2025-08-04 17:45:44 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const SessionProvider: FC<{ children: ReactNode }> = ({ children }) => {
|
2025-08-28 18:27:07 +02:00
|
|
|
const router = useRouter();
|
|
|
|
|
const utils = api.useUtils();
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
const {
|
|
|
|
|
data: user,
|
|
|
|
|
status,
|
|
|
|
|
isLoading,
|
|
|
|
|
isError,
|
|
|
|
|
error,
|
|
|
|
|
} = api.auth.getSession.useQuery(undefined, {
|
2025-08-29 16:18:32 +02:00
|
|
|
refetchInterval: 30000,
|
2025-08-28 18:27:07 +02:00
|
|
|
refetchOnMount: true,
|
2025-08-29 16:18:32 +02:00
|
|
|
refetchOnReconnect: true,
|
|
|
|
|
refetchOnWindowFocus: true,
|
2025-08-28 18:27:07 +02:00
|
|
|
staleTime: 0,
|
|
|
|
|
});
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
if (isError && error) {
|
|
|
|
|
console.error("Session fetch error: ", error);
|
|
|
|
|
}
|
2025-08-28 13:46:51 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
// 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]);
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
// Invalidate session if user is null
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!user) {
|
|
|
|
|
utils.auth.getSession.invalidate().catch((error: Error) => {
|
|
|
|
|
console.error("Error during session invalidation:", error);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}, [user]);
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
return (
|
2025-08-29 16:18:32 +02:00
|
|
|
<SessionContext.Provider value={{ status, user: user || null }}>
|
2025-08-28 18:27:07 +02:00
|
|
|
{children}
|
|
|
|
|
</SessionContext.Provider>
|
|
|
|
|
);
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const useSession = () => useContext(SessionContext);
|
2025-08-20 14:04:23 +02:00
|
|
|
|
|
|
|
|
export const EnforcedSessionContext = createContext<ValidSession | undefined>(
|
2025-08-28 18:27:07 +02:00
|
|
|
undefined,
|
2025-08-20 14:04:23 +02:00
|
|
|
);
|
|
|
|
|
/**
|
|
|
|
|
* AreaRiservata specific session context. It ensures that the session is valid.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
export const useEnforcedSession = () => {
|
2025-08-28 18:27:07 +02:00
|
|
|
const session = useContext(EnforcedSessionContext);
|
|
|
|
|
if (!session) {
|
|
|
|
|
throw new Error(
|
|
|
|
|
"useValidSession must be used within a ValidSessionProvider",
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return session;
|
2025-08-20 14:04:23 +02:00
|
|
|
};
|