ceiba-scores/src/components/Question.vue

327 lines
7.8 KiB
Vue

<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,
},
});
const emits = defineEmits(["answerSelected", "nextQuestion"]);
const slides = ref();
const answerWeight = ref(props.question.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;
emits("answerSelected", props.question, answerWeight);
}
const displayPopup = ref(false);
function showHidePopup() {
displayPopup.value = !displayPopup.value;
}
function validatePopup() {
const calcule = Math.round((h.value * 100) / d.value);
const regexp = /[^0-9]*([0-9]{2})/g;
const answersLength = props.question.answers.length;
const answerIndex = props.question.answers.find((answer, index) => {
const values = Array.from(answer.title.matchAll(regexp), (m) => m[1]);
if (values.length > 0) {
const min = values.length == 1 ? 0 : values[0];
const max = values.length == 1 ? values[0] : values[1];
if (calcule >= min && calcule <= max) {
return true;
}
}
if (answersLength == index + 1) {
return true;
}
});
document.querySelector(
"input[id=" + `question_${props.question.id}_answer_${answerIndex.id}` + "]"
).checked = true;
showHidePopup();
}
const h = ref(1);
const d = ref(1);
</script>
<template>
<div class="main">
<div class="center">
<legend>{{ question.title }}</legend>
<div class="images">
<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">
<img height="200" :src="`/answers/${answer.image}.webp`" />
</SplideSlide>
</Splide>
</template>
</div>
<template v-if="question.answers">
<ul class="choices">
<li
class="choice"
v-for="answer in question.answers"
:key="answer.id"
>
<input
type="radio"
:data-answerId="answer.id"
:name="`question_${question.id}`"
:id="`question_${question.id}_answer_${answer.id}`"
:value="answer.weight"
v-model="answerWeight"
@change="selectAnswer(answer)"
@click="nextQuestion"
/>
<label :for="`question_${question.id}_answer_${answer.id}`">
{{ answer.title }}
</label>
</li>
</ul>
</template>
</div>
</div>
<div class="btns">
<template v-if="question.function == 'rapport_hd'">
<button class="btn calculette" @click="showHidePopup">
<img src="/abacus.svg" alt="" />
</button>
</template>
<button class="btn next" @click="$emit('nextQuestion')">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 40 40"
width="40"
height="40"
>
<path
d="m15.5 0.932-4.3 4.38 14.5 14.6-14.5 14.5 4.3 4.4 14.6-14.6 4.4-4.3-4.4-4.4-14.6-14.6z"
></path>
</svg>
</button>
</div>
<template v-if="displayPopup">
<div class="popup">
<button class="btn close" @click="showHidePopup">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36">
<path
d="M21.529 18.006l8.238-8.238c.977-.976.977-2.559 0-3.535-.977-.977-2.559-.977-3.535 0l-8.238 8.238-8.238-8.238c-.976-.977-2.56-.977-3.535 0-.977.976-.977 2.559 0 3.535l8.238 8.238-8.258 8.258c-.977.977-.977 2.559 0 3.535.488.488 1.128.732 1.768.732s1.28-.244 1.768-.732l8.258-8.259 8.238 8.238c.488.488 1.128.732 1.768.732s1.279-.244 1.768-.732c.977-.977.977-2.559 0-3.535l-8.24-8.237z"
fill="#000"
/>
</svg>
</button>
<label for="H">H (m)</label>
<input v-model="h" type="number" name="H" />
<label for="D">D (cm)</label>
<input v-model="d" type="number" name="D" />
<p>({{ h }} * 100) / {{ d }} ≃ {{ Math.round((h * 100) / d) }}</p>
<button class="btn equal" @click="validatePopup">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36">
<path
fill="#31373D"
d="M34.459 1.375c-1.391-.902-3.248-.506-4.149.884L13.5 28.17l-8.198-7.58c-1.217-1.125-3.114-1.051-4.239.166-1.125 1.216-1.051 3.115.166 4.239l10.764 9.952s.309.266.452.359c.504.328 1.07.484 1.63.484.982 0 1.945-.482 2.52-1.368L35.343 5.524c.902-1.39.506-3.248-.884-4.149z"
/>
</svg>
</button>
</div>
</template>
</template>
<style lang="sass">
.btns
width: 400px
max-width: 100%
min-width: 280px
position: relative
margin: 0 auto
.popup
position: absolute
background: var(--color-highlight-background)
color: var(--color-highlight-text)
top: 0
left: 0
right: 0
bottom: 0
z-index: 100
display: flex
flex-direction: column
padding: 1rem
justify-content: center
align-items: center
p
padding: 1rem
margin: 1rem
border: 1px solid var(--color-highlight-text)
svg path
fill: var(--color-highlight-background)
.close
top: 1rem
right: 1rem
.equal
position: relative
input
padding: .4rem
text-align: center
font-size: 1rem
width: 5rem
.calculette
background: var(--color-highlight-background)
bottom: 1rem
left: 1rem
width: 3rem
height: 3rem
img
width: 80%
height: 80%
.next
background: var(--color-highlight-background)
bottom: 1rem
right: 1rem
width: 3rem
height: 3rem
opacity: .8
&:hover
opacity: 1
svg
width: 80%
height: 80%
transform: rotate(90deg)
fill: var(--color-highlight-text)
.splide__arrow
background: transparent
border: 3px solid var(--color-green)
width: 3rem
height: 3rem
opacity: 1
svg
fill: var(--color-green)
height: 1.6rem
width: 1.6rem
.splide__pagination
bottom: -1.5em
display: none
.splide__pagination__page
width: .7rem
height: .7rem
background: var(--color-green)
&.is-active
background: var(--color-green)
</style>
<style lang="sass" scoped>
legend
text-align: center
font-size: 1.4rem
line-height: 2rem
font-weight: bold
.choices
list-style-type: none
text-align: left
display: inline-block
padding-left: 0
label
cursor: pointer
input[type=radio]
display: none
& + label
position: relative
padding: .2rem .2rem .2rem 2rem
& + label::before,
& + label::after
display: block
position: absolute
box-sizing: border-box
content:''
border-radius: 1rem
& + label::before
bottom: .3rem
left: 0
background-color: var(--color-green)
width: 1rem
height: 1rem
& + label::after
bottom: calc(3px + .3rem)
left: 3px
width: calc(1rem - 6px)
height: calc(1rem - 6px)
&:checked + label
text-shadow: -0.06ex 0 0 currentColor, 0.06ex 0 0 currentColor
&:checked + label::before
background-color: var(--color-green)
&:checked + label::after
background-color: white
.main
height: 100%
max-width: 100%
display: flex
flex-direction: column
justify-content: space-around
align-items: center
.center
width: 100%
text-align: center
.images
margin: 3rem auto
width: 400px
max-width: 100%
min-width: 280px
@media (max-height: 600px)
margin: 1rem auto
h2
font-size: 2rem
.answers
text-align: center
@media only screen and (orientation : landscape)
.main
flex-direction: row
.images
max-width: 50%
</style>