mirror of
https://github.com/Floriansylvain/ParisMuseesQuizz.git
synced 2026-08-19 11:43:22 +02:00
Refactor and implemented full game logic
This commit is contained in:
@@ -11,7 +11,6 @@
|
||||
"type-check": "vue-tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"pinia": "^2.0.32",
|
||||
"vue": "^3.2.47",
|
||||
"vue-router": "^4.1.6"
|
||||
},
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template></template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,103 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, Ref, ref } from "vue"
|
||||
|
||||
interface AuthorData {
|
||||
author: {
|
||||
id: number
|
||||
fullname: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
}
|
||||
|
||||
interface Painting {
|
||||
id: number
|
||||
name: string
|
||||
image_url: string
|
||||
link: string
|
||||
musuemId: number
|
||||
PaintingAuthor: AuthorData[]
|
||||
}
|
||||
|
||||
const emits = defineEmits(["win", "lose"])
|
||||
const props = defineProps<{ disabled: boolean }>()
|
||||
|
||||
const paintings: Ref<Painting[]> = ref([])
|
||||
const winningPainting: Ref<Painting> = ref({} as Painting)
|
||||
|
||||
function fetchRandomPainting(): Promise<{ paintings: Painting[] }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(`${__APP_ENV__.API_ADDRESS}/paintings/random/4`)
|
||||
.then((response) => response.json())
|
||||
.then((data) => resolve(data))
|
||||
.catch((error) => reject(error))
|
||||
})
|
||||
}
|
||||
|
||||
async function initPaintings(): Promise<void> {
|
||||
const fetchedData = await fetchRandomPainting()
|
||||
paintings.value = fetchedData.paintings
|
||||
}
|
||||
|
||||
function setWinningPainting(): void {
|
||||
const randomIndex = Math.floor(Math.random() * paintings.value.length)
|
||||
winningPainting.value = paintings.value[randomIndex]
|
||||
}
|
||||
|
||||
function authorClickHandler(auhtorId: number): void {
|
||||
if (auhtorId === winningPainting.value.PaintingAuthor[0].author.id) {
|
||||
emits("win")
|
||||
} else {
|
||||
emits("lose")
|
||||
}
|
||||
}
|
||||
|
||||
async function initGame(): Promise<void> {
|
||||
await initPaintings()
|
||||
setWinningPainting()
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await initGame()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container">
|
||||
<img :src="winningPainting?.image_url" />
|
||||
<div class="choices">
|
||||
<button
|
||||
v-for="painting of paintings"
|
||||
@click="() => authorClickHandler(painting.PaintingAuthor[0].author.id)"
|
||||
type="button"
|
||||
:disabled="disabled"
|
||||
>
|
||||
{{ painting.PaintingAuthor[0].author.fullname }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container img {
|
||||
max-width: 100%;
|
||||
max-height: 400px;
|
||||
}
|
||||
|
||||
.choices {
|
||||
display: grid;
|
||||
grid-template: repeat(2, 1fr) / repeat(2, 1fr);
|
||||
grid-gap: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,3 +0,0 @@
|
||||
import { defineStore } from "pinia"
|
||||
|
||||
export const useStore = defineStore("store", () => {})
|
||||
+80
-60
@@ -1,81 +1,101 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, Ref, ref } from "vue"
|
||||
import Quizz from "../components/Quizz.vue"
|
||||
|
||||
interface AuthorData {
|
||||
author: {
|
||||
id: number
|
||||
fullname: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
const gameMessage = ref("choisissez une réponse")
|
||||
const gameProgression = ref(1)
|
||||
const gameProgressionMax = 10
|
||||
const gameScore = ref(0)
|
||||
const gameShouldGoNext = ref(false)
|
||||
|
||||
function gameHandler(callback: () => void): void {
|
||||
if (gameShouldGoNext.value) return
|
||||
gameShouldGoNext.value = true
|
||||
|
||||
callback()
|
||||
}
|
||||
|
||||
interface Painting {
|
||||
id: number
|
||||
name: string
|
||||
image_url: string
|
||||
link: string
|
||||
musuemId: number
|
||||
PaintingAuthor: AuthorData[]
|
||||
function winHandler(): void {
|
||||
gameMessage.value = "Bonne réponse !"
|
||||
gameScore.value += 1
|
||||
}
|
||||
|
||||
const paintings: Ref<Painting[]> = ref([])
|
||||
const winningPainting: Ref<Painting> = ref({} as Painting)
|
||||
const gameMessage = ref("")
|
||||
|
||||
function fetchRandomPainting(): Promise<{ paintings: Painting[] }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(`${__APP_ENV__.API_ADDRESS}/paintings/random/4`)
|
||||
.then((response) => response.json())
|
||||
.then((data) => resolve(data))
|
||||
.catch((error) => reject(error))
|
||||
})
|
||||
function loseHandler(): void {
|
||||
gameMessage.value = "Mauvaise réponse"
|
||||
}
|
||||
|
||||
async function initPaintings(): Promise<void> {
|
||||
const fetchedData = await fetchRandomPainting()
|
||||
paintings.value = fetchedData.paintings
|
||||
function nextGame(): void {
|
||||
if (!gameShouldGoNext.value) return
|
||||
gameShouldGoNext.value = false
|
||||
|
||||
gameMessage.value = "choisissez une réponse"
|
||||
gameProgression.value += 1
|
||||
}
|
||||
|
||||
function setWinningPainting(): void {
|
||||
const randomIndex = Math.floor(Math.random() * paintings.value.length)
|
||||
winningPainting.value = paintings.value[randomIndex]
|
||||
function resetGame(): void {
|
||||
gameMessage.value = "choisissez une réponse"
|
||||
gameProgression.value = 1
|
||||
gameScore.value = 0
|
||||
}
|
||||
|
||||
function authorClickHandler(auhtorId: number): void {
|
||||
if (auhtorId === winningPainting.value.PaintingAuthor[0].author.id) {
|
||||
gameMessage.value = "Correct!"
|
||||
} else {
|
||||
gameMessage.value = "Wrong!"
|
||||
}
|
||||
}
|
||||
|
||||
async function initGame(): Promise<void> {
|
||||
await initPaintings()
|
||||
setWinningPainting()
|
||||
gameMessage.value = "What is the author of this painting?"
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await initGame()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<img :src="winningPainting?.image_url" />
|
||||
<button
|
||||
v-for="painting of paintings"
|
||||
@click="() => authorClickHandler(painting.PaintingAuthor[0].author.id)"
|
||||
type="button"
|
||||
>
|
||||
{{ painting.PaintingAuthor[0].author.fullname }}
|
||||
</button>
|
||||
<div class="container">
|
||||
<template v-if="gameProgression < gameProgressionMax">
|
||||
<p>Quiz ({{ gameProgression }}/{{ gameProgressionMax }})</p>
|
||||
<h2>Qui a peint cette oeuvre ?</h2>
|
||||
|
||||
<Quizz
|
||||
@win="() => gameHandler(winHandler)"
|
||||
@lose="() => gameHandler(loseHandler)"
|
||||
:key="gameProgression"
|
||||
:disabled="gameShouldGoNext"
|
||||
></Quizz>
|
||||
<div class="quizz-footer">
|
||||
<p>{{ gameMessage }}</p>
|
||||
<button type="button" @click="initGame">Next</button>
|
||||
<button type="button" @click="nextGame" :disabled="!gameShouldGoNext">
|
||||
suivant
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="game-over" v-else>
|
||||
<p>Vous avez {{ gameScore }}/{{ gameProgressionMax }} bonnes réponses !</p>
|
||||
<button type="button" @click="resetGame">rejouer</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
img {
|
||||
width: 200px;
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
|
||||
width: 100%;
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
.container > p,
|
||||
.container > h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.container > p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.quizz-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.game-over {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user