mirror of
https://github.com/Floriansylvain/ParisMuseesQuizz.git
synced 2026-08-19 19:53:22 +02:00
Refactor and implemented full game logic
This commit is contained in:
@@ -11,7 +11,6 @@
|
|||||||
"type-check": "vue-tsc --noEmit"
|
"type-check": "vue-tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pinia": "^2.0.32",
|
|
||||||
"vue": "^3.2.47",
|
"vue": "^3.2.47",
|
||||||
"vue-router": "^4.1.6"
|
"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", () => {})
|
|
||||||
+81
-61
@@ -1,81 +1,101 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, Ref, ref } from "vue"
|
import { onMounted, Ref, ref } from "vue"
|
||||||
|
import Quizz from "../components/Quizz.vue"
|
||||||
|
|
||||||
interface AuthorData {
|
const gameMessage = ref("choisissez une réponse")
|
||||||
author: {
|
const gameProgression = ref(1)
|
||||||
id: number
|
const gameProgressionMax = 10
|
||||||
fullname: string
|
const gameScore = ref(0)
|
||||||
created_at: string
|
const gameShouldGoNext = ref(false)
|
||||||
updated_at: string
|
|
||||||
}
|
function gameHandler(callback: () => void): void {
|
||||||
|
if (gameShouldGoNext.value) return
|
||||||
|
gameShouldGoNext.value = true
|
||||||
|
|
||||||
|
callback()
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Painting {
|
function winHandler(): void {
|
||||||
id: number
|
gameMessage.value = "Bonne réponse !"
|
||||||
name: string
|
gameScore.value += 1
|
||||||
image_url: string
|
|
||||||
link: string
|
|
||||||
musuemId: number
|
|
||||||
PaintingAuthor: AuthorData[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const paintings: Ref<Painting[]> = ref([])
|
function loseHandler(): void {
|
||||||
const winningPainting: Ref<Painting> = ref({} as Painting)
|
gameMessage.value = "Mauvaise réponse"
|
||||||
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))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function initPaintings(): Promise<void> {
|
function nextGame(): void {
|
||||||
const fetchedData = await fetchRandomPainting()
|
if (!gameShouldGoNext.value) return
|
||||||
paintings.value = fetchedData.paintings
|
gameShouldGoNext.value = false
|
||||||
|
|
||||||
|
gameMessage.value = "choisissez une réponse"
|
||||||
|
gameProgression.value += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
function setWinningPainting(): void {
|
function resetGame(): void {
|
||||||
const randomIndex = Math.floor(Math.random() * paintings.value.length)
|
gameMessage.value = "choisissez une réponse"
|
||||||
winningPainting.value = paintings.value[randomIndex]
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<img :src="winningPainting?.image_url" />
|
<div class="container">
|
||||||
<button
|
<template v-if="gameProgression < gameProgressionMax">
|
||||||
v-for="painting of paintings"
|
<p>Quiz ({{ gameProgression }}/{{ gameProgressionMax }})</p>
|
||||||
@click="() => authorClickHandler(painting.PaintingAuthor[0].author.id)"
|
<h2>Qui a peint cette oeuvre ?</h2>
|
||||||
type="button"
|
|
||||||
>
|
<Quizz
|
||||||
{{ painting.PaintingAuthor[0].author.fullname }}
|
@win="() => gameHandler(winHandler)"
|
||||||
</button>
|
@lose="() => gameHandler(loseHandler)"
|
||||||
<p>{{ gameMessage }}</p>
|
:key="gameProgression"
|
||||||
<button type="button" @click="initGame">Next</button>
|
:disabled="gameShouldGoNext"
|
||||||
|
></Quizz>
|
||||||
|
<div class="quizz-footer">
|
||||||
|
<p>{{ gameMessage }}</p>
|
||||||
|
<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>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
img {
|
.container {
|
||||||
width: 200px;
|
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>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user