244 lines
7.2 KiB
Vue
244 lines
7.2 KiB
Vue
|
<script lang="ts" setup>
|
|||
|
import type {PropType} from "vue";
|
|||
|
import type {Axe} from "~/store/axe";
|
|||
|
import type {Question} from "~/store/question";
|
|||
|
|
|||
|
const questions = ref<Question[]>([]);
|
|||
|
const newQuestionMode = ref(false);
|
|||
|
const newQuestionLabel = ref("");
|
|||
|
const newQuestionDescription = ref("");
|
|||
|
|
|||
|
const emit = defineEmits(["changed", "close"]);
|
|||
|
|
|||
|
const props = defineProps({
|
|||
|
axe: {
|
|||
|
type: Object as PropType<Axe>,
|
|||
|
},
|
|||
|
questions: {
|
|||
|
type: Object as PropType<Question[]>,
|
|||
|
},
|
|||
|
questionsExample: {
|
|||
|
type: Object as PropType<Question[]>,
|
|||
|
default: [{
|
|||
|
label: "",
|
|||
|
description: ""
|
|||
|
}]
|
|||
|
},
|
|||
|
visible: Boolean
|
|||
|
});
|
|||
|
|
|||
|
onMounted(() => {
|
|||
|
questions.value = props.questions ? props.questions.map(q => {
|
|||
|
return {
|
|||
|
label: q.label,
|
|||
|
description: q.description
|
|||
|
}
|
|||
|
}) : [];
|
|||
|
});
|
|||
|
|
|||
|
function removeQuestion(index: number) {
|
|||
|
questions.value.splice(index, 1);
|
|||
|
}
|
|||
|
|
|||
|
function moveQuestion(fromIndex, toIndex) {
|
|||
|
if (toIndex > questions.value.length || toIndex < 0) {
|
|||
|
return;
|
|||
|
}
|
|||
|
const element = questions.value[fromIndex];
|
|||
|
questions.value.splice(fromIndex, 1);
|
|||
|
questions.value.splice(toIndex, 0, element);
|
|||
|
}
|
|||
|
|
|||
|
function questionChanged(event, {index, newQuestion}) {
|
|||
|
questions.value[index] = newQuestion;
|
|||
|
}
|
|||
|
|
|||
|
function addNewQuestion() {
|
|||
|
questions.value.push({label: newQuestionLabel.value, description: newQuestionDescription.value});
|
|||
|
newQuestionMode.value = false;
|
|||
|
}
|
|||
|
|
|||
|
function changeToNewQuestionMode() {
|
|||
|
newQuestionLabel.value = "";
|
|||
|
newQuestionDescription.value = "";
|
|||
|
newQuestionMode.value = true;
|
|||
|
}
|
|||
|
|
|||
|
function validate() {
|
|||
|
emit("changed", {axeId: props.axe.id, newQuestions: questions.value});
|
|||
|
emit("close");
|
|||
|
}
|
|||
|
|
|||
|
</script>
|
|||
|
|
|||
|
<template>
|
|||
|
<div :class="`modal${visible ? ' visible' : ''}`" v-if="axe">
|
|||
|
<section class="modal-content">
|
|||
|
<header class="modal-content-header">
|
|||
|
<h1>{{ axe.identifier }} - {{ axe.shortTitle }}</h1>
|
|||
|
<p>{{ axe.title }}</p>
|
|||
|
<p v-if="axe.description">{{ axe.description }}</p>
|
|||
|
<button class="close_modal" @click="$emit('close')">
|
|||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|||
|
<path d="M1.6 16L0 14.4L6.4 8L0 1.6L1.6 0L8 6.4L14.4 0L16 1.6L9.6 8L16 14.4L14.4 16L8 9.6L1.6 16Z"
|
|||
|
fill="#1C1B1F"/>
|
|||
|
</svg>
|
|||
|
<span>Fermer</span>
|
|||
|
</button>
|
|||
|
</header>
|
|||
|
<main class="modal-content-body">
|
|||
|
<div v-if="newQuestionMode" class="new-question">
|
|||
|
<div class="new-question__inputs">
|
|||
|
<label for="label-new-question">Libellé *</label>
|
|||
|
<input id="label-new-question" type="text" list="question-labels" v-model="newQuestionLabel" maxlength="200"/>
|
|||
|
<label for="description-new-question">Description</label>
|
|||
|
<input id="description-new-question" type="text" list="question-labels" v-model="newQuestionDescription" maxlength="500"/>
|
|||
|
</div>
|
|||
|
<h2>Historique des questions</h2>
|
|||
|
<ul class="new-question__example-list">
|
|||
|
<li v-for="(question, index) in questionsExample">
|
|||
|
<input :id="'example-'+index" type="radio" name="example-radio" @input="() => {newQuestionLabel = question.label;newQuestionDescription = question.description;}">
|
|||
|
<label :for="'example-'+index">
|
|||
|
<span class="new-question__example-list__item-label">{{ question.label }}</span>
|
|||
|
<span class="new-question__example-list__item-description" v-if="question.description">{{ question.description }}</span>
|
|||
|
</label>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
<div v-else>
|
|||
|
<ul class="question-list">
|
|||
|
<li v-for="(question, index) in questions" class="question-list__item">
|
|||
|
<div class="question-list__item__inputs">
|
|||
|
<span class="question-list__item__inputs__title">Question {{index+1}}</span>
|
|||
|
<label :for="'label-'+index">Libellé *</label>
|
|||
|
<input :id="'label-'+index" type="text" list="question-labels" :value="question.label" maxlength="200"
|
|||
|
@change="event => questionChanged(event, {index, newQuestion: {label: event.target.value, description: question.description}})"/>
|
|||
|
<label :for="'description-'+index">Description</label>
|
|||
|
<input :id="'description-'+index" type="text" list="question-descriptions" :value="question.description" maxlength="500"
|
|||
|
@change="event => questionChanged(event, {index, newQuestion: {label: question.label, description: event.target.value}})"/>
|
|||
|
|
|||
|
</div>
|
|||
|
<div class="question-list__item__buttons">
|
|||
|
<button class="button-icon button-up" aria-label="Déplacer vers le haut"
|
|||
|
@click="moveQuestion(index, index-1)" :disabled="index === 0">
|
|||
|
➜
|
|||
|
</button>
|
|||
|
<button class="button-icon button-down" aria-label="Déplacer vers le bas"
|
|||
|
@click="moveQuestion(index, index+1)" :disabled="index === questions.length -1">
|
|||
|
➜
|
|||
|
</button>
|
|||
|
<button class="button-icon" @click="removeQuestion(index)">
|
|||
|
🗑
|
|||
|
</button>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
</main>
|
|||
|
<footer class="modal-content-footer">
|
|||
|
<button v-if="newQuestionMode" class="button gray button-back"
|
|||
|
@click="newQuestionMode = false">❮
|
|||
|
</button>
|
|||
|
<button v-if="newQuestionMode" class="button orange" :disabled="!newQuestionLabel"
|
|||
|
@click="addNewQuestion()">Ajouter
|
|||
|
</button>
|
|||
|
<button v-if="!newQuestionMode" class="button blue" @click="changeToNewQuestionMode()">Ajouter une question
|
|||
|
</button>
|
|||
|
<button v-if="!newQuestionMode" class="button orange" @click="validate()">Valider</button>
|
|||
|
</footer>
|
|||
|
</section>
|
|||
|
<div class="modal-overlay" @click="$emit('close')"></div>
|
|||
|
</div>
|
|||
|
</template>
|
|||
|
|
|||
|
<style scoped lang="scss">
|
|||
|
@import "assets/css/modal";
|
|||
|
.modal-content-body {
|
|||
|
//overflow: unset;
|
|||
|
}
|
|||
|
.question-list,
|
|||
|
.new-question__example-list {
|
|||
|
//overflow-y: scroll;
|
|||
|
//overflow-x: hidden;
|
|||
|
//height: 30%;
|
|||
|
}
|
|||
|
.new-question {
|
|||
|
&__inputs {
|
|||
|
display: flex;
|
|||
|
flex-direction: column;
|
|||
|
gap: $xx_small;
|
|||
|
}
|
|||
|
h2 {
|
|||
|
margin: $xx_small 0;
|
|||
|
font-size: $secondary-font-size;
|
|||
|
}
|
|||
|
|
|||
|
&__example-list {
|
|||
|
display: flex;
|
|||
|
flex-direction: column;
|
|||
|
gap: $xx_small;
|
|||
|
|
|||
|
&__item-description {
|
|||
|
font-style: italic;
|
|||
|
}
|
|||
|
|
|||
|
input {
|
|||
|
//align-content: start;
|
|||
|
}
|
|||
|
|
|||
|
li {
|
|||
|
display: flex;
|
|||
|
gap: $xxx_small;
|
|||
|
//align-items: start;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
label {
|
|||
|
display: flex;
|
|||
|
flex-direction: column;
|
|||
|
gap: $xxxx_small;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
.question-list {
|
|||
|
list-style: none;
|
|||
|
display: flex;
|
|||
|
flex-direction: column;
|
|||
|
gap: $small;
|
|||
|
|
|||
|
|
|||
|
&__item {
|
|||
|
display: flex;
|
|||
|
gap: $xxx_small;
|
|||
|
|
|||
|
&__inputs {
|
|||
|
display: flex;
|
|||
|
flex-direction: column;
|
|||
|
flex: 1;
|
|||
|
gap: $xxx_small;
|
|||
|
|
|||
|
&__title {
|
|||
|
font-weight: bold;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
&__buttons {
|
|||
|
//align-self: center;
|
|||
|
display: flex;
|
|||
|
flex-direction: column;
|
|||
|
align-self: end;
|
|||
|
//gap: $xxx_small;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
.button-up {
|
|||
|
rotate: -90deg;
|
|||
|
}
|
|||
|
|
|||
|
.button-down {
|
|||
|
rotate: 90deg;
|
|||
|
}
|
|||
|
</style>
|