changes last
This commit is contained in:
parent
85d25bef0b
commit
4e47d5d19a
@ -55,10 +55,9 @@ const breadcrumbs = computed<Breadcrumb[]>(() => {
|
|||||||
const pathWithoutLang = route.path.replace(`/${loc}`, '')
|
const pathWithoutLang = route.path.replace(`/${loc}`, '')
|
||||||
const segments = pathWithoutLang.split('/').filter(Boolean)
|
const segments = pathWithoutLang.split('/').filter(Boolean)
|
||||||
|
|
||||||
|
// Ausnahme 1: /projekt/:slug → /references
|
||||||
if (segments.length === 2 && segments[0] === 'projekt') {
|
if (segments.length === 2 && segments[0] === 'projekt') {
|
||||||
const referencesPath = i18nPages.references?.[loc] || '/references'
|
const referencesPath = i18nPages.references?.[loc] || '/references'
|
||||||
|
|
||||||
// Übersetzung für "references" holen, Fallback zu englisch falls nicht vorhanden
|
|
||||||
const referencesLabel = t('references') || 'References'
|
const referencesLabel = t('references') || 'References'
|
||||||
|
|
||||||
const first = {
|
const first = {
|
||||||
@ -77,6 +76,28 @@ const breadcrumbs = computed<Breadcrumb[]>(() => {
|
|||||||
return [first, second]
|
return [first, second]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ausnahme 2: /artikel/:slug → /magazin
|
||||||
|
if (segments.length === 2 && segments[0] === 'artikel') {
|
||||||
|
const magazinePath = i18nPages.magazin?.[loc] || '/magazin'
|
||||||
|
const magazineLabel = t('magazin') || 'Magazin'
|
||||||
|
|
||||||
|
const first = {
|
||||||
|
label: magazineLabel,
|
||||||
|
labelFull: magazineLabel,
|
||||||
|
to: buildUrl(loc, magazinePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
const { label, labelFull } = formatLabel(segments[1])
|
||||||
|
const second = {
|
||||||
|
label,
|
||||||
|
labelFull,
|
||||||
|
to: route.path
|
||||||
|
}
|
||||||
|
|
||||||
|
return [first, second]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard-Fall
|
||||||
let path = ''
|
let path = ''
|
||||||
return segments.map(segment => {
|
return segments.map(segment => {
|
||||||
path += '/' + segment
|
path += '/' + segment
|
||||||
@ -88,6 +109,7 @@ const breadcrumbs = computed<Breadcrumb[]>(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
40
components/TrackingScripts.vue
Normal file
40
components/TrackingScripts.vue
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<template>
|
||||||
|
<!-- intentionally empty -->
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
if (import.meta.client) {
|
||||||
|
useHead({
|
||||||
|
script: [
|
||||||
|
{
|
||||||
|
innerHTML: `
|
||||||
|
var _paq = window._paq = window._paq || [];
|
||||||
|
_paq.push(["setDocumentTitle", document.domain + "/" + document.title]);
|
||||||
|
_paq.push(["setCookieDomain", "*.digimedialoop.de"]);
|
||||||
|
_paq.push(["disableCookies"]);
|
||||||
|
_paq.push(['trackPageView']);
|
||||||
|
_paq.push(['enableLinkTracking']);
|
||||||
|
(function() {
|
||||||
|
var u = "//analytics.digimedialoop.de/";
|
||||||
|
_paq.push(['setTrackerUrl', u + 'matomo.php']);
|
||||||
|
_paq.push(['setSiteId', '1']);
|
||||||
|
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
|
||||||
|
g.async = true; g.src = u + 'matomo.js'; s.parentNode.insertBefore(g, s);
|
||||||
|
})();
|
||||||
|
`,
|
||||||
|
type: 'text/javascript',
|
||||||
|
charset: 'utf-8',
|
||||||
|
// Optional: ID zum gezielten Sanitizer deaktivieren
|
||||||
|
hid: 'matomo-script'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://umami.digimedialoop.de/script.js',
|
||||||
|
defer: true,
|
||||||
|
'data-website-id': '7f521c0f-28b8-4ca8-82bf-150a34e14da6'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
__dangerouslyDisableSanitizersByTagID: {
|
||||||
|
'matomo-script': ['innerHTML']
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -9,7 +9,7 @@
|
|||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
style="
|
style="
|
||||||
transform: scaleY(-1) scaleX(-1) translateY(99%);
|
transform: scaleY(-1) scaleX(-1) translateY(99%);
|
||||||
fill: rgba(38, 38, 38, 0.95);
|
fill: rgba(38, 38, 38, 1);
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<g clip-path="url(#_clipPath_5kVoellZ93LI5Lc2i2b27JZsraaBm0XM)">
|
<g clip-path="url(#_clipPath_5kVoellZ93LI5Lc2i2b27JZsraaBm0XM)">
|
||||||
@ -38,7 +38,7 @@
|
|||||||
{{ companyinfo?.postalcode }}
|
{{ companyinfo?.postalcode }}
|
||||||
{{ companyinfo?.city }}
|
{{ companyinfo?.city }}
|
||||||
</p>
|
</p>
|
||||||
<p><i>{{ companyinfo?.district }}</i></p>
|
<p><i>({{ $t('districtSta') }} | {{ $t('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">
|
||||||
@ -154,7 +154,7 @@
|
|||||||
|
|
||||||
<style lang="sass">
|
<style lang="sass">
|
||||||
footer
|
footer
|
||||||
background: rgba(38,38,38,.95)
|
background-image: linear-gradient(to top , rgba(15, 15, 15, 1), rgba(38, 38, 38, 1))
|
||||||
position: relative
|
position: relative
|
||||||
width: 100vw
|
width: 100vw
|
||||||
color: white
|
color: white
|
||||||
|
|||||||
@ -49,14 +49,14 @@ export const i18nPages = {
|
|||||||
tr: '/projekt/:link'
|
tr: '/projekt/:link'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/*designer: {
|
designer: {
|
||||||
de: '/webentwicklung-fuer-designer-und-mediengestalter',
|
de: '/designer',
|
||||||
en: '/web-development-for-designers-and-media-creators',
|
en: '/designers',
|
||||||
fr: '/developpement-web-pour-designers-et-createurs-de-medias',
|
fr: '/createurs',
|
||||||
it: '/sviluppo-web-per-designer-e-creativi-multimediali',
|
it: '/designer',
|
||||||
es: '/desarrollo-web-para-disenadores-y-creadores-de-medios',
|
es: '/disenadores',
|
||||||
tr: '/tasarimcilar-ve-medya-uzmanlari-icin-web-gelistirme'
|
tr: '/tasarimcilar'
|
||||||
},*/
|
},
|
||||||
privacy: {
|
privacy: {
|
||||||
de: '/datenschutz',
|
de: '/datenschutz',
|
||||||
en: '/privacy',
|
en: '/privacy',
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
{
|
{
|
||||||
"welcome": "Willkommen",
|
"welcome": "Willkommen",
|
||||||
|
"districtSta": "Landkreis Starnberg",
|
||||||
|
"upperBavaria": "Oberbayern",
|
||||||
"webagency": "Webagentur",
|
"webagency": "Webagentur",
|
||||||
"services": "Leistungen",
|
"services": "Leistungen",
|
||||||
"contact": "Kontakt",
|
"contact": "Kontakt",
|
||||||
@ -56,9 +58,9 @@
|
|||||||
"pages": {
|
"pages": {
|
||||||
"home": {
|
"home": {
|
||||||
"heroBox": {
|
"heroBox": {
|
||||||
"h1": "Ihre Agentur für individuelles Webdesign und professionelle Webentwicklung",
|
"h1": "Modulare Weblösungen für Ihren Erfolg",
|
||||||
"h2": "Modulare Webseiten mit modernsten Technologien",
|
"h2": "Wir entwickeln performante Websites mit Fokus auf Skalierbarkeit, Wartbarkeit und Sichtbarkeit",
|
||||||
"h3": "Höchste Performanz - schnell, effizient und zukunftssicher!"
|
"h3": "Wir bringen Ihre digitale Infrastruktur auf ein neues Level."
|
||||||
},
|
},
|
||||||
"solution": {
|
"solution": {
|
||||||
"title": "Performance, KI-Kompatibilität & Barrierefreiheit",
|
"title": "Performance, KI-Kompatibilität & Barrierefreiheit",
|
||||||
@ -178,6 +180,13 @@
|
|||||||
"teaser1": "In unserem Wissensbereich zeigen wir, worauf es bei Suchmaschinen-Optimierung, Barrierefreiheit, Webdesign, Webperformance und Online-Marketing ankommt.",
|
"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.",
|
"teaser2": "Entdecken Sie aktuelle Trends und praxisnahe Tipps, um Ihre Online-Präsenz gezielt zu stärken.",
|
||||||
"readmore": "Artikel lesen"
|
"readmore": "Artikel lesen"
|
||||||
|
},
|
||||||
|
"article": {
|
||||||
|
"artikelUebersicht": "Artikelübersicht",
|
||||||
|
"autor": "Autor:",
|
||||||
|
"aktualisiert": "Aktualisiert am:",
|
||||||
|
"ladenOderNichtGefunden": "Der Artikel wird geladen oder wurde nicht gefunden.",
|
||||||
|
"kontaktieren": "Jetzt kontaktieren"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,22 +1,27 @@
|
|||||||
<!-- layouts/default.vue -->
|
<!-- layouts/default.vue -->
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<ClientOnly>
|
||||||
|
<TrackingScripts />
|
||||||
|
</ClientOnly>
|
||||||
<PageHeader />
|
<PageHeader />
|
||||||
<ContactForm />
|
<ContactForm />
|
||||||
<BackToTopBtn />
|
<BackToTopBtn />
|
||||||
<main>
|
<main>
|
||||||
<Breadcrumbs />
|
<Breadcrumbs />
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
<PageFooter />
|
<PageFooter />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|
||||||
import { usePageMeta } from '~/composables/usePageMeta'
|
import { usePageMeta } from '~/composables/usePageMeta'
|
||||||
|
|
||||||
usePageMeta()
|
usePageMeta()
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="sass">
|
<style lang="sass">
|
||||||
@ -103,7 +108,7 @@ main
|
|||||||
.loopShape
|
.loopShape
|
||||||
border-radius: $loopShape
|
border-radius: $loopShape
|
||||||
|
|
||||||
button
|
button, .btn
|
||||||
background-color: white
|
background-color: white
|
||||||
border: 1px solid $darkgrey
|
border: 1px solid $darkgrey
|
||||||
border-radius: 5px
|
border-radius: 5px
|
||||||
@ -115,6 +120,7 @@ main
|
|||||||
transition: all 0.4s ease-in-out
|
transition: all 0.4s ease-in-out
|
||||||
z-index: 1
|
z-index: 1
|
||||||
color: $darkgrey
|
color: $darkgrey
|
||||||
|
text-decoration: none
|
||||||
&::before
|
&::before
|
||||||
content: ''
|
content: ''
|
||||||
position: absolute
|
position: absolute
|
||||||
|
|||||||
25
pages/[...all].vue
Normal file
25
pages/[...all].vue
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<template>
|
||||||
|
<section>
|
||||||
|
<div class="container-20 topSpace">
|
||||||
|
<h1>Seite nicht gefunden (404)</h1>
|
||||||
|
<h2>Sorry, diese Seite gibt es nicht</h2>
|
||||||
|
<p>
|
||||||
|
Aber ganz ehrlich: Wenn du eine High-Speed-Website willst, die wirklich performt und Besucher begeistert, bist du hier genau richtig.<br>
|
||||||
|
</p><p>
|
||||||
|
Wir setzen dich nicht nur ins Netz – wir bringen dich nach vorne.
|
||||||
|
</p>
|
||||||
|
<NuxtLink to="/" class="btn mintBtn" aria-label="Zur Startseite">
|
||||||
|
Zur Startseite
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
// Nuxt 3 behandelt den 404-Status automatisch
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="sass">
|
||||||
|
|
||||||
|
</style>
|
||||||
@ -1,16 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="article" v-if="article">
|
<div class="article" v-if="article">
|
||||||
<SideBarNaviSlider link="/wissenswertes">
|
<SideBarNaviSlider link="/wissenswertes">
|
||||||
{{ $t('artikel.artikelUebersicht') /* Beispiel für i18n */ }}
|
{{ $t('pages.article.artikelUebersicht') }}
|
||||||
</SideBarNaviSlider>
|
</SideBarNaviSlider>
|
||||||
|
|
||||||
<section class="teaserBox topSpace">
|
<section class="teaserBox topSpace">
|
||||||
<div class="container-10">
|
<div class="container-10">
|
||||||
<p class="articleInfo">
|
<p class="articleInfo">
|
||||||
<b>{{ $t('artikel.autor') }}</b> {{ author }} |
|
<b>{{ $t('pages.article.autor') }}</b> {{ author }} <!--|
|
||||||
<b>{{ $t('artikel.aktualisiert') }}</b> {{ formattedDate }}
|
<b>{{ $t('pages.article.aktualisiert') }}</b> {{ formattedDate }}-->
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<NuxtImg
|
<NuxtImg
|
||||||
v-if="article.image?.url"
|
v-if="article.image?.url"
|
||||||
:src="article.image.url"
|
:src="article.image.url"
|
||||||
@ -23,30 +23,30 @@
|
|||||||
:sizes="'(max-width: 600px) 90vw, 350px'"
|
:sizes="'(max-width: 600px) 90vw, 350px'"
|
||||||
role="img"
|
role="img"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<h1>{{ article.header }}</h1>
|
<h1>{{ article.header }}</h1>
|
||||||
|
<p class="teaser">{{ article.teaser }}</p>
|
||||||
<p class="teaser">{{ article.teaser }}</p>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
</section>
|
|
||||||
|
<section class="articleBox container">
|
||||||
<section class="articleBox container">
|
<div v-html="htmlContent(article.content)" class="content"></div>
|
||||||
<div v-html="htmlContent(article.content)" class="content"></div>
|
<button
|
||||||
<button
|
@click.prevent="toggleContactBubble"
|
||||||
@click.prevent="toggleContactBubble"
|
class="pinkBtn"
|
||||||
class="pinkBtn"
|
role="button"
|
||||||
role="button"
|
aria-label="Kontakt aufnehmen"
|
||||||
aria-label="Kontakt aufnehmen"
|
>
|
||||||
>
|
{{ $t('pages.article.kontaktieren') }}
|
||||||
{{ $t('kontakt.kontaktieren') }}
|
</button>
|
||||||
</button>
|
</section>
|
||||||
</section>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div v-else class="container topSpace">
|
||||||
<div v-else class="container topSpace">
|
<p>{{ $t('pages.article.ladenOderNichtGefunden') }}</p>
|
||||||
<p>{{ $t('artikel.ladenOderNichtGefunden') }}</p>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|||||||
@ -119,7 +119,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<Recommendations />
|
<Recommendations />
|
||||||
<section class="contrastCalcLink">
|
<section class="contrastCalcLink" v-if="false">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<img src="https://strapi.digimedialoop.de/uploads/wcag_kontrastrechner_77abf9d9be.png" alt="kontrast check" class="imgRight">
|
<img src="https://strapi.digimedialoop.de/uploads/wcag_kontrastrechner_77abf9d9be.png" alt="kontrast check" class="imgRight">
|
||||||
<p class="supheadlinePink">Barrierefreies Webdesign</p>
|
<p class="supheadlinePink">Barrierefreies Webdesign</p>
|
||||||
|
|||||||
@ -180,7 +180,7 @@ const logoItems = computed(() => {
|
|||||||
@media (max-width: $breakPointMD)
|
@media (max-width: $breakPointMD)
|
||||||
max-width: 100%
|
max-width: 100%
|
||||||
h1
|
h1
|
||||||
margin-top: 0
|
margin-top: 3rem
|
||||||
font-size: clamp(2rem, 1.4rem + 3vw, 2.8rem)
|
font-size: clamp(2rem, 1.4rem + 3vw, 2.8rem)
|
||||||
margin-bottom: 0
|
margin-bottom: 0
|
||||||
font-family: 'Comfortaa'
|
font-family: 'Comfortaa'
|
||||||
@ -195,7 +195,7 @@ const logoItems = computed(() => {
|
|||||||
position: relative
|
position: relative
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
min-height: 400px
|
min-height: 400px
|
||||||
margin: 5vh 0
|
margin: 2vh 0 8vh 0
|
||||||
padding: 8vh 0
|
padding: 8vh 0
|
||||||
|
|
||||||
.background-image
|
.background-image
|
||||||
|
|||||||
@ -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(localePath({ name: 'designer' }))"
|
@click.prevent="navigateTo(designerLink)"
|
||||||
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>
|
||||||
|
|
||||||
@ -109,6 +109,11 @@ import { useMainStore } from "@/stores/main";
|
|||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import { useRouter } from "nuxt/app";
|
import { useRouter } from "nuxt/app";
|
||||||
|
|
||||||
|
import { i18nPages } from '@/i18n/i18n-pages'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
const { locale } = useI18n()
|
||||||
|
const designerLink = i18nPages.designer?.[locale.value] || '/designer'
|
||||||
|
|
||||||
const mainStore = useMainStore();
|
const mainStore = useMainStore();
|
||||||
const { companyinfo } = storeToRefs(mainStore);
|
const { companyinfo } = storeToRefs(mainStore);
|
||||||
const toggleContactBubble = () => mainStore.toggleContactBubble();
|
const toggleContactBubble = () => mainStore.toggleContactBubble();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user