polarpress-pagebuilder/resources/js/components/Blocks/FAQ/FAQCondensedOptions.vue
Helge-Mikael Nordgård e15d3ae146
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
Transferred and translated the frontend code from L10 to L12
2025-05-05 19:01:27 +02:00

286 lines
13 KiB
Vue

<script setup>
import Icon from '@/Components/Icon.vue'
import { ref, toRef, watch } from 'vue';
const props = defineProps({
block: { type: Object, required: true }
});
const emit = defineEmits(['update:block']);
const local = toRef(props, 'block');
const collapsedCategories = ref([]);
watch(local, (val) => {
emit('update:block', val);
}, { deep: true });
watch(() => local.value.faqs, (faqs) => {
if (collapsedCategories.value.length !== faqs.length) {
collapsedCategories.value = faqs.map((_, i) =>
collapsedCategories.value[i] ?? true
);
}
}, { immediate: true, deep: true });
function toggleCategoryCollapse(index) {
collapsedCategories.value[index] = !collapsedCategories.value[index];
};
// Drag state for categories
const draggedCategoryIndex = ref(null);
function handleDragStartCategory(event, index) {
draggedCategoryIndex.value = index;
event.dataTransfer.effectAllowed = 'move';
event.dataTransfer.setData('text/plain', index);
};
function handleDragOverCategory(event) {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
};
function handleDropCategory(event, index) {
event.preventDefault();
const fromIndex = draggedCategoryIndex.value;
if (fromIndex === null || fromIndex === index) return;
const item = local.value.faqs.splice(fromIndex, 1)[0];
local.value.faqs.splice(index, 0, item);
draggedCategoryIndex.value = null;
};
// End drag state categories
// Add and remove questions
function addFaqCategory() {
local.value.faqs = local.value.faqs || [];
local.value.faqs.push({ categoryName: '', categoryContent: [{}] });
};
function removeFaqCategory(index) {
local.value.faqs.splice(index, 1);
};
// End add and remove categories
// Drag state for questions & answers
const draggedQAIndex = ref(null);
const draggedCategoryForQA = ref(null);
function handleDragStartQA(event, indexQA, categoryIndex) {
draggedQAIndex.value = indexQA;
draggedCategoryForQA.value = categoryIndex;
event.dataTransfer.effectAllowed = 'move';
event.dataTransfer.setData('text/plain', indexQA);
}
function handleDragOverQA(event) {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
}
function handleDropQA(event, indexQA, categoryIndex) {
event.preventDefault();
const fromIndex = draggedQAIndex.value;
const fromCategoryIndex = draggedCategoryForQA.value;
if (
fromIndex === null ||
fromCategoryIndex === null ||
(fromIndex === indexQA && fromCategoryIndex === categoryIndex)
) return;
const sourceCategory = local.value.faqs[fromCategoryIndex];
const targetCategory = local.value.faqs[categoryIndex];
const item = sourceCategory.categoryContent.splice(fromIndex, 1)[0];
targetCategory.categoryContent.splice(indexQA, 0, item);
draggedQAIndex.value = null;
draggedCategoryForQA.value = null;
}
// End drag state for questions & answers
// Add and remove questions & answers
function addQA(categoryIndex) {
local.value.faqs[categoryIndex].categoryContent.push({ question: '', answer: '', state: false });
}
function removeQA(indexQA, categoryIndex) {
local.value.faqs[categoryIndex].categoryContent.splice(indexQA, 1);
}
// End add and remove
</script>
<template>
<div class="space-y-4">
<div class="mb-2">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">DOM ID</label>
<input
type="text"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:text-white"
v-model="local.anchorName"
/>
</div>
<div class="mb-2">
<div class="flex">
<div class="flex items-center h-5">
<input
id="label-checkbox"
aria-describedby="label-checkbox-text"
type="checkbox"
v-model="local.showlabel"
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-sm focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
>
</div>
<div class="ms-2 text-sm">
<label for="label-checkbox" class="font-medium text-gray-900 dark:text-gray-300">Vis merkelapp</label>
<p id="label-checkbox-text" class="text-xs font-normal text-gray-500 dark:text-gray-300">Skru merkelappen øverst på komponenten av, eller på</p>
</div>
</div>
</div>
<div class="mb-2">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Merkelapp tekst</label>
<input
type="text"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:text-white"
v-model="local.label"
:disabled="!local.showlabel"
/>
</div>
<div class="mb-2">
<div class="flex">
<div class="flex items-center h-5">
<input
id="title-checkbox"
aria-describedby="title-checkbox-text"
type="checkbox"
v-model="local.showtitle"
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-sm focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
>
</div>
<div class="ms-2 text-sm">
<label for="title-checkbox" class="font-medium text-gray-900 dark:text-gray-300">Vis tittel</label>
<p id="title-checkbox-text" class="text-xs font-normal text-gray-500 dark:text-gray-300">Skru tittelen på komponenten av, eller på</p>
</div>
</div>
</div>
<div class="mb-2">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Tittel tekst</label>
<input
type="text"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:text-white"
v-model="local.title"
:disabled="!local.showtitle"
/>
</div>
<div class="mb-2">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Tittel kursiv tekst</label>
<input
type="text"
class="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:text-white"
v-model="local.titlecursive"
:disabled="!local.showtitle"
/>
</div>
<div class="space-y-4">
<div
v-for="(faq, index) in local.faqs"
:key="index"
class="flex items-start gap-2 p-4 rounded border dark:border-gray-600 bg-gray-50 dark:bg-gray-800"
draggable="true"
@dragstart="handleDragStartCategory($event, index)"
@dragover="handleDragOverCategory"
@drop="handleDropCategory($event, index)"
>
<!-- Drag handle -->
<div class="cursor-move mt-1 text-gray-500 dark:text-gray-400">
<Icon name="move" class="w-4 h-4" />
</div>
<!-- Content -->
<div class="flex-1 space-y-2">
<div class="flex justify-between items-center">
<span class="text-sm font-semibold text-gray-700 dark:text-gray-300">FAQ Kategori {{ index + 1 }}</span>
<div class="flex items-center gap-2">
<button
@click="toggleCategoryCollapse(index)"
class="text-blue-500 text-xs hover:underline"
>
{{ collapsedCategories[index] ? 'Vis' : 'Skjul' }}
</button>
<button @click="removeFaqCategory(index)" class="text-red-500 hover:underline text-xs">
Fjern
</button>
</div>
</div>
<div class="mb-2">
<label class="block text-xs font-medium text-gray-600 dark:text-gray-400">Kategori tittel</label>
<input type="text" class="block w-full rounded-md border-gray-300 dark:border-gray-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:text-white" v-model="faq.categoryName" />
</div>
<div v-show="!collapsedCategories[index]">
<h5 class="text-xs font-semibold text-gray-600 dark:text-gray-400">Spørsmål & Svar</h5>
<div
v-for="(qa, indexQA) in faq.categoryContent"
:key="indexQA"
class="flex items-start mt-2 gap-2 p-4 rounded border dark:border-gray-600 bg-gray-50 dark:bg-gray-800"
draggable="true"
@dragstart="handleDragStartQA($event, indexQA, index)"
@dragover="handleDragOverQA"
@drop="handleDropQA($event, indexQA, index)"
>
<!-- Drag handle -->
<div class="cursor-move mt-1 text-gray-500 dark:text-gray-400">
<Icon name="move" class="w-4 h-4" />
</div>
<div class="flex-1 space-y-2">
<div class="flex justify-between items-center">
<span class="text-sm font-semibold text-gray-700 dark:text-gray-300">"{{ faq.categoryName }}" spørsmål {{ indexQA + 1 }}</span>
<button @click="removeQA(indexQA, index)" class="text-red-500 hover:underline text-xs">Fjern</button>
</div>
<div class="mb-2">
<label class="block text-xs font-medium text-gray-600 dark:text-gray-400">Spørsmål</label>
<input
type="text"
v-model="qa.question"
class="block w-full rounded-md border-gray-300 dark:border-gray-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:text-white"
/>
</div>
<div class="mb-2">
<label class="block text-xs font-medium text-gray-600 dark:text-gray-400">Svar</label>
<textarea
rows="3"
v-model="qa.answer"
class="block w-full rounded-md border-gray-300 dark:border-gray-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-800 dark:text-white"
></textarea>
</div>
</div>
</div>
<button
@click="addQA(index)"
class="mt-2 px-3 py-1 bg-green-600 text-white text-xs rounded hover:bg-green-700"
>
Legg til spørsmål & svar
</button>
</div>
</div>
</div>
<button @click="addFaqCategory" class="mt-2 px-4 py-2 bg-blue-600 text-white text-sm rounded hover:bg-blue-700">
Legg til ny kategori
</button>
</div>
</div>
</template>