new home
This commit is contained in:
parent
b12ae0f00b
commit
97091be646
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ctaBox">
|
<div class="ctaBox">
|
||||||
<h3>{{ headline }}</h3>
|
<h3 v-if="headline">{{ headline }}</h3>
|
||||||
<p>{{ text }}</p>
|
<p v-if="text">{{ text }}</p>
|
||||||
|
<span v-if="content" v-html="content"></span>
|
||||||
<button class="btn pinkBtn mt-1" role="button" @click.prevent="toggleContactBubble">
|
<button class="btn pinkBtn mt-1" role="button" @click.prevent="toggleContactBubble">
|
||||||
{{ buttonText }}
|
{{ buttonText }}
|
||||||
</button>
|
</button>
|
||||||
@ -18,8 +19,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
headline: { type: String, required: true },
|
headline: { type: String, required: false },
|
||||||
text: { type: String, required: true },
|
text: { type: String, required: false },
|
||||||
|
content: { type: String, required: false },
|
||||||
buttonText: { type: String, required: true }
|
buttonText: { type: String, required: true }
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -46,15 +46,15 @@
|
|||||||
<svg aria-hidden="true">
|
<svg aria-hidden="true">
|
||||||
<use xlink:href="/assets/icons/collection.svg#phone" />
|
<use xlink:href="/assets/icons/collection.svg#phone" />
|
||||||
</svg>
|
</svg>
|
||||||
<span>{{ companyinfo.phone }}</span>
|
<span>{{ companyinfo?.phone }}</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div v-if="screenWidth > 768" class="pt-3">
|
<div v-if="screenWidth > 768" class="pt-3">
|
||||||
<h3>{{ $t('contactForm.ourOffice') }}</h3>
|
<h3>{{ $t('contactForm.ourOffice') }}</h3>
|
||||||
<p class="address">
|
<p class="address">
|
||||||
{{ companyinfo.company }}<br >
|
{{ companyinfo?.company }}<br >
|
||||||
{{ companyinfo.street }} <br >
|
{{ companyinfo?.street }} <br >
|
||||||
{{ companyinfo.postalcode }} {{ companyinfo.city }}
|
{{ companyinfo?.postalcode }} {{ companyinfo?.city }}
|
||||||
</p>
|
</p>
|
||||||
<p class="aspProf">{{ $t('contactForm.yourcontactperson') }} <b>Sabrina Hennrich</b></p>
|
<p class="aspProf">{{ $t('contactForm.yourcontactperson') }} <b>Sabrina Hennrich</b></p>
|
||||||
<div class="aspBox">
|
<div class="aspBox">
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import { useI18n } from 'vue-i18n'
|
|||||||
import { useMainStore } from '@/stores/main'
|
import { useMainStore } from '@/stores/main'
|
||||||
import { useHtmlConverter } from '~/composables/useHTMLConverter'
|
import { useHtmlConverter } from '~/composables/useHTMLConverter'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t, locale } = useI18n()
|
||||||
const { convertToHTML } = useHtmlConverter()
|
const { convertToHTML } = useHtmlConverter()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -38,13 +38,19 @@ const button = computed(() => props.button ?? t('faqBox.btnDefault'))
|
|||||||
|
|
||||||
const mainStore = useMainStore()
|
const mainStore = useMainStore()
|
||||||
|
|
||||||
|
const rawFaqs = computed(() =>
|
||||||
|
mainStore.getFaqsByPageLink(props.pageLink, locale.value) ?? []
|
||||||
|
)
|
||||||
|
|
||||||
const accordionItems = computed(() =>
|
const accordionItems = computed(() =>
|
||||||
mainStore.getFaqsByPageLink(props.pageLink).map(faq => ({
|
rawFaqs.value.map(faq => ({
|
||||||
title: faq.question,
|
title: faq.question,
|
||||||
html: convertToHTML(faq.answer)
|
html: convertToHTML(faq.answer)
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const toggleContactBubble = () => mainStore.toggleContactBubble()
|
const toggleContactBubble = () => mainStore.toggleContactBubble()
|
||||||
|
|
||||||
// FAQ JSON-LD
|
// FAQ JSON-LD
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2 class="pt-4 pb-3">{{ title }}</h2>
|
<span v-html="title"></span>
|
||||||
|
|
||||||
<div class="marquee">
|
<div class="marquee">
|
||||||
<div class="marquee-track" :style="`animation-duration: ${speed}s`">
|
<div class="marquee-track" :style="`animation-duration: ${speed}s`">
|
||||||
@ -120,7 +120,7 @@ const props = defineProps({
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="sass" scoped>
|
<style lang="sass">
|
||||||
.banner-wrapper
|
.banner-wrapper
|
||||||
position: relative
|
position: relative
|
||||||
margin: 3rem auto 6rem auto
|
margin: 3rem auto 6rem auto
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="services">
|
<section class="services">
|
||||||
<div class="textBox">
|
<div class="textBox">
|
||||||
<h2>Unsere Kernkompetenzen für Ihren Erfolg im Web</h2>
|
<span v-html="getHtmlBySection('home_services_header').value"></span>
|
||||||
<h3>Vier starke Säulen für Ihre Website</h3>
|
|
||||||
<p v-show="false"><b>Vier starke Säulen für Ihre Website:</b> Von barrierefrei über SEO bis hin zu Headless CMS und KI-Kompatibilität. Entdecken Sie, wie unsere spezialisierten Leistungen Ihre digitale Präsenz voranbringen. Einfach, effektiv und auf Ihre Bedürfnisse zugeschnitten.</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="serviceBoxes">
|
<div class="serviceBoxes">
|
||||||
@ -25,9 +23,10 @@
|
|||||||
<svg>
|
<svg>
|
||||||
<use :xlink:href="`/assets/icons/collection.svg#${service.icon}`" />
|
<use :xlink:href="`/assets/icons/collection.svg#${service.icon}`" />
|
||||||
</svg>
|
</svg>
|
||||||
<h3>{{ service.title }}</h3>
|
<!-- <h3>{{ service.title }}</h3>
|
||||||
<p>{{ service.description }}</p>
|
<p>{{ service.description }}</p> -->
|
||||||
<span class="link">{{ service.linktext }}</span>
|
<span v-html="getHtmlBySection(service.content).value"></span>
|
||||||
|
<span class="link">{{ $t('buttons.learnMore') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</NuxtLinkLocale>
|
</NuxtLinkLocale>
|
||||||
</div>
|
</div>
|
||||||
@ -35,36 +34,29 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
const { getHtmlBySection } = usePageContentRenderer()
|
||||||
const services = [
|
const services = [
|
||||||
{
|
{
|
||||||
title: 'Barrierefreie Webseiten',
|
content: 'home_services_accessibility',
|
||||||
description: 'Webseiten, die für alle zugänglich sind. Barrierefrei, nutzerfreundlich und technisch modern gestaltet für optimale Bedienbarkeit und bessere Reichweite.',
|
|
||||||
link: 'services-accessibility',
|
link: 'services-accessibility',
|
||||||
linktext: 'Mehr erfahren',
|
|
||||||
backgroundImage: '/uploads/DML_Service_Header_Accessibility_de8f72f0c1.webp',
|
backgroundImage: '/uploads/DML_Service_Header_Accessibility_de8f72f0c1.webp',
|
||||||
icon: 'accessibility'
|
icon: 'accessibility'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Suchmaschinen-Optimierung',
|
content: 'home_services_seo',
|
||||||
description: 'Mit technischer SEO sorgen wir für bessere Sichtbarkeit in Google & Co. Schnelle, strukturierte Webseiten, die Besucher anziehen und überzeugen.',
|
|
||||||
link: 'services-seo',
|
link: 'services-seo',
|
||||||
linktext: 'Mehr erfahren',
|
|
||||||
backgroundImage: '/uploads/DML_Service_Header_SEO_b11ae8940a.webp',
|
backgroundImage: '/uploads/DML_Service_Header_SEO_b11ae8940a.webp',
|
||||||
icon: 'search'
|
icon: 'search'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Headless CMS',
|
content: 'home_services_cms',
|
||||||
description: 'Flexibles Content-Management mit modernem Headless CMS. Schnelle Webseiten, einfache Pflege und volle Kontrolle über Inhalte und Design.',
|
|
||||||
link: 'services-cms',
|
link: 'services-cms',
|
||||||
linktext: 'Mehr erfahren',
|
|
||||||
backgroundImage: '/uploads/DML_Service_Header_CMS_a438599970.webp',
|
backgroundImage: '/uploads/DML_Service_Header_CMS_a438599970.webp',
|
||||||
icon: 'database'
|
icon: 'database'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'KI-Kompatibilität im Web',
|
content: 'home_services_ai',
|
||||||
description: 'Webseiten, die mit Künstlicher Intelligenz zusammenarbeiten. Zukunftssicher, smart optimiert und bereit für automatisierte Prozesse und Personalisierung.',
|
|
||||||
link: 'services-ai',
|
link: 'services-ai',
|
||||||
linktext: 'Mehr erfahren',
|
|
||||||
backgroundImage: '/uploads/DML_Service_Header_AI_639dd0d7b1.webp',
|
backgroundImage: '/uploads/DML_Service_Header_AI_639dd0d7b1.webp',
|
||||||
icon: 'ai'
|
icon: 'ai'
|
||||||
},
|
},
|
||||||
|
|||||||
@ -38,7 +38,7 @@
|
|||||||
{{ companyinfo?.postalcode }}
|
{{ companyinfo?.postalcode }}
|
||||||
{{ companyinfo?.city }}
|
{{ companyinfo?.city }}
|
||||||
</p>
|
</p>
|
||||||
<p><i>({{ $t('districtSta') }} | {{ $t('upperBavaria') }})</i></p>
|
<p><i>({{ $t('footer.districtSta') }} | {{ $t('footer.upperBavaria') }})</i></p>
|
||||||
<br >
|
<br >
|
||||||
<p v-if="false" class="mb-4">
|
<p v-if="false" class="mb-4">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
|
|||||||
39
composables/usePageContentRenderer.ts
Normal file
39
composables/usePageContentRenderer.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { computed } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
import { useMainStore } from '@/stores/main'
|
||||||
|
import { useHtmlConverter } from '@/composables/useHtmlConverter'
|
||||||
|
|
||||||
|
export function usePageContentRenderer() {
|
||||||
|
const { locale } = useI18n()
|
||||||
|
const mainStore = useMainStore()
|
||||||
|
const { pagecontents } = storeToRefs(mainStore)
|
||||||
|
const { convertToHTML } = useHtmlConverter()
|
||||||
|
|
||||||
|
// Hole die Inhalte für section und aktuelle Sprache, fallback auf de oder erstes Item
|
||||||
|
const getHtmlBySection = (section: string, prepend?: string) => {
|
||||||
|
return computed(() => {
|
||||||
|
if (!pagecontents.value?.length) return ''
|
||||||
|
|
||||||
|
// Filter alle Items mit der gesuchten section
|
||||||
|
const sectionItems = pagecontents.value.filter(c => c.section === section)
|
||||||
|
if (!sectionItems.length) return ''
|
||||||
|
|
||||||
|
// Suche Item passend zur aktuellen Sprache
|
||||||
|
let contentBlock = sectionItems.find(c => c.locale === locale.value)
|
||||||
|
|
||||||
|
// Falls nicht gefunden, fallback auf deutsch
|
||||||
|
if (!contentBlock) contentBlock = sectionItems.find(c => c.locale === 'de')
|
||||||
|
|
||||||
|
// Wenn immer noch nichts, fallback auf erstes Item mit der section
|
||||||
|
if (!contentBlock) contentBlock = sectionItems[0]
|
||||||
|
|
||||||
|
if (!contentBlock?.content) return ''
|
||||||
|
|
||||||
|
// content ist Array von RichTextBlöcken, convertiere zu HTML
|
||||||
|
return convertToHTML(contentBlock.content, prepend)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return { getHtmlBySection }
|
||||||
|
}
|
||||||
@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"welcome": "Willkommen",
|
"footer": {
|
||||||
"districtSta": "Landkreis Starnberg",
|
"districtSta": "Landkreis Starnberg",
|
||||||
"upperBavaria": "Oberbayern",
|
"upperBavaria": "Oberbayern"
|
||||||
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"webagency": "Webagentur",
|
"webagency": "Webagentur",
|
||||||
"menuAbout": "Über uns",
|
"menuAbout": "Über uns",
|
||||||
@ -17,6 +18,11 @@
|
|||||||
"references": "Referenzen",
|
"references": "Referenzen",
|
||||||
"contact": "Kontakt"
|
"contact": "Kontakt"
|
||||||
},
|
},
|
||||||
|
"buttons": {
|
||||||
|
"learnMore": "Mehr erfahren",
|
||||||
|
"contactUs": "Kontaktieren Sie uns!",
|
||||||
|
"ourReferences": "Unsere Referenzen"
|
||||||
|
},
|
||||||
"referenceoverview": "Referenzübersicht",
|
"referenceoverview": "Referenzübersicht",
|
||||||
"imprint": "Impressum",
|
"imprint": "Impressum",
|
||||||
"privacy": "Datenschutz",
|
"privacy": "Datenschutz",
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
mainStore.setDarkHeroBack(false) // Standardmäßig false
|
mainStore.setDarkHeroBack(false) // Standardmäßig false
|
||||||
|
mainStore.syncLocaleWithI18n()
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
130
pages/index.vue
130
pages/index.vue
@ -5,15 +5,38 @@
|
|||||||
:aria-label="$t('pages.services.hero.ariaLabel')"
|
:aria-label="$t('pages.services.hero.ariaLabel')"
|
||||||
:dark-background="true"
|
:dark-background="true"
|
||||||
>
|
>
|
||||||
<h1>High-Performance-Webseiten</h1>
|
<div v-html="getHtmlBySection('home_hero').value"></div>
|
||||||
|
<!-- <h1>High-Performance-Webseiten</h1>
|
||||||
<h2>die Ihre Zielgruppe begeistern</h2>
|
<h2>die Ihre Zielgruppe begeistern</h2>
|
||||||
<h3>Schnell, effizient und leistungsstark</h3>
|
<h3>Schnell, effizient und leistungsstark</h3>
|
||||||
<p>Wir nutzen modernste Technologien wie Nuxt 3 + Strapi in Headless-Architektur, um Webseiten zu entwickeln, die zukunftssicher, robust und flexibel sind.</p>
|
<p>Wir nutzen modernste Technologien wie Nuxt 3 + Strapi in Headless-Architektur, um Webseiten zu entwickeln, die zukunftssicher, robust und flexibel sind.</p> -->
|
||||||
<NuxtLinkLocale to="references" class="btn whiteBtn">Unsere Referenzen</NuxtLinkLocale>
|
<NuxtLinkLocale to="references" class="btn whiteBtn">{{ $t('buttons.ourReferences') }}</NuxtLinkLocale>
|
||||||
</HeroBox>
|
</HeroBox>
|
||||||
|
|
||||||
<section class="whatWeDo">
|
<section class="dmlLoop">
|
||||||
|
<span class="loopHeader" v-html="getHtmlBySection('home_loopHeader').value"></span>
|
||||||
|
<div class="content">
|
||||||
|
<div class="column">
|
||||||
|
<span v-html="getHtmlBySection('home_loopInput').value"></span>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<NuxtImg
|
||||||
|
src="/uploads/Loop_83b4311dd0.webp"
|
||||||
|
provider="strapi"
|
||||||
|
class="loopImg"
|
||||||
|
alt="Mensch"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<span v-html="getHtmlBySection('home_loopOutput').value"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<section class="whatWeDo">
|
||||||
<NuxtImg
|
<NuxtImg
|
||||||
src="/uploads/laechelnde_Dame_a393baf878.webp"
|
src="/uploads/laechelnde_Dame_a393baf878.webp"
|
||||||
provider="strapi"
|
provider="strapi"
|
||||||
@ -21,14 +44,7 @@
|
|||||||
alt="Mensch"
|
alt="Mensch"
|
||||||
/>
|
/>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h2>Webseiten für Mensch und Maschine</h2>
|
<div v-html="getHtmlBySection('home_human_machine').value"></div>
|
||||||
<h3>Design das Menschen begeistert mit Struktur die Maschinen verstehen</h3>
|
|
||||||
<p>Wir entwickeln <b>performante, barrierefreie Webseiten</b> mit <b>klarer Struktur</b>,
|
|
||||||
die Nutzer überzeugen und von Suchmaschinen wie Google oder Bing, sowie KI-Systemen optimal verstanden werden.</p>
|
|
||||||
<p>Dabei setzen wir auf moderne Standards, erfüllen rechtliche Anforderungen wie Barrierefreiheit und Datenschutz
|
|
||||||
und sorgen mit <b>zukunftsfähiger Technologie</b> dafür, dass Ihre Webseite auf dem neuesten Stand ist.</p>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<NuxtImg
|
<NuxtImg
|
||||||
src="/uploads/energy_1_e15df59b8a.webp"
|
src="/uploads/energy_1_e15df59b8a.webp"
|
||||||
@ -124,12 +140,12 @@
|
|||||||
</section> -->
|
</section> -->
|
||||||
|
|
||||||
<CallToActionBox
|
<CallToActionBox
|
||||||
:headline="$t('pages.home.finalCall.title')"
|
:content="getHtmlBySection('ctaBox_home').value"
|
||||||
|
|
||||||
:button-text="$t('pages.home.finalCall.button')"
|
:button-text="$t('buttons.contactUs')"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<MarqueeBanner :items="logoItems" :logo-height="60" :title="$t('pages.home.marqueeBanner.title')" :greyscale="true" />
|
<MarqueeBanner :items="logoItems" :logo-height="60" :title="getHtmlBySection('home_company_trustus').value" :greyscale="true" />
|
||||||
<FAQArea page-link="/" :headline="$t('pages.home.faqArea.headline')" />
|
<FAQArea page-link="/" :headline="$t('pages.home.faqArea.headline')" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -143,6 +159,8 @@ import { storeToRefs } from 'pinia';
|
|||||||
const mainStore = useMainStore();
|
const mainStore = useMainStore();
|
||||||
const { customers } = storeToRefs(mainStore);
|
const { customers } = storeToRefs(mainStore);
|
||||||
|
|
||||||
|
const { getHtmlBySection } = usePageContentRenderer()
|
||||||
|
|
||||||
const logoItems = computed(() => {
|
const logoItems = computed(() => {
|
||||||
return customers.value.map(customer => ({
|
return customers.value.map(customer => ({
|
||||||
text: customer.company || '',
|
text: customer.company || '',
|
||||||
@ -156,9 +174,85 @@ const logoItems = computed(() => {
|
|||||||
|
|
||||||
<style lang="sass">
|
<style lang="sass">
|
||||||
.homePage
|
.homePage
|
||||||
|
|
||||||
|
.dmlLoop
|
||||||
|
width: 80%
|
||||||
|
margin: 3rem 10%
|
||||||
|
h2
|
||||||
|
font-size: clamp(1.8rem, .9rem + 2vw, 2.4rem)
|
||||||
|
margin-bottom: 0
|
||||||
|
margin-top: -.5rem
|
||||||
|
h3
|
||||||
|
font-size: clamp(1.4rem, .7rem + 2vw, 2rem)
|
||||||
|
margin: 0 0 1rem 0
|
||||||
|
h4
|
||||||
|
font-size: clamp(1.2rem, .5rem + 2vw, 1.6rem)
|
||||||
|
margin: .5rem 0 1.5rem 0
|
||||||
|
p
|
||||||
|
margin-top: 1rem
|
||||||
|
.content
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
gap: 2rem
|
||||||
|
margin: 3rem 0
|
||||||
|
.column
|
||||||
|
padding: 0
|
||||||
|
border-radius: .5rem
|
||||||
|
min-width: 280px
|
||||||
|
width: calc((100% / 3) - 2rem)
|
||||||
|
// nur für 1 und 3 box
|
||||||
|
// child(1) border rights offen und child(3) border left offen
|
||||||
|
&:nth-child(1), &:nth-child(3)
|
||||||
|
//border-top: 1px solid #effbf7
|
||||||
|
border-bottom: 1px solid #effbf7
|
||||||
|
&:nth-child(1)
|
||||||
|
border-left: 1px solid #effbf7
|
||||||
|
h4
|
||||||
|
background-image: linear-gradient(to right, #effbf7, white)
|
||||||
|
&:nth-child(3)
|
||||||
|
border-right: 1px solid #effbf7
|
||||||
|
h4
|
||||||
|
background-image: linear-gradient(to right, white, #effbf7)
|
||||||
|
&:nth-child(2)
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
justify-content: center
|
||||||
|
h4
|
||||||
|
margin: 0
|
||||||
|
padding: .8rem 2rem
|
||||||
|
color: $darkgrey
|
||||||
|
|
||||||
|
border-top-left-radius: .5rem
|
||||||
|
border-top-right-radius: .5rem
|
||||||
|
font-family: 'Mainfont-Bold'
|
||||||
|
font-size: 1.1rem
|
||||||
|
text-transform: uppercase
|
||||||
|
text-align: center
|
||||||
|
letter-spacing: .05rem
|
||||||
|
|
||||||
|
p
|
||||||
|
padding: .5rem 1rem
|
||||||
|
font-size: .9rem
|
||||||
|
ul
|
||||||
|
margin-left: 2vw
|
||||||
|
li
|
||||||
|
padding: .3rem 0
|
||||||
|
|
||||||
|
.loopImg
|
||||||
|
width: 100%
|
||||||
|
height: auto
|
||||||
|
object-fit: cover
|
||||||
|
object-position: center center
|
||||||
|
|
||||||
|
|
||||||
|
@media screen and (min-width: $breakPointLG)
|
||||||
|
flex-direction: row
|
||||||
|
|
||||||
.whatWeDo
|
.whatWeDo
|
||||||
position: relative
|
position: relative
|
||||||
overflow-x: hidden
|
overflow-x: hidden
|
||||||
|
min-height: 25vw
|
||||||
|
margin: 3rem 0
|
||||||
|
|
||||||
.rightImg, .leftImg
|
.rightImg, .leftImg
|
||||||
height: 100%
|
height: 100%
|
||||||
@ -189,13 +283,13 @@ const logoItems = computed(() => {
|
|||||||
background-color: rgba(255,255,255,.8)
|
background-color: rgba(255,255,255,.8)
|
||||||
|
|
||||||
h2
|
h2
|
||||||
font-size: clamp(1.2rem, .7rem + 2vw, 2rem)
|
font-size: clamp(1.5rem, .7rem + 2vw, 2rem)
|
||||||
font-family: 'Comfortaa'
|
font-family: 'Comfortaa'
|
||||||
h3
|
h3
|
||||||
font-family: 'Mainfont-Bold'
|
font-family: 'Mainfont-Bold'
|
||||||
font-size: 1.3rem
|
font-size: clamp(1.2rem, .9rem + 2vw, 1.6rem)
|
||||||
p
|
p
|
||||||
font-size: 1.1rem
|
font-size: clamp(1rem, .5rem + 2vw, 1.2rem)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,7 @@ interface PageSection {
|
|||||||
interface FAQ {
|
interface FAQ {
|
||||||
question: string
|
question: string
|
||||||
answer: string
|
answer: string
|
||||||
|
locale: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Page {
|
interface Page {
|
||||||
@ -54,6 +55,13 @@ interface Page {
|
|||||||
pageSections: PageSection[]
|
pageSections: PageSection[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface PageContent {
|
||||||
|
id: number
|
||||||
|
section: string
|
||||||
|
content: any // Strapi Blocks – ggf. präzisieren, wenn du eine feste Struktur nutzt
|
||||||
|
locale: string
|
||||||
|
}
|
||||||
|
|
||||||
interface CustomerProject {
|
interface CustomerProject {
|
||||||
id: number
|
id: number
|
||||||
projectTitle: string
|
projectTitle: string
|
||||||
@ -111,6 +119,7 @@ interface ContactData {
|
|||||||
|
|
||||||
export const useMainStore = defineStore('main', {
|
export const useMainStore = defineStore('main', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
|
locale: 'de',
|
||||||
menuOpen: false,
|
menuOpen: false,
|
||||||
contactBoxOpen: false,
|
contactBoxOpen: false,
|
||||||
scrollPosition: 0,
|
scrollPosition: 0,
|
||||||
@ -119,6 +128,7 @@ export const useMainStore = defineStore('main', {
|
|||||||
darkHeroBack: false,
|
darkHeroBack: false,
|
||||||
companyinfo: null as CompanyInfo | null,
|
companyinfo: null as CompanyInfo | null,
|
||||||
pages: [] as Page[],
|
pages: [] as Page[],
|
||||||
|
pagecontents: [] as PageContent[],
|
||||||
customers: [] as Customer[],
|
customers: [] as Customer[],
|
||||||
projects: [] as CustomerProject[],
|
projects: [] as CustomerProject[],
|
||||||
articles: [] as NewsArticle[],
|
articles: [] as NewsArticle[],
|
||||||
@ -143,9 +153,9 @@ export const useMainStore = defineStore('main', {
|
|||||||
state.customers.find((c) => c.id === id),
|
state.customers.find((c) => c.id === id),
|
||||||
getFaqsByPageId: (state) => (pageId: number) =>
|
getFaqsByPageId: (state) => (pageId: number) =>
|
||||||
state.pages.find((p) => p.id === pageId)?.faqs ?? [],
|
state.pages.find((p) => p.id === pageId)?.faqs ?? [],
|
||||||
getFaqsByPageLink: (state) => (link: string) => {
|
getFaqsByPageLink: (state) => (link: string, locale = state.locale) => {
|
||||||
const page = state.pages.find(p => p.pageLink === link);
|
const page = state.pages.find(p => p.pageLink === link && p.locale === locale)
|
||||||
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),
|
||||||
@ -169,7 +179,12 @@ export const useMainStore = defineStore('main', {
|
|||||||
return state.articles.filter(article =>
|
return state.articles.filter(article =>
|
||||||
article.categories?.some(cat => categoryIds.includes(cat.id))
|
article.categories?.some(cat => categoryIds.includes(cat.id))
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
getPageContentBySection: (state) => (section: string): PageContent | undefined =>
|
||||||
|
state.pagecontents.find((pc) => pc.section === section),
|
||||||
|
getAllPageContentsBySection: (state) => (section: string): PageContent[] =>
|
||||||
|
state.pagecontents.filter((pc) => pc.section === section),
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
@ -194,7 +209,14 @@ export const useMainStore = defineStore('main', {
|
|||||||
setDarkHeroBack(value: boolean) {
|
setDarkHeroBack(value: boolean) {
|
||||||
this.darkHeroBack = value
|
this.darkHeroBack = value
|
||||||
},
|
},
|
||||||
|
syncLocaleWithI18n() {
|
||||||
|
const { locale } = useI18n()
|
||||||
|
this.locale = locale.value
|
||||||
|
|
||||||
|
watch(locale, (newLocale) => {
|
||||||
|
this.locale = newLocale
|
||||||
|
})
|
||||||
|
},
|
||||||
// SEND CONTACT REQUEST TO STRAPI
|
// SEND CONTACT REQUEST TO STRAPI
|
||||||
|
|
||||||
sendContactRequestToCMS: async (contactData: ContactData): Promise<void> => {
|
sendContactRequestToCMS: async (contactData: ContactData): Promise<void> => {
|
||||||
@ -235,13 +257,32 @@ export const useMainStore = defineStore('main', {
|
|||||||
const { public: cfg } = useRuntimeConfig()
|
const { public: cfg } = useRuntimeConfig()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const [companyRes, pagesRes, customersRes, projectsRes, articlesRes, categoriesRes] = await Promise.all([
|
const [companyRes, pagesRes, customersRes, projectsRes, articlesRes, categoriesRes, pageContentsRes] = 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}` },
|
||||||
}),
|
}),
|
||||||
$fetch(`${cfg.cmsBaseUrl}/api/pages?populate=*`, {
|
/* $fetch(`${cfg.cmsBaseUrl}/api/pages?populate=*`, {
|
||||||
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
||||||
|
}), */
|
||||||
|
$fetch(`${cfg.cmsBaseUrl}/api/pages`, {
|
||||||
|
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
||||||
|
params: {
|
||||||
|
locale: 'all',
|
||||||
|
populate: [
|
||||||
|
'header_image',
|
||||||
|
'SEO',
|
||||||
|
'SEO.seoImage',
|
||||||
|
'faqs',
|
||||||
|
'faqs.localizations',
|
||||||
|
'pageSections',
|
||||||
|
'pageSections.sectionImage',
|
||||||
|
'pageContents',
|
||||||
|
'pageContents.content',
|
||||||
|
].join(','),
|
||||||
|
}
|
||||||
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
$fetch(`${cfg.cmsBaseUrl}/api/customers?populate=*`, {
|
$fetch(`${cfg.cmsBaseUrl}/api/customers?populate=*`, {
|
||||||
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
||||||
}),
|
}),
|
||||||
@ -251,9 +292,31 @@ export const useMainStore = defineStore('main', {
|
|||||||
$fetch(`${cfg.cmsBaseUrl}/api/newsarticels?populate=image,SEO,categories,author&locale=all&sort=createdAt:desc`, {
|
$fetch(`${cfg.cmsBaseUrl}/api/newsarticels?populate=image,SEO,categories,author&locale=all&sort=createdAt:desc`, {
|
||||||
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
||||||
}),
|
}),
|
||||||
$fetch(`${cfg.cmsBaseUrl}/api/magazin-cats?populate=*&locale=all`, {
|
/* $fetch(`${cfg.cmsBaseUrl}/api/magazin-cats?populate=*&locale=all`, {
|
||||||
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
||||||
}),
|
}),
|
||||||
|
$fetch(`${cfg.cmsBaseUrl}/api/pagecontents?populate=*&locale=all`, {
|
||||||
|
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
||||||
|
}), */
|
||||||
|
$fetch(`${cfg.cmsBaseUrl}/api/magazin-cats`, {
|
||||||
|
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
||||||
|
params: {
|
||||||
|
locale: 'all',
|
||||||
|
populate: '*',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
$fetch(`${cfg.cmsBaseUrl}/api/pagecontents`, {
|
||||||
|
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
|
||||||
|
params: {
|
||||||
|
locale: 'all',
|
||||||
|
// Falls `content` ein RichText-Feld ist und evtl. weitere Relationen,
|
||||||
|
// solltest du die Felder explizit nennen, nicht nur '*'
|
||||||
|
populate: {
|
||||||
|
content: '*',
|
||||||
|
},
|
||||||
|
'pagination[limit]': 3000,
|
||||||
|
},
|
||||||
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
this.companyinfo = companyRes.data?.attributes ?? companyRes
|
this.companyinfo = companyRes.data?.attributes ?? companyRes
|
||||||
@ -262,6 +325,7 @@ export const useMainStore = defineStore('main', {
|
|||||||
const a = item.attributes
|
const a = item.attributes
|
||||||
return {
|
return {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
|
locale: a.locale,
|
||||||
pageName: a.pageName,
|
pageName: a.pageName,
|
||||||
pageLink: a.pageLink,
|
pageLink: a.pageLink,
|
||||||
header_image: a.header_image?.data
|
header_image: a.header_image?.data
|
||||||
@ -287,6 +351,7 @@ export const useMainStore = defineStore('main', {
|
|||||||
faqs: a.faqs?.data?.map((f: any) => ({
|
faqs: a.faqs?.data?.map((f: any) => ({
|
||||||
question: f.attributes.question,
|
question: f.attributes.question,
|
||||||
answer: f.attributes.answer,
|
answer: f.attributes.answer,
|
||||||
|
locale: f.attributes.locale,
|
||||||
})) ?? [],
|
})) ?? [],
|
||||||
pageSections: a.pageSections?.map((s: any) => ({
|
pageSections: a.pageSections?.map((s: any) => ({
|
||||||
id: s.id,
|
id: s.id,
|
||||||
@ -301,6 +366,13 @@ export const useMainStore = defineStore('main', {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.pagecontents = pageContentsRes.data.map((item: any) => ({
|
||||||
|
id: item.id,
|
||||||
|
section: item.attributes.section,
|
||||||
|
content: item.attributes.content,
|
||||||
|
locale: item.attributes.locale
|
||||||
|
}))
|
||||||
|
|
||||||
this.customers = customersRes.data.map((item: any) => {
|
this.customers = customersRes.data.map((item: any) => {
|
||||||
const a = item.attributes
|
const a = item.attributes
|
||||||
return {
|
return {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user