diff --git a/server/routes.ts b/server/routes.ts index 9a7fa98..e623bdb 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -2,6 +2,7 @@ import type { Express, Request, Response } from "express"; import { createServer, type Server } from "http"; import { storage } from "./storage"; import { z } from "zod"; +import { NextFunction } from "express"; import { insertUserSchema, @@ -16,7 +17,8 @@ import { insertCollectionItemSchema, insertTimelineEventSchema, insertBlogPostSchema, - insertReadingProgressSchema + insertReadingProgressSchema, + Comment } from "@shared/schema"; export async function registerRoutes(app: Express): Promise { @@ -471,9 +473,19 @@ export async function registerRoutes(app: Express): Promise { const comments = await storage.getCommentsByEntityId('blogPost', post.id); // Get enhanced comments with user info - const enhancedComments = await Promise.all(comments.map(async (comment) => { + const enhancedComments = await Promise.all(comments.map(async (comment: Comment) => { + // Create enhanced comment object + interface EnhancedComment extends Comment { + user?: { + id: number; + displayName: string | null; + avatar: string | null; + role: string; + }; + } + const user = await storage.getUser(comment.userId); - return { + const enhancedComment: EnhancedComment = { ...comment, user: user ? { id: user.id, @@ -482,6 +494,8 @@ export async function registerRoutes(app: Express): Promise { role: user.role } : undefined }; + + return enhancedComment; })); // Get like count diff --git a/server/storage.ts b/server/storage.ts index ed2c6f9..5b9c996 100644 --- a/server/storage.ts +++ b/server/storage.ts @@ -282,6 +282,46 @@ export class MemStorage implements IStorage { title: "Death", description: "Died in St. Petersburg from wounds received in a duel with Georges d'Anthès" }); + + // Create sample blog post + const blogPost = this.createBlogPost({ + title: "Exploring Russian Poetry in the Digital Age", + slug: "exploring-russian-poetry-digital-age", + content: ` +# Exploring Russian Poetry in the Digital Age + +The rich tradition of Russian poetry, from the romantic verses of Alexander Pushkin to the Soviet-era works of Anna Akhmatova, continues to captivate readers worldwide. In our increasingly digital world, how do we preserve and promote this literary heritage while making it accessible to new generations? + +## The Digital Transformation of Literature + +Digital platforms offer unprecedented opportunities for exploring Russian poetry: + +- Side-by-side translations allow readers to compare different interpretations +- Interactive annotations provide historical and cultural context +- Audio recordings capture the rhythm and musicality of the original language + +## Challenges and Opportunities + +While digitization opens new doors, it also presents challenges. How do we balance modernization with respect for tradition? How can we ensure that the emotional impact of these works isn't lost in the transition from page to screen? + +As we continue to develop the Tercul platform, we're committed to addressing these questions, creating an immersive experience that honors the depth and beauty of Russian poetic traditions while embracing the possibilities of digital innovation. + `, + authorId: user1.id, + excerpt: "Exploring how digital platforms can help preserve and promote the rich tradition of Russian poetry in the modern age.", + publishedAt: new Date() + }); + + // Add tags to the blog post + this.addTagToBlogPost(blogPost.id, poetryTag.id); + this.addTagToBlogPost(blogPost.id, romanticismTag.id); + + // Add a comment to the blog post + this.createComment({ + content: "Fascinating exploration of how technology can preserve literary traditions!", + userId: user1.id, + workId: 0, // Placeholder for blog posts + parentId: blogPost.id + }); } // User methods @@ -436,6 +476,18 @@ export class MemStorage implements IStorage { return Array.from(tagIds).map(id => this.tags.get(id)!).filter(Boolean); } + async getBlogPostTags(postId: number): Promise { + const tagIds = this.blogPostTagsRelations.get(postId) || new Set(); + return Array.from(tagIds).map(id => this.tags.get(id)!).filter(Boolean); + } + + async addTagToBlogPost(postId: number, tagId: number): Promise { + if (!this.blogPostTagsRelations.has(postId)) { + this.blogPostTagsRelations.set(postId, new Set()); + } + this.blogPostTagsRelations.get(postId)!.add(tagId); + } + // Bookmark methods async getBookmarksByUserId(userId: number): Promise { return Array.from(this.bookmarks.values()).filter( @@ -484,6 +536,31 @@ export class MemStorage implements IStorage { ); } + async getCommentsByEntityId(entityType: string, entityId: number): Promise { + // In our storage model, we have specific fields for workId and translationId, + // but we want to support a more generic entity approach for blog posts, etc. + // For now, we'll handle the mapping between entity types and specific fields + + if (entityType === 'work') { + return this.getCommentsByWorkId(entityId); + } else if (entityType === 'translation') { + return this.getCommentsByTranslationId(entityId); + } else if (entityType === 'blogPost') { + // For blog posts, filter comments by their entityType and entityId properties + // This assumes we're storing comment entities with these properties + return Array.from(this.comments.values()).filter( + comment => + // For blog posts, we're storing the references in the parentId field temporarily + // In a real implementation, we would add proper schema fields for this + comment.workId === 0 && // Use a placeholder workId + comment.parentId === entityId + ); + } + + // Default return empty array if entity type is not recognized + return []; + } + async createComment(insertComment: InsertComment): Promise { const id = this.commentId++; const now = new Date();