Add panoramablick implementation
All checks were successful
Build and deploy updated apps / Build & deploy (push) Successful in 2m12s

This commit is contained in:
Dominik Milacher 2025-06-13 23:11:04 +02:00
parent e1bb934f20
commit 85d080ab05
45 changed files with 2140 additions and 9 deletions

View File

@ -0,0 +1,9 @@
export default defineAppConfig({
ui: {
colors: {
primary: 'gimblet',
secondary: 'sapphire',
neutral: 'sandstone'
}
}
})

View File

@ -0,0 +1,73 @@
@import "tailwindcss";
@import "@nuxt/ui";
.red {
border: 1px solid red;
}
.green {
border: 1px solid green;
}
@layer utilities {
.text-outline {
-webkit-text-stroke: 1px black;
color: gold;
}
.pxr {
@apply px-4 sm:px-6 lg:px-8;
}
.pyr {
@apply py-4 sm:py-6 lg:py-8;
}
.pr {
@apply p-4 sm:p-6 lg:p-8;
}
}
@theme static {
--color-gimblet: oklch(74.37% 0.06969 91.48);
--color-gimblet-50: oklch(97.851% 0.00669 97.351);
--color-gimblet-100: oklch(95.198% 0.01238 91.52);
--color-gimblet-200: oklch(90.103% 0.02653 90.109);
--color-gimblet-300: oklch(84.858% 0.04176 91.748);
--color-gimblet-400: oklch(79.678% 0.056 91.049);
--color-gimblet-500: oklch(74.37% 0.06969 91.48);
--color-gimblet-600: oklch(66.9% 0.08657 90.713);
--color-gimblet-700: oklch(55.892% 0.07041 91.887);
--color-gimblet-800: oklch(44.164% 0.05385 91.131);
--color-gimblet-900: oklch(31.471% 0.0355 91.688);
--color-sapphire-50: oklch(97.5% 0.005 260);
--color-sapphire-100: oklch(95.2% 0.01 260);
--color-sapphire-200: oklch(90% 0.02 260);
--color-sapphire-300: oklch(84% 0.035 260);
--color-sapphire-400: oklch(78% 0.05 260);
--color-sapphire-500: oklch(72% 0.065 260);
--color-sapphire-600: oklch(65% 0.075 260);
--color-sapphire-700: oklch(54% 0.06 260);
--color-sapphire-800: oklch(42% 0.045 260);
--color-sapphire-900: oklch(30% 0.03 260);
--color-sandstone-50: oklch(98% 0.003 85);
--color-sandstone-100: oklch(96% 0.006 85);
--color-sandstone-200: oklch(92% 0.012 85);
--color-sandstone-300: oklch(87% 0.02 85);
--color-sandstone-400: oklch(80% 0.03 85);
--color-sandstone-500: oklch(72% 0.035 85);
--color-sandstone-600: oklch(63% 0.03 85);
--color-sandstone-700: oklch(50% 0.025 85);
--color-sandstone-800: oklch(38% 0.02 85);
--color-sandstone-900: oklch(26% 0.015 85);
}
:root {
--ui-radius: 0rem;
}
html {
scroll-behavior: smooth;
}

View File

@ -0,0 +1,5 @@
<template>
<div>
This is an auto-imported component
</div>
</template>

View File

@ -0,0 +1,60 @@
<template>
<section class="w-full">
<!-- two-column card ----------------------------->
<div class="grid gap-8 lg:grid-cols-2 bg-white rounded-lg overflow-hidden">
<!-- left half : image carousel -->
<AppThumbnailCarousel></AppThumbnailCarousel>
<!-- right half : text (top) & icons (bottom) -->
<div class="flex flex-col h-full p-6">
<!-- title + intro copy -->
<div class="flex flex-col gap-4">
<div>
<h2 class="text-3xl font-bold text-neutral-900 mb-2">
{{ rt(apartment.title) }}
</h2>
<p class="text-neutral-700">
{{
rt(apartment.subtitle)
}}
</p>
</div>
<AppFeaturesGrid :features="apartment.features"/>
</div>
<div class="flex-1"></div>
<div class="flex justify-end">
<div class="flex flex-row gap-4 ">
<UButton
to="/contact"
size="md"
color="primary"
variant="outline"
trailing-icon="i-heroicons-envelope"
>
{{ t('button.contact') }}
</UButton>
<UButton
to="/book"
size="md"
color="primary"
variant="solid"
trailing-icon="i-heroicons-globe-alt"
>
{{ t('button.book') }}
</UButton>
</div>
</div>
</div>
</div>
</section>
</template>
<script setup lang="ts">
import type {Apartment} from '@/composables/useApartments'
const {t, tm, rt} = useI18n()
defineProps<{ apartment: Apartment }>()
</script>

View File

@ -0,0 +1,24 @@
<script setup lang="ts">
const props = defineProps({
id: {type: String, default: undefined},
padTop: {type: Boolean, default: true},
padBottom: {type: Boolean, default: true}
})
</script>
<template>
<!-- bind the id renders only when props.id is truthy -->
<section :id="props.id" class="w-full">
<AppStripe>
<div :class="[
props.padTop && 'pt-12',
props.padBottom && 'pb-12'
]">
<div class="bg-neutral-100 border border-neutral-200">
<slot/>
</div>
</div>
</AppStripe>
</section>
</template>

View File

@ -0,0 +1,42 @@
<template>
<div
class="grid gap-y-8 gap-x-10
grid-cols-[repeat(auto-fit,minmax(12rem,1fr))]">
<div
v-for="(feat, idx) in features"
:key="idx"
class="flex items-start gap-4">
<UIcon
:name="`i-lucide-${rt(feat.icon)}`"
class="w-6 h-6 shrink-0 text-primary-600 mt-0.5"
/>
<div>
<h3 class="font-semibold text-neutral-700 leading-tight">
{{ rt(feat.label) }}
</h3>
<p
v-if="feat.detail"
class="text-sm text-neutral-600">
{{ rt(feat.detail) }}
</p>
</div>
</div>
</div>
</template>
<script setup lang="ts">
interface Feature {
icon: string
label: string
detail?: string
}
const props = defineProps<{
features: Feature[]
}>()
const {t, tm, rt} = useI18n()
</script>

View File

@ -0,0 +1,11 @@
<template>
<section class="w-full bg-neutral-100 border-t border-b border-neutral-200">
<AppStripe>
<div class="py-12">
<slot/>
</div>
</AppStripe>
</section>
</template>
<script setup lang="ts">
</script>

View File

@ -0,0 +1,78 @@
<template>
<footer class="bg-neutral-100 border-t border-neutral-200">
<AppStripe>
<!-- 📌 contact block -->
<div
class="flex flex-col sm:flex-row sm:items-center sm:justify-between
gap-4 py-4 border-b border-neutral-300"
>
<!-- avatar + copy -->
<AppHero src="/host.png"
alt="Ihre Gastgeberin Monika"
:size="16"
:title="t('footer.questions')"
:description="t('footer.prompt')">
<!-- Contact shortcuts -->
<div class="mt-2 space-y-1 text-sm">
<!-- Phone (phone + WhatsApp icons) -->
<div class="flex items-center gap-2">
<!-- Heroicons phone -->
<UIcon name="i-heroicons-phone" class="w-4 h-4 text-primary-600"/>
<!-- WhatsApp icon (any Iconify set you use) -->
<UIcon name="i-uil-whatsapp" class="w-4 h-4 text-primary-600"/>
<a :href="`tel:${t('contact.phone').replace(/\s+/g, '')}`" class="hover:underline">
{{ t('contact.phone') }}
</a>
</div>
<!-- E-mail -->
<div class="flex items-center gap-2">
<UIcon name="i-heroicons-envelope" class="w-4 h-4 text-primary-600"/>
<a :href="`mailto:${t('contact.email')}`" class="hover:underline">
{{ t('contact.email') }}
</a>
</div>
</div>
</AppHero>
<div class="flex flex-col gap-4 ">
<UButton
to="/contact"
size="md"
color="primary"
variant="solid"
trailing-icon="i-heroicons-envelope"
>
{{ t('button.contact') }}
</UButton>
<UButton
to="/book"
size="md"
color="primary"
variant="solid"
trailing-icon="i-heroicons-globe-alt"
>
{{ t('button.book') }}
</UButton>
</div>
</div>
<!-- © line -->
<div class="pt-4 text-center text-sm text-neutral-600 flex flex-col py-4">
<span>&copy; {{ year }} Panoramablick Saalbach</span>
<div>
<NuxtLink to="/legal#imprint" :external="true" class="underline ml-2">Impressum</NuxtLink>
<NuxtLink to="/legal#privacy" :external="true" class="underline ml-2">Datenschutz</NuxtLink>
<NuxtLink to="/legal#accessability" :external="true" class="underline ml-2">Barrierefreiheit</NuxtLink>
</div>
</div>
</AppStripe>
</footer>
</template>
<script setup lang="ts">
const {t, tm, rt} = useI18n()
const year = new Date().getFullYear()
</script>

View File

@ -0,0 +1,30 @@
<template>
<header class="sticky top-0 z-50 bg-neutral-200 shadow">
<AppStripe>
<nav class="mx-auto py-4 flex items-center justify-between">
<!-- your logo / home link -->
<NuxtLink to="/" class="text-xl font-semibold">
{{ t('header.home') }}
</NuxtLink>
<!-- nav links -->
<ul class="flex space-x-6">
<li>
<NuxtLink to="/apartments">{{ t('header.apartments') }}</NuxtLink>
</li>
<li>
<NuxtLink to="/book">{{ t('header.book') }}</NuxtLink>
</li>
<li>
<NuxtLink to="/contact">{{ t('header.contact') }}</NuxtLink>
</li>
<AppLocaleSwitcher/>
</ul>
</nav>
</AppStripe>
</header>
</template>
<script setup lang="ts">
const {t, tm, rt} = useI18n()
</script>

View File

@ -0,0 +1,55 @@
<script setup lang="ts">
import {computed} from 'vue'
const props = defineProps({
/* Path or URL for the portrait image */
src: {type: String, required: true},
/* Alt text for the image */
alt: {type: String, default: ''},
/**
* Tailwind size token (e.g. 14 w-14 h-14 or "full" w-full h-full).
* Defaults to 14 (= 3.5 rem = 56 px).
*/
size: {type: [Number, String], default: 14},
/* Heading / description */
title: {type: String, required: true},
description: {type: String, required: true},
/* Image left or right */
imageSide: {type: String as () => 'left' | 'right', default: 'left'},
/* Extra wrapper classes */
wrapperClass: {type: String, default: ''}
})
/* Tailwind width/height classes */
const sizeClasses = computed(() => `w-${props.size} h-${props.size}`)
/* If the token is numeric, convert to px for NuxtImg width/height props */
const numericSize = computed(() => {
const n = Number(props.size)
return Number.isFinite(n) ? n * 4 /* Tailwind token ×4 px */ : undefined
})
const wrapperFlex = computed(() =>
props.imageSide === 'right' ? 'flex-row-reverse text-right' : 'flex-row text-left'
)
</script>
<template>
<div :class="['flex items-center gap-4', wrapperFlex, wrapperClass]">
<NuxtImg
:src="src"
:alt="alt"
:width="numericSize"
:height="numericSize"
class="rounded-full object-cover shrink-0"
:class="sizeClasses"
/>
<div>
<p class="font-semibold text-neutral-900">{{ title }}</p>
<p class="text-sm text-neutral-600">{{ description }}</p>
<slot/>
</div>
</div>
</template>

View File

@ -0,0 +1,14 @@
<script setup>
const {locale, locales} = useI18n()
const switchLocalePath = useSwitchLocalePath()
const availableLocales = computed(() => {
return locales.value.filter(i => i.code !== locale.value)
})
</script>
<template>
<NuxtLink v-for="locale in availableLocales" :key="locale.code" :to="switchLocalePath(locale.code)">
{{ locale.code.toUpperCase() }}
</NuxtLink>
</template>

View File

