68 lines
2.1 KiB
Plaintext
68 lines
2.1 KiB
Plaintext
---
|
|
import BlogCard from './BlogCard.astro';
|
|
import { getCollection } from 'astro:content';
|
|
|
|
interface Props {
|
|
currentSlug: string;
|
|
tags: string[];
|
|
locale?: string;
|
|
maxPosts?: number;
|
|
}
|
|
|
|
const { currentSlug, tags, locale = 'en', maxPosts = 3 } = Astro.props;
|
|
|
|
// Get all published posts in the same locale
|
|
const allPosts = await getCollection('blog', ({ data }) => {
|
|
return data.locale === locale && (import.meta.env.PROD ? data.draft !== true : true);
|
|
});
|
|
|
|
// Filter to find posts with matching tags
|
|
const relatedPosts = allPosts
|
|
.filter((post) => {
|
|
// Exclude current post
|
|
if (post.id === currentSlug || post.id.endsWith(`/${currentSlug}`)) return false;
|
|
|
|
// Must have at least one matching tag
|
|
if (!tags.length) return false;
|
|
return post.data.tags.some((tag) => tags.includes(tag));
|
|
})
|
|
// Sort by number of matching tags, then by date
|
|
.sort((a, b) => {
|
|
const aMatches = a.data.tags.filter((tag) => tags.includes(tag)).length;
|
|
const bMatches = b.data.tags.filter((tag) => tags.includes(tag)).length;
|
|
|
|
if (bMatches !== aMatches) return bMatches - aMatches;
|
|
return b.data.publishedAt.valueOf() - a.data.publishedAt.valueOf();
|
|
})
|
|
.slice(0, maxPosts);
|
|
|
|
// Generate URLs for each post (remove locale prefix from id)
|
|
const getPostUrl = (postId: string) => {
|
|
const slug = postId.replace(`${locale}/`, '');
|
|
return `/blog/${slug}`;
|
|
};
|
|
---
|
|
|
|
{relatedPosts.length > 0 && (
|
|
<section class="border-t border-border py-[var(--space-section-sm)]">
|
|
<h2 class="font-display text-2xl font-bold text-foreground mb-[var(--space-stack-lg)]">
|
|
Related Posts
|
|
</h2>
|
|
|
|
<div class="grid gap-[var(--space-stack-lg)] md:grid-cols-2 lg:grid-cols-3">
|
|
{relatedPosts.map((post) => (
|
|
<BlogCard
|
|
title={post.data.title}
|
|
description={post.data.description}
|
|
href={getPostUrl(post.id)}
|
|
publishedAt={post.data.publishedAt}
|
|
tags={post.data.tags}
|
|
author={post.data.author}
|
|
image={post.data.image}
|
|
svgSlug={post.data.svgSlug}
|
|
/>
|
|
))}
|
|
</div>
|
|
</section>
|
|
)}
|