feat: add books page with filtering and create sample book content

This commit is contained in:
greg 2025-05-21 00:45:20 +02:00
parent 86b335845d
commit 789583142c
2 changed files with 32 additions and 21 deletions

View File

@ -3,7 +3,7 @@ title: "Dune 2"
year: 1966 year: 1966
media_type: "book" media_type: "book"
genre: "Brol" genre: "Brol"
rating: 5 rating: 1
cover: "/covers/dune-placeholder.jpg" cover: "/covers/dune-placeholder.jpg"
status: "Read" status: "Read"
date_added: "2025-05-20" date_added: "2025-05-20"

View File

@ -82,18 +82,32 @@ const alpineData = {
<!-- Book Grid --> <!-- Book Grid -->
{booksFoundCount > 0 ? ( {booksFoundCount > 0 ? (
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-8 md:gap-10 justify-items-center"> <div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-8 md:gap-10 justify-items-center">
{allBooksAstro.map(book => ( <template x-for="book in filteredBooks" :key="book.url">
<div x-show={`$store && $store.matchesFilters ? $store.matchesFilters(${JSON.stringify(book)}) : true`}> {/* fallback to show all if Alpine not ready */} <div class="bg-slate-50 border-2 border-sky-500 rounded-xl shadow-lg w-56 mx-auto p-4 my-4 transition-all duration-200 hover:shadow-2xl">
<MediaCard <a :href="book.url" class="block">
title={book.title || (book.frontmatter && book.frontmatter.title)} <img
cover={book.cover || (book.frontmatter && book.frontmatter.cover)} :src="book.cover || '/placeholder-cover.png'"
rating={book.rating || (book.frontmatter && book.frontmatter.rating)} :alt="book.title ? `Cover for ${book.title}` : 'Book cover'"
url={book.url} class="w-full h-24 object-contain bg-gray-100 rounded-t-lg"
description={book.description || (book.frontmatter && book.frontmatter.description)} @error="event.target.src='/placeholder-cover.png'"
author={book.author || (book.frontmatter && book.frontmatter.author)}
/> />
</a>
<div class="p-2">
<h3 class="text-sm font-semibold text-slate-800 mb-1 truncate">
<a :href="book.url" class="hover:text-sky-600" x-text="book.title"></a>
</h3>
<template x-if="book.author">
<p class="text-xs text-slate-500 mb-1" x-text="`by ${book.author}`"></p>
</template>
<template x-if="book.rating">
<p class="text-xs text-slate-600 mb-1" x-text="`Rating: ${book.rating}/5`"></p>
</template>
<template x-if="book.description">
<p class="text-xs text-slate-700 mt-1 overflow-hidden" x-text="book.description"></p>
</template>
</div> </div>
))} </div>
</template>
</div> </div>
) : ( ) : (
<div class="text-center py-10"> <div class="text-center py-10">
@ -136,14 +150,11 @@ const alpineData = {
let ratingMatch = this.selectedRating === '' || (ratingValue !== undefined && ratingValue !== null && ratingValue >= selectedRatingValue); let ratingMatch = this.selectedRating === '' || (ratingValue !== undefined && ratingValue !== null && ratingValue >= selectedRatingValue);
// Temporary debug log for rating filter // Debug log for genre and rating filter
if (this.selectedRating !== '') {
console.log( console.log(
`Book: "${book.title}", Book Rating: ${ratingValue} (type: ${typeof ratingValue}), ` + `Book: "${book.title}", Book Genre: "${book.genre}", Selected Genre: "${this.selectedGenre}", Genre Match: ${genreMatch}, ` +
`Selected Dropdown Rating: "${this.selectedRating}" (type: ${typeof this.selectedRating}), ` + `Book Rating: ${ratingValue} (type: ${typeof ratingValue}), Selected Dropdown Rating: "${this.selectedRating}" (type: ${typeof this.selectedRating}), Parsed Selected: ${selectedRatingValue} (type: ${typeof selectedRatingValue}), Rating Match: ${ratingMatch}`
`Parsed Selected: ${selectedRatingValue} (type: ${typeof selectedRatingValue}), Match: ${ratingMatch}`
); );
}
return genreMatch && ratingMatch; return genreMatch && ratingMatch;
}); });
}, },