fix: caching of FAQ

Fix wrong caching of FAQs for correct generation
This commit is contained in:
webfussel 2025-07-10 10:05:08 +02:00
parent fa0435efdf
commit cffb719a05
2 changed files with 117 additions and 95 deletions

View file

@ -1,33 +1,44 @@
<template> <template>
<section id="services" class="Services content"> <section id="services" class="Services content">
<h1>Projekt buchen</h1> <h1>Projekt buchen</h1>
<h2>Paketpreise für <Highlight>feste Ergebnisse</Highlight>.</h2> <h2>Paketpreise für
<Highlight>feste Ergebnisse</Highlight>
.
</h2>
<p class="margin-top">Manchmal brauchen wir alle einfach nur eine Kleinigkeit und wollen uns nicht lange binden. Das ist natürlich <p class="margin-top">Manchmal brauchen wir alle einfach nur eine Kleinigkeit und wollen uns nicht lange binden. Das ist natürlich
völlig in Ordnung und genau deshalb biete ich dir die Möglichkeit mich gezielt für <Highlight>kleinere Projekte</Highlight> zu buchen.</p> völlig in Ordnung und genau deshalb biete ich dir die Möglichkeit mich gezielt für
<p class="margin-top-small">Hinter diesen Angeboten gibt es <Highlight>keinerlei Abos oder versteckte Kosten</Highlight>. <Highlight>kleinere Projekte</Highlight>
Aus Transparenzgründen sei aber gesagt, dass sich <Highlight>alle Preise zzgl. 19 % Umsatzsteuer</Highlight> verstehen.</p> zu buchen.
</p>
<p class="margin-top-small">Hinter diesen Angeboten gibt es
<Highlight>keinerlei Abos oder versteckte Kosten</Highlight>
.
Aus Transparenzgründen sei aber gesagt, dass sich
<Highlight>alle Preise zzgl. 19 % Umsatzsteuer</Highlight>
verstehen.
</p>
<FreeInfo /> <FreeInfo/>
<div class="Pricing margin-top"> <div class="Pricing margin-top">
<article v-for="(service, index) in oneOff" :class="{ 'z-3-all': index === 1, 'z-2-all': index !== 1}"> <article v-for="(service, index) in oneOff" :class="{ 'z-3-all': index === 1, 'z-2-all': index !== 1}">
<header> <header>
<strong>{{service.title}}</strong> <strong>{{ service.title }}</strong>
<p class="claim">{{service.smallClaim}}</p> <p class="claim">{{ service.smallClaim }}</p>
<div class="price"> <div class="price">
<span v-if="service.price.pre">{{service.price.pre}}</span> <span v-if="service.price.pre">{{ service.price.pre }}</span>
<span>{{typeof service.price.value === 'number' ? intl.format(service.price.value) : service.price.value}}</span> <span>{{ typeof service.price.value === 'number' ? intl.format(service.price.value) : service.price.value }}</span>
<span v-if="service.price.post" class="post">{{service.price.post}}</span> <span v-if="service.price.post" class="post">{{ service.price.post }}</span>
</div> </div>
<div aria-hidden="true" class="bg-icon"> <div aria-hidden="true" class="bg-icon">
<Icon :name="service.icon" size="1.5em" mode="svg" /> <Icon :name="service.icon" size="1.5em" mode="svg"/>
</div> </div>
</header> </header>
<main> <main>
<div class="list-container"> <div class="list-container">
<ul> <ul>
<li v-for="point in service.list"> <li v-for="point in service.list">
<Icon class="icon yes" name="ph:caret-circle-double-right-duotone" size="1.5em" mode="svg" /> <Icon class="icon yes" name="ph:caret-circle-double-right-duotone" size="1.5em" mode="svg"/>
<span class="label">{{ point }}</span> <span class="label">{{ point }}</span>
</li> </li>
</ul> </ul>
@ -44,7 +55,7 @@
</div> </div>
<div v-if="faq" class="flex-col gap-sm margin-top"> <div v-if="faq" class="flex-col gap-sm margin-top">
<ContentRenderer :value="faq" :style="{ display: 'contents' }" /> <ContentRenderer :value="faq" :style="{ display: 'contents' }"/>
</div> </div>
</section> </section>
</template> </template>
@ -65,16 +76,16 @@ type Service = {
} }
const intl = new Intl.NumberFormat( const intl = new Intl.NumberFormat(
'de-DE', 'de-DE',
{ {
style: 'currency', style: 'currency',
currency: 'EUR', currency: 'EUR',
minimumFractionDigits: 0, minimumFractionDigits: 0,
maximumFractionDigits: 0, maximumFractionDigits: 0,
} },
) )
const oneOff : Service[] = [ const oneOff: Service[] = [
{ {
title: 'Quick Check', title: 'Quick Check',
price: { price: {
@ -129,7 +140,7 @@ const oneOff : Service[] = [
}, },
] ]
const { data: faq } = await useAsyncData('faq', () => queryCollection('faq').path('/snippets/faq/booking').first()) const { data: faq } = await useAsyncData('faq_booking', () => queryCollection('faq').path('/snippets/faq/booking').first())
const texts = generatePlainText<['title']>(faq.value?.body.value) const texts = generatePlainText<['title']>(faq.value?.body.value)
if (faq) { if (faq) {
@ -143,7 +154,7 @@ if (faq) {
'@type': 'Answer', '@type': 'Answer',
'text': entity.text, 'text': entity.text,
}, },
})) })),
}) })
} }
</script> </script>

