feat: implement books collection pages with filtering and dynamic routing

This commit is contained in:
greg 2025-05-21 01:09:37 +02:00
parent 789583142c
commit 7336efbb4b
3 changed files with 69 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

View File

@ -10,7 +10,7 @@ for (const path in bookImports) {
const bookModule = await bookImports[path](); const bookModule = await bookImports[path]();
allBooksAstro.push({ allBooksAstro.push({
frontmatter: bookModule.frontmatter, frontmatter: bookModule.frontmatter,
url: bookModule.url || path.replace('../../content', '').replace('.md', ''), url: `/books/${path.split('/').pop().replace('.md', '')}`,
description: bookModule.frontmatter.description || bookModule.rawContent()?.substring(0, 100) + '...' || 'No description available.', description: bookModule.frontmatter.description || bookModule.rawContent()?.substring(0, 100) + '...' || 'No description available.',
// Ensure all necessary fields for filtering are directly accessible // Ensure all necessary fields for filtering are directly accessible
genre: bookModule.frontmatter.genre, genre: bookModule.frontmatter.genre,

View File

@ -0,0 +1,68 @@
---
import { Markdown } from 'astro/components';
export async function getStaticPaths() {
console.log('Running getStaticPaths...');
// Define glob inside the function
const bookImports = import.meta.glob('/content/books/*.md');
const paths = Object.keys(bookImports);
console.log('Found file paths:', paths);
// Process all matched files
const books = await Promise.all(
paths.map(async (path) => {
const mod = await bookImports[path]();
// Simple slug extraction - just the filename without extension
const filename = path.split('/').pop() || '';
const slug = filename.replace(/\.md$/, '');
console.log(`File: ${filename}, Generated slug: ${slug}`);
console.log(`Debug: Full path=${path}, Normalized URL would be: /books/${slug}`);
return {
...mod,
slug,
fullPath: path
};
})
);
const routes = books.map(book => ({
params: { slug: book.slug },
props: { book }
}));
console.log('Generated routes:', routes.map(r => r.params.slug));
return routes;
}
const { book } = Astro.props;
const { frontmatter, compiledContent } = book;
---
<html>
<head>
<title>{frontmatter.title || 'Book Details'}</title>
</head>
<body class="bg-slate-50 min-h-screen">
<main class="max-w-2xl mx-auto p-8">
<a href="/books" class="text-sky-600 hover:underline">← Back to Books</a>
<div class="bg-white rounded-xl shadow-lg p-6 mt-6 flex flex-col items-center">
<img src={frontmatter.cover || '/placeholder-cover.png'} alt={frontmatter.title} class="w-24 h-32 object-contain bg-gray-100 rounded mb-4 shadow" />
<h1 class="text-3xl font-bold mb-2 text-center">{frontmatter.title}</h1>
<p class="text-slate-500 mb-4 text-center">by {frontmatter.author}</p>
<p class="mb-2"><strong>Genre:</strong> {frontmatter.genre}</p>
<p class="mb-2"><strong>Rating:</strong> {frontmatter.rating}/5</p>
<p class="mb-2"><strong>Year:</strong> {frontmatter.year}</p>
<p class="mb-2"><strong>Status:</strong> {frontmatter.status}</p>
<p class="mb-2"><strong>Pages:</strong> {frontmatter.pages}</p>
<p class="mb-2"><strong>ISBN:</strong> {frontmatter.isbn}</p>
<div class="prose mt-6">
<book.Content />
</div>
</div>
</main>
</body>
</html>