diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/App.tsx | 42 | ||||
-rw-r--r-- | src/api/forms.ts | 32 | ||||
-rw-r--r-- | src/api/question.ts | 11 | ||||
-rw-r--r-- | src/components/FormListing.tsx | 6 | ||||
-rw-r--r-- | src/components/HeaderBar/index.tsx | 36 | ||||
-rw-r--r-- | src/globalStyles.ts | 40 | ||||
-rw-r--r-- | src/pages/FormPage.tsx | 43 | ||||
-rw-r--r-- | src/tests/components/FormListing.test.tsx | 8 | ||||
-rw-r--r-- | src/tests/components/HeaderBar.test.tsx | 7 |
9 files changed, 157 insertions, 68 deletions
diff --git a/src/App.tsx b/src/App.tsx index 05d8ded..9dd8b49 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,6 @@ /** @jsx jsx */ /** @global location */ -import { css, jsx, Global } from "@emotion/core"; +import { jsx, Global } from "@emotion/core"; import { BrowserRouter as Router, @@ -11,49 +11,13 @@ import { import { CSSTransition, TransitionGroup } from "react-transition-group"; import LandingPage from "./pages/LandingPage"; -import colors from "./colors"; import FormPage from "./pages/FormPage"; -const globalStyles = css` -@import url('https://fonts.googleapis.com/css2?family=Hind:wght@700&display=swap'); - -@font-face { - font-family: 'Uni Sans'; - src: url(fonts/unisans.otf) format('opentype'); -} - -body { - background-color: ${colors.notQuiteBlack}; - color: white; - font-family: "Hind", "Helvetica", "Arial", sans-serif; - margin: 0; -} - -.fade-enter, -.fade-exit { - position: absolute; - top: 0; - left: 0; - transition: 300ms ease-in-out opacity, 300ms ease-in-out transform; - width: 100%; -} - -.fade-enter, -.fade-exit-active { - opacity: 0; - transform: scale(0.98); -} - -.fade-enter-active { - opacity: 1; - z-index: 1; - transform: scale(1); -} -`; +import globalStyles from "./globalStyles"; const routes = [ { path: "/", Component: LandingPage }, - { path: "/form", Component: FormPage} + { path: "/form/:id", Component: FormPage} ] function App() { diff --git a/src/api/forms.ts b/src/api/forms.ts index 7c2666a..a4a4981 100644 --- a/src/api/forms.ts +++ b/src/api/forms.ts @@ -1,25 +1,53 @@ -export interface Form { +import { Question, QuestionType } from "./question" + +export interface AllFormsForm { title: string, + id: string, description: string, open: boolean } -export function getForms(): Form[] { +export interface Form extends AllFormsForm { + questions: Array<Question> +} + +export function getForms(): AllFormsForm[] { return [ { title: "Ban Appeals", + id: "ban-appeals", description: "Appealing bans from the Discord server", open: true }, { title: "Insights 2020", + id: "insights-2020", description: "Insights about the Python Discord community", open: false }, { title: "Code Jam 2099 Sign Ups", + id: "code-jam-2099-sign-up", description: "Signing up for Python Discord's millionth code jam!", open: false } ] } + +export function getForm(id: string): Promise<Form> { + const data: Form = { + title: "Ban Appeals", + id: "ban-appeals", + description: "Appealing bans from the Discord server", + open: true, + questions: [ + { + name: "How Spanish are you?", + type: QuestionType.Text + } + ] + } + return new Promise((resolve) => { + setTimeout(() => resolve(data), 1500) + }) +} diff --git a/src/api/question.ts b/src/api/question.ts new file mode 100644 index 0000000..e051459 --- /dev/null +++ b/src/api/question.ts @@ -0,0 +1,11 @@ +export enum QuestionType { + Text, + Checkbox, + Radio, + Code +} + +export interface Question { + name: string, + type: QuestionType +} diff --git a/src/components/FormListing.tsx b/src/components/FormListing.tsx index dc761b6..2493608 100644 --- a/src/components/FormListing.tsx +++ b/src/components/FormListing.tsx @@ -9,10 +9,10 @@ import Tag from "./Tag"; import colors from "../colors"; -import { Form } from "../api/forms"; +import { AllFormsForm } from "../api/forms"; interface FormListingProps { - form: Form + form: AllFormsForm } function FormListing({ form }: FormListingProps) { @@ -43,7 +43,7 @@ function FormListing({ form }: FormListingProps) { closedTag = <Tag text="CLOSED" color={colors.error}/> }; - return <Link to="/form" css={listingStyle}> + return <Link to={`/form/${form.id}`} css={listingStyle}> <div> <h3 css={{fontSize: "1.5em", marginBottom: "0"}}>{closedTag}{form.title} <FontAwesomeIcon icon={faArrowRight} css={{fontSize: "0.75em", paddingBottom: "1px"}}/></h3> <p css={{marginTop: "5px"}}>{form.description}</p> diff --git a/src/components/HeaderBar/index.tsx b/src/components/HeaderBar/index.tsx index 6289dfc..c3d46fc 100644 --- a/src/components/HeaderBar/index.tsx +++ b/src/components/HeaderBar/index.tsx @@ -5,6 +5,10 @@ import SVG from "react-inlinesvg"; import header1 from "./header_1.svg"; import header2 from "./header_2.svg"; +interface HeaderBarProps { + title?: string +} + const headerImageStyles = css` z-index: -1; top: 0; @@ -13,22 +17,22 @@ width: 100%; transition: height 1s; @media (max-width: 770px) { - height: 180px; -} - -@media (max-width: 580px) { height: 140px; } `; -function HeaderBar() { +function HeaderBar({ title }: HeaderBarProps) { + if (!title) { + title = "Python Discord Forms"; + }; + return <div> <div> <SVG src={header1} css={headerImageStyles}/> <SVG src={header2} css={headerImageStyles}/> </div> <h1 css={css` - font-size: 4em; + font-size: 4vw; margin: 0; margin-top: 30px; margin-left: 30px; @@ -37,26 +41,22 @@ function HeaderBar() { transition-duration: 1s; font-family: "Uni Sans", "Hind", "Arial", sans-serif; - @media (max-width: 770px) { - margin-bottom: 100px; - font-size: 3em; + @media (max-width: 1000px) { + margin-top: 15px; + font-size: 8vw; } - @media (max-width: 580px) { - font-size: 2em; + @media (max-width: 770px) { + margin-top: 15px; + font-size: 6vw; + margin-bottom: 100px; } - @media (max-width: 450px) { - font-size: 1.70em; text-align: center; margin-left: 0; } - - @media (max-width: 400px) { - font-size: 1.3em; - } `}> - Python Discord Forms + {title} </h1> </div> } diff --git a/src/globalStyles.ts b/src/globalStyles.ts new file mode 100644 index 0000000..431ee36 --- /dev/null +++ b/src/globalStyles.ts @@ -0,0 +1,40 @@ +import { css } from "@emotion/core"; + +import colors from "./colors"; + +export default css` +@import url('https://fonts.googleapis.com/css2?family=Hind:wght@700&display=swap'); + +@font-face { + font-family: 'Uni Sans'; + src: url(/fonts/unisans.otf) format('opentype'); +} + +body { + background-color: ${colors.notQuiteBlack}; + color: white; + font-family: "Hind", "Helvetica", "Arial", sans-serif; + margin: 0; +} + +.fade-enter, +.fade-exit { + position: absolute; + top: 0; + left: 0; + transition: 300ms ease-in-out opacity, 300ms ease-in-out transform; + width: 100%; +} + +.fade-enter, +.fade-exit-active { + opacity: 0; + transform: scale(0.98); +} + +.fade-enter-active { + opacity: 1; + z-index: 1; + transform: scale(1); +} +`; diff --git a/src/pages/FormPage.tsx b/src/pages/FormPage.tsx index aa4cec3..45c093a 100644 --- a/src/pages/FormPage.tsx +++ b/src/pages/FormPage.tsx @@ -2,10 +2,47 @@ import { jsx } from "@emotion/core"; import { Link } from "react-router-dom"; +import { DotLoader } from "react-spinners"; + +import { useParams } from "react-router"; +import HeaderBar from "../components/HeaderBar"; +import { useEffect, useState } from "react"; +import { Form, getForm } from "../api/forms"; + +interface PathParams { + id: string +} + +function Loading() { + return <div> + <HeaderBar title={"Loading..."}/> + <div css={{display: "flex", justifyContent: "center"}}> + <DotLoader color="white"/> + </div> + </div> +} + function FormPage() { - return <div css={{marginLeft: "20px"}}> - <h1>Form page</h1> - <Link to="/" css={{color: "white"}}>Go home</Link> + const { id } = useParams<PathParams>(); + + const [form, setForm] = useState<Form>(); + + useEffect(() => { + getForm(id).then(form => { + setForm(form); + }) + }) + + if (!form) { + return <Loading/> + } + + return <div> + <HeaderBar title={form.title}/> + <div css={{marginLeft: "20px"}}> + <h1>{form.description}</h1> + <Link to="/" css={{color: "white"}}>Return home</Link> + </div> </div> } diff --git a/src/tests/components/FormListing.test.tsx b/src/tests/components/FormListing.test.tsx index 4080f4d..82d1380 100644 --- a/src/tests/components/FormListing.test.tsx +++ b/src/tests/components/FormListing.test.tsx @@ -3,16 +3,18 @@ import { render } from '@testing-library/react'; import FormListing from "../../components/FormListing"; import { BrowserRouter as Router } from 'react-router-dom'; -import { Form } from '../../api/forms'; +import { AllFormsForm } from '../../api/forms'; -const openFormListing: Form = { +const openFormListing: AllFormsForm = { title: "Example form listing", + id: "example-form-listing", description: "My form listing", open: true } -const closedFormListing: Form = { +const closedFormListing: AllFormsForm = { title: "Example form listing", + id: "example-form-listing", description: "My form listing", open: false } diff --git a/src/tests/components/HeaderBar.test.tsx b/src/tests/components/HeaderBar.test.tsx index 3567d7e..2e1f868 100644 --- a/src/tests/components/HeaderBar.test.tsx +++ b/src/tests/components/HeaderBar.test.tsx @@ -7,3 +7,10 @@ test('renders header bar with title', () => { const formListing = getByText(/Python Discord Forms/i); expect(formListing).toBeInTheDocument(); }); + +test('renders header bar with custom title', () => { + const { getByText } = render(<HeaderBar title="Testing title"/>); + const formListing = getByText(/Testing title/i); + expect(formListing).toBeInTheDocument(); +}); + |