fix: FAQ in NuxtContent
FAQ converted to NuxtContent
This commit is contained in:
parent
8668b96eff
commit
48efe0f75b
14 changed files with 151 additions and 96 deletions
|
@ -123,6 +123,10 @@ a.mail {
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.row {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
.Spoiler {
|
.Spoiler {
|
||||||
background: var(--color-black);
|
background: var(--color-black);
|
||||||
padding: 1rem 2rem;
|
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
|
|
||||||
& .icon {
|
& .icon {
|
||||||
|
@ -17,13 +16,20 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
border-radius: 20px;
|
||||||
|
transition: 150ms ease-in-out;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(0, 0, 0, .3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& > div {
|
& > div {
|
||||||
margin-top: 1rem;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
padding: 1rem 2rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="Burger" :class="{ open }">
|
<div class="Burger" :class="{ open }">
|
||||||
<nav class="z-4" ref="navElement">
|
<nav class="z-4" ref="navElement">
|
||||||
<ul>
|
<ul class="row">
|
||||||
<li v-for="({label, to, aria, icon}) in navigation" :key="label">
|
<li v-for="({label, to, aria, icon}) in navigation" :key="label">
|
||||||
<NuxtLink :to="to" :aria-label="aria" active-class="active" class="inline-flex-row big-gap" @click="close">
|
<NuxtLink :to="to" :aria-label="aria" active-class="active" class="inline-flex-row big-gap" @click="close">
|
||||||
<Icon :name="icon" mode="svg" />
|
<Icon :name="icon" mode="svg" />
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<main>
|
<main>
|
||||||
<small class="customer">{{ company }}</small>
|
<small class="customer">{{ company }}</small>
|
||||||
<h3 class="title">{{ title }}</h3>
|
<h3 class="title">{{ title }}</h3>
|
||||||
<ul>
|
<ul class="row">
|
||||||
<li v-for="skill in tech">
|
<li v-for="skill in tech">
|
||||||
<Technology v-bind="skill" link="" />
|
<Technology v-bind="skill" link="" />
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -43,8 +43,8 @@
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex-col gap-sm margin-top">
|
<div v-if="faq" class="flex-col gap-sm margin-top">
|
||||||
<Spoiler v-for="entry in faq" v-bind="entry" class="z-2" />
|
<ContentRenderer :value="faq" :style="{ display: 'contents' }" />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
@ -71,7 +71,8 @@ const intl = new Intl.NumberFormat(
|
||||||
currency: 'EUR',
|
currency: 'EUR',
|
||||||
minimumFractionDigits: 0,
|
minimumFractionDigits: 0,
|
||||||
maximumFractionDigits: 0,
|
maximumFractionDigits: 0,
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const oneOff : Service[] = [
|
const oneOff : Service[] = [
|
||||||
{
|
{
|
||||||
|
@ -128,36 +129,5 @@ const oneOff : Service[] = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const faq = [
|
const faq = await queryCollection('faq').path('/snippets/faq/booking').first()
|
||||||
{
|
|
||||||
header: 'Warum machst du keine Stundensätze?',
|
|
||||||
content: [
|
|
||||||
'Ich finde Stundensätze haben für beide Seiten nur Nachteile:',
|
|
||||||
'Wenn ich schnell und gut arbeite, dann bekomme ich weniger Geld. Hab ich mal einen Knoten im Gehirn und brauche sehr lange, muss der Kunde mehr zahlen.',
|
|
||||||
'Klar kann man sagen, dass sich das irgendwann ausgleichen könnte - aber so weit will ich es garnicht erst kommen lassen.'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Welche Themen bietest du für deine Schulungen an?',
|
|
||||||
content: [
|
|
||||||
'Sprachen: JavaScript, TypeScript, HTML, CSS',
|
|
||||||
'Frameworks: Vue, Nuxt',
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Wo finden die Schulungen statt?',
|
|
||||||
content: [
|
|
||||||
'Die Schulungen finden online statt. Normalerweise nutze ich dafür Google Meet, aber wenn du oder deine Firma eine andere Plattform wünschen und bereitstellen bin ich natürlich flexibel.',
|
|
||||||
'Wenn sich deine Firma in der Nähe meines Wohnortes befindet - und damit meine ich "In einer Stunde mit der Straßenbahn zu erreichen", dann kann alles natürlich auch vor Ort stattfinden.',
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Ich hab ein cooles Projekt! Aber kein Geld...',
|
|
||||||
content: [
|
|
||||||
'Tja.',
|
|
||||||
'Ne, awas. Meld dich einfach trotzdem über meine E-Mail-Adresse und vielleicht finden wir eine Lösung.'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<p>Falls du irgendwo einen anderen Social Media Account von mir findest, der nicht hier aufgelistet ist, aber aktiv postet, dann ist dieser höchstwahrscheinlich <Highlight>Fake</Highlight>.
|
<p>Falls du irgendwo einen anderen Social Media Account von mir findest, der nicht hier aufgelistet ist, aber aktiv postet, dann ist dieser höchstwahrscheinlich <Highlight>Fake</Highlight>.
|
||||||
<br />Meld' dich gerne bei mir, wenn du so einen findest.
|
<br />Meld' dich gerne bei mir, wenn du so einen findest.
|
||||||
</p>
|
</p>
|
||||||
<ul class="social-media">
|
<ul class="row social-media">
|
||||||
<li v-for="({icon, name, ...rest}) in socials" :key="rest.href">
|
<li v-for="({icon, name, ...rest}) in socials" :key="rest.href">
|
||||||
<a v-bind="rest" target="_blank">
|
<a v-bind="rest" target="_blank">
|
||||||
<Icon :name="icon" :alt="rest['aria-label']" size="1.5em" mode="svg" />
|
<Icon :name="icon" :alt="rest['aria-label']" size="1.5em" mode="svg" />
|
||||||
|
|
|
@ -43,8 +43,8 @@
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex-col gap-sm margin-top">
|
<div v-if="faq" class="flex-col gap-sm margin-top">
|
||||||
<Spoiler v-for="entry in faq" v-bind="entry" class="z-2" />
|
<ContentRenderer :value="faq" :style="{ display: 'contents' }" />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
@ -138,48 +138,5 @@ const flatrate : Service[] =
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const faq = [
|
const faq = await queryCollection('faq').path('/snippets/faq/flatrate').first()
|
||||||
{
|
|
||||||
header: 'Was ist eine Entwickler-Flatrate?',
|
|
||||||
content: [
|
|
||||||
'Die Entwickler-Flatrate ist ein Angebot, bei dem du für eine bestimmte Zeit eine bestimmte Menge an Leistungen erhältst.',
|
|
||||||
'Sie wird auch oft als sogenannter "Retainer" bezeichnet und ist eine günstige Art immer wieder anfallende Aufgaben auszulagern.'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Wie läuft die Zusammenarbeit ab?',
|
|
||||||
content: [
|
|
||||||
'Nach einer ersten Analyse deines Projekts legen wir gemeinsam den Umfang und die monatlichen Aufgaben fest. Du kannst mich je nach Paket auf den vereinbarten Wegen jederzeit kontaktieren.',
|
|
||||||
'Die Bearbeitung erfolgt innerhalb der vereinbarten Fristen.',
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Wie wird abgerechnet?',
|
|
||||||
content: [
|
|
||||||
'Du zahlst monatlich einen festen Betrag im Prepaid-Format unabhängig davon wie viele Aufgaben tatsächlich anfallen.',
|
|
||||||
'Dadurch kannst du dein Budget besser einplanen und Aufgaben verteilen.'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Kann ich den Retainer jederzeit kündigen?',
|
|
||||||
content: [
|
|
||||||
'Ja klar. Du musst dabei nur die Mindestvertragslaufzeit beachten - die bezahlte Leistung steht dir weiterhin zu.',
|
|
||||||
'Falls wir merken, dass wir für eine Zusammenarbeit mehr als ungeeignet sind, bekommst du dein Geld anteilig der verbleibenden Zeit zurück und verlierst den Anspruch auf Leistungen ab diesem Zeitpunkt.'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Was passiert, wenn ich dich mal weniger brauche?',
|
|
||||||
content: [
|
|
||||||
'Der monatliche feste Betrag bleibt bestehen. Ähnlich wie bei einer Versicherung bezahlst du hier für den Fall, dass du mich brauchst und erhältst dann entsprechend die vereinbarten Leistungen.',
|
|
||||||
'Wenn du merkst, dass du mich nicht mehr brauchst, dann kannst du den Vertrag jederzeit kündigen und die Leistungen auslaufen lassen.'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Für wen lohnt sich sowas überhaupt?',
|
|
||||||
content: [
|
|
||||||
'Vor allem Unternehmen, bei denen immer wieder Aufgaben anfallen für die sich aber kein komplettes Projekt oder gar eine feste Stelle in der Firma lohnt, profitieren von dieser Art von Leistung.',
|
|
||||||
'Sie ist ideal für eine langfristige und zuverlässige Zusammenarbeit.'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<footer class="Footer flex-col gap-default">
|
<footer class="Footer flex-col gap-default">
|
||||||
<ul class="sitemap gap-default">
|
<ul class="row sitemap gap-default">
|
||||||
<li v-for="{ label, ...rest} in nav" :key="label">
|
<li v-for="{ label, ...rest} in nav" :key="label">
|
||||||
<NuxtLink v-bind="rest">{{label}}</NuxtLink>
|
<NuxtLink v-bind="rest">{{label}}</NuxtLink>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="sitemap gap-default">
|
<ul class="row sitemap gap-default">
|
||||||
<li v-for="({icon, ...rest}) in socials" :key="rest.href">
|
<li v-for="({icon, ...rest}) in socials" :key="rest.href">
|
||||||
<a v-bind="rest" target="_blank">
|
<a v-bind="rest" target="_blank">
|
||||||
<Icon :name="icon" :alt="rest['aria-label']" size="1.5em" mode="svg" />
|
<Icon :name="icon" :alt="rest['aria-label']" size="1.5em" mode="svg" />
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="sitemap gap-default">
|
<ul class="row sitemap gap-default">
|
||||||
<li class="tip-container">
|
<li class="tip-container">
|
||||||
<Icon name="wf:cookie-slash" size="1.5rem" mode="svg" />
|
<Icon name="wf:cookie-slash" size="1.5rem" mode="svg" />
|
||||||
<span class="tip">Ohne Cookies</span>
|
<span class="tip">Ohne Cookies</span>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<Icon name="ph:waves" mode="svg" size="2em" />
|
<Icon name="ph:waves" mode="svg" size="2em" />
|
||||||
</button>
|
</button>
|
||||||
<nav>
|
<nav>
|
||||||
<ul class="main-nav">
|
<ul class="row main-nav">
|
||||||
<li v-for="({label, to, aria, icon}) in navigation" :key="label">
|
<li v-for="({label, to, aria, icon}) in navigation" :key="label">
|
||||||
<NuxtLink :to="to" :aria-label="aria" active-class="active" class="inline-flex-row big-gap">
|
<NuxtLink :to="to" :aria-label="aria" active-class="active" class="inline-flex-row big-gap">
|
||||||
<Icon :name="icon" mode="svg" />
|
<Icon :name="icon" mode="svg" />
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
</div>
|
</div>
|
||||||
<Card title="Technologien" titleTag="h3" class="margin-top tech-list">
|
<Card title="Technologien" titleTag="h3" class="margin-top tech-list">
|
||||||
<p>Neben den klassischen Webentwicklungsstandards JavaScript, HTML und CSS biete ich außerdem folgende Technologien.</p>
|
<p>Neben den klassischen Webentwicklungsstandards JavaScript, HTML und CSS biete ich außerdem folgende Technologien.</p>
|
||||||
<ul class="gap-default margin-top-small">
|
<ul class="row gap-default margin-top-small">
|
||||||
<li v-for="tech in technologies">
|
<li v-for="tech in technologies">
|
||||||
<Technology v-bind="tech" size="l"/>
|
<Technology v-bind="tech" size="l"/>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<details class="Spoiler" :open="open" @click="toggle">
|
<details class="Spoiler" :open="open">
|
||||||
<summary><Icon class="icon" :name="icon" mode="svg" />{{ header }}</summary>
|
<summary @click="toggle"><Icon class="icon" :name="icon" mode="svg" />{{ title }}</summary>
|
||||||
<div>
|
<div>
|
||||||
<p v-for="text in content">{{ text }}</p>
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
type Props = {
|
type Props = {
|
||||||
header: string
|
title: string
|
||||||
content: string[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProps<Props>()
|
defineProps<Props>()
|
||||||
|
|
|
@ -18,6 +18,14 @@ export default defineContentConfig({
|
||||||
position: z.string(),
|
position: z.string(),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
}),
|
||||||
|
|
||||||
|
faq: defineCollection({
|
||||||
|
type: 'page',
|
||||||
|
source: 'snippets/faq/*.md',
|
||||||
|
schema: z.object({
|
||||||
|
title: z.string(),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
58
content/snippets/faq/booking.md
Normal file
58
content/snippets/faq/booking.md
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
::spoiler
|
||||||
|
---
|
||||||
|
title: "Warum machst du keine Stundensätze?"
|
||||||
|
---
|
||||||
|
Ich finde, Stundensätze haben für beide Seiten nur Nachteile:
|
||||||
|
|
||||||
|
Wenn ich schnell und gut arbeite, bekomme ich weniger Geld. Hab ich mal einen Knoten im Gehirn und brauche sehr lange, muss der Kunde mehr zahlen.
|
||||||
|
|
||||||
|
Klar kann man sagen, dass sich das irgendwann ausgleichen könnte – aber so weit will ich es gar nicht erst kommen lassen.
|
||||||
|
::
|
||||||
|
|
||||||
|
::spoiler
|
||||||
|
---
|
||||||
|
title: "Was bekomme ich denn für die 999 €?"
|
||||||
|
---
|
||||||
|
Grundsätzlich kommt das natürlich immer darauf an, was du genau willst. Da spielen einige Faktoren eine Rolle.
|
||||||
|
|
||||||
|
Ein Beispiel für eine 999 € Seite wäre:
|
||||||
|
- Kein CMS
|
||||||
|
- 2 Sections auf der Landingpage
|
||||||
|
- Impressum, Datenschutzerklärung
|
||||||
|
- Standarddesign
|
||||||
|
|
||||||
|
Je nach dem was du willst, kann sich das aber auch anders zusammensetzen.
|
||||||
|
::
|
||||||
|
|
||||||
|
::spoiler
|
||||||
|
---
|
||||||
|
title: "Welche Themen bietest du für deine Schulungen an?"
|
||||||
|
---
|
||||||
|
<div>
|
||||||
|
<Highlight>Sprachen</Highlight>
|
||||||
|
<br />JavaScript, TypeScript, HTML, CSS
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Highlight>Frameworks</Highlight>
|
||||||
|
<br />Vue, Nuxt
|
||||||
|
</div>
|
||||||
|
::
|
||||||
|
|
||||||
|
::spoiler
|
||||||
|
---
|
||||||
|
title: "Wo finden die Schulungen statt?"
|
||||||
|
---
|
||||||
|
Die Schulungen finden <Highlight>online/Highlight> statt. Normalerweise nutze ich dafür Google Meet, aber wenn du oder deine Firma eine andere Plattform wünschen und bereitstellen bin ich natürlich flexibel.
|
||||||
|
|
||||||
|
Wenn sich deine Firma in der Nähe meines Wohnortes befindet – und damit meine ich "In einer Stunde mit der Straßenbahn zu erreichen", dann kann alles natürlich auch vor Ort stattfinden.
|
||||||
|
::
|
||||||
|
|
||||||
|
::spoiler
|
||||||
|
---
|
||||||
|
title: "Ich hab ein cooles Projekt! Aber kein Geld …"
|
||||||
|
---
|
||||||
|
Tja.
|
||||||
|
|
||||||
|
Ne, awas. Meld dich einfach trotzdem über meine E-Mail-Adresse und vielleicht finden wir eine Lösung.
|
||||||
|
::
|
53
content/snippets/faq/flatrate.md
Normal file
53
content/snippets/faq/flatrate.md
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
::spoiler
|
||||||
|
---
|
||||||
|
title: "Was ist eine Entwickler-Flatrate?"
|
||||||
|
---
|
||||||
|
Die Entwickler-Flatrate ist ein Angebot, bei dem du für eine bestimmte Zeit eine bestimmte Menge an Leistungen erhältst.
|
||||||
|
|
||||||
|
Sie wird auch oft als sogenannter "Retainer" bezeichnet und ist eine günstige Art, immer wieder anfallende Aufgaben auszulagern.
|
||||||
|
::
|
||||||
|
|
||||||
|
::spoiler
|
||||||
|
---
|
||||||
|
title: "Wie läuft die Zusammenarbeit ab?"
|
||||||
|
---
|
||||||
|
Nach einer ersten Analyse deines Projekts legen wir gemeinsam den Umfang und die monatlichen Aufgaben fest. Du kannst mich je nach Paket auf den vereinbarten Wegen jederzeit kontaktieren.
|
||||||
|
|
||||||
|
Die Bearbeitung erfolgt innerhalb der vereinbarten Fristen.
|
||||||
|
::
|
||||||
|
|
||||||
|
::spoiler
|
||||||
|
---
|
||||||
|
title: "Wie wird abgerechnet?"
|
||||||
|
---
|
||||||
|
Du zahlst monatlich einen festen Betrag im Prepaid-Format unabhängig davon, wie viele Aufgaben tatsächlich anfallen.
|
||||||
|
|
||||||
|
Dadurch kannst du dein Budget besser einplanen und Aufgaben verteilen.
|
||||||
|
::
|
||||||
|
|
||||||
|
::spoiler
|
||||||
|
---
|
||||||
|
title: "Kann ich den Retainer jederzeit kündigen?"
|
||||||
|
---
|
||||||
|
Ja klar. Du musst dabei nur die Mindestvertragslaufzeit beachten – die bezahlte Leistung steht dir weiterhin zu.
|
||||||
|
|
||||||
|
Falls wir merken, dass wir für eine Zusammenarbeit mehr als ungeeignet sind, bekommst du dein Geld anteilig der verbleibenden Zeit zurück und verlierst den Anspruch auf Leistungen ab diesem Zeitpunkt.
|
||||||
|
::
|
||||||
|
|
||||||
|
::spoiler
|
||||||
|
---
|
||||||
|
title: "Was passiert, wenn ich dich mal weniger brauche?"
|
||||||
|
---
|
||||||
|
Der monatliche feste Betrag bleibt bestehen. Ähnlich wie bei einer Versicherung bezahlst du hier für den Fall, dass du mich brauchst, und erhältst dann entsprechend die vereinbarten Leistungen.
|
||||||
|
|
||||||
|
Wenn du merkst, dass du mich nicht mehr brauchst, dann kannst du den Vertrag jederzeit kündigen und die Leistungen auslaufen lassen.
|
||||||
|
::
|
||||||
|
|
||||||
|
::spoiler
|
||||||
|
---
|
||||||
|
title: "Für wen lohnt sich sowas überhaupt?"
|
||||||
|
---
|
||||||
|
Vor allem Unternehmen, bei denen immer wieder Aufgaben anfallen, für die sich aber kein komplettes Projekt oder gar eine feste Stelle in der Firma lohnt, profitieren von dieser Art von Leistung.
|
||||||
|
|
||||||
|
Sie ist ideal für eine langfristige und zuverlässige Zusammenarbeit.
|
||||||
|
::
|
Loading…
Add table
Add a link
Reference in a new issue