feat: move all functionality for blog pages to the server

This commit is contained in:
Thomas 2025-03-13 21:43:06 +00:00
parent 5ca7fc1ced
commit 1fd055c38f
No known key found for this signature in database
6 changed files with 99 additions and 72 deletions

View file

@ -1 +1,42 @@
import { BlogController } from '$lib/blog/BlogController.js';
import type { Load } from '@sveltejs/kit';
import { differenceInCalendarDays, getYear } from 'date-fns';
export const prerender = true;
export const load: Load = async ({ params, url }) => {
const controller = await BlogController.singleton();
const tags = url.searchParams.getAll('tag');
let posts = [];
if (tags.length > 0) {
posts = await controller.getBlogPostsByTags(tags);
} else {
posts = await controller.getAllBlogPosts();
}
const currentYear = getYear(new Date());
console.log({ posts });
const mostRecentPost = posts[0];
const daysSinceLastPublish = differenceInCalendarDays(new Date(), new Date(mostRecentPost.date));
const numberOfPosts = posts.length;
const firstPost = posts[numberOfPosts - 1];
const daysSinceFirstPost = differenceInCalendarDays(new Date(), new Date(firstPost.date));
const averageDaysBetweenPosts = Number(daysSinceFirstPost / numberOfPosts).toFixed(2);
const numberOfBlogPostsThisYear: number = posts.filter(
(post) => getYear(new Date(post.date)) === currentYear
).length;
return {
tags,
posts,
firstPost,
averageDaysBetweenPosts,
daysSinceFirstPost,
daysSinceLastPublish,
numberOfPosts,
numberOfBlogPostsThisYear,
};
};

View file

@ -71,7 +71,11 @@
</section>
<section class="section">
<h2>All Writing</h2>
{#if data.tags.length > 0}
<h2>Tags: {data.tags.join(", ")}</h2>
{:else}
<h2>All Writing</h2>
{/if}
<ul class="posts">
{#each posts as post, index}
<BlogPostListItem

View file

@ -1,45 +0,0 @@
import type { LoadEvent } from '@sveltejs/kit';
import { differenceInCalendarDays, getYear } from 'date-fns';
export const prerender = false;
interface BlogPostListItem {
title: string;
author: string;
book_review: boolean;
content: string;
date: string;
preview: string;
slug: string;
content_type: 'blog' | 'book_review' | 'snout_street_studios';
}
export async function load({ fetch }: LoadEvent) {
const posts: BlogPostListItem[] = await fetch('/api/blog.json')
.then((res) => res.json())
.then((res) => res.posts);
const currentYear = getYear(new Date());
console.log({ posts });
const mostRecentPost = posts[0];
console.log({ ...mostRecentPost });
const daysSinceLastPublish = differenceInCalendarDays(new Date(), new Date(mostRecentPost.date));
const numberOfPosts = posts.length;
const firstPost = posts[numberOfPosts - 1];
const daysSinceFirstPost = differenceInCalendarDays(new Date(), new Date(firstPost.date));
const averageDaysBetweenPosts = Number(daysSinceFirstPost / numberOfPosts).toFixed(2);
const numberOfBlogPostsThisYear: number = posts.filter(
(post) => getYear(new Date(post.date)) === currentYear
).length;
return {
posts,
firstPost,
averageDaysBetweenPosts,
daysSinceFirstPost,
daysSinceLastPublish,
numberOfPosts,
numberOfBlogPostsThisYear,
};
}

View file

@ -0,0 +1,14 @@
import { error, type Load, type LoadEvent } from '@sveltejs/kit';
import { BlogController } from '../../../lib/blog/BlogController.js';
export const load: Load = async ({ params, fetch }) => {
const controller = await BlogController.singleton();
const slug = params['slug'] as string;
const post = await controller.getBlogPostBySlug(slug);
if (!post) {
return error(404, 'Post not found');
}
return { post, date: new Date(post.date) };
};

View file

@ -1,5 +1,5 @@
<script lang="ts">
import type { PageData } from "./$types.js";
import type { PageData, PageServerData } from "./$types.js";
import { intlFormat } from "date-fns";
import Navbar from "$lib/components/Navbar.svelte";
import { onMount } from "svelte";
@ -9,11 +9,7 @@
}
let { data }: Props = $props();
let { date, post } = $derived(data);
onMount(() => {
console.log({ date, post });
});
const post = data.post;
</script>
<svelte:head>
@ -41,14 +37,14 @@
<header class="blog__header">
<h1 class="title post-title">{post.title}</h1>
<p class="post-author">
{#if post.autor}
{#if post.author}
{post.author}
{:else}
Thomas Wilson
{/if}
</p>
<p class="post-date">
{intlFormat(date, {
{intlFormat(post.date, {
weekday: "long",
day: "2-digit",
month: "long",
@ -56,6 +52,16 @@
localeMatcher: "best fit",
})}
</p>
{#if post}
<div class="post-tags">
{#each post.tags as tag}
<a
href={`/blog?tag=${encodeURIComponent(tag)}`}
class="post-tags__tag">#{tag}</a
>
{/each}
</div>
{/if}
</header>
<article id="article">
@ -64,7 +70,7 @@
</article>
</main>
<style lang="scss">
<style>
.blog {
background-color: var(--colour-scheme-background);
display: flex;
@ -80,6 +86,7 @@
display: flex;
flex-flow: column;
align-items: center;
container-type: inline-size;
}
.post-title {
@ -87,6 +94,14 @@
line-height: 125%;
max-width: 30ch;
font-family: var(--font-family-serif);
font-size: clamp(2rem, 10vw, 4rem);
max-width: 95%;
}
@container (min-width: 550px) {
.post-title {
font-size: 4rem;
}
}
.post-author {
@ -104,6 +119,21 @@
margin: 0;
}
.post-tags {
display: flex;
flex-wrap: wrap;
justify-content: center;
margin-top: 8px;
gap: 8px;
}
.post-tags__tag {
border: 2px solid var(--brand-orange);
border-radius: 8px;
padding: 4px 8px;
font-size: 0.8rem;
}
:global(#article p) {
padding-bottom: 12px;
}

View file

@ -1,17 +0,0 @@
import type { LoadEvent } from '@sveltejs/kit';
import type { Post } from '$lib/Post.js';
export async function load({ params, fetch }: LoadEvent): Promise<{ post: Post; date: Date }> {
const { slug } = params;
const { post } = await fetch(`/api/blog/${slug}.json`)
.then((res) => res.json())
.catch((error) => {
console.error(error);
return { post: null };
});
return {
post,
date: new Date(post.date),
};
}