From c8ceb861a8776efb3ae1b0f93109b02d528dc0d7 Mon Sep 17 00:00:00 2001 From: mikael-r Date: Tue, 17 May 2022 21:27:31 -0300 Subject: [PATCH] refactor: folders structure and create template --- .storybook/main.js | 2 +- .../{Arrows.tsx => Arrows/index.tsx} | 14 +- .../components/Arrows/stories.tsx | 2 +- src/components/Arrows/styles.ts | 7 + src/components/Button/index.tsx | 15 +++ .../components/Button/stories.tsx | 2 +- .../{Button.tsx => Button/styles.ts} | 23 +--- src/components/Loading/Loading.tsx | 20 --- src/components/Loading/index.tsx | 32 ++++- .../components/Loading/stories.tsx | 2 +- src/components/{Logo.tsx => Logo/index.tsx} | 4 +- .../components/Logo/stories.tsx | 2 +- src/components/Progress/index.tsx | 9 ++ .../components/Progress/stories.tsx | 2 +- .../{Progress.tsx => Progress/styles.ts} | 11 +- src/components/Question/index.tsx | 38 ++++++ src/components/Question/styles.ts | 8 ++ .../{Ranger.tsx => Ranger/index.tsx} | 116 +++------------- .../components/Ranger/stories.tsx | 2 +- src/components/Ranger/styles.ts | 87 ++++++++++++ src/components/Title.tsx | 47 ------- src/components/Title/index.tsx | 13 ++ .../components/Title/stories.tsx | 2 +- src/components/Title/styles.ts | 40 ++++++ .../{WaterMark.tsx => WaterMark/index.tsx} | 22 +-- .../components/WaterMark/stories.tsx | 2 +- src/components/WaterMark/styles.ts | 17 +++ src/contexts/QuestionsContext.tsx | 58 +++----- src/pages/_app.tsx | 4 +- src/pages/_document.tsx | 94 +++++++------ src/pages/index.tsx | 2 +- src/pages/questions/index.tsx | 126 +----------------- src/pages/success/index.tsx | 2 +- .../Default/index.tsx} | 26 +--- src/templates/Default/styles.ts | 19 +++ src/templates/Questions/index.tsx | 59 ++++++++ src/templates/Questions/styles.ts | 38 ++++++ src/types/contexts.d.ts | 24 ++++ src/utils/index.ts | 11 +- 39 files changed, 533 insertions(+), 471 deletions(-) rename src/components/{Arrows.tsx => Arrows/index.tsx} (80%) rename stories/Arrows.tsx => src/components/Arrows/stories.tsx (79%) create mode 100644 src/components/Arrows/styles.ts create mode 100644 src/components/Button/index.tsx rename stories/Button.tsx => src/components/Button/stories.tsx (85%) rename src/components/{Button.tsx => Button/styles.ts} (69%) delete mode 100644 src/components/Loading/Loading.tsx rename stories/Loading.tsx => src/components/Loading/stories.tsx (80%) rename src/components/{Logo.tsx => Logo/index.tsx} (59%) rename stories/Logo.tsx => src/components/Logo/stories.tsx (81%) create mode 100644 src/components/Progress/index.tsx rename stories/Progress.tsx => src/components/Progress/stories.tsx (80%) rename src/components/{Progress.tsx => Progress/styles.ts} (65%) create mode 100644 src/components/Question/index.tsx create mode 100644 src/components/Question/styles.ts rename src/components/{Ranger.tsx => Ranger/index.tsx} (52%) rename stories/Ranger.tsx => src/components/Ranger/stories.tsx (89%) create mode 100644 src/components/Ranger/styles.ts delete mode 100644 src/components/Title.tsx create mode 100644 src/components/Title/index.tsx rename stories/Title.tsx => src/components/Title/stories.tsx (90%) create mode 100644 src/components/Title/styles.ts rename src/components/{WaterMark.tsx => WaterMark/index.tsx} (52%) rename stories/WaterMark.tsx => src/components/WaterMark/stories.tsx (79%) create mode 100644 src/components/WaterMark/styles.ts rename src/{template/Default.tsx => templates/Default/index.tsx} (57%) create mode 100644 src/templates/Default/styles.ts create mode 100644 src/templates/Questions/index.tsx create mode 100644 src/templates/Questions/styles.ts create mode 100644 src/types/contexts.d.ts diff --git a/.storybook/main.js b/.storybook/main.js index 6ac5101..887417d 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -1,7 +1,7 @@ const { resolve } = require('path') module.exports = { - stories: ['../stories/**/*.tsx'], + stories: ['../src/**/stories.tsx'], addons: [ '@storybook/addon-links', '@storybook/addon-essentials', diff --git a/src/components/Arrows.tsx b/src/components/Arrows/index.tsx similarity index 80% rename from src/components/Arrows.tsx rename to src/components/Arrows/index.tsx index 08835db..f81d57d 100644 --- a/src/components/Arrows.tsx +++ b/src/components/Arrows/index.tsx @@ -1,7 +1,7 @@ -import styled from 'styled-components' - import Button from 'components/Button' +import * as S from './styles' + export interface Props { disableUp?: boolean onClickUp?: () => void @@ -11,7 +11,7 @@ export interface Props { const Arrows = ({ disableUp, onClickUp, disableDown, onClickDown }: Props) => { return ( - + - + ) } export default Arrows - -const Container = styled.div` - display: flex; - flex-direction: row; - gap: ${({ theme }) => theme.spacings.xsm}; -` diff --git a/stories/Arrows.tsx b/src/components/Arrows/stories.tsx similarity index 79% rename from stories/Arrows.tsx rename to src/components/Arrows/stories.tsx index 4a7231c..4766c0f 100644 --- a/stories/Arrows.tsx +++ b/src/components/Arrows/stories.tsx @@ -1,5 +1,5 @@ import { Story, Meta } from '@storybook/react' -import Arrows, { Props } from 'components/Arrows' +import Arrows, { Props } from '.' export default { title: 'Arrows', diff --git a/src/components/Arrows/styles.ts b/src/components/Arrows/styles.ts new file mode 100644 index 0000000..e6f7b46 --- /dev/null +++ b/src/components/Arrows/styles.ts @@ -0,0 +1,7 @@ +import styled from 'styled-components' + +export const Wrapper = styled.div` + display: flex; + flex-direction: row; + gap: ${({ theme }) => theme.spacings.xsm}; +` diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx new file mode 100644 index 0000000..4b3ba3c --- /dev/null +++ b/src/components/Button/index.tsx @@ -0,0 +1,15 @@ +import * as S from './styles' + +import type { ButtonHTMLAttributes } from 'react' + +export interface Props extends ButtonHTMLAttributes { + skin?: 'outlined' | 'default' | 'transparent' + rounded?: boolean + size?: 'small' | 'medium' +} + +const Button = (props: Props) => { + return +} + +export default Button diff --git a/stories/Button.tsx b/src/components/Button/stories.tsx similarity index 85% rename from stories/Button.tsx rename to src/components/Button/stories.tsx index 4b9b401..288857c 100644 --- a/stories/Button.tsx +++ b/src/components/Button/stories.tsx @@ -1,5 +1,5 @@ import { Story, Meta } from '@storybook/react' -import Button, { Props } from 'components/Button' +import Button, { Props } from '.' export default { title: 'Button', diff --git a/src/components/Button.tsx b/src/components/Button/styles.ts similarity index 69% rename from src/components/Button.tsx rename to src/components/Button/styles.ts index 3fc57c2..493daaa 100644 --- a/src/components/Button.tsx +++ b/src/components/Button/styles.ts @@ -1,19 +1,8 @@ -import React from 'react' -import styled, { css } from 'styled-components' - -export interface Props extends React.ButtonHTMLAttributes { - skin?: 'outlined' | 'default' | 'transparent' - rounded?: boolean - size?: 'small' | 'medium' -} +import type { Props } from '.' -const Button = (props: Props) => { - return -} - -export default Button +import styled, { css } from 'styled-components' -const Container = styled.button` +export const Button = styled.button` ${({ theme, rounded, skin, size }) => css` font-family: 'Open Sans'; font-style: normal; @@ -38,11 +27,11 @@ const Container = styled.button` ? `border: none; background: ${theme.colors.gray200};color: white;` : ''} - ${skin === 'transparent' && + ${skin === 'transparent' && `border: none;background: transparent;filter: none;box-shadow: none !important;padding: 0 !important;`} - ${size === 'small' || !size ? 'padding: 7px 20px;' : ''} - ${size === 'medium' || !size ? 'padding: 15px 80px;' : ''} + ${size === 'small' || !size ? 'padding: 7px 20px;' : ''} + ${size === 'medium' || !size ? 'padding: 15px 80px;' : ''} filter: drop-shadow(0 1px 2px rgb(0 0 0 / 0.1)) drop-shadow(0 1px 1px rgb(0 0 0 / 0.06)); diff --git a/src/components/Loading/Loading.tsx b/src/components/Loading/Loading.tsx deleted file mode 100644 index 9179306..0000000 --- a/src/components/Loading/Loading.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import Title from 'components/Title' - -import * as S from './styles' - -const Loading = () => { - const phases = [ - 'The age is only a number!', - 'Pls hire me :)', - 'Nice code buddy :)' - ] - const phase = phases[Math.floor(Math.random() * phases.length)] - - return ( - - {phase} - - ) -} - -export default Loading diff --git a/src/components/Loading/index.tsx b/src/components/Loading/index.tsx index e51f114..f4a3651 100644 --- a/src/components/Loading/index.tsx +++ b/src/components/Loading/index.tsx @@ -1,5 +1,29 @@ -import dynamic from 'next/dynamic' +import { useState, useEffect } from 'react' -export default dynamic(() => import('./Loading'), { - ssr: false -}) +import Title from 'components/Title' + +import { getRandomValueFromArray } from 'utils' + +import * as S from './styles' + +const Loading = () => { + const [phase, setPhase] = useState('') + + const phases = [ + 'The age is only a number!', + 'Pls hire me :)', + 'Nice code buddy :)' + ] + + useEffect(() => { + setPhase(getRandomValueFromArray(phases)) + }, []) + + return ( + + {phase} + + ) +} + +export default Loading diff --git a/stories/Loading.tsx b/src/components/Loading/stories.tsx similarity index 80% rename from stories/Loading.tsx rename to src/components/Loading/stories.tsx index 61ee0cc..3be500d 100644 --- a/stories/Loading.tsx +++ b/src/components/Loading/stories.tsx @@ -1,5 +1,5 @@ import { Story, Meta } from '@storybook/react' -import Loading from 'components/Loading' +import Loading from '.' export default { title: 'Loading', diff --git a/src/components/Logo.tsx b/src/components/Logo/index.tsx similarity index 59% rename from src/components/Logo.tsx rename to src/components/Logo/index.tsx index 2ce13eb..fea33b9 100644 --- a/src/components/Logo.tsx +++ b/src/components/Logo/index.tsx @@ -1,6 +1,6 @@ -import React from 'react' +import type { ImgHTMLAttributes } from 'react' -type Props = Partial> +type Props = Partial> const Logo = (props: Props) => { return ( diff --git a/stories/Logo.tsx b/src/components/Logo/stories.tsx similarity index 81% rename from stories/Logo.tsx rename to src/components/Logo/stories.tsx index a71f162..195d49b 100644 --- a/stories/Logo.tsx +++ b/src/components/Logo/stories.tsx @@ -1,5 +1,5 @@ import { Story, Meta } from '@storybook/react' -import Logo from 'components/Logo' +import Logo from '.' export default { title: 'Logo', diff --git a/src/components/Progress/index.tsx b/src/components/Progress/index.tsx new file mode 100644 index 0000000..1a1ba63 --- /dev/null +++ b/src/components/Progress/index.tsx @@ -0,0 +1,9 @@ +import * as S from './styles' + +import type { ProgressHTMLAttributes } from 'react' + +export type Props = ProgressHTMLAttributes + +const Progress = (props: Props) => + +export default Progress diff --git a/stories/Progress.tsx b/src/components/Progress/stories.tsx similarity index 80% rename from stories/Progress.tsx rename to src/components/Progress/stories.tsx index 2c36133..caac846 100644 --- a/stories/Progress.tsx +++ b/src/components/Progress/stories.tsx @@ -1,5 +1,5 @@ import { Story, Meta } from '@storybook/react' -import Progress, { Props } from 'components/Progress' +import Progress, { Props } from '.' export default { title: 'Progress', diff --git a/src/components/Progress.tsx b/src/components/Progress/styles.ts similarity index 65% rename from src/components/Progress.tsx rename to src/components/Progress/styles.ts index 20e6035..557d575 100644 --- a/src/components/Progress.tsx +++ b/src/components/Progress/styles.ts @@ -1,15 +1,6 @@ -import React from 'react' import styled from 'styled-components' -export type Props = React.ProgressHTMLAttributes - -const Progress = (props: Props) => { - return -} - -export default Progress - -const Container = styled.progress` +export const Progress = styled.progress` position: fixed; top: 0; left: 0; diff --git a/src/components/Question/index.tsx b/src/components/Question/index.tsx new file mode 100644 index 0000000..76d2afc --- /dev/null +++ b/src/components/Question/index.tsx @@ -0,0 +1,38 @@ +import Title from 'components/Title' +import Ranger from 'components/Ranger' + +import { useQuestions } from 'contexts/QuestionsContext' + +import * as S from './styles' + +const Question = () => { + const { + currentQuestion, + currentQuestionIndex, + questionsAnswers, + answerQuestion + } = useQuestions() + + return ( + + + {currentQuestionIndex + 1}. {currentQuestion?.category.name} + + + + {currentQuestion?.title} + + + id === currentQuestion?.id)?.answer + } + optionsSize={3} + side='both' + onSelect={(answer) => answerQuestion(currentQuestion?.id || '', answer)} + /> + + ) +} + +export default Question diff --git a/src/components/Question/styles.ts b/src/components/Question/styles.ts new file mode 100644 index 0000000..40845bb --- /dev/null +++ b/src/components/Question/styles.ts @@ -0,0 +1,8 @@ +import styled from 'styled-components' + +export const Wrapper = styled.div` + height: 100%; + + display: flex; + flex-direction: column; +` diff --git a/src/components/Ranger.tsx b/src/components/Ranger/index.tsx similarity index 52% rename from src/components/Ranger.tsx rename to src/components/Ranger/index.tsx index b74527f..3b2f23e 100644 --- a/src/components/Ranger.tsx +++ b/src/components/Ranger/index.tsx @@ -1,4 +1,4 @@ -import styled from 'styled-components' +import * as S from './styles' import { generateArray } from 'utils/index' @@ -47,17 +47,17 @@ const Ranger = ({ optionsSize, side = 'both', selected, onSelect }: Props) => { } return ( - - + + {options.map((option) => { const bgAplha = increaser * option const bg = `rgba(70, 70, 70, ${bgAplha < 0 ? bgAplha * -1 : bgAplha})` const title = `option: ${option} | increase: ${increaser} | background: ${bg}` return ( - handleSelect(option)} @@ -65,117 +65,31 @@ const Ranger = ({ optionsSize, side = 'both', selected, onSelect }: Props) => { /> ) })} - + {optionsSize >= 3 ? ( - {side === 'both' && ( - + Much worse than now - + )} - + Same as now - - + + Much better than now - - + + ) : null} - + ) } export default Ranger - -const Container = styled.div` - width: max-content; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 10px; - margin: auto; -` - -const Questions = styled.div` - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - gap: 6px; -` - -const Texts = styled.div` - width: 100%; - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; -` - -const Text = styled.div` - display: flex; - flex-direction: column; - justify-content: space-between; - align-items: flex-start; - - span { - font-size: 13px; - line-height: 16px; - letter-spacing: -0.5px; - color: ${({ theme }) => theme.colors.gray300}; - } - - span:first-child { - font-style: normal; - font-weight: 700; - } - - span:last-child { - font-style: thin; - font-weight: 300; - } -` - -interface CircleProps { - background: string - selected: boolean -} - -const Circle = styled.button` - width: 36px; - height: 36px; - - @media (min-width: 1024px) { - width: 42px; - height: 42px; - } - - ${({ background }) => `background: ${background};`} - - ${({ selected, theme }) => - selected - ? `border: 2px solid ${theme.colors.green300};` - : `border: 1px solid ${theme.colors.gray200};`} - - border-radius: 100%; - outline: none; - cursor: pointer; - - filter: drop-shadow(0 1px 2px rgb(0 0 0 / 0.1)) - drop-shadow(0 1px 1px rgb(0 0 0 / 0.07)); - box-shadow: 0px 7px 14px rgba(0, 0, 0, 0.1); - transition: all 0.3s ease 0s; - - &:hover { - box-shadow: 0px 7px 14px ${({ theme }) => theme.colors.gray200}; - transform: translateY(-5px); - } -` diff --git a/stories/Ranger.tsx b/src/components/Ranger/stories.tsx similarity index 89% rename from stories/Ranger.tsx rename to src/components/Ranger/stories.tsx index 750875f..0adea03 100644 --- a/stories/Ranger.tsx +++ b/src/components/Ranger/stories.tsx @@ -1,5 +1,5 @@ import { Story, Meta } from '@storybook/react' -import Ranger, { Props } from 'components/Ranger' +import Ranger, { Props } from '.' export default { title: 'Ranger', diff --git a/src/components/Ranger/styles.ts b/src/components/Ranger/styles.ts new file mode 100644 index 0000000..d572a92 --- /dev/null +++ b/src/components/Ranger/styles.ts @@ -0,0 +1,87 @@ +import styled from 'styled-components' + +export const Wrapper = styled.div` + width: max-content; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 10px; + margin: auto; +` + +export const Questions = styled.div` + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 6px; +` + +export const Texts = styled.div` + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; +` + +export const Text = styled.div` + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-start; + + span { + font-size: 13px; + line-height: 16px; + letter-spacing: -0.5px; + color: ${({ theme }) => theme.colors.gray300}; + } + + span:first-child { + font-style: normal; + font-weight: 700; + } + + span:last-child { + font-style: thin; + font-weight: 300; + } +` + +interface CircleProps { + background: string + selected: boolean +} + +export const Circle = styled.button` + width: 36px; + height: 36px; + + @media (min-width: 1024px) { + width: 42px; + height: 42px; + } + + ${({ background }) => `background: ${background};`} + + ${({ selected, theme }) => + selected + ? `border: 2px solid ${theme.colors.green300};` + : `border: 1px solid ${theme.colors.gray200};`} + +border-radius: 100%; + outline: none; + cursor: pointer; + + filter: drop-shadow(0 1px 2px rgb(0 0 0 / 0.1)) + drop-shadow(0 1px 1px rgb(0 0 0 / 0.07)); + box-shadow: 0px 7px 14px rgba(0, 0, 0, 0.1); + transition: all 0.3s ease 0s; + + &:hover { + box-shadow: 0px 7px 14px ${({ theme }) => theme.colors.gray200}; + transform: translateY(-5px); + } +` diff --git a/src/components/Title.tsx b/src/components/Title.tsx deleted file mode 100644 index 812ed1b..0000000 --- a/src/components/Title.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from 'react' - -import styled from 'styled-components' - -export interface Props extends React.HTMLAttributes { - tag: 'h1' | 'h2' | 'h3' -} - -const Title = ({ tag, children, ...props }: Props) => { - const component = React.createElement(tag, props, children) - - return {component} -} - -export default Title - -const Container = styled.div` - font-style: normal; - line-height: 41px; - - color: ${({ theme }) => theme.colors.gray400}; - - h1 { - text-align: center; - - font-size: ${({ theme }) => theme.font.sizes['4xl']}; - font-weight: 300; - } - - h2 { - font-weight: 600; - font-size: ${({ theme }) => theme.font.sizes['xl']}; - line-height: 20px; - - text-transform: uppercase; - - color: ${({ theme }) => theme.colors.green600}; - } - - h3 { - font-weight: 300; - font-size: ${({ theme }) => theme.font.sizes['2xl']}; - line-height: 30px; - - color: ${({ theme }) => theme.colors.gray500}; - } -` diff --git a/src/components/Title/index.tsx b/src/components/Title/index.tsx new file mode 100644 index 0000000..e03790c --- /dev/null +++ b/src/components/Title/index.tsx @@ -0,0 +1,13 @@ +import { HTMLAttributes } from 'react' + +import * as S from './styles' + +export interface Props extends HTMLAttributes { + tag: 'h1' | 'h2' | 'h3' +} + +const Title = (props: Props) => { + return +} + +export default Title diff --git a/stories/Title.tsx b/src/components/Title/stories.tsx similarity index 90% rename from stories/Title.tsx rename to src/components/Title/stories.tsx index 5e8d4f0..43f6dab 100644 --- a/stories/Title.tsx +++ b/src/components/Title/stories.tsx @@ -1,5 +1,5 @@ import { Story, Meta } from '@storybook/react' -import Title, { Props } from 'components/Title' +import Title, { Props } from '.' export default { title: 'Title', diff --git a/src/components/Title/styles.ts b/src/components/Title/styles.ts new file mode 100644 index 0000000..e2da71f --- /dev/null +++ b/src/components/Title/styles.ts @@ -0,0 +1,40 @@ +import styled, { css } from 'styled-components' + +import type { Props } from '.' + +export const Title = styled.h1` + ${({ theme, tag }) => css` + font-style: normal; + line-height: 41px; + + color: ${theme.colors.gray400}; + + ${tag === 'h1' && + ` + text-align: center; + + font-size: ${theme.font.sizes['4xl']}; + font-weight: 300; + `} + + ${tag === 'h2' && + ` + font-weight: 600; + font-size: ${theme.font.sizes['xl']}; + line-height: 20px; + + text-transform: uppercase; + + color: ${theme.colors.green600}; + `} + + ${tag === 'h3' && + ` + font-weight: 300; + font-size: ${theme.font.sizes['2xl']}; + line-height: 30px; + + color: ${theme.colors.gray500}; + `} + `} +` diff --git a/src/components/WaterMark.tsx b/src/components/WaterMark/index.tsx similarity index 52% rename from src/components/WaterMark.tsx rename to src/components/WaterMark/index.tsx index 308ca6d..aa7087b 100644 --- a/src/components/WaterMark.tsx +++ b/src/components/WaterMark/index.tsx @@ -1,8 +1,8 @@ -import styled from 'styled-components' +import * as S from './styles' const WaterMark = () => { return ( - + Made with{' '} Heart by{' '} @@ -13,24 +13,8 @@ const WaterMark = () => { > Mikael-R - + ) } export default WaterMark - -const Container = styled.div` - position: absolute; - left: 20px; - bottom: 12px; - - color: ${({ theme }) => theme.colors.green600}; - - font-size: 12px; - - font-weight: 500; - - img { - margin: 0 4px -5px 1px; - } -` diff --git a/stories/WaterMark.tsx b/src/components/WaterMark/stories.tsx similarity index 79% rename from stories/WaterMark.tsx rename to src/components/WaterMark/stories.tsx index 7167971..927b166 100644 --- a/stories/WaterMark.tsx +++ b/src/components/WaterMark/stories.tsx @@ -1,5 +1,5 @@ import { Story, Meta } from '@storybook/react' -import WaterMark from 'components/WaterMark' +import WaterMark from '.' export default { title: 'WaterMark', diff --git a/src/components/WaterMark/styles.ts b/src/components/WaterMark/styles.ts new file mode 100644 index 0000000..ed2502f --- /dev/null +++ b/src/components/WaterMark/styles.ts @@ -0,0 +1,17 @@ +import styled from 'styled-components' + +export const Wrapper = styled.div` + position: absolute; + left: 20px; + bottom: 12px; + + color: ${({ theme }) => theme.colors.green600}; + + font-size: 12px; + + font-weight: 500; + + img { + margin: 0 4px -5px 1px; + } +` diff --git a/src/contexts/QuestionsContext.tsx b/src/contexts/QuestionsContext.tsx index 2b75d6b..55f8e7a 100644 --- a/src/contexts/QuestionsContext.tsx +++ b/src/contexts/QuestionsContext.tsx @@ -4,30 +4,17 @@ import Router from 'next/router' import QuestionsRepository from 'repositories/questionsRepository' -import type { ReactNode } from 'react' -import type { Question } from 'types/entities' - -type CurrentQuestion = Question | null -type Questions = Question[] -type QuestionsAnswers = { id: string; answer: number }[] -type AnswerQuestion = (questionId: string, answer: number) => void -type GoTo = (to: 'previous' | 'next') => void - -interface AuthContextData { - currentQuestion: CurrentQuestion - currentQuestionIndex: number - disablePrevious: boolean - disableNext: boolean - goTo: GoTo - questions: Questions - questionsAnswers: QuestionsAnswers - loading: boolean - answerQuestion: AnswerQuestion -} - -interface AuthProviderProps { - children: ReactNode -} +import { isNumber } from 'utils' + +import type { + AnswerQuestion, + AuthContextData, + AuthProviderProps, + CurrentQuestion, + GoTo, + Questions, + QuestionsAnswers +} from 'types/contexts' const questionsRepository = new QuestionsRepository() @@ -53,18 +40,17 @@ export const QuestionsProvider = ({ children }: AuthProviderProps) => { ({ id }) => id === currentQuestion?.id ) const previousQuestion = questions[currentQuestionIndex - 1] + const nextQuestion = questions[currentQuestionIndex + 1] - const disablePrevious = isNaN( - Number( - questionsAnswers.find(({ id }) => id === previousQuestion?.id)?.answer - ) - ) + const findQuestionById = (questionId: string) => + questionsAnswers.find(({ id }) => id === questionId) - const disableNext = isNaN( - Number( - questionsAnswers.find(({ id }) => id === currentQuestion?.id)?.answer - ) - ) + const disablePrevious = + !previousQuestion || + !isNumber(findQuestionById(previousQuestion.id)?.answer) + + const disableNext = + !currentQuestion || !isNumber(findQuestionById(currentQuestion.id)?.answer) const send = async () => { await Router.push('success') @@ -78,10 +64,10 @@ export const QuestionsProvider = ({ children }: AuthProviderProps) => { return send() case to === 'previous' && !disablePrevious: - return setCurrentQuestion(questions[currentQuestionIndex - 1]) + return setCurrentQuestion(previousQuestion) case to === 'next' && !disableNext: - return setCurrentQuestion(questions[currentQuestionIndex + 1]) + return setCurrentQuestion(nextQuestion) } } diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 58ae492..4910a11 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -9,7 +9,7 @@ import theme from 'styles/theme' import type { AppProps } from 'next/app' -export default function App({ Component, pageProps }: AppProps) { +const App = ({ Component, pageProps }: AppProps) => { return ( <> @@ -22,3 +22,5 @@ export default function App({ Component, pageProps }: AppProps) { ) } + +export default App diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx index 84cf172..6307a06 100644 --- a/src/pages/_document.tsx +++ b/src/pages/_document.tsx @@ -3,61 +3,57 @@ import Document, { Head, Main, NextScript, - DocumentContext, - DocumentInitialProps + DocumentContext } from 'next/document' import { ServerStyleSheet } from 'styled-components' -export default class MyDocument extends Document { - static async getInitialProps( - ctx: DocumentContext - ): Promise { - const sheet = new ServerStyleSheet() - const originalRenderPage = ctx.renderPage +const _document = () => { + return ( + + + + + + + +
+ + + + ) +} - try { - ctx.renderPage = () => - originalRenderPage({ - enhanceApp: (App) => (props) => - sheet.collectStyles() - }) +_document.getInitialProps = async (ctx: DocumentContext) => { + const sheet = new ServerStyleSheet() + const originalRenderPage = ctx.renderPage - const initialProps = await Document.getInitialProps(ctx) + try { + ctx.renderPage = () => + originalRenderPage({ + enhanceApp: (App) => (props) => sheet.collectStyles() + }) - return { - ...initialProps, - styles: [ - <> - {initialProps.styles} - {sheet.getStyleElement()} - - ] - } - } finally { - sheet.seal() - } - } + const initialProps = await Document.getInitialProps(ctx) - render() { - return ( - - - - - - - -
- - - - ) + return { + ...initialProps, + styles: [ + <> + {initialProps.styles} + {sheet.getStyleElement()} + + ] + } + } finally { + sheet.seal() } } + +export default _document diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 8f33fde..08c5afa 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,6 +1,6 @@ import Router from 'next/router' -import DefaultTemplate from 'template/Default' +import DefaultTemplate from 'templates/Default' import type { NextPage } from 'next' diff --git a/src/pages/questions/index.tsx b/src/pages/questions/index.tsx index f23d2f6..38d4c18 100644 --- a/src/pages/questions/index.tsx +++ b/src/pages/questions/index.tsx @@ -1,126 +1,12 @@ -import styled from 'styled-components' - -import Loading from 'components/Loading' -import Title from 'components/Title' -import Progress from 'components/Progress' -import Ranger from 'components/Ranger' -import Button from 'components/Button' -import Arrows from 'components/Arrows' - -import { useQuestions } from 'contexts/QuestionsContext' - -import type { NextPage } from 'next' - -const QuestionsPage: NextPage = () => { - const { - questions, - currentQuestion, - currentQuestionIndex, - disablePrevious, - disableNext, - goTo, - loading, - questionsAnswers, - answerQuestion - } = useQuestions() +import QuestionsTemplate from 'templates/Questions' +import Question from 'components/Question' +const QuestionsPage = () => { return ( - - - - {loading ? ( - - ) : ( - <> - - - - {currentQuestionIndex + 1}. {currentQuestion?.category.name} - - - - {currentQuestion?.title} - - - id === currentQuestion?.id) - ?.answer - } - optionsSize={3} - side='both' - onSelect={(answer) => - answerQuestion(currentQuestion?.id || '', answer) - } - /> - - - - - goTo('previous')} - onClickDown={() => goTo('next')} - /> - - - - - )} - + + + ) } export default QuestionsPage - -const Container = styled.main` - height: 90vh; - position: relative; -` - -const Question = styled.div` - height: 100%; - - display: flex; - flex-direction: column; -` - -interface WrapperProps { - visible?: boolean -} - -const Wrapper = styled.div` - width: 100vw; - height: 100%; - - display: flex; - flex-direction: column; - justify-content: space-between; - - padding: 36px; - - @media (min-width: ${({ theme }) => theme.breakpoints.md}) { - padding: 56px 36px; - } -` - -const Buttons = styled.div` - width: 100%; - - display: flex; - justify-content: space-between; - - padding: 0 24px; - - @media (min-width: ${({ theme }) => theme.breakpoints.md}) { - padding: 0 36px; - } -` diff --git a/src/pages/success/index.tsx b/src/pages/success/index.tsx index b5d1ba5..8c31ec8 100644 --- a/src/pages/success/index.tsx +++ b/src/pages/success/index.tsx @@ -1,6 +1,6 @@ import Router from 'next/router' -import DefaultTemplate from 'template/Default' +import DefaultTemplate from 'templates/Default' import type { NextPage } from 'next' diff --git a/src/template/Default.tsx b/src/templates/Default/index.tsx similarity index 57% rename from src/template/Default.tsx rename to src/templates/Default/index.tsx index 7eaf19d..5bd2de7 100644 --- a/src/template/Default.tsx +++ b/src/templates/Default/index.tsx @@ -1,9 +1,9 @@ -import styled from 'styled-components' - import Logo from 'components/Logo' import Title from 'components/Title' import Button from 'components/Button' +import * as S from './styles' + import type { ReactNode } from 'react' interface Props { @@ -14,7 +14,7 @@ interface Props { const DefaultTemplate = ({ title, buttonText, buttonOnClick }: Props) => { return ( - + {title && {title}} @@ -24,26 +24,8 @@ const DefaultTemplate = ({ title, buttonText, buttonOnClick }: Props) => { {buttonText} )} - + ) } export default DefaultTemplate - -const Container = styled.main` - width: 100vw; - height: 100vh; - - display: flex; - flex-direction: column; - justify-content: space-between; - align-items: center; - - padding: ${({ theme }) => theme.spacings.xlg} 0; - - background: linear-gradient( - 135deg, - ${({ theme }) => theme.colors.gray100} 45%, - ${({ theme }) => theme.colors.gray200} 100% - ); -` diff --git a/src/templates/Default/styles.ts b/src/templates/Default/styles.ts new file mode 100644 index 0000000..15f9f72 --- /dev/null +++ b/src/templates/Default/styles.ts @@ -0,0 +1,19 @@ +import styled from 'styled-components' + +export const Container = styled.main` + width: 100vw; + height: 100vh; + + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + + padding: ${({ theme }) => theme.spacings.xlg} 0; + + background: linear-gradient( + 135deg, + ${({ theme }) => theme.colors.gray100} 45%, + ${({ theme }) => theme.colors.gray200} 100% + ); +` diff --git a/src/templates/Questions/index.tsx b/src/templates/Questions/index.tsx new file mode 100644 index 0000000..daccfcb --- /dev/null +++ b/src/templates/Questions/index.tsx @@ -0,0 +1,59 @@ +import Progress from 'components/Progress' +import Loading from 'components/Loading' +import Button from 'components/Button' +import Arrows from 'components/Arrows' + +import { useQuestions } from 'contexts/QuestionsContext' + +import * as S from './styles' + +import type { ReactNode } from 'react' + +interface Props { + children: ReactNode +} + +const QuestionsTemplate = ({ children }: Props) => { + const { + questions, + disablePrevious, + disableNext, + goTo, + loading, + questionsAnswers + } = useQuestions() + + return ( + + + + {loading ? ( + + ) : ( + <> + {children} + + + goTo('previous')} + onClickDown={() => goTo('next')} + /> + + + + + )} + + ) +} + +export default QuestionsTemplate diff --git a/src/templates/Questions/styles.ts b/src/templates/Questions/styles.ts new file mode 100644 index 0000000..bfa827f --- /dev/null +++ b/src/templates/Questions/styles.ts @@ -0,0 +1,38 @@ +import styled from 'styled-components' + +export const Container = styled.main` + height: 90vh; + position: relative; +` + +interface WrapperProps { + visible?: boolean +} + +export const Wrapper = styled.div` + width: 100vw; + height: 100%; + + display: flex; + flex-direction: column; + justify-content: space-between; + + padding: 36px; + + @media (min-width: ${({ theme }) => theme.breakpoints.md}) { + padding: 56px 36px; + } +` + +export const Buttons = styled.div` + width: 100%; + + display: flex; + justify-content: space-between; + + padding: 0 24px; + + @media (min-width: ${({ theme }) => theme.breakpoints.md}) { + padding: 0 36px; + } +` diff --git a/src/types/contexts.d.ts b/src/types/contexts.d.ts new file mode 100644 index 0000000..ecfd659 --- /dev/null +++ b/src/types/contexts.d.ts @@ -0,0 +1,24 @@ +import type { ReactNode } from 'react' +import type { Question } from 'types/entities' + +export type CurrentQuestion = Question | null +export type Questions = Question[] +export type QuestionsAnswers = { id: string; answer: number }[] +export type AnswerQuestion = (questionId: string, answer: number) => void +export type GoTo = (to: 'previous' | 'next') => void + +export interface AuthContextData { + currentQuestion: CurrentQuestion + currentQuestionIndex: number + disablePrevious: boolean + disableNext: boolean + goTo: GoTo + questions: Questions + questionsAnswers: QuestionsAnswers + loading: boolean + answerQuestion: AnswerQuestion +} + +export interface AuthProviderProps { + children: ReactNode +} diff --git a/src/utils/index.ts b/src/utils/index.ts index e60645a..843416f 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,4 +1,4 @@ -interface Props { +interface GenerateArrayProps { size: number startAt?: number formatValue?: (value: number) => number @@ -8,10 +8,17 @@ export const generateArray = ({ size, startAt = 0, formatValue = (value) => value -}: Props) => { +}: GenerateArrayProps) => { const array = [] + for (let i = startAt; i < size; i++) { array.push(formatValue(i)) } + return array } + +export const getRandomValueFromArray = (array: any[]) => + array[Math.floor(Math.random() * array.length)] + +export const isNumber = (value: any) => !isNaN(Number(value))