161 lines
3.6 KiB
Vue
161 lines
3.6 KiB
Vue
<script lang="ts" setup>
|
|
import type {PropType} from "vue";
|
|
import {useQuizStore} from "~/store/quiz";
|
|
import type {Question} from "~/store/question";
|
|
|
|
const props = defineProps({
|
|
title: String,
|
|
description: {
|
|
type: String,
|
|
required: false,
|
|
},
|
|
axeNumber: Number,
|
|
totalAxes: Number,
|
|
icon: String,
|
|
color: String,
|
|
questions: {
|
|
type: Object as PropType<Question[]>,
|
|
required: true
|
|
}
|
|
});
|
|
|
|
const emit = defineEmits(["rate"]);
|
|
|
|
const store = useQuizStore();
|
|
|
|
const cssVars = computed(() => {
|
|
return {
|
|
'--color': props.color
|
|
}
|
|
});
|
|
|
|
function onRate(score: number, question: Question) {
|
|
store.updateScoreResponse({axeId: props.axeNumber, questionId: question.id, score});
|
|
const questions = store.questionsRatedPerAxe.get(props.axeNumber);
|
|
const unratedQuestions = questions ? questions.filter(value => !value.rated) : [];
|
|
emit('rate', {
|
|
isFullRated: unratedQuestions.length === 0
|
|
});
|
|
}
|
|
|
|
function onComment(comment: string, question: Question) {
|
|
store.updateCommentResponse({axeId: props.axeNumber, questionId: question.id, comment});
|
|
}
|
|
|
|
function getCurrentScore(question: Question): number | undefined {
|
|
const rate = store.responses.get(question.id) as QuizRate;
|
|
return rate ? rate.score : undefined;
|
|
}
|
|
|
|
function getCurrentComment(question: Question): string | undefined {
|
|
const rate = store.responses.get(question.id) as QuizRate;
|
|
return rate ? rate.comment : undefined;
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<article :style="cssVars">
|
|
<header>
|
|
<quiz-progress :number-steps=totalAxes :current-step=axeNumber :color="color"/>
|
|
<h1 class="title">
|
|
<span class="part-number">{{ axeNumber }}</span>
|
|
<span>{{ title }}</span>
|
|
</h1>
|
|
<div v-if="description" class="description">{{ description }}</div>
|
|
<div class="icon">
|
|
<img :src="icon" width="200px" alt="" aria-hidden="true"/>
|
|
</div>
|
|
</header>
|
|
<section v-if="questions" v-for="question in questions" :key="question.id" class="question">
|
|
<div class="title">
|
|
{{ question.label }}
|
|
</div>
|
|
<details v-if="question.description">
|
|
<summary>Description</summary>
|
|
<p>{{ question.description }}</p>
|
|
</details>
|
|
<div class="rating">
|
|
<rating :color="color" :initial-value="getCurrentScore(question)" @rate="rate => onRate(rate, question)"/>
|
|
</div>
|
|
<input :value="getCurrentComment(question)" type="text" placeholder="Commentaire" maxlength="500"
|
|
@input="event => onComment(event.target.value, question)"/>
|
|
</section>
|
|
</article>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
@import "assets/css/color";
|
|
@import "assets/css/font";
|
|
@import "assets/css/spacing";
|
|
|
|
$size: 31px;
|
|
|
|
.part-number {
|
|
display: inline-flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
color: var(--color);
|
|
border: 3px solid var(--color);
|
|
font-size: 1rem;
|
|
line-height: $size;
|
|
width: $size;
|
|
height: $size;
|
|
}
|
|
|
|
.title {
|
|
display: flex;
|
|
flex-direction: row;
|
|
text-align: left;
|
|
|
|
> span {
|
|
padding: 0 $small;
|
|
}
|
|
}
|
|
|
|
.icon {
|
|
text-align: center;
|
|
margin: $medium;
|
|
}
|
|
|
|
.description {
|
|
color: $gray_3;
|
|
font-weight: 400;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.question {
|
|
width: 100%;
|
|
|
|
details,
|
|
.title {
|
|
margin-bottom: $small;
|
|
}
|
|
.title {
|
|
font-weight: 700;
|
|
font-size: $title-font-size;
|
|
}
|
|
|
|
details summary {
|
|
list-style-position: inside;
|
|
margin-bottom: $xxx_small;
|
|
}
|
|
|
|
.rating {
|
|
margin: 0 auto;
|
|
max-width: 401px;
|
|
}
|
|
|
|
input[type="text"] {
|
|
width: 100%;
|
|
border: 1px solid $gray_2;
|
|
border-radius: 8px;
|
|
background: none;
|
|
margin: $medium 0;
|
|
font-weight: 400;
|
|
font-size: $tertiary-font-size;
|
|
}
|
|
}
|
|
|
|
</style>
|