Enhance blog posts with author info, comments, likes, and tags

Improves blog post API endpoints to fetch author details, comment/like counts, and tags using storage methods.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: cbacfb18-842a-4116-a907-18c0105ad8ec
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/39b5c689-6e8a-4d5a-9792-69cc81a56534/809eda1d-d63f-4926-be8e-d300221b59bf.jpg
This commit is contained in:
mukimovd 2025-05-01 03:40:07 +00:00
parent 987af7c0e7
commit 78d07df844
2 changed files with 93 additions and 6 deletions

View File

@ -410,16 +410,99 @@ export async function registerRoutes(app: Express): Promise<Server> {
app.get("/api/blog", async (req: Request, res: Response) => { app.get("/api/blog", async (req: Request, res: Response) => {
const limit = req.query.limit ? Number(req.query.limit) : undefined; const limit = req.query.limit ? Number(req.query.limit) : undefined;
const offset = req.query.offset ? Number(req.query.offset) : undefined; const offset = req.query.offset ? Number(req.query.offset) : undefined;
const posts = await storage.getBlogPosts(limit, offset);
res.json(posts); try {
// Get basic blog posts
const posts = await storage.getBlogPosts(limit, offset);
// Enhance each post with author details, comment count, and like count
const enhancedPosts = await Promise.all(posts.map(async (post) => {
const author = post.authorId ? await storage.getUser(post.authorId) : undefined;
const authorInfo = author ? {
id: author.id,
displayName: author.displayName,
avatar: author.avatar
} : undefined;
// Get comment count
const comments = await storage.getCommentsByEntityId('blogPost', post.id);
const commentCount = comments.length;
// Get like count
const likes = await storage.getLikesByEntity('blogPost', post.id);
const likeCount = likes.length;
// Get tags for the post
const tags = await storage.getBlogPostTags(post.id);
return {
...post,
author: authorInfo,
commentCount,
likeCount,
tags
};
}));
res.json(enhancedPosts);
} catch (error) {
console.error("Error fetching blog posts:", error);
res.status(500).json({ message: "Failed to fetch blog posts" });
}
}); });
app.get("/api/blog/:slug", async (req: Request, res: Response) => { app.get("/api/blog/:slug", async (req: Request, res: Response) => {
const post = await storage.getBlogPostBySlug(req.params.slug); try {
if (!post) { const post = await storage.getBlogPostBySlug(req.params.slug);
return res.status(404).json({ message: "Blog post not found" }); if (!post) {
return res.status(404).json({ message: "Blog post not found" });
}
// Get author details
const author = post.authorId ? await storage.getUser(post.authorId) : undefined;
// Remove password from author if it exists
const authorInfo = author ? {
...author,
password: undefined
} : undefined;
// Get comments for the post
const comments = await storage.getCommentsByEntityId('blogPost', post.id);
// Get enhanced comments with user info
const enhancedComments = await Promise.all(comments.map(async (comment) => {
const user = await storage.getUser(comment.userId);
return {
...comment,
user: user ? {
id: user.id,
displayName: user.displayName,
avatar: user.avatar,
role: user.role
} : undefined
};
}));
// Get like count
const likes = await storage.getLikesByEntity('blogPost', post.id);
const likeCount = likes.length;
// Get tags for the post
const tags = await storage.getBlogPostTags(post.id);
res.json({
...post,
author: authorInfo,
comments: enhancedComments,
commentCount: comments.length,
likeCount,
tags
});
} catch (error) {
console.error("Error fetching blog post:", error);
res.status(500).json({ message: "Failed to fetch blog post" });
} }
res.json(post);
}); });
app.post("/api/blog", async (req: Request, res: Response) => { app.post("/api/blog", async (req: Request, res: Response) => {

View File

@ -46,6 +46,7 @@ export interface IStorage {
createTag(tag: InsertTag): Promise<Tag>; createTag(tag: InsertTag): Promise<Tag>;
addTagToWork(workId: number, tagId: number): Promise<void>; addTagToWork(workId: number, tagId: number): Promise<void>;
getWorkTags(workId: number): Promise<Tag[]>; getWorkTags(workId: number): Promise<Tag[]>;
getBlogPostTags(postId: number): Promise<Tag[]>;
// Bookmark methods // Bookmark methods
getBookmarksByUserId(userId: number): Promise<Bookmark[]>; getBookmarksByUserId(userId: number): Promise<Bookmark[]>;
@ -57,6 +58,7 @@ export interface IStorage {
getCommentsByWorkId(workId: number): Promise<Comment[]>; getCommentsByWorkId(workId: number): Promise<Comment[]>;
getCommentsByTranslationId(translationId: number): Promise<Comment[]>; getCommentsByTranslationId(translationId: number): Promise<Comment[]>;
getCommentsByUserId(userId: number): Promise<Comment[]>; getCommentsByUserId(userId: number): Promise<Comment[]>;
getCommentsByEntityId(entityType: string, entityId: number): Promise<Comment[]>;
createComment(comment: InsertComment): Promise<Comment>; createComment(comment: InsertComment): Promise<Comment>;
// Like methods // Like methods
@ -101,6 +103,7 @@ export class MemStorage implements IStorage {
private translations: Map<number, Translation>; private translations: Map<number, Translation>;
private tags: Map<number, Tag>; private tags: Map<number, Tag>;
private workTagsRelations: Map<number, Set<number>>; private workTagsRelations: Map<number, Set<number>>;
private blogPostTagsRelations: Map<number, Set<number>>;
private bookmarks: Map<number, Bookmark>; private bookmarks: Map<number, Bookmark>;
private comments: Map<number, Comment>; private comments: Map<number, Comment>;
private likes: Map<number, Like>; private likes: Map<number, Like>;
@ -131,6 +134,7 @@ export class MemStorage implements IStorage {
this.translations = new Map(); this.translations = new Map();
this.tags = new Map(); this.tags = new Map();
this.workTagsRelations = new Map(); this.workTagsRelations = new Map();
this.blogPostTagsRelations = new Map();
this.bookmarks = new Map(); this.bookmarks = new Map();
this.comments = new Map(); this.comments = new Map();
this.likes = new Map(); this.likes = new Map();