backstory/frontend/src/SessionWrapper.tsx

66 lines
1.9 KiB
TypeScript

import { useEffect, useState, useRef } from "react";
import { useNavigate, useLocation } from "react-router-dom";
import { connectionBase } from './Global';
import { SetSnackType } from './Snack';
const getSessionId = async () => {
const response = await fetch(connectionBase + `/api/context`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw Error("Server is temporarily down.");
}
const newSession = (await response.json()).id;
console.log(`Session created: ${newSession}`);
return newSession;
};
interface SessionWrapperProps {
setSnack: SetSnackType;
children: React.ReactNode;
}
const SessionWrapper = ({ setSnack, children }: SessionWrapperProps) => {
const navigate = useNavigate();
const location = useLocation();
const [sessionId, setSessionId] = useState<string | undefined>(undefined);
const fetchingRef = useRef(false);
useEffect(() => {
const ensureSessionId = async () => {
const parts = location.pathname.split("/").filter(Boolean);
const pattern = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/i;
const hasSession = parts.length !== 0 && pattern.test(parts[parts.length - 1]);
if (!hasSession) {
let activeSession = sessionId;
if (!activeSession) {
activeSession = await getSessionId();
setSessionId(activeSession);
}
const newPath = [...parts, activeSession].join("/");
navigate(`/${newPath}`, { replace: true });
}
};
if (!fetchingRef.current) {
fetchingRef.current = true;
ensureSessionId().catch((e) => {
console.error(e);
setSnack("Backstory is temporarily unavailable.", "error");
});
}
}, [location.pathname, navigate, setSnack, sessionId]);
return <>{children}</>;
};
export { SessionWrapper };