Transferred and translated the frontend code from L10 to L12
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run

This commit is contained in:
2025-05-05 19:01:27 +02:00
parent 98205954c3
commit e15d3ae146
96 changed files with 6398 additions and 701 deletions
@@ -0,0 +1,89 @@
<script setup>
import { onMounted, defineProps } from 'vue';
import { initFlowbite } from 'flowbite';
onMounted(() => {
initFlowbite();
});
const props = defineProps({
block: {
type: Object,
required: true,
},
});
const firstColumn = props.block.firstcolumn || [
{ text: 'Vårt samhold styrkes gjennom regelmessige arrangementer, med månedlige lokale turneringer og kvartalsvise vennskapsspill mot naboklubber.', style: 'heading' },
{ text: 'Hvert år arrangerer ENHET også en spennende utenlandstur hvor våre lag får utfordre internasjonale motstandere og oppleve nye kulturer. Bli med og opplev spenningen ved å representere ENHET både hjemme og på turer.', style: 'heading' },
{ text: 'Fotball er mer enn et spill; det er en verdensomspennende lidenskap som lærer oss verdien av lagarbeid og fair play. Som den mest populære sporten i verden, bringer fotball sammen mennesker fra alle livets hjørner, og bygger broer på tvers av kulturelle og språklige barrierer.', style: 'regular' },
{ text: 'Denne vakre sporten er en fest for fysisk dyktighet og strategisk tenkning, hvor spenningen på banen kun er matchet av fansens entusiasme. Fra spennende lokale kamper til den elektriske atmosfæren ved verdensmesterskapet, fotball tilbyr en unik kilde til glede og fellesskapsfølelse', style: 'regular' }
];
const secondColumn = props.block.secondcolumn || [
{ text: 'Bli med på våre ukentlige treninger, strategiseminarer og veldedighetsaktiviteter som styrker både kropp og fellesskap.', style: 'headingbold' },
{ text: 'Og trenger du utstyr har vi har et bredt spekter av fotballrelatert utstyr tilgjengelig for våre medlemmer, for å sikre at alle har det de trenger for å spille sitt beste.', style: 'regular' },
{ text: 'Hvordan begynne? Å starte med fotball har aldri vært enklere. Kom til en åpen trening eller kontakt oss for en prat om hvordan du kan bli en del av ENHET. Alt du trenger for å starte er et par fotballsko og et ønske om å lære. Vi tar oss av resten – fra drakter til treningsutstyr.', style: 'regular' }
];
</script>
<template>
<section class="mx-auto max-w-[1280px] bg-black">
<div class="grid gap-8 grid-cols-1 md:grid-cols-2 p-6">
<div class="max-w-2xl text-gray-200">
<template v-for="(paragraph, index) in firstColumn" :index="index">
<h1 v-if="paragraph.style === 'headinglarge'" class="text-gray-500 text-2xl md:text-4xl font-arctic">
{{ paragraph.text || '' }}
</h1>
<h2 v-if="paragraph.style === 'headingbold'" class="text-gray-500 text-xl md:text-2xl font-arctic mt-4">
{{ paragraph.text || '' }}
</h2>
<h3 v-else-if="paragraph.style === 'heading'" class="text-amber-600 text-xl md:text-2xl font-serif mt-1">
{{ paragraph.text || '' }}
</h3>
<p v-else-if="paragraph.style === 'regular'" class="mt-2">
{{ paragraph.text || '' }}
</p>
<iframe
v-else-if="paragraph.style === 'video'"
class="mt-6 w-72 h-72 md:w-96 md:h-96 lg:w-[560px] lg:h-[315px]"
:src="paragraph.text"
title="YouTube video spiller"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
>
</iframe>
</template>
</div>
<div class="max-w-2xl text-gray-200">
<template v-for="(paragraph, index) in secondColumn" :index="index">
<h1 v-if="paragraph.style === 'headinglarge'" class="text-gray-500 text-2xl md:text-4xl font-arctic">
{{ paragraph.text || '' }}
</h1>
<h2 v-if="paragraph.style === 'headingbold'" class="text-gray-500 text-xl md:text-2xl font-arctic mt-4">
{{ paragraph.text || '' }}
</h2>
<h3 v-else-if="paragraph.style === 'heading'" class="text-amber-600 text-xl md:text-2xl font-serif mt-1">
{{ paragraph.text || '' }}
</h3>
<p v-else-if="paragraph.style === 'regular'" class="mt-2">
{{ paragraph.text || '' }}
</p>
<iframe
v-else-if="paragraph.style === 'video'"
class="mt-6 w-72 h-72 md:w-96 md:h-96 lg:w-[560px] lg:h-[315px]"
:src="paragraph.text"
title="YouTube video spiller"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
>
</iframe>
</template>
</div>
</div>
</section>
</template>
@@ -0,0 +1,213 @@
<script setup>
import Icon from '@/Components/Icon.vue';
import { toRef, ref, onMounted } from 'vue';
import { initFlowbite } from 'flowbite';
onMounted(() => {
initFlowbite();
});
const props = defineProps({
block: {
type: Object,
required: true,
},
});
const emit = defineEmits(['update:block']);
const local = toRef(props, 'block');
// Drag state first column
const firstDraggedIndex = ref(null);
function handleDragStartPFirst(event, index) {
firstDraggedIndex.value = index;
event.dataTransfer.effectAllowed = 'move';
event.dataTransfer.setData('text/plain', index);
};
function handleDragOverPFirst(event) {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
};
function handleDropPFirst(event, index) {
event.preventDefault();
const fromIndex = firstDraggedIndex.value;
if (fromIndex === null || fromIndex === index) return;
const item = local.value.firstcolumn.splice(fromIndex, 1)[0];
local.value.firstcolumn.splice(index, 0, item);
firstDraggedIndex.value = null;
};
function addPFirst() {
local.value.firstcolumn.push({
text: '',
style: 'regular',
});
}
function removePFirst(index) {
local.value.firstcolumn.splice(index, 1);
};
// Drag state second column
const secondDraggedIndex = ref(null);
function handleDragStartPSecond(event, index) {
secondDraggedIndex.value = index;
event.dataTransfer.effectAllowed = 'move';
event.dataTransfer.setData('text/plain', index);
};
function handleDragOverPSecond(event) {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
};
function handleDropPSecond(event, index) {
event.preventDefault();
const fromIndex = secondDraggedIndex.value;
if (fromIndex === null || fromIndex === index) return;
const item = local.value.secondcolumn.splice(fromIndex, 1)[0];
local.value.secondcolumn.splice(index, 0, item);
secondDraggedIndex.value = null;
};
function addPSecond() {
local.value.secondcolumn.push({
text: '',
style: 'regular',
});
}
function removePSecond(index) {
local.value.secondcolumn.splice(index, 1);
}
</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">Anker navn (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="space-y-4">
<h3 class="font-bold text-sm text-gray-800 dark:text-white">
Venstre kolonne
</h3>
</div>
<div class="space-y-4">
<div
v-for="(paragraph, index) in local.firstcolumn"
: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="handleDragStartPFirst($event, index)"
@dragover="handleDragOverPFirst"
@drop="handleDropPFirst($event, index)"
>
<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">Paragraf {{ index + 1 }}</span>
<button @click="removePFirst(index)" class="text-red-500 hover:underline text-xs">Fjern</button>
</div>
<div class="mb-2">
<label :for="`style-l-${index}`" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Velg en tekststil</label>
<select
:id="`style-l-${index}`"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
v-model="paragraph.style"
>
<option value="headinglarge">Stor overskrift</option>
<option value="heading">Overskrift</option>
<option value="headingbold">Fet overskrift</option>
<option value="regular">Vanlig</option>
<option value="video">Video</option>
</select>
</div>
<div>
<label class="block text-xs font-medium text-gray-600 dark:text-gray-400">Tekst/Innhold</label>
<textarea rows="2" 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="paragraph.text"></textarea>
</div>
</div>
</div>
</div>
<button @click="addPFirst" class="mt-2 px-4 py-2 bg-blue-600 text-white text-sm rounded hover:bg-blue-700">
Legg til ny paragraf
</button>
<div class="space-y-4">
<h3 class="font-bold text-sm text-gray-800 dark:text-white">
Høyre kolonne
</h3>
</div>
<div class="space-y-4">
<div
v-for="(paragraph, index) in local.secondcolumn"
: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="handleDragStartPSecond($event, index)"
@dragover="handleDragOverPSecond"
@drop="handleDropPSecond($event, index)"
>
<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">Paragraf {{ index + 1 }}</span>
<button @click="removePSecond(index)" class="text-red-500 hover:underline text-xs">Fjern</button>
</div>
<div class="mb-2">
<label :for="`style-r-${index}`" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Velg en tekststil</label>
<select
:id="`style-r-${index}`"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
v-model="paragraph.style"
>
<option value="headinglarge">Stor overskrift</option>
<option value="heading">Overskrift</option>
<option value="headingbold">Fet overskrift</option>
<option value="regular">Vanlig</option>
<option value="video">Video</option>
</select>
</div>
<div>
<label class="block text-xs font-medium text-gray-600 dark:text-gray-400">Tekst/Innhold</label>
<textarea rows="2" 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="paragraph.text"></textarea>
</div>
</div>
</div>
</div>
<button @click="addPSecond" class="mt-2 px-4 py-2 bg-blue-600 text-white text-sm rounded hover:bg-blue-700">
Legg til ny paragraf
</button>
</div>
</template>
<style scoped>
</style>
@@ -0,0 +1,89 @@
<script setup>
import { onMounted, defineProps } from 'vue';
import { initFlowbite } from 'flowbite';
onMounted(() => {
initFlowbite();
});
const props = defineProps({
block: {
type: Object,
required: true,
},
});
const firstColumn = props.block.firstcolumn || [
{ text: 'Vårt samhold styrkes gjennom regelmessige arrangementer, med månedlige lokale turneringer og kvartalsvise vennskapsspill mot naboklubber.', style: 'heading' },
{ text: 'Hvert år arrangerer ENHET også en spennende utenlandstur hvor våre lag får utfordre internasjonale motstandere og oppleve nye kulturer. Bli med og opplev spenningen ved å representere ENHET både hjemme og på turer.', style: 'heading' },
{ text: 'Fotball er mer enn et spill; det er en verdensomspennende lidenskap som lærer oss verdien av lagarbeid og fair play. Som den mest populære sporten i verden, bringer fotball sammen mennesker fra alle livets hjørner, og bygger broer på tvers av kulturelle og språklige barrierer.', style: 'regular' },
{ text: 'Denne vakre sporten er en fest for fysisk dyktighet og strategisk tenkning, hvor spenningen på banen kun er matchet av fansens entusiasme. Fra spennende lokale kamper til den elektriske atmosfæren ved verdensmesterskapet, fotball tilbyr en unik kilde til glede og fellesskapsfølelse', style: 'regular' }
];
const secondColumn = props.block.secondcolumn || [
{ text: 'Bli med på våre ukentlige treninger, strategiseminarer og veldedighetsaktiviteter som styrker både kropp og fellesskap.', style: 'headingbold' },
{ text: 'Og trenger du utstyr har vi har et bredt spekter av fotballrelatert utstyr tilgjengelig for våre medlemmer, for å sikre at alle har det de trenger for å spille sitt beste.', style: 'regular' },
{ text: 'Hvordan begynne? Å starte med fotball har aldri vært enklere. Kom til en åpen trening eller kontakt oss for en prat om hvordan du kan bli en del av ENHET. Alt du trenger for å starte er et par fotballsko og et ønske om å lære. Vi tar oss av resten – fra drakter til treningsutstyr.', style: 'regular' }
];
</script>
<template>
<section :id="block.anchorName" class="mx-auto max-w-[1280px] bg-black">
<div class="grid gap-8 grid-cols-1 md:grid-cols-2 p-6">
<div class="max-w-2xl text-gray-200">
<template v-for="(paragraph, index) in firstColumn" :index="index">
<h1 v-if="paragraph.style === 'headinglarge'" class="text-gray-500 text-2xl md:text-4xl font-arctic">
{{ paragraph.text || '' }}
</h1>
<h2 v-if="paragraph.style === 'headingbold'" class="text-gray-500 text-xl md:text-2xl font-arctic mt-4">
{{ paragraph.text || '' }}
</h2>
<h3 v-else-if="paragraph.style === 'heading'" class="text-amber-600 text-xl md:text-2xl font-serif mt-1">
{{ paragraph.text || '' }}
</h3>
<p v-else-if="paragraph.style === 'regular'" class="mt-2">
{{ paragraph.text || '' }}
</p>
<iframe
v-else-if="paragraph.style === 'video'"
class="mt-6 w-72 h-72 md:w-96 md:h-96 lg:w-[560px] lg:h-[315px]"
:src="paragraph.text"
title="YouTube video spiller"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
>
</iframe>
</template>
</div>
<div class="max-w-2xl text-gray-200">
<template v-for="(paragraph, index) in secondColumn" :index="index">
<h1 v-if="paragraph.style === 'headinglarge'" class="text-gray-500 text-2xl md:text-4xl font-arctic">
{{ paragraph.text || '' }}
</h1>
<h2 v-if="paragraph.style === 'headingbold'" class="text-gray-500 text-xl md:text-2xl font-arctic mt-4">
{{ paragraph.text || '' }}
</h2>
<h3 v-else-if="paragraph.style === 'heading'" class="text-amber-600 text-xl md:text-2xl font-serif mt-1">
{{ paragraph.text || '' }}
</h3>
<p v-else-if="paragraph.style === 'regular'" class="mt-2">
{{ paragraph.text || '' }}
</p>
<iframe
v-else-if="paragraph.style === 'video'"
class="mt-6 w-72 h-72 md:w-96 md:h-96 lg:w-[560px] lg:h-[315px]"
:src="paragraph.text"
title="YouTube video spiller"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
>
</iframe>
</template>
</div>
</div>
</section>
</template>