form
All checks were successful
deploy to production / deploy (push) Successful in 49s

This commit is contained in:
2023-09-24 09:38:03 +00:00
parent 7813f0b486
commit eee191955e
32 changed files with 1091 additions and 518 deletions

View File

@@ -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;

View File

@@ -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%;

View File

@@ -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;

View File

@@ -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 {

View 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>

View 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>

View File

@@ -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>

View 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>

View File

@@ -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>

View File

@@ -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}

View File

@@ -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>

View File

@@ -7,7 +7,6 @@
register(false)
let swiper: any
console.log("TST RENDERED")
onMount(async () => {
if (swiper) {
const response = await fetch("/dist/index.css")