add: OpenGraph image, timeline card state

Added three states to timeline card, added open graph image and description
This commit is contained in:
Fiona Lena Urban 2025-05-23 08:58:14 +02:00
parent f75d66a0d0
commit d71e59b9c0
12 changed files with 112 additions and 34 deletions

View file

@ -26,6 +26,10 @@
.home-text { .home-text {
padding: var(--padding-xxl) var(--padding-default); padding: var(--padding-xxl) var(--padding-default);
text-align: center; text-align: center;
& h3:has(+ .padding) {
margin-bottom: 0;
}
} }
.timeline { .timeline {

View file

@ -2,7 +2,7 @@
position: relative; position: relative;
width: 100%; width: 100%;
color: var(--color-darkest); color: var(--color-darkest);
border-bottom: 1px solid var(--color-light); border-bottom: 1px dashed var(--color-light);
.bottom { .bottom {
position: absolute; position: absolute;

View file

@ -6,7 +6,7 @@
border-radius: var(--radius-default); border-radius: var(--radius-default);
padding: var(--padding-xs); padding: var(--padding-xs);
& .icon { & > .icon {
flex: 0 0 25%; flex: 0 0 25%;
font-size: var(--font-size-xxl); font-size: var(--font-size-xxl);
color: var(--color-main-dark); color: var(--color-main-dark);
@ -16,4 +16,13 @@
text-align: left; text-align: left;
flex-grow: 1; flex-grow: 1;
} }
& .state {
--color: var(--color-darkest);
display: flex;
align-items: center;
gap: var(--padding-xxs);
margin-top: var(--padding-s);
color: var(--color);
}
} }

View file

@ -58,11 +58,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { Card } from '../../../shared/Card' import type { PriceCard } from '../../../shared/PriceCard'
type Props = { type Props = {
deletable: boolean deletable: boolean
card: Card card: PriceCard
} }
const { card } = defineProps<Props>() const { card } = defineProps<Props>()

View file

@ -86,11 +86,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { Card } from '../../../shared/Card' import type { PriceCard } from '../../../shared/PriceCard'
type Props = { type Props = {
currentCardIndex: number currentCardIndex: number
currentCard?: Card currentCard?: PriceCard
} }
const { currentCardIndex, currentCard } = defineProps<Props>() const { currentCardIndex, currentCard } = defineProps<Props>()

View file

@ -4,16 +4,48 @@
<div class="text"> <div class="text">
<strong>{{ title }}</strong> <strong>{{ title }}</strong>
<p>{{ description }}</p> <p>{{ description }}</p>
<div class="state" :style="{
'--color': stateColor,
}">
<Icon :name="stateIcon" mode="svg" />
<span>{{ stateMessage }}</span>
</div>
</div> </div>
</article> </article>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
type Props = { import type { TimelineCard, TimelineState } from '../../../shared/TimelineCard'
icon: string
title: string
description: string const { state } = defineProps<TimelineCard>()
const icons : Record<TimelineState, string> = {
planned: 'uil:clock',
inProgress: 'uil:cog',
done: 'uil:check-circle'
} }
defineProps<Props>() const colors : Record<TimelineState, string> = {
planned: 'var(--color-darkest)',
inProgress: 'var(--color-main-dark)',
done: 'var(--color-accent-darkest)',
}
const stateColor = computed(() => colors[state.value])
const stateIcon = computed(() => icons[state.value])
const stateMessage = computed(() => {
switch (state.value) {
case 'planned':
let planned = 'Geplant'
if (state.message) planned += ` für ${state.message}`
return planned
case 'inProgress':
return 'In Bearbeitung'
case 'done':
let done = 'Abgeschlossen'
if (state.message) done += ` am ${state.message}`
return done
}
})
</script> </script>

View file

@ -22,6 +22,9 @@
<h3> <h3>
Wir haben noch viel vor! Wir haben noch viel vor!
</h3> </h3>
<p class="padding">
Für ProPapier sind über die nächste Zeit noch einige weitere Features geplant.
</p>
<div class="timeline"> <div class="timeline">
<PpTimelineCard <PpTimelineCard
v-for="card in timeline" v-for="card in timeline"
@ -33,46 +36,62 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { TimelineCard } from '../../shared/TimelineCard'
definePageMeta({ definePageMeta({
layout: 'landingpage' layout: 'landingpage'
}) })
type Card = { const timeline : TimelineCard[] = [
icon: string
title: string
description: string
}
const timeline : Card[] = [
{ {
icon: 'uil:chart-bar', icon: 'uil:chart-bar',
title: 'Mehr Vergleiche', title: 'Mehr Vergleiche',
description: 'Zusätzliche Kategorien für Taschentücher und Küchenrolle', description: 'Zusätzliche Kategorien für Taschentücher und Küchenrolle',
state: {
value: 'inProgress',
}
}, },
{ {
icon: 'uil:cloud-database-tree', icon: 'uil:cloud-database-tree',
title: 'Datenbank', title: 'Datenbank',
description: 'Eine von der Community gestützte Datenbank mit Preisen für alle Produkte' description: 'Eine von der Community gestützte Datenbank mit Preisen für alle Produkte',
state: {
value: 'planned',
message: '2025',
}
}, },
{ {
icon: 'uil:qrcode-scan', icon: 'uil:qrcode-scan',
title: 'Barcode Scan', title: 'Barcode Scan',
description: 'Ganz einfach Barcode Scannen und Produkt direkt zum Rechner hinzufügen' description: 'Ganz einfach Barcode Scannen und Produkt direkt zum Rechner hinzufügen',
state: {
value: 'planned',
message: '2025',
}
}, },
{ {
icon: 'uil:user', icon: 'uil:user',
title: 'Optionale Accounts', title: 'Optionale Accounts',
description: 'Zur Synchronisierung auf mehreren Geräten' description: 'Zur Synchronisierung auf mehreren Geräten',
state: {
value: 'planned',
}
}, },
{ {
icon: 'uil:cog', icon: 'uil:cog',
title: 'Personalisierung', title: 'Personalisierung',
description: 'Persönliche Präferenzen zur Wortwahl, Standardsortierung und mehr' description: 'Persönliche Präferenzen zur Wortwahl, Standardsortierung und mehr',
state: {
value: 'planned',
}
}, },
{ {
icon: 'uil:vector-square', icon: 'uil:vector-square',
title: 'm² Preise', title: 'm² Preise',
description: 'Quadratmeterpreise für noch genauere Vergleiche' description: 'Quadratmeterpreise für noch genauere Vergleiche',
state: {
value: 'planned',
}
}, },
] ]
</script> </script>

View file

@ -46,19 +46,19 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { Card } from '../../shared/Card' import type { PriceCard } from '../../shared/PriceCard'
import type { Button } from '../../shared/ButtonGroup' import type { Button } from '../../shared/ButtonGroup'
import { PpPriceCardDialog, PpDeleteDialog, PpPriceCard } from '#components' import { PpPriceCardDialog, PpDeleteDialog, PpPriceCard } from '#components'
const cards = useLocalStorage<Card[]>('cards', []) const cards = useLocalStorage<PriceCard[]>('cards', [])
const currentSort = useLocalStorage<number>('sort', 0) const currentSort = useLocalStorage<number>('sort', 0)
const currentCard = ref<Card>() const currentCard = ref<PriceCard>()
const currentCardIndex = ref<number>(-1) const currentCardIndex = ref<number>(-1)
const modal = useTemplateRef<typeof PpPriceCardDialog>('modal') const modal = useTemplateRef<typeof PpPriceCardDialog>('modal')
const deleteModal = useTemplateRef<typeof PpDeleteDialog>('deleteModal') const deleteModal = useTemplateRef<typeof PpDeleteDialog>('deleteModal')
const priceCards = useTemplateRef<(typeof PpPriceCard)[]>('priceCard') const priceCards = useTemplateRef<(typeof PpPriceCard)[]>('priceCard')
const createCard = (uuid : string) : Card => ({ const createCard = (uuid : string) : PriceCard => ({
uuid, uuid,
name: '', name: '',
price: '', price: '',
@ -68,7 +68,7 @@ const createCard = (uuid : string) : Card => ({
}) })
const addCard = (card : Card) => { const addCard = (card : PriceCard) => {
cards.value.unshift({ ...card }) cards.value.unshift({ ...card })
sort() sort()
} }

View file

@ -1,4 +1,6 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
const description = 'Bezahlt du zuviel fürs Papier? Vergleiche schnell und unkompliziert die Preise für Toiletten-, Küchen- und andere Papier hier.'
export default defineNuxtConfig({ export default defineNuxtConfig({
compatibilityDate: '2024-11-01', compatibilityDate: '2024-11-01',
devtools: { enabled: false }, devtools: { enabled: false },
@ -73,7 +75,7 @@ export default defineNuxtConfig({
seo: { seo: {
meta: { meta: {
title: 'ProPapier', title: 'ProPapier',
description: '"Bezahlt du zuviel fürs Papier? Vergleiche schnell und unkompliziert die Preise für Toiletten-, Küchen- und andere Papier hier."', description,
themeColor: [ themeColor: [
{ content: '#18181b', media: '(prefers-color-scheme: dark)' }, { content: '#18181b', media: '(prefers-color-scheme: dark)' },
{ content: 'white', media: '(prefers-color-scheme: light)' }, { content: 'white', media: '(prefers-color-scheme: light)' },
@ -90,9 +92,10 @@ export default defineNuxtConfig({
ogType: 'website', ogType: 'website',
ogUrl: 'https://pro-papier.de', ogUrl: 'https://pro-papier.de',
ogTitle: 'ProPapier', ogTitle: 'ProPapier',
ogDescription: description,
// Other Nuxt SEO modules handles these // Other Nuxt SEO modules handles these
ogImage: 'https://example.com/my-og-image.png', ogImage: '/img/og.png',
robots: 'index, follow', robots: 'index, follow',
} }
}, },

BIN
public/img/og.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 KiB

View file

@ -1,4 +1,4 @@
export type Card = { export type PriceCard = {
uuid : string uuid : string
name : string name : string
price : string price : string

11
shared/TimelineCard.ts Normal file
View file

@ -0,0 +1,11 @@
export type TimelineState = 'planned' | 'inProgress' | 'done'
export type TimelineCard = {
icon: string
title: string
description: string
state: {
value: TimelineState
message ?: string
}
}