diff options
| author | 2020-10-05 13:13:51 +0100 | |
|---|---|---|
| committer | 2020-10-05 13:13:51 +0100 | |
| commit | 91ef1e8d905e1ac68f6a3968f379d0675dfe6dcf (patch) | |
| tree | 617e685d475acd15a7a6423d3a9b7826ee674f00 | |
| parent | Merge pull request #14 from python-discord/api/add-dummy-forms (diff) | |
| parent | Update header test to include custom titles (diff) | |
Merge pull request #15 from python-discord/forms/add-form-page
Add specific form page
| -rw-r--r-- | package.json | 1 | ||||
| -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 | ||||
| -rw-r--r-- | yarn.lock | 9 | 
11 files changed, 166 insertions, 69 deletions
diff --git a/package.json b/package.json index 98814fe..ff7968a 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@      "react-inlinesvg": "^2.1.0",      "react-router-dom": "^5.2.0",      "react-scripts": "3.4.3", +    "react-spinners": "^0.9.0",      "react-transition-group": "^4.4.1",      "typescript": "~3.7.2"    }, 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(); +}); + @@ -1176,7 +1176,7 @@      "@emotion/utils" "0.11.3"      "@emotion/weak-memoize" "0.2.5" -"@emotion/core@^10.0.35": +"@emotion/core@^10.0.15", "@emotion/core@^10.0.35":    version "10.0.35"    resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.35.tgz#513fcf2e22cd4dfe9d3894ed138c9d7a859af9b3"    integrity sha512-sH++vJCdk025fBlRZSAhkRlSUoqSqgCzYf5fMOmqqi3bM6how+sQpg3hkgJonj8GxXM4WbD7dRO+4tegDB9fUw== @@ -9045,6 +9045,13 @@ [email protected]:    optionalDependencies:      fsevents "2.1.2" +react-spinners@^0.9.0: +  version "0.9.0" +  resolved "https://registry.yarnpkg.com/react-spinners/-/react-spinners-0.9.0.tgz#b22c38acbfce580cd6f1b04a4649e812370b1fb8" +  integrity sha512-+x6eD8tn/aYLdxZjNW7fSR1uoAXLb9qq6TFYZR1dFweJvckcf/HfP8Pa/cy5HOvB/cvI4JgrYXTjh2Me3S6Now== +  dependencies: +    "@emotion/core" "^10.0.15" +  react-transition-group@^4.4.1:    version "4.4.1"    resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9"  |