most of it
This commit is contained in:
@@ -5,32 +5,24 @@
|
||||
|
||||
<div class="footer">
|
||||
<div class="infos">
|
||||
<h3>Wasserski Erfurt</h3>
|
||||
<h3>AllKids Erfurt</h3>
|
||||
<div class="infos-inner">
|
||||
<div class="upper">
|
||||
<p>Inh. Michael Sadlon</p>
|
||||
<p>Zum Nordstrand 4</p>
|
||||
<p>99085 Erfurt</p>
|
||||
<p>Inh. Grit Grenzdörfer</p>
|
||||
<p>Eichenstraße 8</p>
|
||||
<p>99084 Erfurt</p>
|
||||
</div>
|
||||
<div class="lower">
|
||||
<p>Tel.: 0361 - 796 876 4</p>
|
||||
<p>Fax.: 0361 - 796 876 8</p>
|
||||
<p>Email: info@wasserski-erfurt.de</p>
|
||||
<p>Tel.: <a href="tel:+491784124555">0178 4124555</a></p>
|
||||
<p>Email: <a href="mailto:kiro0206@icloud.com">kiro0206@icloud.com</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="social">
|
||||
<a href="https://www.instagram.com/wasserski_erfurt/">
|
||||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M11.7 3h12.6c4.8 0 8.7 3.9 8.7 8.7v12.6a8.7 8.7 0 0 1-8.7 8.7H11.7C6.9 33 3 29.1 3 24.3V11.7A8.7 8.7 0 0 1 11.7 3zm-.3 3A5.4 5.4 0 0 0 6 11.4v13.2c0 2.985 2.415 5.4 5.4 5.4h13.2a5.4 5.4 0 0 0 5.4-5.4V11.4C30 8.415 27.585 6 24.6 6H11.4zm14.475 2.25a1.875 1.875 0 1 1 0 3.75 1.875 1.875 0 0 1 0-3.75zM18 10.5a7.5 7.5 0 1 1 0 15 7.5 7.5 0 0 1 0-15zm0 3a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9z"
|
||||
fill="#333333"></path>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="https://www.facebook.com/wasserskierfurt/">
|
||||
<a href="https://www.facebook.com/allkids.erfurt/">
|
||||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M18 3.06c-8.25 0-15 6.735-15 15.03 0 7.5 5.49 13.725 12.66 14.85v-10.5h-3.81v-4.35h3.81v-3.315c0-3.765 2.235-5.835 5.67-5.835 1.635 0 3.345.285 3.345.285v3.705h-1.89c-1.86 0-2.445 1.155-2.445 2.34v2.82h4.17l-.675 4.35H20.34v10.5A15 15 0 0 0 33 18.09c0-8.295-6.75-15.03-15-15.03z"
|
||||
fill="#333333"></path>
|
||||
fill="var(--normal-font-color)"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
@@ -39,11 +31,19 @@
|
||||
{#each $serviceNavigation?.elemente || [] as service, i (i)}
|
||||
<button
|
||||
on:click="{() => {
|
||||
navigate(`${$sites[service.seite]?.path}`)
|
||||
navigate(`${$sites[service.seite || '']?.path}`)
|
||||
}}">{service?.name}</button
|
||||
>
|
||||
{/each}
|
||||
</div>
|
||||
<button
|
||||
on:click="{() => {
|
||||
const body = document.querySelector('body')
|
||||
if (body) body.classList.toggle('darkTheme')
|
||||
}}"
|
||||
>
|
||||
toggletheme
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<style lang="less">
|
||||
@@ -58,7 +58,7 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
max-width: calc(@body-maxwidth - min(9vw, 200px));
|
||||
background-color: @hover-color;
|
||||
background-color: var(--hover-color);
|
||||
padding: min(4.5vw, 100px) min(4.5vw, 100px) 0px min(4.5vw, 100px);
|
||||
}
|
||||
.infos {
|
||||
@@ -91,17 +91,15 @@
|
||||
@media @tablet {
|
||||
gap: 40px;
|
||||
}
|
||||
height: 350px;
|
||||
min-height: 350px;
|
||||
.infos-inner {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
.footer {
|
||||
}
|
||||
}
|
||||
@media @desktop {
|
||||
.footer {
|
||||
height: 350px;
|
||||
min-height: 350px;
|
||||
.infos-inner {
|
||||
gap: 5vw;
|
||||
flex-direction: row;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
export let cookieName
|
||||
export let cookieName: string
|
||||
export let backgroundUrl = ""
|
||||
export let textPosition = "center"
|
||||
export let textPosition: "oben" | "mitte" | "unten" = "mitte"
|
||||
export let background = ""
|
||||
let contentShown = false
|
||||
const positions = {
|
||||
@@ -11,15 +11,16 @@
|
||||
}
|
||||
|
||||
window.addEventListener("ccAccept", (e) => {
|
||||
// @ts-ignore
|
||||
if (e.detail[1] == cookieName) contentShown = true
|
||||
})
|
||||
//isCookieSet isnt really precise
|
||||
function checkCookie(name) {
|
||||
function checkCookie(cookieName: string) {
|
||||
// Get all cookies
|
||||
var allCookies = decodeURIComponent(document.cookie)
|
||||
// Split into individual cookies
|
||||
var cookies = allCookies.split(";")
|
||||
var ccTagCookies = []
|
||||
var ccTagCookies: string[] = []
|
||||
cookies.forEach((e) => {
|
||||
e.includes("ccTags") ? (ccTagCookies = e.split(",")) : void 0
|
||||
})
|
||||
|
||||
@@ -3,18 +3,19 @@
|
||||
import CookieSet from "./cookieSet.svelte"
|
||||
$: iframeTitle = "testrest"
|
||||
|
||||
let setHeight = (element) => {
|
||||
let setHeight = (element: HTMLIFrameElement) => {
|
||||
element.style.height = (element.offsetWidth / 16) * 9 + "px"
|
||||
}
|
||||
</script>
|
||||
|
||||
<CookieSet cookieName="{'googleMaps'}" textPosition="{'unten'}" background="{'rgba(44, 44, 44, 0.4)'}">
|
||||
<!-- svelte-ignore a11y-missing-attribute -->
|
||||
<iframe
|
||||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d20097.11535738499!2d11.016094258611309!3d50.976613538609506!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x47a47295445dec17%3A0x78ec05d774043a43!2sall%20kids%20-%20Secondhand%20Kinderbekleidung!5e0!3m2!1sde!2sde!4v1694951373813!5m2!1sde!2sde"
|
||||
use:setHeight
|
||||
id="iframe"
|
||||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2510.8843160281504!2d11.046507612986247!3d50.99980984753832!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x47a46d575a841fe1%3A0xd6703e9ebe1ca279!2sErfurt%20Wasserski-%20und%20Wakeboardanlage!5e0!3m2!1sde!2sde!4v1682691189533!5m2!1sde!2sde"
|
||||
style="border:0;"
|
||||
allowfullscreen=""
|
||||
allowfullscreen="{true}"
|
||||
loading="lazy"
|
||||
referrerpolicy="no-referrer-when-downgrade"></iframe>
|
||||
</CookieSet>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import DesktopHeader from "./desktop.svelte"
|
||||
import MobileHeader from "./mobile.svelte"
|
||||
import { navigation } from "../../stores"
|
||||
</script>
|
||||
|
||||
<main class="headercontainer">
|
||||
@@ -18,7 +17,17 @@
|
||||
|
||||
<style global lang="less">
|
||||
@import "../../assets/css/main.less";
|
||||
@import "../../assets/css/variables.less";
|
||||
|
||||
@desktop: ~"only screen and (min-width: 1440px)";
|
||||
.HP {
|
||||
h2 {
|
||||
font-size: 2.1rem !important;
|
||||
@media @tablet {
|
||||
font-size: 3.2rem !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ignore {
|
||||
display: none !important;
|
||||
@@ -28,6 +37,7 @@
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
.placeholder {
|
||||
height: 105px;
|
||||
@@ -39,8 +49,9 @@
|
||||
top: 0px;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
color: #333;
|
||||
color: var(--normal-font-color);
|
||||
height: 105px;
|
||||
|
||||
}
|
||||
@media @desktop {
|
||||
.headercontainer,
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
else siteContainer.style.overflow = "initial"
|
||||
}
|
||||
|
||||
async function changeSubmenu(e, i) {
|
||||
async function changeSubmenu(e: EventTarget & HTMLLIElement, i: string | number) {
|
||||
changeStateOfSite(true)
|
||||
let submenu = document.getElementById("submenu-container")
|
||||
if (!submenu) return
|
||||
submenu.style.height = "calc(100vh - 120px)"
|
||||
submenu.classList.add("show-submenu")
|
||||
|
||||
@@ -21,23 +22,27 @@
|
||||
element.classList.remove("shown")
|
||||
})
|
||||
let shownMenu = document.getElementById("submenu-" + i)
|
||||
if (!shownMenu) return
|
||||
shownMenu.classList.add("shown")
|
||||
}
|
||||
|
||||
let hoverTimeout
|
||||
let hoverTimeout: string | number | NodeJS.Timeout | undefined
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<ul
|
||||
class="menu"
|
||||
on:mouseover="{(e) => {
|
||||
clearTimeout(hoverTimeout)
|
||||
hoverTimeout = setTimeout(() => {
|
||||
let element = document.getElementById('submenu-container')
|
||||
element.style.height = '0vh'
|
||||
changeStateOfSite(false)
|
||||
element.classList.remove('show-submenu')
|
||||
let elements = document.getElementsByClassName('select-menu')
|
||||
Array.from(elements).forEach((e) => e.classList.remove('select-menu'))
|
||||
if (element) {
|
||||
element.style.height = '0vh'
|
||||
changeStateOfSite(false)
|
||||
element.classList.remove('show-submenu')
|
||||
let elements = document.getElementsByClassName('select-menu')
|
||||
Array.from(elements).forEach((e) => e.classList.remove('select-menu'))
|
||||
}
|
||||
}, 500)
|
||||
}}"
|
||||
on:mouseleave="{() => {
|
||||
@@ -48,27 +53,34 @@
|
||||
class="logo-container"
|
||||
on:click="{() => {
|
||||
let element = document.getElementById('submenu-container')
|
||||
if (!element) return
|
||||
element.style.height = '0vh'
|
||||
element.classList.remove('show-submenu')
|
||||
changeStateOfSite(false)
|
||||
navigate('/')
|
||||
}}"
|
||||
>
|
||||
<button class="img-logo-container"><img src="media/logo.png" alt="logo" /></button>
|
||||
<p class="logo-text">Wasserski-Erfurt</p>
|
||||
<button class="img-logo-container"><img src="/media/logo.svg" alt="logo" /></button>
|
||||
<div class="logo-text">
|
||||
<p id="upper">ALL KIDS</p>
|
||||
<p id="lower">SO GÜNSTIG WIE NACHHALTIG</p>
|
||||
</div>
|
||||
</button>
|
||||
<ul class="menuitem-container">
|
||||
{#if $navigation?.elemente}
|
||||
{#each $navigation.elemente as site, i (i)}
|
||||
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||
<li
|
||||
class="menu-item"
|
||||
on:mousedown="{() => {
|
||||
if (site.endpoint) {
|
||||
let element = document.getElementById('submenu-container')
|
||||
element.style.height = '0vh'
|
||||
element.classList.remove('show-submenu')
|
||||
changeStateOfSite(false)
|
||||
navigate(`${$sites[site.seite].path}`)
|
||||
if (element) {
|
||||
element.style.height = '0vh'
|
||||
element.classList.remove('show-submenu')
|
||||
changeStateOfSite(false)
|
||||
navigate(`${$sites[site.seite || ''].path}`)
|
||||
}
|
||||
}
|
||||
}}"
|
||||
on:mouseenter|stopPropagation="{(e) => {
|
||||
@@ -86,8 +98,10 @@
|
||||
let elements = document.getElementsByClassName('select-menu')
|
||||
Array.from(elements).forEach((e) => e.classList.remove('select-menu'))
|
||||
let element = document.getElementById('submenu-container')
|
||||
element.style.height = '0vh'
|
||||
element.classList.remove('show-submenu')
|
||||
if (element) {
|
||||
element.style.height = '0vh'
|
||||
element.classList.remove('show-submenu')
|
||||
}
|
||||
changeStateOfSite(false)
|
||||
}, 500)
|
||||
}
|
||||
@@ -103,6 +117,7 @@
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<button
|
||||
class="submenu-container"
|
||||
id="submenu-container"
|
||||
@@ -117,6 +132,7 @@
|
||||
<div class="inner-container">
|
||||
{#each $navigation?.elemente as submenu, i (i * 10)}
|
||||
{#if !submenu?.endpoint}
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<button
|
||||
on:mouseover|stopPropagation
|
||||
class="innersubmenu-container"
|
||||
@@ -133,16 +149,17 @@
|
||||
/>
|
||||
</div>
|
||||
<ul class="sub-menu">
|
||||
{#each submenu?.elemente as submenu_point, i (i)}
|
||||
{#each submenu?.elemente || [] as submenu_point, i (i)}
|
||||
<li>
|
||||
<button
|
||||
class="submenu-item"
|
||||
on:click="{() => {
|
||||
let element = document.getElementById('submenu-container')
|
||||
if (!element) return
|
||||
element.style.height = '0vh'
|
||||
element.classList.remove('show-submenu')
|
||||
changeStateOfSite(false)
|
||||
navigate(`${$sites[submenu_point.seite]?.path}`)
|
||||
navigate(`${$sites[submenu_point.seite || '']?.path}`)
|
||||
}}">{submenu_point?.name}</button
|
||||
>
|
||||
</li>
|
||||
@@ -180,6 +197,18 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.logo-text {
|
||||
p {
|
||||
white-space: nowrap;
|
||||
text-align: left;
|
||||
}
|
||||
& > #upper {
|
||||
font-family: "Orbitron" !important;
|
||||
font-size: 30px;
|
||||
font-weight: 700;
|
||||
}
|
||||
& > #lower {
|
||||
font-size: 13px;
|
||||
}
|
||||
font-weight: bold;
|
||||
font-size: 1.2rem;
|
||||
padding-left: 10px;
|
||||
@@ -214,11 +243,11 @@
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: @hover-color;
|
||||
background-color: var(--hover-color);
|
||||
}
|
||||
}
|
||||
.select-menu {
|
||||
background-color: @hover-color;
|
||||
background-color: var(--hover-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -229,7 +258,7 @@
|
||||
overflow: hidden;
|
||||
width: 100vw;
|
||||
z-index: 2000;
|
||||
background-color: rgba(0, 0, 0, 0.854);
|
||||
background-color: var(--opposite-bg-color-80);
|
||||
opacity: 0;
|
||||
.inner-container {
|
||||
width: 100%;
|
||||
@@ -242,7 +271,7 @@
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
background-color: rgb(255, 255, 255);
|
||||
background-color: var(--background-color);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.submenu-most-inner-container {
|
||||
@@ -266,7 +295,7 @@
|
||||
width: 100%;
|
||||
text-align: start;
|
||||
&:hover {
|
||||
border-bottom: 1px solid rgba(24, 24, 24, 0.795);
|
||||
border-bottom: 1px solid var(--opposite-bg-color-80);
|
||||
}
|
||||
button {
|
||||
padding: 10px 0px;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
let images: HTMLImageElement[] = []
|
||||
function changeStateOfSite(menuOn: boolean) {
|
||||
let element = document.getElementById("menu")
|
||||
let element = document.getElementById("menu") as HTMLElement
|
||||
element.classList.toggle("show-menu")
|
||||
let body = document.body
|
||||
if (menuOn) {
|
||||
@@ -26,7 +26,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
function imageSlide(images) {
|
||||
function imageSlide(images: HTMLImageElement[]) {
|
||||
console.log(images)
|
||||
let currentImage = 0
|
||||
images[0].classList.add("show-img")
|
||||
@@ -39,12 +39,15 @@
|
||||
return () => clearInterval(interval)
|
||||
}
|
||||
|
||||
function pushImages(node) {
|
||||
function pushImages(node: HTMLImageElement) {
|
||||
images[0] = node
|
||||
}
|
||||
|
||||
$: {
|
||||
if (images.length != 0) imageSlide(document.getElementsByClassName("img-menu"))
|
||||
const images = Array.from(document.getElementsByClassName("img-menu")) as HTMLImageElement[]
|
||||
if (images.length !== 0) {
|
||||
imageSlide(images)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -54,18 +57,19 @@
|
||||
class="logo-container"
|
||||
on:click="{() => {
|
||||
navigate('/')
|
||||
let element = document.getElementById('menu')
|
||||
changeStateOfSite(element.classList.contains('show-menu'))
|
||||
}}"
|
||||
>
|
||||
<button class="img-logo-container"><img src="media/logo.png" alt="logo" /></button>
|
||||
<p class="logo-text">Wasserski-Erfurt</p>
|
||||
<button class="img-logo-container"><img src="/media/logo.svg" alt="logo" /></button>
|
||||
<div class="logo-text">
|
||||
<p id="upper">ALL KIDS</p>
|
||||
<p id="lower">SO GÜNSTIG WIE NACHHALTIG</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
class="button-three"
|
||||
on:click="{(e) => {
|
||||
let element = document.getElementById('menu')
|
||||
changeStateOfSite(element.classList.contains('show-menu'))
|
||||
if (element) changeStateOfSite(element.classList.contains('show-menu'))
|
||||
}}"
|
||||
aria-controls="primary-navigation"
|
||||
aria-expanded="false"
|
||||
@@ -87,22 +91,27 @@
|
||||
<div class="inner-container">
|
||||
<div class="higher-absolute">
|
||||
{#each $navigation.elemente as link, i (i)}
|
||||
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||
<li
|
||||
class="menu"
|
||||
on:mousedown|stopPropagation="{(e) => {
|
||||
if (link.endpoint) {
|
||||
navigate(`${$sites[link.seite]?.path}`)
|
||||
navigate(`${$sites[link.seite ?? '']?.path}`)
|
||||
let element = document.getElementById('menu')
|
||||
changeStateOfSite(element.classList.contains('show-menu'))
|
||||
if (element) changeStateOfSite(element.classList.contains('show-menu'))
|
||||
return
|
||||
}
|
||||
let element = e.currentTarget
|
||||
element.classList.toggle('active')
|
||||
let chevronContainer = document.getElementById('chevron-' + i)
|
||||
chevronContainer.src =
|
||||
chevronContainer.src.split('/')?.pop() == 'chevron-down.png'
|
||||
? 'media/chevron-up.png'
|
||||
: 'media/chevron-down.png'
|
||||
if (element) {
|
||||
element.classList.toggle('active')
|
||||
let chevronContainer = document.getElementById('chevron-' + i)
|
||||
if (chevronContainer)
|
||||
// @ts-ignore
|
||||
chevronContainer.src = // @ts-ignore
|
||||
chevronContainer.src.split('/')?.pop() == 'chevron-down.png'
|
||||
? 'media/chevron-up.png'
|
||||
: 'media/chevron-down.png'
|
||||
}
|
||||
}}"
|
||||
>
|
||||
<div class="menu-point">
|
||||
@@ -114,13 +123,14 @@
|
||||
</div>
|
||||
{#if !link?.endpoint}
|
||||
<ul class="submenu">
|
||||
{#each link.elemente as submenu, i (i)}
|
||||
{#each link.elemente ?? [] as submenu, i (i)}
|
||||
<li>
|
||||
<button
|
||||
on:mousedown="{(e) => {
|
||||
navigate(`${$sites[submenu.seite]?.path}`)
|
||||
navigate(`${$sites[submenu.seite ?? '']?.path}`)
|
||||
let element = document.getElementById('menu')
|
||||
changeStateOfSite(element.classList.contains('show-menu'))
|
||||
if (element)
|
||||
changeStateOfSite(element.classList.contains('show-menu'))
|
||||
}}">{submenu.name}</button
|
||||
>
|
||||
</li>
|
||||
@@ -131,20 +141,7 @@
|
||||
{/each}
|
||||
|
||||
<button class="socials">
|
||||
<a target="_blank" href="https://www.instagram.com/wasserski_erfurt/">
|
||||
<svg
|
||||
width="36"
|
||||
height="36"
|
||||
viewBox="0 0 36 36"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.7 3h12.6c4.8 0 8.7 3.9 8.7 8.7v12.6a8.7 8.7 0 0 1-8.7 8.7H11.7C6.9 33 3 29.1 3 24.3V11.7A8.7 8.7 0 0 1 11.7 3zm-.3 3A5.4 5.4 0 0 0 6 11.4v13.2c0 2.985 2.415 5.4 5.4 5.4h13.2a5.4 5.4 0 0 0 5.4-5.4V11.4C30 8.415 27.585 6 24.6 6H11.4zm14.475 2.25a1.875 1.875 0 1 1 0 3.75 1.875 1.875 0 0 1 0-3.75zM18 10.5a7.5 7.5 0 1 1 0 15 7.5 7.5 0 0 1 0-15zm0 3a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9z"
|
||||
fill="#fff"></path>
|
||||
</svg>
|
||||
</a>
|
||||
<a target="_blank" href="https://www.facebook.com/wasserskierfurt/">
|
||||
<a target="_blank" href="https://www.facebook.com/allkids.erfurt/">
|
||||
<svg
|
||||
width="36"
|
||||
height="36"
|
||||
@@ -200,7 +197,8 @@
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: white;
|
||||
background-color: var(--background-color);
|
||||
|
||||
ul {
|
||||
.header {
|
||||
padding: 0px min(4.5vw, 100px);
|
||||
@@ -209,7 +207,7 @@
|
||||
justify-content: space-between;
|
||||
height: 105px;
|
||||
.button-three {
|
||||
--button-color: #333;
|
||||
--button-color: var(--normal-font-color);
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
}
|
||||
@@ -234,14 +232,25 @@
|
||||
}
|
||||
|
||||
.logo-container {
|
||||
height: 50px;
|
||||
height: 38px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.logo-text {
|
||||
p {
|
||||
white-space: nowrap;
|
||||
text-align: left;
|
||||
}
|
||||
& > #upper {
|
||||
font-family: "Orbitron" !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
& > #lower {
|
||||
font-size: 10px;
|
||||
}
|
||||
font-weight: bold;
|
||||
font-size: 1.2rem;
|
||||
padding-left: 10px;
|
||||
color: #333;
|
||||
}
|
||||
.img-logo-container {
|
||||
height: 100%;
|
||||
@@ -282,7 +291,7 @@
|
||||
}
|
||||
}
|
||||
.menu-container {
|
||||
background-color: white;
|
||||
background-color: var(--background-color);
|
||||
position: absolute;
|
||||
z-index: 2000;
|
||||
opacity: 0;
|
||||
@@ -304,18 +313,18 @@
|
||||
width: 100%;
|
||||
left: 0px;
|
||||
padding: 0px min(4.5vw, 100px);
|
||||
background-color: white;
|
||||
background-color: var(--background-color);
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
}
|
||||
.socials {
|
||||
width: 100%;
|
||||
background-color: @link-font-color;
|
||||
background-color: var(--link-font-color);
|
||||
height: 50px;
|
||||
border-radius: 20px;
|
||||
color: white;
|
||||
color: var(--background-color);
|
||||
}
|
||||
.active {
|
||||
background-color: rgba(128, 128, 128, 0.153) !important;
|
||||
background-color: var(--normal-font-color-12) !important;
|
||||
.submenu {
|
||||
visibility: visible;
|
||||
max-height: 250px;
|
||||
|
||||
240
frontend/src/lib/components/pagebuilder/Homepage.svelte
Normal file
240
frontend/src/lib/components/pagebuilder/Homepage.svelte
Normal file
@@ -0,0 +1,240 @@
|
||||
<script lang="ts">
|
||||
import { sites } from "../../stores"
|
||||
import { register } from "swiper/element/bundle"
|
||||
import { onMount } from "svelte"
|
||||
import { navigate } from "svelte-routing"
|
||||
|
||||
let teasers = Object.values($sites)?.map((page) => ({ teaser: page.teaser, path: page.path }))
|
||||
|
||||
register(false)
|
||||
let swiper: any
|
||||
|
||||
function handleMouseOver() {}
|
||||
|
||||
function handleMouseOut() {}
|
||||
|
||||
onMount(async () => {
|
||||
if (swiper !== undefined) {
|
||||
const response = await fetch("/dist/index.css")
|
||||
const cssText = await response.text()
|
||||
|
||||
const params = {
|
||||
injectStyles: [cssText],
|
||||
}
|
||||
|
||||
Object.assign(swiper, params)
|
||||
console.log(swiper.getElementsByClassName("swiper-button-prev"), "test", swiper)
|
||||
swiper.initialize()
|
||||
|
||||
// Add the 'active' class to the h1 of the first slide
|
||||
const firstSlideH1 = document.querySelector(".swiper-slide-active .titles h1")
|
||||
if (firstSlideH1) {
|
||||
firstSlideH1.classList.add("active")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function handleSlideChange() {
|
||||
document.querySelectorAll(".titles h1").forEach((h1) => {
|
||||
h1.classList.remove("active")
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
const activeSlideUnderline = document.querySelector(".swiper-slide-active .titles h1")
|
||||
if (activeSlideUnderline) {
|
||||
activeSlideUnderline.classList.add("active")
|
||||
}
|
||||
}, 600)
|
||||
}
|
||||
let teaser = teasers[0]
|
||||
</script>
|
||||
|
||||
{#if teaser}
|
||||
<div class="container" id="HP">
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<swiper-container
|
||||
bind:this="{swiper}"
|
||||
slides-per-view="1"
|
||||
loop="{true}"
|
||||
direction="horizontal"
|
||||
effect="slide"
|
||||
navigation="{true}"
|
||||
init="{false}"
|
||||
autoplay="{{
|
||||
delay: 4000, // 5000ms = 5s
|
||||
pauseOnMouseEnter: true,
|
||||
}}"
|
||||
speed="600"
|
||||
on:focus
|
||||
on:blur
|
||||
on:slidechange="{() => handleSlideChange()}"
|
||||
on:mouseenter="{() => handleMouseOver()}"
|
||||
on:mouseleave="{() => handleMouseOut()}"
|
||||
class="relative"
|
||||
>
|
||||
{#each teasers as teaser}
|
||||
{#if teaser?.teaser?.showTeaser}
|
||||
<swiper-slide class="relative">
|
||||
<div class="inner-container">
|
||||
<div class="titles">
|
||||
<h2>{teaser?.teaser?.subTitle}</h2>
|
||||
<h1>
|
||||
{teaser?.teaser?.teaserTitle}
|
||||
<div class="underline"></div>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="description">
|
||||
<div class="placeholder"></div>
|
||||
<div
|
||||
style=" display: flex;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
gap: 20px;"
|
||||
>
|
||||
<div style="text-align: left;">
|
||||
<p>{@html teaser?.teaser?.teaserDescription}</p>
|
||||
</div>
|
||||
<button
|
||||
on:click="{() => navigate(teaser.path)}"
|
||||
style="
|
||||
font-weight: bold;
|
||||
color: var(--link-font-color);
|
||||
width: fit-content;
|
||||
border-top: 3px solid var(--link-font-color);
|
||||
margin-top: 3rem;
|
||||
">MEHR</button
|
||||
>
|
||||
</div>
|
||||
<div class="placeholder"></div>
|
||||
</div>
|
||||
</div>
|
||||
</swiper-slide>
|
||||
{/if}
|
||||
{/each}
|
||||
</swiper-container>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style lang="less" global>
|
||||
@import "../../assets/css/variables.less";
|
||||
@import "swiper/swiper-bundle.min.css";
|
||||
@import "swiper/modules/effect-fade/effect-fade";
|
||||
@import "swiper/modules/navigation/navigation";
|
||||
@import "swiper/modules/pagination/pagination";
|
||||
@import "../../assets/css/SwiperStylesHP.less";
|
||||
|
||||
.container#HP {
|
||||
padding: 20px 0px 150px 0px;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
swiper-container {
|
||||
max-width: 90vw;
|
||||
width: 1800px;
|
||||
}
|
||||
.inner-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
gap: 20px;
|
||||
@media @tablet {
|
||||
align-items: center;
|
||||
gap: initial;
|
||||
}
|
||||
width: 100%;
|
||||
height: fit-content;
|
||||
|
||||
.titles {
|
||||
padding: 0 5%;
|
||||
font-weight: 500;
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
padding: 10px 0px 0px 0px;
|
||||
@media @tablet {
|
||||
padding: 20px 0px;
|
||||
}
|
||||
margin: 10px 0px 20px 0px;
|
||||
line-height: 1;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 0.9rem !important;
|
||||
@media @tablet {
|
||||
font-size: 1.6rem !important;
|
||||
}
|
||||
line-height: 1;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
.description {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
& > div {
|
||||
flex: 0 0 5%;
|
||||
min-width: 0px;
|
||||
}
|
||||
& > div:nth-child(2) {
|
||||
flex: 0 0 90%;
|
||||
min-width: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@media @tablet {
|
||||
.titles {
|
||||
font-weight: 500;
|
||||
h1 {
|
||||
font-size: 3.5rem;
|
||||
padding: 20px 20px;
|
||||
margin: 20px 0px 40px 0px;
|
||||
font-weight: 500;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
font-weight: 500;
|
||||
}
|
||||
.description {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
& > div {
|
||||
flex: 0 0 25%;
|
||||
min-width: 0px;
|
||||
}
|
||||
& > div:nth-child(2) {
|
||||
flex: 0 0 50%;
|
||||
min-width: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media @desktop {
|
||||
.titles {
|
||||
font-weight: 500;
|
||||
h1 {
|
||||
font-size: 5rem;
|
||||
padding: 20px 0px;
|
||||
margin: 20px 0px 40px 0px;
|
||||
font-weight: 500;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.6rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.description {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
& > div {
|
||||
flex: 0 0 33.33%;
|
||||
min-width: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
let isExpanded = false
|
||||
let currentIndex = 0
|
||||
let interval
|
||||
let interval: NodeJS.Timer
|
||||
let img: HTMLImageElement
|
||||
|
||||
function toggleBanner() {
|
||||
@@ -74,7 +74,7 @@
|
||||
.toggle {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
background-color: @banner-color;
|
||||
background-color: var(--banner-color);
|
||||
transform: translate(-50%, -100%);
|
||||
border-radius: 10px;
|
||||
}
|
||||
@@ -107,7 +107,7 @@
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: @banner-color;
|
||||
background-color: var(--banner-color);
|
||||
cursor: pointer;
|
||||
transition: width 0.5s ease-in-out, height 0.5s ease-in-out;
|
||||
img {
|
||||
@@ -115,8 +115,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.banner.expanded {
|
||||
}
|
||||
.banner-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -124,13 +122,13 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
color: white;
|
||||
color: var(--background-color);
|
||||
.toggle {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.banner-text {
|
||||
color: white;
|
||||
color: var(--background-color);
|
||||
transition: opacity 0.3s ease-in-out;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
|
||||
43
frontend/src/lib/components/pagebuilder/boxlist.svelte
Normal file
43
frontend/src/lib/components/pagebuilder/boxlist.svelte
Normal file
@@ -0,0 +1,43 @@
|
||||
<script lang="ts">
|
||||
export let col: Column
|
||||
import inView from "../../functions/observer"
|
||||
let visible = false
|
||||
import { fade } from "svelte/transition"
|
||||
</script>
|
||||
|
||||
<div class="boxList">
|
||||
{#each col.boxList.boxes as name, i}
|
||||
{#key visible}
|
||||
<div
|
||||
class="box"
|
||||
use:inView="{{ threshold: 0 }}"
|
||||
on:enter="{() => {
|
||||
visible = true
|
||||
}}"
|
||||
in:fade="{{ duration: 500, delay: 100 + 80 * (i + 1) }}"
|
||||
>
|
||||
{name.name}
|
||||
</div>{/key}
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style lang="less">
|
||||
@import "../../assets/css/variables.less";
|
||||
|
||||
.boxList {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
.box {
|
||||
padding: 5px 10px;
|
||||
background-color: var(--opposite-bg-color-80);
|
||||
color: var(--background-color);
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: var(--hover-color);
|
||||
color: var(--opposite-bg-color-80);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,10 +1,12 @@
|
||||
<script lang="ts">
|
||||
import FormLabelNumberBlock from "./formLabelNumberBlock.svelte"
|
||||
import type { Writable } from "svelte/store"
|
||||
|
||||
export let formRow: FormRow
|
||||
export let index: number
|
||||
export let formValues
|
||||
function getSortedFields(column: FormColumn) {
|
||||
|
||||
export let formValues: Writable<FormValues>
|
||||
/* function getSortedFields(column: FormColumn) {
|
||||
const fields = [
|
||||
...(column.text.length ? [{ text: column.text, type: "text", order: column.textfieldOrder ?? 3 }] : []),
|
||||
...(column.showTimes ? [{ type: "times", order: column.timesfieldOrder ?? 3, times: column.times }] : []),
|
||||
@@ -13,11 +15,11 @@
|
||||
: []),
|
||||
]
|
||||
return fields.sort((a, b) => a.order - b.order)
|
||||
}
|
||||
}*/
|
||||
//formRow.columns = formRow.columns.map((e) => getSortedFields(e))
|
||||
function removeInvalid(e) {
|
||||
let element = e.currentTarget
|
||||
element.classList.remove("invalid")
|
||||
function removeInvalid(e: Event) {
|
||||
let element = e.currentTarget as HTMLElement
|
||||
if (element) element.classList.remove("invalid")
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -46,7 +48,7 @@
|
||||
on:change="{removeInvalid}"
|
||||
>
|
||||
<option value="" disabled selected>Bitte Uhrzeit wählen</option>
|
||||
{#each column?.times as time}
|
||||
{#each column?.times || [] as time}
|
||||
<option value="{time?.timeFrom}-{time?.timeTo}">
|
||||
{time?.timeFrom} - {time?.timeTo}
|
||||
</option>
|
||||
@@ -112,7 +114,7 @@
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
{#each column.text as textField, textFieldIndex}
|
||||
{#each column.text || [] as textField, textFieldIndex}
|
||||
{#if textField?.textArea}
|
||||
<label bind:this="{$formValues[`textarea_Nachricht_label`]}">
|
||||
<textarea
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
export let column
|
||||
export let formValues
|
||||
export let rowIndex
|
||||
let blockContainer
|
||||
import type { Writable } from "svelte/store"
|
||||
export let column: FormColumn
|
||||
export let formValues: Writable<FormValues>
|
||||
|
||||
export let rowIndex: number
|
||||
let blockContainer: HTMLDivElement
|
||||
$formValues["blockGroups"] = new Set(column.labelNumber.map((e) => e.group))
|
||||
console.log($formValues["blockGroups"])
|
||||
</script>
|
||||
|
||||
<div class="blockContainer" bind:this="{blockContainer}">
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
<script lang="ts">
|
||||
import FormLabelNumberBlock from "./formLabelNumberBlock.svelte"
|
||||
import type { Writable } from "svelte/store"
|
||||
|
||||
export let formRow: FormRow
|
||||
export let formValues
|
||||
export let index
|
||||
function removeInvalid(e) {
|
||||
let element = e.currentTarget
|
||||
element.classList.remove("invalid")
|
||||
export let formValues: Writable<FormValues>
|
||||
export let index: number
|
||||
function removeInvalid(e: Event) {
|
||||
let element = e.currentTarget as HTMLElement
|
||||
if (element) element.classList.remove("invalid")
|
||||
}
|
||||
|
||||
function getPosition(column, pos, i = 0) {
|
||||
function getPosition(column: FormColumn, pos: number, i = 0) {
|
||||
let position = 0
|
||||
if (pos == 0) return
|
||||
if (column.showLabelNumber) position++
|
||||
@@ -53,7 +54,7 @@
|
||||
on:change="{removeInvalid}"
|
||||
>
|
||||
<option value="" disabled selected>Bitte Uhrzeit wählen</option>
|
||||
{#each column?.times as time}
|
||||
{#each column?.times ?? [] as time}
|
||||
<option value="{time?.timeFrom}-{time?.timeTo}">
|
||||
{time?.timeFrom} - {time?.timeTo}
|
||||
</option>
|
||||
@@ -126,7 +127,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#each column.text as textField, textFieldIndex}
|
||||
{#each column.text ?? [] as textField, textFieldIndex}
|
||||
<div class="column-{columnIndex} position-{getPosition(column, 5 + textFieldIndex, textFieldIndex)}">
|
||||
{#if textField?.textArea}
|
||||
<label bind:this="{$formValues[`textarea_Nachricht_label`]}">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { navigate } from "svelte-routing"
|
||||
import { fly } from "svelte/transition"
|
||||
export let col: Column
|
||||
export let siteId
|
||||
export let siteId: string
|
||||
import { apiBaseURL } from "../../../config"
|
||||
import inView from "../../functions/observer"
|
||||
let visible = false
|
||||
@@ -19,7 +19,7 @@
|
||||
}}"
|
||||
>
|
||||
{#key visible}
|
||||
{#each col.iconBoard as icon, i (i)}
|
||||
{#each col.iconBoard ?? [] as icon, i (i)}
|
||||
<div
|
||||
class="img-container"
|
||||
id="{'img-container' + i}"
|
||||
@@ -67,7 +67,7 @@
|
||||
min-width: 25%;
|
||||
.subText {
|
||||
text-align: center;
|
||||
color: @heading-font-color;
|
||||
color: var(--heading-font-color);
|
||||
}
|
||||
@media @mobile {
|
||||
width: 50%;
|
||||
@@ -77,17 +77,5 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media @tablet {
|
||||
main {
|
||||
margin-top: 300px !important;
|
||||
}
|
||||
.background-container {
|
||||
margin-top: -180px !important;
|
||||
}
|
||||
.title {
|
||||
font-size: 3rem !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
75
frontend/src/lib/components/pagebuilder/iconInfoBoard.svelte
Normal file
75
frontend/src/lib/components/pagebuilder/iconInfoBoard.svelte
Normal file
@@ -0,0 +1,75 @@
|
||||
<script lang="ts">
|
||||
import { apiBaseURL } from "../../../config"
|
||||
import { fly } from "svelte/transition"
|
||||
import inView from "../../functions/observer"
|
||||
let visible = false
|
||||
let node
|
||||
export let col: Column
|
||||
export let pageId: string
|
||||
export let i: number
|
||||
</script>
|
||||
|
||||
{#key visible}
|
||||
<div
|
||||
class="infoBoard"
|
||||
bind:this="{node}"
|
||||
use:inView="{{ threshold: 0 }}"
|
||||
on:enter="{() => {
|
||||
visible = true
|
||||
}}"
|
||||
in:fly="{{ duration: 600, delay: 100 + 100 * (i + 1), x: 300 + i * 200, opacity: 0 }}"
|
||||
>
|
||||
<div class="header">
|
||||
<div class="icon">
|
||||
<svg
|
||||
id="mySvgObject{i}"
|
||||
fill="var(--link-font-color)"
|
||||
data-src="{`${apiBaseURL}content/${pageId}/${col.iconInfoBoard.icon?.src}`}"></svg>
|
||||
</div>
|
||||
<div class="title">
|
||||
{col.iconInfoBoard.title}
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
{@html col.iconInfoBoard.text}
|
||||
</div>
|
||||
</div>
|
||||
{/key}
|
||||
|
||||
<style lang="less">
|
||||
@import "../../assets/css/variables.less";
|
||||
.infoBoard {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 15px;
|
||||
gap: 40px;
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
.icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
font-size: 1.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: var(--link-font-color);
|
||||
div {
|
||||
border-bottom: 1px solid var(--normal-font-color);
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,14 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte"
|
||||
import { register } from "swiper/element/bundle"
|
||||
import Pagebuilder from "./Pagebuilder.svelte"
|
||||
import { apiBaseURL } from "../../../config"
|
||||
|
||||
export let siteId
|
||||
export let siteImages
|
||||
export let siteId: string
|
||||
export let siteImages: ImageSlider[]
|
||||
|
||||
register(false)
|
||||
let swiper
|
||||
let swiper: any
|
||||
|
||||
onMount(async () => {
|
||||
if (swiper !== undefined) {
|
||||
@@ -27,7 +26,7 @@
|
||||
</script>
|
||||
|
||||
{#if siteImages.length > 1}
|
||||
<div class="flex">
|
||||
<div class="flex images">
|
||||
<swiper-container
|
||||
bind:this="{swiper}"
|
||||
slides-per-view="1"
|
||||
@@ -42,7 +41,7 @@
|
||||
class="relative"
|
||||
>
|
||||
{#each siteImages as image, i (i)}
|
||||
<swiper-slide class="relative">
|
||||
<swiper-slide class="relative" id="image">
|
||||
<div class="image-container">
|
||||
<img
|
||||
src="{`${apiBaseURL}content/${siteId}/${image.image?.src}?filter=${
|
||||
@@ -71,11 +70,13 @@
|
||||
@import "swiper/modules/pagination/pagination.less";
|
||||
@import "../../assets/css/variables.less";
|
||||
@import "../../assets/css/swiperStyles.less";
|
||||
|
||||
swiper-container {
|
||||
height: auto;
|
||||
width: 100%;
|
||||
max-width: 100vw;
|
||||
}
|
||||
swiper-slide {
|
||||
swiper-slide#image {
|
||||
width: 100% !important;
|
||||
}
|
||||
.flex {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { navigate } from "svelte-routing"
|
||||
import { fly } from "svelte/transition"
|
||||
|
||||
export let col: Column
|
||||
export let siteId
|
||||
export let i
|
||||
export let siteId: string
|
||||
export let i: number
|
||||
import { apiBaseURL } from "../../../config"
|
||||
import inView from "../../functions/observer"
|
||||
let visible
|
||||
let visible = false
|
||||
let node
|
||||
</script>
|
||||
|
||||
@@ -36,9 +36,11 @@
|
||||
<div class="links">
|
||||
{#if col?.links}
|
||||
{#each col?.links as link}
|
||||
<button on:click="{() => navigate(link?.site)}">
|
||||
<img src="media/arrow-right.svg" alt="arrow" />{link?.name}
|
||||
</button>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4z"
|
||||
fill="var(--link-font-color)"></path>
|
||||
</svg>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
@@ -70,8 +72,7 @@
|
||||
font-weight: 700;
|
||||
padding-bottom: 1.2rem;
|
||||
}
|
||||
.description-container {
|
||||
}
|
||||
|
||||
.links {
|
||||
margin-top: 25px;
|
||||
img {
|
||||
@@ -81,7 +82,7 @@
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: @link-font-color;
|
||||
color: var(--link-font-color);
|
||||
font-weight: 600;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { fly } from "svelte/transition"
|
||||
export let col: Column
|
||||
export let siteId
|
||||
export let siteId: string
|
||||
import { apiBaseURL } from "../../../config"
|
||||
</script>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="inscription" in:fly="{{ duration: 1000, delay: 500, y: 50, opacity: 0 }}">
|
||||
{col.inscription}
|
||||
{col.inscription || ""}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
margin-right: 35px;
|
||||
font-size: 1.7rem;
|
||||
font-weight: 700;
|
||||
color: white;
|
||||
color: var(--heading-font-color);
|
||||
}
|
||||
@media @tablet {
|
||||
.inscription {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
export let row: Row
|
||||
export let rows: Row[]
|
||||
import { apiBaseURL } from "../../../config"
|
||||
import IconBoard from "./iconBoard.svelte"
|
||||
import Image from "./image.svelte"
|
||||
import InfoBoard from "./infoBoard.svelte"
|
||||
@@ -13,24 +12,23 @@
|
||||
import { writable } from "svelte/store"
|
||||
import { validateFields } from "../../functions/validateFields"
|
||||
import { sendForm } from "../../functions/sendForm"
|
||||
import VideoSwitch from "../videoSwitch.svelte"
|
||||
import GoogleMaps from "../googleMaps.svelte"
|
||||
import Video from "./video.svelte"
|
||||
import { navigate } from "svelte-routing"
|
||||
import { onMount } from "svelte"
|
||||
export let siteId
|
||||
export let rowNr
|
||||
import IconInfoBoard from "./iconInfoBoard.svelte"
|
||||
import Boxlist from "./boxlist.svelte"
|
||||
import ProductPreview from "./productPreview.svelte"
|
||||
|
||||
export let siteId: string
|
||||
export let rowNr: number
|
||||
let formSend = false
|
||||
|
||||
let formValues = writable({})
|
||||
function getRowClass(row) {
|
||||
let formValues = writable<FormValues>({})
|
||||
function getRowClass(row: Row) {
|
||||
if (row.maxWidth || row.column.some((col) => col.iconBackgroundImage)) return "max-width"
|
||||
return row.column.some((col) => col.contentType === "mainPicture" || col.contentType == "video")
|
||||
? "max-width"
|
||||
: "small-max-width"
|
||||
return row.column.some((col) => col.contentType === "mainPicture") ? "max-width" : "small-max-width"
|
||||
}
|
||||
|
||||
function submitForm(e) {
|
||||
function submitForm() {
|
||||
const values = Object.entries($formValues).map((entry) => {
|
||||
return [
|
||||
entry[0],
|
||||
@@ -41,114 +39,75 @@
|
||||
})
|
||||
|
||||
const fields = values.filter((entry) => !entry[0].includes("label"))
|
||||
console.log(fields)
|
||||
const validation = validateFields([...fields])
|
||||
if (validation.length) {
|
||||
validation.forEach((error) => {
|
||||
// @ts-ignore
|
||||
if (error[0].includes("block")) {
|
||||
// @ts-ignore
|
||||
error[1]()
|
||||
} else {
|
||||
// @ts-ignore
|
||||
$formValues[error[1]].classList.add("invalid")
|
||||
const label = $formValues[`${error[1]}_label`]
|
||||
const errorElement = document.createElement("div")
|
||||
errorElement.className = "error-message"
|
||||
errorElement.textContent = error[0]
|
||||
errorElement.textContent = error[0] as string
|
||||
label?.appendChild(errorElement)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
const formObj = {}
|
||||
const formObj: any = {}
|
||||
fields.forEach((entry) => {
|
||||
if (Array.isArray(entry[1]) && entry[1].length == 4) {
|
||||
// @ts-ignore
|
||||
if (entry[1][0]) formObj[entry[0]] = entry[1]
|
||||
} else {
|
||||
if (!entry[1][0] && !entry[1][1]) return
|
||||
// @ts-ignore
|
||||
formObj[entry[0]] = entry[1][0]
|
||||
}
|
||||
})
|
||||
console.log(fields, formObj)
|
||||
let form
|
||||
let form: any
|
||||
row.column.forEach((col) => {
|
||||
if (col.contentType == "form") form = col
|
||||
})
|
||||
formObj["formRows"] = form.formRows.map((r) => r.rowName)
|
||||
if (!form) return
|
||||
formObj["formRows"] = form.formRows.map((r: FormRow) => r.rowName)
|
||||
formObj["formTitle"] = form.formEmailTitle
|
||||
formSend = true
|
||||
const hny = document.getElementById("hny")
|
||||
formObj["honey"] = hny.checked
|
||||
const hny = document.getElementById("hny") as HTMLInputElement
|
||||
if (hny) formObj["honey"] = hny.checked
|
||||
sendForm(formObj)
|
||||
}
|
||||
}
|
||||
let videoElement
|
||||
|
||||
onMount(() => {
|
||||
if (videoElement) {
|
||||
var source = document.createElement("source")
|
||||
if (window.innerWidth <= 767) {
|
||||
source.src = "media/wasser_mobile.webm"
|
||||
} else {
|
||||
source.src = "media/wasser_desktop.webm"
|
||||
}
|
||||
videoElement.appendChild(source)
|
||||
videoElement.load()
|
||||
}
|
||||
|
||||
const handleResize = () => {
|
||||
innerWidth = window.innerWidth
|
||||
if (
|
||||
(window.innerWidth >= 768 && innerWidthStore < 768) ||
|
||||
(window.innerWidth < 768 && innerWidthStore >= 768)
|
||||
) {
|
||||
innerWidthStore = window.innerWidth
|
||||
window.location.reload()
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("resize", handleResize)
|
||||
|
||||
// Cleanup function
|
||||
return () => {
|
||||
window.removeEventListener("resize", handleResize)
|
||||
}
|
||||
})
|
||||
|
||||
let innerWidth = window.innerWidth
|
||||
let innerWidthStore = window.innerWidth
|
||||
</script>
|
||||
|
||||
<main class="row" name="{row.title}" class:max-width="{getRowClass(row) === 'max-width'}" id="{`RowNr` + rowNr}">
|
||||
{#if row?.iconBackgroundImage}
|
||||
<div class="virtual-container">
|
||||
<div class="wavebackground-container">
|
||||
{#if row?.iconBackgroundTitle} <div class="title">Highlights des Sees</div>{/if}
|
||||
<video class="video-background" autoplay loop muted playsinline bind:this="{videoElement}"> </video>
|
||||
</div>
|
||||
</div>
|
||||
{#if row.title}
|
||||
<h3 class="row-title" class:no-margin="{rowNr == 0}">{row?.title || ""}</h3>
|
||||
{/if}
|
||||
{#if row.iconBackgroundImage}
|
||||
<div class="wave-placeholder"></div>
|
||||
{/if}
|
||||
{#if row.title || row.iconBackgroundImage}
|
||||
<h3 class="row-title" class:no-margin="{rowNr == 0 || row.iconBackgroundImage}">{row?.title || ""}</h3>
|
||||
{/if}
|
||||
<div class:no-gap="{row.noGap}">
|
||||
{#each row.column as col, i}
|
||||
<div class:no-gap="{row.noGap}" class:wrapAfterTwo="{row.column.length >= 4}">
|
||||
{#each row.column || [] as col, i}
|
||||
{#if col.contentType == "mainPicture"}
|
||||
<MainPicture col="{col}" siteId="{siteId}" />
|
||||
{:else if col.contentType == "text"}
|
||||
<TextContent rows="{rows}" col="{col}" />
|
||||
{:else if col.contentType == "infoBoard"}
|
||||
<InfoBoard siteId="{siteId}" col="{col}" i="{i}" />
|
||||
{:else if col.contentType == "iconInfoBoard"}
|
||||
<IconInfoBoard pageId="{siteId}" col="{col}" i="{i}" />
|
||||
{:else if col.contentType == "boxlist"}
|
||||
<Boxlist col="{col}" />
|
||||
{:else if col.contentType == "iconBoard"}
|
||||
<IconBoard col="{col}" siteId="{siteId}" i="{i}" />
|
||||
<IconBoard col="{col}" siteId="{siteId}" />
|
||||
{:else if col.contentType == "image"}
|
||||
<Image siteImages="{col.imageSlider}" siteId="{siteId}" />
|
||||
{:else if col.contentType == "table"}
|
||||
<Table col="{col}" rows="{rows}" />
|
||||
{:else if col.contentType == "videos"}
|
||||
<VideoSwitch col="{col}" siteId="{siteId}" />
|
||||
{:else if col.contentType == "video"}
|
||||
<Video col="{col}" siteId="{siteId}" />
|
||||
{:else if col.contentType == "productPreview"}
|
||||
<ProductPreview col="{col}" siteId="{siteId}" />
|
||||
{:else if col.contentType == "googleMaps"}{#if col.showGoogleMaps}
|
||||
<GoogleMaps />
|
||||
{/if}
|
||||
@@ -163,10 +122,10 @@
|
||||
class="form-rows"
|
||||
on:submit="{(e) => {
|
||||
e.preventDefault()
|
||||
submitForm(e)
|
||||
submitForm()
|
||||
}}"
|
||||
>
|
||||
{#each col.formRows as formRow, i}
|
||||
{#each col.formRows ?? [] as formRow, i}
|
||||
{#if innerWidth < 768}
|
||||
<MobileForm formRow="{formRow}" formValues="{formValues}" index="{i}" />
|
||||
{:else}
|
||||
@@ -228,67 +187,10 @@
|
||||
margin: 5px 0px;
|
||||
box-shadow: 0 0 25px 10px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.virtual-container {
|
||||
display: flex;
|
||||
padding-top: 90px;
|
||||
max-width: @body-small-maxwidth;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
.wavebackground-container {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100vw;
|
||||
left: 0px;
|
||||
height: 450px;
|
||||
z-index: -1;
|
||||
.video-background {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
-webkit-mask-image: url("../../../../media/welle.svg");
|
||||
mask-image: url("../../../../media/welle.svg");
|
||||
-webkit-mask-size: 30px;
|
||||
mask-size: 30px;
|
||||
-webkit-mask-repeat: repeat-x;
|
||||
mask-repeat: repeat-x;
|
||||
z-index: -1;
|
||||
}
|
||||
@media @mobile {
|
||||
.title {
|
||||
margin-top: 40px;
|
||||
}
|
||||
}
|
||||
@media @tablet {
|
||||
.title {
|
||||
margin-top: 75px;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
font-size: 2rem;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(to top, rgb(255, 255, 255), rgba(255, 255, 255, 0.144));
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.success-message {
|
||||
h1 {
|
||||
color: @banner-color;
|
||||
color: var(--banner-color);
|
||||
font-size: 36px;
|
||||
margin-top: 50px;
|
||||
}
|
||||
@@ -314,15 +216,12 @@
|
||||
border-color: red !important;
|
||||
}
|
||||
|
||||
li {
|
||||
}
|
||||
|
||||
.row-title {
|
||||
font-size: 1.6rem;
|
||||
font-weight: bold;
|
||||
line-height: normal;
|
||||
width: 100%;
|
||||
color: @heading-font-color;
|
||||
color: var(--heading-font-color);
|
||||
@media @mobile {
|
||||
margin: 3.2rem 1.5vw 1.6rem;
|
||||
}
|
||||
@@ -361,6 +260,7 @@
|
||||
|
||||
input[type="number"] {
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
}
|
||||
|
||||
ul {
|
||||
@@ -374,7 +274,7 @@
|
||||
|
||||
li::before {
|
||||
content: ""; /* Add an empty content */
|
||||
background-image: url("../../../../media/arrow-right.svg"); /* Replace this with the path to your SVG file */
|
||||
background-image: url("../../../../media/arrow-right.svg");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
position: absolute;
|
||||
@@ -427,13 +327,13 @@
|
||||
}
|
||||
.submit-request {
|
||||
flex: 1;
|
||||
box-shadow: 0 0 25px 10px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 0 25px 10px var(--opposite-bg-color-5);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
background-color: @heading-font-color;
|
||||
color: white;
|
||||
background-color: var(--heading-font-color);
|
||||
color: var(--background-color);
|
||||
padding: 10px 20px;
|
||||
}
|
||||
}
|
||||
@@ -491,7 +391,7 @@
|
||||
|
||||
p {
|
||||
margin-bottom: 0.5rem;
|
||||
color: #777;
|
||||
color: var(--hover-color);
|
||||
}
|
||||
|
||||
input,
|
||||
@@ -500,10 +400,10 @@
|
||||
.data-protection {
|
||||
padding: 10px 20px;
|
||||
border: 0px solid black;
|
||||
border-bottom: 3px solid @heading-font-color;
|
||||
border-bottom: 3px solid var(--heading-font-color);
|
||||
outline: 0px solid black;
|
||||
|
||||
background-color: white;
|
||||
background-color: var(--background-color);
|
||||
resize: none;
|
||||
}
|
||||
|
||||
@@ -525,12 +425,12 @@
|
||||
select {
|
||||
padding: 10px 20px;
|
||||
border: 0;
|
||||
border-bottom: 3px solid @heading-font-color;
|
||||
border-bottom: 3px solid var(--heading-font-color);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
select:focus {
|
||||
border-bottom-color: @heading-font-color;
|
||||
border-bottom-color: var(--heading-font-color);
|
||||
}
|
||||
|
||||
#time-select {
|
||||
@@ -542,15 +442,13 @@
|
||||
|
||||
option {
|
||||
padding: 10px 20px;
|
||||
background-color: white;
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
}
|
||||
@media @mobile {
|
||||
.date {
|
||||
width: 100vw !important;
|
||||
}
|
||||
.form-cols {
|
||||
}
|
||||
}
|
||||
@media @tablet {
|
||||
.date {
|
||||
@@ -585,6 +483,10 @@
|
||||
& > div {
|
||||
gap: 40px;
|
||||
}
|
||||
& > div.wrapAfterTwo {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
@media @desktop {
|
||||
.no-gap {
|
||||
@@ -593,7 +495,9 @@
|
||||
.row-title {
|
||||
font-size: 2.5rem !important;
|
||||
}
|
||||
& > div {
|
||||
& > div,
|
||||
& > div.wrapAfterTwo {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: start;
|
||||
justify-content: center;
|
||||
|
||||
120
frontend/src/lib/components/pagebuilder/productPreview.svelte
Normal file
120
frontend/src/lib/components/pagebuilder/productPreview.svelte
Normal file
@@ -0,0 +1,120 @@
|
||||
<script lang="ts">
|
||||
export let col: Column
|
||||
export let siteId: string
|
||||
import { register } from "swiper/element/bundle"
|
||||
import { apiBaseURL } from "../../../config"
|
||||
import { onMount } from "svelte"
|
||||
|
||||
register(false)
|
||||
let swiper: any
|
||||
console.log("TST RENDERED")
|
||||
onMount(async () => {
|
||||
if (swiper) {
|
||||
const response = await fetch("/dist/index.css")
|
||||
const cssText = await response.text()
|
||||
|
||||
const params = {
|
||||
injectStyles: [cssText],
|
||||
}
|
||||
if (swiper) {
|
||||
Object.assign(swiper, params)
|
||||
swiper.initialize()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<main id="products">
|
||||
<swiper-container
|
||||
bind:this="{swiper}"
|
||||
slides-per-view="3"
|
||||
loop="{true}"
|
||||
direction="horizontal"
|
||||
effect="coverflow"
|
||||
init="{false}"
|
||||
speed="400"
|
||||
class="relative"
|
||||
grab-cursor="{true}"
|
||||
scrollbar-hide="false"
|
||||
on:focus
|
||||
on:blur
|
||||
autoplay="{{
|
||||
delay: 1000, // 5000ms = 5s
|
||||
pauseOnMouseEnter: true,
|
||||
}}"
|
||||
>
|
||||
{#each col.productPreview as product}
|
||||
<swiper-slide class="relative" id="product">
|
||||
<div class="product">
|
||||
<div class="img-container">
|
||||
<img
|
||||
src="{`${apiBaseURL}content/${siteId}/${product.image?.src}?filter=${
|
||||
window.innerWidth > 500 ? 'xl' : 'm'
|
||||
}`}"
|
||||
alt="img"
|
||||
/>
|
||||
<div class="price-container">
|
||||
{product?.price} €
|
||||
</div>
|
||||
</div>
|
||||
<div class="title-container">
|
||||
{@html product?.title}
|
||||
</div>
|
||||
|
||||
<div class="description-container">
|
||||
{@html product?.text}
|
||||
</div>
|
||||
</div>
|
||||
</swiper-slide>
|
||||
{/each}
|
||||
</swiper-container>
|
||||
</main>
|
||||
|
||||
<style lang="less" global>
|
||||
@import "../../assets/css/variables.less";
|
||||
@import "swiper/swiper-bundle.min.css";
|
||||
@import "swiper/modules/effect-fade/effect-fade";
|
||||
@import "swiper/modules/navigation/navigation";
|
||||
@import "swiper/modules/pagination/pagination";
|
||||
@import "../../assets/css/productSwiper.less";
|
||||
#products {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
max-width: @body-small-maxwidth;
|
||||
|
||||
.product {
|
||||
margin: 0px 35px 40px 35px;
|
||||
.img-container {
|
||||
flex: 1;
|
||||
height: 270px;
|
||||
background-color: var(--background-color);
|
||||
@media @tablet {
|
||||
height: 65vw;
|
||||
}
|
||||
@media @desktop {
|
||||
height: 270px;
|
||||
}
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
padding: 1rem 0px;
|
||||
}
|
||||
position: relative;
|
||||
.price-container {
|
||||
position: absolute;
|
||||
bottom: 1rem;
|
||||
right: 0px;
|
||||
font-weight: bold;
|
||||
background-color: var(--background-color);
|
||||
padding: 9px;
|
||||
}
|
||||
}
|
||||
.title-container {
|
||||
font-weight: 700;
|
||||
padding-bottom: 1.2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
66
frontend/src/lib/components/pagebuilder/scrollDown.svelte
Normal file
66
frontend/src/lib/components/pagebuilder/scrollDown.svelte
Normal file
@@ -0,0 +1,66 @@
|
||||
<script>
|
||||
import { onMount, onDestroy } from "svelte"
|
||||
// import { rerender } from "../../store"
|
||||
|
||||
let showButton = true
|
||||
|
||||
const checkScroll = () => {
|
||||
// Change the visibility of the button based on the scroll position
|
||||
showButton = window.pageYOffset < 100
|
||||
}
|
||||
|
||||
const jumpDown = () => {
|
||||
// Jump down by 100vh
|
||||
window.scrollTo({ top: window.innerHeight, behavior: "smooth" })
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
// Attach scroll event listener when component is mounted
|
||||
window.addEventListener("scroll", checkScroll)
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
// Remove scroll event listener when component is destroyed
|
||||
window.removeEventListener("scroll", checkScroll)
|
||||
})
|
||||
let force = true
|
||||
setInterval(() => {
|
||||
if (location.pathname != "/") {
|
||||
force = false
|
||||
} else force = true
|
||||
}, 1000)
|
||||
$: {
|
||||
/* if ($rerender) {
|
||||
if (location.pathname != "/") {
|
||||
force = false
|
||||
} else force = true
|
||||
}*/
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if showButton && force}
|
||||
<button on:click="{jumpDown}" class="jump-down"
|
||||
><span> SCROLL </span>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="m22.723 5.473 1.054 1.054L12 18.305.223 6.527l1.054-1.054L12 16.195 22.723 5.473z"
|
||||
fill="var(--link-font-color)"></path>
|
||||
</svg>
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.jump-down {
|
||||
/* Place your styles here */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
color: var(--link-font-color);
|
||||
z-index: 100;
|
||||
gap: 5px;
|
||||
bottom: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
</style>
|
||||
54
frontend/src/lib/components/pagebuilder/scrollTop.svelte
Normal file
54
frontend/src/lib/components/pagebuilder/scrollTop.svelte
Normal file
@@ -0,0 +1,54 @@
|
||||
<script>
|
||||
import { onMount, onDestroy } from "svelte"
|
||||
|
||||
let showButton = false
|
||||
|
||||
const checkScroll = () => {
|
||||
// Change the visibility of the button based on the scroll position
|
||||
showButton = window.pageYOffset > 200
|
||||
}
|
||||
|
||||
const scrollToTop = () => {
|
||||
// Scroll smoothly to the top
|
||||
window.scrollTo({ top: 0, behavior: "smooth" })
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
// Attach scroll event listener when component is mounted
|
||||
window.addEventListener("scroll", checkScroll)
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
// Remove scroll event listener when component is destroyed
|
||||
window.removeEventListener("scroll", checkScroll)
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if showButton}
|
||||
<button on:click="{scrollToTop}" class="arrow-up">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z" fill="var(--background-color)"
|
||||
></path>
|
||||
</svg></button
|
||||
>
|
||||
{/if}
|
||||
|
||||
<style lang="less">
|
||||
@import "../../assets/css/variables.less";
|
||||
.arrow-up {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
height: 2rem;
|
||||
width: 2rem;
|
||||
border-radius: 50%;
|
||||
z-index: 1000;
|
||||
background-color: var(--link-font-color);
|
||||
svg {
|
||||
transform-origin: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -2,7 +2,7 @@
|
||||
import inView from "../../functions/observer"
|
||||
import { fly } from "svelte/transition"
|
||||
export let rows: Row[]
|
||||
function scrollToRow(name) {
|
||||
function scrollToRow(name: string) {
|
||||
const element = document.getElementsByName(name)[0]
|
||||
if (element) {
|
||||
element.scrollIntoView({ behavior: "smooth" })
|
||||
@@ -27,7 +27,10 @@
|
||||
class="siteRef"
|
||||
on:click="{() => scrollToRow(row.title)}"
|
||||
in:fly="{{ duration: 1000, delay: 40 * i, opacity: 0, y: 150 }}"
|
||||
><img src="media/arrow-bottom-right.svg" alt="arrow" />{row?.title}</button
|
||||
><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5 6.41 6.41 5 17 15.59V9h2v10H9v-2h6.59L5 6.41z" fill="var(--link-font-color)"></path>
|
||||
</svg>
|
||||
{row?.title}</button
|
||||
>
|
||||
{/if}
|
||||
{/each}
|
||||
@@ -41,11 +44,11 @@
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
img {
|
||||
svg {
|
||||
transform: scale(1.4);
|
||||
margin: 0.5rem 0.9rem 0.5rem 0rem;
|
||||
}
|
||||
color: @link-font-color;
|
||||
color: var(--link-font-color);
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
>
|
||||
<h3>{col?.tableFieldHeading ?? ""}</h3>
|
||||
{#key visible}
|
||||
{#each col?.table as table, i (table?.title)}
|
||||
{#each col?.table ?? [] as table, i (table?.title)}
|
||||
<div class="table" in:fly="{{ duration: 1000, delay: i * 150, y: 130, opacity: 0 }}">
|
||||
<div class="tableTitle">{table?.title ?? ""}</div>
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
margin: 0rem 0vw 1.6rem 0vw;
|
||||
color: @heading-font-color;
|
||||
color: var(--heading-font-color);
|
||||
}
|
||||
|
||||
h5 {
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
import { navigate } from "svelte-routing"
|
||||
export let site: Site
|
||||
import Image from "./image.svelte"
|
||||
export let index
|
||||
export let index: number
|
||||
</script>
|
||||
|
||||
<main class="teaser">
|
||||
{#if index % 2 == 0 || window.innerWidth < 1023}
|
||||
<Image siteId="{site?.id}" siteImages="{site?.teaserImages}" />
|
||||
<Image siteId="{site?.id}" siteImages="{site?.teaserImages || []}" />
|
||||
{/if}
|
||||
<div class="content">
|
||||
<h3>{site?.teaserTitle}</h3>
|
||||
@@ -15,7 +15,7 @@
|
||||
<button on:click="{() => navigate(site.path)}">MEHR</button>
|
||||
</div>
|
||||
{#if index % 2 == 1 && window.innerWidth > 1023}
|
||||
<Image siteId="{site?.id}" siteImages="{site?.teaserImages}" />
|
||||
<Image siteId="{site?.id}" siteImages="{site?.teaserImages || []}" />
|
||||
{/if}
|
||||
</main>
|
||||
|
||||
@@ -41,13 +41,13 @@
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
margin: 0rem 0 1.6rem 0;
|
||||
color: @heading-font-color;
|
||||
color: var(--heading-font-color);
|
||||
}
|
||||
button {
|
||||
font-weight: bold;
|
||||
color: @link-font-color;
|
||||
color: var(--link-font-color);
|
||||
width: fit-content;
|
||||
border-top: 3px solid @link-font-color;
|
||||
border-top: 3px solid var(--link-font-color);
|
||||
margin-top: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</script>
|
||||
|
||||
<div class="text-container">
|
||||
<h3 class:noMargin={!col.textFieldHeading}>{col.textFieldHeading ?? ""}</h3>
|
||||
<h3 class:noMargin="{!col.textFieldHeading}">{col.textFieldHeading ?? ""}</h3>
|
||||
{#if col?.textContent}
|
||||
<div>
|
||||
{@html col?.textContent}
|
||||
@@ -15,11 +15,12 @@
|
||||
{#if col.siteReference}
|
||||
<SiteRefs rows="{rows}" />
|
||||
{/if}
|
||||
<li style="display: none;"></li>
|
||||
</div>
|
||||
|
||||
<style lang="less">
|
||||
@import "../../assets/css/variables.less";
|
||||
.noMargin{
|
||||
.noMargin {
|
||||
margin: 0px !important;
|
||||
}
|
||||
.text-container {
|
||||
@@ -30,7 +31,7 @@
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
margin: 0rem 0vw 1.6rem 0vw;
|
||||
color: @heading-font-color;
|
||||
color: var(--heading-font-color);
|
||||
}
|
||||
}
|
||||
@media @mobile {
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { apiBaseURL } from "../../../config"
|
||||
import { navigate } from "svelte-routing"
|
||||
import { fly } from "svelte/transition"
|
||||
let container
|
||||
let videoElement
|
||||
let videoText
|
||||
let videoWrapper
|
||||
let cooldown = false
|
||||
export let col
|
||||
export let siteId
|
||||
</script>
|
||||
|
||||
<div id="wrapper" class="video-container" bind:this="{container}">
|
||||
<div class="video-wrapper video-wrapper-big" bind:this="{videoWrapper}">
|
||||
<div class="text shown" bind:this="{videoText}">
|
||||
<h2 in:fly="{{ duration: 1000, delay: 500, y: 50, opacity: 0 }}">{col.titleVideo}</h2>
|
||||
<p in:fly="{{ duration: 1000, delay: 500, y: 50, opacity: 0 }}">
|
||||
{col.descriptionVideo}
|
||||
</p>
|
||||
</div>
|
||||
<video
|
||||
autoplay
|
||||
class="video"
|
||||
playsinline
|
||||
src="{`${apiBaseURL}content/${siteId}/${col.video?.src}`}"
|
||||
loop
|
||||
alt="video1"
|
||||
muted
|
||||
bind:this="{videoElement}"><track kind="captions" /></video
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="less">
|
||||
@import "../../assets/css/variables.less";
|
||||
|
||||
#wrapper {
|
||||
width: 100%;
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.video-wrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
max-height: min(700px, 55vh);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
z-index: 10;
|
||||
}
|
||||
@media @mobile {
|
||||
.hidden {
|
||||
p,
|
||||
button {
|
||||
visibility: hidden !important;
|
||||
opacity: 0;
|
||||
height: 0px;
|
||||
margin-top: 0px !important;
|
||||
transition: opacity 0s;
|
||||
}
|
||||
h2 {
|
||||
margin-bottom: 0px !important;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
}
|
||||
|
||||
.shown {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
@media @desktop {
|
||||
.hidden {
|
||||
h2 {
|
||||
visibility: hidden;
|
||||
transition: opacity 0s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
position: absolute;
|
||||
z-index: 20;
|
||||
max-width: 85%;
|
||||
color: rgb(255, 255, 255);
|
||||
animation-delay: 500ms;
|
||||
bottom: 35px;
|
||||
left: 35px;
|
||||
|
||||
@media @mobile {
|
||||
h2 {
|
||||
font-size: 2.8rem;
|
||||
font-weight: bold;
|
||||
line-height: normal;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
p {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
button {
|
||||
border-top: 3px solid white;
|
||||
font-size: 1.4rem;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
@media @desktop {
|
||||
max-width: 70%;
|
||||
h2 {
|
||||
font-size: 2.7rem;
|
||||
}
|
||||
p {
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.video {
|
||||
width: 100%;
|
||||
min-height: max(35vh, 400px);
|
||||
height: 100% !important;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
@media (max-width: 1023px) {
|
||||
.video-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.text {
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
video {
|
||||
height: 100% !important;
|
||||
min-height: max(45vh, 60vw) !important;
|
||||
width: auto !important;
|
||||
min-width: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.video-wrapper-small,
|
||||
.video-wrapper-big {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,315 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte"
|
||||
import { apiBaseURL } from "../../config"
|
||||
import { navigate } from "svelte-routing"
|
||||
import { temperature } from "../stores"
|
||||
export let siteId
|
||||
let container
|
||||
let videoElements = []
|
||||
let videoTexts = []
|
||||
let videoWrappers = []
|
||||
let cooldown = false
|
||||
export let col
|
||||
|
||||
onMount(() => {
|
||||
container.style.height = videoElements[0].offsetHeight + "px"
|
||||
Array.from(videoElements).forEach((e) => {
|
||||
e.style.height = "100%"
|
||||
})
|
||||
videoElements[0].play()
|
||||
videoElements[1].play()
|
||||
setTimeout(() => {
|
||||
videoElements[1].pause()
|
||||
}, 0)
|
||||
videoWrappers.forEach((videoWrapper) => {
|
||||
const video = videoWrapper.querySelector(".video")
|
||||
let eventFunc = (e) => {
|
||||
if (cooldown) return
|
||||
let selected = e.currentTarget
|
||||
cooldown = true
|
||||
setTimeout(() => {
|
||||
cooldown = false
|
||||
}, 502)
|
||||
let text = selected.querySelector(".text")
|
||||
videoWrappers.forEach((vw) => {
|
||||
if (selected == vw) {
|
||||
vw.classList.add("video-wrapper-big")
|
||||
vw.classList.remove("video-wrapper-small")
|
||||
} else {
|
||||
vw.classList.add("video-wrapper-small")
|
||||
vw.classList.remove("video-wrapper-big")
|
||||
}
|
||||
vw.querySelector(".video").pause()
|
||||
})
|
||||
videoTexts.forEach((vt) => {
|
||||
if (text == vt) {
|
||||
setTimeout(() => {
|
||||
vt.classList.add("shown")
|
||||
vt.classList.remove("hidden")
|
||||
}, 500)
|
||||
} else {
|
||||
vt.classList.add("hidden")
|
||||
vt.classList.remove("shown")
|
||||
}
|
||||
})
|
||||
video.play()
|
||||
}
|
||||
|
||||
videoWrapper.addEventListener("mousemove", (e) => eventFunc(e))
|
||||
videoWrapper.addEventListener("click", (e) => eventFunc(e))
|
||||
})
|
||||
})
|
||||
let innerWidth = window.innerWidth
|
||||
</script>
|
||||
|
||||
<div class="video-top-lvl-container">
|
||||
<div id="wrapper" class="video-container" bind:this="{container}">
|
||||
<div class="video-wrapper video-wrapper-big" bind:this="{videoWrappers[0]}">
|
||||
<div class="text shown" bind:this="{videoTexts[0]}">
|
||||
<h2>{col.videoSwitch[0]?.title}</h2>
|
||||
<p>
|
||||
{col.videoSwitch[0]?.description}
|
||||
</p>
|
||||
<button
|
||||
class="link"
|
||||
on:click="{() => {
|
||||
navigate(col.videoSwitch[0]?.link)
|
||||
}}">MEHR</button
|
||||
>
|
||||
</div>
|
||||
<video
|
||||
class="video"
|
||||
playsinline
|
||||
src="{`${apiBaseURL}content/${siteId}/${col.videoSwitch[0].video?.src}`}"
|
||||
loop
|
||||
alt="video1"
|
||||
muted
|
||||
bind:this="{videoElements[0]}"><track kind="captions" /></video
|
||||
>
|
||||
</div>
|
||||
<div class="video-wrapper video-wrapper-small" bind:this="{videoWrappers[1]}">
|
||||
<div class="text hidden" bind:this="{videoTexts[1]}">
|
||||
<h2>{col.videoSwitch[1]?.title}</h2>
|
||||
<p>
|
||||
{col.videoSwitch[1]?.description}
|
||||
</p>
|
||||
<button
|
||||
class="link"
|
||||
on:click="{() => {
|
||||
navigate(col.videoSwitch[1]?.link)
|
||||
}}">MEHR</button
|
||||
>
|
||||
</div>
|
||||
<video
|
||||
class="video"
|
||||
loop
|
||||
playsinline
|
||||
src="{`${apiBaseURL}content/${siteId}/${col.videoSwitch[1].video?.src}`}"
|
||||
muted
|
||||
bind:this="{videoElements[1]}"><track kind="captions" /></video
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="icons">
|
||||
<button class="thermo">
|
||||
<img src="/media/thermometer.svg" alt="temp" />
|
||||
{Number($temperature).toFixed(1) || "-"} °C
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="less">
|
||||
@import "../assets/css/variables.less";
|
||||
|
||||
.video-top-lvl-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 40px;
|
||||
}
|
||||
|
||||
.video-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
@media @mobile {
|
||||
gap: 20px;
|
||||
}
|
||||
@media @tablet {
|
||||
gap: 40px;
|
||||
}
|
||||
}
|
||||
.icons {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
@media @mobile {
|
||||
justify-content: end;
|
||||
}
|
||||
@media @tablet {
|
||||
justify-content: end;
|
||||
button {
|
||||
margin: 28px 2rem !important;
|
||||
}
|
||||
}
|
||||
margin-bottom: 60px;
|
||||
|
||||
img {
|
||||
transform: scale(1.5);
|
||||
margin: 0px 0.4rem;
|
||||
}
|
||||
button {
|
||||
display: flex;
|
||||
font-weight: bold;
|
||||
justify-content: center;
|
||||
font-size: 1rem;
|
||||
position: relative;
|
||||
margin: 0 1rem;
|
||||
}
|
||||
button::before {
|
||||
font-weight: 400;
|
||||
position: absolute;
|
||||
transform: translateY(-150%);
|
||||
}
|
||||
.camera::before {
|
||||
content: "Webcam";
|
||||
}
|
||||
.thermo::before {
|
||||
content: "Lufttemperatur";
|
||||
}
|
||||
.waves::before {
|
||||
content: "Wassertemperatur";
|
||||
}
|
||||
}
|
||||
|
||||
.video-wrapper {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
z-index: 10;
|
||||
}
|
||||
@media @mobile {
|
||||
.hidden {
|
||||
p,
|
||||
button {
|
||||
visibility: hidden !important;
|
||||
opacity: 0;
|
||||
height: 0px;
|
||||
margin-top: 0px !important;
|
||||
transition: opacity 0s;
|
||||
}
|
||||
h2 {
|
||||
margin-bottom: 0px !important;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
}
|
||||
|
||||
.shown {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
@media @desktop {
|
||||
.hidden {
|
||||
h2 {
|
||||
visibility: hidden;
|
||||
transition: opacity 0s;
|
||||
}
|
||||
}
|
||||
}
|
||||
.text {
|
||||
position: absolute;
|
||||
z-index: 20;
|
||||
max-width: 85%;
|
||||
color: rgb(255, 255, 255);
|
||||
animation-delay: 500ms;
|
||||
bottom: 35px;
|
||||
left: 35px;
|
||||
|
||||
@media @mobile {
|
||||
h2 {
|
||||
font-size: 2.8rem;
|
||||
font-weight: bold;
|
||||
line-height: normal;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
p {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
button {
|
||||
border-top: 3px solid white;
|
||||
font-weight: bold;
|
||||
padding-top: 2px;
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
@media @desktop {
|
||||
max-width: 70%;
|
||||
h2 {
|
||||
font-size: 2.7rem;
|
||||
}
|
||||
p {
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.video {
|
||||
width: 100%;
|
||||
min-height: max(35vh, 400px);
|
||||
height: auto;
|
||||
object-fit: cover;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.video-wrapper-big {
|
||||
flex: 3;
|
||||
}
|
||||
|
||||
.video-wrapper-small {
|
||||
flex: 1 !important;
|
||||
}
|
||||
|
||||
.video-wrapper-big:hover,
|
||||
.video-wrapper-small:hover {
|
||||
flex: 3;
|
||||
}
|
||||
|
||||
@media (max-width: 1023px) {
|
||||
.video-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.text {
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
video {
|
||||
height: 100% !important;
|
||||
min-height: 75vh !important;
|
||||
width: auto !important;
|
||||
min-width: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.video-wrapper-small,
|
||||
.video-wrapper-big {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user