feat: Add book ratings and reviews managed via Directus CMS
Adds a new "Read Books" section below "Currently Reading" in the About page. Book reviews with star ratings and comments are fetched from a Directus CMS collection (book_reviews) and displayed with the existing liquid design system. Includes i18n support (EN/DE), show more/less toggle, and graceful fallback when the CMS collection does not exist yet. https://claude.ai/code/session_017E8W9CcHFM5WQVHw74JP34
This commit is contained in:
@@ -422,6 +422,71 @@ export async function getHobbies(locale: string): Promise<Hobby[] | null> {
|
||||
}
|
||||
}
|
||||
|
||||
// Book Review Types
|
||||
export interface BookReview {
|
||||
id: string;
|
||||
hardcover_id?: string;
|
||||
book_title: string;
|
||||
book_author: string;
|
||||
book_image?: string;
|
||||
rating: number; // 1-5
|
||||
review?: string; // Translated review text
|
||||
finished_at?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Book Reviews from Directus with translations
|
||||
*/
|
||||
export async function getBookReviews(locale: string): Promise<BookReview[] | null> {
|
||||
const directusLocale = toDirectusLocale(locale);
|
||||
|
||||
const query = `
|
||||
query {
|
||||
book_reviews(
|
||||
filter: { status: { _eq: "published" } }
|
||||
sort: ["-finished_at", "-date_created"]
|
||||
) {
|
||||
id
|
||||
hardcover_id
|
||||
book_title
|
||||
book_author
|
||||
book_image
|
||||
rating
|
||||
finished_at
|
||||
translations(filter: { languages_code: { code: { _eq: "${directusLocale}" } } }) {
|
||||
review
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
try {
|
||||
const result = await directusRequest(
|
||||
'',
|
||||
{ body: { query } }
|
||||
);
|
||||
|
||||
const reviews = (result as any)?.book_reviews;
|
||||
if (!reviews || reviews.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return reviews.map((item: any) => ({
|
||||
id: item.id,
|
||||
hardcover_id: item.hardcover_id || undefined,
|
||||
book_title: item.book_title,
|
||||
book_author: item.book_author,
|
||||
book_image: item.book_image || undefined,
|
||||
rating: typeof item.rating === 'number' ? item.rating : parseInt(item.rating) || 0,
|
||||
review: item.translations?.[0]?.review || undefined,
|
||||
finished_at: item.finished_at || undefined,
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch book reviews (${locale}):`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Projects Types
|
||||
export interface Project {
|
||||
id: string;
|
||||
|
||||
Reference in New Issue
Block a user