@ -0,0 +1,12 @@
<script setup lang="ts">
defineOptions({inheritAttrs: false})
const {innerClass = 'px-4 sm:px-6 lg:px-8'} = defineProps<{ innerClass?: string }>()
</script>
<template>
<div class="w-full flex justify-center">
<div :class="['w-full max-w-6xl', innerClass]" v-bind="$attrs">
<slot/>
</div>
</div>
</template>

View File

@ -0,0 +1,63 @@
<script setup lang="ts">
import {ref} from 'vue'
import {useTemplateRef} from '#imports'
interface Props {
images?: string[] // Fragezeichen = optional
}
const props = withDefaults(defineProps<Props>(), {
images: () => [
'/ap-1/1.webp',
'/ap-1/2.webp'
]
})
/* ───────── shared slider state ───────── */
const carousel = useTemplateRef('carousel')
const activeIndex = ref(0)
function onSelect(index: number) {
activeIndex.value = index
}
function select(index: number) {
activeIndex.value = index
carousel.value?.emblaApi?.scrollTo(index)
}
</script>
<template>
<div class="flex flex-col items-center justify-center p-4">
<!-- main slider -->
<UCarousel
ref="carousel"
v-slot="{ item }"
:items="props.images"
:autoplay="{ delay: 5_000 }"
:ui="{item: 'ps-0'}"
loop
class="relative w-full max-w-3xl"
@select="onSelect"
>
<img :src="item" class="w-full h-auto object-cover" alt="Bild"/>
</UCarousel>
<!-- thumbnails -->
<div class="flex gap-2 pt-4">
<button
v-for="(thumb, idx) in props.images"
:key="idx"
@click="select(idx)"
:class="[
'size-16 rounded-lg overflow-hidden opacity-40 hover:opacity-100',
'transition-opacity focus:outline-none focus-visible:ring',
activeIndex === idx && 'opacity-100 ring-2 ring-primary-500'
]"
>
<img :src="thumb" alt="" class="w-full h-full object-cover"/>
</button>
</div>
</div>
</template>

View File

@ -0,0 +1,27 @@
<!-- components/TransBlock.vue -->
<template>
<div class="flex-1">
<!-- title -->
<h2 class="text-2xl font-bold mb-4">
{{ t(`${i18nKey}.title`) }}
</h2>
<!-- description (optional) -->
<p
v-if="true"
class="text-gray-700 text-lg pb-4">
{{ t(`${i18nKey}.description`) }}
</p>
<!-- anything the parent puts in here -->
<slot/>
</div>
</template>
<script setup lang="ts">
const props = defineProps<{
i18nKey: string
}>()
const {t, tm, rt} = useI18n()
</script>

View File

@ -0,0 +1,22 @@
// ~/composables/useApartments.ts
import {computed} from 'vue' // ① explizit importieren
import {useI18n} from '#imports'
export interface Apartment {
title: string
subtitle: string
images: string[]
features: { icon: string; label: string }[]
}
export function useApartments() {
const {t} = useI18n()
const list = computed(() =>
t('apartments') as unknown as Apartment[]
)
const lst = list//[1, 2, 3]
return {lst}
}

View File

@ -0,0 +1,363 @@
{
"header": {
"home": "Landhaus Panoramablick",
"apartments": "Apartments & Preise",
"book": "Buchen",
"contact": "Kontakt"
},
"footer": {
"questions": "Fragen oder Wünsche?",
"prompt": "Monika freut sich von Ihnen zu hören!"
},
"button": {
"apartments": "Apartments",
"book": "Buchen",
"contact": "Kontakt",
"hosts": "Die Gastgeber",
"map": "Maps Öffnen"
},
"features": [
{
"icon": "wifi",
"label": "Schnelles WLAN",
"detail": "Stabile 250 MBit/s Leitung im ganzen Haus."
},
{
"icon": "car-front",
"label": "Gratis Parkplatz",
"detail": "Kostenlose Stellplätze direkt vor der Tür."
},
{
"icon": "map-pin",
"label": "Exzellente Lage",
"detail": "5 Min. zur Altstadt, 3 Min. zum Bahnhof."
},
{
"icon": "users",
"label": "Liebenswürdige Gastgeber",
"detail": "Persönliche Tipps & herzlicher Service rund um die Uhr."
},
{
"icon": "trees",
"label": "Atemberaubendes Panorama",
"detail": "Nur das beste für die Gäste."
},
{
"icon": "bike",
"label": "Sportgeschäft in nächster Nähe",
"detail": "Lirum larum löffelstiel, Bründl."
},
{
"icon": "heater",
"label": "Sauna verfügbar",
"detail": "Ene mene miste."
}
],
"landing": {
"welcome": {
"title": "Willkommen im Landhaus Panoramablick",
"description": "Genießen Sie erholsame Tage inmitten der Natur mit herrlichem Ausblick auf die Berge. Unser Landhaus bietet gemütliche Apartments und herzliche Gastfreundschaft."
},
"highlight": {
"title": "Erleben Sie Natur hautnah",
"description": "Unser Landhaus liegt eingebettet in idyllischer Landschaft mit atemberaubendem Ausblick. Ob Wandern, Entspannen oder die Umgebung erkunden bei uns finden Sie Ruhe und Erholung."
},
"location": {
"title": "Logieren Sie in bester Lage",
"description": "Blabla asdfasdf asdf asdf asdf asddf asddf asdf asdf asdfasd ffad."
},
"apartments": {
"title": "Unsere Apartments",
"description": "Blabla asdfasdf asdf asdf asdf asddf asddf asdf asdf asdfasd ffad."
},
"features": {
"title": "Das erwartet Sie",
"description": "Blabla asdfasdf asdf asdf asdf asddf asddf asdf asdf asdfasd ffad."
}
},
"apartments": {
"highlight": {
"title": "Das gibt es bei uns",
"description": "Es ist alles so toll"
},
"list": [
{
"id": "apartment-1",
"title": "Apartment 1",
"subtitle": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
"thumbnail": "/ap-1/1.webp",
"highlights": [
"Ab € 225,- pro Tag",
"4 Personen"
],
"images": [
"/ap-1/1.webp",
"/ap-1/2.webp"
],
"features": [
{
"icon": "wifi",
"label": "Schnelles WLAN"
},
{
"icon": "car-front",
"label": "Parkplatz"
},
{
"icon": "map-pin",
"label": "Exzellente Lage"
},
{
"icon": "users",
"label": "Liebens­würdige Gastgeber"
},
{
"icon": "trees",
"label": "Panorama"
},
{
"icon": "bike",
"label": "Sport­geschäft in Nähe"
},
{
"icon": "heater",
"label": "Sauna"
}
]
},
{
"id": "apartment-2",
"title": "Apartment 2",
"subtitle": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
"thumbnail": "/ap-1/1.webp",
"highlights": [
"Ab € 225,- pro Tag",
"4 Personen"
],
"images": [
"/ap-2/1.webp",
"/ap-2/2.webp"
],
"features": [
{
"icon": "wifi",
"label": "Schnelles WLAN"
},
{
"icon": "car-front",
"label": "Parkplatz"
},
{
"icon": "map-pin",
"label": "Exzellente Lage"
},
{
"icon": "users",
"label": "Liebens­würdige Gastgeber"
},
{
"icon": "trees",
"label": "Panorama"
},
{
"icon": "bike",
"label": "Sport­geschäft in Nähe"
},
{
"icon": "heater",
"label": "Sauna"
}
]
},
{
"id": "apartment-3",
"title": "Apartment 3",
"subtitle": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
"thumbnail": "/ap-1/1.webp",
"highlights": [
"Ab € 225,- pro Tag",
"4 Personen"
],
"images": [
"/ap-2/1.webp",
"/ap-2/2.webp"
],
"features": [
{
"icon": "wifi",
"label": "Schnelles WLAN"
},
{
"icon": "car-front",
"label": "Parkplatz"
},
{
"icon": "map-pin",
"label": "Exzellente Lage"
},
{
"icon": "users",
"label": "Liebens­würdige Gastgeber"
},
{
"icon": "trees",
"label": "Panorama"
},
{
"icon": "bike",
"label": "Sport­geschäft in Nähe"
},
{
"icon": "heater",
"label": "Sauna"
}
]
}
]
},
"contact": {
"title": "Kontakt aufnehmen",
"description": "Wir freuen uns auf Ihre Anfrage Sie erreichen uns per Telefon, SMS, WhatsApp, E-Mail oder über das untenstehende Formular.",
"phone": "+43 123 456789",
"email": "info{'@'}panoramablick-saalbach.at",
"online-1": "Sie wollen direkt online buchen?",
"online-2": "Hier",
"online-3": "geht's lang",
"form": {
"name": "Ihr Name",
"email": "Ihre E-Mail",
"subject": "Betreff",
"message": "Ihre Nachricht",
"send": "Absenden"
},
"heroes": {
"parents": {
"title": "Monika & Norbert",
"description": "Herzliche Gastgeber immer mit einem Tipp zur Region parat.",
"image": "/family/monika-norbert.webp"
},
"children": {
"title": "Sabrina & Daniel",
"description": "Jung, aktiv und voller Energie sie bringen Schwung ins Haus.",
"image": "/family/sabrina-daniel.webp"
}
}
},
"legal": [
{
"id": "imprint",
"title": "Impressum",
"sections": [
{
"title": "Panoramablick Saalbach",
"paragraphs": [
"Nach § 5 Abs. 1 des österreichischen eCommerce-Gesetz (ECG) und § 24 Mediengesetz geben wir hiermit uns als den Betreiber dieser Internetseite bekannt:",
"Panoramablick Saalbach\nMonika und Norbert Pail\nUnterer Ronachweg 731, 5753 Saalbach\nTelefonnummer: +43 664 790 4775\ninfo{'@'}panoramablick-saalbach.at"
]
},
{
"title": "Inhalt des Onlineangebotes",
"paragraphs": [
"Panoramablick Saalbach übernimmt keinerlei Gewähr für die Aktualität, Korrektheit, Vollständigkeit oder Qualität der bereitgestellten Informationen. Haftungsansprüche gegen Panoramablick Saalbach, welche sich auf Schäden materieller oder ideeller Art beziehen, die durch die Nutzung oder Nichtnutzung der dargebotenen Informationen bzw. durch die Nutzung fehlerhafter und unvollständiger Informationen verursacht wurden, sind grundsätzlich ausgeschlossen, sofern seitens Panoramablick Saalbach kein nachweislich vorsätzliches oder grob fahrlässiges Verschulden vorliegt. Alle Angebote sind freibleibend und unverbindlich. Panoramablick Saalbach behält es sich ausdrücklich vor, Teile der Seiten oder das gesamte Angebot ohne gesonderte Ankündigung zu verändern, zu ergänzen, zu löschen oder die Veröffentlichung zeitweise oder endgültig einzustellen."
]
},
{
"title": "Verweise und Links",
"paragraphs": [
"Bei direkten oder indirekten Verweisen auf fremde Internetseiten, sogenannten „Links“, die außerhalb des Verantwortungsbereiches des Panoramablick Saalbach liegen, würde eine Haftungsverpflichtung ausschließlich in dem Fall in Kraft treten, in dem Panoramablick Saalbach von den Inhalten Kenntnis hat und selbiger technisch möglich und zumutbar wäre, die Nutzung im Falle rechtswidriger Inhalte zu verhindern. Panoramablick Saalbach erklärt hiermit ausdrücklich, dass zum Zeitpunkt der Linksetzung die entsprechenden verlinkten Seiten frei von illegalen Inhalten waren. Auf die aktuelle und zukünftige Gestaltung, die Inhalte oder die Urheberschaft der gelinkten, bzw. verknüpften Seiten hat Panoramablick Saalbach keinerlei Einfluss. Deshalb distanziert sich Panoramablick Saalbach hiermit ausdrücklich von allen Inhalten aller gelinkten, bzw. verknüpften Seiten, die nach der Linksetzung verändert wurden. Diese Feststellung gilt für alle innerhalb des eigenen Internetangebotes gesetzten Links und Verweise sowie für Fremdeinträge in von dem Unternehmen eingerichteten Services wie Gästebüchern, Diskussionsforen, Mailinglisten und ähnlichem. Für illegale, fehlerhafte oder unvollständige Inhalte und insbesondere für Schäden, die aus der Nutzung oder Nichtnutzung solcherart dargebotener Informationen entstehen, haftet allein der Anbieter der Seite, auf welche verwiesen wurde, nicht derjenige, der über Links auf die jeweilige Veröffentlichung lediglich verweist."
]
},
{
"title": "Urheber- und Kennzeichenrecht",
"paragraphs": [
"Bildnachweis: (c) Saalbach Hinterglemm, Eigenes Bildmaterial",
"Panoramablick Saalbach ist bestrebt, in allen Publikationen die Urheberrechte der verwendeten Grafiken, Tondokumente, Videosequenzen und Texte zu beachten, von ihr selbst erstellte Grafiken, Tondokumente, Videosequenzen und Texte zu nutzen oder auf lizenzfreie Grafiken, Tondokumente, Videosequenzen und Texte zurückzugreifen. Alle innerhalb des Internetangebotes genannten und ggf. durch Dritte geschützten Marken- und Warenzeichen unterliegen uneingeschränkt den Bestimmungen des jeweils gültigen Kennzeichenrechts und den Besitzrechten der jeweiligen eingetragenen Eigentümer. Allein aufgrund der bloßen Nennung ist nicht der Schluss zu ziehen, dass Markenzeichen nicht durch Rechte Dritter geschützt sind! Das Copyright für veröffentlichte, von Panoramablick Saalbach selbst erstellte Objekte bleibt allein beim Besitzer der Seiten. Eine Vervielfältigung oder Verwendung solcher Grafiken, Tondokumente, Videosequenzen und Texte in anderen elektronischen oder gedruckten Publikationen ist ohne ausdrückliche Zustimmung seitens Panoramablick Saalbach nicht gestattet."
]
},
{
"title": "Copyright/Haftung",
"paragraphs": [
"Im Hinblick auf die technischen Eigenschaften des Internet kann keine Gewähr für die Authentizität, Richtigkeit und Vollständigkeit der im Internet zur Verfügung gestellten Informationen übernommen werden. Es wird auch keine Gewähr für die Verfügbarkeit oder den Betrieb der gegenständlichen Website und ihrer Inhalte übernommen. Jede Haftung für unmittelbare, mittelbare oder sonstige Schäden, unabhängig von deren Ursachen, die aus der Benutzung oder Nichtverfügbarkeit der Daten und Informationen dieser Website erwachsen, wird, soweit rechtlich zulässig, ausgeschlossen. Der Inhalt dieser Website ist urheberrechtlich geschützt. Die Informationen sind nur für die persönliche Verwendung bestimmt. Jede weitergehende Nutzung insbesondere die Speicherung in Datenbanken, Vervielfältigung und jede Form von gewerblicher Nutzung sowie die Weitergabe an Dritte auch in Teilen oder in überarbeiteter Form ohne Zustimmung der jeweiligen Organisation ist untersagt. Jede Einbindung einzelner Seiten unseres Angebotes in fremde Frames ist zu unterlassen."
]
},
{
"title": "Sonstiges",
"paragraphs": [
"Sofern Teile oder einzelne Formulierungen dieses Textes der geltenden Rechtslage nicht, nicht mehr oder nicht vollständig entsprechen sollten, bleiben die übrigen Teile des Dokumentes in ihrem Inhalt und ihrer Gültigkeit davon unberührt."
]
},
{
"title": "Online-Streitbeilegung",
"paragraphs": [
"Seit dem 9.1.2016 gilt die EU-Verordnung über Online-Streitbeilegung in Verbraucherangelegenheiten (Nr. 524/2013). Streitigkeiten zwischen Verbrauchern und Händlern im Zusammenhang von Online-Kaufverträgen oder Online-Dienstleistungsverträgen können über folgende Online-Plattform beigelegt werden.",
"https://ec.europa.eu/consumers/odr/"
]
}
]
},
{
"id": "privacy",
"title": "Datenschutz",
"sections": [
{
"title": "Allgemein",
"paragraphs": [
"Uns ist die Sicherheit Ihrer Daten wichtig. Wir verwenden sie ausschließlich zweckgebunden und geben sie nur dann an Dritte weiter, sofern diese in unserem ausdrücklichen Auftrag zur Zweckerfüllung beitragen. Nach EU-Datenschutz-Grundverordnung (DSGVO) und nach dem Bundesgesetzblatt 2017/120 (LINK) der Republik Österreich mit endgültiger Wirksamkeit 25.5.2018 haben Nutzer das Recht, auf Antrag unentgeltlich Auskunft über die personenbezogenen Daten zu erhalten, die wir über sie gespeichert haben. Zusätzlich hat jeder Kunde bzw. Nutzer jederzeit das Recht auf Berichtigung unrichtiger Daten, Sperrung und Löschung seiner personenbezogene Daten, soweit dem keine gesetzliche Aufbewahrungs- oder Meldepflichtpflicht entgegensteht."
]
},
{
"title": "Datenschutz & Cookies",
"paragraphs": [
"Datenschutzerklärung nach Telekommunikationsgesetz (TKG) und dem Datenschutzgesetz (DSG)"
]
},
{
"title": "Datenverarbeitung",
"paragraphs": [
"Personenbezogene Daten, die Sie uns über eine Webseite oder Email übermittelt haben, werden nur zur Korrespondenz mit Ihnen und nur für den Zweck verarbeitet, zu dem Sie uns Ihre Daten zur Verfügung gestellt haben. Die zur Verfügung gestellten Daten werden ausschließlich an die zuständige Stelle im Unternehmen weitergeleitet.",
"Wir versichern, dass Ihre personenbezogenen Daten nicht an Dritte weitergegeben werden, es sei denn, dass gesetzliche Vorgaben dies verlangen."
]
},
{
"title": "Datenspeicherung",
"paragraphs": [
"Die uns zur Verfügung gestellten Daten werden nur so lange gespeichert, bis der Zweck erfüllt ist, zu dem sie uns anvertraut wurden. Sofern gesetzliche Aufbewahrungsfristen zu beachten sind, werden diese eingehalten.",
"Sollten Sie mit der Speicherung Ihrer personenbezogenen Daten nicht mehr einverstanden sein, werden wir die gespeicherten Daten auf Ihre Weisung hin löschen. Haben sich ihre personenbezogenen Daten geändert, werden wir diese nach Ihrer Information richtigstellen."
]
},
{
"title": "Ändern der Cookie-Einstellungen",
"paragraphs": [
"In Ihren Browsereinstellungen (z.B. Internet Explorer, Safari, Firefox, Chrome) können Sie festlegen, welche Cookies Sie zulassen oder ablehnen möchten. Wo genau Sie diese Einstellungen finden, hängt von Ihrem Browser ab. Die entsprechenden Einstellungen finden Sie mit der Hilfefunktion Ihres Browsers.",
"[pw_cookie_notice]"
]
}
]
},
{
"id": "accessability",
"title": "Barrierefreiheit",
"sections": [
{
"title": "Allgemein",
"paragraphs": [
"Panoramablick Saalbach setzt sich dafür ein, ihre Website bestmöglich barrierefrei zu gestalten und dabei die Anforderungen des Barrierefreiheitsgesetz (BaFG) im Web zu berücksichtigen. Diese Erklärung zur Barrierefreiheit bezieht sich auf die Website www.panoramablick-saalbach.at."
]
},
{
"title": "Erklärung",
"paragraphs": [
"Die Website wurde nach den Vorgaben der „Richtlinien für barrierefreie Webinhalte WCAG 2.2“ optimiert. Wir haben alle technisch möglichen Maßnahmen nach bestem Wissen und Gewissen umgesetzt, um eine weitgehende Barrierefreiheit zu gewährleisten.",
"Diese Erklärung wurde am 02. Februar 2025 erstellt."
]
},
{
"title": "Feedback",
"paragraphs": [
"Sollten Sie Inhalte auf unserer Website entdecken, die nicht barrierefrei zugänglich sind, oder möchten Sie uns Feedback geben, kontaktieren Sie uns gerne per E-Mail unter info{'@'}panoramablick-saalbach.at. Wir prüfen Ihre Anfrage sorgfältig und bemühen uns, Sie so rasch wie möglich zu kontaktieren."
]
}
]
}
]
}

