Update and rework project structure with new pagebuilder concept. (based on RK Architekten and SFU Politik configs and sources)

This commit is contained in:
2022-11-17 16:01:52 +00:00
parent 825dfc18f9
commit 30c05143fe
1421 changed files with 3875 additions and 4975 deletions

View File

@@ -39,7 +39,7 @@
<meta name="description" content="{$generalInfo?.meta?.metaDescription}" />
{/if}
{#if $generalInfo?.meta?.metaKeywords}
<meta name="keywords" content="{$generalInfo?.meta?.metaKeywords.replaceAll(' ', '')}" />
<meta name="keywords" content="{$generalInfo?.meta?.metaKeywords?.replaceAll(' ', '')}" />
{/if}
{#if $generalInfo?.person?.firstname || $generalInfo?.person?.lastname}
<meta

View File

@@ -0,0 +1,28 @@
<script lang="ts">
import modules from "./modules"
export let content: Content
</script>
{#if content?.pageBuilder && content?.pageBuilder?.length}
<div class="page-builder">
{#each content.pageBuilder as row}
<div class="page-builder-row">
{#each Object.entries(row.columns) as [index, column]}
{#if row.publish}
{#if column.module || (column.html && column.html !== "")}
<div class="{column.width !== '' ? `page-builder-col-${column.width}` : ''}">
{#if column.html}
{@html column.html}
{/if}
{#if column.module}
<svelte:component this="{modules[column.module]}" content="{content}" />
{/if}
</div>
{/if}
{/if}
{/each}
</div>
{/each}
</div>
{/if}

View File

@@ -0,0 +1,48 @@
<script lang="ts">
import { _ } from "svelte-i18n"
import { generalInfo } from "../../../store"
</script>
{#if $generalInfo && $generalInfo?.company?.companyAddresses}
<div class="addresses">
<div class="address-companyName">
<strong>{$generalInfo?.company?.companyName}</strong>
</div>
<div class="address-list">
{#each $generalInfo.company.companyAddresses as address}
<div class="address">
{#if address.street && address.houseNumber}
<div class="address-item street">
<span>{address.street}</span>
<span>{address.houseNumber}</span>
</div>
{/if}
{#if address.postcode && address.city}
<div class="address-item city">
<span>{address.postcode}</span>
<span>{address.city}</span>
</div>
{/if}
{#if address.tel}
<div class="address-item tel">
<span>{$_("tel")}</span>
<span>{address.tel}</span>
</div>
{/if}
{#if address.fax}
<div class="address-item fax">
<span>{$_("fax")}</span>
<span>{address.fax}</span>
</div>
{/if}
{#if address.email}
<div class="address-item email">
<span>{$_("email")}</span>
<a href="mailto:{address.email}">{address.email}</a>
</div>
{/if}
</div>
{/each}
</div>
</div>
{/if}

View File

@@ -0,0 +1,148 @@
<script lang="ts">
import { _ } from "svelte-i18n"
import { fade } from "svelte/transition"
import { mdiCheck } from "@mdi/js"
import Icon from "mdi-svelte"
import { link } from "svelte-routing"
import { sendEmail } from "../../../api"
import { currentLang } from "../../../store"
export let type: string = "contact"
let formData: {
name: string
email: string
subject: string
message: string
privacy: boolean
} = {
name: null,
email: null,
subject: null,
message: null,
privacy: false,
}
let requestSucessfully: boolean = false
let requestPending: boolean = false
const submit = () => {
if (
formData["name"] &&
formData["email"] &&
formData["subject"] &&
formData["message"] &&
formData["privacy"]
) {
requestPending = true
sendEmail(type + "Form", formData)
.then(() => {
resetForm()
requestSucessfully = true
requestPending = false
setTimeout(() => {
requestSucessfully = false
}, 10000)
})
.catch((e) => {
console.error(e)
requestPending = false
})
.finally(() => {
requestPending = false
})
}
}
const resetForm = () => {
formData = {
name: null,
email: null,
subject: null,
message: null,
privacy: false,
}
}
$: isValid =
formData["name"] && formData["email"] && formData["subject"] && formData["message"] && formData["privacy"]
</script>
<form on:submit|preventDefault="{submit}">
<div class="row">
<div class="col-md-6 mt-sm">
<input
type="text"
bind:value="{formData['name']}"
placeholder="{$_('form.contact.name')}"
readonly="{requestPending}"
/>
</div>
<div class="col-md-6 mt-sm">
<input
type="email"
bind:value="{formData['email']}"
placeholder="{$_('form.contact.email')}"
readonly="{requestPending}"
/>
</div>
</div>
<div class="row">
<div class="col-md-12 mt-sm">
<input
type="text"
bind:value="{formData['subject']}"
placeholder="{$_('form.contact.subject')}"
readonly="{requestPending}"
/>
</div>
</div>
<div class="row">
<div class="col-md-12 mt-sm">
<textarea
bind:value="{formData['message']}"
readonly="{requestPending}"
placeholder="{$_('form.contact.message')}"></textarea>
</div>
</div>
<div class="row">
<div class="col-md-6 mt-sm">
<label for="privacy-checkbox" class="checkbox-container">
<div
class="checkbox"
id="privacy-checkbox"
on:click="{() => (formData.privacy = !formData.privacy)}"
on:keydown
>
{#if formData.privacy}
<div class="icon">
<Icon path="{mdiCheck}" size="2" />
</div>
{/if}
</div>
<div on:click|stopPropagation="{() => (formData.privacy = !formData.privacy)}" on:keydown>
<a use:link href="{`/${$currentLang}/${$_('privacy').toLowerCase()}`}" on:click|stopPropagation
><strong>{$_("privacy")}</strong></a
>
{$_("accept")}
</div>
</label>
</div>
<div class="col-md-6 mt-sm">
<button type="submit" disabled="{!isValid || requestPending}">{$_("form.contact.send")}</button>
</div>
</div>
{#if requestSucessfully}
<div class="mt-sm" transition:fade>
<div>
<strong>{$_("form.contact.thankYou")}</strong>
</div>
<p>{$_("form.contact.getInTouch")}</p>
</div>
{/if}
</form>

View File

@@ -0,0 +1,7 @@
import ContactForm from "./ContactForm.svelte"
import Addresses from "./Addresses.svelte"
export default {
ContactForm,
Addresses,
}

View File

@@ -4,7 +4,7 @@
import { getGalleries } from "../../api"
import { apiBaseURL } from "../../config"
import Modal from "./Modal.svelte"
import Modal from "../__UNUSED__/widgets/Modal.svelte"
export let article
let galleries: Gallery[]

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { generalInfo, ccTags } from "../../store"
import { generalInfo, ccTags } from "../../../store"
$: iframeTitle =
$generalInfo?.person?.salutation +

View File

@@ -1,192 +1,56 @@
<script lang="ts">
import { afterUpdate } from "svelte"
import * as animateScroll from "svelte-scrollto"
import { _ } from "svelte-i18n"
import { getContent, getArticles } from "../../api"
import { generalInfo, currentLang, location } from "../../store"
import { navigate } from "svelte-routing"
import { _, locale } from "svelte-i18n"
import { getContent } from "../../api"
import { generalInfo, currentLang } from "../../store"
import ArticlesList from "../widgets/ArticlesList.svelte"
import ArticleDetails from "../routes/ArticleDetails.svelte"
import Page from "./Page.svelte"
export let path: string
let pathLang: string
let loading = true
let content: Content
let article: TibiArticle
let connectedContentNotFound: boolean = false
let currentLocale: string = null
let blockedDoubleCall: boolean = false
$: currentDomain = window.location.origin
const loadContent = (type?: string) => {
// Set default API call filter
let filter: { [key: string]: any } = {
locale: $currentLang,
path,
const updateLang = () => {
if (pathLang !== $currentLang) {
let pathElements = path.split("/")
// Update currentLang in store
$currentLang = pathElements[0]
// Update i18n language
locale.set($currentLang)
}
}
// API call filter without locale if URL changed
if (path !== content?.path) {
delete filter.locale
}
// Changed filter to find simmilar content for changed language
if (type === "changedLanguage" && content?.pages) {
filter = {
_id: { $in: content?.pages },
const loadContent = async (path: string) => {
let apiParams: APIParams = {
filter: {
public: true,
locale: $currentLang,
}
delete filter.path
}
// Get content by API call
let apiParams: APIParams = {
filter,
path,
},
}
loading = true
getContent(apiParams)
.then((c) => {
if (c) {
if (type === "changedLanguage" && path !== c.path) {
let newPath = c.path + $location.search
window.history.pushState({}, document.getElementsByTagName("title")[0].innerHTML, newPath + "/")
blockedDoubleCall = true
path = newPath
}
content = c
connectedContentNotFound = false
} else {
// Show message if not found simmilar content for changed language
if (filter.tags) {
connectedContentNotFound = true
}
content = null
}
// Redirect to HOME if no content has been found. So the page 404 content will never shown.
if (!content) {
navigate("/")
}
})
.finally(() => {
loading = false
scrollToAnchor()
})
}
const loadArticle = (type?: string, locale: string = null) => {
let pathParts = path.split("/")
let slugOrId = pathParts[pathParts.length - 1].toString()
let urlLocale = pathParts[0].toString()
let loc = $currentLang
if (urlLocale) {
locale = urlLocale
}
// Set default API call filter
let filter: { [key: string]: any } = {
"article.general.locale": loc,
"article.content.slug": slugOrId,
}
// Changed filter to find simmilar article for changed language
if (type === "changedLanguage") {
filter = {
_id: { $in: article?.article?.assignments?.articles },
"article.general.locale": $currentLang,
}
}
// Get content by API call
let apiParams: APIParams = {
filter,
}
loading = true
getArticles("articles", apiParams)
.then((respoonse) => {
if (respoonse) {
if (type === "changedLanguage") {
let newPath =
"/" +
respoonse[0].article.assignments.pages +
"/" +
respoonse[0].article.content.slug +
$location.search
window.history.pushState({}, document.getElementsByTagName("title")[0].innerHTML, newPath)
}
article = respoonse[0]
} else {
article = null
// Redirect to HOME if no content has been found. So the page 404 content will never shown.
if (!content) {
navigate("/")
}
}
})
.finally(() => {
loading = false
scrollToAnchor()
})
}
currentLang.subscribe((locale) => {
currentLocale = locale
if (content) {
loadContent("changedLanguage")
} else if (article) {
loadArticle("changedLanguage", currentLocale)
} else if (window.location.pathname.endsWith("/")) {
loadContent()
const c = await getContent(apiParams)
if (c) {
content = c[0]
} else {
loadArticle(currentLocale)
window.history.back()
}
})
loading = false
}
$: if (path) {
// Set initial current locale for this page
if (!currentLocale) {
currentLocale = $currentLang
}
if (!blockedDoubleCall) {
// Reset all content and articles
content = null
article = null
// Update current language when lang in URL not equal to current language
if (path !== window.location.pathname) {
let pathParts = window.location.pathname.split("/")
if (pathParts.length > 3 && $currentLang !== pathParts[1]) {
$currentLang = currentLocale
}
}
}
blockedDoubleCall = false
updateLang()
loadContent(path)
}
afterUpdate(() => {
scrollToAnchor()
})
const scrollToAnchor = () => {
if (content && window.location.hash) {
window.setTimeout(() => {
animateScroll.scrollTo({
delay: 100,
element: window.location.hash,
offset: -200,
onDone: () => {},
})
}, 500)
}
}
$: console.log(content)
</script>
<svelte:head>
@@ -204,8 +68,8 @@
<meta
name="keywords"
content="{content?.meta?.metaKeywords
? content?.meta?.metaKeywords.replaceAll(' ', '')
: $generalInfo?.meta?.metaKeywords.replaceAll(' ', '')}"
? content?.meta?.metaKeywords?.replaceAll(' ', '')
: $generalInfo?.meta?.metaKeywords?.replaceAll(' ', '')}"
/>
<meta
name="robots"
@@ -224,22 +88,13 @@
{#if loading}
<!-- Loader -->
{:else if article}
<ArticleDetails entry="{article}" />
{:else if content}
<ArticlesList path="{path}" tags="{content?.tags}" />
<!-- Content Page Router -->
{#if content.type.includes("page")}
<Page content="{content}" />
{/if}
{:else}
<!-- <div class="page-404">
<div>
<Image
collectionName="general"
entryId="{$generalInfo.id}"
file="{$generalInfo?.media?.brand}"
alt="{$generalInfo?.meta?.metaTitle}"
cssClass="brand"
/>
</div>
<div class="page-404">
<h1>{$_("pageNotFound")}</h1>
<p class="mb-md">
@@ -266,5 +121,5 @@
},
})}
</p>
</div> -->
</div>
{/if}

View File

@@ -1,18 +1,38 @@
<script lang="ts">
import * as animateScroll from "svelte-scrollto"
// import { _ } from "svelte-i18n"
import { currentLang } from "../../store"
import { getContent } from "../../api"
// import { generalInfo } from "../../store"
let loading = true
let projects: Content[]
let currentImpressionsProject: Content
// import ContactForm from "../widgets/ContactForm.svelte"
// import GoogleMaps from "../widgets/GoogleMaps.svelte"
// import GeneralMediaImage from "../widgets/GeneralMediaImage.svelte"
import ArticlesList from "../widgets/ArticlesList.svelte"
const loadContent = async () => {
let apiParams: APIParams = {
filter: {
public: true,
locale: $currentLang,
type: "project",
},
}
loading = true
const c = await getContent(apiParams)
if (c) {
projects = c
currentImpressionsProject = projects[Math.floor(Math.random() * projects.length)]
}
loading = false
}
loadContent()
$: console.log(projects)
</script>
<ArticlesList pages="{['/']}" />
<!-- <GeneralMediaImage id="test1" /> -->
<!-- <ContactForm type="recipe" collapsed="{expandedForm !== 'recipe'}" /> -->
<!-- <ContactForm type="contact" collapsed="{expandedForm !== 'contact'}" /> -->
<!-- <GoogleMaps /> -->
{#if projects}
<section>
{JSON.stringify(projects)}
</section>
{/if}

View File

@@ -0,0 +1,11 @@
<script lang="ts">
import PageBuilder from "../PageBuilder/PageBuilder.svelte"
export let content: Content
</script>
{#if content}
<main class="page {content.type.join(' ').toLowerCase()}">
<PageBuilder content="{content}" />
</main>
{/if}

View File

@@ -1,227 +0,0 @@
<script lang="ts">
import { _ } from "svelte-i18n"
import { navigate, link } from "svelte-routing"
import TibiArticleMediaFile from "./TibiArticleMediaFile.svelte"
export let entry: CollectionEntry = null
export let cssClass: string = ""
export let showDetails: boolean = false
let path = window.location.pathname
let article = null
if (entry) {
article = entry.article
}
let marginClasses: string = ""
let paddingClasses: string = ""
let published: boolean = true
const updatePublishedState = () => {
let currentDate = new Date().getTime()
let from = new Date(article?.general?.publish_date?.from).getTime()
let until = new Date(article?.general?.publish_date?.until).getTime()
let publish = true
if (from && until) {
if (currentDate > from && currentDate < until) {
publish = true
} else {
publish = false
}
} else {
if (from) {
if (currentDate > from) {
publish = true
} else {
publish = false
}
}
if (until && publish) {
if (currentDate < until) {
publish = true
} else {
publish = false
}
}
}
published = publish
}
$: if (article) {
marginClasses = Object.values(article?.layout?.properties?.margin).join(" ").replace(" ", " ")
paddingClasses = Object.values(article?.layout?.properties?.padding).join(" ").replace(" ", " ")
}
$: if (article?.general?.publish_date?.from || article?.general?.publish_date?.until) updatePublishedState()
// Update publish state every interval time (default 60sec)
setInterval(
updatePublishedState,
article?.general?.publish_date?.interval ? article?.general?.publish_date?.interval : 60000
)
</script>
{#if article && published}
<article
class="{cssClass} {article?.layout?.variant} {marginClasses} {paddingClasses}"
id="{article?.content?.slug}"
>
{#if article?.layout?.variant === "top"}
{#if article?.content?.types?.media?.files?.length}
<TibiArticleMediaFile
collectionName="articles"
entryId="{entry.id}"
mediaFile="{article?.content?.types?.media?.files[0]}"
/>
{/if}
{#if article?.content?.title}
<div class="article-title">{@html article?.content?.title}</div>
{/if}
{#if article?.content?.subtitle}
<div class="article-subtitle">{@html article?.content?.subtitle}</div>
{/if}
{#if article?.content?.types?.teaser}
<div class="article-teaser">{@html article?.content?.types?.teaser}</div>
{/if}
{#if article?.link?.url}
<a
href="{article?.link?.url}"
target="{article?.link?.target ? article?.link?.target : '_self'}"
class="article-link">{@html article?.link?.text ? article?.link?.text : $_("details")}</a
>
{/if}
{#if article?.content?.types?.details && showDetails}
<div class="article-details">{@html article?.content?.types?.details}</div>
{/if}
{:else if article?.layout?.variant === "right"}
<div class="row">
<div class="col-md-8">
{#if article?.content?.title}
<div class="article-title">{@html article?.content?.title}</div>
{/if}
{#if article?.content?.subtitle}
<div class="article-subtitle">{@html article?.content?.subtitle}</div>
{/if}
{#if article?.content?.types?.teaser}
<div class="article-teaser">{@html article?.content?.types?.teaser}</div>
{/if}
{#if article?.link?.url}
<a
href="{article?.link?.url}"
target="{article?.link?.target ? article?.link?.target : '_self'}"
class="article-link">{@html article?.link?.text ? article?.link?.text : $_("details")}</a
>
{/if}
{#if article?.content?.types?.details && showDetails}
<div class="article-details">{@html article?.content?.types?.details}</div>
{/if}
</div>
<div class="col-md-4">
{#if article?.content?.types?.media?.files?.length}
<TibiArticleMediaFile
collectionName="articles"
entryId="{entry.id}"
mediaFile="{article?.content?.types?.media?.files[0]}"
/>
{/if}
</div>
</div>
{:else if article?.layout?.variant === "bottom"}
{#if article?.content?.title}
<div class="article-title">{@html article?.content?.title}</div>
{/if}
{#if article?.content?.subtitle}
<div class="article-subtitle">{@html article?.content?.subtitle}</div>
{/if}
{#if article?.content?.types?.teaser}
<div class="article-teaser">{@html article?.content?.types?.teaser}</div>
{/if}
{#if article?.link?.url}
<a
href="{article?.link?.url}"
target="{article?.link?.target ? article?.link?.target : '_self'}"
class="article-link">{@html article?.link?.text ? article?.link?.text : $_("details")}</a
>
{/if}
{#if article?.content?.types?.details && showDetails}
<div class="article-details">{@html article?.content?.types?.details}</div>
{/if}
{#if article?.content?.types?.media?.files?.length}
<TibiArticleMediaFile
collectionName="articles"
entryId="{entry.id}"
mediaFile="{article?.content?.types?.media?.files[0]}"
/>
{/if}
{:else if article?.layout?.variant === "left" || article?.layout?.variant === "default"}
<div class="row">
<div class="col-md-4">
{#if article?.content?.types?.media?.files?.length}
<TibiArticleMediaFile
collectionName="articles"
entryId="{entry.id}"
mediaFile="{article?.content?.types?.media?.files[0]}"
/>
{/if}
</div>
<div class="col-md-8">
{#if article?.content?.title}
<div class="article-title">{@html article?.content?.title}</div>
{/if}
{#if article?.content?.subtitle}
<div class="article-subtitle">{@html article?.content?.subtitle}</div>
{/if}
{#if article?.content?.types?.teaser}
<div class="article-teaser">{@html article?.content?.types?.teaser}</div>
{/if}
{#if article?.link?.url}
<a
href="{article?.link?.url}"
target="{article?.link?.target ? article?.link?.target : '_self'}"
class="article-link">{@html article?.link?.text ? article?.link?.text : $_("details")}</a
>
{/if}
{#if article?.content?.types?.details && showDetails}
<div class="article-details">{@html article?.content?.types?.details}</div>
{:else if article?.content?.types?.details}
<a
use:link
href="{`${path}${encodeURIComponent(
article?.content?.slug
? article?.content?.slug
.toLowerCase()
.replace(/[^a-zA-Z0-9]/g, '-')
.replaceAll('---', '--')
: entry.id
)}`}"
class="article-link"
>
{@html article?.link?.text ? article?.link?.text : $_("details")}
</a>
{/if}
</div>
</div>
{/if}
</article>
{/if}

View File

@@ -1,38 +0,0 @@
<script lang="ts">
import { currentLang } from "../../store"
import { getArticles } from "../../api"
import Article from "../widgets/Article.svelte"
export let tags: string[] = null
export let pages: string[] = null
export let path: string = null
let articleEntries: CollectionEntry[] = []
$: if ($currentLang) {
let filter = {
"article.general.locale": $currentLang,
}
if (tags && tags?.length) {
filter["article.assignments.tags"] = { $in: tags }
}
if (pages && pages?.length) {
filter["article.assignments.pages"] = { $in: pages }
}
if (path) {
filter["article.assignments.pages"] = { $in: [path] }
}
getArticles("articles", { filter }).then((response) => {
articleEntries = response
})
}
</script>
{#each articleEntries || [] as entry}
<Article entry="{entry}" />
{/each}

View File

@@ -1,160 +0,0 @@
<script lang="ts">
import { fade } from "svelte/transition"
import { mdiCheck, mdiChevronDown } from "@mdi/js"
import Icon from "mdi-svelte"
import { sendEmail } from "../../api"
export let type: string
export let collapsed: boolean = false
let formData: {
name: string
email: string
subject: string
message: string
privacy: boolean
} = {
name: null,
email: null,
subject: null,
message: null,
privacy: false,
}
let requestSucessfully: boolean = false
let requestPending: boolean = false
const submit = () => {
if (
formData["name"] &&
formData["email"] &&
formData["subject"] &&
formData["message"] &&
formData["privacy"]
) {
requestPending = true
sendEmail(type + "Form", formData)
.then(() => {
resetForm()
requestSucessfully = true
requestPending = false
setTimeout(() => {
requestSucessfully = false
}, 10000)
})
.catch((e) => {
console.error(e)
requestPending = false
})
.finally(() => {
requestPending = false
})
}
}
const resetForm = () => {
formData = {
name: null,
email: null,
subject: null,
message: null,
privacy: false,
}
}
$: isValid =
formData["name"] && formData["email"] && formData["subject"] && formData["message"] && formData["privacy"]
</script>
<div id="{type}">
<form on:submit|preventDefault="{submit}" class="mt-lg">
<div class="layout justify-content-space-between layout-gap-md">
<div class="hidden-sm icon {type}">
<!-- <img src="img/icon/{type}.svg" alt="" /> -->
</div>
<div class="titles" on:click="{() => (collapsed = !collapsed)}">
<h3 class="title">
{type === "contact" ? "Kontakt" : ""}
{type === "recipe" ? "Rezeptanfrage" : ""}
</h3>
<h4 class="subTitle">
{type === "contact" ? "Schreiben Sie uns Ihr Anliegen" : ""}
{type === "recipe" ? "Teilen Sie uns Ihren Rezeptwunsch mit" : ""}
</h4>
</div>
<div class="collapse-icon" class:collapsed="{!collapsed}" on:click="{() => (collapsed = !collapsed)}">
<Icon path="{mdiChevronDown}" size="2" />
</div>
</div>
{#if !collapsed}
<div>
<div class="row">
<div class="col-md-6 mt-sm">
<input
type="text"
bind:value="{formData['name']}"
placeholder="Name"
readonly="{requestPending}"
/>
</div>
<div class="col-md-6 mt-sm">
<input
type="text"
bind:value="{formData['email']}"
placeholder="E-Mail Adresse"
readonly="{requestPending}"
/>
</div>
</div>
<div class="row nospace">
<div class="col-md-12 mt-sm">
<input
type="text"
bind:value="{formData['subject']}"
placeholder="Betreff"
readonly="{requestPending}"
/>
</div>
</div>
<div class="row nospace">
<div class="col-md-12 mt-sm">
<textarea bind:value="{formData['message']}" readonly="{requestPending}"></textarea>
</div>
</div>
<div class="row nospace">
<div class="col-md-12 mt-sm">
<div class="layout layout-gap-md align-items-center">
<div
class="checkbox"
on:click="{() => {
formData.privacy = !formData.privacy
}}"
>
{#if formData.privacy}
<div class="icon">
<Icon path="{mdiCheck}" size="2" />
</div>
{/if}
</div>
<div on:click="{() => (formData.privacy = !formData.privacy)}">
<a href="/datenschutz"><strong>Datenschutz</strong></a> akzeptieren
</div>
</div>
</div>
</div>
{#if requestSucessfully}
<div class="mt-sm" transition:fade>
<div>
<strong>Vielen Dank für Ihre Kontaktaufnahme!</strong>
</div>
<p>Wir werden uns zeitnah mit Ihnen in Verbindung setzen!</p>
</div>
{/if}
<div class="layout justify-content-end mt-sm">
<button type="submit" disabled="{!isValid || requestPending}">Absenden</button>
</div>
</div>
{/if}
</form>
</div>

View File

@@ -5,20 +5,18 @@
</script>
<footer>
<div class="container">
<section class="no-space align-right">
<main class="section-content">
<Navigation ident="footer" />
</main>
</section>
{#if $generalInfo?.copyrightText}
<div class="row">
<div class="col-md-12">
<Navigation ident="footer" />
</div>
</div>
{#if $generalInfo?.copyrightText}
<div class="row">
<div class="col-md-12">
<div class="copyright">
{$generalInfo?.copyrightText}
</div>
<div class="copyright">
{$generalInfo?.copyrightText}
</div>
</div>
{/if}
</div>
</div>
{/if}
</footer>

View File

@@ -1,32 +1,45 @@
<script lang="ts">
import { link } from "svelte-routing"
// import * as animateScroll from "svelte-scrollto"
import { generalInfo } from "../../store"
import { generalInfo, showMobileNav } from "../../store"
import Navigation from "./Navigation.svelte"
import Image from "./Image.svelte"
let y: number = 0
let innerHeight: number = 0
let outerHeight: number = 0
</script>
<header>
<div class="container">
<div class="row">
<div class="col-sm-12">
<div class="header-content">
<a href="/" use:link>
<Image
collectionName="general"
entryId="{$generalInfo?.id}"
file="{$generalInfo?.media?.brand}"
alt="{$generalInfo?.meta?.metaTitle}"
cssClass="brand"
/>
</a>
<svelte:window bind:scrollY="{y}" bind:innerHeight bind:outerHeight />
<div class="header-content-right">
<Navigation />
</div>
</div>
<header>
<div class="header-content">
<a href="/" class="brand-container" use:link>
<Image
collectionName="general"
entryId="{$generalInfo?.id}"
file="{$generalInfo?.media?.brand}"
alt="{$generalInfo?.meta?.metaTitle}"
cssClass="brand"
/>
</a>
<div class="header-content-right">
<Navigation />
<div class="nav-mobile-toggle" on:click="{() => ($showMobileNav = !$showMobileNav)}" on:keydown>
{#if $showMobileNav}
<img src="img/icons/close.svg" alt="" />
{:else}
<img src="img/icons/menu.svg" alt="" />
{/if}
</div>
</div>
</div>
</header>
<div class="main-mobile" class:show="{$showMobileNav}">
<Navigation mobile="{true}" />
</div>

View File

@@ -1,16 +1,12 @@
<script lang="ts">
import Icon from "mdi-svelte"
import { mdiMenu } from "@mdi/js"
import { navigations, currentLang } from "../../store"
import LanguageChooser from "./LanguageChooser.svelte"
// import LanguageChooser from "./LanguageChooser.svelte"
import NavigationItem from "./NavigationItem.svelte"
export let ident = "main"
export let mobile: boolean = false
let navigation: Navigation
let showMobileNav: boolean = false
$: {
navigation = null
@@ -22,24 +18,12 @@
}
</script>
<LanguageChooser />
<!--<LanguageChooser />-->
{#if navigation}
<nav class="{ident}">
<nav class="{ident}" class:mobile>
{#each navigation?.items || [] as item}
<NavigationItem item="{item}" />
{/each}
</nav>
{#if ident === "main"}
<div class="nav-mobile-toggle" on:click="{() => (showMobileNav = !showMobileNav)}">
<Icon path="{mdiMenu}" size="2" />
</div>
<nav class="{ident}-mobile" class:show="{showMobileNav}">
{#each navigation?.items || [] as item}
<NavigationItem item="{item}" />
{/each}
</nav>
{/if}
{/if}

View File

@@ -1,32 +1,31 @@
<script lang="ts">
// import * as animateScroll from "svelte-scrollto"
import { link, navigate } from "svelte-routing"
import { location } from "../../store"
import { navigate } from "svelte-routing"
import { location, showMobileNav } from "../../store"
export let item: NavigationItem
const isActive = (itemPath: string, locationPath: string): boolean | any => {
itemPath = "/" + itemPath + (locationPath.endsWith("/") ? "/" : "")
locationPath = (locationPath.startsWith("/") ? "" : "/") + locationPath
itemPath = itemPath
locationPath = locationPath
if (!locationPath.endsWith("/")) {
return locationPath.startsWith(itemPath)
}
return itemPath === locationPath
return locationPath.includes(itemPath)
}
const onClickInternalLink = (item: NavigationItem) => {
let url = ""
if (item.settings?.page) {
url += item.settings?.page
}
if (item.settings?.url?.url) {
url += (url.endsWith("/") ? "" : "/") + item.settings.url.url
}
if (item.settings?.page) {
navigate(url, { replace: true })
$showMobileNav = false
navigate(url)
}
}
@@ -35,7 +34,7 @@
return item.settings.page
}
return item.settings.page + "/"
return item.settings.page
}
</script>
@@ -43,21 +42,29 @@
{#if item.settings.url.url}
{#if item.settings.url.target === "default"}
<a
use:link
on:click|preventDefault="{() => onClickInternalLink(item)}"
on:keydown
href="{getInternalUrl(item)}"
class:active="{isActive(item.settings.page, $location.path)}"
on:click|stopPropagation="{() => onClickInternalLink(item)}"
>
{item.settings.title}
<div class="box"></div>
<span>{item.settings.title}</span>
</a>
{:else}
<a href="{item.settings.url.url}" target="{item.settings.url.target}">
{item.settings.title}
<div class="box"></div>
<span>{item.settings.title}</span>
</a>
{/if}
{:else}
<a use:link href="{getInternalUrl(item)}" class:active="{isActive(item.settings.page, $location.path)}">
{item.settings.title}
<a
on:click|preventDefault="{() => onClickInternalLink(item)}"
on:keydown
href="{getInternalUrl(item)}"
class:active="{isActive(item.settings.page, $location.path)}"
>
<div class="box"></div>
<span>{item.settings.title}</span>
</a>
{/if}
{/if}

View File

@@ -1,56 +0,0 @@
<script lang="ts">
import { news } from "../../store"
const getNewsDate = (news) => {
const from = news?.from ? new Date(news?.from) : null
const until = news?.until ? new Date(news?.until) : null
const options = { year: "numeric", month: "2-digit", day: "2-digit" }
let d = ""
if (from) {
// @ts-ignore
d += from.toLocaleDateString("de-DE", options)
}
if (until) {
// @ts-ignore
d += " bis " + until.toLocaleDateString("de-DE", options)
}
if (news.title) {
d += " - "
}
return d
}
</script>
{#if $news?.length}
<section class="news" id="news">
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>Neuigkeiten</h2>
</div>
</div>
<div class="row">
{#each $news as n}
{#if n.title || n.from || n.until}
<div class="col-md-6">
<article>
<div class="title">
{getNewsDate(n)}
{#if n.title}
{@html n.title}
{/if}
</div>
{#if n.content}
<div class="content">
{@html n.content}
</div>
{/if}
</article>
</div>
{/if}
{/each}
</div>
</div>
</section>
{/if}

View File

@@ -1,74 +0,0 @@
<svg
class="promotion-image-wave-top"
width="1920"
height="70"
viewBox="0 0 1920 70"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="m1920 70-80-12c-80-12-240-36-400-42s-320 6-480 18-320 24-480 18S160 22 80 10L0-2v-108h1920V70z"
fill="#fff"></path>
</svg>
<!-- <img src="img/promotion/promotion-image.png" alt="" class="promotion-image" /> -->
<svg class="promotion-image-wave-bottom" viewBox="0 0 1920 137" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M0 30.708 80 24.7c80-6.008 240-18.024 400-6.008 160 12.016 320 48.065 480 42.057 160-6.009 320-54.073 480-60.082 160-6.008 320 30.041 400 48.065l80 18.025V137H0V30.708z"
fill="url(#plkj8d2oga)"></path>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M0 30.708 80 24.7c80-6.008 240-18.024 400-6.008 160 12.016 320 48.065 480 42.057 160-6.009 320-54.073 480-60.082 160-6.008 320 30.041 400 48.065l80 18.025V137H0V30.708z"
fill="url(#iwnto70uxb)"></path>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M0 30.708 80 24.7c80-6.008 240-18.024 400-6.008 160 12.016 320 48.065 480 42.057 160-6.009 320-54.073 480-60.082 160-6.008 320 30.041 400 48.065l80 18.025V137H0V30.708z"
fill="url(#aco1fmuv9c)"></path>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M0 121.708 80 108.7c80-6.008 240-48.024 400-36.008 160 12.016 320 48.065 480 42.057 160-6.009 320-94.073 480-100.081 160-6.009 320 30.04 400 48.064l80 18.025V141H0v-19.292z"
fill="#fff"></path>
<defs>
<radialGradient
id="plkj8d2oga"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(960 0 0 41.5089 960 95.491)"
>
<stop stop-color="#FFFEFF"></stop>
<stop offset="1" stop-color="#D7FFFE"></stop>
</radialGradient>
<radialGradient
id="iwnto70uxb"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-652.99956 -34.96514 36.02623 -672.81617 1033.5 102.034)"
>
<stop stop-color="#BCFFFD"></stop>
<stop offset="1" stop-color="#fff" stop-opacity="0"></stop>
</radialGradient>
<radialGradient
id="aco1fmuv9c"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(8.473 63.69 3351.307) scale(825.005 723.955)"
>
<stop stop-color="#fff"></stop>
<stop offset="1" stop-color="#fff" stop-opacity="0"></stop>
</radialGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -1,39 +0,0 @@
<script lang="ts">
import { createEventDispatcher } from "svelte"
import GeneralMediaImage from "./GeneralMediaImage.svelte"
const dispatch = createEventDispatcher()
</script>
<div class="scroll-to-top">
<div class="circle-email">
<a
href="/#"
on:click="{() => {
dispatch('scrollTo', {
element: 'contact',
})
}}"
>
<GeneralMediaImage id="contact" />
</a>
</div>
<div class="circle-contact">
<a
href="/#"
on:click="{() => {
dispatch('scrollTo', {
element: 'recipe',
})
}}"
>
<GeneralMediaImage id="recipe" />
</a>
</div>
<div class="circle-top">
<a href="/#">
<GeneralMediaImage id="up" />
</a>
</div>
</div>