astro/src/pages/fics/[ficId]/index.astro
2025-08-03 23:58:13 -04:00

118 lines
3.1 KiB
Plaintext

---
import type { GetStaticPaths } from "astro";
import { Font } from "astro:assets";
import { getCollection, getEntry, render } from "astro:content";
import Layout from "@/layouts/Layout.astro";
import formatDate from "@/utils/formatDate";
import ChapterContent from "~/ChapterContent.astro";
export const getStaticPaths = (async () => {
const fics = await getCollection("fics");
return fics.map(fic => ({
params: { ficId: fic.id },
props: { fic },
}));
}) satisfies GetStaticPaths;
const { fic } = Astro.props;
const chapters = await getCollection("chapters", ({ id }) => {
return id.startsWith(fic.id);
});
chapters.length = Math.min(chapters.length, 5);
chapters.sort((a, b) => a.data.sortOrder - b.data.sortOrder);
const oneshot = chapters.length === 1 && await getEntry(chapters[0]);
const { Content } = oneshot && await render(oneshot);
---
<Layout title={fic.data.title}>
<Fragment slot="head">
<link rel="alternate" type="application/rss+xml" title={fic.data.title} href={new URL(`/fics/${Astro.params.ficId}/rss.xml`, Astro.site)} />
<meta name="description" content={fic.data.summary?.substring(0, 150) + "…"} />
{oneshot && (
<Font cssVariable="--serif" preload />
)}
</Fragment>
<main>
<section>
<h1>{fic.data.title}</h1>
<header class="info">
<dl>
<dt>Fandom</dt>
{typeof fic.data.series === "object"
? (<ul>
{fic.data.series.map(fandom => (<li>{fandom}</li>))}
</ul>)
: (<dd>{fic.data.series}</dd>)
}
<dt>Date</dt>
<dd>
<time datetime={formatDate(fic.data.publishedAt, true)}>
<span class="data">{formatDate(fic.data.publishedAt)}</span>
</time>
</dd>
<dt>Summary</dt>
<dd>
<blockquote>
<Fragment set:html={fic.data.summary} />
</blockquote>
</dd>
</dl>
<div class="links">
{!oneshot && (
<a class="button" href={`/fics/${chapters[0].id}`}>start reading</a>
)}
<a class="button" href={`/fics/${Astro.params.ficId}/rss.xml`}>rss feed</a>
</div>
</header>
{!oneshot && (
<h2>chapters</h2>
<ul>
{chapters.map(chapter => (
<li><a href={chapter.id}>{chapter.data.title}</a></li>
))}
</ul>
)}
</section>
{oneshot && (
<section id="oneshot">
<ChapterContent lastModified={oneshot.data.lastModified} notes={oneshot.data.notes}>
<Content />
</ChapterContent>
</section>
)}
</main>
</Layout>
<style>
main {
display: grid;
place-content: center;
section {
max-width: 80ch;
.info {
dl {
dt { font-weight: bold; }
}
blockquote {
margin: 1rem 2rem;
}
.links {
display: flex;
align-content: center;
justify-content: space-around;
}
}
}
#oneshot {
margin-top: 2rem;
}
}
</style>