From 58ea820e1481b48b6c10ed6b744197c1a809be06 Mon Sep 17 00:00:00 2001 From: mukeshs Date: Fri, 10 Oct 2025 00:37:00 +0530 Subject: [PATCH] blog update --- src/services/blogService.ts | 65 +++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/src/services/blogService.ts b/src/services/blogService.ts index a52ee8b..6abc274 100644 --- a/src/services/blogService.ts +++ b/src/services/blogService.ts @@ -2,7 +2,7 @@ export interface Professor { id: number; firstName?: string; - name?: string; // Fallback for different naming + name?: string; } export interface ApiBlog { @@ -11,12 +11,12 @@ export interface ApiBlog { content: string; professors: Professor[]; tags: string[]; - posted: boolean; // From your Angular form + posted: boolean; author?: string; createdDate?: string; updatedDate?: string; publishDate?: string; - imageUrl?: string; // Added for uploaded images + imageUrl?: string; } export interface Blog { @@ -44,7 +44,7 @@ class BlogService { return this.transformApiBlogsToBlogs(apiBlogs); } catch (error) { console.error('Error fetching blogs:', error); - return this.getFallbackBlogs(); // Return fallback data if API fails + return this.getFallbackBlogs(); } } @@ -65,7 +65,6 @@ class BlogService { } } - // Get only posted blogs for public display async getPostedBlogs(): Promise { try { const response = await fetch(`${this.apiBaseUrl}/api/posts/posted`); @@ -80,7 +79,6 @@ class BlogService { } } - // Get blogs by tag async getBlogsByTag(tag: string): Promise { try { const response = await fetch(`${this.apiBaseUrl}/api/posts/tag/${encodeURIComponent(tag)}`); @@ -95,7 +93,6 @@ class BlogService { } } - // Get tag counts async getTagsWithCount(): Promise<{ [key: string]: number }> { try { const response = await fetch(`${this.apiBaseUrl}/api/posts/tags/count`); @@ -120,7 +117,7 @@ class BlogService { title: apiBlog.title, excerpt: this.generateExcerpt(apiBlog.content), tags: apiBlog.tags || [], - image: this.getImageUrl(apiBlog.imageUrl), // Use uploaded image or default + image: this.getImageUrl(apiBlog.imageUrl), publishDate: this.formatDate(apiBlog.publishDate || apiBlog.createdDate || new Date().toISOString()), readTime: this.calculateReadTime(apiBlog.content), content: apiBlog.content, @@ -131,14 +128,12 @@ class BlogService { private generateExcerpt(content: string, maxLength: number = 150): string { if (!content) return 'No content available.'; - // Strip HTML tags and get plain text const plainText = content.replace(/<[^>]*>/g, ''); if (plainText.length <= maxLength) { return plainText; } - // Find the last complete word within the limit const truncated = plainText.substr(0, maxLength); const lastSpaceIndex = truncated.lastIndexOf(' '); @@ -152,11 +147,9 @@ class BlogService { private calculateReadTime(content: string): string { if (!content) return '1 min read'; - // Strip HTML and count words const plainText = content.replace(/<[^>]*>/g, ''); const wordCount = plainText.split(/\s+/).filter(word => word.length > 0).length; - // Average reading speed is 200-250 words per minute const readingSpeed = 225; const minutes = Math.ceil(wordCount / readingSpeed); @@ -166,41 +159,57 @@ class BlogService { private formatDate(dateString: string): string { try { const date = new Date(dateString); - return date.toISOString().split('T')[0]; // Returns YYYY-MM-DD format + return date.toISOString().split('T')[0]; } catch (error) { - return new Date().toISOString().split('T')[0]; // Fallback to current date + return new Date().toISOString().split('T')[0]; } } private getImageUrl(imageUrl?: string): string { - if (imageUrl) { - // If the imageUrl is a full URL, return as is - if (imageUrl.startsWith('http')) { - return imageUrl; - } - // If it's a relative path from your backend, construct full URL - return `${this.apiBaseUrl}${imageUrl}`; + // Return default if no imageUrl provided + if (!imageUrl || imageUrl.trim() === '') { + return this.getDefaultImage(); + } + + try { + // Decode if the URL is encoded + const decodedUrl = imageUrl.includes('%') ? decodeURIComponent(imageUrl) : imageUrl; + + // If it's already a complete URL, return as is + if (decodedUrl.startsWith('http://') || decodedUrl.startsWith('https://')) { + return decodedUrl; + } + + // If it starts with /, it's a relative path + if (decodedUrl.startsWith('/')) { + // Check if it's a local public path + if (decodedUrl.startsWith('/images/')) { + return decodedUrl; + } + // It's from the backend API + return `${this.apiBaseUrl}${decodedUrl}`; + } + + // Otherwise, assume it's a backend path without leading / + return `${this.apiBaseUrl}/${decodedUrl}`; + } catch (error) { + console.error('Error processing image URL:', imageUrl, error); + return this.getDefaultImage(); } - - // Return default image when no image is uploaded - return this.getDefaultImage(); } private getDefaultImage(): string { - // Return a single default image from your public folder - // Make sure to add this image to your Next.js public/images directory return '/images/default-blog-image.jpg'; } private getFallbackBlogs(): Blog[] { - // Return the original hardcoded blogs as fallback when API is unavailable return [ { id: 1, title: "Understanding PTSD: Signs, Symptoms, and Treatment Options", excerpt: "Post-traumatic stress disorder affects millions worldwide. Learn about the key symptoms, triggers, and evidence-based treatment approaches that can help individuals reclaim their lives.", tags: ["PTSD", "Mental Health", "Treatment"], - image: "/images/default-blog-image.jpg", // Use default image for fallback + image: "/images/default-blog-image.jpg", publishDate: "2024-01-15", readTime: "8 min read" },