Skip to content

Commit

Permalink
feat: create questions context
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikael-R committed May 14, 2022
1 parent 487c019 commit 06b3215
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 44 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"next": "12.1.6",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-helmet": "^6.1.0",
"styled-components": "^5.3.5"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion src/components/Ranger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const Ranger = ({ optionsSize, side = 'both', onSelect }: Props) => {
optionsSize += 1
}

const [selected, setSelected] = useState(-1)
const [selected, setSelected] = useState<number | null>(null)

const increaser = Number((1 / optionsSize).toFixed(2))

Expand Down
82 changes: 82 additions & 0 deletions src/contexts/QuestionsContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { createContext, useContext, useEffect, useState } from 'react'

import Router from 'next/router'

import QuestionsRepository from 'repositories/questionsRepository'

import type { ReactNode } from 'react'
import type { Question } from 'types/entities'

type Questions = Question[]
type QuestionsAnswers = { id: string; answer: number }[]
type AnswerQuestion = (questionId: string, answer: number) => void

interface AuthContextData {
questions: Questions
questionsAnswers: QuestionsAnswers
isLoading: boolean
answerQuestion: AnswerQuestion
}

interface AuthProviderProps {
children: ReactNode
}

const questionsRepository = new QuestionsRepository()

const QuestionsContext = createContext<AuthContextData>({
questions: [],
questionsAnswers: [],
isLoading: true,
answerQuestion: () => undefined
})

export const QuestionsProvider = ({ children }: AuthProviderProps) => {
const [questions, setQuestions] = useState<Questions>([])
const [questionsAnswers, setQuestionsAnswers] = useState<QuestionsAnswers>([])
const [isLoading, setIsLoading] = useState(true)

const answerQuestion: AnswerQuestion = (questionId, answer) => {
setQuestionsAnswers([
...questionsAnswers.filter(({ id }) => id !== questionId),
{
id: questionId,
answer
}
])
}

const fetchQuestions = async () => {
try {
const { questions } = await questionsRepository.getQuestions()
setQuestions(questions)
} catch {
Router.push('/')
} finally {
setIsLoading(false)
}
}

useEffect(() => {
fetchQuestions()
}, [])

return (
<QuestionsContext.Provider
value={{
questions,
questionsAnswers,
isLoading,
answerQuestion
}}
>
{children}
</QuestionsContext.Provider>
)
}

export const useQuestions = () => {
const context = useContext(QuestionsContext)

return context
}
19 changes: 5 additions & 14 deletions src/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Helmet } from 'react-helmet'
import { ThemeProvider } from 'styled-components'

import { QuestionsProvider } from 'contexts/QuestionsContext'

import GlobalStyles from 'styles/global'
import theme from 'styles/theme'

Expand All @@ -9,21 +10,11 @@ import type { AppProps } from 'next/app'
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Helmet>
<link rel='preconnect' href='https://fonts.googleapis.com' />
<link
rel='preconnect'
href='https://fonts.gstatic.com'
crossOrigin='anonymous'
/>
<link
href='https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700&display=swap'
rel='stylesheet'
/>
</Helmet>
<GlobalStyles />
<ThemeProvider theme={theme}>
<Component {...pageProps} />
<QuestionsProvider>
<Component {...pageProps} />
</QuestionsProvider>
</ThemeProvider>
</>
)
Expand Down
32 changes: 31 additions & 1 deletion src/pages/_document.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import Document, { DocumentContext, DocumentInitialProps } from 'next/document'
import Document, {
Html,
Head,
Main,
NextScript,
DocumentContext,
DocumentInitialProps
} from 'next/document'
import { ServerStyleSheet } from 'styled-components'

export default class MyDocument extends Document {
Expand Down Expand Up @@ -30,4 +37,27 @@ export default class MyDocument extends Document {
sheet.seal()
}
}

render() {
return (
<Html>
<Head>
<link rel='preconnect' href='https://fonts.googleapis.com' />
<link
rel='preconnect'
href='https://fonts.gstatic.com'
crossOrigin='anonymous'
/>
<link
href='https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700&display=swap'
rel='stylesheet'
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
17 changes: 14 additions & 3 deletions src/pages/questions/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import Ranger from 'components/Ranger'

import { useQuestions } from 'contexts/QuestionsContext'

import type { NextPage } from 'next'

const HomePage: NextPage = () => {
const QuestionsPage: NextPage = () => {
const { questions, answerQuestion } = useQuestions()

return (
<>
<Ranger optionsSize={3} side='both' />
{questions.map((question) => (
<Ranger
key={question.id}
optionsSize={3}
side='both'
onSelect={(answer) => answerQuestion(question.id, answer)}
/>
))}
</>
)
}

export default HomePage
export default QuestionsPage
6 changes: 4 additions & 2 deletions src/repositories/questionsRepository.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import Http from 'services/Http'

import type { GetQuestionsResponse } from 'types/requests'

export default class QuestionsRepository extends Http {
async all() {
return await this.get('surveys/frontend-interview')
getQuestions() {
return this.get<GetQuestionsResponse>('surveys/frontend-interview')
}
}
12 changes: 12 additions & 0 deletions src/types/entities.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export type Question = {
id: string
createdAt: string
title: string
category: Category
surveyId?: string
}

export type Category = {
id: number
name: string
}
6 changes: 6 additions & 0 deletions src/types/requests.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { Question } from './entities'

export type GetQuestionsResponse = {
surveyId: number
questions: Question[]
}
File renamed without changes.
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"baseUrl": "src"
"baseUrl": "src",
"typeRoots": ["src/types"]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
Expand Down
22 changes: 1 addition & 21 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2221,7 +2221,7 @@ prettier@^2.6.2:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032"
integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==

prop-types@^15.7.2, prop-types@^15.8.1:
prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
Expand All @@ -2248,31 +2248,11 @@ [email protected]:
loose-envify "^1.1.0"
scheduler "^0.22.0"

react-fast-compare@^3.1.1:
version "3.2.0"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==

react-helmet@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.1.0.tgz#a750d5165cb13cf213e44747502652e794468726"
integrity sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==
dependencies:
object-assign "^4.1.1"
prop-types "^15.7.2"
react-fast-compare "^3.1.1"
react-side-effect "^2.1.0"

react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==

react-side-effect@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.1.tgz#66c5701c3e7560ab4822a4ee2742dee215d72eb3"
integrity sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==

[email protected]:
version "18.1.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.1.0.tgz#6f8620382decb17fdc5cc223a115e2adbf104890"
Expand Down

1 comment on commit 06b3215

@vercel
Copy link

@vercel vercel bot commented on 06b3215 May 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.