feat: add related blog posts component

This commit is contained in:
Theodore Kruczek
2024-01-14 07:51:36 -05:00
parent 155a602203
commit 13cbe429cc
5 changed files with 67 additions and 0 deletions

View File

@ -0,0 +1,28 @@
---
import { APP_BLOG } from "~/utils/config";
import { fetchPosts, getRelatedPosts } from "~/utils/blog";
import BlogHighlightedPosts from "../widgets/BlogHighlightedPosts.astro";
import type { Post } from "~/types";
import { getBlogPermalink } from "~/utils/permalinks";
export interface Props {
post: Post;
}
const { post } = Astro.props;
const fetchedPosts = await fetchPosts();
const relatedPosts = post.tags ? getRelatedPosts(fetchedPosts, post.slug, post.tags) : [];
---
{
APP_BLOG.isRelatedPostsEnabled ? (
<BlogHighlightedPosts
classes={{ container: "pt-0 lg:pt-0 md:pt-0" }}
title="Related Posts"
linkText="View All Posts"
linkUrl={getBlogPermalink()}
postIds={relatedPosts.map((post) => post.id)}
/>
) : null
}

View File

@ -35,6 +35,8 @@ apps:
blog: blog:
isEnabled: true isEnabled: true
postsPerPage: 6 postsPerPage: 6
isRelatedPostsEnabled: true
relatedPostsCount: 4
post: post:
isEnabled: true isEnabled: true

View File

@ -11,6 +11,7 @@ import { getCanonical, getPermalink } from '~/utils/permalinks';
import { getStaticPathsBlogPost, blogPostRobots } from '~/utils/blog'; import { getStaticPathsBlogPost, blogPostRobots } from '~/utils/blog';
import { findImage } from '~/utils/images'; import { findImage } from '~/utils/images';
import type { MetaData } from '~/types'; import type { MetaData } from '~/types';
import RelatedPosts from '~/components/blog/RelatedPosts.astro';
export const prerender = true; export const prerender = true;
@ -45,4 +46,5 @@ const metadata = merge(
<Layout metadata={metadata}> <Layout metadata={metadata}>
<SinglePost post={{ ...post, image: image }} url={url} /> <SinglePost post={{ ...post, image: image }} url={url} />
<ToBlogLink /> <ToBlogLink />
<RelatedPosts post={post} />
</Layout> </Layout>

View File

@ -90,6 +90,18 @@ const getNormalizedPost = async (post: CollectionEntry<'post'>): Promise<Post> =
}; };
}; };
const getRandomizedPosts = (array: Post[], num: number) => {
const newArray: Post[] = [];
while (newArray.length < num && array.length > 0) {
const randomIndex = Math.floor(Math.random() * array.length);
newArray.push(array[randomIndex]);
array.splice(randomIndex, 1);
}
return newArray;
};
const load = async function (): Promise<Array<Post>> { const load = async function (): Promise<Array<Post>> {
const posts = await getCollection('post'); const posts = await getCollection('post');
const normalizedPosts = posts.map(async (post) => await getNormalizedPost(post)); const normalizedPosts = posts.map(async (post) => await getNormalizedPost(post));
@ -105,6 +117,7 @@ let _posts: Array<Post>;
/** */ /** */
export const isBlogEnabled = APP_BLOG.isEnabled; export const isBlogEnabled = APP_BLOG.isEnabled;
export const isRelatedPostsEnabled = APP_BLOG.isRelatedPostsEnabled;
export const isBlogListRouteEnabled = APP_BLOG.list.isEnabled; export const isBlogListRouteEnabled = APP_BLOG.list.isEnabled;
export const isBlogPostRouteEnabled = APP_BLOG.post.isEnabled; export const isBlogPostRouteEnabled = APP_BLOG.post.isEnabled;
export const isBlogCategoryRouteEnabled = APP_BLOG.category.isEnabled; export const isBlogCategoryRouteEnabled = APP_BLOG.category.isEnabled;
@ -225,3 +238,23 @@ export const getStaticPathsBlogTag = async ({ paginate }: { paginate: PaginateFu
) )
); );
}; };
/** */
export function getRelatedPosts(allPosts: Post[], currentSlug: string, currentTags: string[]) {
if (!isBlogEnabled || !isRelatedPostsEnabled) return [];
const relatedPosts = getRandomizedPosts(
allPosts.filter((post) => post.slug !== currentSlug && post.tags?.some((tag) => currentTags.includes(tag))),
APP_BLOG.relatedPostsCount
);
if (relatedPosts.length < APP_BLOG.relatedPostsCount) {
const morePosts = getRandomizedPosts(
allPosts.filter((post) => post.slug !== currentSlug && !post.tags?.some((tag) => currentTags.includes(tag))),
APP_BLOG.relatedPostsCount - relatedPosts.length
);
relatedPosts.push(...morePosts);
}
return relatedPosts;
}

View File

@ -25,6 +25,8 @@ export interface I18NConfig {
export interface AppBlogConfig { export interface AppBlogConfig {
isEnabled: boolean; isEnabled: boolean;
postsPerPage: number; postsPerPage: number;
isRelatedPostsEnabled: boolean;
relatedPostsCount: number;
post: { post: {
isEnabled: boolean; isEnabled: boolean;
permalink: string; permalink: string;