View file

@ -1,33 +1,44 @@
<template> <template>
<section id="services" class="Services content"> <section id="services" class="Services content">
<h1>Prepaid Flatrates</h1> <h1>Prepaid Flatrates</h1>
<h2>Genieße fusselige <Highlight>Qualität</Highlight> ohne groß herumzurechnen.</h2> <h2>Genieße fusselige
<Highlight>Qualität</Highlight>
ohne groß herumzurechnen.
</h2>
<p class="margin-top">Bei dir fällt ständig was an oder du hast ein langlaufendes Projekt, bei dem du immer wieder mal Unterstützung brauchst? Kein Ding. <p class="margin-top">Bei dir fällt ständig was an oder du hast ein langlaufendes Projekt, bei dem du immer wieder mal Unterstützung brauchst?
Hier gibt's die <Highlight>Entwickler-Flat</Highlight> für planbare Kosten und On-Demand-Entwicklung.</p> Kein Ding.
<p class="margin-top-small">Aus Transparenzgründen sei gesagt, dass sich <Highlight>alle Preise zzgl. 19 % Umsatzsteuer</Highlight> verstehen.</p> Hier gibt's die
<Highlight>Entwickler-Flat</Highlight>
für planbare Kosten und On-Demand-Entwicklung.
</p>
<p class="margin-top-small">Aus Transparenzgründen sei gesagt, dass sich
<Highlight>alle Preise zzgl. 19 % Umsatzsteuer</Highlight>
verstehen.
</p>
<FreeInfo /> <FreeInfo/>
<div class="Pricing margin-top"> <div class="Pricing margin-top">
<article v-for="(service, index) in flatrate" :class=" { 'z-2' : index === 1, 'z-1' : index !== 1 }"> <article v-for="(service, index) in flatrate" :class=" { 'z-2' : index === 1, 'z-1' : index !== 1 }">
<header> <header>
<span v-if="service.best" class="chip dark z-2"><Icon name="ph:fire-duotone" mode="svg"/> Beschd</span> <span v-if="service.best" class="chip dark z-2"><Icon name="ph:fire-duotone" mode="svg"/> Beschd</span>
<strong class="margin-top-small">{{service.title}}</strong> <strong class="margin-top-small">{{ service.title }}</strong>
<p class="claim">{{service.smallClaim}}</p> <p class="claim">{{ service.smallClaim }}</p>
<p class="price">{{intl.format(service.price)}}<span class="post">/ Monat</span></p> <p class="price">{{ intl.format(service.price) }}<span class="post">/ Monat</span></p>
<div aria-hidden="true" class="bg-icon"> <div aria-hidden="true" class="bg-icon">
<Icon :name="service.icon" size="1.5em" mode="svg" /> <Icon :name="service.icon" size="1.5em" mode="svg"/>
</div> </div>
</header> </header>
<main> <main>
<ul> <ul>
<li> <li>
<Icon class="icon yes" name="ph:check-circle-duotone" mode="svg" /> <Icon class="icon yes" name="ph:check-circle-duotone" mode="svg"/>
<span class="value">{{ service.hours }} Stunden pro Woche zugesichert</span> <span class="value">{{ service.hours }} Stunden pro Woche zugesichert</span>
</li> </li>
<li v-for="(check, index) in service.checks"> <li v-for="(check, index) in service.checks">
<Icon class="icon" :class="{ 'yes' : check, 'no' : !check }" :name="check ? 'ph:check-circle-duotone' : 'ph:x-circle-duotone'" mode="svg" /> <Icon class="icon" :class="{ 'yes' : check, 'no' : !check }" :name="check ? 'ph:check-circle-duotone' : 'ph:x-circle-duotone'"
mode="svg"/>
<span class="value">{{ points[index] }}</span> <span class="value">{{ points[index] }}</span>
</li> </li>
</ul> </ul>
@ -44,7 +55,7 @@
</div> </div>
<div v-if="faq" class="flex-col gap-sm margin-top"> <div v-if="faq" class="flex-col gap-sm margin-top">
<ContentRenderer :value="faq" :style="{ display: 'contents' }" /> <ContentRenderer :value="faq" :style="{ display: 'contents' }"/>
</div> </div>
</section> </section>
</template> </template>
@ -72,7 +83,7 @@ const intl = new Intl.NumberFormat(
maximumFractionDigits: 0, maximumFractionDigits: 0,
}) })
const points : string[] = [ const points: string[] = [
'Kontakt per E-Mail', 'Kontakt per E-Mail',
'Kontakt per Instant Messaging', 'Kontakt per Instant Messaging',
'Kontakt per Video Call', 'Kontakt per Video Call',
@ -80,65 +91,65 @@ const points : string[] = [
'Framework Migration', 'Framework Migration',
] ]
const flatrate : Service[] = const flatrate: Service[] =
[ [
{ {
title: 'Casual', title: 'Casual',
smallClaim: 'Für kleine Aufgaben nebenbei.', smallClaim: 'Für kleine Aufgaben nebenbei.',
icon: 'ph:baby-carriage-thin', icon: 'ph:baby-carriage-thin',
button: 'Jetzt klar machen', button: 'Jetzt klar machen',
link: 'https://tidycal.com/webfussel/flatrate-casual', link: 'https://tidycal.com/webfussel/flatrate-casual',
best: false, best: false,
price: 2950, price: 2950,
hours: 5, hours: 5,
contractMin: 3, contractMin: 3,
checks: [ checks: [
true, true,
false, false,
false, false,
false, false,
false, false,
], ],
}, },
{ {
title: 'Gold-Fussel', title: 'Gold-Fussel',
smallClaim: 'Wenn\'s mal wieder zu viel wird.', smallClaim: 'Wenn\'s mal wieder zu viel wird.',
icon: 'ph:coins-thin', icon: 'ph:coins-thin',
button: 'Jetzt Gold schürfen', button: 'Jetzt Gold schürfen',
link: 'https://tidycal.com/webfussel/flatrate-gold-fussel', link: 'https://tidycal.com/webfussel/flatrate-gold-fussel',
best: true, best: true,
price: 5555, price: 5555,
hours: 10, hours: 10,
contractMin: 3, contractMin: 3,
checks: [ checks: [
true, true,
true, true,
false, false,
true, true,
false, false,
], ],
}, },
{ {
title: 'Big Chonker', title: 'Big Chonker',
smallClaim: 'Für die richtig großen Sachen.', smallClaim: 'Für die richtig großen Sachen.',
icon: 'ph:skull-thin', icon: 'ph:skull-thin',
button: 'Jetzt Fett trimmen', button: 'Jetzt Fett trimmen',
link: 'https://tidycal.com/webfussel/flatrate-big-chonker', link: 'https://tidycal.com/webfussel/flatrate-big-chonker',
best: false, best: false,
price: 8550, price: 8550,
hours: 15, hours: 15,
contractMin: 6, contractMin: 6,
checks: [ checks: [
true, true,
true, true,
true, true,
true, true,
true, true,
], ],
} },
] ]
const { data : faq } = await useAsyncData('faq', () => queryCollection('faq').path('/snippets/faq/flatrate').first()) const { data: faq } = await useAsyncData('faq_flatrate', () => queryCollection('faq').path('/snippets/faq/flatrate').first())
const texts = generatePlainText<['title']>(faq.value?.body.value) const texts = generatePlainText<['title']>(faq.value?.body.value)
if (faq) { if (faq) {
@ -152,7 +163,7 @@ if (faq) {
'@type': 'Answer', '@type': 'Answer',
'text': entity.text, 'text': entity.text,
}, },
})) })),
}) })
} }
</script> </script>