Some checks failed
Dev Deployment (Zero Downtime) / deploy-dev (push) Failing after 9m19s
Fixed missing types, import errors, and updated test suites to match the new editorial design. Verified Docker container build.
101 lines
4.6 KiB
TypeScript
101 lines
4.6 KiB
TypeScript
"use client";
|
|
|
|
import { Star, ArrowLeft } from "lucide-react";
|
|
import Link from "next/link";
|
|
import Image from "next/image";
|
|
import { useEffect, useState } from "react";
|
|
import { useLocale } from "next-intl";
|
|
import { Skeleton } from "@/app/components/ui/Skeleton";
|
|
import { BookReview } from "@/lib/directus";
|
|
|
|
export default function BooksPage() {
|
|
const locale = useLocale();
|
|
const [reviews, setReviews] = useState<BookReview[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
const fetchBooks = async () => {
|
|
try {
|
|
const res = await fetch(`/api/book-reviews?locale=${locale}`);
|
|
const data = await res.json();
|
|
if (data.bookReviews) setReviews(data.bookReviews);
|
|
} catch (error) {
|
|
console.error("Books fetch failed:", error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
fetchBooks();
|
|
}, [locale]);
|
|
|
|
return (
|
|
<div className="min-h-screen bg-[#fdfcf8] dark:bg-stone-950 pt-32 pb-20 px-6 transition-colors duration-500">
|
|
<div className="max-w-7xl mx-auto">
|
|
<div className="mb-20">
|
|
<Link
|
|
href={`/${locale}`}
|
|
className="inline-flex items-center gap-2 text-stone-500 hover:text-stone-900 dark:hover:text-white transition-colors mb-10 group"
|
|
>
|
|
<ArrowLeft size={20} className="group-hover:-translate-x-1 transition-transform" />
|
|
<span className="font-bold uppercase tracking-widest text-xs">{locale === 'de' ? 'Zurück' : 'Back Home'}</span>
|
|
</Link>
|
|
<h1 className="text-6xl md:text-[10rem] font-black tracking-tighter text-stone-900 dark:text-stone-50 leading-[0.85] uppercase">
|
|
Library<span className="text-liquid-purple">.</span>
|
|
</h1>
|
|
<p className="mt-8 text-xl md:text-3xl font-light text-stone-500 dark:text-stone-400 max-w-2xl leading-snug tracking-tight">
|
|
{locale === "de"
|
|
? "Bücher, die meine Denkweise verändert und mein Wissen erweitert haben."
|
|
: "Books that shaped my mindset and expanded my horizons."}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
|
{loading ? (
|
|
Array.from({ length: 6 }).map((_, i) => (
|
|
<div key={i} className="bg-white dark:bg-stone-900 rounded-[2.5rem] p-10 border border-stone-200/60 dark:border-stone-800/60 shadow-sm flex flex-col h-full">
|
|
<Skeleton className="aspect-[3/4] rounded-2xl mb-8" />
|
|
<div className="space-y-3">
|
|
<Skeleton className="h-8 w-3/4" />
|
|
<Skeleton className="h-4 w-1/2" />
|
|
</div>
|
|
</div>
|
|
))
|
|
) : (
|
|
reviews?.map((review) => (
|
|
<div
|
|
key={review.id}
|
|
className="bg-white dark:bg-stone-900 rounded-[2.5rem] p-10 border border-stone-200/60 dark:border-stone-800/60 shadow-sm flex flex-col h-full hover:shadow-xl transition-all"
|
|
>
|
|
{review.book_image && (
|
|
<div className="relative aspect-[3/4] rounded-2xl overflow-hidden mb-8 shadow-xl border-4 border-stone-50 dark:border-stone-800">
|
|
<Image src={review.book_image} alt={review.book_title} fill className="object-cover" />
|
|
</div>
|
|
)}
|
|
<div className="flex-1 flex flex-col">
|
|
<div className="flex justify-between items-start gap-4 mb-4">
|
|
<h3 className="text-2xl font-black text-stone-900 dark:text-white leading-tight">{review.book_title}</h3>
|
|
{review.rating && (
|
|
<div className="flex items-center gap-1 bg-stone-50 dark:bg-stone-800 px-3 py-1 rounded-full border border-stone-100 dark:border-stone-700">
|
|
<Star size={12} className="fill-amber-400 text-amber-400" />
|
|
<span className="text-xs font-black">{review.rating}</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
<p className="text-stone-500 dark:text-stone-400 font-bold text-sm mb-6">{review.book_author}</p>
|
|
{review.review && (
|
|
<div className="mt-auto pt-6 border-t border-stone-50 dark:border-stone-800">
|
|
<p className="text-stone-600 dark:text-stone-300 italic font-light leading-relaxed">
|
|
“{review.review.replace(/<[^>]*>/g, '')}”
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
))
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|