refactor: add a generic listing page component

This commit is contained in:
Oliver Davies 2023-02-11 22:53:00 +00:00
parent bcd846f08c
commit 2efcb575f1
4 changed files with 71 additions and 57 deletions

View file

@ -0,0 +1,24 @@
---
import PageLayout from "~/layouts/PageLayout.astro";
import ListingPageItem from "./ListingPageItem.astro";
interface Item {
description: string;
title: string;
}
interface Props {
items: Array<Item>;
title: string;
}
const { items, title } = Astro.props as Props;
---
<PageLayout title={title}>
<slot name="intro" />
<div class="mt-6 space-y-6">
{items.map((item) => <ListingPageItem item={item} />)}
</div>
</PageLayout>

View file

@ -0,0 +1,31 @@
---
interface ItemProps {
date: string;
description?: string;
excerpt?: string;
title: string;
}
const { date, description, excerpt, title } = Astro.props.item.item
.frontmatter as ItemProps;
const { slug } = Astro.props.item;
---
<article>
<a href={slug} class="mb-2"><h2>{title}</h2></a>
{
date && (
<time class="mt-0 mb-2 block text-base" datetime={date}>
{new Date(date).toLocaleDateString("en-GB", {
day: "numeric",
month: "long",
year: "numeric",
})}
</time>
)
}
{description && <p>{description}</p>}
{excerpt && <p>{excerpt}</p>}
</article>

View file

@ -1,4 +1,5 @@
--- ---
import ListingPage from "~/components/ListingPage.astro";
import PageLayout from "~/layouts/PageLayout.astro"; import PageLayout from "~/layouts/PageLayout.astro";
import { getSlugFromFile } from "~/utils.ts"; import { getSlugFromFile } from "~/utils.ts";
@ -11,50 +12,21 @@ const filteredPosts = posts
const sortedPosts = filteredPosts const sortedPosts = filteredPosts
.map((post) => { .map((post) => {
const slug = getSlugFromFile(post.file); const slug = `/blog/${getSlugFromFile(post.file)}`;
return { post, slug }; return { item: post, slug };
}) })
.sort( .sort(
(a, b) => (a, b) =>
new Date(b.post.frontmatter.date).valueOf() - new Date(b.item.frontmatter.date).valueOf() -
new Date(a.post.frontmatter.date).valueOf() new Date(a.item.frontmatter.date).valueOf()
); );
--- ---
<PageLayout title="Blog"> <ListingPage items={sortedPosts} title="Blog">
<p> <p slot="intro">
This is where I publish my personal blog posts as well as technical posts This is where I publish my personal blog posts as well as technical posts
and tutorials on topics such as Drupal, PHP, Tailwind CSS, automated and tutorials on topics such as Drupal, PHP, Tailwind CSS, automated
testing, and systems administration. testing, and systems administration.
</p> </p>
</ListingPage>
<div>
{
sortedPosts.map((post) => (
<article>
<a href={`/blog/${post.slug}`}>
<h2>{post.post.frontmatter.title}</h2>
</a>
{post.post.frontmatter.date && (
<time class="text-base" datetime={post.post.frontmatter.date}>
{new Date(post.post.frontmatter.date).toLocaleDateString(
"en-GB",
{
day: "numeric",
month: "long",
year: "numeric",
}
)}
</time>
)}
<div class="mt-1">
<p>{post.post.frontmatter.excerpt}</p>
</div>
</article>
))
}
</div>
</PageLayout>

View file

@ -2,6 +2,7 @@
import PageLayout from "~/layouts/PageLayout.astro"; import PageLayout from "~/layouts/PageLayout.astro";
import _ from "lodash"; import _ from "lodash";
import { getSlugFromFile } from "~/utils.ts"; import { getSlugFromFile } from "~/utils.ts";
import ListingPage from "~/components/ListingPage.astro";
const talks = await Astro.glob("../../talks/*.md"); const talks = await Astro.glob("../../talks/*.md");
@ -11,14 +12,14 @@ const talkCount = _(talks)
const sortedTalks = talks const sortedTalks = talks
.map((talk) => { .map((talk) => {
const slug = getSlugFromFile(talk.file); const slug = `/talks/${getSlugFromFile(talk.file)}`;
return { slug, talk }; return { slug, item: talk };
}) })
.sort((b, a) => { .sort((b, a) => {
const events = [ const events = [
a.talk.frontmatter.events[a.talk.frontmatter.events.length - 1], a.item.frontmatter.events[a.item.frontmatter.events.length - 1],
b.talk.frontmatter.events[b.talk.frontmatter.events.length - 1], b.item.frontmatter.events[b.item.frontmatter.events.length - 1],
]; ];
return ( return (
@ -27,24 +28,10 @@ const sortedTalks = talks
}); });
--- ---
<PageLayout title="Talks and workshops"> <ListingPage items={sortedTalks} title="Talks and workshops">
<p> <p slot="intro">
Starting with my first talk in September 2012, I have given {talkCount} presentations Starting with my first talk in September 2012, I have given {talkCount} presentations
and workshops at various conferences and meetups, in-person and remotely, on and workshops at various conferences and meetups, in-person and remotely, on
topics including PHP, Drupal, automated testing, Git, CSS, and systems administration. topics including PHP, Drupal, automated testing, Git, CSS, and systems administration.
</p> </p>
</ListingPage>
<div>
{
sortedTalks.map((talk) => (
<article>
<a href={`/talks/${talk.slug}`}>
<h2>{talk.talk.frontmatter.title}</h2>
</a>
{talk.talk.frontmatter.description}
</article>
))
}
</div>
</PageLayout>