REMOVE: RichText
Removed all traces of RichText implementation in Favor of NuxtContent
This commit is contained in:
parent
73f09ad76e
commit
4e953392fc
23 changed files with 38 additions and 412 deletions
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<article class="z-2 card flex-col margin-top font-big text-center">
|
||||
<p>Derzeit habe ich <span class="highlight">keine freien Plätze</span>.</p>
|
||||
<p class="margin-top-small">Das ändert sich ab <span class="highlight">01. Januar 2026</span>.</p>
|
||||
<p>Derzeit habe ich <Highlight>keine freien Plätze</Highlight>.</p>
|
||||
<p class="margin-top-small">Das ändert sich ab <Highlight>01. Januar 2026</Highlight>.</p>
|
||||
</article>
|
||||
</template>
|
3
app/components/Highlight.vue
Normal file
3
app/components/Highlight.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<span class="highlight"><slot /></span>
|
||||
</template>
|
3
app/components/Icon/LinkExternal.vue
Normal file
3
app/components/Icon/LinkExternal.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<Icon name="ph:arrow-square-out-duotone" mode="svg" />
|
||||
</template>
|
3
app/components/Icon/LinkInternal.vue
Normal file
3
app/components/Icon/LinkInternal.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<Icon name="ph:link-simple-duotone" mode="svg" />
|
||||
</template>
|
|
@ -1,40 +0,0 @@
|
|||
<template>
|
||||
<component :is="computedComponent.is" v-bind="computedComponent.props" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { RichText } from './Types'
|
||||
|
||||
type Props = {
|
||||
element : RichText
|
||||
}
|
||||
|
||||
const { element } = defineProps<Props>()
|
||||
|
||||
const computedComponent = computed(() => {
|
||||
let is : ReturnType<typeof resolveComponent> = {}
|
||||
|
||||
switch (element.type) {
|
||||
case 'plain':
|
||||
is = resolveComponent('RichTextPlain')
|
||||
break
|
||||
case 'p':
|
||||
is = resolveComponent('RichTextParagraph')
|
||||
break
|
||||
case 'span':
|
||||
is = resolveComponent('RichTextString')
|
||||
break
|
||||
case 'a':
|
||||
is = resolveComponent('RichTextLink')
|
||||
break
|
||||
case 'br':
|
||||
is = resolveComponent('RichTextNewLine')
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
return { is, props: { ...element } }
|
||||
})
|
||||
|
||||
</script>
|
|
@ -1,18 +0,0 @@
|
|||
<template>
|
||||
<a v-if="isExternal" :href="href" :target="target" class="text inline-flex-row">
|
||||
{{ content }}
|
||||
<Icon name="ph:arrow-square-out-duotone" mode="svg" />
|
||||
</a>
|
||||
<NuxtLink v-else :to="href" class="text inline-flex-row">
|
||||
{{ content }}
|
||||
<Icon name="ph:link-simple-duotone" mode="svg" />
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { RichTextLink } from './Types'
|
||||
|
||||
const { href } = defineProps<RichTextLink>()
|
||||
|
||||
const isExternal = href.startsWith('http')
|
||||
</script>
|
|
@ -1,3 +0,0 @@
|
|||
<template>
|
||||
<br>
|
||||
</template>
|
|
@ -1,11 +0,0 @@
|
|||
<template>
|
||||
<p :class="css">
|
||||
<RichTextGeneral v-for="element in children" :element="element" />
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { RichTextParagraph } from './Types'
|
||||
|
||||
defineProps<RichTextParagraph>()
|
||||
</script>
|
|
@ -1,9 +0,0 @@
|
|||
<template>
|
||||
{{ content }}
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { RichTextPlain } from './Types'
|
||||
|
||||
defineProps<RichTextPlain>()
|
||||
</script>
|
|
@ -1,20 +0,0 @@
|
|||
<template>
|
||||
<template v-if="Array.isArray(elements)">
|
||||
<General v-for="element in elements" :element="element" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<General :element="elements" />
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { RichText } from './Types'
|
||||
import General from './General.vue'
|
||||
|
||||
type Props = {
|
||||
elements : RichText | RichText[]
|
||||
}
|
||||
|
||||
|
||||
defineProps<Props>()
|
||||
</script>
|
|
@ -1,11 +0,0 @@
|
|||
<template>
|
||||
<span :class="css">
|
||||
{{ content }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { RichTextSpan } from './Types'
|
||||
|
||||
defineProps<RichTextSpan>()
|
||||
</script>
|
|
@ -1,30 +0,0 @@
|
|||
type RichTextBasis = {
|
||||
type: string
|
||||
content: string
|
||||
css ?: string
|
||||
}
|
||||
|
||||
export type RichTextPlain = RichTextBasis & {
|
||||
type: 'plain'
|
||||
}
|
||||
|
||||
export type RichTextParagraph = Omit<RichTextBasis, 'content'> & {
|
||||
type: 'p'
|
||||
children ?: RichText[]
|
||||
}
|
||||
|
||||
export type RichTextSpan = RichTextBasis & {
|
||||
type: 'span'
|
||||
}
|
||||
|
||||
export type RichTextLink = RichTextBasis & {
|
||||
type: 'a'
|
||||
href: string
|
||||
target ?: string
|
||||
}
|
||||
|
||||
export type RichTextNewLine = {
|
||||
type: 'br'
|
||||
}
|
||||
|
||||
export type RichText = RichTextPlain | RichTextParagraph | RichTextSpan | RichTextLink | RichTextNewLine
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<section id="services" class="Services content">
|
||||
<h1>Projekt buchen</h1>
|
||||
<h2>Du hast also beschlossen, dass du <span class="highlight">meine Hilfe</span> brauchst. Cool!</h2>
|
||||
<h2>Du hast also beschlossen, dass du <Highlight>meine Hilfe</Highlight> brauchst. Cool!</h2>
|
||||
<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 <span class="highlight">kleinere Projekte</span> zu buchen.</p>
|
||||
<p class="margin-top-small">Hinter diesen Angeboten gibt es <span class="highlight">keinerlei Abos oder versteckte Kosten</span>.
|
||||
Aus Transparenzgründen sei aber gesagt, dass sich <span class="highlight">alle Preise zzgl. 19 % Umsatzsteuer</span> verstehen.</p>
|
||||
völlig in Ordnung und genau deshalb biete ich dir die Möglichkeit mich gezielt für <Highlight>kleinere Projekte</Highlight> 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 />
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<section id="contact" class="Contact content full gap-default">
|
||||
<h1>Kontakt <span class="highlight">&</span> Social Media</h1>
|
||||
<h2>Kannst ruhig in meine <span class="highlight">DMs sliden</span>. Oder in's Postfach.</h2>
|
||||
<h1>Kontakt <Highlight>&</Highlight> Social Media</h1>
|
||||
<h2>Kannst ruhig in meine <Highlight>DMs sliden</Highlight>. Oder in's Postfach.</h2>
|
||||
|
||||
<article class="z-2 card flex-col gap-sm margin-top">
|
||||
<h3>Du willst einfach nur 'ne Mail schreiben?</h3>
|
||||
|
@ -12,7 +12,7 @@
|
|||
|
||||
<article class="z-2 card flex-col gap-sm margin-top">
|
||||
<h3>Ich auf Social Media</h3>
|
||||
<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 <span class="highlight">Fake</span>.
|
||||
<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.
|
||||
</p>
|
||||
<ul class="social-media">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<section id="customers" class="Customers content">
|
||||
<h1>Kunden <span class="highlight">&</span> Projekte.</h1>
|
||||
<h1>Kunden <Highlight>&</Highlight> Projekte.</h1>
|
||||
<h2>Meine bisherigen Geschäftpartner</h2>
|
||||
<div class="customer-list margin-top gap-default">
|
||||
<a v-for="customer in customers" :href="customer.link" target="_blank" rel="noopener noreferrer">
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<section id="services" class="Services content">
|
||||
<h1>Prepaid Flatrates</h1>
|
||||
<h2>Genieße fusselige <span class="highlight">Qualität</span> 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.
|
||||
Hier gibt's die <span class="highlight">Entwickler-Flat</span> für planbare Kosten und On-Demand-Entwicklung.</p>
|
||||
<p class="margin-top-small">Aus Transparenzgründen sei gesagt, dass sich <span class="highlight">alle Preise zzgl. 19 % Umsatzsteuer</span> 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 />
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<span class="tip">Ohne Tracker</span>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="inline-flex-row"><Icon name="ph:copyright-duotone" mode="svg"/> 2024 by <a href="https://webfussel.de">webfussel</a></p>
|
||||
<p class="inline-flex-row"><Icon name="ph:copyright-duotone" mode="svg"/> 2024 by <NuxtLink to="/">webfussel</NuxtLink></p>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
<div class="intro-text flex-col gap-default">
|
||||
<h1 class="flex-col">
|
||||
<span class="greeting inline-flex-row">Moin. <Icon name="ph:hand-peace-duotone" mode="svg"/></span>
|
||||
<span class="my-name-wrapper">Ich bin <span class="highlight">Fiona</span>.</span>
|
||||
<span class="my-name-wrapper">Ich bin <Highlight>Fiona</Highlight>.</span>
|
||||
</h1>
|
||||
<h2>
|
||||
Component <span class="highlight">&</span> API Entwicklerin
|
||||
Component <Highlight>&</Highlight> API Entwicklerin
|
||||
</h2>
|
||||
<p class="fulltext">
|
||||
Ich unterstütze Unternehmen dabei, ihre Daten von verschiedenen Endpunkten sauber aufzubereiten
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<section id="skills" class="Skills content">
|
||||
<h2>Meine Expertise.</h2>
|
||||
<h3>Dies sind meine <span class="highlight">Spezialgebiete</span> - aber ich bin flexibel!</h3>
|
||||
<h3>Dies sind meine <Highlight>Spezialgebiete</Highlight> - aber ich bin flexibel!</h3>
|
||||
<div class="skill-list margin-top gap-default">
|
||||
<Card v-for="skill in skills" :title="skill.title" titleTag="h3">
|
||||
<p v-for="(t, i) in skill.text" :class="[i === skill.text.length - 1 && 'bold']">{{t}}</p>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<template>
|
||||
<section id="skills_easy" class="Skills content">
|
||||
<h2>Jetzt mal ganz konkret.</h2>
|
||||
<h3>In diesem Abschnitt ganz <span class="highlight">ohne Technik-Blabla</span>.</h3>
|
||||
<h3>In diesem Abschnitt ganz <Highlight>ohne Technik-Blabla</Highlight>.</h3>
|
||||
<div class="skill-container flex-col margin-top gap-default">
|
||||
<ContentRenderer v-for="skill in skills" :key="skill.id" :value="skill" :style="{ display: 'contents' }" />
|
||||
</div>
|
||||
<div class="bottom flex-col margin-top gap-default">
|
||||
<h3>Verwirkliche jetzt dein Webprojekt.</h3>
|
||||
<Button href="/booking" class="cta">
|
||||
<Button href="/booking/" class="cta">
|
||||
<Icon name="ph:chat-circle-text-duotone" size="1.5em" mode="svg" />
|
||||
Lass mal reden
|
||||
</Button>
|
||||
|
@ -16,246 +16,5 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { RichText } from '@/components/RichText/Types'
|
||||
|
||||
type Skill = {
|
||||
img: string
|
||||
title: string
|
||||
text: RichText[]
|
||||
}
|
||||
|
||||
const getExplanationImage = (img : string) => getImage('/img/explanations/', img)
|
||||
|
||||
// const skills : Skill[] = [
|
||||
// {
|
||||
// img: 'components',
|
||||
// title: 'Das, was du sehen kannst',
|
||||
// text: [
|
||||
// {
|
||||
// type: 'p',
|
||||
// children: [
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'Die meisten Anwendungen haben eine grafische Benutzeroberfläche - die so genannte GUI. Wenn etwas graphisch ist, ' +
|
||||
// 'dann bedeutet das auch natürlich, dass es sinnvoll dargestellt werden muss. Dafür verwenden wir kleine Bausteine, die wir Komponenten nennen.',
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// type: 'p',
|
||||
// children: [
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'Grundsätzlich lassen sich komplette Anwendungen und auch einfache Webseiten ziemlich cool über Komponenten aufbauen, sodass wir wiederkehrende Elemente ' +
|
||||
// 'wie Buttons, Textabschnitte, Links oder Teaser immer wieder verwenden können - selbst wenn sich diese in ihren Details wie Farben oder Icons unterscheiden.',
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// type: 'p',
|
||||
// children: [
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'Diese Komponenten so zu entwickeln, dass sie wirklich flexibel sind und auch perfekt mit dem Design übereinstimmen ist gar nicht so einfach, denn oft sollten sie ' +
|
||||
// 'auch mehr können als im Design kurzfristig ersichtlich ist.',
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// type: 'p',
|
||||
// css: 'place-bottom bold',
|
||||
// children: [
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'Diese Voraussicht, für den Fall der Fälle vorzusorgen:',
|
||||
// },
|
||||
// {
|
||||
// type: 'br',
|
||||
// },
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'Die gibt\'s bei mir dazu.',
|
||||
// },
|
||||
// {
|
||||
// type: 'br',
|
||||
// },
|
||||
// {
|
||||
// type: 'span',
|
||||
// css: 'highlight',
|
||||
// content: 'Fussel-Ehrenwort.'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// ],
|
||||
// }, {
|
||||
// img: 'cms',
|
||||
// title: 'Da, wo du eintragen kannst',
|
||||
// text: [
|
||||
// {
|
||||
// type: 'p',
|
||||
// children: [
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'In vielen Fällen ist es natürlich praktisch, wenn du einfach Inhalte einer Seite auf das ändern kannst, was gerade aktuell ist, ohne auf andere angewiesen zu sein.'
|
||||
// + 'Damit das reibungslos möglich ist, entwickle ich dir gerne eine Anwendung oder Homepage, deren Inhalte du komplett selbst auf dem neuesten Stand halten kannst - und zwar '
|
||||
// + 'mit einem sogenannten CMS - ein ',
|
||||
// },
|
||||
// {
|
||||
// type: 'span',
|
||||
// css: 'highlight',
|
||||
// content: 'C'
|
||||
// },
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'ontent '
|
||||
// },
|
||||
// {
|
||||
// type: 'span',
|
||||
// css: 'highlight',
|
||||
// content: 'M'
|
||||
// },
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'anagement '
|
||||
// },
|
||||
// {
|
||||
// type: 'span',
|
||||
// css: 'highlight',
|
||||
// content: 'S'
|
||||
// },
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'ystem.'
|
||||
// },
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// type: 'p',
|
||||
// children: [
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'Für CMS setze ich in erster Linie auf die cloudbasierte Lösung ',
|
||||
// },
|
||||
// {
|
||||
// type: 'a',
|
||||
// target: '_blank',
|
||||
// css: 'text',
|
||||
// href: 'https://www.storyblok.com',
|
||||
// content: 'Storyblok'
|
||||
// },
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: '. Dies stellt für die Meisten eine kostenlose bis kostengünstige Lösung dar ohne viel technisches Wissen mitbringen zu müssen.',
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// type: 'p',
|
||||
// children: [
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'Falls du aber nicht möchtest, dass deine Daten auf irgendeinem Fremden server liegen - was ich durchaus verstehen kann! - dann gibt es auch die Möglichkeit mit ',
|
||||
// },
|
||||
// {
|
||||
// type: 'a',
|
||||
// target: '_blank',
|
||||
// css: 'text',
|
||||
// href: 'https://www.strapi.io',
|
||||
// content: 'Strapi'
|
||||
// },
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: ' selbst das eigene CMS zu hosten. Das musst du dann aber allerdings selbst erledigen oder ich erledige das für dich für einen Aufpreis.',
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// type: 'p',
|
||||
// css: 'place-bottom bold',
|
||||
// children: [
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'Nie wieder jemand anderen Fragen zu müssen, um deine Website auf dem neuesten Stand zu halten.',
|
||||
// },
|
||||
// {
|
||||
// type: 'br',
|
||||
// },
|
||||
// {
|
||||
// type: 'span',
|
||||
// css: 'highlight',
|
||||
// content: 'Mit Fussel-Garantie.'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// ],
|
||||
// }, {
|
||||
// img: 'result',
|
||||
// title: 'Was dabei am Ende rauskommt',
|
||||
// text: [
|
||||
// {
|
||||
// type: 'p',
|
||||
// children: [
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'Grundsätzlich lässt sich das ganz einfach zusammenfassen: ',
|
||||
// },
|
||||
// {
|
||||
// type: 'span',
|
||||
// css: 'highlight',
|
||||
// content: 'Dein persönlicher Webauftritt.',
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// type: 'p',
|
||||
// children: [
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'Ob du nun etwas kleineres brauchst, um ein paar Hobbies zu zeigen. Oder vielleicht etwas größeres, weil du dir ein eigenes Business aufbauen willst. Eventuell ein eigener Blog, eine komplette Applikation oder '
|
||||
// + 'die Möglichkeit für andere Leute deine Daten bereit zu stellen. All das, das kann ich dir mit meinen Fähigkeiten und meiner Erfahrung bieten.'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// type: 'p',
|
||||
// children: [
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'Erkunde einfach meine ',
|
||||
// },
|
||||
// {
|
||||
// type: 'a',
|
||||
// href: '/references',
|
||||
// content: 'Referenzen'
|
||||
// },
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: ' und dir wird auffallen, dass diese äußerst durchmischt und bunt sind. So individuell wie die Projekte meiner bisherigen Kunden wird auch dein Projekt behandelt. Und auch, wenn '
|
||||
// + 'du glaubst, dass die Referenzen nicht zu deinem Projekt passen, werden wir deine ganz individuelle Lösung gemeinsam erarbeiten.'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// type: 'p',
|
||||
// css: 'place-bottom bold',
|
||||
// children: [
|
||||
// {
|
||||
// type: 'plain',
|
||||
// content: 'Denn jedes Projekt ist etwas eigenes und besonderes.',
|
||||
// },
|
||||
// {
|
||||
// type: 'br',
|
||||
// },
|
||||
// {
|
||||
// type: 'span',
|
||||
// css: 'highlight',
|
||||
// content: 'Auch deins.'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// ],
|
||||
// }
|
||||
// ]
|
||||
|
||||
const skills = await queryCollection('skills').all()
|
||||
</script>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue