| import { Request, Response } from 'express';
|
| import prisma from '../models/prisma';
|
|
|
|
|
| type BlogPostWithAuthor = {
|
| id: string;
|
| title: string;
|
| slug: string;
|
| content: string;
|
| excerpt: string | null;
|
| featuredImage: string | null;
|
| tags: string | null;
|
| status: string;
|
| publishedAt: Date | null;
|
| createdAt: Date;
|
| updatedAt: Date;
|
| authorId: string;
|
| author: { name: string | null } | null;
|
| };
|
|
|
|
|
| export const getRelatedPosts = async (req: Request, res: Response) => {
|
| try {
|
| const { slug } = req.params;
|
|
|
|
|
| const currentPost = await prisma.blogPost.findFirst({
|
| where: { slug }
|
| });
|
|
|
| if (!currentPost) {
|
| return res.status(404).json({ error: 'Post not found' });
|
| }
|
|
|
|
|
| let tags: string[] = [];
|
| try {
|
| if (currentPost.tags) tags = JSON.parse(currentPost.tags);
|
| } catch (e) {
|
|
|
| }
|
|
|
|
|
| if (tags.length === 0) {
|
| const latest = await prisma.blogPost.findMany({
|
| where: {
|
| status: 'PUBLISHED',
|
| slug: { not: slug },
|
| publishedAt: { lte: new Date() }
|
| },
|
| orderBy: { publishedAt: 'desc' },
|
| take: 3,
|
| include: { author: { select: { name: true } } }
|
| });
|
| return res.status(200).json(latest);
|
| }
|
|
|
|
|
|
|
|
|
|
|
| const allOtherPosts = await prisma.blogPost.findMany({
|
| where: {
|
| status: 'PUBLISHED',
|
| slug: { not: slug },
|
| publishedAt: { lte: new Date() }
|
| },
|
| orderBy: {
|
| publishedAt: 'desc'
|
| },
|
| take: 50,
|
| include: { author: { select: { name: true } } }
|
| });
|
|
|
|
|
| const scoredPosts: { post: BlogPostWithAuthor; score: number }[] = allOtherPosts.map((post: BlogPostWithAuthor) => {
|
| let postTags: string[] = [];
|
| try {
|
| if (post.tags) postTags = JSON.parse(post.tags);
|
| } catch (e) { }
|
|
|
| const intersection = tags.filter(t => postTags.includes(t));
|
| return { post, score: intersection.length };
|
| });
|
|
|
|
|
| scoredPosts.sort((a: { post: BlogPostWithAuthor; score: number }, b: { post: BlogPostWithAuthor; score: number }) => b.score - a.score);
|
|
|
|
|
| const related = scoredPosts.slice(0, 3).map((s: { post: BlogPostWithAuthor; score: number }) => s.post);
|
|
|
| return res.status(200).json(related);
|
| } catch (error) {
|
| console.error('Error fetching related posts:', error);
|
| return res.status(500).json({ error: 'Internal server error' });
|
| }
|
| }
|
|
|