/** @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"; import Loading from "../../components/Loading"; import ScrollToTop from "../../components/ScrollToTop"; import {FormFeatures, FormWithAncillaryData, getForm} from "../../api/forms"; import {OAuthScopes} from "../../api/auth"; import {unselectable} from "../../commonStyles"; import handleSubmit, {FormState} from "./submit"; import Navigation from "./Navigation"; import Success from "./SuccessPage"; import ErrorPage from "./ErrorPage"; import NotFound from "../NotFound"; import PrecheckBox from "../../components/PrecheckBox"; export type RefMapType = Map>; const formStyles = css` margin: auto; width: 50%; @media (max-width: 800px) { /* Make form larger on mobile and tablet screens */ width: 80%; } `; 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(() => { // ID can't be null due to the routing to get here 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) { // This should be an impossible state throw Error("Form was not set despite loading state being set to found."); } const refMap: RefMapType = new Map(); // Authentication Logic const require_auth: boolean = form.features.includes(FormFeatures.RequiresLogin); const scopes: OAuthScopes[] = []; if (require_auth) { scopes.push(OAuthScopes.Identify); if (form.features.includes(FormFeatures.CollectEmail)) { scopes.push(OAuthScopes.Email); } } const prechecks: JSX.Element[] = []; for (const precheck of form.submission_precheck.problems) { prechecks.push(); } const questions: RenderedQuestion[] = form.questions.map((question, index) => { const questionRef = createRef(); refMap.set(question.id, questionRef); return ()} focus_ref={createRef()} // eslint-disable-line @typescript-eslint/no-explicit-any key={index + Date.now()} selfRef={questionRef} ref={questionRef} /> as unknown as RenderedQuestion; // Annotations for JSX elements resolve to a generic ReactElement }); switch (state) { case FormState.SENT: return ; case FormState.SENDING: return (
); case FormState.UNKNOWN_ERROR: return ; } const handler = (event: SyntheticEvent) => handleSubmit(event, form.id, questions, refMap, setState, OAuthRef, scopes); return (
<> {...prechecks} {questions}
); } export default FormPage;