View File

@ -0,0 +1,363 @@
{
"header": {
"home": "Landhaus Panoramablick",
"apartments": "Apartments & Preise",
"book": "Buchen",
"contact": "Kontakt"
},
"footer": {
"questions": "Fragen oder Wünsche?",
"prompt": "Monika freut sich von Ihnen zu hören!"
},
"button": {
"apartments": "Apartments",
"book": "Buchen",
"contact": "Kontakt",
"hosts": "Die Gastgeber",
"map": "Maps Öffnen"
},
"features": [
{
"icon": "wifi",
"label": "Schnelles WLAN",
"detail": "Stabile 250 MBit/s Leitung im ganzen Haus."
},
{
"icon": "car-front",
"label": "Gratis Parkplatz",
"detail": "Kostenlose Stellplätze direkt vor der Tür."
},
{
"icon": "map-pin",
"label": "Exzellente Lage",
"detail": "5 Min. zur Altstadt, 3 Min. zum Bahnhof."
},
{
"icon": "users",
"label": "Liebenswürdige Gastgeber",
"detail": "Persönliche Tipps & herzlicher Service rund um die Uhr."
},
{
"icon": "trees",
"label": "Atemberaubendes Panorama",
"detail": "Nur das beste für die Gäste."
},
{
"icon": "bike",
"label": "Sportgeschäft in nächster Nähe",
"detail": "Lirum larum löffelstiel, Bründl."
},
{
"icon": "heater",
"label": "Sauna verfügbar",
"detail": "Ene mene miste."
}
],
"landing": {
"welcome": {
"title": "Willkommen im Landhaus Panoramablick",
"description": "Genießen Sie erholsame Tage inmitten der Natur mit herrlichem Ausblick auf die Berge. Unser Landhaus bietet gemütliche Apartments und herzliche Gastfreundschaft."
},
"highlight": {
"title": "Erleben Sie Natur hautnah",
"description": "Unser Landhaus liegt eingebettet in idyllischer Landschaft mit atemberaubendem Ausblick. Ob Wandern, Entspannen oder die Umgebung erkunden bei uns finden Sie Ruhe und Erholung."
},
"location": {
"title": "Logieren Sie in bester Lage",
"description": "Blabla asdfasdf asdf asdf asdf asddf asddf asdf asdf asdfasd ffad."
},
"apartments": {
"title": "Unsere Apartments",
"description": "Blabla asdfasdf asdf asdf asdf asddf asddf asdf asdf asdfasd ffad."
},
"features": {
"title": "Das erwartet Sie",
"description": "Blabla asdfasdf asdf asdf asdf asddf asddf asdf asdf asdfasd ffad."
}
},
"apartments": {
"highlight": {
"title": "Das gibt es bei uns",
"description": "Es ist alles so toll"
},
"list": [
{
"id": "apartment-1",
"title": "Apartment 1",
"subtitle": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
"thumbnail": "/ap-1/1.webp",
"highlights": [
"Ab € 225,- pro Tag",
"4 Personen"
],
"images": [
"/ap-1/1.webp",
"/ap-1/2.webp"
],
"features": [
{
"icon": "wifi",
"label": "Schnelles WLAN"
},
{
"icon": "car-front",
"label": "Parkplatz"
},
{
"icon": "map-pin",
"label": "Exzellente Lage"
},
{
"icon": "users",
"label": "Liebens­würdige Gastgeber"
},
{
"icon": "trees",
"label": "Panorama"
},
{
"icon": "bike",
"label": "Sport­geschäft in Nähe"
},
{
"icon": "heater",
"label": "Sauna"
}
]
},
{
"id": "apartment-2",
"title": "Apartment 2",
"subtitle": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
"thumbnail": "/ap-1/1.webp",
"highlights": [
"Ab € 225,- pro Tag",
"4 Personen"
],
"images": [
"/ap-2/1.webp",
"/ap-2/2.webp"
],
"features": [
{
"icon": "wifi",
"label": "Schnelles WLAN"
},
{
"icon": "car-front",
"label": "Parkplatz"
},
{
"icon": "map-pin",
"label": "Exzellente Lage"
},
{
"icon": "users",
"label": "Liebens­würdige Gastgeber"
},
{
"icon": "trees",
"label": "Panorama"
},
{
"icon": "bike",
"label": "Sport­geschäft in Nähe"
},
{
"icon": "heater",
"label": "Sauna"
}
]
},
{
"id": "apartment-3",
"title": "Apartment 3",
"subtitle": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
"thumbnail": "/ap-1/1.webp",
"highlights": [
"Ab € 225,- pro Tag",
"4 Personen"
],
"images": [
"/ap-2/1.webp",
"/ap-2/2.webp"
],
"features": [
{
"icon": "wifi",
"label": "Schnelles WLAN"
},
{
"icon": "car-front",
"label": "Parkplatz"
},
{
"icon": "map-pin",
"label": "Exzellente Lage"
},
{
"icon": "users",
"label": "Liebens­würdige Gastgeber"
},
{
"icon": "trees",
"label": "Panorama"
},
{
"icon": "bike",
"label": "Sport­geschäft in Nähe"
},
{
"icon": "heater",
"label": "Sauna"
}
]
}
]
},
"contact": {
"title": "Kontakt aufnehmen",
"description": "Wir freuen uns auf Ihre Anfrage Sie erreichen uns per Telefon, SMS, WhatsApp, E-Mail oder über das untenstehende Formular.",
"phone": "+43 123 456789",
"email": "info{'@'}panoramablick-saalbach.at",
"online-1": "Sie wollen direkt online buchen?",
"online-2": "Hier",
"online-3": "geht's lang",
"form": {
"name": "Ihr Name",
"email": "Ihre E-Mail",
"subject": "Betreff",
"message": "Ihre Nachricht",
"send": "Absenden"
},
"heroes": {
"parents": {
"title": "Monika & Norbert",
"description": "Herzliche Gastgeber immer mit einem Tipp zur Region parat.",
"image": "/family/monika-norbert.webp"
},
"children": {
"title": "Sabrina & Daniel",
"description": "Jung, aktiv und voller Energie sie bringen Schwung ins Haus.",
"image": "/family/sabrina-daniel.webp"
}
}
},
"legal": [
{
"id": "imprint",
"title": "Impressum",
"sections": [
{
"title": "Panoramablick Saalbach",
"paragraphs": [
"Nach § 5 Abs. 1 des österreichischen eCommerce-Gesetz (ECG) und § 24 Mediengesetz geben wir hiermit uns als den Betreiber dieser Internetseite bekannt:",
"Panoramablick Saalbach\nMonika und Norbert Pail\nUnterer Ronachweg 731, 5753 Saalbach\nTelefonnummer: +43 664 790 4775\ninfo{'@'}panoramablick-saalbach.at"
]
},
{
"title": "Inhalt des Onlineangebotes",
"paragraphs": [
"Panoramablick Saalbach übernimmt keinerlei Gewähr für die Aktualität, Korrektheit, Vollständigkeit oder Qualität der bereitgestellten Informationen. Haftungsansprüche gegen Panoramablick Saalbach, welche sich auf Schäden materieller oder ideeller Art beziehen, die durch die Nutzung oder Nichtnutzung der dargebotenen Informationen bzw. durch die Nutzung fehlerhafter und unvollständiger Informationen verursacht wurden, sind grundsätzlich ausgeschlossen, sofern seitens Panoramablick Saalbach kein nachweislich vorsätzliches oder grob fahrlässiges Verschulden vorliegt. Alle Angebote sind freibleibend und unverbindlich. Panoramablick Saalbach behält es sich ausdrücklich vor, Teile der Seiten oder das gesamte Angebot ohne gesonderte Ankündigung zu verändern, zu ergänzen, zu löschen oder die Veröffentlichung zeitweise oder endgültig einzustellen."
]
},
{
"title": "Verweise und Links",
"paragraphs": [
"Bei direkten oder indirekten Verweisen auf fremde Internetseiten, sogenannten „Links“, die außerhalb des Verantwortungsbereiches des Panoramablick Saalbach liegen, würde eine Haftungsverpflichtung ausschließlich in dem Fall in Kraft treten, in dem Panoramablick Saalbach von den Inhalten Kenntnis hat und selbiger technisch möglich und zumutbar wäre, die Nutzung im Falle rechtswidriger Inhalte zu verhindern. Panoramablick Saalbach erklärt hiermit ausdrücklich, dass zum Zeitpunkt der Linksetzung die entsprechenden verlinkten Seiten frei von illegalen Inhalten waren. Auf die aktuelle und zukünftige Gestaltung, die Inhalte oder die Urheberschaft der gelinkten, bzw. verknüpften Seiten hat Panoramablick Saalbach keinerlei Einfluss. Deshalb distanziert sich Panoramablick Saalbach hiermit ausdrücklich von allen Inhalten aller gelinkten, bzw. verknüpften Seiten, die nach der Linksetzung verändert wurden. Diese Feststellung gilt für alle innerhalb des eigenen Internetangebotes gesetzten Links und Verweise sowie für Fremdeinträge in von dem Unternehmen eingerichteten Services wie Gästebüchern, Diskussionsforen, Mailinglisten und ähnlichem. Für illegale, fehlerhafte oder unvollständige Inhalte und insbesondere für Schäden, die aus der Nutzung oder Nichtnutzung solcherart dargebotener Informationen entstehen, haftet allein der Anbieter der Seite, auf welche verwiesen wurde, nicht derjenige, der über Links auf die jeweilige Veröffentlichung lediglich verweist."
]
},
{
"title": "Urheber- und Kennzeichenrecht",
"paragraphs": [
"Bildnachweis: (c) Saalbach Hinterglemm, Eigenes Bildmaterial",
"Panoramablick Saalbach ist bestrebt, in allen Publikationen die Urheberrechte der verwendeten Grafiken, Tondokumente, Videosequenzen und Texte zu beachten, von ihr selbst erstellte Grafiken, Tondokumente, Videosequenzen und Texte zu nutzen oder auf lizenzfreie Grafiken, Tondokumente, Videosequenzen und Texte zurückzugreifen. Alle innerhalb des Internetangebotes genannten und ggf. durch Dritte geschützten Marken- und Warenzeichen unterliegen uneingeschränkt den Bestimmungen des jeweils gültigen Kennzeichenrechts und den Besitzrechten der jeweiligen eingetragenen Eigentümer. Allein aufgrund der bloßen Nennung ist nicht der Schluss zu ziehen, dass Markenzeichen nicht durch Rechte Dritter geschützt sind! Das Copyright für veröffentlichte, von Panoramablick Saalbach selbst erstellte Objekte bleibt allein beim Besitzer der Seiten. Eine Vervielfältigung oder Verwendung solcher Grafiken, Tondokumente, Videosequenzen und Texte in anderen elektronischen oder gedruckten Publikationen ist ohne ausdrückliche Zustimmung seitens Panoramablick Saalbach nicht gestattet."
]
},
{
"title": "Copyright/Haftung",
"paragraphs": [
"Im Hinblick auf die technischen Eigenschaften des Internet kann keine Gewähr für die Authentizität, Richtigkeit und Vollständigkeit der im Internet zur Verfügung gestellten Informationen übernommen werden. Es wird auch keine Gewähr für die Verfügbarkeit oder den Betrieb der gegenständlichen Website und ihrer Inhalte übernommen. Jede Haftung für unmittelbare, mittelbare oder sonstige Schäden, unabhängig von deren Ursachen, die aus der Benutzung oder Nichtverfügbarkeit der Daten und Informationen dieser Website erwachsen, wird, soweit rechtlich zulässig, ausgeschlossen. Der Inhalt dieser Website ist urheberrechtlich geschützt. Die Informationen sind nur für die persönliche Verwendung bestimmt. Jede weitergehende Nutzung insbesondere die Speicherung in Datenbanken, Vervielfältigung und jede Form von gewerblicher Nutzung sowie die Weitergabe an Dritte auch in Teilen oder in überarbeiteter Form ohne Zustimmung der jeweiligen Organisation ist untersagt. Jede Einbindung einzelner Seiten unseres Angebotes in fremde Frames ist zu unterlassen."
]
},
{
"title": "Sonstiges",
"paragraphs": [
"Sofern Teile oder einzelne Formulierungen dieses Textes der geltenden Rechtslage nicht, nicht mehr oder nicht vollständig entsprechen sollten, bleiben die übrigen Teile des Dokumentes in ihrem Inhalt und ihrer Gültigkeit davon unberührt."
]
},
{
"title": "Online-Streitbeilegung",
"paragraphs": [
"Seit dem 9.1.2016 gilt die EU-Verordnung über Online-Streitbeilegung in Verbraucherangelegenheiten (Nr. 524/2013). Streitigkeiten zwischen Verbrauchern und Händlern im Zusammenhang von Online-Kaufverträgen oder Online-Dienstleistungsverträgen können über folgende Online-Plattform beigelegt werden.",
"https://ec.europa.eu/consumers/odr/"
]
}
]
},
{
"id": "privacy",
"title": "Datenschutz",
"sections": [
{
"title": "Allgemein",
"paragraphs": [
"Uns ist die Sicherheit Ihrer Daten wichtig. Wir verwenden sie ausschließlich zweckgebunden und geben sie nur dann an Dritte weiter, sofern diese in unserem ausdrücklichen Auftrag zur Zweckerfüllung beitragen. Nach EU-Datenschutz-Grundverordnung (DSGVO) und nach dem Bundesgesetzblatt 2017/120 (LINK) der Republik Österreich mit endgültiger Wirksamkeit 25.5.2018 haben Nutzer das Recht, auf Antrag unentgeltlich Auskunft über die personenbezogenen Daten zu erhalten, die wir über sie gespeichert haben. Zusätzlich hat jeder Kunde bzw. Nutzer jederzeit das Recht auf Berichtigung unrichtiger Daten, Sperrung und Löschung seiner personenbezogene Daten, soweit dem keine gesetzliche Aufbewahrungs- oder Meldepflichtpflicht entgegensteht."
]
},
{
"title": "Datenschutz & Cookies",
"paragraphs": [
"Datenschutzerklärung nach Telekommunikationsgesetz (TKG) und dem Datenschutzgesetz (DSG)"
]
},
{
"title": "Datenverarbeitung",
"paragraphs": [
"Personenbezogene Daten, die Sie uns über eine Webseite oder Email übermittelt haben, werden nur zur Korrespondenz mit Ihnen und nur für den Zweck verarbeitet, zu dem Sie uns Ihre Daten zur Verfügung gestellt haben. Die zur Verfügung gestellten Daten werden ausschließlich an die zuständige Stelle im Unternehmen weitergeleitet.",
"Wir versichern, dass Ihre personenbezogenen Daten nicht an Dritte weitergegeben werden, es sei denn, dass gesetzliche Vorgaben dies verlangen."
]
},
{
"title": "Datenspeicherung",
"paragraphs": [
"Die uns zur Verfügung gestellten Daten werden nur so lange gespeichert, bis der Zweck erfüllt ist, zu dem sie uns anvertraut wurden. Sofern gesetzliche Aufbewahrungsfristen zu beachten sind, werden diese eingehalten.",
"Sollten Sie mit der Speicherung Ihrer personenbezogenen Daten nicht mehr einverstanden sein, werden wir die gespeicherten Daten auf Ihre Weisung hin löschen. Haben sich ihre personenbezogenen Daten geändert, werden wir diese nach Ihrer Information richtigstellen."
]
},
{
"title": "Ändern der Cookie-Einstellungen",
"paragraphs": [
"In Ihren Browsereinstellungen (z.B. Internet Explorer, Safari, Firefox, Chrome) können Sie festlegen, welche Cookies Sie zulassen oder ablehnen möchten. Wo genau Sie diese Einstellungen finden, hängt von Ihrem Browser ab. Die entsprechenden Einstellungen finden Sie mit der Hilfefunktion Ihres Browsers.",
"[pw_cookie_notice]"
]
}
]
},
{
"id": "accessability",
"title": "Barrierefreiheit",
"sections": [
{
"title": "Allgemein",
"paragraphs": [
"Panoramablick Saalbach setzt sich dafür ein, ihre Website bestmöglich barrierefrei zu gestalten und dabei die Anforderungen des Barrierefreiheitsgesetz (BaFG) im Web zu berücksichtigen. Diese Erklärung zur Barrierefreiheit bezieht sich auf die Website www.panoramablick-saalbach.at."
]
},
{
"title": "Erklärung",
"paragraphs": [
"Die Website wurde nach den Vorgaben der „Richtlinien für barrierefreie Webinhalte WCAG 2.2“ optimiert. Wir haben alle technisch möglichen Maßnahmen nach bestem Wissen und Gewissen umgesetzt, um eine weitgehende Barrierefreiheit zu gewährleisten.",
"Diese Erklärung wurde am 02. Februar 2025 erstellt."
]
},
{
"title": "Feedback",
"paragraphs": [
"Sollten Sie Inhalte auf unserer Website entdecken, die nicht barrierefrei zugänglich sind, oder möchten Sie uns Feedback geben, kontaktieren Sie uns gerne per E-Mail unter info{'@'}panoramablick-saalbach.at. Wir prüfen Ihre Anfrage sorgfältig und bemühen uns, Sie so rasch wie möglich zu kontaktieren."
]
}
]
}
]
}

