most of it
@@ -7,10 +7,9 @@ DirectoryIndex spa.html
|
||||
RewriteEngine On
|
||||
RewriteBase /
|
||||
|
||||
RewriteRule ^/?api/(.*)$ http://tibi-server:8080/api/v1/_/wasserski_erfurt/$1 [P,QSA,L]
|
||||
RewriteRule ^/?api/(.*)$ http://tibi-server:8080/api/v1/_/allkids_erfurt/$1 [P,QSA,L]
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
#RewriteRule ^/?(.*)$ http://tibi-server:8080/api/v1/_/wasserski_erfurt/ssr?token=owshwerNwoa&url=/$1 [P,QSA,L]
|
||||
RewriteRule (.*) /spa.html [QSA,L]
|
||||
</ifModule>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<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="#4b678b"/>
|
||||
<path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4z" fill="#9fb3c7"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 183 B After Width: | Height: | Size: 202 B |
@@ -1,3 +1,3 @@
|
||||
<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="#4b678b"/>
|
||||
<path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4z" fill="#672129"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 202 B After Width: | Height: | Size: 202 B |
@@ -1,3 +0,0 @@
|
||||
<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="#fff"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 199 B |
@@ -1,3 +0,0 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7 10h5v5H7m12 4H5V8h14m0-5h-1V1h-2v2H8V1H6v2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z" fill="#000"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 244 B |
@@ -1,3 +0,0 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18.5 16.8c-.7 0-1.2-.6-1.2-1.2 0-.7.6-1.2 1.2-1.2s1.2.6 1.2 1.2c.1.6-.5 1.2-1.2 1.2zm0-4.8c-1.9 0-3.5 1.6-3.5 3.5 0 2.6 3.5 6.5 3.5 6.5s3.5-3.9 3.5-6.5c0-1.9-1.6-3.5-3.5-3.5zM9 2 7 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h10.5c-.6-.9-1.1-1.9-1.4-3.1-.3.1-.7.1-1.1.1-2.8 0-5-2.2-5-5s2.2-5 5-5c2.1 0 4 1.3 4.7 3.3.6-.2 1.2-.3 1.8-.3 1.3 0 2.5.5 3.5 1.3V6c0-1.1-.9-2-2-2h-3l-2-2H9zm2.9 7C10.3 9 9 10.4 9 12c0 1.7 1.3 3 3 3 .4 0 .7-.1 1-.2.2-1.4.9-2.6 1.9-3.5-.3-1.3-1.5-2.3-3-2.3.1 0 .1 0 0 0z" fill="#4b678b"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 622 B |
@@ -1,3 +0,0 @@
|
||||
<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="#4b678b"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 413 B |
17
frontend/media/logo.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="rgba(207,165,149,0)"/>
|
||||
<g transform="matrix(4.995999813079834, 0, 0, 4.995999813079834, 501.0972900390626, 499.6000061035156)" id="495873">
|
||||
<filter id="SVGID_40" y="-20%" height="140%" x="-20%" width="140%">
|
||||
<feGaussianBlur in="SourceAlpha" stdDeviation="0"/>
|
||||
<feOffset dx="0" dy="0" result="oBlur"/>
|
||||
<feFlood flood-color="rgb(0,0,0)" flood-opacity="0"/>
|
||||
<feComposite in2="oBlur" operator="in"/>
|
||||
<feMerge>
|
||||
<feMergeNode/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
<path style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; is-custom-font: none; font-file-url: none; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;filter: url(#SVGID_40);" vector-effect="non-scaling-stroke" d="M 112.787 80.919 L 134.765 125.275 L 114.985 125.275 L 100.599 95.904 L 77.822 126.074 L 77.822 200 L 59.84 200 L 59.84 110.09 L 77.822 79.52 L 77.822 104.695 L 147.952 0 L 168.731 0 L 131.768 54.545 L 112.787 80.919 Z M 77.822 0 L 77.822 38.162 L 59.84 68.931 L 59.84 0 L 77.822 0 Z M 120.38 38.561 L 109.79 54.346 L 100.2 38.162 L 47.652 127.073 L 58.042 127.073 L 58.042 141.059 L 39.261 141.059 L 19.481 174.625 L -0.3 174.625 L 87.413 25.774 L 99.732 4.555 L 112.587 25.774 L 120.38 38.561 Z M 200.3 174.625 L 180.719 174.625 L 160.939 141.059 L 79.82 141.059 L 79.82 127.073 L 152.547 127.073 L 120.779 73.127 L 131.568 57.942 L 200.3 174.625 Z M 170.929 200 L 150.35 200 L 123.576 142.857 L 143.556 142.857 L 170.929 200 Z" stroke-linecap="round" transform=" translate(-100, -100)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -1,3 +0,0 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15 13V5a3 3 0 0 0-6 0v8a5 5 0 1 0 6 0zm-3-9a1 1 0 0 1 1 1v3h-2V5a1 1 0 0 1 1-1z" fill="#4b678b"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 215 B |
@@ -1,3 +0,0 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20 12h2v2h-2c-1.38 0-2.74-.35-4-1-2.5 1.3-5.5 1.3-8 0-1.26.65-2.63 1-4 1H2v-2h2c1.39 0 2.78-.47 4-1.33 2.44 1.71 5.56 1.71 8 0 1.22.86 2.61 1.33 4 1.33zm0-6h2v2h-2c-1.38 0-2.74-.35-4-1-2.5 1.3-5.5 1.3-8 0-1.26.65-2.63 1-4 1H2V6h2c1.39 0 2.78-.47 4-1.33 2.44 1.71 5.56 1.71 8 0C17.22 5.53 18.61 6 20 6zm0 12h2v2h-2c-1.38 0-2.74-.35-4-1-2.5 1.3-5.5 1.3-8 0-1.26.65-2.63 1-4 1H2v-2h2c1.39 0 2.78-.47 4-1.33 2.44 1.71 5.56 1.71 8 0 1.22.86 2.61 1.33 4 1.33z" fill="#4b678b"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 589 B |
@@ -1 +0,0 @@
|
||||
<svg id="e75HGxgJUV31" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 29.9 450" shape-rendering="geometricPrecision" text-rendering="geometricPrecision"><path d="M29.925258,450.800658c2.416953,17.862542,0-224.999303.074742-438.639846-.024742.014818-.049485.030164-.074742.044982-.723711.42918-1.540722.775806-2.48866,1.001244-2.735567.650915-5.713402.150293-7.978351-1.338873-2.219588-1.46006-3.644845-4.042551-3.391237-6.139237.180412-1.504513,1.157732-2.672984,2.826289-3.379994.229897-.098431.272165-.275713.276804-.372556.009278-.18522-.097938-.355093-.285052-.450348-1.480412-.755167-4.034021-1.34099-7.715979.218559-2.266495.956263-4.109794,3.095285-6.057732,5.357611C3.555155,8.907826,1.946907,10.775369,0,12.161342l.1,438.639319l29.825258-.000003Z" transform="matrix(1 0 0 1.000003-.1-.802011)"/></svg>
|
||||
|
Before Width: | Height: | Size: 856 B |
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Wasserski Erfurt</title>
|
||||
<title>AllKids Erfurt</title>
|
||||
<base href="/" />
|
||||
<link rel="stylesheet" href="/dist/index.css?t=__TIMESTAMP__" />
|
||||
<script
|
||||
@@ -12,6 +12,7 @@
|
||||
src="https://unpkg.com/external-svg-loader@latest/svg-loader.min.js"
|
||||
async
|
||||
></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/less.js/4.1.1/less.min.js"></script>
|
||||
|
||||
<!--HEAD-->
|
||||
<!--PRELOAD-->
|
||||
@@ -33,4 +34,4 @@
|
||||
|
||||
<!--SSR.ERROR-->
|
||||
<!--SSR.COMMENT-->
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { location, navigation, sites, temperature, banner, serviceNavigation} from "./lib/stores"
|
||||
import { location, navigation, sites, temperature, banner, serviceNavigation } from "./lib/stores"
|
||||
import Header from "./lib/components/header/Header.svelte"
|
||||
import Footer from "./lib/components/Footer.svelte"
|
||||
import { Route, Router } from "svelte-routing"
|
||||
@@ -8,12 +8,13 @@
|
||||
import { loadBanner } from "./lib/functions/loadBanner"
|
||||
import { loadSites } from "./lib/functions/loadSites"
|
||||
import { loadTemperature } from "./lib/functions/loadTemperature"
|
||||
import Site from "./routes/Site.svelte"
|
||||
import Banner from "./lib/components/pagebuilder/banner.svelte"
|
||||
import SiteComp from "./routes/Site.svelte"
|
||||
import NotFound from "./routes/NotFound.svelte"
|
||||
import insta from "../media/instagram.svg"
|
||||
import BannerComp from "./lib/components/pagebuilder/banner.svelte"
|
||||
import ScrollTop from "./lib/components/pagebuilder/scrollTop.svelte"
|
||||
import ScrollDown from "./lib/components/pagebuilder/scrollDown.svelte"
|
||||
export let url = ""
|
||||
|
||||
|
||||
if (url) {
|
||||
// ssr
|
||||
let l = url.split("?")
|
||||
@@ -28,38 +29,37 @@
|
||||
}
|
||||
|
||||
async function getNavigation() {
|
||||
let nav: Navigation = await loadNavigation()
|
||||
let nav: Navigation[] = await loadNavigation()
|
||||
$navigation = nav[0]
|
||||
$serviceNavigation = nav[1]
|
||||
}
|
||||
async function getBanner() {
|
||||
let banner: Banner[] = await loadBanner()
|
||||
console.log(banner)
|
||||
$banner = banner
|
||||
let bannerRes: Banner[] = await loadBanner()
|
||||
$banner = bannerRes
|
||||
}
|
||||
async function getSites() {
|
||||
let sitesArray: Site[] = await loadSites()
|
||||
let sites: Sites = {}
|
||||
|
||||
let sitesRes: Sites = {}
|
||||
sitesArray.forEach((e) => {
|
||||
sites[e.id] = e
|
||||
sitesRes[e.id] = e
|
||||
})
|
||||
$sites = sites
|
||||
$sites = sitesRes
|
||||
console.log("ALARM OVER", $sites)
|
||||
}
|
||||
|
||||
async function getTemperature() {
|
||||
let temperature = await loadTemperature()
|
||||
console.log(temperature)
|
||||
$temperature = temperature.temperature.toFixed(2)
|
||||
}
|
||||
getNavigation()
|
||||
getSites()
|
||||
getBanner()
|
||||
getTemperature()
|
||||
|
||||
$: {
|
||||
if (Object.values($sites).length == 0) {
|
||||
getSites()
|
||||
}
|
||||
}
|
||||
|
||||
// scroll to top on new site
|
||||
location.subscribe((l) => {
|
||||
if (l.push) scrollToTop()
|
||||
if (l.push) scrollTo({ top: 0 })
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -71,7 +71,8 @@
|
||||
<HomePage />
|
||||
</Route>
|
||||
<Route path="/*path" let:params>
|
||||
<Site path="{params.path}" />
|
||||
{#key $sites}
|
||||
<SiteComp path="{params.path}" />{/key}
|
||||
</Route>
|
||||
<Route>
|
||||
<NotFound />
|
||||
@@ -79,21 +80,25 @@
|
||||
</Router>
|
||||
<Footer />
|
||||
</div>
|
||||
<button class="arrow-up" on:click="{() => window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })}"
|
||||
><img src="media/arrow-up.svg" alt="arrow" /></button
|
||||
>
|
||||
<Banner />
|
||||
<button class="arrow-up" on:click="{() => window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })}"> </button>
|
||||
|
||||
<ScrollTop />
|
||||
<ScrollDown />
|
||||
|
||||
<BannerComp />
|
||||
<div class="socialMedia">
|
||||
<a target="_blank" href="https://www.instagram.com/wasserski_erfurt/"
|
||||
><img src="media/instagram.svg" alt="insta" /></a
|
||||
>
|
||||
<a target="_blank" href="https://www.facebook.com/wasserskierfurt/"><img src="media/facebook.svg" alt="fb" /></a
|
||||
>
|
||||
<a target="_blank" 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="var(--link-font-color)"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<style lang="less">
|
||||
@import "./lib/assets/css/main.less";
|
||||
@import "./lib/assets/css/variables.less";
|
||||
@import "./lib/assets/css/fonts.less";
|
||||
@font-face {
|
||||
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||
@@ -107,6 +112,14 @@
|
||||
url("./lib/assets/fonts/roboto-condensed-v25-latin-regular.ttf") format("truetype"),
|
||||
url("./lib/assets/fonts/roboto-condensed-v25-latin-regular.svg") format("svg");
|
||||
}
|
||||
/* orbitron-regular - latin */
|
||||
@font-face {
|
||||
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||
font-family: "Orbitron";
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
src: url("./lib/assets/fonts/orbitron-v31-latin-900.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||
}
|
||||
|
||||
.socialMedia {
|
||||
display: none;
|
||||
@@ -133,31 +146,18 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
color: @normal-font-color;
|
||||
.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: @link-font-color;
|
||||
img {
|
||||
transform-origin: center;
|
||||
}
|
||||
}
|
||||
color: var(--normal-font-color);
|
||||
|
||||
.content-container {
|
||||
display: flex;
|
||||
z-index: 10;
|
||||
min-height: 100vh;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
|
||||
overflow: hidden;
|
||||
justify-content: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1800px) {
|
||||
|
||||
@@ -31,7 +31,7 @@ const publishLocation = (_p?: string) => {
|
||||
if (typeof history !== "undefined") {
|
||||
if (typeof Proxy !== "undefined") {
|
||||
// modern browser
|
||||
const historyApply = (target, thisArg, argumentsList) => {
|
||||
const historyApply = (target: (this: any, ...args: readonly any[]) => unknown, thisArg: any, argumentsList: string | readonly any[]) => {
|
||||
publishLocation(argumentsList && argumentsList.length >= 2 && argumentsList[2])
|
||||
Reflect.apply(target, thisArg, argumentsList)
|
||||
}
|
||||
|
||||
142
frontend/src/lib/assets/css/SwiperStylesHP.less
Normal file
@@ -0,0 +1,142 @@
|
||||
.underline {
|
||||
display: inline;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.underline:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
z-index: 10000;
|
||||
right: 0;
|
||||
width: 0;
|
||||
bottom: -2px;
|
||||
background: var(--background-color);
|
||||
height: 4px;
|
||||
transition: width 0.5s ease-in;
|
||||
}
|
||||
.underline:hover:after,
|
||||
.underline:focus:after,
|
||||
.underline:active:after {
|
||||
left: 0;
|
||||
right: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.fill {
|
||||
display: inline;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fill:hover {
|
||||
color: var(--background-color) !important;
|
||||
div {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
.fill:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
right: 0;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
width: 0px;
|
||||
background: var(--opposite-bg-color);
|
||||
transition: width 0.5s ease-in;
|
||||
}
|
||||
.fill:hover:after,
|
||||
.fill:focus:after,
|
||||
.fill:active:after {
|
||||
right: auto;
|
||||
width: 100%;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
@keyframes underlineEffect {
|
||||
0% {
|
||||
width: 0;
|
||||
}
|
||||
100% {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
swiper-slide {
|
||||
&:hover {
|
||||
h1.active .underline {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.titles {
|
||||
h1 {
|
||||
.underline {
|
||||
position: absolute;
|
||||
z-index: 10000;
|
||||
left: 0px;
|
||||
bottom: -10px;
|
||||
background: var(--opposite-bg-color);
|
||||
height: 5px;
|
||||
width: 0;
|
||||
animation: underlineEffect 4s linear forwards;
|
||||
@media @tablet {
|
||||
height: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.active) .underline {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swiper-button-prev,
|
||||
.swiper-button-next {
|
||||
color: var(--normal-font-color) !important;
|
||||
height: 70px !important;
|
||||
width: 70px !important;
|
||||
bottom: 0px !important;
|
||||
top: initial !important;
|
||||
transform: scale(0.5) !important;
|
||||
}
|
||||
|
||||
.swiper-button-prev {
|
||||
right: 18% !important;
|
||||
left: initial !important;
|
||||
transform-origin: left !important;
|
||||
}
|
||||
|
||||
.swiper-button-next {
|
||||
right: 3% !important;
|
||||
transform-origin: right;
|
||||
}
|
||||
|
||||
@media @tablet {
|
||||
.swiper-button-prev,
|
||||
.swiper-button-next {
|
||||
bottom: initial !important;
|
||||
top: 120px !important;
|
||||
transform: scale(0.8) !important;
|
||||
transform-origin: center !important;
|
||||
}
|
||||
.swiper-button-prev {
|
||||
left: 0% !important;
|
||||
right: initial !important;
|
||||
transform-origin: left !important;
|
||||
}
|
||||
.swiper-button-next {
|
||||
right: 0% !important;
|
||||
transform-origin: right !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media @desktop {
|
||||
.swiper-button-prev,
|
||||
.swiper-button-next {
|
||||
top: 125px !important;
|
||||
transform: scale(1) !important;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,33 @@
|
||||
@background-color: white;
|
||||
@normal-font-color: #333333;
|
||||
@hover-color: #dee2e6;
|
||||
@heading-font-color: #4b678b;
|
||||
@link-font-color: #4b678b;
|
||||
@banner-color: #06d6a0;
|
||||
:root {
|
||||
--background-color: white;
|
||||
--background-color-90: #ffffffe6;
|
||||
--normal-font-color: #333333;
|
||||
--normal-font-color-12: rgba(51, 51, 51, 0.12);
|
||||
--hover-color: #dee2e6;
|
||||
--heading-font-color: #672129;
|
||||
--link-font-color: #672129;
|
||||
--banner-color: #06d6a0;
|
||||
--opposite-bg-color: #000;
|
||||
--opposite-bg-color-80: rgba(0, 0, 0, 0.8);
|
||||
--opposite-bg-color-5: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
@desktop: ~"only screen and (min-width: 1024px)";
|
||||
@tablet: ~"only screen and (min-width: 768px)";
|
||||
@mobile: ~"only screen and (min-width: 100px)";
|
||||
|
||||
@body-fontsize-mobile: 17px;
|
||||
@body-fontsize-pc: 24px;
|
||||
@body-fontsize-mobile: 16px;
|
||||
@body-lineheight-mobile: 130%;
|
||||
@body-lineheight-pc: 130%;
|
||||
|
||||
@body-maxwidth: 1800px;
|
||||
@body-small-maxwidth: 1200px;
|
||||
|
||||
/* Allgemeine Stile */
|
||||
|
||||
/* roboto-condensed-regular - latin */
|
||||
body.darkTheme {
|
||||
--background-color: #1a1a1a; /* softer than #121212 */
|
||||
--background-color-90: rgba(26, 26, 26, 0.9);
|
||||
--normal-font-color: #d1d1d1; /* off-white, less harsh */
|
||||
--normal-font-color-12: rgba(209, 209, 209, 0.12);
|
||||
--hover-color: #404040; /* subtle change for hover */
|
||||
--heading-font-color: #9fb3c7; /* slightly brighter for better readability */
|
||||
--link-font-color: #9fb3c7;
|
||||
--banner-color: #04a577; /* a cooler shade for the banner */
|
||||
--opposite-bg-color: #fafafa; /* off-white */
|
||||
--opposite-bg-color-80: rgba(250, 250, 250, 0.8);
|
||||
--opposite-bg-color-5: rgba(250, 250, 250, 0.05);
|
||||
.row ul li::before {
|
||||
background-image: url("../../../../media/arrow-right-darkt.svg") !important;
|
||||
}
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: "Roboto Condensed", sans-serif;
|
||||
@@ -30,14 +37,13 @@
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Roboto Condensed", sans-serif;
|
||||
color: #333 !important;
|
||||
height: 100%;
|
||||
background-color: #f9f9f9;
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
body {
|
||||
background-color: @background-color;
|
||||
color: var(--normal-font-color);
|
||||
font-family: "Roboto Condensed", sans-serif;
|
||||
background-color: var(--background-color);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -69,8 +75,8 @@ ol {
|
||||
|
||||
/* Links */
|
||||
a {
|
||||
color: @link-font-color;
|
||||
text-decoration: none;
|
||||
color: var(--link-font-color);
|
||||
text-decoration: underline;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@@ -94,20 +100,17 @@ td {
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #f4f4f4;
|
||||
background-color: var(--background-color-90);
|
||||
}
|
||||
button {
|
||||
background-color: inherit;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: inherit;
|
||||
color: #333;
|
||||
color: var(--normal-font-color);
|
||||
}
|
||||
input,
|
||||
select {
|
||||
color: #333;
|
||||
color: var(--normal-font-color);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.text-container {
|
||||
}
|
||||
|
||||
6
frontend/src/lib/assets/css/productSwiper.less
Normal file
@@ -0,0 +1,6 @@
|
||||
swiper-container {
|
||||
height: auto;
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
padding: 20px !important;
|
||||
}
|
||||
@@ -1,19 +1,21 @@
|
||||
.swiper-button-prev,
|
||||
.swiper-button-next {
|
||||
transform-origin: left;
|
||||
color: #333;
|
||||
transform: scale(0.3);
|
||||
background-color: rgba(255, 255, 255, 0.6);
|
||||
top: 50%;
|
||||
padding: 10px;
|
||||
height: 70px;
|
||||
width: 70px;
|
||||
border-radius: 50px;
|
||||
}
|
||||
.swiper-button-prev {
|
||||
left: 6%;
|
||||
}
|
||||
.swiper-button-next {
|
||||
right: 6%;
|
||||
transform-origin: right;
|
||||
.images {
|
||||
.swiper-button-prev,
|
||||
.swiper-button-next {
|
||||
transform-origin: left;
|
||||
color: var(--normal-font-color);
|
||||
transform: scale(0.3);
|
||||
background-color: rgba(255, 255, 255, 0.6);
|
||||
top: 50%;
|
||||
padding: 10px;
|
||||
height: 70px;
|
||||
width: 70px;
|
||||
border-radius: 50px;
|
||||
}
|
||||
.swiper-button-prev {
|
||||
left: 6%;
|
||||
}
|
||||
.swiper-button-next {
|
||||
right: 6%;
|
||||
transform-origin: right;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
@background-color: white;
|
||||
@normal-font-color: #333333;
|
||||
@hover-color: #dee2e6;
|
||||
@heading-font-color: #4b678b;
|
||||
@link-font-color: #4b678b;
|
||||
@banner-color: #06d6a0;
|
||||
|
||||
@desktop: ~"only screen and (min-width: 1024px)";
|
||||
@tablet: ~"only screen and (min-width: 768px)";
|
||||
@mobile: ~"only screen and (min-width: 100px)";
|
||||
|
||||
@body-fontsize-mobile: 17px;
|
||||
@body-fontsize-pc: 24px;
|
||||
@@ -17,3 +8,7 @@
|
||||
|
||||
@body-maxwidth: 1800px;
|
||||
@body-small-maxwidth: 1200px;
|
||||
|
||||
@desktop: ~"only screen and (min-width: 1024px)";
|
||||
@tablet: ~"only screen and (min-width: 768px)";
|
||||
@mobile: ~"only screen and (min-width: 100px)";
|
||||
|
||||
BIN
frontend/src/lib/assets/fonts/orbitron-v31-latin-900.woff2
Normal file
BIN
frontend/src/lib/assets/fonts/orbitron-v31-latin-regular.woff2
Normal file
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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>
|
||||
@@ -1,6 +1,6 @@
|
||||
import { api } from "../../api"
|
||||
|
||||
export async function loadBanner(): Promise<Banner[]> {
|
||||
let banner = await api<any>("banner", {})
|
||||
return banner.data.map(e => e.banner)
|
||||
let banner = await api<Site>("banner", {})
|
||||
return banner.data.map(e=> e.banner)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export default function inView(node, params = { threshold: 0 }) {
|
||||
let observer
|
||||
export default function inView(node: Element, params = { threshold: 0 }) {
|
||||
let observer: IntersectionObserver
|
||||
|
||||
const handleIntersect = (e) => {
|
||||
const handleIntersect = (e: any) => {
|
||||
const v = e[0].isIntersecting ? "enter" : "exit"
|
||||
node.dispatchEvent(new CustomEvent(v))
|
||||
}
|
||||
@@ -16,7 +16,7 @@ export default function inView(node, params = { threshold: 0 }) {
|
||||
setObserver(params)
|
||||
|
||||
return {
|
||||
update(params) {
|
||||
update(params: any) {
|
||||
setObserver(params)
|
||||
},
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { api } from "../../api"
|
||||
|
||||
export async function sendForm(body) {
|
||||
export async function sendForm(body: any) {
|
||||
let response: any
|
||||
response = await api("forms", { method: "POST" }, { formular: body })
|
||||
return response
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export function validateFields(fieldsArray): string[] {
|
||||
export function validateFields(fieldsArray: (string | boolean | any[])[][]): (string | (() => void))[][] {
|
||||
const errors = []
|
||||
let selectedGroup
|
||||
let selectedGroup: number
|
||||
const numberRegex = /^[+]?([.]\d+|\d+([.]\d+)?)$/
|
||||
const emailRegex =
|
||||
/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/
|
||||
@@ -15,13 +15,14 @@ export function validateFields(fieldsArray): string[] {
|
||||
blockContainer[0].classList.add("invalidBlocks")
|
||||
}
|
||||
|
||||
const validateNumber = (value, field, element) => {
|
||||
const validateNumber = (value: string, field: any, element: HTMLElement) => {
|
||||
if (!numberRegex.test(`${value}`)) errors.push(["block", () => element.classList.add("border-red")])
|
||||
}
|
||||
|
||||
fieldsArray.forEach(([field, value]) => {
|
||||
if (field === "blockGroups" || field.includes("numberLabel")) {
|
||||
if (field === "blockGroups" || (typeof field === "string" && field.includes("numberLabel"))) {
|
||||
if (!field.includes("numberLabel")) return
|
||||
// @ts-ignore
|
||||
const [elementValue, element, group, boolean] = value
|
||||
if (!elementValue) return
|
||||
if (selectedGroup !== undefined) {
|
||||
@@ -33,29 +34,31 @@ export function validateFields(fieldsArray): string[] {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
value = value as any[]
|
||||
let required = value[1]
|
||||
value = value[0]
|
||||
if (!required && !value) return
|
||||
if (!value) {
|
||||
errors.push(["Eingabe ist erforderlich.", field])
|
||||
} else if (field.includes("number_")) {
|
||||
if (!numberRegex.test(`${value}`)) errors.push(["Ungültiger numerischer Wert.", field])
|
||||
} else if (field.includes("agreement_")) {
|
||||
if (value !== true) errors.push(["Bitte das Kontrollkästchen anklicken.", field])
|
||||
} else if (field.includes("Email_")) {
|
||||
if (!emailRegex.test(value)) errors.push(["Ungültiges E-Mail-Format.", field])
|
||||
} else if (field.includes("date_")) {
|
||||
if (!dateRegex.test(value)) errors.push(["Ungültiges Datumsformat.", field])
|
||||
} else if (field.includes("times_")) {
|
||||
if (!timeRegex.test(value)) errors.push(["Ungültiges Zeitformat.", field])
|
||||
} else if (field.includes("Telefon_")) {
|
||||
if (!phoneRegex.test(value)) errors.push(["Ungültiges Telefonnummernformat.", field])
|
||||
} else if (typeof field === "string") {
|
||||
if (field.includes("number_")) {
|
||||
if (!numberRegex.test(`${value}`)) errors.push(["Ungültiger numerischer Wert.", field])
|
||||
} else if (field.includes("agreement_")) {
|
||||
if (value !== true) errors.push(["Bitte das Kontrollkästchen anklicken.", field])
|
||||
} else if (field.includes("Email_")) {
|
||||
if (!emailRegex.test(value as string)) errors.push(["Ungültiges E-Mail-Format.", field])
|
||||
} else if (field.includes("date_")) {
|
||||
if (!dateRegex.test(value as string)) errors.push(["Ungültiges Datumsformat.", field])
|
||||
} else if (field.includes("times_")) {
|
||||
if (!timeRegex.test(value as string)) errors.push(["Ungültiges Zeitformat.", field])
|
||||
} else if (field.includes("Telefon_")) {
|
||||
if (!phoneRegex.test(value as string)) errors.push(["Ungültiges Telefonnummernformat.", field])
|
||||
}
|
||||
}
|
||||
})
|
||||
const blockContainer = document.getElementsByClassName("blockContainer")
|
||||
// @ts-ignore
|
||||
if (blockContainer.length && selectedGroup === undefined) {
|
||||
console.log("NO SELECTED GROUP")
|
||||
errors.push(["block", wholeBlockInvalid])
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import Homepage from "../lib/components/pagebuilder/Homepage.svelte"
|
||||
import Pagebuilder from "../lib/components/pagebuilder/pagebuilder.svelte"
|
||||
import Teaser from "../lib/components/pagebuilder/teaser.svelte"
|
||||
import VideoSwitch from "../lib/components/videoSwitch.svelte"
|
||||
import { navigation, sites } from "../lib/stores"
|
||||
let site
|
||||
function getHomePage(): Site {
|
||||
let site
|
||||
let site: Site | undefined
|
||||
function getHomePage(): Site | undefined {
|
||||
let site: Site | undefined = undefined
|
||||
Object.values($sites).forEach((element) => {
|
||||
if (element.path == "/") site = element
|
||||
})
|
||||
@@ -18,12 +18,11 @@
|
||||
</script>
|
||||
|
||||
<main>
|
||||
|
||||
{#if site != undefined}
|
||||
<Homepage />
|
||||
{#each site.row as row, i}
|
||||
<Pagebuilder rowNr="{i}" row="{row}" rows="{site?.row}" siteId="{site?.id}" />
|
||||
{/each}
|
||||
|
||||
{#each Object.values($sites) as site, i}
|
||||
{#if site.showTeaser}
|
||||
<Teaser site="{site}" index="{i}" />
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
import { navigate } from "svelte-routing"
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<meta name="robots" content="noindex" />
|
||||
<meta http-equiv="refresh" content="5; URL=/" />
|
||||
</svelte:head>
|
||||
|
||||
<div class="not-found">
|
||||
<div class="content">
|
||||
<h1>404</h1>
|
||||
@@ -33,17 +38,17 @@
|
||||
text-align: center;
|
||||
max-width: @body-small-maxwidth;
|
||||
padding: 2rem;
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
background-color: var(--background-color-90);
|
||||
|
||||
h1 {
|
||||
font-size: 6rem;
|
||||
color: @banner-color;
|
||||
color: var(--banner-color);
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
color: @heading-font-color;
|
||||
color: var(--heading-font-color);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
@@ -58,8 +63,8 @@
|
||||
transition: background-color 0.2s, color 0.2s;
|
||||
|
||||
&:hover {
|
||||
background-color: @hover-color;
|
||||
color: @normal-font-color;
|
||||
background-color: var(--hover-color);
|
||||
color: var(--normal-font-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
import { navigation, sites } from "../lib/stores"
|
||||
import NotFound from "./NotFound.svelte"
|
||||
export let path: string
|
||||
let site = false
|
||||
function getSelectedSite(path: string): Site {
|
||||
let site
|
||||
let site: Site
|
||||
function getSelectedSite(path: string): Site | {} {
|
||||
let site = {}
|
||||
console.log($sites, "sites")
|
||||
if (Object.values($sites).length == 0) return false
|
||||
if (Object.values($sites).length == 0) return {}
|
||||
Object.values($sites).forEach((element) => {
|
||||
if (element.path == "/" + path) site = element
|
||||
})
|
||||
@@ -15,13 +15,45 @@
|
||||
}
|
||||
$: {
|
||||
void $sites
|
||||
//@ts-ignore
|
||||
site = getSelectedSite(path)
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
{#key site}
|
||||
<!-- Title -->
|
||||
{#if site?.title}
|
||||
<title>{site.title}</title>
|
||||
{:else if site?.meta?.titel}
|
||||
<title>{site.meta.titel}</title>
|
||||
{:else}
|
||||
<title>AllKids Erfurt</title>
|
||||
{/if}
|
||||
|
||||
<!-- Description -->
|
||||
{#if site?.meta?.beschreibung}
|
||||
<meta name="description" content="{site.meta.beschreibung}" />
|
||||
{/if}
|
||||
|
||||
<!-- Keywords -->
|
||||
{#if site?.meta?.keywords}
|
||||
<meta name="keywords" content="{site.meta.keywords}" />
|
||||
{:else}
|
||||
<meta
|
||||
name="keywords"
|
||||
content="AllKids Erfurt, Second-Hand Kinderkleidung Erfurt, Gebrauchte Kinderspielzeuge Erfurt, AllKids Second-Hand, Erfurt Kinder Second-Hand-Shop, Kinderkleidung Erfurt, Nachhaltige Kinderprodukte Erfurt, AllKids Kinderladen, Second-Hand Babyausstattung Erfurt, AllKids Kleidung Tausch, Erfurt Second-Hand Kinderbücher, AllKids ökologisch, Kinder Second-Hand Markt Erfurt, Günstige Kinderkleidung Erfurt, AllKids Bewertungen, Kinderartikel Kauf und Verkauf Erfurt, Second-Hand Kinderwagen Erfurt, AllKids nachhaltiger Laden, Gebrauchte Kindermöbel Erfurt, AllKids Erfurt Standort"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if site?.aktiv === false}
|
||||
<meta name="robots" content="noindex" />
|
||||
{/if}
|
||||
{/key}
|
||||
</svelte:head>
|
||||
<main class="">
|
||||
{#if site}
|
||||
{#each site.row as row, i}
|
||||
{#if site != undefined}
|
||||
{#each site.row || [] as row, i}
|
||||
<Pagebuilder rowNr="{i}" row="{row}" rows="{site?.row}" siteId="{site?.id}" />
|
||||
{/each}
|
||||
{:else if site === undefined}
|
||||
|
||||