This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { location, navigation, sites, temperature, banner, serviceNavigation } from "./lib/stores"
|
||||
import { location, navigation, sites, banner, serviceNavigation } from "./lib/stores"
|
||||
import Header from "./lib/components/header/Header.svelte"
|
||||
import "fluent-svelte/theme.css"
|
||||
|
||||
import Footer from "./lib/components/Footer.svelte"
|
||||
import { Route, Router } from "svelte-routing"
|
||||
import HomePage from "./routes/HomePage.svelte"
|
||||
@@ -44,7 +46,6 @@
|
||||
sitesRes[e.id] = e
|
||||
})
|
||||
$sites = sitesRes
|
||||
console.log("ALARM OVER", $sites)
|
||||
}
|
||||
|
||||
getNavigation()
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
right: 0;
|
||||
width: 0;
|
||||
bottom: -2px;
|
||||
background: var(--background-color);
|
||||
background: var(--heading-font-color);
|
||||
height: 4px;
|
||||
transition: width 0.5s ease-in;
|
||||
}
|
||||
@@ -29,7 +29,7 @@
|
||||
}
|
||||
|
||||
.fill:hover {
|
||||
color: var(--background-color) !important;
|
||||
color: var(--heading-font-color) !important;
|
||||
div {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
@@ -43,7 +43,7 @@
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
width: 0px;
|
||||
background: var(--opposite-bg-color);
|
||||
background: var(--heading-font-color);
|
||||
transition: width 0.5s ease-in;
|
||||
}
|
||||
.fill:hover:after,
|
||||
@@ -78,7 +78,7 @@ swiper-slide {
|
||||
z-index: 10000;
|
||||
left: 0px;
|
||||
bottom: -10px;
|
||||
background: var(--opposite-bg-color);
|
||||
background: var(--heading-font-color);
|
||||
height: 5px;
|
||||
width: 0;
|
||||
animation: underlineEffect 4s linear forwards;
|
||||
@@ -95,7 +95,7 @@ swiper-slide {
|
||||
|
||||
.swiper-button-prev,
|
||||
.swiper-button-next {
|
||||
color: var(--normal-font-color) !important;
|
||||
color: var(--heading-font-color) !important;
|
||||
height: 70px !important;
|
||||
width: 70px !important;
|
||||
bottom: 0px !important;
|
||||
@@ -136,7 +136,7 @@ swiper-slide {
|
||||
@media @desktop {
|
||||
.swiper-button-prev,
|
||||
.swiper-button-next {
|
||||
top: 125px !important;
|
||||
top: 155px !important;
|
||||
transform: scale(1) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,35 @@
|
||||
:root {
|
||||
--background-color: white;
|
||||
--background-color: rgb(235, 221, 221);
|
||||
--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;
|
||||
--normal-font-color-80: rgba(51, 51, 51, 0.8);
|
||||
--normal-font-color-50: rgba(51, 51, 51, 0.5);
|
||||
--normal-font-color-30: rgba(51, 51, 51, 0.3);
|
||||
|
||||
--hover-color: rgb(197, 173, 173);
|
||||
--heading-font-color: #ff0000;
|
||||
--top-heading-font-color: rgb(255, 165, 0);
|
||||
--link-font-color: rgb(255, 165, 0);
|
||||
--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);
|
||||
--opposite-bg-color-80: rgba(24, 24, 24, 0.8);
|
||||
--opposite-bg-color-5: rgba(24, 24, 24, 0.05);
|
||||
}
|
||||
|
||||
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-80: rgba(209, 209, 209, 0.8);
|
||||
--normal-font-color-50: rgba(209, 209, 209, 0.5);
|
||||
--normal-font-color-30: rgba(209, 209, 209, 0.3);
|
||||
--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;
|
||||
--top-heading-font-color: rgb(200, 106, 0);
|
||||
--link-font-color: rgb(200, 106, 0);
|
||||
--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);
|
||||
@@ -75,9 +85,8 @@ ol {
|
||||
|
||||
/* Links */
|
||||
a {
|
||||
color: var(--link-font-color);
|
||||
text-decoration: underline;
|
||||
font-weight: 700;
|
||||
color: var(--normal-font-color);
|
||||
}
|
||||
|
||||
/* Tabellen */
|
||||
@@ -92,16 +101,6 @@ table {
|
||||
right 0.5s ease, transform 0.5s ease;
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: var(--background-color-90);
|
||||
}
|
||||
button {
|
||||
background-color: inherit;
|
||||
border: none;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { navigate } from "svelte-routing"
|
||||
import { serviceNavigation, sites } from "../stores"
|
||||
import { serviceNavigation, sites, darkMode } from "../stores"
|
||||
</script>
|
||||
|
||||
<div class="footer">
|
||||
@@ -37,12 +37,20 @@
|
||||
{/each}
|
||||
</div>
|
||||
<button
|
||||
class="darklight"
|
||||
on:click="{() => {
|
||||
const body = document.querySelector('body')
|
||||
if (body) body.classList.toggle('darkTheme')
|
||||
if (body) {
|
||||
body.classList.toggle('darkTheme')
|
||||
}
|
||||
$darkMode = !$darkMode
|
||||
}}"
|
||||
>
|
||||
toggletheme
|
||||
{#if !$darkMode}
|
||||
<img src="/media/dark.svg" alt="darkmode" />
|
||||
{:else}
|
||||
<img src="/media/light.svg" alt="lightmode" />
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -51,6 +59,15 @@
|
||||
.social {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.darklight {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
object-fit: contain;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.footer {
|
||||
margin-top: 60px;
|
||||
width: 100vw;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { navigation, sites } from "../../stores"
|
||||
import { darkMode, navigation, sites } from "../../stores"
|
||||
|
||||
import { apiBaseURL } from "../../../config"
|
||||
import { navigate } from "svelte-routing"
|
||||
@@ -60,9 +60,11 @@
|
||||
navigate('/')
|
||||
}}"
|
||||
>
|
||||
<button class="img-logo-container"><img src="/media/logo.svg" alt="logo" /></button>
|
||||
<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="upper"><span class="yellow">ALL</span> <span class="red">KIDS</span></p>
|
||||
<p id="lower">SO GÜNSTIG WIE NACHHALTIG</p>
|
||||
</div>
|
||||
</button>
|
||||
@@ -202,12 +204,22 @@
|
||||
text-align: left;
|
||||
}
|
||||
& > #upper {
|
||||
font-family: "Orbitron" !important;
|
||||
font-size: 30px;
|
||||
font-weight: 700;
|
||||
span {
|
||||
font-family: "Orbitron" !important;
|
||||
font-size: 31px;
|
||||
font-weight: 700;
|
||||
&.red {
|
||||
color: red;
|
||||
}
|
||||
&.yellow {
|
||||
color: yellow;
|
||||
}
|
||||
}
|
||||
}
|
||||
& > #lower {
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
color: orange;
|
||||
}
|
||||
font-weight: bold;
|
||||
font-size: 1.2rem;
|
||||
@@ -258,7 +270,7 @@
|
||||
overflow: hidden;
|
||||
width: 100vw;
|
||||
z-index: 2000;
|
||||
background-color: var(--opposite-bg-color-80);
|
||||
background-color: rgba(0, 0, 0, 0.849);
|
||||
opacity: 0;
|
||||
.inner-container {
|
||||
width: 100%;
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
}
|
||||
|
||||
function imageSlide(images: HTMLImageElement[]) {
|
||||
console.log(images)
|
||||
let currentImage = 0
|
||||
images[0].classList.add("show-img")
|
||||
let interval = setInterval(() => {
|
||||
@@ -59,9 +58,11 @@
|
||||
navigate('/')
|
||||
}}"
|
||||
>
|
||||
<button class="img-logo-container"><img src="/media/logo.svg" alt="logo" /></button>
|
||||
<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="upper"><span class="yellow">ALL</span> <span class="red">KIDS</span></p>
|
||||
<p id="lower">SO GÜNSTIG WIE NACHHALTIG</p>
|
||||
</div>
|
||||
</button>
|
||||
@@ -241,12 +242,22 @@
|
||||
text-align: left;
|
||||
}
|
||||
& > #upper {
|
||||
font-family: "Orbitron" !important;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
span {
|
||||
font-family: "Orbitron" !important;
|
||||
font-size: 31px;
|
||||
font-weight: 700;
|
||||
&.red {
|
||||
color: red;
|
||||
}
|
||||
&.yellow {
|
||||
color: yellow;
|
||||
}
|
||||
}
|
||||
}
|
||||
& > #lower {
|
||||
font-size: 10px;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
color: orange;
|
||||
}
|
||||
font-weight: bold;
|
||||
font-size: 1.2rem;
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
}
|
||||
|
||||
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
|
||||
@@ -159,6 +158,7 @@
|
||||
line-height: 1;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
color: var(--heading-font-color);
|
||||
}
|
||||
|
||||
h2 {
|
||||
@@ -168,6 +168,7 @@
|
||||
}
|
||||
line-height: 1;
|
||||
font-weight: 500;
|
||||
color: var(--top-heading-font-color);
|
||||
}
|
||||
}
|
||||
.description {
|
||||
|
||||
399
frontend/src/lib/components/pagebuilder/form/Formular.svelte
Normal file
399
frontend/src/lib/components/pagebuilder/form/Formular.svelte
Normal file
@@ -0,0 +1,399 @@
|
||||
<script lang="ts">
|
||||
import Form from "./form.svelte"
|
||||
import MobileForm from "./mobileForm.svelte"
|
||||
import { writable } from "svelte/store"
|
||||
import { validateFields } from "../../../functions/validateFields"
|
||||
import { sendForm } from "../../../functions/sendForm"
|
||||
import { navigate } from "svelte-routing"
|
||||
import { onMount } from "svelte"
|
||||
|
||||
export let col: Column
|
||||
export let siteId: string
|
||||
export let rowNr: number
|
||||
export let row: Row
|
||||
export let rows: Row[]
|
||||
|
||||
let formSend = false
|
||||
let formValues = writable<FormValues>({})
|
||||
|
||||
function submitForm() {
|
||||
const values: Array<ValueEntry> = Object.entries($formValues).map((entry: ObjectEntry) => {
|
||||
const key: string = entry[0]
|
||||
const value: CustomHTMLElement = entry[1]
|
||||
if (!key.includes("numberLabel")) {
|
||||
return [key, [value.checked || value.value, value.required]] as ValueEntry
|
||||
} else {
|
||||
return [key, [value.value, value, value.getAttribute("name"), value.required]] as ValueEntry
|
||||
}
|
||||
})
|
||||
|
||||
const fields: Array<ValueEntry> = values.filter((entry: ValueEntry) => !entry[0].includes("label"))
|
||||
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] as string
|
||||
label?.appendChild(errorElement)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// @ts-ignore
|
||||
const formObj: FormObj = {}
|
||||
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]
|
||||
}
|
||||
})
|
||||
let form: any
|
||||
row.column.forEach((col) => {
|
||||
if (col.contentType == "form") form = col
|
||||
})
|
||||
if (!form) return
|
||||
formObj["formRows"] = form.formRows.map((r: FormRow) => r.rowName)
|
||||
formObj["formTitle"] = form.formEmailTitle
|
||||
formSend = true
|
||||
const hny = document.getElementById("hny") as HTMLInputElement
|
||||
if (hny) formObj["honey"] = hny.checked
|
||||
sendForm(formObj)
|
||||
}
|
||||
}
|
||||
let innerWidth = window.innerWidth
|
||||
|
||||
onMount(() => {
|
||||
const handleResize = () => {
|
||||
innerWidth = window.innerWidth
|
||||
}
|
||||
|
||||
window.addEventListener("resize", handleResize)
|
||||
|
||||
// Cleanup function
|
||||
return () => {
|
||||
window.removeEventListener("resize", handleResize)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if formSend}
|
||||
<div class="success-message">
|
||||
<h1>Formular erfolgreich gesendet!</h1>
|
||||
<p>Vielen Dank für Ihre Anfrage. Wir werden uns in Kürze bei Ihnen melden.</p>
|
||||
</div>
|
||||
{:else}
|
||||
<form
|
||||
class="form-rows"
|
||||
on:submit="{(e) => {
|
||||
e.preventDefault()
|
||||
submitForm()
|
||||
}}"
|
||||
>
|
||||
{#each col.formRows ?? [] as formRow, i}
|
||||
{#if innerWidth < 768}
|
||||
<MobileForm formRow="{formRow}" formValues="{formValues}" index="{i}" />
|
||||
{:else}
|
||||
<Form formRow="{formRow}" formValues="{formValues}" index="{i}" />
|
||||
{/if}
|
||||
{/each}
|
||||
<div class="row additional">
|
||||
<div class="data-protection">
|
||||
<label bind:this="{$formValues[`agreement_label`]}">
|
||||
<input
|
||||
required="{true}"
|
||||
class="checkit"
|
||||
type="checkbox"
|
||||
on:change="{(e) => {
|
||||
let element = e.currentTarget
|
||||
element.classList.remove('invalid')
|
||||
}}"
|
||||
bind:this="{$formValues['agreement']}"
|
||||
/>
|
||||
<span class="checkit-span"></span>
|
||||
</label>
|
||||
|
||||
<div class="datasec">
|
||||
<button on:click|preventDefault="{() => navigate('/datenschutz')}" class="link">
|
||||
Datenschutz
|
||||
</button>
|
||||
akzeptieren
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="checkbox"
|
||||
name="contact_me_by_fax_only"
|
||||
id="hny"
|
||||
value="1"
|
||||
style="display:none !important"
|
||||
tabindex="-1"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<button class="submit-request" type="submit">Anfrage absenden</button>
|
||||
</div>
|
||||
</form>
|
||||
{/if}
|
||||
|
||||
<style lang="less" global>
|
||||
@import "../../../assets/css/variables.less";
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
.data-protection {
|
||||
margin: 5px 0px;
|
||||
box-shadow: 0 0 25px 10px var(--opposite-bg-color-5);
|
||||
}
|
||||
|
||||
.success-message {
|
||||
h1 {
|
||||
color: var(--heading-font-color);
|
||||
font-size: 36px;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
.invalidBlocks {
|
||||
border: 2px solid rgb(255, 0, 0) !important;
|
||||
position: relative;
|
||||
&::after {
|
||||
font-size: 0.9rem !important;
|
||||
color: red !important;
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
content: "Bitte wähle entweder eine Kartenanzahl oder einen Wunschbetrag aus.";
|
||||
}
|
||||
}
|
||||
|
||||
.border-red {
|
||||
border-color: red !important;
|
||||
}
|
||||
|
||||
.no-margin {
|
||||
margin-top: 15px !important;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
border: 2px solid red !important;
|
||||
}
|
||||
.error-message {
|
||||
font-size: 0.9rem !important;
|
||||
color: red !important;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
}
|
||||
|
||||
.checkit {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.checkit-span {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
border: 1px solid grey;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
[type="checkbox"]:checked + span:before {
|
||||
content: "\2714";
|
||||
position: absolute;
|
||||
transform-origin: bottom;
|
||||
}
|
||||
|
||||
.form-rows {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
width: 100%;
|
||||
h3 {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: 1.5rem;
|
||||
|
||||
.date {
|
||||
max-width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
label {
|
||||
width: 100% !important;
|
||||
font-size: inherit;
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
width: 100%;
|
||||
font-size: inherit;
|
||||
}
|
||||
}
|
||||
.form-cols {
|
||||
display: flex;
|
||||
gap: 1.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.form-column {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
width: 100%;
|
||||
gap: 1rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--hover-color);
|
||||
}
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
.data-protection {
|
||||
padding: 10px 20px;
|
||||
border: 0px solid var(--opposite-bg-color);
|
||||
border-bottom: 3px solid var(--heading-font-color);
|
||||
outline: 0px solid var(--opposite-bg-color);
|
||||
color: var(--opposite-bg-color);
|
||||
background-color: var(--background-color);
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.data-protection {
|
||||
display: flex;
|
||||
|
||||
flex-wrap: nowrap;
|
||||
gap: 5px !important;
|
||||
justify-content: start;
|
||||
flex-direction: row !important;
|
||||
}
|
||||
|
||||
input[type="date"] {
|
||||
font-family: inherit;
|
||||
width: 100% !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
select {
|
||||
padding: 10px 20px;
|
||||
border: 0;
|
||||
border-bottom: 3px solid var(--heading-font-color);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
select:focus {
|
||||
border-bottom-color: var(--heading-font-color);
|
||||
}
|
||||
|
||||
#time-select {
|
||||
appearance: none;
|
||||
background-image: url("../../../../../media/clock.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 20px center;
|
||||
background-size: 18px;
|
||||
|
||||
option {
|
||||
padding: 10px 20px;
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
}
|
||||
@media @mobile {
|
||||
.date {
|
||||
width: 100vw !important;
|
||||
}
|
||||
}
|
||||
@media @tablet {
|
||||
.date {
|
||||
width: 100% !important;
|
||||
}
|
||||
.form-cols {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
}
|
||||
i .max-width {
|
||||
max-width: @body-maxwidth !important;
|
||||
}
|
||||
|
||||
.datasec {
|
||||
display: flex;
|
||||
align-items: center !important;
|
||||
.link {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: flex-end !important;
|
||||
text-decoration: underline;
|
||||
margin-right: 3px;
|
||||
color: rgb(14, 91, 146);
|
||||
}
|
||||
}
|
||||
|
||||
.additional {
|
||||
display: flex;
|
||||
@media @mobile {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
@media @tablet {
|
||||
flex-direction: row !important;
|
||||
}
|
||||
gap: 2.5rem;
|
||||
div {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
}
|
||||
.submit-request {
|
||||
flex: 1;
|
||||
box-shadow: 0 0 25px 10px var(--opposite-bg-color-5);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
background-color: var(--heading-font-color);
|
||||
color: var(--background-color);
|
||||
padding: 10px 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
18
frontend/src/lib/components/pagebuilder/form/checkbox.svelte
Normal file
18
frontend/src/lib/components/pagebuilder/form/checkbox.svelte
Normal file
@@ -0,0 +1,18 @@
|
||||
<script lang="ts">
|
||||
import type { Writable } from "svelte/store"
|
||||
|
||||
export let label = "" // Der Text, der neben der Checkbox angezeigt wird
|
||||
export let bindValue: any // Der Wert der Checkbox
|
||||
export let formValues: Writable<FormValues> // Das formValues-Objekt aus dem übergeordneten Komponenten
|
||||
export let id = "" // Eindeutige ID für die Checkbox, um den Label korrekt zuzuweisen
|
||||
export let name = "" // Name des Formularelements
|
||||
</script>
|
||||
|
||||
<label class="checkbox-container" for="{id}">
|
||||
<input type="checkbox" bind:checked="{bindValue}" id="{id}" name="{name}" bind:this="{formValues[name]}" />
|
||||
<span>{label}</span>
|
||||
</label>
|
||||
|
||||
<style>
|
||||
/* Sie können hier den Stil für Ihre Checkbox anpassen */
|
||||
</style>
|
||||
@@ -0,0 +1,48 @@
|
||||
<script lang="ts">
|
||||
import type { Writable } from "svelte/store"
|
||||
export let groupTitle: string
|
||||
export let checkboxes: { name: string; emailName: string }[]
|
||||
export let formValues: Writable<FormValues>
|
||||
export let rowNr: number
|
||||
</script>
|
||||
|
||||
<div class="checkbox-group">
|
||||
<h3>{groupTitle}</h3>
|
||||
<div class="containerr">
|
||||
{#each checkboxes as checkbox, i}
|
||||
<label class="checkbox-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox-input checkit"
|
||||
bind:this="{$formValues[`checkbox_${groupTitle}_${rowNr}_${checkbox.emailName}`]}"
|
||||
/>
|
||||
<span class="checkit-span"></span>
|
||||
{checkbox.name}
|
||||
</label>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="less">
|
||||
.checkbox-group {
|
||||
.checkbox-input {
|
||||
vertical-align: middle;
|
||||
margin-right: 8px;
|
||||
width: fit-content !important;
|
||||
}
|
||||
|
||||
.checkbox-label {
|
||||
width: 100%;
|
||||
vertical-align: middle;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
& > .containerr {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
131
frontend/src/lib/components/pagebuilder/form/datepicker.svelte
Normal file
131
frontend/src/lib/components/pagebuilder/form/datepicker.svelte
Normal file
@@ -0,0 +1,131 @@
|
||||
<script lang="ts">
|
||||
import { CalendarView } from "fluent-svelte"
|
||||
|
||||
export let groupTitle: string
|
||||
export let datePickerProps: DatePickerProps
|
||||
export let formValues: any
|
||||
export let rowNr: number
|
||||
export let formCol: FormColumn
|
||||
|
||||
const today = new Date()
|
||||
const oneYearFromNow = new Date(today)
|
||||
oneYearFromNow.setFullYear(today.getFullYear() + 1)
|
||||
const indexToDay: Record<number, string> = {
|
||||
0: "sunday",
|
||||
1: "monday",
|
||||
2: "tuesday",
|
||||
3: "wednesday",
|
||||
4: "thursday",
|
||||
5: "friday",
|
||||
6: "saturday",
|
||||
}
|
||||
|
||||
function generateBlackoutDates(props: DatePickerProps): Date[] {
|
||||
let blackoutDates = []
|
||||
|
||||
// Funktion, um einen ISO-String in ein vereinfachtes Date-Objekt umzuwandeln
|
||||
const dateFromISOString = (isoString: string) => {
|
||||
const date = new Date(isoString)
|
||||
return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()))
|
||||
}
|
||||
|
||||
const dayToIndex: Record<string, number> = {
|
||||
sunday: 0,
|
||||
monday: 1,
|
||||
tuesday: 2,
|
||||
wednesday: 3,
|
||||
thursday: 4,
|
||||
friday: 5,
|
||||
saturday: 6,
|
||||
}
|
||||
|
||||
// Initialisiere ein aktuelles Datum auf heute
|
||||
let currentDate = new Date(Date.UTC(today.getFullYear(), today.getMonth(), today.getDate()))
|
||||
|
||||
// Schleife durch die nächsten 365 Tage
|
||||
for (let i = 0; i <= 365; i++) {
|
||||
// Überprüfen, ob dieses Datum erlaubt ist
|
||||
const isAllowed = props.allowedDateRanges.some((range) => {
|
||||
const fromDate = dateFromISOString(range.from)
|
||||
const toDate = dateFromISOString(range.to)
|
||||
|
||||
return currentDate >= fromDate && currentDate <= toDate
|
||||
})
|
||||
|
||||
// Überprüfen, ob der Wochentag ausgeschlossen ist
|
||||
const currentDayIndex = currentDate.getUTCDay()
|
||||
const currentDayString = indexToDay[currentDayIndex]
|
||||
const isExcluded = props.excludeDays?.includes(currentDayString)
|
||||
|
||||
// Wenn nicht erlaubt oder ausgeschlossen, zu den Blackout-Daten hinzufügen
|
||||
if (!isAllowed || isExcluded) {
|
||||
blackoutDates.push(new Date(currentDate))
|
||||
}
|
||||
|
||||
// Zum nächsten Tag wechseln
|
||||
currentDate.setUTCDate(currentDate.getUTCDate() + 1)
|
||||
}
|
||||
|
||||
return blackoutDates
|
||||
}
|
||||
|
||||
let value = new Date()
|
||||
const blackoutDates = generateBlackoutDates(datePickerProps)
|
||||
|
||||
function setFormValues() {
|
||||
$formValues[`datepicker_${groupTitle}_${rowNr}_${formCol.datePickerEmailTitle}`] = {
|
||||
value: value.toLocaleDateString("de-DE"),
|
||||
required: !formCol.datePickerNotRequired,
|
||||
}
|
||||
}
|
||||
//needs email conntection
|
||||
$: {
|
||||
if (value) {
|
||||
setFormValues()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div class="container">
|
||||
<div
|
||||
class="datepicker"
|
||||
on:click|preventDefault|stopPropagation
|
||||
on:keydown|stopPropagation
|
||||
on:submit|stopPropagation|preventDefault
|
||||
>
|
||||
<CalendarView
|
||||
weekStart="{1}"
|
||||
bind:vaue="{value}"
|
||||
on:change="{(e) => {
|
||||
value = e.detail
|
||||
}}"
|
||||
min="{today}"
|
||||
max="{oneYearFromNow}"
|
||||
blackout="{blackoutDates}"
|
||||
locale="de-DE"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="less">
|
||||
@import url("https://unpkg.com/fluent-svelte/theme.css");
|
||||
.container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
--fds-solid-background-quarternary: var(--background-color);
|
||||
--fds-text-primary: var(--normal-font-color);
|
||||
--fds-text-secondary: var(--normal-font-color-80);
|
||||
--fds-text-tertiary: var(--normal-font-color-50);
|
||||
--fds-text-disabled: var(--normal-font-color-30);
|
||||
--fds-accent-disabled: var(--opposite-bg-color-5);
|
||||
--fds-control-strong-stroke-default: var(--opposite-bg-color-80);
|
||||
.datepicker {
|
||||
width: fit-content;
|
||||
margin: 5px 0px;
|
||||
box-shadow: 0 0 25px 10px var(--opposite-bg-color-5);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import CheckboxGroup from "./checkboxGroup.svelte"
|
||||
import Datepicker from "./datepicker.svelte"
|
||||
import FormLabelNumberBlock from "./formLabelNumberBlock.svelte"
|
||||
import type { Writable } from "svelte/store"
|
||||
|
||||
@@ -24,6 +26,9 @@
|
||||
</script>
|
||||
|
||||
<div class="form-row">
|
||||
<h3 style="margin-bottom: -0.5rem;">
|
||||
{#if formRow.showRowName}{formRow.rowName || ""}{/if}
|
||||
</h3>
|
||||
<div class="form-cols">
|
||||
{#each formRow.columns as column, columnIndex}
|
||||
<div class="form-column">
|
||||
@@ -48,7 +53,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>
|
||||
@@ -114,49 +119,70 @@
|
||||
</label>
|
||||
{/if}
|
||||
|
||||
{#each column.text || [] as textField, textFieldIndex}
|
||||
{#if textField?.textArea}
|
||||
<label bind:this="{$formValues[`textarea_Nachricht_label`]}">
|
||||
<textarea
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
on:change="{removeInvalid}"
|
||||
{#if column.showCheckboxGroup}
|
||||
<CheckboxGroup
|
||||
checkboxes="{column.checkboxes}"
|
||||
groupTitle="{column.groupTitle}"
|
||||
formValues="{formValues}"
|
||||
rowNr="{index}"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if column.showDatePicker}
|
||||
<Datepicker
|
||||
datePickerProps="{column.datePickerProps}"
|
||||
groupTitle="{column.groupTitle}"
|
||||
formValues="{formValues}"
|
||||
rowNr="{index}"
|
||||
formCol="{column}"
|
||||
|
||||
/>
|
||||
{/if}
|
||||
{#each column.text ?? [] as textField, textFieldIndex}
|
||||
<div>
|
||||
<h3 class="textTitle">{textField.textTitle || ""}</h3>
|
||||
{#if textField?.textArea}
|
||||
<label bind:this="{$formValues[`textarea_Nachricht_label`]}">
|
||||
<textarea
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
on:change="{removeInvalid}"
|
||||
bind:this="{$formValues[
|
||||
`textarea_Nachricht_${textField.textfieldOrder}_${index}_${
|
||||
textField.emailName || columnIndex + 'invalidtext' + textFieldIndex
|
||||
}`
|
||||
]}"></textarea>
|
||||
</label>
|
||||
{:else}
|
||||
<label
|
||||
bind:this="{$formValues[
|
||||
`textarea_Nachricht_${textField.textfieldOrder}_${index}_${
|
||||
textField.emailName || columnIndex + 'invalidtext' + textFieldIndex
|
||||
}`
|
||||
]}"></textarea>
|
||||
</label>
|
||||
{:else}
|
||||
<label
|
||||
bind:this="{$formValues[
|
||||
`input_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_label`
|
||||
]}"
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
on:change="{removeInvalid}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
bind:this="{$formValues[
|
||||
`${
|
||||
textField?.telValidation
|
||||
? 'Telefon'
|
||||
: textField?.emailValidation
|
||||
? 'Email'
|
||||
: 'input'
|
||||
}_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_${
|
||||
textField.textfieldOrder
|
||||
}_${index}_${textField.emailName || columnIndex + 'invalidtext' + textFieldIndex}`
|
||||
`input_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_label`
|
||||
]}"
|
||||
/>
|
||||
</label>
|
||||
{/if}
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
on:change="{removeInvalid}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
bind:this="{$formValues[
|
||||
`${
|
||||
textField?.telValidation
|
||||
? 'Telefon'
|
||||
: textField?.emailValidation
|
||||
? 'Email'
|
||||
: 'input'
|
||||
}_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_${
|
||||
textField.textfieldOrder
|
||||
}_${index}_${
|
||||
textField.emailName || columnIndex + 'invalidtext' + textFieldIndex
|
||||
}`
|
||||
]}"
|
||||
/>
|
||||
</label>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="less">
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import FormLabelNumberBlock from "./formLabelNumberBlock.svelte"
|
||||
import type { Writable } from "svelte/store"
|
||||
|
||||
import CheckboxGroup from "./checkboxGroup.svelte"
|
||||
import Datepicker from "./datepicker.svelte"
|
||||
export let formRow: FormRow
|
||||
export let formValues: Writable<FormValues>
|
||||
export let index: number
|
||||
@@ -126,46 +127,69 @@
|
||||
</label>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if column.showCheckboxGroup}
|
||||
<CheckboxGroup
|
||||
checkboxes="{column.checkboxes}"
|
||||
groupTitle="{column.groupTitle}"
|
||||
formValues="{formValues}"
|
||||
rowNr="{index}"
|
||||
/>
|
||||
{/if}
|
||||
{#if column.showDatePicker}
|
||||
<Datepicker
|
||||
datePickerProps="{column.datePickerProps}"
|
||||
groupTitle="{column.groupTitle}"
|
||||
formValues="{formValues}"
|
||||
rowNr="{index}"
|
||||
formCol="{column}"
|
||||
/>
|
||||
{/if}
|
||||
{#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`]}">
|
||||
<textarea
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
on:change="{removeInvalid}"
|
||||
<h3 class="textTitle">{textField.textTitle || ""}</h3>
|
||||
<div
|
||||
class="column-{columnIndex} position-{getPosition(column, 5 + textFieldIndex, textFieldIndex)}"
|
||||
>
|
||||
{#if textField?.textArea}
|
||||
<label bind:this="{$formValues[`textarea_Nachricht_label`]}">
|
||||
<textarea
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
on:change="{removeInvalid}"
|
||||
bind:this="{$formValues[
|
||||
`textarea_Nachricht_${textField.textfieldOrder}_${index}_${
|
||||
textField.emailName || columnIndex + 'invalidtext' + textFieldIndex
|
||||
}`
|
||||
]}"></textarea>
|
||||
</label>
|
||||
{:else}
|
||||
<label
|
||||
bind:this="{$formValues[
|
||||
`textarea_Nachricht_${textField.textfieldOrder}_${index}_${
|
||||
textField.emailName || columnIndex + 'invalidtext' + textFieldIndex
|
||||
}`
|
||||
]}"></textarea>
|
||||
</label>
|
||||
{:else}
|
||||
<label
|
||||
bind:this="{$formValues[
|
||||
`input_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_label`
|
||||
]}"
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
on:change="{removeInvalid}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
bind:this="{$formValues[
|
||||
`${
|
||||
textField?.telValidation
|
||||
? 'Telefon'
|
||||
: textField?.emailValidation
|
||||
? 'Email'
|
||||
: 'input'
|
||||
}_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_${
|
||||
textField.textfieldOrder
|
||||
}_${index}_${textField.emailName || columnIndex + 'invalidtext' + textFieldIndex}`
|
||||
`input_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_label`
|
||||
]}"
|
||||
/>
|
||||
</label>
|
||||
{/if}
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="{textField?.textPlaceholder}"
|
||||
on:change="{removeInvalid}"
|
||||
required="{textField?.notRequired !== true}"
|
||||
bind:this="{$formValues[
|
||||
`${
|
||||
textField?.telValidation
|
||||
? 'Telefon'
|
||||
: textField?.emailValidation
|
||||
? 'Email'
|
||||
: 'input'
|
||||
}_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_${
|
||||
textField.textfieldOrder
|
||||
}_${index}_${
|
||||
textField.emailName || columnIndex + 'invalidtext' + textFieldIndex
|
||||
}`
|
||||
]}"
|
||||
/>
|
||||
</label>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
{/each}
|
||||
|
||||
@@ -7,81 +7,20 @@
|
||||
import MainPicture from "./mainPicture.svelte"
|
||||
import TextContent from "./textContent.svelte"
|
||||
import Table from "./table.svelte"
|
||||
import Form from "./form/form.svelte"
|
||||
import MobileForm from "./form/mobileForm.svelte"
|
||||
import Formular from "./form/Formular.svelte"
|
||||
import { writable } from "svelte/store"
|
||||
import { validateFields } from "../../functions/validateFields"
|
||||
import { sendForm } from "../../functions/sendForm"
|
||||
import GoogleMaps from "../googleMaps.svelte"
|
||||
import { navigate } from "svelte-routing"
|
||||
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<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") ? "max-width" : "small-max-width"
|
||||
}
|
||||
|
||||
function submitForm() {
|
||||
const values = Object.entries($formValues).map((entry) => {
|
||||
return [
|
||||
entry[0],
|
||||
!entry[0].includes("numberLabel")
|
||||
? [entry[1].checked || entry[1].value, entry[1].required]
|
||||
: [entry[1].value, entry[1], entry[1].getAttribute("name"), entry[1].required],
|
||||
]
|
||||
})
|
||||
|
||||
const fields = values.filter((entry) => !entry[0].includes("label"))
|
||||
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] as string
|
||||
label?.appendChild(errorElement)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
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]
|
||||
}
|
||||
})
|
||||
let form: any
|
||||
row.column.forEach((col) => {
|
||||
if (col.contentType == "form") form = col
|
||||
})
|
||||
if (!form) return
|
||||
formObj["formRows"] = form.formRows.map((r: FormRow) => r.rowName)
|
||||
formObj["formTitle"] = form.formEmailTitle
|
||||
formSend = true
|
||||
const hny = document.getElementById("hny") as HTMLInputElement
|
||||
if (hny) formObj["honey"] = hny.checked
|
||||
sendForm(formObj)
|
||||
}
|
||||
}
|
||||
let innerWidth = window.innerWidth
|
||||
</script>
|
||||
|
||||
<main class="row" name="{row.title}" class:max-width="{getRowClass(row) === 'max-width'}" id="{`RowNr` + rowNr}">
|
||||
@@ -112,63 +51,7 @@
|
||||
<GoogleMaps />
|
||||
{/if}
|
||||
{:else if col.contentType == "form"}
|
||||
{#if formSend}
|
||||
<div class="success-message">
|
||||
<h1>Formular erfolgreich gesendet!</h1>
|
||||
<p>Vielen Dank für Ihre Anfrage. Wir werden uns in Kürze bei Ihnen melden.</p>
|
||||
</div>
|
||||
{:else}
|
||||
<form
|
||||
class="form-rows"
|
||||
on:submit="{(e) => {
|
||||
e.preventDefault()
|
||||
submitForm()
|
||||
}}"
|
||||
>
|
||||
{#each col.formRows ?? [] as formRow, i}
|
||||
{#if innerWidth < 768}
|
||||
<MobileForm formRow="{formRow}" formValues="{formValues}" index="{i}" />
|
||||
{:else}
|
||||
<Form formRow="{formRow}" formValues="{formValues}" index="{i}" />
|
||||
{/if}
|
||||
{/each}
|
||||
<div class="row additional">
|
||||
<div class="data-protection">
|
||||
<label bind:this="{$formValues[`agreement_label`]}">
|
||||
<input
|
||||
required="{true}"
|
||||
class="checkit"
|
||||
type="checkbox"
|
||||
on:change="{(e) => {
|
||||
let element = e.currentTarget
|
||||
element.classList.remove('invalid')
|
||||
}}"
|
||||
bind:this="{$formValues['agreement']}"
|
||||
/>
|
||||
<span class="checkit-span"></span>
|
||||
</label>
|
||||
|
||||
<div class="datasec">
|
||||
<button on:click|preventDefault="{() => navigate('/datenschutz')}" class="link">
|
||||
Datenschutz
|
||||
</button>
|
||||
akzeptieren
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="checkbox"
|
||||
name="contact_me_by_fax_only"
|
||||
id="hny"
|
||||
value="1"
|
||||
style="display:none !important"
|
||||
tabindex="-1"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<button class="submit-request" type="submit">Anfrage absenden</button>
|
||||
</div>
|
||||
</form>
|
||||
{/if}
|
||||
<Formular col="{col}" siteId="{siteId}" rowNr="{rowNr}" row="{row}" rows="{rows}" />
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
@@ -176,45 +59,6 @@
|
||||
|
||||
<style lang="less" global>
|
||||
@import "../../assets/css/variables.less";
|
||||
.wave-placeholder {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
.data-protection {
|
||||
margin: 5px 0px;
|
||||
box-shadow: 0 0 25px 10px var(--opposite-bg-color-5);
|
||||
}
|
||||
|
||||
.success-message {
|
||||
h1 {
|
||||
color: var(--heading-font-color);
|
||||
font-size: 36px;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
.invalidBlocks {
|
||||
border: 2px solid rgb(255, 0, 0) !important;
|
||||
position: relative;
|
||||
&::after {
|
||||
font-size: 0.9rem !important;
|
||||
color: red !important;
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
content: "Bitte wähle entweder eine Kartenanzahl oder einen Wunschbetrag aus.";
|
||||
}
|
||||
}
|
||||
|
||||
.border-red {
|
||||
border-color: red !important;
|
||||
}
|
||||
|
||||
.row-title {
|
||||
font-size: 1.6rem;
|
||||
@@ -234,15 +78,6 @@
|
||||
margin-top: 15px !important;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
border-bottom: 2px solid red !important;
|
||||
}
|
||||
.error-message {
|
||||
font-size: 0.9rem !important;
|
||||
color: red !important;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.row {
|
||||
width: 100%;
|
||||
padding: 0px 0px 15px 0;
|
||||
@@ -251,18 +86,6 @@
|
||||
align-items: center;
|
||||
max-width: @body-small-maxwidth;
|
||||
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none; /* Remove default bullet points */
|
||||
padding: 0;
|
||||
@@ -290,175 +113,6 @@
|
||||
& > h3 {
|
||||
width: 100%;
|
||||
}
|
||||
.checkit {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.checkit-span {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
border: 1px solid grey;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
[type="checkbox"]:checked + span:before {
|
||||
content: "\2714";
|
||||
position: absolute;
|
||||
transform-origin: bottom;
|
||||
}
|
||||
&.additional {
|
||||
display: flex;
|
||||
|
||||
@media @mobile {
|
||||
flex-direction: column;
|
||||
}
|
||||
@media @tablet {
|
||||
flex-direction: row;
|
||||
}
|
||||
gap: 2.5rem;
|
||||
div {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
}
|
||||
.submit-request {
|
||||
flex: 1;
|
||||
box-shadow: 0 0 25px 10px var(--opposite-bg-color-5);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
background-color: var(--heading-font-color);
|
||||
color: var(--background-color);
|
||||
padding: 10px 20px;
|
||||
}
|
||||
}
|
||||
.form-rows {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
gap: 1.5rem;
|
||||
width: 100%;
|
||||
h3 {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: 1.5rem;
|
||||
|
||||
.date {
|
||||
max-width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
label {
|
||||
width: 100% !important;
|
||||
font-size: inherit;
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
width: 100%;
|
||||
font-size: inherit;
|
||||
}
|
||||
}
|
||||
.form-cols {
|
||||
display: flex;
|
||||
gap: 1.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.form-column {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
gap: 1rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--hover-color);
|
||||
}
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
.data-protection {
|
||||
padding: 10px 20px;
|
||||
border: 0px solid var(--opposite-bg-color);
|
||||
border-bottom: 3px solid var(--heading-font-color);
|
||||
outline: 0px solid var(--opposite-bg-color);
|
||||
color: var(--opposite-bg-color);
|
||||
background-color: var(--background-color);
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.data-protection {
|
||||
display: flex;
|
||||
|
||||
flex-wrap: nowrap;
|
||||
gap: 5px !important;
|
||||
justify-content: start;
|
||||
flex-direction: row !important;
|
||||
}
|
||||
|
||||
input[type="date"] {
|
||||
font-family: inherit;
|
||||
width: 100% !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
select {
|
||||
padding: 10px 20px;
|
||||
border: 0;
|
||||
border-bottom: 3px solid var(--heading-font-color);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
select:focus {
|
||||
border-bottom-color: var(--heading-font-color);
|
||||
}
|
||||
|
||||
#time-select {
|
||||
appearance: none;
|
||||
background-image: url("../../../../media/clock.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 20px center;
|
||||
background-size: 18px;
|
||||
|
||||
option {
|
||||
padding: 10px 20px;
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
}
|
||||
@media @mobile {
|
||||
.date {
|
||||
width: 100vw !important;
|
||||
}
|
||||
}
|
||||
@media @tablet {
|
||||
.date {
|
||||
width: 100% !important;
|
||||
}
|
||||
.form-cols {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media @mobile {
|
||||
.no-gap {
|
||||
@@ -507,17 +161,4 @@
|
||||
.max-width {
|
||||
max-width: @body-maxwidth !important;
|
||||
}
|
||||
|
||||
.datasec {
|
||||
display: flex;
|
||||
align-items: center !important;
|
||||
.link {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: flex-end !important;
|
||||
text-decoration: underline;
|
||||
margin-right: 3px;
|
||||
color: rgb(14, 91, 146);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
register(false)
|
||||
let swiper: any
|
||||
console.log("TST RENDERED")
|
||||
onMount(async () => {
|
||||
if (swiper) {
|
||||
const response = await fetch("/dist/index.css")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function validateFields(fieldsArray: (string | boolean | any[])[][]): (string | (() => void))[][] {
|
||||
export function validateFields(fieldsArray: ValueEntry[]): (string | (() => void))[][] {
|
||||
const errors = []
|
||||
let selectedGroup: number
|
||||
const numberRegex = /^[+]?([.]\d+|\d+([.]\d+)?)$/
|
||||
@@ -23,18 +23,20 @@ export function validateFields(fieldsArray: (string | boolean | any[])[][]): (st
|
||||
if (field === "blockGroups" || (typeof field === "string" && field.includes("numberLabel"))) {
|
||||
if (!field.includes("numberLabel")) return
|
||||
// @ts-ignore
|
||||
const [elementValue, element, group, boolean] = value
|
||||
let [elementValue, element, group, boolean] = value
|
||||
element = element as HTMLElement
|
||||
if (!elementValue) return
|
||||
if (selectedGroup !== undefined) {
|
||||
if (group !== selectedGroup) errors.push(["block", wholeBlockInvalid])
|
||||
if (group !== String(selectedGroup)) errors.push(["block", wholeBlockInvalid])
|
||||
else validateNumber(elementValue, field, element)
|
||||
} else {
|
||||
//@ts-ignore
|
||||
selectedGroup = group
|
||||
validateNumber(elementValue, field, element)
|
||||
}
|
||||
return
|
||||
}
|
||||
value = value as any[]
|
||||
value = value
|
||||
let required = value[1]
|
||||
value = value[0]
|
||||
if (!required && !value) return
|
||||
@@ -43,16 +45,16 @@ export function validateFields(fieldsArray: (string | boolean | any[])[][]): (st
|
||||
} 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_")) {
|
||||
} else if (field.includes("agreement_") && typeof value == "boolean") {
|
||||
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])
|
||||
} else if (field.includes("Email_") && typeof value == "string") {
|
||||
if (!emailRegex.test(value)) errors.push(["Ungültiges E-Mail-Format.", field])
|
||||
} else if (field.includes("date_") && typeof value == "string") {
|
||||
if (!dateRegex.test(value)) errors.push(["Ungültiges Datumsformat.", field])
|
||||
} else if (field.includes("times_") && typeof value == "string") {
|
||||
if (!timeRegex.test(value) && typeof value == "string") errors.push(["Ungültiges Zeitformat.", field])
|
||||
} else if (field.includes("Telefon_") && typeof value == "string") {
|
||||
if (!phoneRegex.test(value)) errors.push(["Ungültiges Telefonnummernformat.", field])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -14,4 +14,4 @@ export let navigation = writable<Navigation>()
|
||||
export let sites = writable<Sites>({})
|
||||
export let serviceNavigation = writable<Navigation>()
|
||||
export let banner = writable<Banner[]>([])
|
||||
export let temperature = writable<Temperature>()
|
||||
export let darkMode = writable<boolean>(false)
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
let site: Site
|
||||
function getSelectedSite(path: string): Site | {} {
|
||||
let site = {}
|
||||
console.log($sites, "sites")
|
||||
if (Object.values($sites).length == 0) return {}
|
||||
Object.values($sites).forEach((element) => {
|
||||
if (element.path == "/" + path) site = element
|
||||
|
||||
Reference in New Issue
Block a user