View File

@ -1,5 +1,14 @@
<template>
<UApp :toaster="{ position: 'top-center' }">
<WDummy/>
<div class="flex flex-col min-h-dvh bg-neutral-50">
<AppHeader/>
<main class="flex-1">
<NuxtPage/>
</main>
<AppFooter/>
</div>
</UApp>
</template>
</template>

View File

@ -2,5 +2,23 @@
export default defineNuxtConfig({
compatibilityDate: '2025-05-15',
devtools: { enabled: true },
modules: ['@nuxt/fonts', '@nuxt/icon', '@nuxt/image', '@nuxt/ui', '@websites/ui']
modules: [
'@nuxt/fonts',
'@nuxt/icon',
'@nuxt/image',
'@nuxt/ui',
'@websites/ui',
'@nuxtjs/i18n',
],
css: ['@/assets/css/main.css'],
ui: {
colorMode: false
},
i18n: {
defaultLocale: 'de',
locales: [
{code: 'de', name: 'Deutsch', file: 'de.json'},
{code: 'en', name: 'English', file: 'en.json'}
]
},
})

View File

@ -10,14 +10,18 @@
"postinstall": "nuxt prepare"
},
"dependencies": {
"@websites/ui": "workspace:*",
"@websites/tsconfig": "workspace:*",
"@nuxt/fonts": "0.11.4",
"@nuxt/icon": "1.13.0",
"@nuxt/image": "1.10.0",
"@nuxt/ui": "3.1.3",
"@nuxtjs/i18n": "9.5.5",
"@tailwindcss/vite": "^4.1.10",
"@websites/tsconfig": "workspace:*",
"@websites/ui": "workspace:*",
"nuxt": "^3.17.5",
"tailwindcss": "^4.1.10",
"typescript": "^5.6.3",
"valibot": "^1.1.0",
"vue": "^3.5.16",
"vue-router": "^4.5.1"
}

