aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/App.tsx2
-rw-r--r--src/pages/FormPage/FormPage.tsx41
-rw-r--r--src/pages/NotFound.tsx26
3 files changed, 61 insertions, 8 deletions
diff --git a/src/App.tsx b/src/App.tsx
index 5430e40..70e0b11 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -10,6 +10,7 @@ import { PropagateLoader } from "react-spinners";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import globalStyles from "./globalStyles";
+import NotFound from "./pages/NotFound";
const LandingPage = React.lazy(() => import("./pages/LandingPage"));
const FormPage = React.lazy(() => import("./pages/FormPage/FormPage"));
@@ -41,6 +42,7 @@ function Routing(): JSX.Element {
return (
<Routes location={location}>
{renderedRoutes}
+ <Route path="*" element={<NotFound message={"404: This page does not exist"}/>}/>
</Routes>
);
}
diff --git a/src/pages/FormPage/FormPage.tsx b/src/pages/FormPage/FormPage.tsx
index 9f74410..05b51c0 100644
--- a/src/pages/FormPage/FormPage.tsx
+++ b/src/pages/FormPage/FormPage.tsx
@@ -1,9 +1,11 @@
/** @jsx jsx */
+/** @jsxFrag */
import {jsx, css} from "@emotion/react";
import React, {createRef, SyntheticEvent, useEffect, useState} from "react";
import {useParams} from "react-router";
import {PropagateLoader} from "react-spinners";
+import {AxiosError} from "axios";
import HeaderBar from "../../components/HeaderBar";
import RenderedQuestion from "../../components/Question";
@@ -19,6 +21,7 @@ import handleSubmit, {FormState} from "./submit";
import Navigation from "./Navigation";
import Success from "./SuccessPage";
import ErrorPage from "./ErrorPage";
+import NotFound from "../NotFound";
export type RefMapType = Map<string, React.RefObject<RenderedQuestion>>;
@@ -49,24 +52,47 @@ const closedHeaderStyles = css`
}
`;
+enum LoadingState {
+ Pending,
+ Found,
+ Missing
+}
+
function FormPage(): JSX.Element {
const {id} = useParams<{id: string}>();
const [form, setForm] = useState<Form>();
+ const [formLoading, setFormLoading] = useState<LoadingState>(LoadingState.Pending);
const [state, setState] = useState<string>(FormState.INITIAL);
const OAuthRef = createRef<HTMLDivElement>();
useEffect(() => {
- // This can't be null due to the routing to get here
+ // ID can't be null due to the routing to get here
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
getForm(id!).then(form => {
setForm(form);
+ setFormLoading(LoadingState.Found);
+ }).catch((error: AxiosError) => {
+ if (error.response?.status === 404) {
+ setFormLoading(LoadingState.Missing);
+ return;
+ }
+
+ throw error;
});
}, []);
+ switch (formLoading) {
+ case LoadingState.Pending:
+ return <Loading/>;
+ case LoadingState.Missing:
+ return <NotFound message={"Could not find a matching form. Make sure the requested form exists and is open."}/>;
+ }
+
if (!form) {
- return <Loading/>;
+ // This should be an impossible state
+ throw Error("Form was not set despite loading state being set to found.");
}
const refMap: RefMapType = new Map();
@@ -88,9 +114,6 @@ function FormPage(): JSX.Element {
<div css={closedHeaderStyles}>This form is now closed. You will not be able to submit your response.</div>;
}
- // FIXME: Remove this ignore
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
const questions: RenderedQuestion[] = form.questions.map((question, index) => {
const questionRef = createRef<RenderedQuestion>();
refMap.set(question.id, questionRef);
@@ -102,7 +125,7 @@ function FormPage(): JSX.Element {
key={index + Date.now()}
selfRef={questionRef}
ref={questionRef}
- />;
+ /> as unknown as RenderedQuestion; // Annotations for JSX elements resolve to a generic ReactElement
});
switch (state) {
@@ -133,8 +156,10 @@ function FormPage(): JSX.Element {
<div>
<form id="form" onSubmit={handler} css={[formStyles, unselectable]}>
- {closed_header}
- {questions}
+ <>
+ {closed_header}
+ {questions}
+ </>
</form>
<Navigation form_state={open} scopes={scopes}/>
</div>
diff --git a/src/pages/NotFound.tsx b/src/pages/NotFound.tsx
new file mode 100644
index 0000000..6947a38
--- /dev/null
+++ b/src/pages/NotFound.tsx
@@ -0,0 +1,26 @@
+/** @jsx jsx */
+import {jsx, css} from "@emotion/react";
+import {Link} from "react-router-dom";
+
+import HeaderBar from "../components/HeaderBar";
+import {mainTextStyles, navigationStyles, returnButtonStyles, unselectable} from "../commonStyles";
+
+interface NotFoundProps {
+ message: string
+}
+
+
+/** Simple 404 page. */
+export default function NotFound(props: NotFoundProps): JSX.Element {
+ return <div>
+ <HeaderBar/>
+ <div css={css`width: 80%; margin: auto;`}>
+ <div css={mainTextStyles}>
+ <p>{props.message}</p>
+ </div>
+ <div css={[unselectable, navigationStyles]}>
+ <Link css={returnButtonStyles} to="/">Return Home</Link>
+ </div>
+ </div>
+ </div>;
+}