Initial commit

This commit is contained in:
2025-10-02 08:54:03 +02:00
commit ea54638227
1642 changed files with 53677 additions and 0 deletions

View File

View File

@@ -0,0 +1,62 @@
<script lang="ts">
import { getCachedEntry } from "../api"
import NotFound from "./NotFound.svelte"
import Breadcrumbs from "../lib/components/pagebuilder/Breadcrumbs.svelte"
import ContentBlock from "../lib/components/pagebuilder/ContentBlock.svelte"
import Loader from "../lib/components/pagebuilder/Loader.svelte"
import Index from "../lib/components/pagebuilder/SEO/Index.svelte"
export let location: LocationStore = undefined,
id: string = undefined
let loading = true
let contentEntry: ContentEntry
async function loadContent() {
loading = true
contentEntry = null
try {
contentEntry = await getCachedEntry(
"content",
location ? { $or: [{ path: location.path }, { "alternativePaths.path": location.path }] } : { _id: id }
)
} catch (e) {
console.error(e)
}
loading = false
}
// only load new content if location.path or id changes
let _location: typeof location
let _id: typeof id
$: if (location?.path != _location?.path || id != _id) {
_id = id
_location = location
loadContent()
}
$: breadCrumbPosition = contentEntry?.blocks?.length && contentEntry.blocks[0].type?.startsWith("hero") ? 1 : 0
</script>
{#if loading}
<Loader size="3" />
{:else if contentEntry}
<Index
createdAt="{new Date(contentEntry.insertTime)}"
updatedAt="{new Date(contentEntry.updateTime)}"
metaDescription="{contentEntry.meta?.description}"
title="{contentEntry.meta?.title}"
keywords="{contentEntry.meta?.keywords}"
article="{contentEntry.meta.isArticle}"
active="{contentEntry.active}"
FAQ="{contentEntry.meta.hasFAQ}"
FAQDetails="{contentEntry.meta.FAQ}"
/>
{#each contentEntry.blocks || [] as block, idx}
{#if idx === breadCrumbPosition}
<Breadcrumbs location="{location}" />
{/if}
<ContentBlock block="{block}" />
{/each}
{:else}
<NotFound />
{/if}

View File

@@ -0,0 +1,89 @@
<script lang="ts">
import { getHelpCenterChapters } from "../lib/functions/CommerceAPIs/tibiEndpoints/helpCenter"
import PageTitle from "../lib/components/widgets/PageTitle.svelte"
import Loader from "../lib/components/pagebuilder/Loader.svelte"
import Chapter from "../lib/components/pagebuilder/helpCenter/Chapter.svelte"
import ChapterDetailed from "../lib/components/pagebuilder/helpCenter/ChapterDetailed.svelte"
import Index from "../lib/components/pagebuilder/SEO/Index.svelte"
import CustomerSupportRequest from "../lib/components/widgets/CustomerSupportRequest.svelte"
export let location: LocationStore = undefined
let chapters: HelpCenterChapter[]
let loading = true
getHelpCenterChapters()
.then((res) => {
chapters = res
})
.finally(() => {
loading = false
})
</script>
<PageTitle title="HelpCenter" />
<section class="wrapper helpCenter">
<div class="inner-wrapper">
{#if location.path.toLowerCase() == "/helpcenter" || location.path.toLowerCase() == "/helpcenter/"}
<Index
metaDescription="Häufig gestellte Fragen und Antworten zu BinKrassDuFass."
title="Hilfe - BinKrassDuFass"
keywords="Hilfe, FAQ, Fragen, Antworten, BinKrassDuFass"
/>
<ul class="helpcenterUl">
{#if loading}
<Loader size="3" />
{:else if chapters}
{#each chapters as chapter}
<Chapter chapter="{chapter}" />
{/each}
{:else}
<p>Es wurden keine Kapitel gefunden.</p>
{/if}
</ul>
{:else}
<ChapterDetailed location="{location}" />
{/if}
</div>
</section>
<CustomerSupportRequest />
<style
lang="less"
global
>
@import "../lib/assets/css/variables.less";
.wrapper.helpCenter {
overflow: visible;
margin-top: 2.4rem;
.inner-wrapper {
width: 100%;
overflow: visible;
display: flex;
flex-direction: column;
gap: 2.4rem;
ul.helpcenterUl {
overflow: visible;
width: 100%;
display: grid;
@media @mobile {
grid-template-columns: 1fr;
}
@media @min-tablet {
grid-template-columns: 1fr 1fr;
}
@media @desktop {
grid-template-columns: 1fr 1fr 1fr;
}
gap: 2.4rem;
li {
overflow: visible;
width: 100%;
}
}
}
}
</style>

View File

@@ -0,0 +1,27 @@
<script lang="ts">
import ChallengeDetailed from "../lib/components/krasskraft/ChallengeDetailed.svelte"
import KrassKraftHomepage from "../lib/components/krasskraft/KrassKraftHomepage.svelte"
import { location, selfImprovementChapters } from "../lib/store"
$: chapter = $selfImprovementChapters.find((c) => c.type == 1)
</script>
<section class="content">
{#if $location.path.includes("challenge")}
<ChallengeDetailed slug="{$location.path.split('/').filter(Boolean).pop()}" />
{:else if chapter}
<KrassKraftHomepage chapter="{chapter}" />
{/if}
</section>
<style lang="less">
.content {
height: 100%;
width: 100%;
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
background-color: var(--bg-100);
}
</style>

View File

@@ -0,0 +1,69 @@
<script>
import Index from "../lib/components/pagebuilder/SEO/Index.svelte"
// set 404 for ssr
if (typeof window === "undefined") {
// @ts-ignore
if (context) context.is404 = true
}
export let disableIndex = false
</script>
{#if disableIndex}
<Index
title="404 - Nicht Gefunden"
metaDescription="Die Seite konnte nicht gefunden werden."
keywords="404, Nicht Gefunden, Seite"
/>
{/if}
<div class="not-found">
<div class="content">
<h1>404</h1>
<h2>Nicht Gefunden</h2>
<p></p>
<a
href="/"
class="back-home">Zurück</a
>
</div>
</div>
<style lang="less">
@import "../lib/assets/css/variables.less";
.not-found {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
.content {
text-align: center;
padding: 2rem;
background-color: rgba(255, 255, 255, 0.9);
h1 {
font-size: 6rem;
color: var(--text-invers-200);
margin-bottom: 2rem;
}
h2 {
font-size: 2rem;
margin-bottom: 1rem;
}
p {
margin-bottom: 2rem;
}
.back-home {
text-decoration: none;
border: 1px solid black;
padding: 0.5rem 1rem;
transition: background-color 0.2s, color 0.2s;
}
}
}
</style>

View File

@@ -0,0 +1,75 @@
<script lang="ts">
import CrinkledSection from "../lib/components/CrinkledSection.svelte"
import Loader from "../lib/components/pagebuilder/Loader.svelte"
import ProductPageDesktop from "../lib/components/pagebuilder/product/ProductPageDesktop.svelte"
import ProductPageMobile from "../lib/components/pagebuilder/product/ProductPageMobile.svelte"
import Index from "../lib/components/pagebuilder/SEO/Index.svelte"
import MediaQuery from "../lib/components/widgets/MediaQuery.svelte"
import { getBCGraphProductByHandle } from "../lib/functions/CommerceAPIs/bigCommerce/product"
import { NotFoundError } from "../lib/functions/errors"
export let handle = ""
let product: BKDFProduct
async function setProduct() {
product = await getBCGraphProductByHandle(handle)
if (!product) NotFoundError("Produkt")
}
setProduct()
function generateProductMetaKeywords(product: BKDFProduct): string {
const categories = product.categories.map((category) => category.name)
const title = product.title
const metaTitle = product.seo.title
const metaDescription = product.seo.description
const tags = product.tags
const price = `${product.priceRange.minVariantPrice.amount}-${product.priceRange.maxVariantPrice.amount} ${product.priceRange.minVariantPrice.currencyCode}`
const salePrice = `${product.salePrice.amount} ${product.salePrice.currencyCode}`
const keywords = [...categories, title, metaTitle, metaDescription, price, salePrice, ...tags]
const uniqueKeywords = Array.from(new Set(keywords)) // Remove duplicates
const metaKeywordsString = uniqueKeywords.join(", ")
return metaKeywordsString
}
</script>
{#if product}
<Index
createdAt="{new Date(product.updatedAt)}"
updatedAt="{new Date(product.updatedAt)}"
metaDescription="{product.seo.description}"
title="{product.seo.title}"
product="{product}"
keywords="{generateProductMetaKeywords(product)}"
/>
<MediaQuery query="(min-width: 1024px)">
<div class="sticky-bar">
<div class="bar"></div>
<CrinkledSection />
</div>
<ProductPageDesktop product="{product}" />
</MediaQuery>
<MediaQuery query="(max-width: 1023px)">
<ProductPageMobile product="{product}" />
</MediaQuery>
{:else}
<Loader
size="4"
type="bar"
/>
{/if}
<style lang="less">
.sticky-bar {
top: 86px;
width: 100%;
position: sticky;
z-index: 1000;
.bar {
background-color: #0d0c0c;
width: 100%;
height: 3rem;
}
}
</style>

View File

@@ -0,0 +1,119 @@
<script lang="ts">
import CrinkledSection from "../lib/components/CrinkledSection.svelte"
import Filter from "../lib/components/pagebuilder/product/Filter.svelte"
import ProductPreview from "../lib/components/pagebuilder/product/ProductPreview.svelte"
import Index from "../lib/components/pagebuilder/SEO/Index.svelte"
import PageTitle from "../lib/components/widgets/PageTitle.svelte"
import { getBCGraphProductsByCategory } from "../lib/functions/CommerceAPIs/bigCommerce/product"
import { categories } from "../lib/store"
export let categoryPath: string[]
let categoryId: number = null
let products: BKDFProduct[] = []
function setCategoryId(categories: BigCommerceCategory[], categoryPath: string[]) {
if (categories.length === 0) return
for (let i = 0; i < categories.length; i++) {
if (categories[i].path.includes(categoryPath[0])) {
categoryPath.shift()
if (categoryPath.length === 0) {
categoryId = categories[i].entityId
return
}
setCategoryId(categories[i].children, [...categoryPath])
}
}
}
function getCategoryById(categories: BigCommerceCategory[], id: number): BigCommerceCategory {
for (let i = 0; i < categories.length; i++) {
if (categories[i].entityId === id) return categories[i]
const category = getCategoryById(categories[i].children, id)
if (category) return category
}
return null
}
setCategoryId($categories, [...categoryPath]) // Use a copy of categoryPath
getBCGraphProductsByCategory(categoryId).then((res) => {
products = res
products = products.sort((p1, p2) => p2?.salePrice?.amount - p1?.salePrice?.amount)
})
</script>
{#if categoryId}
<Index
createdAt="{new Date()}"
updatedAt="{new Date()}"
metaDescription="{getCategoryById($categories, categoryId)?.seo?.metaDescription ||
'Hier sind Produkte von der Marke BinKrassDuFass.'}"
title="{getCategoryById($categories, categoryId)?.seo?.pageTitle}"
keywords="{getCategoryById($categories, categoryId)?.seo?.pageTitle}"
/>
{/if}
<PageTitle title="Produkte">
<p slot="above"></p>
<p slot="below">{products.length} Produkte</p>
</PageTitle>
<div class="sticky-bar">
<div class="bar"></div>
<CrinkledSection />
</div>
<section class="filter-row">
<Filter path="/{categoryPath.join('/')}/" />
</section>
<section class="wrapper">
<ul id="products">
{#each products as product}
<ProductPreview product="{product}" />
{/each}
</ul>
</section>
<style lang="less">
.sticky-bar {
top: 86px;
width: 100%;
position: sticky;
z-index: 1000;
.bar {
background-color: #0d0c0c;
width: 100%;
height: 3rem;
}
}
.filter-row:global {
height: 62px;
display: flex;
position: relative;
width: 100%;
justify-content: center;
padding: 12px 0px;
max-width: 100%;
width: 100%;
display: flex;
& > * {
max-width: var(--normal-max-width);
width: 100%;
margin: 0px var(--horizontal-default-margin);
display: flex;
}
}
.wrapper {
#products {
margin: 0px var(--horizontal-default-margin);
max-width: var(--normal-max-width);
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
width: 100%;
gap: 2.4rem;
}
:global #products > li {
margin-bottom: 2.4rem;
}
}
</style>

View File

@@ -0,0 +1,7 @@
<script lang="ts">
import { location } from "../lib/store"
window.location.href = `https://legacy.binkrassdufass.de${
$location.path.startsWith("/") ? $location.path : "/" + $location.path
}`
</script>

View File

@@ -0,0 +1,135 @@
<script lang="ts">
import Loader from "../lib/components/pagebuilder/Loader.svelte"
import Records from "../lib/components/pagebuilder/profile/profile/Records.svelte"
import {
getUsernameFromLink,
getValidLink,
socialMediaLinks,
} from "../lib/components/pagebuilder/profile/profile/SocialMediaRow.svelte"
import Index from "../lib/components/pagebuilder/SEO/Index.svelte"
import PageTitle from "../lib/components/widgets/PageTitle.svelte"
import { getCustomerByUsername } from "../lib/functions/CommerceAPIs/tibiEndpoints/customer"
import { location } from "../lib/store"
let loading = true
let cs: Customer
// redirect to same path but on legacy.binkrassdufass.de via window.location
window.location.href = `https://legacy.binkrassdufass.de${
$location.path.startsWith("/") ? $location.path : "/" + $location.path
}`
getCustomerByUsername($location.path.split("/@")[1])
.then((res) => (cs = res))
.finally(() => (loading = false))
</script>
<PageTitle
title="Gym Profile"
marginBottom="{true}"
/>
<section class="wrapper">
<div class="inner-wrapper">
{#if loading}
<Loader
size="4"
type="bar"
/>
{:else if cs}
<h2>
{cs.username}
</h2>
<Index
keywords="Öffentliches Profil, Fitness, Gym, {cs.username}, Rekorde, Social Media"
title="{cs.username} - BinKrassDuFass"
metaDescription="Das öffentliche Profil von {cs.username} auf BinKrassDuFass. Hier findest du alle Rekorde und Social Media Profile von {cs.username}."
/>
<ul class="social-media-list">
{#each socialMediaLinks as socialMedia}
{#if cs?.socialMediaAccounts?.[socialMedia?.link]}
<a
href="{getValidLink(cs.socialMediaAccounts[socialMedia.link])}"
target="_blank"
>
<figure class="footer-icon">
<img
alt="{socialMedia.name}"
src="{socialMedia.icon}"
/>
</figure>
<p>
{#if !getUsernameFromLink(cs.socialMediaAccounts[socialMedia.link]).startsWith("@")}
@{/if}{getUsernameFromLink(cs.socialMediaAccounts[socialMedia.link])}
</p>
</a>
{/if}
{/each}
</ul>
<Records
records="{(cs?.personalRecords || []).sort((a, b) => a.priority - b.priority).reverse()}"
entryId="{cs.id}"
/>
{:else}
<h2>Profil wurde nicht gefunden!</h2>
{/if}
</div>
</section>
<style lang="less">
.wrapper {
.inner-wrapper {
width: 100%;
display: flex;
flex-direction: column;
gap: 1.2rem;
h2,
h2 button {
color: var(--text-invers-100);
display: flex;
gap: 12px;
align-items: flex-end;
height: fit-content;
}
.social-media-list {
display: flex;
justify-content: flex-start;
gap: 1.2rem;
overflow-x: auto;
flex-grow: 1;
a {
display: flex;
gap: 6px;
align-items: center;
color: var(--text-invers-100);
button {
color: var(--text-invers-100);
opacity: 0;
}
&:hover {
button {
opacity: 1;
}
}
}
}
.records {
display: flex;
flex-direction: column;
gap: 12px;
h3 {
color: var(--text-invers-100);
}
a {
display: flex;
gap: 12px;
align-items: center;
color: var(--text-invers-100);
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,26 @@
<script lang="ts">
import { _ } from "svelte-i18n"
export let params
let orderSequence, postalCode
if (params) {
orderSequence = params.split("/")[0]
postalCode = params.split("/")[1]
}
</script>
<div class="container">
<section class=" section-type-1 section_padding checkout">
<div class="subline">{$_("ratings.rating")}</div>
<h2 class="h2_nooffset">{$_("ratings.thanks")}</h2>
<section>
<p>
{@html $_("ratings.rating-confirm")}
</p>
<a
class="backbutton"
href="{`/order/rating/${orderSequence}/${postalCode}`}">zurück</a
>
</section>
</section>
</div>

View File

@@ -0,0 +1,14 @@
<script lang="ts">
import Loader from "../lib/components/pagebuilder/Loader.svelte"
import { location } from "../lib/store"
export let id: string
window.location.href = `https://legacy.binkrassdufass.de${
$location.path.startsWith("/") ? $location.path : "/" + $location.path
}`
</script>
<Loader
size="3"
type="bar"
/>