View File

@ -0,0 +1,39 @@
<!-- /error.vue (Nuxt automatically serves this for 404 routes) -->
<template>
<section
class="flex min-h-screen flex-col items-center justify-center
bg-neutral-100 px-4 text-center"
>
<!-- Icon -->
<UIcon
name="i-heroicons-face-frown"
class="h-16 w-16 text-primary-600 mb-6"
/>
<!-- Headline -->
<h1 class="text-4xl font-bold text-neutral-900 mb-2">
Seite nicht gefunden
</h1>
<!-- Sub-copy -->
<p class="max-w-md text-neutral-600 mb-8">
Die gewünschte Seite existiert leider nicht (mehr) oder der Link war
fehlerhaft. Versuchen Sie es über die Startseite noch einmal.
</p>
<!-- CTA -->
<UButton
to="/"
size="lg"
color="primary"
variant="solid"
trailing-icon="i-heroicons-arrow-uturn-left"
>
Zur Startseite
</UButton>
</section>
</template>
<script setup lang="ts">
definePageMeta({layout: false, statusCode: 404})
</script>

View File

@ -0,0 +1,5 @@
<template>
<section>
<p>This page will be displayed at the /about route.</p>
</section>
</template>

View File

@ -0,0 +1,25 @@
<template>
<div class="w-full h-full bg-neutral-50">
<AppFlatSection>
<div class="flex gap-12 items-center">
<!-- Left: Image Group -->
<div class="flex flex-row gap-4 justify-center relative">
<img src="/ap.webp" alt="Image 1" class="w-40 h-60 object-cover rounded-lg"/>
<img src="/sauna.webp" alt="Image 2" class="w-40 h-60 object-cover rounded-lg translate-y-6"/>
</div>
<AppTitleText i18n-key="apartments.highlight">
<AppFeaturesGrid :features="tm('features')"/>
</AppTitleText>
</div>
</AppFlatSection>
<AppCardSection v-for="apartment in tm('apartments.list')" :id="rt(apartment.id)">
<AppApartment :apartment="apartment"/>
</AppCardSection>
</div>
</template>
<script setup lang="ts">
const {t, tm, rt} = useI18n()
</script>

View File

@ -0,0 +1,38 @@
<script setup lang="ts">
/* Inject the external assets into <head> */
useHead({
link: [
{
rel: 'stylesheet',
href: 'https://mainframe.capcorn.net/ressourcen/newUI/css/capcorn.css'
}
],
script: [
{
src: 'https://mainframe.capcorn.net/ressourcen/newUI/js/jquery.js',
tagPosition: 'bodyClose', // load at the end of <body>
defer: true // optional
},
{
src: 'https://mainframe.capcorn.net/ressourcen/newUI/js/capcorn.js',
tagPosition: 'bodyClose',
defer: true
}
]
})
</script>
<template>
<AppFlatSection>
<!-- SSR-safe: iframe appears only in the browser -->
<ClientOnly>
<iframe
id="iframeCapCorn"
src="https://www.capcorn.net/MasterReq?MB=1487&FL=17&LG=0"
frameborder="0"
width="100%"
scrolling="auto"
/>
</ClientOnly>
</AppFlatSection>
</template>

View File

@ -0,0 +1,143 @@
<template>
<!-- Contactcentric layout -->
<AppFlatSection>
<!-- Grid: form (fixed maxwidth) | host snapshots -->
<div class="grid gap-12 lg:grid-cols-[minmax(0,480px)_1fr] items-start lg:items-center">
<!-- Contact form -->
<div class="w-full max-w-xl mx-auto lg:mx-0">
<h1 class="text-3xl sm:text-4xl font-bold mb-4">{{ t('contact.title') }}</h1>
<!-- Extended intro -->
<p class="text-neutral-700 mb-4 max-w-prose">
{{ t('contact.description') }}
</p>
<!-- Contact shortcuts -->
<div class="mb-8 space-y-1 text-sm">
<!-- Phone (phone + WhatsApp icons) -->
<div class="flex items-center gap-2">
<!-- Heroicons phone -->
<UIcon name="i-heroicons-phone" class="w-4 h-4 text-primary-600"/>
<!-- WhatsApp icon (any Iconify set you use) -->
<UIcon name="i-uil-whatsapp" class="w-4 h-4 text-primary-600"/>
<a :href="`tel:${t('contact.phone').replace(/\s+/g, '')}`" class="hover:underline">
{{ t('contact.phone') }}
</a>
</div>
<!-- E-mail -->
<div class="flex items-center gap-2">
<UIcon name="i-heroicons-envelope" class="w-4 h-4 text-primary-600"/>
<a :href="`mailto:${t('contact.email')}`" class="hover:underline">
{{ t('contact.email') }}
</a>
</div>
</div>
<p class="text-neutral-700 mb-4 max-w-prose">
{{ t('contact.online-1') }}
<UButton to="/book" variant="outline" trailing-icon="i-heroicons-arrow-right">{{
t('contact.online-2')
}}
</UButton>
{{ t('contact.online-3') }}
</p>
<!-- Form -->
<UForm :state="state" class="space-y-4" @submit="onSubmit">
<UFormField name="name" label="Name" :ui="{ label: 'sr-only' }">
<UInput v-model="state.name" class="w-full" :placeholder="t('contact.form.name')"/>
</UFormField>
<UFormField name="email" label="E-Mail" :ui="{ label: 'sr-only' }">
<UInput v-model="state.email" type="email" class="w-full"
:placeholder="t('contact.form.email')"/>
</UFormField>
<UFormField name="subject" label="Betreff" :ui="{ label: 'sr-only' }">
<UInput v-model="state.subject" class="w-full" :placeholder="t('contact.form.subject')"/>
</UFormField>
<UFormField name="message" label="Nachricht" :ui="{ label: 'sr-only' }">
<UTextarea v-model="state.message" :rows="6" class="w-full"
:placeholder="t('contact.form.message')"/>
</UFormField>
<UButton type="submit" color="primary" size="lg" class="w-full sm:w-auto">
{{ t('contact.form.send') }}
</UButton>
</UForm>
</div>
<!-- Decorative host snapshots -->
<div id="hosts" class="flex flex-col gap-10 lg:self-center">
<AppHero
:src="t('contact.heroes.parents.image')"
:alt="t('contact.heroes.parents.title')"
image-side="left"
:size="50"
:title="t('contact.heroes.parents.title')"
:description="t('contact.heroes.parents.description')"
/>
<AppHero
:src="t('contact.heroes.children.image')"
:alt="t('contact.heroes.children.title')"
image-side="right"
:size="50"
:title="t('contact.heroes.children.title')"
:description="t('contact.heroes.children.description')"
/>
</div>
</div>
</AppFlatSection>
</template>
<script setup lang="ts">
const {t, tm, rt} = useI18n()
import * as v from 'valibot'
import type {FormSubmitEvent} from '@nuxt/ui'
/* ───── validation schema ───── */
const schema = v.object({
name: v.pipe(v.string(), v.minLength(2, 'Bitte Namen eingeben')),
email: v.pipe(v.string(), v.email('Ungültige E-Mail')),
subject: v.pipe(v.string(), v.minLength(3, 'Betreff fehlt')),
message: v.pipe(v.string(), v.minLength(10, 'Nachricht ist zu kurz'))
})
type Schema = v.InferOutput<typeof schema>
/* ───── reactive form state ───── */
const state = reactive<Schema>({
name: '', email: '', subject: '', message: ''
})
const toast = useToast()
/* ───── submit handler ───── */
async function onSubmit(event: FormSubmitEvent<Schema>) {
try {
await $fetch('/contact.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: event.data
})
toast.add({
title: 'Nachricht gesendet',
description: 'Vielen Dank wir melden uns bald.',
color: 'green'
})
/* reset fields */
Object.assign(state, {name: '', email: '', subject: '', message: ''})
} catch (err: any) {
toast.add({
title: 'Fehler',
description: err?.data?.message ?? 'Nachricht konnte nicht gesendet werden.',
color: 'red'
})
}
}
</script>

View File

