Skip to content

Commit

Permalink
feature: improve UI
Browse files Browse the repository at this point in the history
  • Loading branch information
wilcorrea committed Apr 9, 2024
1 parent 834f59f commit 6cf46de
Show file tree
Hide file tree
Showing 28 changed files with 469 additions and 322 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
VITE_BASE_PATH=/quiz
VITE_IN_MEMORY_TIMEOUT=200

VITE_SUPABASE_URL=https://<project>.supabase.co
VITE_SUPABASE_ANON_KEY=<your-anon-key>
Expand Down
Binary file added public/assets/images/status/correct.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/images/status/wrong.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 14 additions & 13 deletions src/App.css
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
.pergunta {
padding: 0 12px 12px 12px;
background: #ffffff;
color: #51575b;
.GamePlaySessionQuestionUnanswered > .card {
text-shadow: 1px 1px 1px #707070;
}

.GamePlaySessionQuestionUnanswered > .card code {
text-shadow: none;
padding: 4px 6px;
border-radius: 6px;
background-color: #ffffff;
color: #565656;
margin: 0 0.1rem;
}

.pergunta .radio p {
display: inline-block;
padding-left: 5px;
.GamePlaySessionQuestionUnanswered > .card > .card-header code {
font-size: 1rem;
}

.pergunta .radio code {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
background-color: #f9f2f4;
border-radius: 4px;
main .btn.btn-primary {
box-shadow: rgba(64, 60, 67, 0.3) 1px 2px 5px 1px !important;
}
4 changes: 2 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { ProtectPage } from './view/components/auth/ProtectPage'
import { HomePage } from './view/pages/HomePage.tsx'
// game
import { GameWelcomePage } from './view/pages/game/GameWelcomePage.tsx'
import { GamePage } from './view/pages/game/GamePage.tsx'
import { GamePlayPage } from './view/pages/game/GamePlayPage.tsx'
import { GameEndPage } from './view/pages/game/GameEndPage.tsx'
// session
import { PrivatePage } from './view/pages/PrivatePage'
Expand All @@ -37,7 +37,7 @@ export default function App () {
/>
<Route
path="/game/:id/play"
element={<GamePage />}
element={<GamePlayPage />}
/>
<Route
path="/game/:id/end"
Expand Down
3 changes: 2 additions & 1 deletion src/app/Infrastructure/InMemory/InMemoryGameRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ export default class InMemoryGameRepository implements GameRepository {
}

async promisify <T>(data: T): Promise<T> {
const timeout = import.meta.env.VITE_IN_MEMORY_TIMEOUT || 300
return new Promise((resolve) => {
const handler = () => resolve(data)
window.setTimeout(handler, 300)
window.setTimeout(handler, Number(timeout))
})
}

Expand Down
20 changes: 10 additions & 10 deletions src/app/Infrastructure/InMemory/games.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,15 @@ export default function (): Game[] {
text: '`construtor__`'
}
]
},
}
]
}, {
id: 2,
description: 'Avançado',
author: '[email protected]',
createdAt: new Date(),
updatedAt: new Date(),
questions: [
{
id: 3,
text: 'Utilizando banco de dados MySQL, qual a função para enviar uma consulta SQL ao banco de dados ativo?',
Expand Down Expand Up @@ -271,15 +279,7 @@ export default function (): Game[] {
text: '`__construct()` e `__destruct()`'
}
]
}
]
}, {
id: 2,
description: 'Avançado',
author: '[email protected]',
createdAt: new Date(),
updatedAt: new Date(),
questions: [
},
{
id: 10,
text: 'O que a keyword `final` faz?',
Expand Down
2 changes: 1 addition & 1 deletion src/config/dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import SupabaseGameRepository from '../app/Infrastructure/Supabase/SupabaseGameR
export default function () {
container.register('AuthService', { useClass: AuthService })
container.register('AuthRepository', { useClass: JsonHttpAuthRepository })
if (process.env.NODE_ENV === 'development') {
if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'production') {
container.register('GameRepository', { useClass: InMemoryGameRepository })
return container
}
Expand Down
42 changes: 33 additions & 9 deletions src/config/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,39 @@ const resources = {
callToAction: 'Jogar agora »'
},
game: {
play: {
pending: 'Carregando Jogo ...',
rejected: 'Não foi possível carregar o jogo',
error: 'Oh snap!',
instructions: {
title: 'O jogo já vai começar!',
selected: 'Jogo Selecionado: ',
description: 'Certifique-se de que todos estão prontos e clique em Começar!\n' +
'Lembrando que este jogo tem um tempo limite de {{timeout}} segundos para responder ' +
'cada pergunta e {{total}} perguntas ao todo',
greetings: 'Boa sorte!',
start: 'Começar'
},
session: {
correct: {
title: 'Certa a resposta! Acerto Mizeravi!',
description: 'Você acertou! Escolha alguém para beber e passe a vez para a pessoa à sua esquerda.'
},
wrong: {
title: 'Você errou! Bebe!',
description: 'Errou feio, errou Rude! Agora tem de beber e passar a vez para a pessoa à sua esquerda.'
},
expired: {
title: 'Acabou o tempo!',
description: 'Você demorou demais para responder! Agora tem de beber e passar a vez para a pessoa à sua esquerda.'
},
unanswered: {
timer: 'Tempo restante: {{time}} segundos',
},
next: 'Próximo',
answer: 'Responder',
}
},
welcome: {
title: 'Escolha um Jogo',
description: 'Depois de selecionar um jogo cada um na mesa deve responder a uma pergunta.\n' +
Expand All @@ -33,15 +66,6 @@ const resources = {
rejected: 'Não foi possível carregar os jogos',
error: 'Oh snap!'
},
play: {
title: 'O jogo já vai começar!',
selected: 'Jogo Selecionado: ',
description: 'Certifique-se de que todos estão prontos para começar e clique em Começar!\n' +
'Lembrando que este jogo tem um tempo limite de {{timeout}} segundos para responder ' +
'cada pergunta e {{total}} perguntas ao todo',
greetings: 'Boa sorte!',
start: 'Começar'
},
end: {
title: 'O jogo acabou!',
description: 'Não está bêbado suficiente? Clique em "Começar de novo"!',
Expand Down
5 changes: 5 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
padding-top: 82px;
}

body {
background-image: linear-gradient(90deg, #33b7e2, #a680da, #fd81b8);
}

nav {
height: 82px;
}
Expand All @@ -15,6 +19,7 @@ main {

main > .container {
min-height: calc(100vh - 198px);
transition: height 0.3s;
}

footer {
Expand Down
26 changes: 0 additions & 26 deletions src/view/components/game/GameCorrectAnswer.tsx

This file was deleted.

28 changes: 28 additions & 0 deletions src/view/components/game/GameImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { image } from '../../../config/assets.ts'

export function Drink () {
return (
<div className="d-flex justify-content-center justify-content-center">
<img
className="img-fluid"
src={image('/status/wrong.png')}
alt="PHPinga"
style={{ maxHeight: '40vh' }}
/>
</div>
)
}

export function Celebrate () {
return (
<div className="d-flex justify-content-center justify-content-center">
<img
className="img-fluid"
src={image('/status/correct.png')}
alt="PHPinga"
style={{ maxHeight: '40vh' }}
/>
</div>
)
}

68 changes: 0 additions & 68 deletions src/view/components/game/GamePlay.tsx

This file was deleted.

83 changes: 83 additions & 0 deletions src/view/components/game/GamePlaySession.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { useEffect, useState } from 'react'

import Question from '../../../app/Domain/Game/Question.ts'
import AnswerStatus from '../../../app/Domain/Game/AnswerStatus.ts'
import { shuffle } from '../../../app/Domain/Util.ts'
import Game from '../../../app/Domain/Game/Game.ts'

import { GamePlaySessionInstruction } from './game-play-session/GamePlaySessionInstruction.tsx'
import { GamePlaySessionQuestion, GameQuestionAnswerQuestion } from './game-play-session/GamePlaySessionQuestion.tsx'

export type GamePlaySessionProps = {
game: Game,
onStart?: () => void,
onFinish?: () => void
}

export function GamePlaySession ({ game, onStart, onFinish }: GamePlaySessionProps) {
const timeout = 1000000
const [questions, setQuestions] = useState<Question[]>([])
const [currentQuestion, setCurrentQuestion] = useState<Question | null>(null)

const nextQuestion = () => {
if (questions.length === 0) {
finishGame()
return
}
const randomIndex = Math.floor(Math.random() * questions.length)
const newQuestion = questions[randomIndex]
setCurrentQuestion(newQuestion)
}

const startGame = () => {
nextQuestion()
onStart && onStart()
}

const finishGame = () => {
setCurrentQuestion(null)
onFinish && onFinish()
}

const answerQuestion: GameQuestionAnswerQuestion = (status) => {
// TODO: improve actions for each result
const actions = {
[AnswerStatus.CORRECT]: () => {
console.log('Correct!')
const current = questions.findIndex((q) => q === currentQuestion)
const newQuestions = questions.filter((_, index) => index !== current)
setQuestions(shuffle<Question>(newQuestions))
},
[AnswerStatus.WRONG]: () => console.log('Wrong!'),
[AnswerStatus.UNANSWERED]: () => console.log('Unanswered!'),
[AnswerStatus.TIME_EXPIRED]: () => console.log('Time expired!'),
}
actions[status]()
}

useEffect(() => {
if (questions.length > 0) {
return
}
setQuestions(shuffle<Question>(game.questions))
}, [game, questions])

return !currentQuestion ?
<GamePlaySessionInstruction
timeout={timeout}
game={game}
nextQuestion={startGame}
/> :
<>
<GamePlaySessionQuestion
timeout={timeout}
text={currentQuestion.text}
answers={currentQuestion.answers}
answerQuestion={answerQuestion}
nextQuestion={nextQuestion}
/>
<div className="pt-1">
<small>{game.questions.length - questions.length} / {game.questions.length}</small>
</div>
</>
}
Loading

0 comments on commit 6cf46de

Please sign in to comment.