src/pages/library.astro 1.7 K raw
1
---
2
export const prerender = false;
3
4
import PageLayout from "@/layouts/Base.astro";
5
import BookCard from "@/components/page/BookCard.astro";
6
7
type Book = {
8
	id: number;
9
	title: string;
10
	authors: string;
11
	cover_url: string | null;
12
	notes: string | null;
13
	status: "read" | "reading" | "want";
14
};
15
16
const meta = {
17
	title: "/library",
18
	description: "Books I'm reading, have read, and want to read",
19
};
20
21
let books: Book[] = [];
22
let error: string | null = null;
23
try {
24
	const res = await fetch(
25
		"https://library.stevedylan.dev/api/books?status=all",
26
	);
27
	if (res.ok) {
28
		books = await res.json();
29
	} else {
30
		error = `API returned ${res.status}`;
31
	}
32
} catch (e) {
33
	error = e instanceof Error ? e.message : "Failed to reach library API";
34
}
35
36
const reading = books.filter((b) => b.status === "reading");
37
const read = books.filter((b) => b.status === "read");
38
const want = books.filter((b) => b.status === "want");
39
40
const sections: { label: string; items: Book[] }[] = [
41
	{ label: "Reading", items: reading },
42
	{ label: "Read", items: read },
43
	{ label: "Want to Read", items: want },
44
];
45
---
46
47
<PageLayout meta={meta}>
48
	<div class="flex min-h-screen flex-col items-start justify-start gap-6">
49
    <h1 class="title">/library</h1>
50
		{error ? (
51
			<p class="text-red-400 text-sm">Could not load books: {error}</p>
52
		) : books.length === 0 ? (
53
			<p class="text-zinc-400 text-sm">no books yet</p>
54
		) : (
55
			<div class="flex flex-col w-full gap-8">
56
				{sections.filter((s) => s.items.length > 0).map((section) => (
57
					<div class="flex flex-col w-full">
58
						<h2 class="text-sm font-semibold uppercase tracking-widest opacity-50 mb-2">{section.label}</h2>
59
						{section.items.map((book) => (
60
							<BookCard book={book} />
61
						))}
62
					</div>
63
				))}
64
			</div>
65
		)}
66
	</div>
67
</PageLayout>