diff options
Diffstat (limited to 'src/pages')
-rw-r--r-- | src/pages/FormPage.tsx | 194 | ||||
-rw-r--r-- | src/pages/LandingPage.tsx | 7 |
2 files changed, 188 insertions, 13 deletions
diff --git a/src/pages/FormPage.tsx b/src/pages/FormPage.tsx index 1805897..c49b9fd 100644 --- a/src/pages/FormPage.tsx +++ b/src/pages/FormPage.tsx @@ -1,17 +1,157 @@ /** @jsx jsx */ -import { jsx } from "@emotion/react"; +import { jsx, css } from "@emotion/react"; import { Link } from "react-router-dom"; +import React, { SyntheticEvent, useEffect, useState } from "react"; import { useParams } from "react-router"; + import HeaderBar from "../components/HeaderBar"; -import { useEffect, useState } from "react"; -import { Form, getForm } from "../api/forms"; +import RenderedQuestion from "../components/Question"; import Loading from "../components/Loading"; +import ScrollToTop from "../components/ScrollToTop"; + +import { Form, FormFeatures, getForm } from "../api/forms"; +import colors from "../colors"; +import { unselectable } from "../commonStyles"; + interface PathParams { id: string } +interface NavigationProps { + form_state: boolean // Whether the form is open or not +} + +class Navigation extends React.Component<NavigationProps> { + containerStyles = css` + margin: auto; + width: 50%; + + text-align: center; + font-size: 1.5rem; + white-space: nowrap; + + > div { + display: inline-block; + margin: 2rem auto; + width: 50%; + } + + @media (max-width: 850px) { + width: 100%; + + > div { + display: flex; + justify-content: center; + + margin: 0 auto; + } + } + + .return_button { + text-align: left; + } + + .return_button.closed { + text-align: center; + } + `; + + separatorStyles = css` + height: 0; + display: none; + + @media (max-width: 850px) { + display: block; + } + `; + + returnStyles = css` + padding: 0.5rem 2rem; + border-radius: 8px; + + color: white; + text-decoration: none; + + background-color: ${colors.greyple}; + transition: background-color 300ms; + + :hover { + background-color: ${colors.darkerGreyple}; + } + } + `; + + submitStyles = css` + text-align: right; + + button { + padding: 0.5rem 4rem; + cursor: pointer; + + border: none; + border-radius: 8px; + + color: white; + font: inherit; + + background-color: ${colors.blurple}; + transition: background-color 300ms; + } + + button:hover { + background-color: ${colors.darkerBlurple}; + } + `; + + render(): JSX.Element { + let submit = null; + if (this.props.form_state) { + submit = ( + <div css={this.submitStyles}> + <button form="form" type="submit">Submit</button> + </div> + ); + } + + return ( + <div css={[unselectable, this.containerStyles]}> + <div className={ "return_button" + (this.props.form_state ? "" : " closed") }> + <Link to="/" css={this.returnStyles}>Return Home</Link> + </div> + <br css={this.separatorStyles}/> + { submit } + </div> + ); + } +} + +const formStyles = css` + margin: auto; + width: 50%; + + @media (max-width: 800px) { + /* Make form larger on mobile and tablet screens */ + width: 80%; + } +`; + +const closedHeaderStyles = css` + margin-bottom: 2rem; + padding: 1rem 4rem; + border-radius: 8px; + + text-align: center; + font-size: 1.5rem; + + background-color: ${colors.error}; + + @media (max-width: 500px) { + padding: 1rem 1.5rem; + } +`; + function FormPage(): JSX.Element { const { id } = useParams<PathParams>(); @@ -21,19 +161,53 @@ function FormPage(): JSX.Element { getForm(id).then(form => { setForm(form); }); - }); + }, []); if (!form) { return <Loading/>; } - return <div> - <HeaderBar title={form.name}/> - <div css={{marginLeft: "20px"}}> - <h1>{form.description}</h1> - <Link to="/" css={{color: "white"}}>Return home</Link> + const questions = form.questions.map((question, index) => { + return <RenderedQuestion question={question} public_state={new Map()} key={index + Date.now()}/>; + }); + + function handleSubmit(event: SyntheticEvent) { + questions.forEach(prop => { + const question = prop.props.question; + + // TODO: Parse input from each question, and submit + switch (question.type) { + default: + console.log(question.id, prop.props.public_state); + } + }); + + event.preventDefault(); + } + + const open: boolean = form.features.includes(FormFeatures.Open); + + let closed_header = null; + if (!open) { + closed_header = <div css={closedHeaderStyles}>This form is now closed. You will not be able to submit your response.</div>; + } + + return ( + <div> + <HeaderBar title={form.name} description={form.description}/> + + <div> + <form id="form" onSubmit={handleSubmit} css={[formStyles, unselectable]}> + { closed_header } + { questions } + </form> + <Navigation form_state={open}/> + </div> + + <div css={css`margin-bottom: 10rem`}/> + <ScrollToTop/> </div> - </div>; + ); } export default FormPage; diff --git a/src/pages/LandingPage.tsx b/src/pages/LandingPage.tsx index 124bbcf..af968ad 100644 --- a/src/pages/LandingPage.tsx +++ b/src/pages/LandingPage.tsx @@ -4,10 +4,11 @@ import { useEffect, useState } from "react"; import HeaderBar from "../components/HeaderBar"; import FormListing from "../components/FormListing"; - -import { getForms, Form } from "../api/forms"; import OAuth2Button from "../components/OAuth2Button"; import Loading from "../components/Loading"; +import ScrollToTop from "../components/ScrollToTop"; + +import { getForms, Form } from "../api/forms"; function LandingPage(): JSX.Element { const [forms, setForms] = useState<Form[]>(); @@ -25,8 +26,8 @@ function LandingPage(): JSX.Element { return <div> <HeaderBar/> + <ScrollToTop/> <div> - <div css={css` display: flex; align-items: center; |