@ -0,0 +1,134 @@
<template>
<section class="relative w-full">
<div class="relative w-full">
<UCarousel
v-slot="{ item }"
:items="images"
:ui="{item: 'basis-full h-full ps-0', container: 'flex items-stretch h-150 sm:h-75 md:h-100 lg:h-150'}"
:autoplay="{ delay: 5000 }"
:loop="true"
:fade="true"
:duration="75"
class="w-full h-full">
<div class="w-full h-full flex items-center justify-center">
<img :src="item" class="w-full h-full object-cover" alt="Demo Picture"/>
</div>
</UCarousel>
<div class="absolute inset-0 z-10 bg-black/60">
<div class="w-full h-full flex justify-center items-center">
<AppStripe class="text-white">
<div class="max-w-2xl">
<h1 class="text-5xl max-w-4xl font-bold">{{ t('landing.welcome.title') }}</h1>
<p class="mt-4 text-lg text-gray-200">
{{
t('landing.welcome.description')
}}
</p>
</div>
<div class="mt-8 flex gap-4">
<UButton to="/apartments" color="primary" variant="solid" size="xl"
trailing-icon="i-heroicons-arrow-right">{{ t('button.apartments') }}
</UButton>
<UButton to="/book" color="secondary" variant="solid" size="xl" trailing-icon="i-heroicons-globe-alt">
{{ t('button.book') }}
</UButton>
<UButton to="/contact" color="secondary" variant="solid" size="xl" trailing-icon="i-heroicons-envelope">
{{ t('button.contact') }}
</UButton>
</div>
</AppStripe>
</div>
</div>
</div>
</section>
<AppFlatSection>
<div class="flex gap-12 items-center">
<!-- Left: Image Group -->
<div class="flex flex-row gap-4 justify-center relative">
<img src="/ap.webp" alt="Image 1" class="w-40 h-60 object-cover rounded-lg"/>
<img src="/sauna.webp" alt="Image 2" class="w-40 h-60 object-cover rounded-lg translate-y-6"/>
</div>
<!-- Right: Text Content -->
<AppTitleText i18n-key="landing.highlight">
<UButton :external="true" to="/contact#hosts" color="primary" variant="solid" size="xl"
trailing-icon="i-heroicons-arrow-right">
{{
t('button.hosts')
}}
</UButton>
</AppTitleText>
</div>
</AppFlatSection>
<AppCardSection>
<div class="flex gap-12 items-center">
<!-- Left: Text (40%) -->
<div class="basis-2/5 pr">
<AppTitleText i18n-key="landing.location">
<UButton to="https://maps.app.goo.gl/FtTC8ervoBCnfU3j7" color="primary" variant="solid" size="xl"
trailing-icon="i-heroicons-arrow-right">
{{ t('button.map') }}
</UButton>
</AppTitleText>
</div>
<!-- Right: Image (60%) -->
<a
href="https://maps.app.goo.gl/FtTC8ervoBCnfU3j7"
target="_blank"
rel="noopener"
class="basis-3/5 flex justify-center overflow-hidden rounded-lg group"
aria-label="Google Maps öffnen"
>
<img
src="/maps.png"
alt="Vorschaubild der Lage in Google Maps"
class="w-full h-80 object-cover transition-transform duration-300 ease-out group-hover:scale-110"
/>
</a>
</div>
</AppCardSection>
<AppFlatSection>
<AppTitleText i18n-key="landing.apartments">
<div class="flex flex-wrap gap-4 justify-center">
<a v-for="apartment in tm('apartments.list')" :href="`/apartments#${rt(apartment.id)}`"
class="relative group block w-60 h-80 overflow-hidden">
<img :src="rt(apartment.thumbnail)" alt="Image 1"
class="w-full h-full object-cover transition-transform duration-300 ease-out group-hover:scale-110"/>
<div class="absolute inset-0 bg-black/50"></div>
<div
class="absolute inset-0 flex items-center justify-center text-white text-lg font-semibold drop-shadow-md">
<div class="text-center">
<h2>{{ rt(apartment.title) }}</h2>
<ul>
<li v-for="highlight in apartment.highlights" class="text-sm">{{ rt(highlight) }}</li>
</ul>
</div>
</div>
</a>
</div>
</AppTitleText>
</AppFlatSection>
<AppCardSection>
<AppTitleText i18n-key="landing.features" class="pr">
<AppFeaturesGrid :features="tm('features')"/>
</AppTitleText>
</AppCardSection>
</template>
<script setup lang="ts">
const images = [
'/house.webp',
'/panorama.webp'
]
const {t, tm, rt} = useI18n()
</script>

View File

@ -0,0 +1,30 @@
<template>
<AppFlatSection>
<section class="prose mx-auto max-w-3xl p-4 lg:p-8">
<article
v-for="block in tm('legal')"
:key="rt(block.id)"
:id="rt(block.id)"
class="mb-12"
>
<h1 class="text-3xl font-bold mb-6 whitespace-pre-line">{{ rt(block.title) }}</h1>
<section
v-for="sec in block.sections"
:key="sec.title"
class="mb-8 whitespace-pre-line"
>
<h2 class="text-2xl font-semibold mb-4">{{ rt(sec.title) }}</h2>
<p v-for="p in sec.paragraphs" :key="p" class="mb-3 leading-relaxed whitespace-pre-line">
{{ rt(p) }}
</p>
</section>
</article>
</section>
</AppFlatSection>
</template>
<script setup lang="ts">
const {t, tm, rt} = useI18n()
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

443
pnpm-lock.yaml generated
View File

