ready check
This commit is contained in:
parent
f929763892
commit
aa1203bff8
66
components/BackToTopBtn.vue
Normal file
66
components/BackToTopBtn.vue
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<template>
|
||||||
|
<transition name="fade">
|
||||||
|
<button class="back-to-top" v-show="isVisible" @click="scrollToTop" aria-label="Zurück nach oben">
|
||||||
|
<span class="arrow-up"></span>
|
||||||
|
</button>
|
||||||
|
</transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, onUnmounted } from 'vue'
|
||||||
|
|
||||||
|
const isVisible = ref(false)
|
||||||
|
|
||||||
|
const toggleVisibility = () => {
|
||||||
|
isVisible.value = window.scrollY > 100
|
||||||
|
}
|
||||||
|
|
||||||
|
const scrollToTop = () => {
|
||||||
|
window.scrollTo({ top: 0, behavior: 'smooth' })
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
window.addEventListener('scroll', toggleVisibility)
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener('scroll', toggleVisibility)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="sass">
|
||||||
|
.back-to-top
|
||||||
|
position: fixed
|
||||||
|
bottom: 2rem
|
||||||
|
left: 2rem
|
||||||
|
background-color: rgba($darkgrey, .95)
|
||||||
|
border: 1px solid white
|
||||||
|
z-index: 100
|
||||||
|
border-radius: 50%
|
||||||
|
width: 3rem
|
||||||
|
height: 3rem
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
justify-content: center
|
||||||
|
cursor: pointer
|
||||||
|
transition: opacity 0.4s ease-in-out
|
||||||
|
opacity: 0.8
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
opacity: 1
|
||||||
|
|
||||||
|
.arrow-up
|
||||||
|
width: 0
|
||||||
|
height: 0
|
||||||
|
border-left: 8px solid transparent
|
||||||
|
border-right: 8px solid transparent
|
||||||
|
border-bottom: 12px solid white
|
||||||
|
|
||||||
|
// Transition für den Button
|
||||||
|
.fade-enter-active, .fade-leave-active
|
||||||
|
transition: opacity 0.4s ease-in-out
|
||||||
|
|
||||||
|
.fade-enter-from, .fade-leave-to
|
||||||
|
opacity: 0
|
||||||
|
</style>
|
||||||
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="languageBox" @click="toggleOpen">
|
<div class="languageBox" v-if="locales.length >=2" @click="toggleOpen">
|
||||||
<div v-if="!open" class="current">{{ currentLanguage }}</div>
|
<div v-if="!open" class="current">{{ currentLanguage }}</div>
|
||||||
|
|
||||||
<transition name="slide">
|
<transition name="slide">
|
||||||
|
|||||||
50
components/PageContent.vue
Normal file
50
components/PageContent.vue
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<template>
|
||||||
|
<section class="topSpace" v-if="currentPage">
|
||||||
|
<div v-if="currentPage.pageSections[0].sectionText">
|
||||||
|
<div class="container content" v-html="htmlContent(currentPage.pageSections[0].sectionText)"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="topSpace" v-else>
|
||||||
|
<h1>Seite nicht gefunden</h1>
|
||||||
|
<p>Die angeforderte Seite existiert nicht.</p>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useMainStore } from '@/stores/main';
|
||||||
|
import { useHtmlConverter } from '@/composables/useHTMLConverter';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const mainStore = useMainStore();
|
||||||
|
const { convertToHTML } = useHtmlConverter();
|
||||||
|
|
||||||
|
// Aktuelle Seite über Getter und Route
|
||||||
|
const currentPage = computed(() => mainStore.getPageByLink(route.path));
|
||||||
|
|
||||||
|
// HTML-Konvertierung
|
||||||
|
const htmlContent = (data) => convertToHTML(data);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="sass">
|
||||||
|
section:first-of-type::before
|
||||||
|
top: 0
|
||||||
|
left: 0
|
||||||
|
width: 10vw
|
||||||
|
|
||||||
|
.content
|
||||||
|
h2
|
||||||
|
font-size: 1.1rem
|
||||||
|
font-family: 'Mainfont-Bold'
|
||||||
|
margin: 1rem 0
|
||||||
|
h3
|
||||||
|
font-size: 1rem
|
||||||
|
font-family: 'Mainfont-Bold'
|
||||||
|
margin: .6rem 0
|
||||||
|
p
|
||||||
|
font-size: 1rem
|
||||||
|
margin: .5rem auto
|
||||||
|
</style>
|
||||||
|
|
||||||
147
components/Recommendations.vue
Normal file
147
components/Recommendations.vue
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<template>
|
||||||
|
<section class="recommendations">
|
||||||
|
<!-- Vor dem Container: Welle oben -->
|
||||||
|
<svg class="sectionWave wave-top" :style="`height: ${waveHeight};top:-${waveHeight-2}`" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 20">
|
||||||
|
<path d="M 0 0 L 500 0 L 500 14 Q 354.4 -2.8 250 11 Q 145.6 24.8 0 14 L 0 0 Z" fill="#EEEBE5"></path>
|
||||||
|
</svg>
|
||||||
|
<div class="container">
|
||||||
|
<h2>Das sagen andere Designer und Kreative über digimedialoop</h2>
|
||||||
|
<div class="personBox" v-for="person, index in persons" :key="index" :class="person.active ? 'active' : ''" @click="setActive(index)">
|
||||||
|
<img :src="person.image" alt="">
|
||||||
|
<div class="infoBox">
|
||||||
|
<h3>{{ person.name }}</h3>
|
||||||
|
<q>{{ person.quote }}</q>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Nach dem Container: Spiegelwelle unten -->
|
||||||
|
<svg class="sectionWave wave-bottom" :style="`height: ${waveHeight};bottom:-${waveHeight-2}`" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 20">
|
||||||
|
<path d="M 0 0 L 500 0 L 500 14 Q 354.4 -2.8 250 11 Q 145.6 24.8 0 14 L 0 0 Z" fill="#EEEBE5"></path>
|
||||||
|
</svg>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useMainStore } from '@/stores/main';
|
||||||
|
const mainStore = useMainStore();
|
||||||
|
|
||||||
|
const screenWidth = computed(() => mainStore.screenWidth);
|
||||||
|
const waveHeight = computed(() => (screenWidth.value / 25).toFixed(0));
|
||||||
|
|
||||||
|
const persons = ref([
|
||||||
|
{
|
||||||
|
name: 'Nadine Mattern',
|
||||||
|
quote: 'Fachlich wirklich kompetent, die Ruhe selbst (auch bei knappen Deadlines) und absolut angenehme und verlässliche Zusammenarbeit. Gerne jederzeit wieder für ein nächstes Projekt. Ich kann Sabrina wärmstens weiter empfehlen!',
|
||||||
|
image: 'https://strapi.digimedialoop.de/uploads/Nadine_Matterns_2b5c0500a3.jpeg',
|
||||||
|
active: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Anna Liebel',
|
||||||
|
quote: 'Jeder Mediengestalter sollte einen guten Entwickler im Rücken haben. Sabrina ist meine Wahl, wenn es technisch knifflig wird.',
|
||||||
|
image: 'https://strapi.digimedialoop.de/uploads/Anna_Liebel_8fb67e4a86.jpg',
|
||||||
|
active: false
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// Methode zum Setzen der aktiven Person mit Verzögerung
|
||||||
|
const setActive = (index) => {
|
||||||
|
// Alle Personen auf inactive setzen
|
||||||
|
persons.value.forEach((person) => {
|
||||||
|
person.active = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Nach 0,5 Sekunden die gewählte Person aktiv setzen
|
||||||
|
setTimeout(() => {
|
||||||
|
persons.value[index].active = true;
|
||||||
|
}, 200); // 500 Millisekunden warten
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="sass">
|
||||||
|
.recommendations
|
||||||
|
background-color: $beige
|
||||||
|
padding: .5rem 0 6rem 0
|
||||||
|
margin: 6rem auto !important
|
||||||
|
position: relative
|
||||||
|
|
||||||
|
/* Welle oben */
|
||||||
|
.sectionWave.wave-top
|
||||||
|
position: absolute
|
||||||
|
left: 0
|
||||||
|
width: 100%
|
||||||
|
z-index:1
|
||||||
|
transform: scaley(-1) /* Spiegeln der oberen Welle */
|
||||||
|
|
||||||
|
/* Welle unten */
|
||||||
|
.sectionWave.wave-bottom
|
||||||
|
position: absolute
|
||||||
|
left: 0
|
||||||
|
width: 100%
|
||||||
|
z-index: 1
|
||||||
|
transform: scaleX(1) /* Die untere Welle wird nicht gespiegelt */
|
||||||
|
|
||||||
|
h2
|
||||||
|
font-size: 1.2rem
|
||||||
|
font-family: 'Mainfont-Bold'
|
||||||
|
color: darken($pink, 10%)
|
||||||
|
|
||||||
|
.personBox
|
||||||
|
display: inline-block
|
||||||
|
margin: 0 3rem 2rem 0
|
||||||
|
width: 100px
|
||||||
|
transition: .3s
|
||||||
|
position: relative
|
||||||
|
cursor: pointer
|
||||||
|
animation: bubble-wobble 12s infinite ease alternate, gradient-animation 15s infinite alternate ease-in-out
|
||||||
|
z-index: 3
|
||||||
|
|
||||||
|
.infoBox
|
||||||
|
display: none
|
||||||
|
|
||||||
|
img
|
||||||
|
width: 100%
|
||||||
|
border-radius: 50%
|
||||||
|
border: 6px solid rgba(white, .4)
|
||||||
|
z-index: 4
|
||||||
|
box-shadow: $innerShadow
|
||||||
|
|
||||||
|
&.active
|
||||||
|
width: 55%
|
||||||
|
max-width: 260px
|
||||||
|
transition: .8s
|
||||||
|
z-index: 5
|
||||||
|
animation: bubble-wobble 15s infinite ease alternate, gradient-animation 10s infinite alternate ease-in-out
|
||||||
|
|
||||||
|
.infoBox
|
||||||
|
display: block
|
||||||
|
position: absolute
|
||||||
|
top: 70%
|
||||||
|
left: 80%
|
||||||
|
transform: translateX(-50%)
|
||||||
|
background-color: rgba(white, .7)
|
||||||
|
width: 120%
|
||||||
|
max-width: 400px
|
||||||
|
padding: .5rem 1rem 1rem 1rem
|
||||||
|
border-radius: 1rem
|
||||||
|
z-index: 5
|
||||||
|
@media(max-width: $breakPointMD)
|
||||||
|
width: 150%
|
||||||
|
transform: translateX(-30%)
|
||||||
|
|
||||||
|
h3
|
||||||
|
font-size: 1.2rem
|
||||||
|
font-family: 'Mainfont-Bold'
|
||||||
|
margin: 0
|
||||||
|
color: darken($primaryColor, 15%)
|
||||||
|
text-transform: uppercase
|
||||||
|
|
||||||
|
q
|
||||||
|
font-size: .8rem
|
||||||
|
line-height: 1rem
|
||||||
|
font-family: 'Mainfont-Bold'
|
||||||
|
|
||||||
|
</style>
|
||||||
@ -28,6 +28,16 @@ class="closer"
|
|||||||
@click="toggleMenu"
|
@click="toggleMenu"
|
||||||
@keydown.enter="toggleMenu"/>
|
@keydown.enter="toggleMenu"/>
|
||||||
<nav v-if="isMenuOpen || screenWidth > 1350" aria-expanded="true">
|
<nav v-if="isMenuOpen || screenWidth > 1350" aria-expanded="true">
|
||||||
|
<div class="mobilNavLogo" v-if="false">
|
||||||
|
<NuxtImg
|
||||||
|
provider="strapi"
|
||||||
|
src="/uploads/DML_Logo_mint_negative_2024_9257db5430.svg"
|
||||||
|
alt="digimedialoop Logo"
|
||||||
|
width="120"
|
||||||
|
v-if="screenWidth < 1350"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<NuxtLinkLocale
|
<NuxtLinkLocale
|
||||||
v-for="link in navigationLinks"
|
v-for="link in navigationLinks"
|
||||||
:key="link.routeKey"
|
:key="link.routeKey"
|
||||||
@ -310,6 +320,7 @@ header
|
|||||||
border-bottom-right-radius: 0
|
border-bottom-right-radius: 0
|
||||||
background: transparent
|
background: transparent
|
||||||
border: 1px solid transparent
|
border: 1px solid transparent
|
||||||
|
|
||||||
a
|
a
|
||||||
font-size: 1rem
|
font-size: 1rem
|
||||||
font-weight: bold
|
font-weight: bold
|
||||||
@ -320,5 +331,4 @@ header
|
|||||||
margin-bottom: .5rem
|
margin-bottom: .5rem
|
||||||
width: 70%
|
width: 70%
|
||||||
max-width: 200px
|
max-width: 200px
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@ -20,8 +20,14 @@ export function useI18nPages () {
|
|||||||
return path.replace(':link', slug)
|
return path.replace(':link', slug)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getArticleLink = (slug: string) => {
|
||||||
|
const path = getRoute('artikel___link')
|
||||||
|
return path.replace(':link', slug)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getRoute,
|
getRoute,
|
||||||
getProjectLink
|
getProjectLink,
|
||||||
|
getArticleLink
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,6 +49,14 @@ export const i18nPages = {
|
|||||||
tr: '/projekt/:link'
|
tr: '/projekt/:link'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/*designer: {
|
||||||
|
de: '/webentwicklung-fuer-designer-und-mediengestalter',
|
||||||
|
en: '/web-development-for-designers-and-media-creators',
|
||||||
|
fr: '/developpement-web-pour-designers-et-createurs-de-medias',
|
||||||
|
it: '/sviluppo-web-per-designer-e-creativi-multimediali',
|
||||||
|
es: '/desarrollo-web-para-disenadores-y-creadores-de-medios',
|
||||||
|
tr: '/tasarimcilar-ve-medya-uzmanlari-icin-web-gelistirme'
|
||||||
|
},*/
|
||||||
privacy: {
|
privacy: {
|
||||||
de: '/datenschutz',
|
de: '/datenschutz',
|
||||||
en: '/privacy',
|
en: '/privacy',
|
||||||
@ -72,5 +80,15 @@ export const i18nPages = {
|
|||||||
it: '/magazine',
|
it: '/magazine',
|
||||||
es: '/revista',
|
es: '/revista',
|
||||||
tr: '/dergi'
|
tr: '/dergi'
|
||||||
}
|
},
|
||||||
|
'artikel___link': {
|
||||||
|
paths: {
|
||||||
|
de: '/artikel/:link',
|
||||||
|
en: '/artikel/:link',
|
||||||
|
fr: '/artikel/:link',
|
||||||
|
it: '/artikel/:link',
|
||||||
|
es: '/artikel/:link',
|
||||||
|
tr: '/artikel/:link'
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@
|
|||||||
"ariaLabel": "Einleitungsbereich über digitale Lösungen",
|
"ariaLabel": "Einleitungsbereich über digitale Lösungen",
|
||||||
"imageAlt": "Illustration von Programmierung am Ammersee",
|
"imageAlt": "Illustration von Programmierung am Ammersee",
|
||||||
"headline1": "High-Performance-Webseiten",
|
"headline1": "High-Performance-Webseiten",
|
||||||
"headline2": "mit moderner Headless-Architektur",
|
"headline2": "mit Nuxt 3 + Strapi in moderner Headless-Architektur",
|
||||||
"headline3": "Schnell, effizient und leistungsstark!"
|
"headline3": "Schnell, effizient und leistungsstark!"
|
||||||
},
|
},
|
||||||
"explain": {
|
"explain": {
|
||||||
@ -172,6 +172,12 @@
|
|||||||
"text": "Lassen Sie uns gemeinsam Ihre individuelle Website gestalten – perfekt abgestimmt auf Ihre Bedürfnisse und Ziele.",
|
"text": "Lassen Sie uns gemeinsam Ihre individuelle Website gestalten – perfekt abgestimmt auf Ihre Bedürfnisse und Ziele.",
|
||||||
"button": "Jetzt unverbindliches Angebot anfordern!"
|
"button": "Jetzt unverbindliches Angebot anfordern!"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"magazin": {
|
||||||
|
"title": "Wissenswertes rund ums Thema Webseite",
|
||||||
|
"teaser1": "In unserem Wissensbereich zeigen wir, worauf es bei Suchmaschinen-Optimierung, Barrierefreiheit, Webdesign, Webperformance und Online-Marketing ankommt.",
|
||||||
|
"teaser2": "Entdecken Sie aktuelle Trends und praxisnahe Tipps, um Ihre Online-Präsenz gezielt zu stärken.",
|
||||||
|
"readmore": "Artikel lesen"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<PageHeader />
|
<PageHeader />
|
||||||
<ContactForm />
|
<ContactForm />
|
||||||
|
<BackToTopBtn />
|
||||||
<main>
|
<main>
|
||||||
<Breadcrumbs />
|
<Breadcrumbs />
|
||||||
<slot />
|
<slot />
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { defineNuxtConfig } from 'nuxt/config'
|
import { defineNuxtConfig } from 'nuxt/config'
|
||||||
import { i18nPages } from './i18n/i18n-pages'
|
import { i18nPages } from './i18n/i18n-pages'
|
||||||
|
import { getSitemapRoutes } from './server/utils/sitemapData'
|
||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
app: {
|
app: {
|
||||||
@ -42,6 +43,7 @@ export default defineNuxtConfig({
|
|||||||
'@nuxt/eslint',
|
'@nuxt/eslint',
|
||||||
'@pinia/nuxt',
|
'@pinia/nuxt',
|
||||||
'@nuxtjs/i18n',
|
'@nuxtjs/i18n',
|
||||||
|
'@nuxtjs/sitemap',
|
||||||
['@pinia/nuxt', {
|
['@pinia/nuxt', {
|
||||||
autoImports: [
|
autoImports: [
|
||||||
'defineStore',
|
'defineStore',
|
||||||
@ -50,6 +52,14 @@ export default defineNuxtConfig({
|
|||||||
]
|
]
|
||||||
}],
|
}],
|
||||||
],
|
],
|
||||||
|
sitemap: {
|
||||||
|
siteUrl: process.env.APP_URL || 'https://www.digimedialoop.de',
|
||||||
|
trailingSlash: false,
|
||||||
|
i18n: true,
|
||||||
|
async routes() {
|
||||||
|
return await getSitemapRoutes()
|
||||||
|
}
|
||||||
|
},
|
||||||
image: {
|
image: {
|
||||||
debug: true,
|
debug: true,
|
||||||
strapi: {
|
strapi: {
|
||||||
@ -73,13 +83,14 @@ export default defineNuxtConfig({
|
|||||||
i18n: {
|
i18n: {
|
||||||
defaultLocale: 'de',
|
defaultLocale: 'de',
|
||||||
strategy: 'prefix_except_default',
|
strategy: 'prefix_except_default',
|
||||||
|
langDir: 'locales',
|
||||||
locales: [
|
locales: [
|
||||||
{ code: 'de', name: 'Deutsch', file: 'de.json' },
|
{ code: 'de', name: 'Deutsch', file: 'de.json' },
|
||||||
{ code: 'en', name: 'English', file: 'en.json' },
|
/*{ code: 'en', name: 'English', file: 'en.json' },
|
||||||
{ code: 'es', name: 'Español', file: 'es.json' },
|
{ code: 'es', name: 'Español', file: 'es.json' },
|
||||||
{ code: 'fr', name: 'Français', file: 'fr.json' },
|
{ code: 'fr', name: 'Français', file: 'fr.json' },
|
||||||
{ code: 'it', name: 'Italiano', file: 'it.json' },
|
{ code: 'it', name: 'Italiano', file: 'it.json' },
|
||||||
{ code: 'tr', name: 'Türkçe', file: 'tr.json' }
|
{ code: 'tr', name: 'Türkçe', file: 'tr.json' }*/
|
||||||
],
|
],
|
||||||
customRoutes: 'config',
|
customRoutes: 'config',
|
||||||
pages: i18nPages,
|
pages: i18nPages,
|
||||||
|
|||||||
363
package-lock.json
generated
363
package-lock.json
generated
@ -14,6 +14,7 @@
|
|||||||
"@nuxt/scripts": "^0.11.6",
|
"@nuxt/scripts": "^0.11.6",
|
||||||
"@nuxt/ui": "^3.0.2",
|
"@nuxt/ui": "^3.0.2",
|
||||||
"@nuxtjs/i18n": "^9.5.3",
|
"@nuxtjs/i18n": "^9.5.3",
|
||||||
|
"@nuxtjs/sitemap": "^7.3.0",
|
||||||
"@pinia/nuxt": "^0.11.0",
|
"@pinia/nuxt": "^0.11.0",
|
||||||
"nitropack": "^2.11.9",
|
"nitropack": "^2.11.9",
|
||||||
"nuxt": "^3.16.2",
|
"nuxt": "^3.16.2",
|
||||||
@ -3427,6 +3428,151 @@
|
|||||||
"url": "https://github.com/sponsors/bobbiegoede"
|
"url": "https://github.com/sponsors/bobbiegoede"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@nuxtjs/sitemap": {
|
||||||
|
"version": "7.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nuxtjs/sitemap/-/sitemap-7.3.0.tgz",
|
||||||
|
"integrity": "sha512-R3X5hqhWoMXIB4XWQmUuVSGmPFrKTFYFho7pk990si8iayKjSMbBCtTPtHdEscglZukKy4cL7V0WYdDFrUvV5w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@nuxt/devtools-kit": "^2.4.1",
|
||||||
|
"@nuxt/kit": "^3.17.3",
|
||||||
|
"chalk": "^5.4.1",
|
||||||
|
"defu": "^6.1.4",
|
||||||
|
"h3-compression": "^0.3.2",
|
||||||
|
"nuxt-site-config": "^3.2.0",
|
||||||
|
"ofetch": "^1.4.1",
|
||||||
|
"pathe": "^2.0.3",
|
||||||
|
"pkg-types": "^2.1.0",
|
||||||
|
"radix3": "^1.1.2",
|
||||||
|
"semver": "^7.7.2",
|
||||||
|
"sirv": "^3.0.1",
|
||||||
|
"ufo": "^1.6.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/harlan-zw"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@nuxtjs/sitemap/node_modules/@nuxt/devtools-kit": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nuxt/devtools-kit/-/devtools-kit-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-taA2Nm03JiV3I+SEYS/u1AfjvLm3V9PO8lh0xLsUk/2mlUnL6GZ9xLXrp8VRg11HHt7EPXERGQh8h4iSPU2bSQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@nuxt/kit": "^3.17.3",
|
||||||
|
"@nuxt/schema": "^3.17.3",
|
||||||
|
"execa": "^8.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vite": ">=6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@nuxtjs/sitemap/node_modules/@nuxt/kit": {
|
||||||
|
"version": "3.17.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.17.4.tgz",
|
||||||
|
"integrity": "sha512-l+hY8sy2XFfg3PigZj+PTu6+KIJzmbACTRimn1ew/gtCz+F38f6KTF4sMRTN5CUxiB8TRENgEonASmkAWfpO9Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"c12": "^3.0.4",
|
||||||
|
"consola": "^3.4.2",
|
||||||
|
"defu": "^6.1.4",
|
||||||
|
"destr": "^2.0.5",
|
||||||
|
"errx": "^0.1.0",
|
||||||
|
"exsolve": "^1.0.5",
|
||||||
|
"ignore": "^7.0.4",
|
||||||
|
"jiti": "^2.4.2",
|
||||||
|
"klona": "^2.0.6",
|
||||||
|
"knitwork": "^1.2.0",
|
||||||
|
"mlly": "^1.7.4",
|
||||||
|
"ohash": "^2.0.11",
|
||||||
|
"pathe": "^2.0.3",
|
||||||
|
"pkg-types": "^2.1.0",
|
||||||
|
"scule": "^1.3.0",
|
||||||
|
"semver": "^7.7.2",
|
||||||
|
"std-env": "^3.9.0",
|
||||||
|
"tinyglobby": "^0.2.13",
|
||||||
|
"ufo": "^1.6.1",
|
||||||
|
"unctx": "^2.4.1",
|
||||||
|
"unimport": "^5.0.1",
|
||||||
|
"untyped": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@nuxtjs/sitemap/node_modules/@nuxt/schema": {
|
||||||
|
"version": "3.17.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nuxt/schema/-/schema-3.17.4.tgz",
|
||||||
|
"integrity": "sha512-bsfJdWjKNYLkVQt7Ykr9YsAql1u8Tuo6iecSUOltTIhsvAIYsknRFPHoNKNmaiv/L6FgCQgUgQppPTPUAXiJQQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/shared": "^3.5.14",
|
||||||
|
"consola": "^3.4.2",
|
||||||
|
"defu": "^6.1.4",
|
||||||
|
"pathe": "^2.0.3",
|
||||||
|
"std-env": "^3.9.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^14.18.0 || >=16.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@nuxtjs/sitemap/node_modules/@vue/shared": {
|
||||||
|
"version": "3.5.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.15.tgz",
|
||||||
|
"integrity": "sha512-bKvgFJJL1ZX9KxMCTQY6xD9Dhe3nusd1OhyOb1cJYGqvAr0Vg8FIjHPMOEVbJ9GDT9HG+Bjdn4oS8ohKP8EvoA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@nuxtjs/sitemap/node_modules/chalk": {
|
||||||
|
"version": "5.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz",
|
||||||
|
"integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@nuxtjs/sitemap/node_modules/escape-string-regexp": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@nuxtjs/sitemap/node_modules/unimport": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/unimport/-/unimport-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-1YWzPj6wYhtwHE+9LxRlyqP4DiRrhGfJxdtH475im8ktyZXO3jHj/3PZ97zDdvkYoovFdi0K4SKl3a7l92v3sQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"acorn": "^8.14.1",
|
||||||
|
"escape-string-regexp": "^5.0.0",
|
||||||
|
"estree-walker": "^3.0.3",
|
||||||
|
"local-pkg": "^1.1.1",
|
||||||
|
"magic-string": "^0.30.17",
|
||||||
|
"mlly": "^1.7.4",
|
||||||
|
"pathe": "^2.0.3",
|
||||||
|
"picomatch": "^4.0.2",
|
||||||
|
"pkg-types": "^2.1.0",
|
||||||
|
"scule": "^1.3.0",
|
||||||
|
"strip-literal": "^3.0.0",
|
||||||
|
"tinyglobby": "^0.2.13",
|
||||||
|
"unplugin": "^2.3.2",
|
||||||
|
"unplugin-utils": "^0.2.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@oxc-parser/binding-darwin-arm64": {
|
"node_modules/@oxc-parser/binding-darwin-arm64": {
|
||||||
"version": "0.61.2",
|
"version": "0.61.2",
|
||||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.61.2.tgz",
|
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.61.2.tgz",
|
||||||
@ -6650,16 +6796,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/c12": {
|
"node_modules/c12": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/c12/-/c12-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/c12/-/c12-3.0.4.tgz",
|
||||||
"integrity": "sha512-uC3MacKBb0Z15o5QWCHvHWj5Zv34pGQj9P+iXKSpTuSGFS0KKhUWf4t9AJ+gWjYOdmWCPEGpEzm8sS0iqbpo1w==",
|
"integrity": "sha512-t5FaZTYbbCtvxuZq9xxIruYydrAGsJ+8UdP0pZzMiK2xl/gNiSOy0OxhLzHUEEb0m1QXYqfzfvyIFEmz/g9lqg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": "^4.0.3",
|
"chokidar": "^4.0.3",
|
||||||
"confbox": "^0.2.2",
|
"confbox": "^0.2.2",
|
||||||
"defu": "^6.1.4",
|
"defu": "^6.1.4",
|
||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.5.0",
|
||||||
"exsolve": "^1.0.4",
|
"exsolve": "^1.0.5",
|
||||||
"giget": "^2.0.0",
|
"giget": "^2.0.0",
|
||||||
"jiti": "^2.4.2",
|
"jiti": "^2.4.2",
|
||||||
"ohash": "^2.0.11",
|
"ohash": "^2.0.11",
|
||||||
@ -9763,6 +9909,18 @@
|
|||||||
"uncrypto": "^0.1.3"
|
"uncrypto": "^0.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/h3-compression": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/h3-compression/-/h3-compression-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-B+yCKyDRnO0BXSfjAP4tCXJgJwmnKp3GyH5Yh66mY9KuOCrrGQSPk/gBFG2TgH7OyB/6mvqNZ1X0XNVuy0qRsw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/codedredd"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"h3": "^1.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/has-flag": {
|
"node_modules/has-flag": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||||
@ -11952,6 +12110,180 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nuxt-site-config": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nuxt-site-config/-/nuxt-site-config-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-o1LDV+eaiP0qgM97RxoX2ost3mzmNmg5D3BmiORXCD9lx9CR5OZKc7nXI0zGsASk3eSVj4iNp0ctyF6afPFTow==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@nuxt/kit": "^3.17.3",
|
||||||
|
"nuxt-site-config-kit": "3.2.0",
|
||||||
|
"pathe": "^2.0.3",
|
||||||
|
"pkg-types": "^2.1.0",
|
||||||
|
"sirv": "^3.0.1",
|
||||||
|
"site-config-stack": "3.2.0",
|
||||||
|
"ufo": "^1.6.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/harlan-zw"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nuxt-site-config-kit": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nuxt-site-config-kit/-/nuxt-site-config-kit-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-kVBXljR7Py8mz5eL6ZysVMlPRwbVX1Tts66StQRwYSJL/srEL8kr/ZfLW6tQU7pDHihcPH3MDgid2gDTFMY3fg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@nuxt/kit": "^3.17.3",
|
||||||
|
"pkg-types": "^2.1.0",
|
||||||
|
"site-config-stack": "3.2.0",
|
||||||
|
"std-env": "^3.9.0",
|
||||||
|
"ufo": "^1.6.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/harlan-zw"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nuxt-site-config-kit/node_modules/@nuxt/kit": {
|
||||||
|
"version": "3.17.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.17.4.tgz",
|
||||||
|
"integrity": "sha512-l+hY8sy2XFfg3PigZj+PTu6+KIJzmbACTRimn1ew/gtCz+F38f6KTF4sMRTN5CUxiB8TRENgEonASmkAWfpO9Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"c12": "^3.0.4",
|
||||||
|
"consola": "^3.4.2",
|
||||||
|
"defu": "^6.1.4",
|
||||||
|
"destr": "^2.0.5",
|
||||||
|
"errx": "^0.1.0",
|
||||||
|
"exsolve": "^1.0.5",
|
||||||
|
"ignore": "^7.0.4",
|
||||||
|
"jiti": "^2.4.2",
|
||||||
|
"klona": "^2.0.6",
|
||||||
|
"knitwork": "^1.2.0",
|
||||||
|
"mlly": "^1.7.4",
|
||||||
|
"ohash": "^2.0.11",
|
||||||
|
"pathe": "^2.0.3",
|
||||||
|
"pkg-types": "^2.1.0",
|
||||||
|
"scule": "^1.3.0",
|
||||||
|
"semver": "^7.7.2",
|
||||||
|
"std-env": "^3.9.0",
|
||||||
|
"tinyglobby": "^0.2.13",
|
||||||
|
"ufo": "^1.6.1",
|
||||||
|
"unctx": "^2.4.1",
|
||||||
|
"unimport": "^5.0.1",
|
||||||
|
"untyped": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nuxt-site-config-kit/node_modules/escape-string-regexp": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nuxt-site-config-kit/node_modules/unimport": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/unimport/-/unimport-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-1YWzPj6wYhtwHE+9LxRlyqP4DiRrhGfJxdtH475im8ktyZXO3jHj/3PZ97zDdvkYoovFdi0K4SKl3a7l92v3sQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"acorn": "^8.14.1",
|
||||||
|
"escape-string-regexp": "^5.0.0",
|
||||||
|
"estree-walker": "^3.0.3",
|
||||||
|
"local-pkg": "^1.1.1",
|
||||||
|
"magic-string": "^0.30.17",
|
||||||
|
"mlly": "^1.7.4",
|
||||||
|
"pathe": "^2.0.3",
|
||||||
|
"picomatch": "^4.0.2",
|
||||||
|
"pkg-types": "^2.1.0",
|
||||||
|
"scule": "^1.3.0",
|
||||||
|
"strip-literal": "^3.0.0",
|
||||||
|
"tinyglobby": "^0.2.13",
|
||||||
|
"unplugin": "^2.3.2",
|
||||||
|
"unplugin-utils": "^0.2.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nuxt-site-config/node_modules/@nuxt/kit": {
|
||||||
|
"version": "3.17.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.17.4.tgz",
|
||||||
|
"integrity": "sha512-l+hY8sy2XFfg3PigZj+PTu6+KIJzmbACTRimn1ew/gtCz+F38f6KTF4sMRTN5CUxiB8TRENgEonASmkAWfpO9Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"c12": "^3.0.4",
|
||||||
|
"consola": "^3.4.2",
|
||||||
|
"defu": "^6.1.4",
|
||||||
|
"destr": "^2.0.5",
|
||||||
|
"errx": "^0.1.0",
|
||||||
|
"exsolve": "^1.0.5",
|
||||||
|
"ignore": "^7.0.4",
|
||||||
|
"jiti": "^2.4.2",
|
||||||
|
"klona": "^2.0.6",
|
||||||
|
"knitwork": "^1.2.0",
|
||||||
|
"mlly": "^1.7.4",
|
||||||
|
"ohash": "^2.0.11",
|
||||||
|
"pathe": "^2.0.3",
|
||||||
|
"pkg-types": "^2.1.0",
|
||||||
|
"scule": "^1.3.0",
|
||||||
|
"semver": "^7.7.2",
|
||||||
|
"std-env": "^3.9.0",
|
||||||
|
"tinyglobby": "^0.2.13",
|
||||||
|
"ufo": "^1.6.1",
|
||||||
|
"unctx": "^2.4.1",
|
||||||
|
"unimport": "^5.0.1",
|
||||||
|
"untyped": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nuxt-site-config/node_modules/escape-string-regexp": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nuxt-site-config/node_modules/unimport": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/unimport/-/unimport-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-1YWzPj6wYhtwHE+9LxRlyqP4DiRrhGfJxdtH475im8ktyZXO3jHj/3PZ97zDdvkYoovFdi0K4SKl3a7l92v3sQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"acorn": "^8.14.1",
|
||||||
|
"escape-string-regexp": "^5.0.0",
|
||||||
|
"estree-walker": "^3.0.3",
|
||||||
|
"local-pkg": "^1.1.1",
|
||||||
|
"magic-string": "^0.30.17",
|
||||||
|
"mlly": "^1.7.4",
|
||||||
|
"pathe": "^2.0.3",
|
||||||
|
"picomatch": "^4.0.2",
|
||||||
|
"pkg-types": "^2.1.0",
|
||||||
|
"scule": "^1.3.0",
|
||||||
|
"strip-literal": "^3.0.0",
|
||||||
|
"tinyglobby": "^0.2.13",
|
||||||
|
"unplugin": "^2.3.2",
|
||||||
|
"unplugin-utils": "^0.2.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/nuxt/node_modules/@oxc-parser/binding-darwin-arm64": {
|
"node_modules/nuxt/node_modules/@oxc-parser/binding-darwin-arm64": {
|
||||||
"version": "0.67.0",
|
"version": "0.67.0",
|
||||||
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.67.0.tgz",
|
"resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.67.0.tgz",
|
||||||
@ -14200,9 +14532,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.7.1",
|
"version": "7.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||||
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
@ -14517,6 +14849,21 @@
|
|||||||
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
|
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/site-config-stack": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/site-config-stack/-/site-config-stack-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-YmHQr5nMfec5ZTtuxK52YVG8nj4DwI68rSsbznuurQ96bIh2bHf5mNPAZnAyDBPpTWRwmWAliWMRD6WFewWGdA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ufo": "^1.6.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/harlan-zw"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "^3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/slash": {
|
"node_modules/slash": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz",
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
"@nuxt/scripts": "^0.11.6",
|
"@nuxt/scripts": "^0.11.6",
|
||||||
"@nuxt/ui": "^3.0.2",
|
"@nuxt/ui": "^3.0.2",
|
||||||
"@nuxtjs/i18n": "^9.5.3",
|
"@nuxtjs/i18n": "^9.5.3",
|
||||||
|
"@nuxtjs/sitemap": "^7.3.0",
|
||||||
"@pinia/nuxt": "^0.11.0",
|
"@pinia/nuxt": "^0.11.0",
|
||||||
"nitropack": "^2.11.9",
|
"nitropack": "^2.11.9",
|
||||||
"nuxt": "^3.16.2",
|
"nuxt": "^3.16.2",
|
||||||
|
|||||||
126
pages/artikel/[link].vue
Normal file
126
pages/artikel/[link].vue
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<template>
|
||||||
|
<div class="article" v-if="article">
|
||||||
|
<SideBarNaviSlider link="/wissenswertes">
|
||||||
|
{{ $t('artikel.artikelUebersicht') /* Beispiel für i18n */ }}
|
||||||
|
</SideBarNaviSlider>
|
||||||
|
|
||||||
|
<section class="teaserBox topSpace">
|
||||||
|
<div class="container-10">
|
||||||
|
<p class="articleInfo">
|
||||||
|
<b>{{ $t('artikel.autor') }}</b> {{ author }} |
|
||||||
|
<b>{{ $t('artikel.aktualisiert') }}</b> {{ formattedDate }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<NuxtImg
|
||||||
|
v-if="article.image?.url"
|
||||||
|
:src="article.image.url"
|
||||||
|
:alt="article.image.alternativeText || article.header"
|
||||||
|
class="img_detail"
|
||||||
|
width="350"
|
||||||
|
height="auto"
|
||||||
|
priority
|
||||||
|
provider="strapi"
|
||||||
|
:sizes="'(max-width: 600px) 90vw, 350px'"
|
||||||
|
role="img"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<h1>{{ article.header }}</h1>
|
||||||
|
|
||||||
|
<p class="teaser">{{ article.teaser }}</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="articleBox container">
|
||||||
|
<div v-html="htmlContent(article.content)" class="content"></div>
|
||||||
|
<button
|
||||||
|
@click.prevent="toggleContactBubble"
|
||||||
|
class="pinkBtn"
|
||||||
|
role="button"
|
||||||
|
aria-label="Kontakt aufnehmen"
|
||||||
|
>
|
||||||
|
{{ $t('kontakt.kontaktieren') }}
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="container topSpace">
|
||||||
|
<p>{{ $t('artikel.ladenOderNichtGefunden') }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
import { useMainStore } from '@/stores/main'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
import { useHtmlConverter } from '@/composables/useHTMLConverter'
|
||||||
|
import SideBarNaviSlider from '@/components/SideBarNaviSlider.vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const slug = route.params.link
|
||||||
|
console.log(slug)
|
||||||
|
|
||||||
|
const mainStore = useMainStore()
|
||||||
|
const { articles } = storeToRefs(mainStore)
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
// Artikel suchen
|
||||||
|
const article = computed(() => {
|
||||||
|
if (!articles.value) return null
|
||||||
|
return articles.value.find(item => item.slug === slug) ?? null
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const { convertToHTML } = useHtmlConverter()
|
||||||
|
const htmlContent = (content) => convertToHTML(content)
|
||||||
|
|
||||||
|
const toggleContactBubble = () => mainStore.toggleContactBubble()
|
||||||
|
|
||||||
|
|
||||||
|
// Beispiel Autor und formatierte Datum (kannst du anpassen)
|
||||||
|
const author = 'Sabrina Hennrich'
|
||||||
|
const formattedDate = computed(() => {
|
||||||
|
if (!article.value?.dateModified) return ''
|
||||||
|
const d = new Date(article.value.dateModified)
|
||||||
|
return d.toLocaleDateString('de-DE')
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="sass">
|
||||||
|
.article
|
||||||
|
margin-top: 2rem
|
||||||
|
.teaserBox
|
||||||
|
margin-bottom: 1.5rem !important
|
||||||
|
.teaser
|
||||||
|
font-family: 'Mainfont-Bold'
|
||||||
|
.articleInfo
|
||||||
|
font-size: 0.8rem
|
||||||
|
color: lighten(#333, 50%)
|
||||||
|
b
|
||||||
|
color: #e91e63
|
||||||
|
h1
|
||||||
|
font-size: 1.6rem
|
||||||
|
font-family: 'Mainfont-Bold'
|
||||||
|
margin-bottom: 1.5rem
|
||||||
|
line-height: 2.2rem
|
||||||
|
.img_detail
|
||||||
|
width: 100%
|
||||||
|
max-width: 350px
|
||||||
|
float: right
|
||||||
|
margin: 0 0 2rem 2rem
|
||||||
|
border-radius: 1rem
|
||||||
|
filter: grayscale(100%)
|
||||||
|
.articleBox
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
align-items: flex-start
|
||||||
|
|
||||||
|
.pinkBtn
|
||||||
|
clear: both
|
||||||
|
display: block
|
||||||
|
width: max-content
|
||||||
|
</style>
|
||||||
|
|
||||||
393
pages/designer/index.vue
Normal file
393
pages/designer/index.vue
Normal file
@ -0,0 +1,393 @@
|
|||||||
|
<template>
|
||||||
|
<div class="landing topSpace">
|
||||||
|
<section class="heroBox">
|
||||||
|
<div class="container">
|
||||||
|
<div class="contentBox">
|
||||||
|
<p class="supheadlinePink">Webentwicklung für Grafikdesigner und Mediengestalter</p>
|
||||||
|
<h1>Du hast ein geniales Design im Kopf ... </h1>
|
||||||
|
<h2>...doch im Pagebuilder lässt es sich nicht umsetzen?</h2>
|
||||||
|
<h3>Jou! Das kann richtig frustrierend sein - muss es aber nicht! <br>Gemeinsam setzen wir deine kreativen Ideen pixelgenau, performant und individuell um!</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="speechBox d-flex align-items-start">
|
||||||
|
<NuxtImg
|
||||||
|
class="profileImage"
|
||||||
|
src="/uploads/sabrinahennrich_0f07d46857.jpg"
|
||||||
|
provider="strapi"
|
||||||
|
alt="Sabrina Hennrich"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="bubble">
|
||||||
|
<p><b><span>Servus!</span> <br>Ich bin Sabrina – eine Webentwicklerin am Ammersee, südwestlich von München, die richtig programmieren kann!</b></p>
|
||||||
|
<p>Egal wie kreativ, individuell oder ausgefallen deine Idee ist – ich finde einen Weg, sie genau so umzusetzen. Falls es mal schwierig wird, stehe ich dir jederzeit unterstützend zur Seite, oder ich setze alles komplett ohne starre Templates um, ganz nach deinen Vorstellungen.</p>
|
||||||
|
<p>Gemeinsam erschaffen wir Webseiten, die dich und deinen Kunden begeistern werden!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="cooperation">
|
||||||
|
<div class="container">
|
||||||
|
<h2>Mehr Freiheit für dein Design</h2>
|
||||||
|
<ul>
|
||||||
|
<li><b>Pixelgenaue Umsetzung</b> <br>Ich setze dein Design so nah wie möglich am Original um und achte dabei auf jedes Detail.</li>
|
||||||
|
<li><b>Individuelle Lösungen & komplexe Funktionen</b> <br>Egal ob API-Anbindung, dynamische Inhalte oder interaktive Features – ich finde eine Lösung für fast alles.</li>
|
||||||
|
<li><b>Performance & Ladegeschwindigkeit</b> <br>Schnelle & schlanke Webseiten, die auf jedem Gerät reibungslos laufen.</li>
|
||||||
|
<li><b>Tool-übergreifende Kompetenz</b> <br>Kein WordPress-Zwang – ich nutze die beste Lösung für dein Projekt, unabhängig vom System.</li>
|
||||||
|
</ul>
|
||||||
|
<p><b>Du bleibst der kreative Kopf!</b><br>
|
||||||
|
Ich sorge dafür, dass dein Design genauso im Web erscheint, wie du es geplant hast – mit Top-Performance & perfekter technischer Umsetzung.</p>
|
||||||
|
<button class="pinkBtn" @click.prevent="toggleContactBubble" role="button">Lass uns kennenlernen</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<section class="deviceCheck" v-if="false">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<p class="supheadlinePink">Responsive Check</p>
|
||||||
|
<h2>Wie sieht deine Webseite auf den verschiedenen Bildschirmbreiten aus?</h2>
|
||||||
|
<h3>Probiers einfach aus!</h3>
|
||||||
|
<input type="text" placeholder="https://www.deinewebseite.de" v-model="weblink" @keyup.enter="updateIframe">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<svg v-if="desk" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 450">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="_clipPath_mz11Urxh3q4HMztuYrKSFIZi2059ENKc">
|
||||||
|
<rect width="500" height="450"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g clip-path="url(#_clipPath_mz11Urxh3q4HMztuYrKSFIZi2059ENKc)" style="z-index: 10">
|
||||||
|
<linearGradient id="_lgradient_0" x1="0.49993063593634346" y1="1.0075692569857018" x2="0.5082382316706063" y2="0.6847598402209258" gradientTransform="matrix(175.952,0,0,65.207,161.506,313.536)" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0.8699999999999999%" stop-opacity="1" style="stop-color:rgb(209,209,209)"/>
|
||||||
|
<stop offset="47.83%" stop-opacity="1" style="stop-color:rgb(232,232,232)"/>
|
||||||
|
<stop offset="100%" stop-opacity="1" style="stop-color:rgb(209,209,209)"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path d=" M 305.374 354.758 L 305.374 313.536 L 193.592 313.536 L 193.592 353.951 L 161.506 378.743 L 249.483 377.869 L 337.458 378.743 L 305.374 354.758 Z " fill="url(#_lgradient_0)" vector-effect="non-scaling-stroke" stroke-width="1" stroke="rgb(217,215,215)" stroke-opacity="100" stroke-linejoin="miter" stroke-linecap="square" stroke-miterlimit="3"/>
|
||||||
|
<linearGradient id="_lgradient_1" x1="0.0000010284238562002779" y1="0.499981826442526" x2="0.9999991252331814" y2="0.499981826442526" gradientTransform="matrix(443,0,0,43.47,28.5,275.242)" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="1.7399999999999998%" stop-opacity="1" style="stop-color:rgb(209,209,209)"/>
|
||||||
|
<stop offset="100%" stop-opacity="1" style="stop-color:rgb(235,235,235)"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path d=" M 34.273 275.242 L 465.964 275.242 C 469.02 275.242 471.5 277.728 471.5 280.79 L 471.5 297.862 C 471.5 309.369 462.177 318.712 450.697 318.712 L 49.302 318.712 C 37.822 318.712 28.5 309.369 28.5 297.862 L 28.5 281.027 C 28.5 277.834 31.087 275.242 34.273 275.242 Z " fill="url(#_lgradient_1)" vector-effect="non-scaling-stroke" stroke-width="1" stroke="rgb(217,215,215)" stroke-opacity="100" stroke-linejoin="miter" stroke-linecap="square" stroke-miterlimit="3"/>
|
||||||
|
<path d=" M 472.012 254.78 L 472.012 51.832 C 472.012 40.335 462.945 31 451.776 31 L 48.223 31 C 37.055 31 27.988 40.335 27.988 51.832 L 27.988 254.78 L 27.988 255.259 L 27.988 282.486 L 472.012 282.486 L 472.012 255.259 L 472.012 254.78 Z M 45.583 46.984 L 454.416 46.984 L 454.416 268.633 L 45.583 268.633 L 45.583 46.984 Z " fill-rule="evenodd" fill="rgb(55,55,55)"/>
|
||||||
|
<path d="M 73.451 74.227 L 133.299 74.227 L 133.299 134.075 L 73.451 134.075 L 73.451 74.227 Z" style="stroke:none;fill:#F0F0F0;stroke-miterlimit:10;"/>
|
||||||
|
<linearGradient id="_lgradient_2" x1="-0.0000019194307706443814" y1="0.5000543177381012" x2="0.9999980747113533" y2="0.5000543177381012" gradientTransform="matrix(306.503,0,0,9.583,96.179,370.194)" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0.8699999999999999%" stop-opacity="1" style="stop-color:rgb(162,162,162)"/>
|
||||||
|
<stop offset="97.83%" stop-opacity="1" style="stop-color:rgb(232,232,232)"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path d=" M 98.371 370.463 C 102.752 369.979 396.421 370.256 400.595 370.463 C 403.378 370.6 403.378 373.706 400.595 379.777 L 98.371 379.777 C 95.449 373.89 95.449 370.785 98.371 370.463 Z " fill="url(#_lgradient_2)" vector-effect="non-scaling-stroke" stroke-width="1" stroke="rgb(185,185,185)" stroke-opacity="100" stroke-linejoin="miter" stroke-linecap="square" stroke-miterlimit="3"/>
|
||||||
|
<rect x="45.583" y="46.984" width="408.832" height="222.047" transform="matrix(1,0,0,1,0,0)" fill="rgb(0,0,0)"/>
|
||||||
|
<path d=" M 243.844 302.371 C 242.175 299.831 245.066 297.867 247.098 297.222 C 251.729 295.751 255.722 297.863 254.907 301.23 C 253.327 307.756 245.055 304.215 243.844 302.371 Z " fill="rgb(55,55,55)"/>
|
||||||
|
<rect id="deskScreenBlank" x="46" y="47.5" width="409.5" height="221.5" transform="matrix(1,0,0,1,0,0)" fill="rgb(0,0,0)"/>
|
||||||
|
<g>
|
||||||
|
<foreignObject v-if="isValidUrl(weblink)" id="deskScreen" x="46" y="47.5" width="409.5" height="221.5">
|
||||||
|
<iframe ref="iframeRef" :src="weblink" frameborder="0"></iframe>
|
||||||
|
</foreignObject>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<svg v-else xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
|
||||||
|
<defs>
|
||||||
|
<clipPath id="_clipPath_J5sSadUalMgzHmiGMPTuwCKeG9KghIf7">
|
||||||
|
<rect width="500" height="500"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<g clip-path="url(#_clipPath_J5sSadUalMgzHmiGMPTuwCKeG9KghIf7)">
|
||||||
|
<path d=" M 152.048 12.143 L 352.475 12.143 C 368.401 12.143 381.331 25.073 381.331 40.999 L 381.331 451.861 C 381.331 467.787 368.401 480.716 352.475 480.716 L 152.048 480.716 C 136.122 480.716 123.192 467.787 123.192 451.861 L 123.192 40.999 C 123.192 25.073 136.122 12.143 152.048 12.143 Z " fill="rgb(55,55,55)"/>
|
||||||
|
<path d="M 155.466 25.45 L 347.174 25.45 C 355.373 25.45 362.03 32.107 362.03 40.306 L 362.03 438.864 C 362.03 447.063 355.373 453.72 347.174 453.72 L 155.466 453.72 C 147.267 453.72 140.61 447.063 140.61 438.864 L 140.61 40.306 C 140.61 32.107 147.267 25.45 155.466 25.45 Z" style="stroke:none;fill:#000000;stroke-miterlimit:10;"/>
|
||||||
|
<mask id="_mask_kRhtIUM0vsIJwCru8KMEeoX7mwdCHdLR">
|
||||||
|
<path d=" M 241.815 465.584 C 241.815 461.174 245.395 457.594 249.804 457.594 C 254.214 457.594 257.794 461.174 257.794 465.584 C 257.794 469.993 254.214 473.573 249.804 473.573 C 245.395 473.573 241.815 469.993 241.815 465.584 Z " fill="white" stroke="none"/>
|
||||||
|
</mask>
|
||||||
|
<path d=" M 241.815 465.584 C 241.815 461.174 245.395 457.594 249.804 457.594 C 254.214 457.594 257.794 461.174 257.794 465.584 C 257.794 469.993 254.214 473.573 249.804 473.573 C 245.395 473.573 241.815 469.993 241.815 465.584 Z " fill="rgb(49,49,49)"/>
|
||||||
|
<path d=" M 241.815 465.584 C 241.815 461.174 245.395 457.594 249.804 457.594 C 254.214 457.594 257.794 461.174 257.794 465.584 C 257.794 469.993 254.214 473.573 249.804 473.573 C 245.395 473.573 241.815 469.993 241.815 465.584 Z " fill="rgb(49,49,49)" mask="url(#_mask_kRhtIUM0vsIJwCru8KMEeoX7mwdCHdLR)" vector-effect="non-scaling-stroke" stroke-width="4" stroke="rgb(119,119,119)" stroke-linejoin="miter" stroke-linecap="square" stroke-miterlimit="3"/>
|
||||||
|
<path d=" M 210.188 13.882 L 294.187 13.882 C 298.869 13.882 302.669 17.683 302.669 22.364 L 302.669 22.739 C 302.669 27.42 298.869 31.221 294.187 31.221 L 210.188 31.221 C 205.506 31.221 201.706 27.42 201.706 22.739 L 201.706 22.364 C 201.706 17.683 205.506 13.882 210.188 13.882 Z " fill="rgb(55,55,55)"/>
|
||||||
|
<clipPath id="_clipPath_yG0PUG5xuGwoBQdYIaTfyJw0eBJTI7af">
|
||||||
|
<path d=" M 210.188 13.882 L 294.187 13.882 C 298.869 13.882 302.669 17.683 302.669 22.364 L 302.669 22.739 C 302.669 27.42 298.869 31.221 294.187 31.221 L 210.188 31.221 C 205.506 31.221 201.706 27.42 201.706 22.739 L 201.706 22.364 C 201.706 17.683 205.506 13.882 210.188 13.882 Z " fill="rgb(55,55,55)"/>
|
||||||
|
</clipPath>
|
||||||
|
<g clip-path="url(#_clipPath_yG0PUG5xuGwoBQdYIaTfyJw0eBJTI7af)">
|
||||||
|
<mask id="_mask_toYsxxmj7yA1tlh5Xolo04GF3EKtC9b5">
|
||||||
|
<path d=" M 248.906 23.145 C 248.906 21.069 250.591 19.384 252.667 19.384 C 254.743 19.384 256.429 21.069 256.429 23.145 C 256.429 25.221 254.743 26.907 252.667 26.907 C 250.591 26.907 248.906 25.221 248.906 23.145 Z " fill="white" stroke="none"/>
|
||||||
|
</mask>
|
||||||
|
<path d=" M 248.906 23.145 C 248.906 21.069 250.591 19.384 252.667 19.384 C 254.743 19.384 256.429 21.069 256.429 23.145 C 256.429 25.221 254.743 26.907 252.667 26.907 C 250.591 26.907 248.906 25.221 248.906 23.145 Z " fill="rgb(157,157,157)"/>
|
||||||
|
<path d=" M 248.906 23.145 C 248.906 21.069 250.591 19.384 252.667 19.384 C 254.743 19.384 256.429 21.069 256.429 23.145 C 256.429 25.221 254.743 26.907 252.667 26.907 C 250.591 26.907 248.906 25.221 248.906 23.145 Z " fill="rgb(157,157,157)" mask="url(#_mask_toYsxxmj7yA1tlh5Xolo04GF3EKtC9b5)" vector-effect="non-scaling-stroke" stroke-width="2" stroke="rgb(181,181,181)" stroke-linejoin="miter" stroke-linecap="square" stroke-miterlimit="3"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<Recommendations />
|
||||||
|
<section class="contrastCalcLink">
|
||||||
|
<div class="container">
|
||||||
|
<img src="https://strapi.digimedialoop.de/uploads/wcag_kontrastrechner_77abf9d9be.png" alt="kontrast check" class="imgRight">
|
||||||
|
<p class="supheadlinePink">Barrierefreies Webdesign</p>
|
||||||
|
<h2>Hat Dein Design den richtigen Kontrast?</h2>
|
||||||
|
<p>Mit dem praktischen Kontrastchecker kannst Du herausfinden, ob die Schrift und der Hintergrund in Deinem Design den WCAG_Richtlinien entsprechen. So stellst Du sicher, dass Dein Design für alle gut lesbar ist.</p>
|
||||||
|
<button class="mintBtn" @click.prevent="navigateTo('/toolbox/kontrastchecker')"
|
||||||
|
role="button"
|
||||||
|
aria-label="Zum Kontrastchecker">Jetzt kostenlos Konstrast prüfen</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<FAQArea
|
||||||
|
pageLink="/webentwicklung-fuer-designer-und-mediengestalter"
|
||||||
|
headline="Wichtige Antworten zur Zusammenarbeit im Überblick für Dich"
|
||||||
|
button="Dann lass uns quatschen!"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
definePageMeta({
|
||||||
|
name: 'designer'
|
||||||
|
})
|
||||||
|
import { ref, onMounted, onUnmounted, nextTick } from "vue";
|
||||||
|
import { useMainStore } from '@/stores/main';
|
||||||
|
// Lade diese Komponente synchron wegen SEO
|
||||||
|
|
||||||
|
|
||||||
|
const mainStore = useMainStore();
|
||||||
|
|
||||||
|
const toggleContactBubble = () => mainStore.toggleContactBubble();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const weblink = ref("https://digimedialoop.de");
|
||||||
|
const iframeRef = ref(null);
|
||||||
|
const observer = ref(null);
|
||||||
|
const desk = ref(true)
|
||||||
|
|
||||||
|
// Berechnet die exakte Größe des `foreignObject` basierend auf `#deskScreenBlank`
|
||||||
|
const updateIframeSize = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
const blankRect = document.getElementById("deskScreenBlank");
|
||||||
|
const foreignObject = document.getElementById("deskScreen");
|
||||||
|
|
||||||
|
if (blankRect && foreignObject && iframeRef.value) {
|
||||||
|
// Exakte Werte auslesen und Float-Werte setzen (verhindert Subpixel-Rundungen)
|
||||||
|
const currentWidth = parseFloat(blankRect.getAttribute("width"));
|
||||||
|
const currentHeight = parseFloat(blankRect.getAttribute("height"));
|
||||||
|
|
||||||
|
// Setze `foreignObject` exakt auf `#deskScreenBlank`
|
||||||
|
foreignObject.setAttribute("width", currentWidth.toFixed(2));
|
||||||
|
foreignObject.setAttribute("height", currentHeight.toFixed(2));
|
||||||
|
|
||||||
|
// Berechne den Skalierungsfaktor für 1400px Breite
|
||||||
|
const zoomFactor = currentWidth / 1400;
|
||||||
|
|
||||||
|
// Setze das `iframe` korrekt
|
||||||
|
iframeRef.value.style.width = "1400px"; // Fixierte Breite
|
||||||
|
iframeRef.value.style.height = "755px"; // Höhe für Scrollbarkeit
|
||||||
|
iframeRef.value.style.zoom = zoomFactor; // Zoom-Faktor
|
||||||
|
iframeRef.value.style.overflowY = "scroll"; // Scrollen aktivieren
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Startet `ResizeObserver`, um live Änderungen zu tracken
|
||||||
|
const startObserver = () => {
|
||||||
|
const blankRect = document.getElementById("deskScreenBlank");
|
||||||
|
if (blankRect) {
|
||||||
|
observer.value = new ResizeObserver(updateIframeSize);
|
||||||
|
observer.value.observe(blankRect);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// URL aktualisieren & Größe anpassen
|
||||||
|
const updateIframe = () => {
|
||||||
|
if (!weblink.value.trim()) return;
|
||||||
|
|
||||||
|
weblink.value = ensureValidUrl(weblink.value);
|
||||||
|
|
||||||
|
if (!isValidUrl(weblink.value)) {
|
||||||
|
alert("Bitte eine gültige URL eingeben.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateIframeSize();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Automatisch "https://" hinzufügen, falls nötig
|
||||||
|
const ensureValidUrl = (url) => {
|
||||||
|
if (!url.match(/^https?:\/\//)) {
|
||||||
|
return "https://" + url;
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prüft, ob die URL gültig ist
|
||||||
|
const isValidUrl = (url) => {
|
||||||
|
try {
|
||||||
|
new URL(url);
|
||||||
|
return true;
|
||||||
|
} catch (_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialisiere `ResizeObserver` beim Mounten
|
||||||
|
onMounted(() => {
|
||||||
|
startObserver();
|
||||||
|
updateIframeSize();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Entferne Observer, wenn die Komponente zerstört wird
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (observer.value) observer.value.disconnect();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="sass">
|
||||||
|
.landing
|
||||||
|
section
|
||||||
|
margin: 5vh auto
|
||||||
|
h1
|
||||||
|
margin-bottom: 1rem
|
||||||
|
h3
|
||||||
|
line-height: 150%
|
||||||
|
font-size: 1.4rem
|
||||||
|
.heroBox
|
||||||
|
position: relative
|
||||||
|
overflow-x: hidden
|
||||||
|
overflow-y: hidden
|
||||||
|
/*&::after
|
||||||
|
content: ''
|
||||||
|
position: absolute
|
||||||
|
top: 2vh
|
||||||
|
right: -50vw
|
||||||
|
width: 80vw
|
||||||
|
height: 90%
|
||||||
|
min-height: 500px
|
||||||
|
max-height: 800px
|
||||||
|
background-image: url('https://strapi.digimedialoop.de/uploads/Screen_Shot_Tool_20250225214638_2209c9c92e.png')
|
||||||
|
background-repeat: no-repeat
|
||||||
|
background-position: center right
|
||||||
|
background-size: cover
|
||||||
|
border-radius: 42% 49% 52% 48% / 53% 38% 62% 47%
|
||||||
|
animation: bubble-wobble 25s infinite ease alternate, gradient-animation 70s infinite alternate ease-in-out
|
||||||
|
box-shadow: $innerShadow
|
||||||
|
opacity: 1
|
||||||
|
@media(max-width: $breakPointXL)
|
||||||
|
right: -60vw
|
||||||
|
@media(max-width: $breakPointLG)
|
||||||
|
right: -60vw
|
||||||
|
min-height: 300px
|
||||||
|
max-height: 500px
|
||||||
|
@media(max-width: $breakPointLG)
|
||||||
|
min-height: 200px
|
||||||
|
max-height: 400px
|
||||||
|
right: -65vw
|
||||||
|
@media(max-width: $breakPointLG)
|
||||||
|
min-height: 200px
|
||||||
|
max-height: 400px
|
||||||
|
right: -70vw */
|
||||||
|
h2
|
||||||
|
margin-bottom: 1rem
|
||||||
|
font-size: 1.4rem
|
||||||
|
h3
|
||||||
|
font-size: 1.1rem
|
||||||
|
font-family: 'Mainfont-Bold'
|
||||||
|
margin-bottom: 1rem
|
||||||
|
.contentBox
|
||||||
|
width: 95%
|
||||||
|
// width: 55vw
|
||||||
|
//@media(max-width: $breakPointMD)
|
||||||
|
//width: 68vw
|
||||||
|
.speechBox
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
max-width: 100%
|
||||||
|
margin: 0 auto
|
||||||
|
padding: 1rem 0
|
||||||
|
gap: 4vw
|
||||||
|
|
||||||
|
.profileImage
|
||||||
|
width: 30vw
|
||||||
|
margin-left: -3vw
|
||||||
|
max-width: 260px
|
||||||
|
border-radius: $loopShape
|
||||||
|
flex-shrink: 0
|
||||||
|
background-color: rgba(white, .7)
|
||||||
|
//animation: bubble-wobble 15s infinite ease alternate, gradient-animation 10s infinite alternate ease-in-out
|
||||||
|
|
||||||
|
.bubble
|
||||||
|
position: relative
|
||||||
|
//background-image: linear-gradient(to right, lighten($beige, 5%), white)
|
||||||
|
border: 1px solid darken($beige, 5%)
|
||||||
|
border-radius: 1rem
|
||||||
|
padding: 1.5rem
|
||||||
|
width: 100%
|
||||||
|
max-width: 450px
|
||||||
|
line-height: 1.4
|
||||||
|
span
|
||||||
|
color: darken($pink, 5%)
|
||||||
|
font-size: 1.2rem
|
||||||
|
text-transform: uppercase
|
||||||
|
padding: 1rem 0
|
||||||
|
p
|
||||||
|
font-size: .9rem
|
||||||
|
&:before
|
||||||
|
content: ''
|
||||||
|
position: absolute
|
||||||
|
top: 40px
|
||||||
|
left: -12px
|
||||||
|
width: 20px
|
||||||
|
height: 20px
|
||||||
|
background: white //lighten($beige, 5%)
|
||||||
|
border-left: 1px solid darken($beige, 5%)
|
||||||
|
border-top: 1px solid darken($beige, 5%)
|
||||||
|
transform: rotate(-45deg)
|
||||||
|
@media(max-width: $breakPointMD)
|
||||||
|
|
||||||
|
.cooperation
|
||||||
|
margin: 0 0 5rem 0
|
||||||
|
ul
|
||||||
|
list-style: none
|
||||||
|
padding: 0 0 1rem 1rem
|
||||||
|
|
||||||
|
li
|
||||||
|
position: relative
|
||||||
|
padding-left: 2rem
|
||||||
|
font-size: 1rem
|
||||||
|
margin-bottom: 1rem
|
||||||
|
|
||||||
|
&::before
|
||||||
|
content: "✔"
|
||||||
|
color: $primaryColor
|
||||||
|
font-weight: bold
|
||||||
|
position: absolute
|
||||||
|
font-size: 1.4rem
|
||||||
|
left: 0
|
||||||
|
.contrastCalcLink
|
||||||
|
margin-bottom: 10vh
|
||||||
|
img
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
.deviceCheck
|
||||||
|
h2
|
||||||
|
margin-bottom: .5rem
|
||||||
|
input
|
||||||
|
width: 100%
|
||||||
|
padding: .5rem 1rem
|
||||||
|
border: 1px solid lightgrey
|
||||||
|
border-radius: 5px
|
||||||
|
font-size: 1.2rem
|
||||||
|
color: $darkgrey
|
||||||
|
#deskScreen
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
position: relative
|
||||||
|
overflow: hidden
|
||||||
|
|
||||||
|
iframe
|
||||||
|
width: 1400px // Fixierte virtuelle Breite
|
||||||
|
height: auto // Automatische Höhe für Scrollen
|
||||||
|
border: none
|
||||||
|
display: block
|
||||||
|
overflow-y: auto // Scrollen aktivieren
|
||||||
|
|
||||||
|
</style>
|
||||||
@ -1,7 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container-10">
|
<PageContent />
|
||||||
<h1>{{ $t('imprint') }}</h1>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|||||||
336
pages/index.vue
336
pages/index.vue
@ -1,9 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="homePage">
|
<div class="homePage">
|
||||||
<section class="heroBox_service" aria-labelledby="hero-heading">
|
|
||||||
|
<section class="heroBox" :aria-label="$t('pages.services.hero.ariaLabel')">
|
||||||
<NuxtImg
|
<NuxtImg
|
||||||
provider="strapi"
|
provider="strapi"
|
||||||
src="/uploads/large_DML_Home_Hero_4f27bc7f8e.webp"
|
src="/uploads/bg_technologie_d24f950ccf.webp"
|
||||||
class="hero-bg"
|
class="hero-bg"
|
||||||
sizes="sm:100vw md:100vw lg:100vw"
|
sizes="sm:100vw md:100vw lg:100vw"
|
||||||
alt=""
|
alt=""
|
||||||
@ -14,9 +15,9 @@
|
|||||||
fetchpriority="high"
|
fetchpriority="high"
|
||||||
/>
|
/>
|
||||||
<div class="container-10">
|
<div class="container-10">
|
||||||
<h1 id="hero-heading">{{ $t('pages.home.heroBox.h1') }}</h1>
|
<h1>{{ $t('pages.services.hero.headline1') }}</h1>
|
||||||
<h2>{{ $t('pages.home.heroBox.h2') }}</h2>
|
<h2>{{ $t('pages.services.hero.headline2') }}</h2>
|
||||||
<h3>{{ $t('pages.home.heroBox.h3') }}</h3>
|
<h3>{{ $t('pages.services.hero.headline3') }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<!-- Nach dem Container: Spiegelwelle unten -->
|
<!-- Nach dem Container: Spiegelwelle unten -->
|
||||||
<svg class="sectionWave wave-bottom" style="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 20" aria-hidden="true">
|
<svg class="sectionWave wave-bottom" style="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 20" aria-hidden="true">
|
||||||
@ -25,82 +26,36 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
||||||
<section aria-labelledby="solution-title">
|
<section class="explainBox" :aria-label="$t('pages.services.explain.ariaLabel')">
|
||||||
<div class="container-10 webStrategy">
|
<NuxtImg
|
||||||
<h2 id="solution-title">{{ $t('pages.home.solution.title') }}</h2>
|
src="/uploads/Human_Maschine_BG_5c91e9100f.webp"
|
||||||
<h3>{{ $t('pages.home.solution.teaser') }}</h3>
|
provider="strapi"
|
||||||
<p>{{ $t('pages.home.solution.text') }}</p>
|
format="webp"
|
||||||
<button
|
sizes="100vw"
|
||||||
class="mintBtn"
|
class="background-image"
|
||||||
role="button"
|
alt=""
|
||||||
aria-describedby="solution-title"
|
aria-hidden="true"
|
||||||
aria-label="headless CMS Info" @click="navigateToArticle">
|
/>
|
||||||
{{ $t('pages.home.solution.buttonText') }}
|
<div class="container-15 content">
|
||||||
</button>
|
<h2>{{ $t('pages.services.explain.headline1') }}</h2>
|
||||||
|
<h3>{{ $t('pages.services.explain.headline2') }}</h3>
|
||||||
|
|
||||||
|
<p>{{ $t('pages.services.explain.paragraph') }}</p>
|
||||||
|
<ul class="check">
|
||||||
|
<li>{{ $t('pages.services.explain.bullet1') }}</li>
|
||||||
|
<li>{{ $t('pages.services.explain.bullet2') }}</li>
|
||||||
|
<li>{{ $t('pages.services.explain.bullet3') }}</li>
|
||||||
|
<li>{{ $t('pages.services.explain.bullet4') }}</li>
|
||||||
|
<li>{{ $t('pages.services.explain.bullet5') }}</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
||||||
<section class="targetGroup" aria-labelledby="invitation-title">
|
|
||||||
<svg class="sectionWave wave-top" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 20" aria-hidden="true">
|
|
||||||
<path d="M 0 0 L 500 0 L 500 14 Q 354.4 -2.8 250 11 Q 145.6 24.8 0 14 L 0 0 Z" fill="#FFF"/>
|
|
||||||
</svg>
|
|
||||||
<div class="container-10">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4"/>
|
|
||||||
<div class="col-md-8 pt-5 pb-5">
|
|
||||||
<h2 id="invitation-title">{{ $t('pages.home.invitation.title') }}</h2>
|
|
||||||
<h3>{{ $t('pages.home.invitation.teaser') }}</h3>
|
|
||||||
<button
|
|
||||||
class="pinkBtn" role="button"
|
|
||||||
aria-describedby="invitation-title"
|
|
||||||
aria-label="Kontaktformular öffnen"
|
|
||||||
@click.prevent="toggleContactBubble">{{ $t('pages.home.invitation.button') }}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<svg class="sectionWave wave-bottom" style="transform: scale(-1,-1)" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 20" aria-hidden="true">
|
|
||||||
<path d="M 0 0 L 500 0 L 500 14 Q 354.4 -2.8 250 11 Q 145.6 24.8 0 14 L 0 0 Z" fill="#FFF"/>
|
|
||||||
</svg>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
<section class="canDo" aria-labelledby="canDo-section-title">
|
|
||||||
<div class="container">
|
|
||||||
<h2 id="canDo-section-title" class="text-center">
|
|
||||||
{{ $t('pages.home.canDo.title') }}
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div class="canDoGrid">
|
|
||||||
<div
|
|
||||||
v-for="(item, index) in canDoItems"
|
|
||||||
:key="index"
|
|
||||||
class="canDoBox"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="canDoItem"
|
|
||||||
:role="index === 2 ? 'group' : null"
|
|
||||||
:aria-labelledby="index === 2 ? 'cando-title' : null"
|
|
||||||
>
|
|
||||||
<NuxtImg
|
|
||||||
provider="strapi"
|
|
||||||
:src="item.img"
|
|
||||||
format="webp"
|
|
||||||
:modifiers="{ quality: 80 }"
|
|
||||||
sizes="xs:280px sm:300px md:350px"
|
|
||||||
class="imageBox"
|
|
||||||
loading="lazy"
|
|
||||||
:alt="item.alt"
|
|
||||||
/>
|
|
||||||
<h3 :id="index === 2 ? 'cando-title' : null">
|
|
||||||
{{ $t(item.title) }}
|
|
||||||
</h3>
|
|
||||||
<p>{{ $t(item.text) }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
<section class="compBox">
|
<section class="compBox">
|
||||||
@ -152,16 +107,10 @@ import { defineAsyncComponent } from 'vue';
|
|||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const runtimeConfig = useRuntimeConfig();
|
|
||||||
const cmsUrl = computed(() => runtimeConfig.public.cmsBaseUrl)
|
|
||||||
|
|
||||||
const mainStore = useMainStore();
|
const mainStore = useMainStore();
|
||||||
const { customers } = storeToRefs(mainStore);
|
const { customers } = storeToRefs(mainStore);
|
||||||
const toggleContactBubble = () => mainStore.toggleContactBubble();
|
const toggleContactBubble = () => mainStore.toggleContactBubble();
|
||||||
|
|
||||||
const navigateToArticle = () => {
|
|
||||||
router.push('/wissenswertes/artikel/design-und-inhalt-sauber-getrennt-warum-headless-webdesign-die-beste-wahl-fuer-moderne-unternehmen-ist');
|
|
||||||
};
|
|
||||||
|
|
||||||
const screenWidth = computed(() => mainStore.screenWidth);
|
const screenWidth = computed(() => mainStore.screenWidth);
|
||||||
const waveHeight = computed(() => (screenWidth.value / 25).toFixed(0));
|
const waveHeight = computed(() => (screenWidth.value / 25).toFixed(0));
|
||||||
@ -176,32 +125,7 @@ const logoItems = computed(() => {
|
|||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
const canDoItems = [
|
|
||||||
{
|
|
||||||
img: '/uploads/website_Erfolg_Marketing_3c36a43ba5.png',
|
|
||||||
alt: 'Website Erfolg Marketing',
|
|
||||||
title: 'pages.home.canDo.item1.title',
|
|
||||||
text: 'pages.home.canDo.item1.text',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
img: '/uploads/Kundenbindung_45d45ef3fc.png',
|
|
||||||
alt: 'Kundenbindung Strategie',
|
|
||||||
title: 'pages.home.canDo.item2.title',
|
|
||||||
text: 'pages.home.canDo.item2.text',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
img: '/uploads/Screen_Shot_Tool_20250228133408_beb2a11980.png',
|
|
||||||
alt: 'Screen Tool Beispiel 1',
|
|
||||||
title: 'pages.home.canDo.item3.title',
|
|
||||||
text: 'pages.home.canDo.item3.text',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
img: '/uploads/Screen_Shot_Tool_20250228133812_0a20d4320e.png',
|
|
||||||
alt: 'Screen Tool Beispiel 2',
|
|
||||||
title: 'pages.home.canDo.item4.title',
|
|
||||||
text: 'pages.home.canDo.item4.text',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -209,7 +133,7 @@ const canDoItems = [
|
|||||||
<style lang="sass">
|
<style lang="sass">
|
||||||
.homePage
|
.homePage
|
||||||
|
|
||||||
.heroBox_service
|
.heroBox
|
||||||
position: relative
|
position: relative
|
||||||
min-height: 35rem
|
min-height: 35rem
|
||||||
height: 70vh
|
height: 70vh
|
||||||
@ -218,108 +142,87 @@ const canDoItems = [
|
|||||||
justify-content: center
|
justify-content: center
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
|
|
||||||
|
&::after
|
||||||
|
position: absolute
|
||||||
|
content: ""
|
||||||
|
z-index: 0
|
||||||
|
top: 0
|
||||||
|
left: 0
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
background-image: linear-gradient(
|
||||||
|
to bottom right,
|
||||||
|
rgba(255,255,255,0.4) 0%,
|
||||||
|
rgba(255,255,255,0.3) 2%,
|
||||||
|
rgba(0, 0, 0, 0.7) 60%,
|
||||||
|
rgba(255, 255, 255, 0) 100%,
|
||||||
|
transparent 100%
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
.hero-bg
|
.hero-bg
|
||||||
position: absolute
|
position: absolute
|
||||||
inset: 0
|
inset: 0
|
||||||
width: 100%
|
width: 100%
|
||||||
height: 100%
|
height: 100%
|
||||||
object-fit: cover
|
object-fit: cover
|
||||||
object-position: center bottom
|
object-position: center top
|
||||||
z-index: 0
|
z-index: -1
|
||||||
|
|
||||||
.container-10, h1, h2, h3
|
.container-10, h1, h2, h3
|
||||||
position: relative
|
position: relative
|
||||||
z-index: 1
|
z-index: 1
|
||||||
|
h1, h2, h3
|
||||||
h1
|
color: white
|
||||||
margin-top: 3rem
|
|
||||||
z-index: 2
|
z-index: 2
|
||||||
color: mix(black, $pink, 2%)
|
|
||||||
font-size: clamp(1rem, .8rem + 1vw, 1.2rem)
|
|
||||||
line-height: 1.5
|
line-height: 1.5
|
||||||
margin-bottom: 0
|
|
||||||
max-width: 70%
|
max-width: 70%
|
||||||
@media (max-width: $breakPointMD)
|
@media (max-width: $breakPointMD)
|
||||||
max-width: 100%
|
max-width: 100%
|
||||||
h2
|
h1
|
||||||
z-index: 2
|
margin-top: 0
|
||||||
font-size: clamp(1.4rem, .8rem + 2vw, 2.4rem)
|
font-size: clamp(2rem, 1.4rem + 3vw, 2.8rem)
|
||||||
line-height: 1.5
|
margin-bottom: 0
|
||||||
margin-top: 1rem
|
font-family: 'Comfortaa'
|
||||||
max-width: 55%
|
h2
|
||||||
|
font-size: clamp(1.2rem, .7rem + 2vw, 2rem)
|
||||||
|
margin: .8rem 0 .8rem 0
|
||||||
font-family: 'Comfortaa'
|
font-family: 'Comfortaa'
|
||||||
@media (max-width: $breakPointMD)
|
|
||||||
max-width: 90%
|
|
||||||
h3
|
h3
|
||||||
max-width: 55%
|
font-size: 1.2rem
|
||||||
line-height: 1.5
|
|
||||||
font-size: clamp(1rem, .8rem + 1vw, 1.6rem)
|
.explainBox
|
||||||
@media (max-width: $breakPointMD)
|
position: relative
|
||||||
max-width: 90%
|
overflow: hidden
|
||||||
&::after
|
min-height: 400px
|
||||||
content: ''
|
margin: 5vh 0
|
||||||
|
padding: 8vh 0
|
||||||
|
|
||||||
|
.background-image
|
||||||
position: absolute
|
position: absolute
|
||||||
top: 0
|
top: 0
|
||||||
left: 0
|
left: 0
|
||||||
width: 50%
|
width: 100%
|
||||||
height: 100%
|
height: auto
|
||||||
background-image: linear-gradient(to right, rgba(white, .3), transparent)
|
object-fit: contain
|
||||||
|
object-position: center center
|
||||||
|
z-index: 0
|
||||||
|
pointer-events: none
|
||||||
|
|
||||||
|
.content
|
||||||
|
position: relative
|
||||||
z-index: 1
|
z-index: 1
|
||||||
.container
|
padding-left: 10%
|
||||||
z-index: 2
|
h2
|
||||||
|
font-size: clamp(1.2rem, .7rem + 2vw, 2rem)
|
||||||
|
font-family: 'Comfortaa'
|
||||||
|
h3
|
||||||
|
font-family: 'Mainfont-Bold'
|
||||||
|
font-size: 1.2rem
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.webStrategy
|
|
||||||
padding: 4rem 0 3.5rem 0
|
|
||||||
h2
|
|
||||||
font-size: clamp(1.6rem, 1rem + 2vw, 1.8rem)
|
|
||||||
line-height: 150%
|
|
||||||
font-family: 'Comfortaa'
|
|
||||||
margin-left: 30%
|
|
||||||
h3
|
|
||||||
font-size: clamp(1.1rem, .75rem + 1vw, 1.25rem)
|
|
||||||
line-height: 150%
|
|
||||||
margin-left: 30%
|
|
||||||
p
|
|
||||||
margin-left: 30%
|
|
||||||
button
|
|
||||||
margin-left: 30%
|
|
||||||
&::after
|
|
||||||
content: ''
|
|
||||||
position: absolute
|
|
||||||
top: 5%
|
|
||||||
left: -36vw
|
|
||||||
width: 60vw
|
|
||||||
height: 90%
|
|
||||||
min-height: 550px
|
|
||||||
max-height: 800px
|
|
||||||
background-image: url('https://strapi.digimedialoop.de/uploads/Net_f1020a2216.png')
|
|
||||||
background-repeat: no-repeat
|
|
||||||
background-position: center right
|
|
||||||
background-size: cover
|
|
||||||
border-radius: 42% 49% 52% 48% / 53% 38% 62% 47%
|
|
||||||
animation: bubble-wobble 25s infinite ease alternate, gradient-animation 70s infinite alternate ease-in-out
|
|
||||||
box-shadow: $innerShadow
|
|
||||||
@media(max-width: $breakPointMD)
|
|
||||||
right: -50vw
|
|
||||||
|
|
||||||
.targetGroup
|
|
||||||
background-image: url('https://strapi.digimedialoop.de/uploads/smartphone_Contacts_40ae56a178.jpg')
|
|
||||||
background-repeat: no-repeat
|
|
||||||
background-size: cover
|
|
||||||
background-position: center top
|
|
||||||
min-height: 70vh
|
|
||||||
display: flex
|
|
||||||
align-items: center
|
|
||||||
justify-content: center
|
|
||||||
position: relative
|
|
||||||
padding: 3rem 0
|
|
||||||
h2
|
|
||||||
font-size: clamp(1.6rem, 1rem + 2vw, 1.8rem)
|
|
||||||
h3
|
|
||||||
font-size: clamp(1.1rem, .8rem + 1vw, 1.2rem)
|
|
||||||
line-height: 150%
|
|
||||||
|
|
||||||
.firstTeaser
|
.firstTeaser
|
||||||
h2
|
h2
|
||||||
@ -349,71 +252,6 @@ const canDoItems = [
|
|||||||
padding-right: 1rem
|
padding-right: 1rem
|
||||||
|
|
||||||
|
|
||||||
.canDo
|
|
||||||
margin: 12vh 0
|
|
||||||
h2
|
|
||||||
margin-bottom: 3.5rem
|
|
||||||
font-size: clamp(1.6rem, 1rem + 2vw, 1.8rem)
|
|
||||||
.canDoGrid
|
|
||||||
display: grid
|
|
||||||
gap: 2rem
|
|
||||||
justify-content: center
|
|
||||||
align-items: stretch
|
|
||||||
grid-template-columns: 1fr // Default: 1 Spalte
|
|
||||||
|
|
||||||
@media (min-width: $breakPointMD)
|
|
||||||
grid-template-columns: repeat(2, 1fr)
|
|
||||||
|
|
||||||
@media (min-width: $breakPointXL)
|
|
||||||
grid-template-columns: repeat(4, 1fr)
|
|
||||||
|
|
||||||
.canDoBox
|
|
||||||
width: 100%
|
|
||||||
display: flex
|
|
||||||
flex-direction: column
|
|
||||||
align-items: center
|
|
||||||
justify-content: flex-start
|
|
||||||
background-image: linear-gradient(to bottom right, transparent , white)
|
|
||||||
box-shadow: 3px 3px 8px 1px $lightgrey
|
|
||||||
border-bottom-right-radius: 1rem
|
|
||||||
padding: 1rem 1.5rem
|
|
||||||
border-right: 1px solid lighten($beige, 0%)
|
|
||||||
border-bottom: 1px solid lighten($beige, 0%)
|
|
||||||
height: 100%
|
|
||||||
|
|
||||||
.canDoItem
|
|
||||||
width: 100%
|
|
||||||
|
|
||||||
.imageBox
|
|
||||||
margin: 0rem auto 1rem auto
|
|
||||||
width: 100%
|
|
||||||
max-width: 180px
|
|
||||||
aspect-ratio: 5 / 4
|
|
||||||
object-fit: cover
|
|
||||||
border-radius: 1rem
|
|
||||||
display: block
|
|
||||||
|
|
||||||
&:nth-child(1)
|
|
||||||
border-radius: $loopShape1
|
|
||||||
&:nth-child(2)
|
|
||||||
border-radius: $loopShape2
|
|
||||||
&:nth-child(3)
|
|
||||||
border-radius: $loopShape3
|
|
||||||
&:nth-child(4)
|
|
||||||
border-radius: $loopShape4
|
|
||||||
|
|
||||||
h3
|
|
||||||
font-size: 1.2rem
|
|
||||||
line-height: 1.5rem
|
|
||||||
text-align: center
|
|
||||||
font-family: 'Mainfont-Bold'
|
|
||||||
color: darken($pink, 10%)
|
|
||||||
text-transform: uppercase
|
|
||||||
margin-bottom: .5rem
|
|
||||||
|
|
||||||
p
|
|
||||||
font-size: .9rem
|
|
||||||
text-align: left !important
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,170 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container-10">
|
<div class="knowledgeBox topSpace">
|
||||||
<h1>{{ $t('magazin') }}</h1>
|
<section class="teaserBox">
|
||||||
</div>
|
<div class="container">
|
||||||
|
<h1>{{ $t('pages.magazin.title') }}</h1>
|
||||||
|
<p>{{ $t('pages.magazin.teaser1') }}</p>
|
||||||
|
<p>{{ $t('pages.magazin.teaser2') }}</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="articleBox container">
|
||||||
|
<div class="grid">
|
||||||
|
<div
|
||||||
|
v-for="article in articles"
|
||||||
|
:key="article.id"
|
||||||
|
class="article"
|
||||||
|
>
|
||||||
|
|
||||||
|
<NuxtLink :to="getArticleLink(article.slug)" class="article-link">
|
||||||
|
<div class="image-wrapper">
|
||||||
|
<NuxtImg
|
||||||
|
v-if="article.image?.url"
|
||||||
|
:src="article.image.url"
|
||||||
|
provider="strapi"
|
||||||
|
:alt="article.image.alternativeText"
|
||||||
|
format="webp"
|
||||||
|
class="article-image"
|
||||||
|
/>
|
||||||
|
<div class="overlay">
|
||||||
|
<h2>{{ article.header }}</h2>
|
||||||
|
<button class="mintBtn">{{ $t('pages.magazin.readmore') }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</NuxtLink>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
|
||||||
definePageMeta({
|
<script setup lang="ts">
|
||||||
layout: 'default'
|
import { computed, watch } from 'vue'
|
||||||
})
|
import { useMainStore } from '@/stores/main'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
|
||||||
|
const mainStore = useMainStore()
|
||||||
|
const { articles, cmsUrl } = storeToRefs(mainStore)
|
||||||
|
|
||||||
|
const { getArticleLink } = useI18nPages()
|
||||||
|
|
||||||
|
const truncateText = (text: string, length = 200) =>
|
||||||
|
text?.length > length ? text.substring(0, length) + '…' : text
|
||||||
|
|
||||||
|
const currentDomain = typeof window !== 'undefined'
|
||||||
|
? window.location.origin
|
||||||
|
: 'https://www.digimedialoop.de'
|
||||||
|
|
||||||
|
// SEO: JSON-LD für Artikelübersicht
|
||||||
|
watch(articles, (newVal) => {
|
||||||
|
if (newVal?.length) {
|
||||||
|
useHead({
|
||||||
|
script: [
|
||||||
|
{
|
||||||
|
type: 'application/ld+json',
|
||||||
|
children: JSON.stringify({
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "ItemList",
|
||||||
|
itemListElement: newVal.map((article, index) => ({
|
||||||
|
"@type": "ListItem",
|
||||||
|
position: index + 1,
|
||||||
|
url: `${currentDomain}/wissenswertes/artikel/${article.slug}`,
|
||||||
|
name: article.header,
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, { immediate: true })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="sass">
|
|
||||||
|
|
||||||
|
<style lang="sass">
|
||||||
|
.articleBox
|
||||||
|
display: flex
|
||||||
|
justify-content: center
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
.grid
|
||||||
|
display: grid
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr))
|
||||||
|
gap: 1rem
|
||||||
|
justify-content: start
|
||||||
|
width: 100%
|
||||||
|
max-width: 100%
|
||||||
|
margin: 0 auto
|
||||||
|
|
||||||
|
.article
|
||||||
|
width: 100%
|
||||||
|
max-width: 450px
|
||||||
|
border: 1px solid $beige
|
||||||
|
background: linear-gradient(to bottom right, white, $lightgrey)
|
||||||
|
border-radius: 1rem
|
||||||
|
transition: .8s
|
||||||
|
position: relative
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
align-items: flex-start
|
||||||
|
overflow: hidden
|
||||||
|
|
||||||
|
.article-link
|
||||||
|
position: relative
|
||||||
|
display: block
|
||||||
|
color: white
|
||||||
|
text-decoration: none
|
||||||
|
|
||||||
|
.image-wrapper
|
||||||
|
position: relative
|
||||||
|
width: 100%
|
||||||
|
height: 220px
|
||||||
|
|
||||||
|
.article-image
|
||||||
|
width: 100%
|
||||||
|
height: 450px
|
||||||
|
object-fit: cover
|
||||||
|
border-top-left-radius: 1rem
|
||||||
|
border-top-right-radius: 1rem
|
||||||
|
|
||||||
|
|
||||||
|
.overlay
|
||||||
|
position: absolute
|
||||||
|
top: 0
|
||||||
|
left: 0
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
background-color: rgba(0, 0, 0, 0.7)
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
align-items: center
|
||||||
|
justify-content: center
|
||||||
|
padding: 1rem
|
||||||
|
border-top-left-radius: 1rem
|
||||||
|
border-top-right-radius: 1rem
|
||||||
|
text-align: center
|
||||||
|
transition: .5s
|
||||||
|
&:hover
|
||||||
|
background-color: rgba(255, 255, 255, 0.8)
|
||||||
|
h2
|
||||||
|
color: black
|
||||||
|
|
||||||
|
h2
|
||||||
|
color: white
|
||||||
|
font-size: 1.1rem
|
||||||
|
line-height: 130%
|
||||||
|
font-family: 'Mainfont-Bold'
|
||||||
|
margin-bottom: 0.5rem
|
||||||
|
|
||||||
|
.mintBtn
|
||||||
|
background-color: $primaryColor
|
||||||
|
color: white
|
||||||
|
font-size: 0.9rem
|
||||||
|
font-family: 'Mainfont-Bold'
|
||||||
|
border: none
|
||||||
|
padding: 0.4rem 1rem
|
||||||
|
border-radius: 0.3rem
|
||||||
|
cursor: pointer
|
||||||
</style>
|
</style>
|
||||||
@ -1,12 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container-10">
|
<PageContent />
|
||||||
<h1>{{ $t('privacy') }}</h1>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: 'default'
|
layout: 'default'
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<section class="heroBox" :aria-label="$t('pages.services.hero.ariaLabel')">
|
<section class="heroBox_service" aria-labelledby="hero-heading">
|
||||||
<NuxtImg
|
<NuxtImg
|
||||||
provider="strapi"
|
provider="strapi"
|
||||||
src="/uploads/BG_technology_b6b0083811.png"
|
src="/uploads/large_DML_Home_Hero_4f27bc7f8e.webp"
|
||||||
class="hero-bg"
|
class="hero-bg"
|
||||||
sizes="sm:100vw md:100vw lg:100vw"
|
sizes="sm:100vw md:100vw lg:100vw"
|
||||||
alt=""
|
alt=""
|
||||||
@ -14,9 +14,9 @@
|
|||||||
fetchpriority="high"
|
fetchpriority="high"
|
||||||
/>
|
/>
|
||||||
<div class="container-10">
|
<div class="container-10">
|
||||||
<h1>{{ $t('pages.services.hero.headline1') }}</h1>
|
<h1 id="hero-heading">{{ $t('pages.home.heroBox.h1') }}</h1>
|
||||||
<h2>{{ $t('pages.services.hero.headline2') }}</h2>
|
<h2>{{ $t('pages.home.heroBox.h2') }}</h2>
|
||||||
<h3>{{ $t('pages.services.hero.headline3') }}</h3>
|
<h3>{{ $t('pages.home.heroBox.h3') }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<!-- Nach dem Container: Spiegelwelle unten -->
|
<!-- Nach dem Container: Spiegelwelle unten -->
|
||||||
<svg class="sectionWave wave-bottom" style="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 20" aria-hidden="true">
|
<svg class="sectionWave wave-bottom" style="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 20" aria-hidden="true">
|
||||||
@ -25,28 +25,78 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
||||||
<section class="explainBox" :aria-label="$t('pages.services.explain.ariaLabel')">
|
<section aria-labelledby="solution-title">
|
||||||
<NuxtImg
|
<div class="container-10 webStrategy">
|
||||||
src="/uploads/Human_Maschine_BG_5c91e9100f.webp"
|
<h2 id="solution-title">{{ $t('pages.home.solution.title') }}</h2>
|
||||||
provider="strapi"
|
<h3>{{ $t('pages.home.solution.teaser') }}</h3>
|
||||||
format="webp"
|
<p>{{ $t('pages.home.solution.text') }}</p>
|
||||||
sizes="100vw"
|
<button
|
||||||
class="background-image"
|
class="mintBtn"
|
||||||
alt=""
|
role="button"
|
||||||
aria-hidden="true"
|
aria-describedby="solution-title"
|
||||||
/>
|
aria-label="headless CMS Info" @click="navigateToArticle">
|
||||||
<div class="container-15 content">
|
{{ $t('pages.home.solution.buttonText') }}
|
||||||
<h2>{{ $t('pages.services.explain.headline1') }}</h2>
|
</button>
|
||||||
<h3>{{ $t('pages.services.explain.headline2') }}</h3>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<p>{{ $t('pages.services.explain.paragraph') }}</p>
|
<section class="targetGroup" aria-labelledby="invitation-title">
|
||||||
<ul class="check">
|
<svg class="sectionWave wave-top" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 20" aria-hidden="true">
|
||||||
<li>{{ t('pages.services.explain.bullet1') }}</li>
|
<path d="M 0 0 L 500 0 L 500 14 Q 354.4 -2.8 250 11 Q 145.6 24.8 0 14 L 0 0 Z" fill="#FFF"/>
|
||||||
<li>{{ t('pages.services.explain.bullet2') }}</li>
|
</svg>
|
||||||
<li>{{ t('pages.services.explain.bullet3') }}</li>
|
<div class="container-10">
|
||||||
<li>{{ t('pages.services.explain.bullet4') }}</li>
|
<div class="row">
|
||||||
<li>{{ t('pages.services.explain.bullet5') }}</li>
|
<div class="col-md-4"/>
|
||||||
</ul>
|
<div class="col-md-8 pt-5 pb-5">
|
||||||
|
<h2 id="invitation-title">{{ $t('pages.home.invitation.title') }}</h2>
|
||||||
|
<h3>{{ $t('pages.home.invitation.teaser') }}</h3>
|
||||||
|
<button
|
||||||
|
class="pinkBtn" role="button"
|
||||||
|
aria-describedby="invitation-title"
|
||||||
|
aria-label="Kontaktformular öffnen"
|
||||||
|
@click.prevent="toggleContactBubble">{{ $t('pages.home.invitation.button') }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<svg class="sectionWave wave-bottom" style="transform: scale(-1,-1)" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 20" aria-hidden="true">
|
||||||
|
<path d="M 0 0 L 500 0 L 500 14 Q 354.4 -2.8 250 11 Q 145.6 24.8 0 14 L 0 0 Z" fill="#FFF"/>
|
||||||
|
</svg>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="canDo" aria-labelledby="canDo-section-title">
|
||||||
|
<div class="container">
|
||||||
|
<h2 id="canDo-section-title" class="text-center">
|
||||||
|
{{ $t('pages.home.canDo.title') }}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="canDoGrid">
|
||||||
|
<div
|
||||||
|
v-for="(item, index) in canDoItems"
|
||||||
|
:key="index"
|
||||||
|
class="canDoBox"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="canDoItem"
|
||||||
|
:role="index === 2 ? 'group' : null"
|
||||||
|
:aria-labelledby="index === 2 ? 'cando-title' : null"
|
||||||
|
>
|
||||||
|
<NuxtImg
|
||||||
|
provider="strapi"
|
||||||
|
:src="item.img"
|
||||||
|
format="webp"
|
||||||
|
:modifiers="{ quality: 80 }"
|
||||||
|
sizes="xs:280px sm:300px md:350px"
|
||||||
|
class="imageBox"
|
||||||
|
loading="lazy"
|
||||||
|
:alt="item.alt"
|
||||||
|
/>
|
||||||
|
<h3 :id="index === 2 ? 'cando-title' : null">
|
||||||
|
{{ $t(item.title) }}
|
||||||
|
</h3>
|
||||||
|
<p>{{ $t(item.text) }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@ -82,6 +132,10 @@ const { t } = useI18n();
|
|||||||
const mainStore = useMainStore();
|
const mainStore = useMainStore();
|
||||||
const { projects, companyinfo } = storeToRefs(mainStore)
|
const { projects, companyinfo } = storeToRefs(mainStore)
|
||||||
|
|
||||||
|
const navigateToArticle = () => {
|
||||||
|
router.push('/wissenswertes/artikel/design-und-inhalt-sauber-getrennt-warum-headless-webdesign-die-beste-wahl-fuer-moderne-unternehmen-ist');
|
||||||
|
};
|
||||||
|
|
||||||
const projectItems = computed(() => {
|
const projectItems = computed(() => {
|
||||||
return projects.value
|
return projects.value
|
||||||
.filter(project => project.customer && project.projectImages.length > 0)
|
.filter(project => project.customer && project.projectImages.length > 0)
|
||||||
@ -102,6 +156,33 @@ const logoUrl = computed(() => {
|
|||||||
: origin + '/logo.svg';
|
: origin + '/logo.svg';
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const canDoItems = [
|
||||||
|
{
|
||||||
|
img: '/uploads/website_Erfolg_Marketing_3c36a43ba5.png',
|
||||||
|
alt: 'Website Erfolg Marketing',
|
||||||
|
title: 'pages.home.canDo.item1.title',
|
||||||
|
text: 'pages.home.canDo.item1.text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
img: '/uploads/Kundenbindung_45d45ef3fc.png',
|
||||||
|
alt: 'Kundenbindung Strategie',
|
||||||
|
title: 'pages.home.canDo.item2.title',
|
||||||
|
text: 'pages.home.canDo.item2.text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
img: '/uploads/Screen_Shot_Tool_20250228133408_beb2a11980.png',
|
||||||
|
alt: 'Screen Tool Beispiel 1',
|
||||||
|
title: 'pages.home.canDo.item3.title',
|
||||||
|
text: 'pages.home.canDo.item3.text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
img: '/uploads/Screen_Shot_Tool_20250228133812_0a20d4320e.png',
|
||||||
|
alt: 'Screen Tool Beispiel 2',
|
||||||
|
title: 'pages.home.canDo.item4.title',
|
||||||
|
text: 'pages.home.canDo.item4.text',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
// JSON_LD für Services
|
// JSON_LD für Services
|
||||||
const jsonLdServices = computed(() => {
|
const jsonLdServices = computed(() => {
|
||||||
|
|
||||||
@ -172,72 +253,179 @@ watchEffect(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="sass">
|
<style lang="sass">
|
||||||
|
.heroBox_service
|
||||||
.heroBox
|
|
||||||
position: relative
|
|
||||||
min-height: 35rem
|
|
||||||
height: 70vh
|
|
||||||
display: flex
|
|
||||||
align-items: center
|
|
||||||
justify-content: center
|
|
||||||
overflow: hidden
|
|
||||||
|
|
||||||
.hero-bg
|
|
||||||
position: absolute
|
|
||||||
inset: 0
|
|
||||||
width: 100%
|
|
||||||
height: 100%
|
|
||||||
object-fit: cover
|
|
||||||
object-position: center center
|
|
||||||
z-index: 0
|
|
||||||
|
|
||||||
.container-10, h1, h2, h3
|
|
||||||
position: relative
|
|
||||||
z-index: 1
|
|
||||||
h1, h2, h3
|
|
||||||
color: white
|
|
||||||
z-index: 2
|
|
||||||
line-height: 1.5
|
|
||||||
max-width: 70%
|
|
||||||
@media (max-width: $breakPointMD)
|
|
||||||
max-width: 100%
|
|
||||||
h1
|
|
||||||
margin-top: 0
|
|
||||||
font-size: clamp(2rem, 1.4rem + 3vw, 2.8rem)
|
|
||||||
margin-bottom: 0
|
|
||||||
font-family: 'Comfortaa'
|
|
||||||
h2
|
|
||||||
font-size: clamp(1.2rem, .7rem + 2vw, 2rem)
|
|
||||||
margin: .8rem 0 .8rem 0
|
|
||||||
font-family: 'Comfortaa'
|
|
||||||
h3
|
|
||||||
font-size: 1.2rem
|
|
||||||
|
|
||||||
.explainBox
|
|
||||||
position: relative
|
position: relative
|
||||||
|
min-height: 35rem
|
||||||
|
height: 70vh
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
justify-content: center
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
min-height: 400px
|
|
||||||
margin: 5vh 0
|
|
||||||
padding: 8vh 0
|
|
||||||
|
|
||||||
.background-image
|
.hero-bg
|
||||||
|
position: absolute
|
||||||
|
inset: 0
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
object-fit: cover
|
||||||
|
object-position: center bottom
|
||||||
|
z-index: 0
|
||||||
|
|
||||||
|
.container-10, h1, h2, h3
|
||||||
|
position: relative
|
||||||
|
z-index: 1
|
||||||
|
|
||||||
|
h1
|
||||||
|
margin-top: 3rem
|
||||||
|
z-index: 2
|
||||||
|
color: mix(black, $pink, 2%)
|
||||||
|
font-size: clamp(1rem, .8rem + 1vw, 1.2rem)
|
||||||
|
line-height: 1.5
|
||||||
|
margin-bottom: 0
|
||||||
|
max-width: 70%
|
||||||
|
@media (max-width: $breakPointMD)
|
||||||
|
max-width: 100%
|
||||||
|
h2
|
||||||
|
z-index: 2
|
||||||
|
font-size: clamp(1.4rem, .8rem + 2vw, 2.4rem)
|
||||||
|
line-height: 1.5
|
||||||
|
margin-top: 1rem
|
||||||
|
max-width: 55%
|
||||||
|
font-family: 'Comfortaa'
|
||||||
|
@media (max-width: $breakPointMD)
|
||||||
|
max-width: 90%
|
||||||
|
h3
|
||||||
|
max-width: 55%
|
||||||
|
line-height: 1.5
|
||||||
|
font-size: clamp(1rem, .8rem + 1vw, 1.6rem)
|
||||||
|
@media (max-width: $breakPointMD)
|
||||||
|
max-width: 90%
|
||||||
|
&::after
|
||||||
|
content: ''
|
||||||
position: absolute
|
position: absolute
|
||||||
top: 0
|
top: 0
|
||||||
left: 0
|
left: 0
|
||||||
width: 100%
|
width: 50%
|
||||||
height: auto
|
height: 100%
|
||||||
object-fit: contain
|
background-image: linear-gradient(to right, rgba(white, .3), transparent)
|
||||||
object-position: center center
|
|
||||||
z-index: 0
|
|
||||||
pointer-events: none
|
|
||||||
|
|
||||||
.content
|
|
||||||
position: relative
|
|
||||||
z-index: 1
|
z-index: 1
|
||||||
padding-left: 10%
|
.container
|
||||||
|
z-index: 2
|
||||||
|
|
||||||
h3
|
.webStrategy
|
||||||
font-family: 'Mainfont-Bold'
|
padding: 4rem 0 3.5rem 0
|
||||||
font-size: 1.2rem
|
h2
|
||||||
|
font-size: clamp(1.6rem, 1rem + 2vw, 1.8rem)
|
||||||
|
line-height: 150%
|
||||||
|
font-family: 'Comfortaa'
|
||||||
|
margin-left: 30%
|
||||||
|
h3
|
||||||
|
font-size: clamp(1.1rem, .75rem + 1vw, 1.25rem)
|
||||||
|
line-height: 150%
|
||||||
|
margin-left: 30%
|
||||||
|
p
|
||||||
|
margin-left: 30%
|
||||||
|
button
|
||||||
|
margin-left: 30%
|
||||||
|
&::after
|
||||||
|
content: ''
|
||||||
|
position: absolute
|
||||||
|
top: 5%
|
||||||
|
left: -36vw
|
||||||
|
width: 60vw
|
||||||
|
height: 90%
|
||||||
|
min-height: 550px
|
||||||
|
max-height: 800px
|
||||||
|
background-image: url('https://strapi.digimedialoop.de/uploads/Net_f1020a2216.png')
|
||||||
|
background-repeat: no-repeat
|
||||||
|
background-position: center right
|
||||||
|
background-size: cover
|
||||||
|
border-radius: 42% 49% 52% 48% / 53% 38% 62% 47%
|
||||||
|
animation: bubble-wobble 25s infinite ease alternate, gradient-animation 70s infinite alternate ease-in-out
|
||||||
|
box-shadow: $innerShadow
|
||||||
|
@media(max-width: $breakPointMD)
|
||||||
|
right: -50vw
|
||||||
|
.canDo
|
||||||
|
margin: 12vh 0
|
||||||
|
h2
|
||||||
|
margin-bottom: 3.5rem
|
||||||
|
font-size: clamp(1.6rem, 1rem + 2vw, 1.8rem)
|
||||||
|
.canDoGrid
|
||||||
|
display: grid
|
||||||
|
gap: 2rem
|
||||||
|
justify-content: center
|
||||||
|
align-items: stretch
|
||||||
|
grid-template-columns: 1fr // Default: 1 Spalte
|
||||||
|
|
||||||
|
@media (min-width: $breakPointMD)
|
||||||
|
grid-template-columns: repeat(2, 1fr)
|
||||||
|
|
||||||
|
@media (min-width: $breakPointXL)
|
||||||
|
grid-template-columns: repeat(4, 1fr)
|
||||||
|
|
||||||
|
.canDoBox
|
||||||
|
width: 100%
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
align-items: center
|
||||||
|
justify-content: flex-start
|
||||||
|
background-image: linear-gradient(to bottom right, transparent , white)
|
||||||
|
box-shadow: 3px 3px 8px 1px $lightgrey
|
||||||
|
border-bottom-right-radius: 1rem
|
||||||
|
padding: 1rem 1.5rem
|
||||||
|
border-right: 1px solid lighten($beige, 0%)
|
||||||
|
border-bottom: 1px solid lighten($beige, 0%)
|
||||||
|
height: 100%
|
||||||
|
|
||||||
|
.canDoItem
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
.imageBox
|
||||||
|
margin: 0rem auto 1rem auto
|
||||||
|
width: 100%
|
||||||
|
max-width: 180px
|
||||||
|
aspect-ratio: 5 / 4
|
||||||
|
object-fit: cover
|
||||||
|
border-radius: 1rem
|
||||||
|
display: block
|
||||||
|
|
||||||
|
&:nth-child(1)
|
||||||
|
border-radius: $loopShape1
|
||||||
|
&:nth-child(2)
|
||||||
|
border-radius: $loopShape2
|
||||||
|
&:nth-child(3)
|
||||||
|
border-radius: $loopShape3
|
||||||
|
&:nth-child(4)
|
||||||
|
border-radius: $loopShape4
|
||||||
|
|
||||||
|
h3
|
||||||
|
font-size: 1.2rem
|
||||||
|
line-height: 1.5rem
|
||||||
|
text-align: center
|
||||||
|
font-family: 'Mainfont-Bold'
|
||||||
|
color: darken($pink, 10%)
|
||||||
|
text-transform: uppercase
|
||||||
|
margin-bottom: .5rem
|
||||||
|
|
||||||
|
p
|
||||||
|
font-size: .9rem
|
||||||
|
text-align: left !important
|
||||||
|
|
||||||
|
|
||||||
|
.targetGroup
|
||||||
|
background-image: url('https://strapi.digimedialoop.de/uploads/smartphone_Contacts_40ae56a178.jpg')
|
||||||
|
background-repeat: no-repeat
|
||||||
|
background-size: cover
|
||||||
|
background-position: center top
|
||||||
|
min-height: 70vh
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
justify-content: center
|
||||||
|
position: relative
|
||||||
|
padding: 3rem 0
|
||||||
|
h2
|
||||||
|
font-size: clamp(1.6rem, 1rem + 2vw, 1.8rem)
|
||||||
|
h3
|
||||||
|
font-size: clamp(1.1rem, .8rem + 1vw, 1.2rem)
|
||||||
|
line-height: 150%
|
||||||
</style>
|
</style>
|
||||||
@ -1,12 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container-10">
|
<PageContent />
|
||||||
<h1>{{ $t('termsOfService') }}</h1>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: 'default'
|
layout: 'default'
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -85,20 +85,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="grafiker">
|
<!--<section class="grafiker">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<p class="supheadlineMint">{{ $t('pages.webagency.grafiker.supheadline') }}</p>
|
<p class="supheadlineMint">{{ $t('pages.webagency.grafiker.supheadline') }}</p>
|
||||||
<h2>{{ $t('pages.webagency.grafiker.title') }}</h2>
|
<h2>{{ $t('pages.webagency.grafiker.title') }}</h2>
|
||||||
<button
|
<button
|
||||||
class="mintBtn"
|
class="mintBtn"
|
||||||
@click.prevent="navigateTo('/webentwicklung-fuer-designer-und-mediengestalter')"
|
@click.prevent="navigateTo(localePath({ name: 'designer' }))"
|
||||||
role="button"
|
role="button"
|
||||||
aria-label="Zum Angebot für Kreative"
|
aria-label="Zum Angebot für Kreative"
|
||||||
>
|
>
|
||||||
{{ $t('pages.webagency.grafiker.button') }}
|
{{ $t('pages.webagency.grafiker.button') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>-->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
28
server/utils/sitemapData.ts
Normal file
28
server/utils/sitemapData.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
export async function getSitemapRoutes() {
|
||||||
|
const CMS_BASE_URL = process.env.NUXT_PUBLIC_CMS_BASE_URL
|
||||||
|
const CMS_TOKEN = process.env.NUXT_PUBLIC_CMS_TOKEN
|
||||||
|
|
||||||
|
if (!CMS_BASE_URL || !CMS_TOKEN) {
|
||||||
|
throw new Error('CMS-Umgebungsvariablen fehlen')
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers = {
|
||||||
|
Authorization: `Bearer ${CMS_TOKEN}`,
|
||||||
|
}
|
||||||
|
|
||||||
|
const [projectsRes, articlesRes] = await Promise.all([
|
||||||
|
$fetch(`${CMS_BASE_URL}/api/references?fields=link`, { headers }),
|
||||||
|
$fetch(`${CMS_BASE_URL}/api/newsarticels?fields=slug&locale=all`, { headers }),
|
||||||
|
])
|
||||||
|
|
||||||
|
const projectRoutes = projectsRes.data
|
||||||
|
.filter((p: any) => p.attributes.link)
|
||||||
|
.map((p: any) => `/projekt/${p.attributes.link}`)
|
||||||
|
|
||||||
|
const articleRoutes = articlesRes.data
|
||||||
|
.filter((a: any) => a.attributes.slug)
|
||||||
|
.map((a: any) => `/artikel/${a.attributes.slug}`)
|
||||||
|
|
||||||
|
return [...projectRoutes, ...articleRoutes]
|
||||||
|
}
|
||||||
|
|
||||||
110
stores/main.ts
110
stores/main.ts
@ -1,4 +1,5 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
|
import { useRuntimeConfig } from '#app'
|
||||||
|
|
||||||
interface CompanyLogo {
|
interface CompanyLogo {
|
||||||
url: string
|
url: string
|
||||||
@ -78,6 +79,32 @@ interface Customer {
|
|||||||
projects: CustomerProject[]
|
projects: CustomerProject[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface NewsArticle {
|
||||||
|
id: number
|
||||||
|
header: string
|
||||||
|
teaser: string
|
||||||
|
content: any
|
||||||
|
slug: string
|
||||||
|
image?: CompanyLogo | null
|
||||||
|
testfield?: string
|
||||||
|
SEO?: SEO | null
|
||||||
|
author?: {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
// optional: weitere Felder aus dem Team-Modell
|
||||||
|
} | null
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ContactData {
|
||||||
|
name: string;
|
||||||
|
email?: string;
|
||||||
|
phone?: string;
|
||||||
|
company?: string;
|
||||||
|
message: string;
|
||||||
|
language: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export const useMainStore = defineStore('main', {
|
export const useMainStore = defineStore('main', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
menuOpen: false,
|
menuOpen: false,
|
||||||
@ -88,6 +115,7 @@ export const useMainStore = defineStore('main', {
|
|||||||
pages: [] as Page[],
|
pages: [] as Page[],
|
||||||
customers: [] as Customer[],
|
customers: [] as Customer[],
|
||||||
projects: [] as CustomerProject[],
|
projects: [] as CustomerProject[],
|
||||||
|
articles: [] as NewsArticle[],
|
||||||
dataFetched: false,
|
dataFetched: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
error: null as { message: string; stack?: string } | null,
|
error: null as { message: string; stack?: string } | null,
|
||||||
@ -113,7 +141,9 @@ export const useMainStore = defineStore('main', {
|
|||||||
return page?.faqs ?? [];
|
return page?.faqs ?? [];
|
||||||
},
|
},
|
||||||
getProjectByLink: (state) => (link: string) =>
|
getProjectByLink: (state) => (link: string) =>
|
||||||
state.projects.find(project => project.link === link),
|
state.projects.find(project => project.link === link),
|
||||||
|
getArticleBySlug: (state) => (slug: string) =>
|
||||||
|
state.articles.find((a) => a.slug === slug),
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
@ -133,6 +163,41 @@ export const useMainStore = defineStore('main', {
|
|||||||
this.screenWidth = width
|
this.screenWidth = width
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// SEND CONTACT REQUEST TO STRAPI
|
||||||
|
|
||||||
|
async sendContactRequestToCMS(contactData: ContactData): Promise<void> {
|
||||||
|
const router = useRouter()
|
||||||
|
const config = useRuntimeConfig()
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios.post(
|
||||||
|
`${config.public.cmsBaseUrl}/api/contacts`,
|
||||||
|
{
|
||||||
|
data: {
|
||||||
|
name: contactData.name,
|
||||||
|
email: contactData.email,
|
||||||
|
phone: contactData.phone,
|
||||||
|
company: contactData.company,
|
||||||
|
text: contactData.message,
|
||||||
|
page: router.currentRoute.value.fullPath,
|
||||||
|
language: contactData.language,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${config.public.cmsToken}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Fehler beim Senden der Kontaktanfrage:', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// FETCH ALL THE DATA FROM STRAPI
|
||||||
async fetchInitialData() {
|
async fetchInitialData() {
|
||||||
if (this.dataFetched) return
|
if (this.dataFetched) return
|
||||||
|
|
||||||
@ -140,7 +205,7 @@ export const useMainStore = defineStore('main', {
|
|||||||
const { public: cfg } = useRuntimeConfig()
|
const { public: cfg } = useRuntimeConfig()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const [companyRes, pagesRes, customersRes, projectsRes] = await Promise.all([
|
const [companyRes, pagesRes, customersRes, projectsRes, articlesRes] = await Promise.all([
|
||||||
$fetch(`${cfg.cmsBaseUrl}/api/companyinfo?populate=*`, {
|
$fetch(`${cfg.cmsBaseUrl}/api/companyinfo?populate=*`, {
|
||||||
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
||||||
}),
|
}),
|
||||||
@ -153,6 +218,9 @@ export const useMainStore = defineStore('main', {
|
|||||||
$fetch(`${cfg.cmsBaseUrl}/api/references?populate=projectImages,Technologien,customer&sort=launchDate:desc`, {
|
$fetch(`${cfg.cmsBaseUrl}/api/references?populate=projectImages,Technologien,customer&sort=launchDate:desc`, {
|
||||||
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
||||||
}),
|
}),
|
||||||
|
$fetch(`${cfg.cmsBaseUrl}/api/newsarticels?populate=image,SEO,author&locale=all`, {
|
||||||
|
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
||||||
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
this.companyinfo = companyRes.data?.attributes ?? companyRes
|
this.companyinfo = companyRes.data?.attributes ?? companyRes
|
||||||
@ -239,6 +307,44 @@ export const useMainStore = defineStore('main', {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.articles = articlesRes.data.map((item: any) => {
|
||||||
|
const a = item.attributes
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
header: a.header,
|
||||||
|
teaser: a.teaser,
|
||||||
|
content: a.content,
|
||||||
|
slug: a.slug,
|
||||||
|
testfield: a.testfield,
|
||||||
|
image: a.image?.data
|
||||||
|
? {
|
||||||
|
url: a.image.data.attributes.url,
|
||||||
|
alternativeText: a.image.data.attributes.alternativeText,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
SEO: a.SEO
|
||||||
|
? {
|
||||||
|
pageTitle: a.SEO.pageTitle,
|
||||||
|
seoDescription: a.SEO.seoDesicription,
|
||||||
|
seoKeywords: a.SEO.seoKeywords,
|
||||||
|
type: a.SEO.type,
|
||||||
|
seoImage: a.SEO.seoImage?.data
|
||||||
|
? {
|
||||||
|
url: a.SEO.seoImage.data.attributes.url,
|
||||||
|
alternativeText: a.SEO.seoImage.data.attributes.alternativeText,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
author: a.author?.data
|
||||||
|
? {
|
||||||
|
id: a.author.data.id,
|
||||||
|
name: a.author.data.attributes.name,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
this.dataFetched = true
|
this.dataFetched = true
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const e = err as Error
|
const e = err as Error
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user