feat: add related articles section based on tags or most recent posts
This commit is contained in:
@@ -72,6 +72,33 @@ export default async function BlogPostPage({ params }: Props) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
// Articles en rapport : par tags communs, sinon les plus récents
|
||||
let relatedPosts = await prisma.blogPost.findMany({
|
||||
where: {
|
||||
status: 'PUBLISHED',
|
||||
publishedAt: { lte: new Date() },
|
||||
id: { not: post.id },
|
||||
tags: { hasSome: post.tags }
|
||||
},
|
||||
take: 3,
|
||||
orderBy: { date: 'desc' }
|
||||
});
|
||||
|
||||
// Compléter avec les articles récents si nécessaire
|
||||
if (relatedPosts.length < 2) {
|
||||
const excludedIds = [post.id, ...relatedPosts.map(p => p.id)];
|
||||
const additionalPosts = await prisma.blogPost.findMany({
|
||||
where: {
|
||||
status: 'PUBLISHED',
|
||||
publishedAt: { lte: new Date() },
|
||||
id: { notIn: excludedIds }
|
||||
},
|
||||
take: 3 - relatedPosts.length,
|
||||
orderBy: { date: 'desc' }
|
||||
});
|
||||
relatedPosts = [...relatedPosts, ...additionalPosts];
|
||||
}
|
||||
|
||||
return (
|
||||
<article className="bg-gray-50 min-h-screen py-12 relative">
|
||||
{/* Injection du style de force pour le texte */}
|
||||
@@ -163,6 +190,47 @@ export default async function BlogPostPage({ params }: Props) {
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Section Articles en rapport */}
|
||||
{relatedPosts.length > 0 && (
|
||||
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 mt-16 pt-16 border-t border-gray-200">
|
||||
<h2 className="text-2xl md:text-3xl font-serif font-bold text-gray-900 mb-8">Articles en rapport</h2>
|
||||
<div className="grid gap-8 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{relatedPosts.map((rPost) => (
|
||||
<Link
|
||||
key={rPost.id}
|
||||
href={`/blog/${rPost.slug || rPost.id}`}
|
||||
className="group bg-white rounded-xl shadow-sm overflow-hidden border border-gray-100 hover:shadow-md transition-shadow"
|
||||
>
|
||||
<div className="aspect-video relative overflow-hidden">
|
||||
<img
|
||||
src={rPost.imageUrl}
|
||||
alt={rPost.title}
|
||||
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/5 group-hover:bg-transparent transition-colors" />
|
||||
</div>
|
||||
<div className="p-5">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<span className="text-[10px] font-bold uppercase tracking-wider text-brand-600 bg-brand-50 px-2 py-0.5 rounded">
|
||||
{rPost.tags?.[0] || 'Article'}
|
||||
</span>
|
||||
<span className="text-xs text-gray-400">
|
||||
{new Date(rPost.date).toLocaleDateString('fr-FR', { month: 'short', day: 'numeric' })}
|
||||
</span>
|
||||
</div>
|
||||
<h3 className="text-lg font-bold text-gray-900 group-hover:text-brand-600 transition-colors line-clamp-2 leading-snug">
|
||||
{rPost.title}
|
||||
</h3>
|
||||
<p className="mt-2 text-sm text-gray-500 line-clamp-2">
|
||||
{rPost.excerpt}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</article>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user