This commit is contained in:
BIN
.yarn/cache/fluent-svelte-npm-1.6.0-b51efa5efd-1b2ac33343.zip
vendored
Normal file
BIN
.yarn/cache/fluent-svelte-npm-1.6.0-b51efa5efd-1b2ac33343.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/focus-trap-npm-6.9.4-64b032bc16-0b4cebcc11.zip
vendored
Normal file
BIN
.yarn/cache/focus-trap-npm-6.9.4-64b032bc16-0b4cebcc11.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/tabbable-npm-5.3.3-baf35cffe9-1aa56e1bb6.zip
vendored
Normal file
BIN
.yarn/cache/tabbable-npm-5.3.3-baf35cffe9-1aa56e1bb6.zip
vendored
Normal file
Binary file not shown.
@@ -361,6 +361,12 @@ subFields:
|
|||||||
type: string
|
type: string
|
||||||
meta:
|
meta:
|
||||||
label: Zeilenname
|
label: Zeilenname
|
||||||
|
|
||||||
|
- name: showRowName
|
||||||
|
type: boolean
|
||||||
|
meta:
|
||||||
|
label: Zeilenname anzeigen
|
||||||
|
|
||||||
- name: columns
|
- name: columns
|
||||||
type: object[]
|
type: object[]
|
||||||
|
|
||||||
@@ -598,6 +604,97 @@ subFields:
|
|||||||
dependsOn:
|
dependsOn:
|
||||||
eval: $parent?.showNumber
|
eval: $parent?.showNumber
|
||||||
|
|
||||||
|
- name: showCheckboxGroup
|
||||||
|
type: boolean
|
||||||
|
meta:
|
||||||
|
label: Checkbox Gruppe Anzeigen
|
||||||
|
|
||||||
|
- name: groupTitle
|
||||||
|
type: string
|
||||||
|
meta:
|
||||||
|
label: Checkbox Gruppe Titel
|
||||||
|
dependsOn:
|
||||||
|
eval: $parent.showCheckboxGroup
|
||||||
|
|
||||||
|
- name: checkboxes
|
||||||
|
type: object[]
|
||||||
|
meta:
|
||||||
|
label: Checkbox Gruppe
|
||||||
|
dependsOn:
|
||||||
|
eval: $parent.showCheckboxGroup
|
||||||
|
direction: row
|
||||||
|
subFields:
|
||||||
|
- name: name
|
||||||
|
type: string
|
||||||
|
meta:
|
||||||
|
label: Name
|
||||||
|
|
||||||
|
- name: emailName
|
||||||
|
type: string
|
||||||
|
meta:
|
||||||
|
label: Email Name
|
||||||
|
|
||||||
|
- name: showDatePicker
|
||||||
|
type: boolean
|
||||||
|
meta:
|
||||||
|
label: Datumauswahl anzeigen
|
||||||
|
- name: datePickerEmailTitle
|
||||||
|
type: string
|
||||||
|
meta:
|
||||||
|
label: Datumauswahl Email Titel
|
||||||
|
dependsOn:
|
||||||
|
eval: $parent.showDatePicker
|
||||||
|
|
||||||
|
- name: datePickerNotRequired
|
||||||
|
type: boolean
|
||||||
|
meta:
|
||||||
|
label: nicht Notwendig
|
||||||
|
dependsOn:
|
||||||
|
eval: $parent.showDatePicker
|
||||||
|
|
||||||
|
- name: datePickerProps
|
||||||
|
type: object
|
||||||
|
meta:
|
||||||
|
label: Datumauswahl Eigenschaften
|
||||||
|
dependsOn:
|
||||||
|
eval: $parent.showDatePicker
|
||||||
|
subFields:
|
||||||
|
- name: allowedDateRanges
|
||||||
|
type: object[]
|
||||||
|
meta:
|
||||||
|
label: Erlaubte Datumsbereiche
|
||||||
|
subFields:
|
||||||
|
- name: from
|
||||||
|
type: date
|
||||||
|
meta:
|
||||||
|
label: Von
|
||||||
|
widget: date
|
||||||
|
- name: to
|
||||||
|
type: date
|
||||||
|
meta:
|
||||||
|
label: Bis
|
||||||
|
widget: date
|
||||||
|
- name: excludeDays
|
||||||
|
type: string[]
|
||||||
|
meta:
|
||||||
|
label: Auszuschließende Wochentage
|
||||||
|
widget: selectArray
|
||||||
|
choices:
|
||||||
|
- id: monday
|
||||||
|
name: Montag
|
||||||
|
- id: tuesday
|
||||||
|
name: Dienstag
|
||||||
|
- id: wednesday
|
||||||
|
name: Mittwoch
|
||||||
|
- id: thursday
|
||||||
|
name: Donnerstag
|
||||||
|
- id: friday
|
||||||
|
name: Freitag
|
||||||
|
- id: saturday
|
||||||
|
name: Samstag
|
||||||
|
- id: sunday
|
||||||
|
name: Sonntag
|
||||||
|
|
||||||
- name: text
|
- name: text
|
||||||
type: object[]
|
type: object[]
|
||||||
meta:
|
meta:
|
||||||
@@ -614,6 +711,12 @@ subFields:
|
|||||||
meta:
|
meta:
|
||||||
label: Platzhalter für das leere Eingabefeld
|
label: Platzhalter für das leere Eingabefeld
|
||||||
|
|
||||||
|
- name: textTitle
|
||||||
|
type: string
|
||||||
|
meta:
|
||||||
|
label: Text Titel
|
||||||
|
helperText: Alternative zu textPlaceholder
|
||||||
|
|
||||||
- name: textArea
|
- name: textArea
|
||||||
type: boolean
|
type: boolean
|
||||||
meta:
|
meta:
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
const { validateFields } = require("./validateFields")
|
const { validateFields } = require("./validateFields")
|
||||||
;(function () {
|
;(function () {
|
||||||
if (context.data.formular.honey) {
|
if (context?.data?.formular?.honey) {
|
||||||
throw { status: 400, error: "Bot detection" }
|
throw { status: 400, error: "Bot detection" }
|
||||||
}
|
}
|
||||||
delete context.data.formular.honey
|
delete context.data.formular.honey
|
||||||
let values = Object.entries(context.data.formular)
|
/**
|
||||||
|
* @type {Array<[string, FormObj]>}
|
||||||
|
*/
|
||||||
|
let values = Object.entries(context?.data?.formular)
|
||||||
let validation = validateFields(values)
|
let validation = validateFields(values)
|
||||||
console.log(validation)
|
|
||||||
if (validation.length) {
|
if (validation.length) {
|
||||||
throw { status: 400, error: validation }
|
throw { status: 400, error: validation }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,54 @@
|
|||||||
var utils = require("../lib/utils")
|
|
||||||
var config = require("../config")
|
|
||||||
|
|
||||||
;(function () {
|
;(function () {
|
||||||
let formular = context.data.formular
|
/** @type {FormObj} */
|
||||||
|
let formular = context?.data?.formular
|
||||||
|
|
||||||
|
/** @type {TempFormBefore | TempFormAfter} */
|
||||||
let tempForm = {}
|
let tempForm = {}
|
||||||
|
|
||||||
let formTitle = `${formular.formTitle}`
|
let formTitle = `${formular.formTitle}`
|
||||||
delete formular.formTitle
|
delete formular.formTitle
|
||||||
delete formular["agreement"]
|
delete formular["agreement"]
|
||||||
delete formular["honey"]
|
delete formular["honey"]
|
||||||
formular.formRows.forEach((rowName, i) => {
|
|
||||||
tempForm[rowName] = {}
|
formular?.formRows?.forEach(
|
||||||
})
|
/** @param {string} rowName */
|
||||||
|
(rowName) => {
|
||||||
|
tempForm[rowName] = {}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {[string, any]} e
|
||||||
|
* @returns {any}
|
||||||
|
*/
|
||||||
let getValue = (e) => {
|
let getValue = (e) => {
|
||||||
if (e[0].includes("numberLabel")) return e[1][0]
|
if (e[0].includes("numberLabel")) return e[1][0]
|
||||||
return e[1]
|
return e[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @type {TempFormIndices} */
|
||||||
let indices = {}
|
let indices = {}
|
||||||
|
|
||||||
Object.entries(formular).forEach((e) => {
|
Object.entries(formular).forEach((e) => {
|
||||||
if (e[0] == "formRows") return
|
if (e[0] === "formRows") return
|
||||||
|
|
||||||
let key = e[0].split("_")
|
let key = e[0].split("_")
|
||||||
let newKey = key[key.length - 1]
|
let newKey = key[key.length - 1]
|
||||||
let rowName = formular.formRows[Number(key[key.length - 2])]
|
|
||||||
|
// @ts-ignore
|
||||||
|
let rowName = formular?.formRows[Number(key[key.length - 2])]
|
||||||
let index = isNaN(Number(key[key.length - 3])) ? 100 : Number(key[key.length - 3])
|
let index = isNaN(Number(key[key.length - 3])) ? 100 : Number(key[key.length - 3])
|
||||||
|
|
||||||
if (!rowName) return
|
if (!rowName) return
|
||||||
if (!tempForm[rowName]) tempForm[rowName] = {}
|
if (!tempForm[rowName]) tempForm[rowName] = {}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
if (tempForm[rowName][newKey]) {
|
if (tempForm[rowName][newKey]) {
|
||||||
|
// @ts-ignore
|
||||||
tempForm[rowName][newKey][0] += "\\" + getValue(e)
|
tempForm[rowName][newKey][0] += "\\" + getValue(e)
|
||||||
} else {
|
} else {
|
||||||
tempForm[rowName][newKey] = [getValue(e), newKey[0] == "n", newKey.includes("invalid")]
|
// @ts-ignore
|
||||||
|
tempForm[rowName][newKey] = [getValue(e), newKey[0] === "n", newKey.includes("invalid")]
|
||||||
indices[rowName] = { ...indices[rowName], [newKey]: index }
|
indices[rowName] = { ...indices[rowName], [newKey]: index }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -40,12 +59,12 @@ var config = require("../config")
|
|||||||
.sort((a, b) => indices[rowName][a[0]] - indices[rowName][b[0]])
|
.sort((a, b) => indices[rowName][a[0]] - indices[rowName][b[0]])
|
||||||
.reduce((acc, [key, val]) => ({ ...acc, [key]: val }), {})
|
.reduce((acc, [key, val]) => ({ ...acc, [key]: val }), {})
|
||||||
})
|
})
|
||||||
console.log(JSON.stringify(tempForm), JSON.stringify(indices))
|
|
||||||
|
|
||||||
Object.keys(tempForm).forEach((row) => {
|
Object.keys(tempForm).forEach((row) => {
|
||||||
tempForm[row] = Object.entries(tempForm[row])
|
tempForm[row] = Object.entries(tempForm[row])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
delete tempForm[undefined]
|
delete tempForm[undefined]
|
||||||
context.smtp.sendMail({
|
context.smtp.sendMail({
|
||||||
to: "binkrassdufass@gmail.com",
|
to: "binkrassdufass@gmail.com",
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* @param {Array<[string, FormObj]>} fieldsArray
|
||||||
|
* @returns {(string | (() => void))[][]}
|
||||||
|
*/
|
||||||
function validateFields(fieldsArray) {
|
function validateFields(fieldsArray) {
|
||||||
|
/**@type {(string | (() => void))[][]} */
|
||||||
const errors = []
|
const errors = []
|
||||||
|
/**@type {number} */
|
||||||
let selectedGroup
|
let selectedGroup
|
||||||
|
|
||||||
const numberRegex = /^[+]?([.]\d+|\d+([.]\d+)?)$/
|
const numberRegex = /^[+]?([.]\d+|\d+([.]\d+)?)$/
|
||||||
@@ -14,6 +20,12 @@ function validateFields(fieldsArray) {
|
|||||||
blockContainer.classList.add("invalidBlocks")
|
blockContainer.classList.add("invalidBlocks")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} value
|
||||||
|
* @param {any} field
|
||||||
|
* @param {HTMLElement} element
|
||||||
|
*/
|
||||||
const validateNumber = (value, field, element) => {
|
const validateNumber = (value, field, element) => {
|
||||||
if (!numberRegex.test(`${value}`)) {
|
if (!numberRegex.test(`${value}`)) {
|
||||||
errors.push(["block", () => element.classList.add("border-red")])
|
errors.push(["block", () => element.classList.add("border-red")])
|
||||||
@@ -23,6 +35,7 @@ function validateFields(fieldsArray) {
|
|||||||
fieldsArray.forEach(([field, value]) => {
|
fieldsArray.forEach(([field, value]) => {
|
||||||
if (field === "blockGroups" || field.includes("numberLabel")) {
|
if (field === "blockGroups" || field.includes("numberLabel")) {
|
||||||
if (!field.includes("numberLabel")) return
|
if (!field.includes("numberLabel")) return
|
||||||
|
// @ts-ignore
|
||||||
const [elementValue, element, group] = value
|
const [elementValue, element, group] = value
|
||||||
|
|
||||||
if (!elementValue) return
|
if (!elementValue) return
|
||||||
|
|||||||
24
frontend/media/dark.svg
Normal file
24
frontend/media/dark.svg
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
width="800px" height="800px" viewBox="0 0 512 512" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
<![CDATA[
|
||||||
|
.st0{fill:#000000;}
|
||||||
|
]]>
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M403.469,395.031c-129.203,0-233.938-104.75-233.938-233.953c0-62.438,24.5-119.125,64.375-161.078
|
||||||
|
C109.313,17.953,13.563,125.094,13.563,254.656C13.563,396.781,128.781,512,270.906,512c98.688,0,184.359-55.578,227.531-137.125
|
||||||
|
C469.406,387.781,437.297,395.031,403.469,395.031z"/>
|
||||||
|
<path class="st0" d="M349.641,179.328c1.047,1.016,1.516,2.484,1.266,3.922l-8.563,49.938c-0.281,1.672,0.406,3.344,1.766,4.344
|
||||||
|
c1.359,0.984,3.156,1.109,4.656,0.328l44.859-23.578c1.281-0.688,2.813-0.688,4.109,0l44.859,23.578
|
||||||
|
c1.484,0.781,3.297,0.656,4.656-0.328c1.359-1,2.031-2.672,1.75-4.344l-8.563-49.938c-0.25-1.438,0.219-2.906,1.266-3.922
|
||||||
|
L478,143.969c1.203-1.172,1.641-2.938,1.125-4.531c-0.531-1.594-1.906-2.781-3.578-3.016l-50.141-7.297
|
||||||
|
c-1.438-0.203-2.688-1.109-3.344-2.406l-22.422-45.453c-0.734-1.516-2.281-2.453-3.969-2.453c-1.672,0-3.219,0.938-3.953,2.453
|
||||||
|
l-22.438,45.453c-0.641,1.297-1.891,2.203-3.328,2.406l-50.141,7.297c-1.672,0.234-3.063,1.422-3.578,3.016
|
||||||
|
s-0.078,3.359,1.125,4.531L349.641,179.328z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
2
frontend/media/light.svg
Normal file
2
frontend/media/light.svg
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="#ffffff"><circle cx="32" cy="32" r="16"/><line x1="32" y1="8" x2="32" y2="16"/><line x1="32" y1="56" x2="32" y2="48"/><line x1="56" y1="32" x2="48" y2="32"/><line x1="8" y1="32" x2="16" y2="32"/><line x1="48.97" y1="15.03" x2="43.31" y2="20.69"/><line x1="15.03" y1="48.97" x2="20.69" y2="43.31"/><line x1="48.97" y1="48.97" x2="43.31" y2="43.31"/><line x1="15.03" y1="15.03" x2="20.69" y2="20.69"/></svg>
|
||||||
|
After Width: | Height: | Size: 634 B |
@@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<svg viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg">
|
<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.985044002532959, 0, 0, 5, 1419.3128662109375, 549.1923828125)" id="495873" style="">
|
||||||
<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%">
|
<filter id="SVGID_40" y="-20%" height="140%" x="-20%" width="140%">
|
||||||
<feGaussianBlur in="SourceAlpha" stdDeviation="0"/>
|
<feGaussianBlur in="SourceAlpha" stdDeviation="0"/>
|
||||||
<feOffset dx="0" dy="0" result="oBlur"/>
|
<feOffset dx="0" dy="0" result="oBlur"/>
|
||||||
@@ -12,6 +11,10 @@
|
|||||||
<feMergeNode in="SourceGraphic"/>
|
<feMergeNode in="SourceGraphic"/>
|
||||||
</feMerge>
|
</feMerge>
|
||||||
</filter>
|
</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)"/>
|
<path style="stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill-rule: nonzero; opacity: 1; filter: url('#SVGID_40'); stroke-width: 0px; stroke: rgb(131, 89, 89); paint-order: stroke; fill: rgb(255, 0, 0);" vector-effect="non-scaling-stroke" d="M -171.628 -28.919 L -149.65 15.437 L -169.43 15.437 L -183.816 -13.934 L -206.593 16.236 L -206.593 90.162 L -224.575 90.162 L -224.575 0.252 L -206.593 -30.318 L -206.593 -5.143 C -206.593 -4.057 -136.463 -109.109 -136.463 -109.838 L -115.684 -109.838 L -152.647 -55.293 L -171.628 -28.919" stroke-linecap="round"/>
|
||||||
|
<path style="stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill-rule: nonzero; opacity: 1; filter: url('#SVGID_40'); stroke-width: 0px; stroke: rgb(131, 89, 89); paint-order: stroke; fill: rgb(255, 0, 0);" vector-effect="non-scaling-stroke" d="M -113.486 90.162 L -134.065 90.162 L -160.839 33.019 L -140.859 33.019 L -113.486 90.162 Z" stroke-linecap="round"/>
|
||||||
|
<path style="stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill-rule: nonzero; opacity: 1; filter: url('#SVGID_40'); stroke-width: 0px; stroke: rgb(131, 89, 89); paint-order: stroke; fill: rgb(255, 255, 0);" vector-effect="non-scaling-stroke" d="M -84.115 64.787 L -103.696 64.787 L -123.476 31.221 L -204.595 31.221 L -204.595 17.235 L -131.868 17.235 L -163.636 -36.711 L -152.847 -51.896 L -84.115 64.787 Z" stroke-linecap="round"/>
|
||||||
|
<path style="stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill-rule: nonzero; opacity: 1; filter: url('#SVGID_40'); stroke-width: 0px; stroke: rgb(131, 89, 89); paint-order: stroke; fill: rgb(255, 255, 0);" vector-effect="non-scaling-stroke" d="M -164.035 -71.277 L -174.625 -55.492 L -184.215 -71.676 L -236.763 17.235 L -226.373 17.235 L -226.373 31.221 L -245.154 31.221 L -264.934 64.787 L -284.715 64.787 L -197.002 -84.064 L -184.683 -105.283 L -171.828 -84.064 L -164.035 -71.277 Z" stroke-linecap="round"/>
|
||||||
|
<path style="stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill-rule: nonzero; opacity: 1; filter: url('#SVGID_40'); stroke-width: 0px; stroke: rgb(131, 89, 89); paint-order: stroke; fill: rgb(255, 0, 0);" vector-effect="non-scaling-stroke" d="M -206.593 -109.838 L -206.593 -71.676 L -224.575 -40.907 L -224.575 -109.838 L -206.593 -109.838 Z" stroke-linecap="round"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 3.2 KiB |
@@ -17,7 +17,7 @@
|
|||||||
<!--HEAD-->
|
<!--HEAD-->
|
||||||
<!--PRELOAD-->
|
<!--PRELOAD-->
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body class="">
|
||||||
<div id="appContainer"><!--HTML--></div>
|
<div id="appContainer"><!--HTML--></div>
|
||||||
<script type="module" src="/dist/index.mjs?t=__TIMESTAMP__"></script>
|
<script type="module" src="/dist/index.mjs?t=__TIMESTAMP__"></script>
|
||||||
<script nomodule src="/dist/index.es5.js?t=__TIMESTAMP__"></script>
|
<script nomodule src="/dist/index.es5.js?t=__TIMESTAMP__"></script>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<script lang="ts">
|
<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 Header from "./lib/components/header/Header.svelte"
|
||||||
|
import "fluent-svelte/theme.css"
|
||||||
|
|
||||||
import Footer from "./lib/components/Footer.svelte"
|
import Footer from "./lib/components/Footer.svelte"
|
||||||
import { Route, Router } from "svelte-routing"
|
import { Route, Router } from "svelte-routing"
|
||||||
import HomePage from "./routes/HomePage.svelte"
|
import HomePage from "./routes/HomePage.svelte"
|
||||||
@@ -44,7 +46,6 @@
|
|||||||
sitesRes[e.id] = e
|
sitesRes[e.id] = e
|
||||||
})
|
})
|
||||||
$sites = sitesRes
|
$sites = sitesRes
|
||||||
console.log("ALARM OVER", $sites)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getNavigation()
|
getNavigation()
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
width: 0;
|
width: 0;
|
||||||
bottom: -2px;
|
bottom: -2px;
|
||||||
background: var(--background-color);
|
background: var(--heading-font-color);
|
||||||
height: 4px;
|
height: 4px;
|
||||||
transition: width 0.5s ease-in;
|
transition: width 0.5s ease-in;
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.fill:hover {
|
.fill:hover {
|
||||||
color: var(--background-color) !important;
|
color: var(--heading-font-color) !important;
|
||||||
div {
|
div {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
top: 0px;
|
top: 0px;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
width: 0px;
|
width: 0px;
|
||||||
background: var(--opposite-bg-color);
|
background: var(--heading-font-color);
|
||||||
transition: width 0.5s ease-in;
|
transition: width 0.5s ease-in;
|
||||||
}
|
}
|
||||||
.fill:hover:after,
|
.fill:hover:after,
|
||||||
@@ -78,7 +78,7 @@ swiper-slide {
|
|||||||
z-index: 10000;
|
z-index: 10000;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
bottom: -10px;
|
bottom: -10px;
|
||||||
background: var(--opposite-bg-color);
|
background: var(--heading-font-color);
|
||||||
height: 5px;
|
height: 5px;
|
||||||
width: 0;
|
width: 0;
|
||||||
animation: underlineEffect 4s linear forwards;
|
animation: underlineEffect 4s linear forwards;
|
||||||
@@ -95,7 +95,7 @@ swiper-slide {
|
|||||||
|
|
||||||
.swiper-button-prev,
|
.swiper-button-prev,
|
||||||
.swiper-button-next {
|
.swiper-button-next {
|
||||||
color: var(--normal-font-color) !important;
|
color: var(--heading-font-color) !important;
|
||||||
height: 70px !important;
|
height: 70px !important;
|
||||||
width: 70px !important;
|
width: 70px !important;
|
||||||
bottom: 0px !important;
|
bottom: 0px !important;
|
||||||
@@ -136,7 +136,7 @@ swiper-slide {
|
|||||||
@media @desktop {
|
@media @desktop {
|
||||||
.swiper-button-prev,
|
.swiper-button-prev,
|
||||||
.swiper-button-next {
|
.swiper-button-next {
|
||||||
top: 125px !important;
|
top: 155px !important;
|
||||||
transform: scale(1) !important;
|
transform: scale(1) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,35 @@
|
|||||||
:root {
|
:root {
|
||||||
--background-color: white;
|
--background-color: rgb(235, 221, 221);
|
||||||
--background-color-90: #ffffffe6;
|
--background-color-90: #ffffffe6;
|
||||||
--normal-font-color: #333333;
|
--normal-font-color: #333333;
|
||||||
--normal-font-color-12: rgba(51, 51, 51, 0.12);
|
--normal-font-color-12: rgba(51, 51, 51, 0.12);
|
||||||
--hover-color: #dee2e6;
|
--normal-font-color-80: rgba(51, 51, 51, 0.8);
|
||||||
--heading-font-color: #672129;
|
--normal-font-color-50: rgba(51, 51, 51, 0.5);
|
||||||
--link-font-color: #672129;
|
--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;
|
--banner-color: #06d6a0;
|
||||||
--opposite-bg-color: #000;
|
--opposite-bg-color: #000;
|
||||||
--opposite-bg-color-80: rgba(0, 0, 0, 0.8);
|
--opposite-bg-color-80: rgba(24, 24, 24, 0.8);
|
||||||
--opposite-bg-color-5: rgba(0, 0, 0, 0.05);
|
--opposite-bg-color-5: rgba(24, 24, 24, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.darkTheme {
|
body.darkTheme {
|
||||||
--background-color: #1a1a1a; /* softer than #121212 */
|
--background-color: #1a1a1a; /* softer than #121212 */
|
||||||
--background-color-90: rgba(26, 26, 26, 0.9);
|
--background-color-90: rgba(26, 26, 26, 0.9);
|
||||||
--normal-font-color: #d1d1d1; /* off-white, less harsh */
|
--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);
|
--normal-font-color-12: rgba(209, 209, 209, 0.12);
|
||||||
--hover-color: #404040; /* subtle change for hover */
|
--hover-color: #404040; /* subtle change for hover */
|
||||||
--heading-font-color: #9fb3c7; /* slightly brighter for better readability */
|
--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 */
|
--banner-color: #04a577; /* a cooler shade for the banner */
|
||||||
--opposite-bg-color: #fafafa; /* off-white */
|
--opposite-bg-color: #fafafa; /* off-white */
|
||||||
--opposite-bg-color-80: rgba(250, 250, 250, 0.8);
|
--opposite-bg-color-80: rgba(250, 250, 250, 0.8);
|
||||||
@@ -75,9 +85,8 @@ ol {
|
|||||||
|
|
||||||
/* Links */
|
/* Links */
|
||||||
a {
|
a {
|
||||||
color: var(--link-font-color);
|
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
font-weight: 700;
|
color: var(--normal-font-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tabellen */
|
/* Tabellen */
|
||||||
@@ -92,16 +101,6 @@ table {
|
|||||||
right 0.5s ease, transform 0.5s ease;
|
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 {
|
button {
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
border: none;
|
border: none;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { navigate } from "svelte-routing"
|
import { navigate } from "svelte-routing"
|
||||||
import { serviceNavigation, sites } from "../stores"
|
import { serviceNavigation, sites, darkMode } from "../stores"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
@@ -37,12 +37,20 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
|
class="darklight"
|
||||||
on:click="{() => {
|
on:click="{() => {
|
||||||
const body = document.querySelector('body')
|
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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -51,6 +59,15 @@
|
|||||||
.social {
|
.social {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
.darklight {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
object-fit: contain;
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
.footer {
|
.footer {
|
||||||
margin-top: 60px;
|
margin-top: 60px;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { navigation, sites } from "../../stores"
|
import { darkMode, navigation, sites } from "../../stores"
|
||||||
|
|
||||||
import { apiBaseURL } from "../../../config"
|
import { apiBaseURL } from "../../../config"
|
||||||
import { navigate } from "svelte-routing"
|
import { navigate } from "svelte-routing"
|
||||||
@@ -60,9 +60,11 @@
|
|||||||
navigate('/')
|
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">
|
<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>
|
<p id="lower">SO GÜNSTIG WIE NACHHALTIG</p>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
@@ -202,12 +204,22 @@
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
& > #upper {
|
& > #upper {
|
||||||
font-family: "Orbitron" !important;
|
span {
|
||||||
font-size: 30px;
|
font-family: "Orbitron" !important;
|
||||||
font-weight: 700;
|
font-size: 31px;
|
||||||
|
font-weight: 700;
|
||||||
|
&.red {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
&.yellow {
|
||||||
|
color: yellow;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
& > #lower {
|
& > #lower {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: orange;
|
||||||
}
|
}
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
@@ -258,7 +270,7 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
z-index: 2000;
|
z-index: 2000;
|
||||||
background-color: var(--opposite-bg-color-80);
|
background-color: rgba(0, 0, 0, 0.849);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
.inner-container {
|
.inner-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function imageSlide(images: HTMLImageElement[]) {
|
function imageSlide(images: HTMLImageElement[]) {
|
||||||
console.log(images)
|
|
||||||
let currentImage = 0
|
let currentImage = 0
|
||||||
images[0].classList.add("show-img")
|
images[0].classList.add("show-img")
|
||||||
let interval = setInterval(() => {
|
let interval = setInterval(() => {
|
||||||
@@ -59,9 +58,11 @@
|
|||||||
navigate('/')
|
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">
|
<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>
|
<p id="lower">SO GÜNSTIG WIE NACHHALTIG</p>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
@@ -241,12 +242,22 @@
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
& > #upper {
|
& > #upper {
|
||||||
font-family: "Orbitron" !important;
|
span {
|
||||||
font-size: 24px;
|
font-family: "Orbitron" !important;
|
||||||
font-weight: 700;
|
font-size: 31px;
|
||||||
|
font-weight: 700;
|
||||||
|
&.red {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
&.yellow {
|
||||||
|
color: yellow;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
& > #lower {
|
& > #lower {
|
||||||
font-size: 10px;
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: orange;
|
||||||
}
|
}
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object.assign(swiper, params)
|
Object.assign(swiper, params)
|
||||||
console.log(swiper.getElementsByClassName("swiper-button-prev"), "test", swiper)
|
|
||||||
swiper.initialize()
|
swiper.initialize()
|
||||||
|
|
||||||
// Add the 'active' class to the h1 of the first slide
|
// Add the 'active' class to the h1 of the first slide
|
||||||
@@ -159,6 +158,7 @@
|
|||||||
line-height: 1;
|
line-height: 1;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
color: var(--heading-font-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
@@ -168,6 +168,7 @@
|
|||||||
}
|
}
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
color: var(--top-heading-font-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.description {
|
.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">
|
<script lang="ts">
|
||||||
|
import CheckboxGroup from "./checkboxGroup.svelte"
|
||||||
|
import Datepicker from "./datepicker.svelte"
|
||||||
import FormLabelNumberBlock from "./formLabelNumberBlock.svelte"
|
import FormLabelNumberBlock from "./formLabelNumberBlock.svelte"
|
||||||
import type { Writable } from "svelte/store"
|
import type { Writable } from "svelte/store"
|
||||||
|
|
||||||
@@ -24,6 +26,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
|
<h3 style="margin-bottom: -0.5rem;">
|
||||||
|
{#if formRow.showRowName}{formRow.rowName || ""}{/if}
|
||||||
|
</h3>
|
||||||
<div class="form-cols">
|
<div class="form-cols">
|
||||||
{#each formRow.columns as column, columnIndex}
|
{#each formRow.columns as column, columnIndex}
|
||||||
<div class="form-column">
|
<div class="form-column">
|
||||||
@@ -48,7 +53,7 @@
|
|||||||
on:change="{removeInvalid}"
|
on:change="{removeInvalid}"
|
||||||
>
|
>
|
||||||
<option value="" disabled selected>Bitte Uhrzeit wählen</option>
|
<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}">
|
<option value="{time?.timeFrom}-{time?.timeTo}">
|
||||||
{time?.timeFrom} - {time?.timeTo}
|
{time?.timeFrom} - {time?.timeTo}
|
||||||
</option>
|
</option>
|
||||||
@@ -114,49 +119,70 @@
|
|||||||
</label>
|
</label>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#each column.text || [] as textField, textFieldIndex}
|
{#if column.showCheckboxGroup}
|
||||||
{#if textField?.textArea}
|
<CheckboxGroup
|
||||||
<label bind:this="{$formValues[`textarea_Nachricht_label`]}">
|
checkboxes="{column.checkboxes}"
|
||||||
<textarea
|
groupTitle="{column.groupTitle}"
|
||||||
placeholder="{textField?.textPlaceholder}"
|
formValues="{formValues}"
|
||||||
required="{textField?.notRequired !== true}"
|
rowNr="{index}"
|
||||||
on:change="{removeInvalid}"
|
/>
|
||||||
|
{/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[
|
bind:this="{$formValues[
|
||||||
`textarea_Nachricht_${textField.textfieldOrder}_${index}_${
|
`input_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_label`
|
||||||
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}`
|
|
||||||
]}"
|
]}"
|
||||||
/>
|
>
|
||||||
</label>
|
<input
|
||||||
{/if}
|
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}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="less">
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import FormLabelNumberBlock from "./formLabelNumberBlock.svelte"
|
import FormLabelNumberBlock from "./formLabelNumberBlock.svelte"
|
||||||
import type { Writable } from "svelte/store"
|
import type { Writable } from "svelte/store"
|
||||||
|
import CheckboxGroup from "./checkboxGroup.svelte"
|
||||||
|
import Datepicker from "./datepicker.svelte"
|
||||||
export let formRow: FormRow
|
export let formRow: FormRow
|
||||||
export let formValues: Writable<FormValues>
|
export let formValues: Writable<FormValues>
|
||||||
export let index: number
|
export let index: number
|
||||||
@@ -126,46 +127,69 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/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}
|
{#each column.text ?? [] as textField, textFieldIndex}
|
||||||
<div class="column-{columnIndex} position-{getPosition(column, 5 + textFieldIndex, textFieldIndex)}">
|
<div class="column-{columnIndex} position-{getPosition(column, 5 + textFieldIndex, textFieldIndex)}">
|
||||||
{#if textField?.textArea}
|
<h3 class="textTitle">{textField.textTitle || ""}</h3>
|
||||||
<label bind:this="{$formValues[`textarea_Nachricht_label`]}">
|
<div
|
||||||
<textarea
|
class="column-{columnIndex} position-{getPosition(column, 5 + textFieldIndex, textFieldIndex)}"
|
||||||
placeholder="{textField?.textPlaceholder}"
|
>
|
||||||
required="{textField?.notRequired !== true}"
|
{#if textField?.textArea}
|
||||||
on:change="{removeInvalid}"
|
<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[
|
bind:this="{$formValues[
|
||||||
`textarea_Nachricht_${textField.textfieldOrder}_${index}_${
|
`input_${column.title ? column.title + '_' : ''}${textField?.textPlaceholder}_label`
|
||||||
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}`
|
|
||||||
]}"
|
]}"
|
||||||
/>
|
>
|
||||||
</label>
|
<input
|
||||||
{/if}
|
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>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
{/each}
|
{/each}
|
||||||
|
|||||||
@@ -7,81 +7,20 @@
|
|||||||
import MainPicture from "./mainPicture.svelte"
|
import MainPicture from "./mainPicture.svelte"
|
||||||
import TextContent from "./textContent.svelte"
|
import TextContent from "./textContent.svelte"
|
||||||
import Table from "./table.svelte"
|
import Table from "./table.svelte"
|
||||||
import Form from "./form/form.svelte"
|
import Formular from "./form/Formular.svelte"
|
||||||
import MobileForm from "./form/mobileForm.svelte"
|
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
import { validateFields } from "../../functions/validateFields"
|
|
||||||
import { sendForm } from "../../functions/sendForm"
|
|
||||||
import GoogleMaps from "../googleMaps.svelte"
|
import GoogleMaps from "../googleMaps.svelte"
|
||||||
import { navigate } from "svelte-routing"
|
|
||||||
import IconInfoBoard from "./iconInfoBoard.svelte"
|
import IconInfoBoard from "./iconInfoBoard.svelte"
|
||||||
import Boxlist from "./boxlist.svelte"
|
import Boxlist from "./boxlist.svelte"
|
||||||
import ProductPreview from "./productPreview.svelte"
|
import ProductPreview from "./productPreview.svelte"
|
||||||
|
|
||||||
export let siteId: string
|
export let siteId: string
|
||||||
export let rowNr: number
|
export let rowNr: number
|
||||||
let formSend = false
|
|
||||||
|
|
||||||
let formValues = writable<FormValues>({})
|
|
||||||
function getRowClass(row: Row) {
|
function getRowClass(row: Row) {
|
||||||
if (row.maxWidth || row.column.some((col) => col.iconBackgroundImage)) return "max-width"
|
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"
|
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>
|
</script>
|
||||||
|
|
||||||
<main class="row" name="{row.title}" class:max-width="{getRowClass(row) === 'max-width'}" id="{`RowNr` + rowNr}">
|
<main class="row" name="{row.title}" class:max-width="{getRowClass(row) === 'max-width'}" id="{`RowNr` + rowNr}">
|
||||||
@@ -112,63 +51,7 @@
|
|||||||
<GoogleMaps />
|
<GoogleMaps />
|
||||||
{/if}
|
{/if}
|
||||||
{:else if col.contentType == "form"}
|
{:else if col.contentType == "form"}
|
||||||
{#if formSend}
|
<Formular col="{col}" siteId="{siteId}" rowNr="{rowNr}" row="{row}" rows="{rows}" />
|
||||||
<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}
|
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
@@ -176,45 +59,6 @@
|
|||||||
|
|
||||||
<style lang="less" global>
|
<style lang="less" global>
|
||||||
@import "../../assets/css/variables.less";
|
@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 {
|
.row-title {
|
||||||
font-size: 1.6rem;
|
font-size: 1.6rem;
|
||||||
@@ -234,15 +78,6 @@
|
|||||||
margin-top: 15px !important;
|
margin-top: 15px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.invalid {
|
|
||||||
border-bottom: 2px solid red !important;
|
|
||||||
}
|
|
||||||
.error-message {
|
|
||||||
font-size: 0.9rem !important;
|
|
||||||
color: red !important;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row {
|
.row {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0px 0px 15px 0;
|
padding: 0px 0px 15px 0;
|
||||||
@@ -251,18 +86,6 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
max-width: @body-small-maxwidth;
|
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 {
|
ul {
|
||||||
list-style-type: none; /* Remove default bullet points */
|
list-style-type: none; /* Remove default bullet points */
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -290,175 +113,6 @@
|
|||||||
& > h3 {
|
& > h3 {
|
||||||
width: 100%;
|
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 {
|
@media @mobile {
|
||||||
.no-gap {
|
.no-gap {
|
||||||
@@ -507,17 +161,4 @@
|
|||||||
.max-width {
|
.max-width {
|
||||||
max-width: @body-maxwidth !important;
|
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>
|
</style>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
register(false)
|
register(false)
|
||||||
let swiper: any
|
let swiper: any
|
||||||
console.log("TST RENDERED")
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (swiper) {
|
if (swiper) {
|
||||||
const response = await fetch("/dist/index.css")
|
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 = []
|
const errors = []
|
||||||
let selectedGroup: number
|
let selectedGroup: number
|
||||||
const numberRegex = /^[+]?([.]\d+|\d+([.]\d+)?)$/
|
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 === "blockGroups" || (typeof field === "string" && field.includes("numberLabel"))) {
|
||||||
if (!field.includes("numberLabel")) return
|
if (!field.includes("numberLabel")) return
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const [elementValue, element, group, boolean] = value
|
let [elementValue, element, group, boolean] = value
|
||||||
|
element = element as HTMLElement
|
||||||
if (!elementValue) return
|
if (!elementValue) return
|
||||||
if (selectedGroup !== undefined) {
|
if (selectedGroup !== undefined) {
|
||||||
if (group !== selectedGroup) errors.push(["block", wholeBlockInvalid])
|
if (group !== String(selectedGroup)) errors.push(["block", wholeBlockInvalid])
|
||||||
else validateNumber(elementValue, field, element)
|
else validateNumber(elementValue, field, element)
|
||||||
} else {
|
} else {
|
||||||
|
//@ts-ignore
|
||||||
selectedGroup = group
|
selectedGroup = group
|
||||||
validateNumber(elementValue, field, element)
|
validateNumber(elementValue, field, element)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
value = value as any[]
|
value = value
|
||||||
let required = value[1]
|
let required = value[1]
|
||||||
value = value[0]
|
value = value[0]
|
||||||
if (!required && !value) return
|
if (!required && !value) return
|
||||||
@@ -43,16 +45,16 @@ export function validateFields(fieldsArray: (string | boolean | any[])[][]): (st
|
|||||||
} else if (typeof field === "string") {
|
} else if (typeof field === "string") {
|
||||||
if (field.includes("number_")) {
|
if (field.includes("number_")) {
|
||||||
if (!numberRegex.test(`${value}`)) errors.push(["Ungültiger numerischer Wert.", field])
|
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])
|
if (value !== true) errors.push(["Bitte das Kontrollkästchen anklicken.", field])
|
||||||
} else if (field.includes("Email_")) {
|
} else if (field.includes("Email_") && typeof value == "string") {
|
||||||
if (!emailRegex.test(value as string)) errors.push(["Ungültiges E-Mail-Format.", field])
|
if (!emailRegex.test(value)) errors.push(["Ungültiges E-Mail-Format.", field])
|
||||||
} else if (field.includes("date_")) {
|
} else if (field.includes("date_") && typeof value == "string") {
|
||||||
if (!dateRegex.test(value as string)) errors.push(["Ungültiges Datumsformat.", field])
|
if (!dateRegex.test(value)) errors.push(["Ungültiges Datumsformat.", field])
|
||||||
} else if (field.includes("times_")) {
|
} else if (field.includes("times_") && typeof value == "string") {
|
||||||
if (!timeRegex.test(value as string)) errors.push(["Ungültiges Zeitformat.", field])
|
if (!timeRegex.test(value) && typeof value == "string") errors.push(["Ungültiges Zeitformat.", field])
|
||||||
} else if (field.includes("Telefon_")) {
|
} else if (field.includes("Telefon_") && typeof value == "string") {
|
||||||
if (!phoneRegex.test(value as string)) errors.push(["Ungültiges Telefonnummernformat.", field])
|
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 sites = writable<Sites>({})
|
||||||
export let serviceNavigation = writable<Navigation>()
|
export let serviceNavigation = writable<Navigation>()
|
||||||
export let banner = writable<Banner[]>([])
|
export let banner = writable<Banner[]>([])
|
||||||
export let temperature = writable<Temperature>()
|
export let darkMode = writable<boolean>(false)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
let site: Site
|
let site: Site
|
||||||
function getSelectedSite(path: string): Site | {} {
|
function getSelectedSite(path: string): Site | {} {
|
||||||
let site = {}
|
let site = {}
|
||||||
console.log($sites, "sites")
|
|
||||||
if (Object.values($sites).length == 0) return {}
|
if (Object.values($sites).length == 0) return {}
|
||||||
Object.values($sites).forEach((element) => {
|
Object.values($sites).forEach((element) => {
|
||||||
if (element.path == "/" + path) site = element
|
if (element.path == "/" + path) site = element
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
"connect-history-api-fallback": "^2.0.0",
|
"connect-history-api-fallback": "^2.0.0",
|
||||||
"esbuild": "^0.19.3",
|
"esbuild": "^0.19.3",
|
||||||
"esbuild-svelte": "^0.8.0",
|
"esbuild-svelte": "^0.8.0",
|
||||||
|
"fluent-svelte": "^1.6.0",
|
||||||
"http-proxy-middleware": "^2.0.6",
|
"http-proxy-middleware": "^2.0.6",
|
||||||
"less": "^4.2.0",
|
"less": "^4.2.0",
|
||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
|
|||||||
52
types/global.d.ts
vendored
52
types/global.d.ts
vendored
@@ -127,10 +127,45 @@ interface VideoSwitch {
|
|||||||
link: string
|
link: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface FormObj {
|
||||||
|
formRows?: string[]
|
||||||
|
index?: number
|
||||||
|
formTitle?: string
|
||||||
|
formValues?: Writable<FormValues>
|
||||||
|
honey?: boolean
|
||||||
|
agreement?: boolean
|
||||||
|
}
|
||||||
|
// Before transformation
|
||||||
|
interface TempFormBefore {
|
||||||
|
[rowName: string]: TempFormRowBefore
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TempFormRowBefore {
|
||||||
|
[newKey: string]: [any, boolean, boolean]
|
||||||
|
}
|
||||||
|
|
||||||
|
// After transformation
|
||||||
|
interface TempFormAfter {
|
||||||
|
[rowName: string]: Array<[string, [any, boolean, boolean]]>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TempFormIndices {
|
||||||
|
[rowName: string]: {
|
||||||
|
[newKey: string]: number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ValueEntry =
|
||||||
|
| [string, [boolean | string | any, boolean]]
|
||||||
|
| [string, [any, CustomHTMLElement, string | null, boolean]]
|
||||||
|
|
||||||
|
type ObjectEntry = [string, CustomHTMLElement]
|
||||||
|
|
||||||
interface FormRow {
|
interface FormRow {
|
||||||
title?: string
|
title?: string
|
||||||
rowName: string
|
rowName: string
|
||||||
columns: FormColumn[]
|
columns: FormColumn[]
|
||||||
|
showRowName: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Block {
|
interface Block {
|
||||||
@@ -174,7 +209,15 @@ interface FormColumn {
|
|||||||
emailNameTime: string
|
emailNameTime: string
|
||||||
emailNameTimes: string
|
emailNameTimes: string
|
||||||
numberfieldOrder?: number
|
numberfieldOrder?: number
|
||||||
|
showCheckboxGroup: boolean
|
||||||
|
groupTitle: string
|
||||||
|
checkboxes: Checkbox[]
|
||||||
|
showDatePicker: boolean
|
||||||
|
datePickerNotRequired: boolean
|
||||||
|
datePickerProps: DatePickerProps
|
||||||
|
datePickerEmailTitle: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CustomHTMLElement extends HTMLElement {
|
interface CustomHTMLElement extends HTMLElement {
|
||||||
checked?: boolean
|
checked?: boolean
|
||||||
value?: any
|
value?: any
|
||||||
@@ -182,6 +225,14 @@ interface CustomHTMLElement extends HTMLElement {
|
|||||||
getAttribute(attr: string): string | null
|
getAttribute(attr: string): string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DatePickerProps {
|
||||||
|
allowedDateRanges: {
|
||||||
|
from: string
|
||||||
|
to: string
|
||||||
|
}[]
|
||||||
|
excludeDays: "monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday" | "sunday"
|
||||||
|
}
|
||||||
|
|
||||||
interface FormValues {
|
interface FormValues {
|
||||||
[key: string]: CustomHTMLElement
|
[key: string]: CustomHTMLElement
|
||||||
blockGroups?: Set<number>
|
blockGroups?: Set<number>
|
||||||
@@ -210,6 +261,7 @@ interface TextField {
|
|||||||
dateSelectNotRequired: boolean
|
dateSelectNotRequired: boolean
|
||||||
emailName: string
|
emailName: string
|
||||||
textfieldOrder: string
|
textfieldOrder: string
|
||||||
|
textTitle: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TeaserImage {
|
interface TeaserImage {
|
||||||
|
|||||||
27
yarn.lock
27
yarn.lock
@@ -3642,6 +3642,25 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"fluent-svelte@npm:^1.6.0":
|
||||||
|
version: 1.6.0
|
||||||
|
resolution: "fluent-svelte@npm:1.6.0"
|
||||||
|
dependencies:
|
||||||
|
focus-trap: ^6.7.3
|
||||||
|
tabbable: ^5.2.1
|
||||||
|
checksum: 1b2ac33343f6e34469e4af9b31e0d446b021b3b2cd64f91b5b010fcf045abdbf7bb5910b9bc4ad90bd5020cf4293e23f625acb01addede3806eb0325514b727d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"focus-trap@npm:^6.7.3":
|
||||||
|
version: 6.9.4
|
||||||
|
resolution: "focus-trap@npm:6.9.4"
|
||||||
|
dependencies:
|
||||||
|
tabbable: ^5.3.3
|
||||||
|
checksum: 0b4cebcc11010bd9397731092bd59a981e838c710c6497374ba70571875a14ab27c0db7d60f36005ec01bdabc3b9cfeda11d30ddf5b8874596dcc95e18913b3b
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.0":
|
"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.0":
|
||||||
version: 1.15.2
|
version: 1.15.2
|
||||||
resolution: "follow-redirects@npm:1.15.2"
|
resolution: "follow-redirects@npm:1.15.2"
|
||||||
@@ -6533,6 +6552,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"tabbable@npm:^5.2.1, tabbable@npm:^5.3.3":
|
||||||
|
version: 5.3.3
|
||||||
|
resolution: "tabbable@npm:5.3.3"
|
||||||
|
checksum: 1aa56e1bb617cc10616c407f4e756f0607f3e2d30f9803664d70b85db037ca27e75918ed1c71443f3dc902e21dc9f991ce4b52d63a538c9b69b3218d3babcd70
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"tar@npm:^6.1.11, tar@npm:^6.1.2":
|
"tar@npm:^6.1.11, tar@npm:^6.1.2":
|
||||||
version: 6.1.12
|
version: 6.1.12
|
||||||
resolution: "tar@npm:6.1.12"
|
resolution: "tar@npm:6.1.12"
|
||||||
@@ -6567,6 +6593,7 @@ __metadata:
|
|||||||
cssnano: ^6.0.1
|
cssnano: ^6.0.1
|
||||||
esbuild: ^0.19.3
|
esbuild: ^0.19.3
|
||||||
esbuild-svelte: ^0.8.0
|
esbuild-svelte: ^0.8.0
|
||||||
|
fluent-svelte: ^1.6.0
|
||||||
http-proxy-middleware: ^2.0.6
|
http-proxy-middleware: ^2.0.6
|
||||||
less: ^4.2.0
|
less: ^4.2.0
|
||||||
morgan: ^1.10.0
|
morgan: ^1.10.0
|
||||||
|
|||||||
Reference in New Issue
Block a user