From cebc474bd5806571a1b7bf8717ab70d971a12405 Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Tue, 19 Jul 2022 14:56:23 +0200 Subject: Add 404 Page Signed-off-by: Hassan Abouelela --- src/App.tsx | 2 ++ src/pages/FormPage/FormPage.tsx | 41 +++++++++++++++++++++++++++++++++-------- src/pages/NotFound.tsx | 26 ++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 src/pages/NotFound.tsx (limited to 'src') 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 ( {renderedRoutes} + }/> ); } 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>; @@ -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
(); + const [formLoading, setFormLoading] = useState(LoadingState.Pending); const [state, setState] = useState(FormState.INITIAL); const OAuthRef = createRef(); 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 ; + case LoadingState.Missing: + return ; + } + if (!form) { - return ; + // 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 {
This form is now closed. You will not be able to submit your response.
; } - // 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(); 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 {
- {closed_header} - {questions} + <> + {closed_header} + {questions} +
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
+ +
+
+

{props.message}

+
+
+ Return Home +
+
+
; +} -- cgit v1.2.3