Neue Büchersuche Seite

This commit is contained in:
Michi Tomaschko 2025-04-02 20:17:44 +02:00
parent 76f83cbae9
commit 701e1ba9e3

View File

@ -1,32 +1,48 @@
<template> <template>
<VRow class="match-height"> <VRow class="match-height">
<VCol <VCol cols="12" md="12">
cols="12" <VCard title="Büchersuche" subtitle="Vorbeischauen Vergleichen Verlieben">
md="12" <VCardTitle class="text-center text-h4 font-weight-bold">
> SKOUTZ BUCHSUCHE
<VCard </VCardTitle>
title="Büchersuche"
subtitle="Vorbeischauen Vergleichen Verlieben"
>
<!-- ******* Fieberkurve ***** -->
<Fieberkurve :show-reset-button="true" :show-categories="true" />
<!-- <div style="position: absolute; top: 255px; left: 10px; color: rgba(185,17,17,0.85)"> <!-- Fieberkurve -->
{{ selectedCheckbox }} <Fieberkurve
</div>--> ref="fieberkurveRef"
:show-reset-button="true"
:show-categories="true"
@update:values="updateFieberkurveValues"
@filter-by-row="filterByRow"
/>
<!-- ******* Genre´s ***** --> <br>
<div style="padding: 0 7rem;">
<VCol> <!-- Genres -->
<CustomCheckboxesWithIcon <div class="genre-section-main">
v-model:selected-checkbox="selectedCheckbox" <div
:checkbox-content="checkboxContent" v-for="genre in genres"
/> :key="genre.value"
</VCol> class="custom-checkbox"
:class="{ active: selectedCheckbox.includes(genre.value) }"
@click="toggleGenre(genre.value)"
>
<VTooltip location="top">
{{ genre.value }}
<template #activator="{ props }">
<div v-bind="props" class="icon">
<VIcon :icon="genre.icon.icon" />
</div>
</template>
</VTooltip>
</div>
</div> </div>
<!-- ******* TEXT SUCHFELD!! ***** --> <!-- Button zum Zurücksetzen der Genres -->
<VBtn class="my-3 mx-auto d-block" color="primary" @click="clearGenres">
Alle Genres Zurücksetzen
</VBtn>
<!-- Text Suchfeld -->
<div style="padding: 0 5rem;"> <div style="padding: 0 5rem;">
<AppTextField <AppTextField
v-model="message" v-model="message"
@ -36,392 +52,186 @@
type="text" type="text"
class="textfield-demo-icon-slot" class="textfield-demo-icon-slot"
> >
<!-- Prepend -->
<template #prepend>
<VTooltip location="bottom">
<template #activator="{ props }">
<VIcon
v-bind="props"
icon="tabler-help"
/>
</template>
Skoutz ist die Buchsuche, <br>
die deinen Geschmack trifft. <br>
5 Klicks 🖱 statt 5 Sterne und du <br>
findest genau, was du willst. <br>
</VTooltip>
</template>
<!-- AppendInner -->
<template #append-inner>
<VFadeTransition leave-absolute>
<VProgressCircular
v-if="loading"
color="primary"
width="3"
size="24"
indeterminate
/>
<VNodeRenderer
v-else
class="text-2xl"
:nodes="themeConfig.app.logo"
/>
</VFadeTransition>
</template>
<!-- Append -->
<template #append> <template #append>
<VBtn <VBtn :icon="$vuetify.display.smAndDown" @click="searchBooks">
:icon="$vuetify.display.smAndDown" <VIcon icon="tabler-search" color="#fff" size="22" />
@click="clickMe" <span v-if="$vuetify.display.mdAndUp" class="ms-3">Suchen</span>
>
<VIcon
icon="tabler-search"
color="#fff"
size="22"
/>
<span
v-if="$vuetify.display.mdAndUp"
class="ms-3"
>Suchen</span>
</VBtn> </VBtn>
</template> </template>
</AppTextField> </AppTextField>
</div> </div>
<br> <!-- Button zum Zurücksetzen der Einstellungen -->
<VBtn
class="my-3 mx-auto d-block"
:color="resetFeedback ? 'success' : 'error'"
@click="resetAllSettings"
>
{{ resetFeedback ? 'Zurückgesetzt!' : 'Alle Einstellungen zurücksetzen' }}
</VBtn>
<br />
</VCard> </VCard>
</VCol> </VCol>
<VCol cols="12" md="12">
<VCard class="mb-6" title="Gefundene Bücher:">
<VRow>
<VCol v-for="book in filteredBooks" :key="book.id" sm="6" cols="12">
<VCard>
<div class="d-flex justify-space-between flex-wrap flex-md-nowrap flex-column flex-md-row">
<div class="ma-auto pa-5">
<VImg width="200px" height="300px" :src="book.image" />
</div>
<VDivider :vertical="$vuetify.display.mdAndUp" />
<div>
<VCardTitle>{{ book.title }}</VCardTitle>
<VCardText>{{ book.description }}</VCardText>
<VCol <Fieberkurve
cols="12" :is-static="true"
md="12" :default-values="book.fieberkurve"
> :hide-text="true"
<!--
<VCard
title="Bücher eintragen"
subtitle="Dir fehlt ein Buch? Hier kannst du es eintragen!"
>
-->
<VCard
class="mb-6"
title="Gefundene Bücher:"
>
Hallo Hier ist die API:
{{book}}
<div v-if="book">
<p>Titel: {{ book.title }}</p>
<!-- <p>Autor: {{ book.author }}</p>-->
</div>
<!-- 👉 Hier werden die Bücher aufgelistet. -->
<VCol
sm="6"
cols="12"
>
<VCard>
<div class="d-flex justify-space-between flex-wrap flex-md-nowrap flex-column flex-md-row">
<div class="ma-auto pa-5">
<VImg
width="200px"
height="300px"
:src="harry_potter"
/>
</div>
<VDivider :vertical="$vuetify.display.mdAndUp" />
<div>
<VCardTitle>Harry Potter</VCardTitle>
<VCardText>
<!-- <div style="position: relative; height: 120px">-->
<!-- Fieberkurve -->
</VCardText>
<VCardText>
Harry Potter ist eine Kinder- und Jugendromanreihe der englischen Schriftstellerin Joanne K. Rowling. ...
</VCardText>
<!--
<VCardText class="text-subtitle-1">
<span>Bestellen:</span> <span class="font-weight-medium">Amazon</span>
</VCardText>
-->
<VCardActions class="justify-space-between">
<VBtn>
<VIcon icon="tabler-list-details" />
<span class="ms-2">Detail Seite</span>
</VBtn>
<IconBtn
color="secondary"
icon="tabler-share"
/> />
</VCardActions> <VCardActions class="justify-space-between">
<VBtn>
<VIcon icon="tabler-list-details" />
<span class="ms-2">Detail Seite</span>
</VBtn>
<IconBtn color="secondary" icon="tabler-share" />
</VCardActions>
</div>
</div> </div>
</div> </VCard>
</VCard> </VCol>
</VCol> </VRow>
<!-- ENDE: Genre -->
</VCard> </VCard>
</VCol> </VCol>
</VRow> </VRow>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { VNodeRenderer } from '@layouts/components/VNodeRenderer' import { ref, computed } from "vue";
import { themeConfig } from '@themeConfig' import Fieberkurve from "@/components/Fieberkurve.vue";
import { ref, onMounted, watch } from 'vue' import { books } from "@/components/buecherdatenbank";
import Fieberkurve from "@/components/Fieberkurve.vue" import { genres } from "@/components/genredatenbank";
import harry_potter from "@/assets/images/harry_potter_stein_weisen_rowling.jpg"
import BookService from './BookService'
import { useTheme } from "vuetify"
const message = ref('') const message = ref("");
const loading = ref(false) const loading = ref(false);
const selectedCheckbox = ref([]);
const fieberkurveValues = ref([4, 4, 4, 4, 4]); // Standardwerte für die Fieberkurve
const fieberkurveRowFilter = ref({ rowIndex: null, value: null });
const clickMe = () => { const filteredBooks = computed(() => {
loading.value = true return books.filter((book) => {
message.value = 'Warte darauf...' const matchesGenres =
selectedCheckbox.value.length === 0 ||
selectedCheckbox.value.some((genre) => book.genres.includes(genre));
const matchesText =
!message.value ||
book.title.toLowerCase().includes(message.value.toLowerCase()) ||
book.authors?.some((author) =>
author.name.toLowerCase().includes(message.value.toLowerCase())
) ||
book.isbn?.includes(message.value);
const matchesFieberkurve = fieberkurveValues.value.every((value, index) => {
const bookValue = book.fieberkurve[index]?.value || 4;
return value === 4 || value === bookValue;
});
const matchesRowFilter =
fieberkurveRowFilter.value.rowIndex === null ||
book.fieberkurve[fieberkurveRowFilter.value.rowIndex].value ===
fieberkurveRowFilter.value.value;
return matchesGenres && matchesText && matchesFieberkurve && matchesRowFilter;
});
});
const searchBooks = () => {
console.log("Suche gestartet mit Text:", message.value);
};
const toggleGenre = (genre) => {
if (selectedCheckbox.value.includes(genre)) {
selectedCheckbox.value = selectedCheckbox.value.filter((g) => g !== genre);
} else {
selectedCheckbox.value.push(genre);
}
};
const clearGenres = () => {
selectedCheckbox.value = [];
};
const fieberkurveRef = ref(null);
const resetFeedback = ref(false);
const resetAllSettings = () => {
selectedCheckbox.value = [];
fieberkurveRef.value?.resetSliders();
message.value = "";
fieberkurveRowFilter.value = { rowIndex: null, value: null };
resetFeedback.value = true;
setTimeout(() => { setTimeout(() => {
loading.value = false resetFeedback.value = false;
message.value = '' }, 1500);
}, 2000) };
}
const checkboxContent = [ const updateFieberkurveValues = (values) => {
/*{ fieberkurveValues.value = values;
title: 'Backup', };
desc: 'Backup every file from your project.',
value: 'backup',
icon: {
icon: 'tabler-server-2',
size: '28',
},
},*/
{
value: 'Abendteuer',
icon: {
icon: 'tabler-compass',
size: '28',
},
},
{
value: 'Contemporary',
icon: {
icon: 'tabler-building-skyscraper',
size: '28',
},
},
{
value: 'Crime',
icon: {
icon: 'tabler-fingerprint',
size: '28',
},
},
{
value: 'Erotik',
icon: {
icon: 'tabler-bed',
size: '28',
},
},
{
value: 'Fantasy',
icon: {
icon: 'tabler-paw',
size: '28',
},
},
{
value: 'History',
icon: {
icon: 'tabler-swords',
size: '28',
},
},
{
value: 'Horror',
icon: {
icon: 'tabler-ghost-2',
size: '28',
},
},
{
value: 'Humor',
icon: {
icon: 'tabler-mood-xd',
size: '28',
},
},
{
value: 'Romance',
icon: {
icon: 'tabler-hearts',
size: '28',
},
},
{
value: 'ScienceFiction',
icon: {
icon: 'tabler-ufo',
size: '28',
},
},
]
const selectedCheckbox = ref([]) const filterByRow = (filter) => {
fieberkurveRowFilter.value = filter;
console.log("Filter gesetzt:", filter);
};
// Hier ist der Abschnitt für die API (BACKEND)
let book = null
onMounted(() => {
const isbn = '9783898798822' // Ersetze durch die gewünschte ISBN
BookService.getBookByIsbn(isbn)
.then(response => {
// book = response.data
book = response
})
.catch(error => {
console.error(error)
})
})
// const toggleCheckboxOne = ref(true)
// const genreBool = ref(false)
// const genre1Color = ref('#a8a6a6')
// let activeGenre = []
/*let genres = [{
id: 1,
name: "Horror",
icon: "tabler-ghost-2",
color: "#a8a6a6",
bool: true,
},
{
id: 2,
name: "Test",
color: "#a8a6a6",
icon: "tabler-ghost-2",
bool: false,
},
{
id: 3,
name: "History",
color: "#9fa8da",
icon: "tabler-timeline",
bool: false,
},
{
id: 4,
name: "Anton",
color: "#9fa8da",
icon: "tabler-ghost-2",
bool: false,
}]*/
// const abenteuerBool = ref(false)
// const people = ref(['Mike'])
/*function TestGenreActive(genre, bool){
console.log("Hey Genre:", genre, bool)
bool = !bool
console.log("Bye Genre:", genre, bool)
return bool
}*/
/*function IsGenreActive(genre) {
return activeGenre.includes(genre)
}*/
/*function ToggleIsGenreSelected(genre) {
console.log('IsGenreActive', IsGenreActive(genre))
console.log('ToggleIsGenreSelected genre', genre)
if (IsGenreActive(genre)){
const index = activeGenre.indexOf(genre)
activeGenre.splice(index, 1)
console.log(`if values: ${activeGenre}`)
} else {
activeGenre.push(genre)
console.log(`else values: ${activeGenre}`)
}
// this.genreBool = !this.genreBool
/!*genre.bool = !genre.bool
genre = {
id: genre.id,
name: genre.name,
color: genre.color,
icon: genre.icon,
bool: genre.bool
}*!/
// console.log("genreBool", genreBool)
// console.log("genre", genre)
// console.log("genreselected", genre.selected)
// console.log("genres name", genre.name)
// console.log("genres id", genre.id)
// console.log("genres icon", genre.icon)
// console.log("genres color", genre.color)
/!*genre.selected = !genre.selected
if (!genre.selected) {
genre.color = "#cccccc" + "!important"
console.log("IF !genre.selected", genre.selected, genre.color)
} else {
genre.color = vuetifyTheme.current.value.colors.primary
console.log("ELSE genre.selected", genre.selected, genre.color)
}
// genre.color = "#cccccc" + "!important"
console.log("genreNew", genre, genre.color)*!/
}*/
// lifecycle hooks
/*onMounted(() => {
// rowFevercurveConnectors()
})*/
/*computed() {
genreBackgroundColor() {
return (genreId) => {
return IsGenreActive(genreId) ? vuetifyTheme.current.value.colors.primary : '#acadac'
}
}
}*/
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.genre-section-main { .genre-section-main {
display: flex; display: flex;
flex-wrap: wrap;
gap: 0.5rem;
justify-content: center;
}
.genre-section-main > div {
display: flex;
justify-content: center;
align-items: center;
width: 50px;
height: 50px;
border: 1px solid #ddd;
border-radius: 8px;
background-color: #f9f9f9;
cursor: pointer;
transition: all 0.3s ease;
}
.genre-section-main > div.active {
background-color: rgb(var(--v-theme-primary));
color: white;
border-color: #4e60e4;
}
.genre-section-main > div:hover {
background-color: #e6e8f0;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.genre-section-main .icon {
font-size: 18px;
color: inherit;
}
.v-text-field {
margin-bottom: 1.5rem;
} }
</style> </style>