more question types creation support && made questions prototypes draggable

This commit is contained in:
grey-cat-1908 2024-09-07 22:17:11 +03:00
parent 6bcf0a1467
commit 4d7b0636ab
3 changed files with 127 additions and 23 deletions

View file

@ -15,7 +15,8 @@
"@phosphor-icons/vue": "^2.2.1", "@phosphor-icons/vue": "^2.2.1",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"vue": "^3.4.29", "vue": "^3.4.29",
"vue-router": "^4.3.3" "vue-router": "^4.3.3",
"vuedraggable": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@tsconfig/node20": "^20.1.4", "@tsconfig/node20": "^20.1.4",

View file

@ -2,29 +2,51 @@
import { PhX, PhXCircle } from '@phosphor-icons/vue' import { PhX, PhXCircle } from '@phosphor-icons/vue'
import { onMounted, ref } from 'vue' import { onMounted, ref } from 'vue'
const emit = defineEmits(['input']) const props = defineProps({
const data = ref({}) data: {
type: Object,
onMounted(() => { default: {
data.value = { label: 'Пустой Вопрос',
label: null,
description: null, description: null,
question_type: 1, question_type: 1,
required: false, required: false,
validator: null, validator: null,
min_length: null, min_length: null,
max_length: null max_length: null,
options: [],
min_values: null,
max_values: null,
min_value: 1,
max_value: 5,
min_label: null,
max_label: null
} }
}
})
const emit = defineEmits(['input'])
const data = ref({})
onMounted(() => {
data.value = { ...props.data }
}) })
async function submitForm() { async function submitForm() {
if (data.value.question_type === 1 && data.value.validator === null) { if (data.value.question_type === 1) {
if (data.value.min_length !== null && data.value.min_length < 0) return if (data.value.min_length !== null && data.value.min_length < 0) return
if (data.value.max_length !== null) { if (data.value.max_length !== null) {
if (data.value.max_length <= 0) return if (data.value.max_length <= 0) return
if (data.value.min_length !== null && data.value.max_length < data.value.min_length) return if (data.value.min_length !== null && data.value.max_length < data.value.min_length) return
} }
} }
if (data.value.question_type === 2) {
if (data.value.options.length < 1) return
if (data.value.min_values && data.value.min_values < 1) return
if (data.value.max_values && data.value.min_values > data.value.max_values) return
}
if (data.value.question_type === 3) {
if (!(data.value.min_value in [0, 1])) return
if (data.value.max_value < 2 || data.value.max_value > 10) return
}
emit('input', data.value) emit('input', data.value)
} }
@ -79,6 +101,61 @@ async function submitForm() {
</div> </div>
</div> </div>
</div> </div>
<div class="" v-if="data.question_type === 2">
<div class="">
<div class="">
<p>Варианты</p>
<ul>
<li v-for="(option, index) in data.options">
<input v-model="data.options[index].label" />
<span @click="data.options.splice(index, 1)">X</span>
</li>
<li>
<span
style="text-decoration: underline dashed"
@click="data.options.push({ label: 'Вариант' })"
>Добавить вариант</span
>
</li>
</ul>
</div>
<div class="">
<p>Минимум значений</p>
<input v-model="data.min_values" type="number" placeholder="1" />
</div>
<div class="">
<p>Максимум значений</p>
<input v-model="data.max_values" type="number" />
</div>
</div>
</div>
<div class="" v-if="data.question_type === 3">
<div class="">
<div class="">
<div class="">
<p>
От
<select required v-model="data.min_value">
<option :value="0">0</option>
<option :value="1">1</option>
</select>
до
<select required v-model="data.max_value">
<option v-for="value in 9" :value="1 + value">{{ 1 + value }}</option>
</select>
</p>
</div>
</div>
<div class="">
<p>{{ data.min_value }}</p>
<input v-model="data.min_label" />
</div>
<div class="">
<p>{{ data.max_value }}</p>
<input v-model="data.max_label" />
</div>
</div>
</div>
</div> </div>
<div class=""> <div class="">
<p>Обязательный?</p> <p>Обязательный?</p>
@ -87,7 +164,7 @@ async function submitForm() {
<span class="slider"></span> <span class="slider"></span>
</label> </label>
</div> </div>
<button type="submit">Сохранить</button> <button>Сохранить</button>
</form> </form>
</div> </div>
</div> </div>

View file

@ -1,27 +1,53 @@
<script setup lang="ts"> <script setup lang="ts">
import QuestionEdit from '@/components/edit/QuestionEdit.vue' import QuestionEdit from '@/components/edit/QuestionEdit.vue'
import { ref } from 'vue' import { ref } from 'vue'
import draggable from 'vuedraggable'
const questions = ref([]) const pages = ref([
{ text: 'Тестовый текст 1', questions: [] },
{ text: 'лоре ипсум долор сит амет', questions: [] }
])
const showDialog = ref(false) const showDialog = ref(false)
function addNewQuestion(event: any) {
pages.value[pages.value.length - 1].questions.push(event)
showDialog.value = false
}
</script> </script>
<template> <template>
<QuestionEdit <QuestionEdit v-if="showDialog" @input="addNewQuestion($event)" />
v-if="showDialog"
@input="
questions.push($event)
showDialog = false
"
/>
<div class=""> <div class="">
<button @click="showDialog = true">Создать</button> <button @click="showDialog = true">Создать</button>
<button>Сохранить</button> <button>Сохранить</button>
<button>Превью</button> <button>Превью</button>
</div> </div>
<div class=""> <div>
{{ questions }} <div v-for="(page, index) in pages">
<div>
<h3>Страница {{ index + 1 }}</h3>
<p>{{ page.text }}</p>
</div>
<hr />
<draggable group="questions" :list="page.questions">
<template #item="{ element }">
<div style="cursor: pointer">{{ element.label }}</div>
</template>
</draggable>
</div>
</div> </div>
</template> </template>
<style scoped lang="scss"></style> <style scoped lang="scss">
.drop-zone {
background-color: #eee;
margin-bottom: 10px;
padding: 10px;
}
.drag-el {
background-color: #fff;
margin-bottom: 10px;
padding: 5px;
}
</style>