@ -28,7 +28,13 @@ importers:
version: 1.10.0
'@nuxt/ui':
specifier: 3.1.3
version: 3.1.3(embla-carousel@8.6.0)(typescript@5.8.3)(vite@6.3.5)(vue-router@4.5.1)(vue@3.5.16)
version: 3.1.3(embla-carousel@8.6.0)(typescript@5.8.3)(valibot@1.1.0)(vite@6.3.5)(vue-router@4.5.1)(vue@3.5.16)
'@nuxtjs/i18n':
specifier: 9.5.5
version: 9.5.5(eslint@9.28.0)(rollup@4.43.0)(vue@3.5.16)
'@tailwindcss/vite':
specifier: ^4.1.10
version: 4.1.10(vite@6.3.5)
'@websites/tsconfig':
specifier: workspace:*
version: link:../../packages/tsconfig
@ -38,9 +44,15 @@ importers:
nuxt:
specifier: ^3.17.5
version: 3.17.5(@types/node@24.0.1)(eslint@9.28.0)(rollup@4.43.0)(typescript@5.8.3)(vite@6.3.5)(vue-tsc@2.2.10)
tailwindcss:
specifier: ^4.1.10
version: 4.1.10
typescript:
specifier: ^5.6.3
version: 5.8.3
valibot:
specifier: ^1.1.0
version: 1.1.0(typescript@5.8.3)
vue:
specifier: ^3.5.16
version: 3.5.16(typescript@5.8.3)
@ -86,7 +98,7 @@ importers:
version: 3.19.1(@types/node@24.0.1)(typescript@5.8.3)(vitest@3.2.3)
'@nuxt/ui':
specifier: 3.1.3
version: 3.1.3(embla-carousel@8.6.0)(typescript@5.8.3)(vite@6.3.5)(vue-router@4.5.1)(vue@3.5.16)
version: 3.1.3(embla-carousel@8.6.0)(typescript@5.8.3)(valibot@1.1.0)(vite@6.3.5)(vue-router@4.5.1)(vue@3.5.16)
'@types/node':
specifier: latest
version: 24.0.1
@ -839,6 +851,147 @@ packages:
dependencies:
'@swc/helpers': 0.5.17
/@intlify/bundle-utils@10.0.1(vue-i18n@10.0.7):
resolution: {integrity: sha512-WkaXfSevtpgtUR4t8K2M6lbR7g03mtOxFeh+vXp5KExvPqS12ppaRj1QxzwRuRI5VUto54A22BjKoBMLyHILWQ==}
engines: {node: '>= 18'}
peerDependencies:
petite-vue-i18n: '*'
vue-i18n: '*'
peerDependenciesMeta:
petite-vue-i18n:
optional: true
vue-i18n:
optional: true
dependencies:
'@intlify/message-compiler': 11.1.5
'@intlify/shared': 11.1.5
acorn: 8.15.0
escodegen: 2.1.0
estree-walker: 2.0.2
jsonc-eslint-parser: 2.4.0
mlly: 1.7.4
source-map-js: 1.2.1
vue-i18n: 10.0.7(vue@3.5.16)
yaml-eslint-parser: 1.3.0
dev: false
/@intlify/core-base@10.0.7:
resolution: {integrity: sha512-mE71aUH5baH0me8duB4FY5qevUJizypHsYw3eCvmOx07QvmKppgOONx3dYINxuA89Z2qkAGb/K6Nrpi7aAMwew==}
engines: {node: '>= 16'}
dependencies:
'@intlify/message-compiler': 10.0.7
'@intlify/shared': 10.0.7
dev: false
/@intlify/core@10.0.7:
resolution: {integrity: sha512-4n9tKt0/HcPrXfm0ceQlNC/wsgrrfXyHwRHSSiekMAy5vkOBc4PJXB5aUHGGkkH0dDdlkYyxUWqhZ3V64+gcKw==}
engines: {node: '>= 16'}
dependencies:
'@intlify/core-base': 10.0.7
'@intlify/shared': 10.0.7
dev: false
/@intlify/h3@0.6.1:
resolution: {integrity: sha512-hFMcqWXCoFNZkraa+JF7wzByGdE0vGi8rUs7CTFrE4hE3X2u9QcelH8VRO8mPgJDH+TgatzvrVp6iZsWVluk2A==}
engines: {node: '>= 18'}
dependencies:
'@intlify/core': 10.0.7
'@intlify/utils': 0.13.0
dev: false
/@intlify/message-compiler@10.0.7:
resolution: {integrity: sha512-nrC4cDL/UHZSUqd8sRbVz+DPukzZ8NnG5OK+EB/nlxsH35deyzyVkXP/QuR8mFZrISJ+4hCd6VtCQCcT+RO+5g==}
engines: {node: '>= 16'}
dependencies:
'@intlify/shared': 10.0.7
source-map-js: 1.2.1
dev: false
/@intlify/message-compiler@11.1.5:
resolution: {integrity: sha512-YLSBbjD7qUdShe3ZAat9Hnf9E8FRpN6qmNFD/x5Xg5JVXjsks0kJ90Zj6aAuyoppJQA/YJdWZ8/bB7k3dg2TjQ==}
engines: {node: '>= 16'}
dependencies:
'@intlify/shared': 11.1.5
source-map-js: 1.2.1
dev: false
/@intlify/shared@10.0.7:
resolution: {integrity: sha512-oeoq0L5+5P4ShXa6jBQcx+BT+USe3MjX0xJexZO1y7rfDJdwZ9+QP3jO4tcS1nxhBYYdjvFTqe4bmnLijV0GxQ==}
engines: {node: '>= 16'}
dev: false
/@intlify/shared@11.1.5:
resolution: {integrity: sha512-+I4vRzHm38VjLr/CAciEPJhGYFzWWW4HMTm+6H3WqknXLh0ozNX9oC8ogMUwTSXYR/wGUb1/lTpNziiCH5MybQ==}
engines: {node: '>= 16'}
dev: false
/@intlify/unplugin-vue-i18n@6.0.8(eslint@9.28.0)(rollup@4.43.0)(typescript@5.8.3)(vue-i18n@10.0.7)(vue@3.5.16):
resolution: {integrity: sha512-Vvm3KhjE6TIBVUQAk37rBiaYy2M5OcWH0ZcI1XKEsOTeN1o0bErk+zeuXmcrcMc/73YggfI8RoxOUz9EB/69JQ==}
engines: {node: '>= 18'}
peerDependencies:
petite-vue-i18n: '*'
vue: ^3.2.25
vue-i18n: '*'
peerDependenciesMeta:
petite-vue-i18n:
optional: true
vue-i18n:
optional: true
dependencies:
'@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0)
'@intlify/bundle-utils': 10.0.1(vue-i18n@10.0.7)
'@intlify/shared': 11.1.5
'@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.1.5)(vue-i18n@10.0.7)(vue@3.5.16)
'@rollup/pluginutils': 5.1.4(rollup@4.43.0)
'@typescript-eslint/scope-manager': 8.34.0
'@typescript-eslint/typescript-estree': 8.34.0(typescript@5.8.3)
debug: 4.4.1
fast-glob: 3.3.3
js-yaml: 4.1.0
json5: 2.2.3
pathe: 1.1.2
picocolors: 1.1.1
source-map-js: 1.2.1
unplugin: 1.16.1
vue: 3.5.16(typescript@5.8.3)
vue-i18n: 10.0.7(vue@3.5.16)
transitivePeerDependencies:
- '@vue/compiler-dom'
- eslint
- rollup
- supports-color
- typescript
dev: false
/@intlify/utils@0.13.0:
resolution: {integrity: sha512-8i3uRdAxCGzuHwfmHcVjeLQBtysQB2aXl/ojoagDut5/gY5lvWCQ2+cnl2TiqE/fXj/D8EhWG/SLKA7qz4a3QA==}
engines: {node: '>= 18'}
dev: false
/@intlify/vue-i18n-extensions@8.0.0(@intlify/shared@11.1.5)(vue-i18n@10.0.7)(vue@3.5.16):
resolution: {integrity: sha512-w0+70CvTmuqbskWfzeYhn0IXxllr6mU+IeM2MU0M+j9OW64jkrvqY+pYFWrUnIIC9bEdij3NICruicwd5EgUuQ==}
engines: {node: '>= 18'}
peerDependencies:
'@intlify/shared': ^9.0.0 || ^10.0.0 || ^11.0.0
'@vue/compiler-dom': ^3.0.0
vue: ^3.0.0
vue-i18n: ^9.0.0 || ^10.0.0 || ^11.0.0
peerDependenciesMeta:
'@intlify/shared':
optional: true
'@vue/compiler-dom':
optional: true
vue:
optional: true
vue-i18n:
optional: true
dependencies:
'@babel/parser': 7.27.5
'@intlify/shared': 11.1.5
vue: 3.5.16(typescript@5.8.3)
vue-i18n: 10.0.7(vue@3.5.16)
dev: false
/@ioredis/commands@1.2.0:
resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==}
@ -928,6 +1081,16 @@ packages:
- encoding
- supports-color
/@miyaneee/rollup-plugin-json5@1.2.0(rollup@4.43.0):
resolution: {integrity: sha512-JjTIaXZp9WzhUHpElrqPnl1AzBi/rvRs065F71+aTmlqvTMVkdbjZ8vfFl4nRlgJy+TPBw69ZK4pwFdmOAt4aA==}
peerDependencies:
rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0
dependencies:
'@rollup/pluginutils': 5.1.4(rollup@4.43.0)
json5: 2.2.3
rollup: 4.43.0
dev: false
/@napi-rs/wasm-runtime@0.2.11:
resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==}
requiresBuild: true
@ -1492,7 +1655,7 @@ packages:
- yaml
dev: true
/@nuxt/ui@3.1.3(embla-carousel@8.6.0)(typescript@5.8.3)(vite@6.3.5)(vue-router@4.5.1)(vue@3.5.16):
/@nuxt/ui@3.1.3(embla-carousel@8.6.0)(typescript@5.8.3)(valibot@1.1.0)(vite@6.3.5)(vue-router@4.5.1)(vue@3.5.16):
resolution: {integrity: sha512-mhoYyXrRf1JAWj3RZ3htGup9N/IbNgNLn4jWHBxOilEFUk7af6qGUVqawv/EiPRa8iP2kK3tkxmzZ0wf2wt/KQ==}
hasBin: true
peerDependencies:
@ -1561,6 +1724,7 @@ packages:
unplugin: 2.3.5
unplugin-auto-import: 19.3.0(@nuxt/kit@3.17.5)(@vueuse/core@13.3.0)
unplugin-vue-components: 28.7.0(@nuxt/kit@3.17.5)(vue@3.5.16)
valibot: 1.1.0(typescript@5.8.3)
vaul-vue: 0.4.1(reka-ui@2.3.1)(vue@3.5.16)
vue-component-type-helpers: 2.2.10
vue-router: 4.5.1(vue@3.5.16)
@ -1677,6 +1841,54 @@ packages:
transitivePeerDependencies:
- magicast
/@nuxtjs/i18n@9.5.5(eslint@9.28.0)(rollup@4.43.0)(vue@3.5.16):
resolution: {integrity: sha512-c3zuH9JCslzRGbe5OVq7FFF4BFQuTUvHncaIk6gROf0uFbc7uqAL3h+MQSV7kQj9bRsbBoccppYqITTuKb3dvg==}
engines: {node: '>=18.12.0'}
dependencies:
'@intlify/h3': 0.6.1
'@intlify/shared': 10.0.7
'@intlify/unplugin-vue-i18n': 6.0.8(eslint@9.28.0)(rollup@4.43.0)(typescript@5.8.3)(vue-i18n@10.0.7)(vue@3.5.16)
'@intlify/utils': 0.13.0
'@miyaneee/rollup-plugin-json5': 1.2.0(rollup@4.43.0)
'@nuxt/kit': 3.17.5(magicast@0.3.5)
'@oxc-parser/wasm': 0.60.0
'@rollup/plugin-yaml': 4.1.2(rollup@4.43.0)
'@vue/compiler-sfc': 3.5.16
debug: 4.4.1
defu: 6.1.4
esbuild: 0.25.5
estree-walker: 3.0.3
h3: 1.15.3
knitwork: 1.2.0
magic-string: 0.30.17
mlly: 1.7.4
oxc-parser: 0.70.0
pathe: 2.0.3
typescript: 5.8.3
ufo: 1.6.1
unplugin: 2.3.5
unplugin-vue-router: 0.12.0(vue-router@4.5.1)(vue@3.5.16)
vue-i18n: 10.0.7(vue@3.5.16)
vue-router: 4.5.1(vue@3.5.16)
transitivePeerDependencies:
- '@vue/compiler-dom'
- eslint
- magicast
- petite-vue-i18n
- rollup
- supports-color
- vue
dev: false
/@oxc-parser/binding-darwin-arm64@0.70.0:
resolution: {integrity: sha512-pIi7L9PnsBctS/ruW6JQVSYRJkh76PblBN46uQxpBfVsM57c1s4HGZlmGysQWbdmQTFDZW+SmH3u0JpmDLF0+A==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: false
optional: true
/@oxc-parser/binding-darwin-arm64@0.72.3:
resolution: {integrity: sha512-g6wgcfL7At4wHNHutl0NmPZTAju+cUSmSX5WGUMyTJmozRzhx8E9a2KL4rTqNJPwEpbCFrgC29qX9f4fpDnUpA==}
engines: {node: '>=14.0.0'}
@ -1685,6 +1897,15 @@ packages:
requiresBuild: true
optional: true
/@oxc-parser/binding-darwin-x64@0.70.0:
resolution: {integrity: sha512-EbKqtOHzZR56ZFC5HHg6XrYneFAJmpLC1Z6FSgbI061Ley1atAViQg7S6Agm9wAcPpns+BeFJqXEBx/y3MKa2w==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: false
optional: true
/@oxc-parser/binding-darwin-x64@0.72.3:
resolution: {integrity: sha512-pc+tplB2fd0AqdnXY90FguqSF2OwbxXwrMOLAMmsUiK4/ytr8Z/ftd49+d27GgvQJKeg2LfnIbskaQtY/j2tAA==}
engines: {node: '>=14.0.0'}
@ -1693,6 +1914,15 @@ packages:
requiresBuild: true
optional: true
/@oxc-parser/binding-freebsd-x64@0.70.0:
resolution: {integrity: sha512-MVUaOMEUVE8q3nsWtEo589h++V5wAdqTbCRa9WY4Yuyxska4xcuJQk/kDNCx+n92saS7Luk+b20O9+VCI03c+A==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [freebsd]
requiresBuild: true
dev: false
optional: true
/@oxc-parser/binding-freebsd-x64@0.72.3:
resolution: {integrity: sha512-igBR6rOvL8t5SBm1f1rjtWNsjB53HNrM3au582JpYzWxOqCjeA5Jlm9KZbjQJC+J8SPB9xyljM7G+6yGZ2UAkQ==}
engines: {node: '>=14.0.0'}
@ -1701,6 +1931,15 @@ packages:
requiresBuild: true
optional: true
/@oxc-parser/binding-linux-arm-gnueabihf@0.70.0:
resolution: {integrity: sha512-8N4JTYTgKiRHlMUDAdzKs6iEC57a8ex408VgKoLD/Fl+Un79qOti3S9sotdnWSdH/BsDQeO5NW+PKaqFBTw+hA==}
engines: {node: '>=14.0.0'}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@oxc-parser/binding-linux-arm-gnueabihf@0.72.3:
resolution: {integrity: sha512-/izdr3wg7bK+2RmNhZXC2fQwxbaTH3ELeqdR+Wg4FiEJ/C7ZBIjfB0E734bZGgbDu+rbEJTBlbG77XzY0wRX/Q==}
engines: {node: '>=14.0.0'}
@ -1709,6 +1948,15 @@ packages:
requiresBuild: true
optional: true
/@oxc-parser/binding-linux-arm-musleabihf@0.70.0:
resolution: {integrity: sha512-Bsu+YvtgWuSfSDJTHMF5APZBOtvddR0GiHyrL0yaXDwaYvAL/E7XcoSK2GdmKTpw+J8nk5IlejEXlQliPo52pQ==}
engines: {node: '>=14.0.0'}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@oxc-parser/binding-linux-arm-musleabihf@0.72.3:
resolution: {integrity: sha512-Vz7C+qJb22HIFl3zXMlwvlTOR+MaIp5ps78060zsdeZh2PUGlYuUYkYXtGEjJV3kc8aKFj79XKqAY1EPG2NWQA==}
engines: {node: '>=14.0.0'}
@ -1717,6 +1965,15 @@ packages:
requiresBuild: true
optional: true
/@oxc-parser/binding-linux-arm64-gnu@0.70.0:
resolution: {integrity: sha512-tDzHWKexJPHR+qSiuAFoZ1v8EgCd4ggBNbjJHkcIHsoYKnsKaT1+uE9xfW9UhI1mhv2lo1JJ9n9og2yDTGxSeA==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@oxc-parser/binding-linux-arm64-gnu@0.72.3:
resolution: {integrity: sha512-nomoMe2VpVxW767jhF+G3mDGmE0U6nvvi5nw9Edqd/5DIylQfq/lEGUWL7qITk+E72YXBsnwHtpRRlIAJOMyZg==}
engines: {node: '>=14.0.0'}
@ -1725,6 +1982,15 @@ packages:
requiresBuild: true
optional: true
/@oxc-parser/binding-linux-arm64-musl@0.70.0:
resolution: {integrity: sha512-BJ+N25UWmHU624558ojSTnht3uFL00jV1c8qk1hnKf4cl6+ovFcoktRWAWSBlgLEP8tLlu8qgIhz875tMj2PkQ==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@oxc-parser/binding-linux-arm64-musl@0.72.3:
resolution: {integrity: sha512-4DswiIK5dI7hFqcMKWtZ7IZnWkRuskh6poI1ad4gkY2p678NOGtl6uOGCCRlDmLOOhp3R27u4VCTzQ6zra977w==}
engines: {node: '>=14.0.0'}
@ -1733,6 +1999,15 @@ packages:
requiresBuild: true
optional: true
/@oxc-parser/binding-linux-riscv64-gnu@0.70.0:
resolution: {integrity: sha512-nxu22nVuPA2xy1cxvBC0D5mVl0myqStOw3XBkVkDViNL01iPyuEFJd5VsM0GqsgrXvF95H/jrbMd+XWnto924g==}
engines: {node: '>=14.0.0'}
cpu: [riscv64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@oxc-parser/binding-linux-riscv64-gnu@0.72.3:
resolution: {integrity: sha512-R9GEiA4WFPGU/3RxAhEd6SaMdpqongGTvGEyTvYCS/MAQyXKxX/LFvc2xwjdvESpjIemmc/12aTTq6if28vHkQ==}
engines: {node: '>=14.0.0'}
@ -1741,6 +2016,15 @@ packages:
requiresBuild: true
optional: true
/@oxc-parser/binding-linux-s390x-gnu@0.70.0:
resolution: {integrity: sha512-AQ6Xj97lYRxHZl94cZIHJxT5M1qkeEi+vQe+e7M2lAtjcURl8cwhZmWKSv4rt4BQRVfO3ys0bY8AgIh4eFJiqw==}
engines: {node: '>=14.0.0'}
cpu: [s390x]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@oxc-parser/binding-linux-s390x-gnu@0.72.3:
resolution: {integrity: sha512-/sEYJQMVqikZO8gK9VDPT4zXo9du3gvvu8jp6erMmW5ev+14PErWRypJjktp0qoTj+uq4MzXro0tg7U+t5hP1w==}
engines: {node: '>=14.0.0'}
@ -1749,6 +2033,15 @@ packages:
requiresBuild: true
optional: true
/@oxc-parser/binding-linux-x64-gnu@0.70.0:
resolution: {integrity: sha512-RIxaVsIxtG90CoX6/Okij8itaMrJp4SEJm1pSL0pz3hGo0yur3Il9M1mmGvOpW+avY8uHdwXIvf2qMnnTKZuoQ==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@oxc-parser/binding-linux-x64-gnu@0.72.3:
resolution: {integrity: sha512-hlyljEZ0sMPKJQCd5pxnRh2sAf/w+Ot2iJecgV9Hl3brrYrYCK2kofC0DFaJM3NRmG/8ZB3PlxnSRSKZTocwCw==}
engines: {node: '>=14.0.0'}
@ -1757,6 +2050,15 @@ packages:
requiresBuild: true
optional: true
/@oxc-parser/binding-linux-x64-musl@0.70.0:
resolution: {integrity: sha512-B3S0G4TlZ+WLdQq4mSQtt2ZW0MAkKWc8dla17tZY86kcXvvCWwACvj7I27Z/nSlb7uJOdRZS9/r6Gw0uAARNVQ==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@oxc-parser/binding-linux-x64-musl@0.72.3:
resolution: {integrity: sha512-T17S8ORqAIq+YDFMvLfbNdAiYHYDM1+sLMNhesR5eWBtyTHX510/NbgEvcNemO9N6BNR7m4A9o+q468UG+dmbg==}
engines: {node: '>=14.0.0'}
@ -1765,6 +2067,16 @@ packages:
requiresBuild: true
optional: true
/@oxc-parser/binding-wasm32-wasi@0.70.0:
resolution: {integrity: sha512-QN8yxH7eHXTqed8Oo7ZUzOWn6hixXa8EVINLy21eLU9isoifSPKMswSmCXHxsM2L5rIIvzoaKfghGOru1mMQbw==}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
requiresBuild: true
dependencies:
'@napi-rs/wasm-runtime': 0.2.11
dev: false
optional: true
/@oxc-parser/binding-wasm32-wasi@0.72.3:
resolution: {integrity: sha512-x0Ojn/jyRUk6MllvVB/puSvI2tczZBIYweKVYHNv1nBatjPRiqo+6/uXiKrZwSfGLkGARrKkTuHSa5RdZBMOdA==}
engines: {node: '>=14.0.0'}
@ -1774,6 +2086,15 @@ packages:
'@napi-rs/wasm-runtime': 0.2.11
optional: true
/@oxc-parser/binding-win32-arm64-msvc@0.70.0:
resolution: {integrity: sha512-6k8/s78g0GQKqrxk4F0wYj32NBF9oSP6089e6BeuIRQ9l+Zh0cuI6unJeLzXNszxmlqq84xmf/tmP3MSDG43Uw==}
engines: {node: '>=14.0.0'}
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: false
optional: true
/@oxc-parser/binding-win32-arm64-msvc@0.72.3:
resolution: {integrity: sha512-kRVAl87ugRjLZTm9vGUyiXU50mqxLPHY81rgnZUP1HtNcqcmTQtM/wUKQL2UdqvhA6xm6zciqzqCgJfU+RW8uA==}
engines: {node: '>=14.0.0'}
@ -1782,6 +2103,15 @@ packages:
requiresBuild: true
optional: true
/@oxc-parser/binding-win32-x64-msvc@0.70.0:
resolution: {integrity: sha512-nd9o1QtEvupaJZ3Wn7PfsuC00n31NNRQZ5+Mui6Q0ZyDzp+obqPUSbSt7xh9Dy0c5zgtYMk8WY4n/VBJY2VvTQ==}
engines: {node: '>=14.0.0'}
cpu: [x64]
os: [win32]
requiresBuild: true
dev: false
optional: true
/@oxc-parser/binding-win32-x64-msvc@0.72.3:
resolution: {integrity: sha512-vpVdoGAP5iGE5tIEPJgr7FkQJZA+sKjMkg5x1jarWJ1nnBamfGsfYiZum4QjCfW7jb+pl42rHVSS3lRmMPcyrQ==}
engines: {node: '>=14.0.0'}
@ -1790,6 +2120,21 @@ packages:
requiresBuild: true
optional: true
/@oxc-parser/wasm@0.60.0:
resolution: {integrity: sha512-Dkf9/D87WGBCW3L0+1DtpAfL4SrNsgeRvxwjpKCtbH7Kf6K+pxrT0IridaJfmWKu1Ml+fDvj+7HEyBcfUC/TXQ==}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
dependencies:
'@oxc-project/types': 0.60.0
dev: false
/@oxc-project/types@0.60.0:
resolution: {integrity: sha512-prhfNnb3ATFHOCv7mzKFfwLij5RzoUz6Y1n525ZhCEqfq5wreCXL+DyVoq3ShukPo7q45ZjYIdjFUgjj+WKzng==}
dev: false
/@oxc-project/types@0.70.0:
resolution: {integrity: sha512-ngyLUpUjO3dpqygSRQDx7nMx8+BmXbWOU4oIwTJFV2MVIDG7knIZwgdwXlQWLg3C3oxg1lS7ppMtPKqKFb7wzw==}
dev: false
/@oxc-project/types@0.72.3:
resolution: {integrity: sha512-CfAC4wrmMkUoISpQkFAIfMVvlPfQV3xg7ZlcqPXPOIMQhdKIId44G8W0mCPgtpWdFFAyJ+SFtiM+9vbyCkoVng==}
@ -2057,6 +2402,21 @@ packages:
smob: 1.5.0
terser: 5.42.0
/@rollup/plugin-yaml@4.1.2(rollup@4.43.0):
resolution: {integrity: sha512-RpupciIeZMUqhgFE97ba0s98mOFS7CWzN3EJNhJkqSv9XLlWYtwVdtE6cDw6ASOF/sZVFS7kRJXftaqM2Vakdw==}
engines: {node: '>=14.0.0'}
peerDependencies:
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
peerDependenciesMeta:
rollup:
optional: true
dependencies:
'@rollup/pluginutils': 5.1.4(rollup@4.43.0)
js-yaml: 4.1.0
rollup: 4.43.0
tosource: 2.0.0-alpha.3
dev: false
/@rollup/pluginutils@5.1.4(rollup@4.43.0):
resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==}
engines: {node: '>=14.0.0'}
@ -2549,7 +2909,6 @@ packages:
dependencies:
'@typescript-eslint/types': 8.34.0
'@typescript-eslint/visitor-keys': 8.34.0
dev: true
/@typescript-eslint/tsconfig-utils@8.34.0(typescript@5.8.3):
resolution: {integrity: sha512-+W9VYHKFIzA5cBeooqQxqNriAP0QeQ7xTiDuIOr71hzgffm3EL2hxwWBIIj4GuofIbKxGNarpKqIq6Q6YrShOA==}
@ -4701,6 +5060,15 @@ packages:
acorn-jsx: 5.3.2(acorn@8.15.0)
eslint-visitor-keys: 4.2.1
/espree@9.6.1:
resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
acorn: 8.15.0
acorn-jsx: 5.3.2(acorn@8.15.0)
eslint-visitor-keys: 3.4.3
dev: false
/esprima@4.0.1:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
engines: {node: '>=4'}
@ -5532,6 +5900,16 @@ packages:
engines: {node: '>=6'}
hasBin: true
/jsonc-eslint-parser@2.4.0:
resolution: {integrity: sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
acorn: 8.15.0
eslint-visitor-keys: 3.4.3
espree: 9.6.1
semver: 7.7.2
dev: false
/junk@4.0.1:
resolution: {integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==}
engines: {node: '>=12.20'}
@ -6491,6 +6869,28 @@ packages:
type-check: 0.4.0
word-wrap: 1.2.5
/oxc-parser@0.70.0:
resolution: {integrity: sha512-YbqTuQDDIYwQF/li0VFK5uTbmHV4jWFeQQONkPdf77vz+JMiq7SusmcSVZ4hBrGM+3WyLdKH5S7spnvz4XVVzQ==}
engines: {node: '>=14.0.0'}
dependencies:
'@oxc-project/types': 0.70.0
optionalDependencies:
'@oxc-parser/binding-darwin-arm64': 0.70.0
'@oxc-parser/binding-darwin-x64': 0.70.0
'@oxc-parser/binding-freebsd-x64': 0.70.0
'@oxc-parser/binding-linux-arm-gnueabihf': 0.70.0
'@oxc-parser/binding-linux-arm-musleabihf': 0.70.0
'@oxc-parser/binding-linux-arm64-gnu': 0.70.0
'@oxc-parser/binding-linux-arm64-musl': 0.70.0
'@oxc-parser/binding-linux-riscv64-gnu': 0.70.0
'@oxc-parser/binding-linux-s390x-gnu': 0.70.0
'@oxc-parser/binding-linux-x64-gnu': 0.70.0
'@oxc-parser/binding-linux-x64-musl': 0.70.0
'@oxc-parser/binding-wasm32-wasi': 0.70.0
'@oxc-parser/binding-win32-arm64-msvc': 0.70.0
'@oxc-parser/binding-win32-x64-msvc': 0.70.0
dev: false
/oxc-parser@0.72.3:
resolution: {integrity: sha512-JYQeJKDcUTTZ/uTdJ+fZBGFjAjkLD1h0p3Tf44ZYXRcoMk+57d81paNPFAAwzrzzqhZmkGvKKXDxwyhJXYZlpg==}
engines: {node: '>=14.0.0'}
@ -7918,6 +8318,11 @@ packages:
/toml@3.0.0:
resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==}
/tosource@2.0.0-alpha.3:
resolution: {integrity: sha512-KAB2lrSS48y91MzFPFuDg4hLbvDiyTjOVgaK7Erw+5AmZXNq4sFRVn8r6yxSLuNs15PaokrDRpS61ERY9uZOug==}
engines: {node: '>=10'}
dev: false
/totalist@3.0.1:
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
engines: {node: '>=6'}
@ -8435,6 +8840,16 @@ packages:
resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==}
hasBin: true
/valibot@1.1.0(typescript@5.8.3):
resolution: {integrity: sha512-Nk8lX30Qhu+9txPYTwM0cFlWLdPFsFr6LblzqIySfbZph9+BFsAHsNvHOymEviUepeIW6KFHzpX8TKhbptBXXw==}
peerDependencies:
typescript: '>=5'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
typescript: 5.8.3
/validate-npm-package-license@3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
dependencies:
@ -8773,6 +9188,18 @@ packages:
- supports-color
dev: true
/vue-i18n@10.0.7(vue@3.5.16):
resolution: {integrity: sha512-bKsk0PYwP9gdYF4nqSAT0kDpnLu1gZzlxFl885VH4mHVhEnqP16+/mAU05r1U6NIrc0fGDWP89tZ8GzeJZpe+w==}
engines: {node: '>= 16'}
peerDependencies:
vue: ^3.0.0
dependencies:
'@intlify/core-base': 10.0.7
'@intlify/shared': 10.0.7
'@vue/devtools-api': 6.6.4
vue: 3.5.16(typescript@5.8.3)
dev: false
/vue-router@4.5.1(vue@3.5.16):
resolution: {integrity: sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==}
peerDependencies:
@ -8956,6 +9383,14 @@ packages:
resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
engines: {node: '>=18'}
/yaml-eslint-parser@1.3.0:
resolution: {integrity: sha512-E/+VitOorXSLiAqtTd7Yqax0/pAS3xaYMP+AUUJGOK1OZG3rhcj9fcJOM5HJ2VrP1FrStVCWr1muTfQCdj4tAA==}
engines: {node: ^14.17.0 || >=16.0.0}
dependencies:
eslint-visitor-keys: 3.4.3
yaml: 2.8.0
dev: false
/yaml@2.8.0:
resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==}
engines: {node: '>= 14.6'}