feat: Séparation du code spécifique aux questions
This commit is contained in:
parent
cd149770ab
commit
f9bd10b640
|
@ -0,0 +1,99 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { Splide, SplideSlide } from "@splidejs/vue-splide";
|
||||||
|
import "@splidejs/splide/dist/css/splide.min.css";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
question: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
defineEmits(["answerSelected"]);
|
||||||
|
|
||||||
|
const slides = ref();
|
||||||
|
const answerWeight = ref(props.question.answers[0].weight);
|
||||||
|
|
||||||
|
function selectAnswer(answer) {
|
||||||
|
const answerIndex = props.question.answers.findIndex(
|
||||||
|
(a) => a.id === answer.id
|
||||||
|
);
|
||||||
|
slides.value.splide.go(answerIndex);
|
||||||
|
}
|
||||||
|
function slideMove(splide, newIndex) {
|
||||||
|
answerWeight.value = props.question.answers[newIndex].weight;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="main">
|
||||||
|
<div class="top">
|
||||||
|
<legend>{{ question.title }}</legend>
|
||||||
|
<template v-if="question.answers">
|
||||||
|
<div class="choice" v-for="answer in question.answers" :key="answer.id">
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
:data-answerId="answer.id"
|
||||||
|
:name="`question_${question.id}`"
|
||||||
|
:value="answer.weight"
|
||||||
|
v-model="answerWeight"
|
||||||
|
@click="selectAnswer(answer)"
|
||||||
|
/>
|
||||||
|
{{ answer.title }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class="bottom">
|
||||||
|
<template v-if="question.answers">
|
||||||
|
<Splide
|
||||||
|
@splide:move="slideMove"
|
||||||
|
class="answers"
|
||||||
|
:id="`question_${question.id}`"
|
||||||
|
ref="slides"
|
||||||
|
>
|
||||||
|
<SplideSlide
|
||||||
|
v-for="answer in question.answers"
|
||||||
|
:key="answer.id"
|
||||||
|
@click="$emit('answerSelected', question, answerWeight)"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
width="200"
|
||||||
|
height="200"
|
||||||
|
:src="`/answers/${answer.image}.png`"
|
||||||
|
/>
|
||||||
|
</SplideSlide>
|
||||||
|
</Splide>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="sass" scoped>
|
||||||
|
input[type=radio]
|
||||||
|
margin-right: .5rem
|
||||||
|
|
||||||
|
.main
|
||||||
|
height: 100%
|
||||||
|
max-width: 100%
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
justify-content: space-around
|
||||||
|
align-items: center
|
||||||
|
|
||||||
|
.bottom
|
||||||
|
width: 400px
|
||||||
|
max-width: 100%
|
||||||
|
min-width: 280px
|
||||||
|
|
||||||
|
.answers
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
@media only screen and (orientation : landscape)
|
||||||
|
.main
|
||||||
|
flex-direction: row
|
||||||
|
|
||||||
|
.bottom
|
||||||
|
max-width: 50%
|
||||||
|
</style>
|
|
@ -6,6 +6,7 @@ import { ref, computed } from "vue";
|
||||||
import { useStore } from "@/stores";
|
import { useStore } from "@/stores";
|
||||||
|
|
||||||
import { Splide, SplideSlide } from "@splidejs/vue-splide";
|
import { Splide, SplideSlide } from "@splidejs/vue-splide";
|
||||||
|
import Question from "./Question.vue";
|
||||||
import "@splidejs/splide/dist/css/splide.min.css";
|
import "@splidejs/splide/dist/css/splide.min.css";
|
||||||
import ScoreHeader from "./ScoreHeader.vue";
|
import ScoreHeader from "./ScoreHeader.vue";
|
||||||
|
|
||||||
|
@ -60,9 +61,6 @@ function formatScore(score) {
|
||||||
const title = score ? score.title : "";
|
const title = score ? score.title : "";
|
||||||
const questions = ref(formatScore(score));
|
const questions = ref(formatScore(score));
|
||||||
|
|
||||||
function nextQuestion() {
|
|
||||||
setTimeout(() => slides.value.go(">"), 100);
|
|
||||||
}
|
|
||||||
const scoreSum = computed(() => {
|
const scoreSum = computed(() => {
|
||||||
return questions.value
|
return questions.value
|
||||||
.map((question) => question.weight)
|
.map((question) => question.weight)
|
||||||
|
@ -97,21 +95,16 @@ const result = computed(() =>
|
||||||
.filter((r) => !r.max || r.max >= scoreSum.value)[0]
|
.filter((r) => !r.max || r.max >= scoreSum.value)[0]
|
||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
function selectImage(event, question, answer) {
|
function goQuestionSlide(question) {
|
||||||
const input = document.querySelector(
|
console.log(slides.value);
|
||||||
`input[name='question_${question.id}'][value='${answer.weight}']`
|
|
||||||
);
|
|
||||||
if (input) {
|
|
||||||
input.checked = true;
|
|
||||||
input.dispatchEvent(new Event("change"));
|
|
||||||
}
|
|
||||||
nextQuestion();
|
|
||||||
}
|
|
||||||
function geQuestionSlide(question) {
|
|
||||||
slides.value.go(
|
slides.value.go(
|
||||||
questions.value.findIndex((element) => element.id === question.id)
|
questions.value.findIndex((element) => element.id === question.id)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
function answerSelected(question, answerWeight) {
|
||||||
|
questions.value.find((q) => q.id === question.id).weight = answerWeight;
|
||||||
|
setTimeout(() => slides.value.go(">"), 100);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -131,57 +124,7 @@ function geQuestionSlide(question) {
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<SplideSlide v-for="question in questions" :key="question.id">
|
<SplideSlide v-for="question in questions" :key="question.id">
|
||||||
<div class="main">
|
<Question :question="question" @answerSelected="answerSelected" />
|
||||||
<div class="top">
|
|
||||||
<legend>{{ question.title }}</legend>
|
|
||||||
<template v-if="question.answers">
|
|
||||||
<div
|
|
||||||
class="choice"
|
|
||||||
v-for="answer in question.answers"
|
|
||||||
:key="answer.id"
|
|
||||||
>
|
|
||||||
<label>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
:data-answerId="answer.id"
|
|
||||||
:name="`question_${question.id}`"
|
|
||||||
:value="answer.weight"
|
|
||||||
@change="
|
|
||||||
(event) => {
|
|
||||||
question.weight = parseFloat(event.target.value);
|
|
||||||
}
|
|
||||||
"
|
|
||||||
@click="nextQuestion"
|
|
||||||
/>
|
|
||||||
{{ answer.title }}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
<div class="bottom">
|
|
||||||
<template v-if="question.answers">
|
|
||||||
<Splide
|
|
||||||
class="answers"
|
|
||||||
:id="`question_${question.id}`"
|
|
||||||
ref="question.splide"
|
|
||||||
>
|
|
||||||
<SplideSlide
|
|
||||||
v-for="answer in question.answers"
|
|
||||||
:key="answer.id"
|
|
||||||
@click="
|
|
||||||
(event) => selectImage(event, { ...question }, { ...answer })
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
width="200"
|
|
||||||
height="200"
|
|
||||||
:src="`/answers/${answer.image}.png`"
|
|
||||||
/>
|
|
||||||
</SplideSlide>
|
|
||||||
</Splide>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SplideSlide>
|
</SplideSlide>
|
||||||
<SplideSlide class="latest">
|
<SplideSlide class="latest">
|
||||||
<template v-if="displayScoreResult && result">
|
<template v-if="displayScoreResult && result">
|
||||||
|
@ -216,7 +159,7 @@ function geQuestionSlide(question) {
|
||||||
<a
|
<a
|
||||||
@click="
|
@click="
|
||||||
(event) => {
|
(event) => {
|
||||||
geQuestionSlide(question);
|
goQuestionSlide(question);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
|
@ -254,9 +197,6 @@ function geQuestionSlide(question) {
|
||||||
bottom: 0
|
bottom: 0
|
||||||
background: transparent
|
background: transparent
|
||||||
|
|
||||||
input[type=radio]
|
|
||||||
margin-right: .5rem
|
|
||||||
|
|
||||||
|
|
||||||
.splide__slide
|
.splide__slide
|
||||||
background: transparent
|
background: transparent
|
||||||
|
@ -313,29 +253,6 @@ label
|
||||||
top: 0
|
top: 0
|
||||||
line-height: .7rem
|
line-height: .7rem
|
||||||
|
|
||||||
.main
|
|
||||||
height: 100%
|
|
||||||
max-width: 100%
|
|
||||||
display: flex
|
|
||||||
flex-direction: column
|
|
||||||
justify-content: space-around
|
|
||||||
align-items: center
|
|
||||||
|
|
||||||
.bottom
|
|
||||||
width: 400px
|
|
||||||
max-width: 100%
|
|
||||||
min-width: 280px
|
|
||||||
|
|
||||||
.answers
|
|
||||||
text-align: center
|
|
||||||
|
|
||||||
.splide__arrows
|
.splide__arrows
|
||||||
position: inherit
|
position: inherit
|
||||||
|
|
||||||
@media only screen and (orientation : landscape)
|
|
||||||
.main
|
|
||||||
flex-direction: row
|
|
||||||
|
|
||||||
.bottom
|
|
||||||
max-width: 50%
|
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue