buchdetailseite: Umsetzung von PowerPoint Layout, sowie zusätliche Idee "Community-Statistik" usw.

This commit is contained in:
Michi Tomaschko 2025-04-07 05:24:51 +02:00
parent 2818ec4a60
commit 6679083789

View File

@ -1,102 +1,213 @@
<template>
<VContainer class="pt-6">
<VRow>
<VCol cols="12" md="4">
<VImg
:src="book.image"
max-height="500"
max-width="100%"
contain
class="rounded"
/>
</VCol>
<VContainer class="py-6">
<VCard class="pa-4" elevation="2">
<VRow>
<!-- Cover & Shops + Community -->
<VCol cols="12" md="3">
<div class="mb-4" style="aspect-ratio: 2/3; overflow: hidden;">
<VImg :src="book.image" height="100%" width="100%" cover class="elevation-1" />
</div>
<VCol cols="12" md="8">
<VCard class="pa-4">
<VCardTitle class="text-h5 font-weight-bold">
{{ book.title }}<br>
<span class="text-subtitle-1" v-if="book.subtitle">{{ book.subtitle }}</span>
</VCardTitle>
<div class="d-flex flex-column gap-2 mb-4">
<VBtn block color="black" variant="outlined" href="https://www.amazon.de" target="_blank">
<VIcon start icon="tabler-brand-amazon" /> Amazon
</VBtn>
<VBtn block color="blue" variant="outlined">
<VIcon start icon="tabler-book" /> Hugendubel
</VBtn>
<VBtn block color="grey" variant="outlined">
<VIcon start icon="tabler-brand-apple" /> Apple
</VBtn>
<VBtn block color="green" variant="outlined">
<VIcon start icon="tabler-book-2" /> Thalia
</VBtn>
</div>
<VCardText>
<div v-if="book.authors?.length" class="mb-2">
<strong>Autor(en):</strong>
{{ book.authors.map(a => a.name).join(', ') }}
</div>
<!-- Community-Statistik -->
<VCard class="pa-3" variant="outlined" style="min-height: 220px;">
<VCardTitle>Community-Statistik</VCardTitle>
<VCardText>
<VList density="compact">
<VListItem prepend-icon="tabler-library">In 47 Bibliotheken</VListItem>
<VListItem prepend-icon="tabler-bookmark">Auf 20 Merkzettel</VListItem>
<VListItem prepend-icon="tabler-book">4 Leser*innen lesen es gerade</VListItem>
</VList>
</VCardText>
</VCard>
</VCol>
<!-- Genres mit Icons -->
<div class="d-flex flex-wrap align-center mb-3">
<VChip
v-for="genre in book.genres"
:key="genre"
color="primary"
class="ma-1"
size="small"
>
<VIcon
v-if="genreIconMap[genre]"
:icon="genreIconMap[genre].icon"
:size="genreIconMap[genre].size"
class="me-1"
/>
{{ genre }}
</VChip>
</div>
<!-- Hauptbereich -->
<VCol cols="12" md="9">
<div class="mb-6">
<h1 class="text-h4 font-weight-bold mb-1">{{ book.title }}</h1>
<h2 class="text-subtitle-1">von {{ book.authors[0]?.name }}</h2>
<div class="mt-2 text-muted">{{ book.subtitle }}</div>
</div>
<!-- Fieberkurve -->
<Fieberkurve :is-static="true" :default-values="book.fieberkurve" :hide-text="true" class="mb-4" />
<!-- Genres -->
<div class="d-flex align-center gap-2 flex-wrap mb-4">
<VChip
v-for="genre in book.genres"
:key="genre"
color="primary"
variant="flat"
class="me-1"
>
<VIcon start :icon="genreIcon(genre)" /> {{ genre }}
</VChip>
</div>
<!-- Beschreibung -->
<div class="mb-4">
<strong>Beschreibung:</strong>
<p class="mt-1">{{ book.blurb }}</p>
</div>
<!-- Neue statische Fieberkurve -->
<Fieberkurve :isStatic="true" :defaultValues="[{ value: 5 }, { value: 2 }, { value: 7 }, { value: 3 }, { value: 5 }]" class="my-4" />
<!-- Detailtabelle -->
<VTable dense>
<tbody>
<tr><td><strong>Seitenzahl</strong></td><td>{{ book.pageCount }}</td></tr>
<tr><td><strong>Sprache</strong></td><td>{{ book.language }}</td></tr>
<tr v-if="book.publishers"><td><strong>Verlag</strong></td><td>{{ book.publishers }}</td></tr>
<tr><td><strong>Veröffentlicht</strong></td><td>{{ book.publishedDate }}</td></tr>
<tr v-if="book.isbn"><td><strong>ISBN</strong></td><td>{{ book.isbn }}</td></tr>
</tbody>
</VTable>
<!-- Inhaltsangabe -->
<VCard class="mb-4" variant="outlined" style="min-height: 180px;">
<VCardTitle>Inhaltsangabe</VCardTitle>
<VCardText>{{ book.blurb }}</VCardText>
</VCard>
<!-- Shoplink (Platzhalter) -->
<div class="mt-4">
<VBtn color="success" variant="flat">
<VIcon icon="tabler-shopping-cart" class="me-2" />
Bei Amazon suchen
</VBtn>
</div>
<!-- Buchdetails & Infos -->
<VRow>
<VCol cols="12" md="6">
<VCard class="pa-3" variant="outlined" style="min-height: 220px;">
<VCardTitle>Buchdetails</VCardTitle>
<VCardText>
<strong>ISBN:</strong> {{ book.isbn || '' }}<br />
<strong>Sprache:</strong> {{ book.language }}<br />
<strong>Seiten:</strong> {{ book.pageCount }}<br />
<strong>Verlag:</strong> {{ book.publishers || '' }}<br />
<strong>Veröffentlicht:</strong> {{ book.publishedDate }}
</VCardText>
</VCard>
</VCol>
<VCol cols="12" md="6">
<VCard class="pa-3" variant="outlined" style="min-height: 220px;">
<VCardTitle>Weitere Informationen</VCardTitle>
<VCardText>
<ul class="pa-0" style="list-style: none">
<li><a href="#">Alle Ausgaben in der Übersicht</a></li>
<li><a href="#">Vergleichbare Bücher suchen</a></li>
<li><a href="#">Mehr über das Buch (z.B. Skoutz-Artikel)</a></li>
<li><a href="#">Über den Autor/die Autorin</a></li>
<li><a href="#">Über den Verlag</a></li>
<li><a href="#">Weitere Bücher aus der Reihe</a></li>
</ul>
</VCardText>
</VCard>
</VCol>
</VRow>
</VCardText>
</VCard>
</VCol>
</VRow>
<!-- Weitere Bücher vom Autor -->
<VCard class="mt-6 mb-6" elevation="0">
<VCardTitle>Bücher von {{ book.authors[0]?.name }}</VCardTitle>
<VCardText>
<VRow>
<VCol v-for="item in authorBooks" :key="item.id" cols="12" sm="6" md="3">
<RouterLink :to="`/buchdetailseite/${item.id}`">
<VCard class="hover:scale-105 transition-transform duration-200">
<VImg :src="item.image" height="180" cover />
<VCardText>
<div class="text-sm font-semibold">{{ item.title }}</div>
</VCardText>
</VCard>
</RouterLink>
</VCol>
<!-- Beispielbücher -->
<VCol cols="12" sm="6" md="3">
<VCard>
<VImg src="https://m.media-amazon.com/images/I/81bsw6fnUiL.jpg" height="180" cover />
<VCardText>
<div class="text-sm font-semibold">Rich Dad's Cashflow Quadrant</div>
</VCardText>
</VCard>
</VCol>
<VCol cols="12" sm="6" md="3">
<VCard>
<VImg src="https://m.media-amazon.com/images/I/81eUwF5QzIL.jpg" height="180" cover />
<VCardText>
<div class="text-sm font-semibold">Rich Dad's Guide to Investing</div>
</VCardText>
</VCard>
</VCol>
</VRow>
</VCardText>
</VCard>
<!-- Rezensionen -->
<VCard elevation="0">
<VCardTitle>Rezensionen & Bewertungen</VCardTitle>
<VCardText>
<p class="mb-2"> 4,3 / 5 Sterne (15 Stimmen)</p>
<em>Hier könnten später echte Rezensionen von Nutzern folgen.</em>
</VCardText>
</VCard>
<!-- Ähnliche Bücher -->
<VCard class="mt-6" elevation="0">
<VCardTitle>Ähnliche Bücher</VCardTitle>
<VCardText>
<VRow>
<VCol
v-for="similar in similarBooks"
:key="similar.id"
cols="12"
sm="6"
md="3"
>
<RouterLink :to="`/buchdetailseite/${similar.id}`">
<VCard class="hover:scale-105 transition-transform duration-200">
<VImg :src="similar.image" height="180" cover />
<VCardText>
<div class="text-sm font-semibold">{{ similar.title }}</div>
</VCardText>
</VCard>
</RouterLink>
</VCol>
</VRow>
</VCardText>
</VCard>
</VCol>
</VRow>
</VCard>
</VContainer>
</template>
<script setup>
import { ref } from 'vue'
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import { books } from '@/components/buecherdatenbank.js'
import { genres as genreIcons } from '@/components/genredatenbank.js'
import { books } from '@/components/buecherdatenbank'
import Fieberkurve from '@/components/Fieberkurve.vue'
const route = useRoute()
const bookId = parseInt(route.params.id)
const book = books.find(b => b.id === bookId) || {}
const id = parseInt(route.params.id)
const book = books.find(b => b.id === id) || {}
const genreIconMap = genreIcons.reduce((acc, g) => {
acc[g.value] = g.icon
return acc
}, {})
</script>
const authorBooks = computed(() => {
if (!book?.authors?.[0]?.name) return []
return books.filter(b => b.authors?.[0]?.name === book.authors[0].name && b.id !== book.id)
})
<style scoped>
p {
line-height: 1.6;
const similarBooks = computed(() => {
if (!book.genres || !book.genres.length) return []
return books.filter(b =>
b.id !== book.id &&
b.genres?.some(g => book.genres.includes(g))
).slice(0, 4)
})
const genreIcon = genre => {
const icons = {
Crime: 'tabler-fingerprint',
Erotik: 'tabler-bed',
Fantasy: 'tabler-paw',
History: 'tabler-swords',
Horror: 'tabler-ghost-2',
Humor: 'tabler-mood-xd',
Romance: 'tabler-hearts',
ScienceFiction: 'tabler-ufo',
Contemporary: 'tabler-building-skyscraper',
Abenteuer: 'tabler-compass',
}
return icons[genre] || 'tabler-book'
}
</style>
</script>