first commit

This commit is contained in:
2025-10-09 20:05:39 +05:30
commit d4fcb658e3
69 changed files with 13582 additions and 0 deletions

256
src/services/blogService.ts Normal file
View File

@ -0,0 +1,256 @@
// services/blogService.ts
export interface Professor {
id: number;
firstName?: string;
name?: string; // Fallback for different naming
}
export interface ApiBlog {
id: number;
title: string;
content: string;
professors: Professor[];
tags: string[];
posted: boolean; // From your Angular form
author?: string;
createdDate?: string;
updatedDate?: string;
publishDate?: string;
imageUrl?: string; // Added for uploaded images
}
export interface Blog {
id: number;
title: string;
excerpt: string;
tags: string[];
image: string;
publishDate: string;
readTime: string;
content?: string;
professors?: Professor[];
}
class BlogService {
private apiBaseUrl = process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:8080';
async getAllBlogs(): Promise<Blog[]> {
try {
const response = await fetch(`${this.apiBaseUrl}/api/posts`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const apiBlogs: ApiBlog[] = await response.json();
return this.transformApiBlogsToBlogs(apiBlogs);
} catch (error) {
console.error('Error fetching blogs:', error);
return this.getFallbackBlogs(); // Return fallback data if API fails
}
}
async getBlogById(id: number): Promise<Blog | null> {
try {
const response = await fetch(`${this.apiBaseUrl}/api/posts/${id}`);
if (!response.ok) {
if (response.status === 404) {
return null;
}
throw new Error(`HTTP error! status: ${response.status}`);
}
const apiBlog: ApiBlog = await response.json();
return this.transformApiBlogToBlog(apiBlog);
} catch (error) {
console.error(`Error fetching blog ${id}:`, error);
return null;
}
}
// Get only posted blogs for public display
async getPostedBlogs(): Promise<Blog[]> {
try {
const response = await fetch(`${this.apiBaseUrl}/api/posts/posted`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const apiBlogs: ApiBlog[] = await response.json();
return this.transformApiBlogsToBlogs(apiBlogs);
} catch (error) {
console.error('Error fetching posted blogs:', error);
return this.getFallbackBlogs();
}
}
// Get blogs by tag
async getBlogsByTag(tag: string): Promise<Blog[]> {
try {
const response = await fetch(`${this.apiBaseUrl}/api/posts/tag/${encodeURIComponent(tag)}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const apiBlogs: ApiBlog[] = await response.json();
return this.transformApiBlogsToBlogs(apiBlogs);
} catch (error) {
console.error(`Error fetching blogs by tag ${tag}:`, error);
return [];
}
}
// Get tag counts
async getTagsWithCount(): Promise<{ [key: string]: number }> {
try {
const response = await fetch(`${this.apiBaseUrl}/api/posts/tags/count`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const tagCounts: { [key: string]: number } = await response.json();
return tagCounts;
} catch (error) {
console.error('Error fetching tag counts:', error);
return {};
}
}
private transformApiBlogsToBlogs(apiBlogs: ApiBlog[]): Blog[] {
return apiBlogs.map(apiBlog => this.transformApiBlogToBlog(apiBlog));
}
private transformApiBlogToBlog(apiBlog: ApiBlog): Blog {
return {
id: apiBlog.id,
title: apiBlog.title,
excerpt: this.generateExcerpt(apiBlog.content),
tags: apiBlog.tags || [],
image: this.getImageUrl(apiBlog.imageUrl), // Use uploaded image or default
publishDate: this.formatDate(apiBlog.publishDate || apiBlog.createdDate || new Date().toISOString()),
readTime: this.calculateReadTime(apiBlog.content),
content: apiBlog.content,
professors: apiBlog.professors
};
}
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(' ');
if (lastSpaceIndex > 0) {
return truncated.substr(0, lastSpaceIndex) + '...';
}
return truncated + '...';
}
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);
return `${minutes} min read`;
}
private formatDate(dateString: string): string {
try {
const date = new Date(dateString);
return date.toISOString().split('T')[0]; // Returns YYYY-MM-DD format
} catch (error) {
return new Date().toISOString().split('T')[0]; // Fallback to current date
}
}
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 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
publishDate: "2024-01-15",
readTime: "8 min read"
},
{
id: 2,
title: "Building Resilience After Childhood Trauma",
excerpt: "Discover practical strategies and therapeutic approaches for healing from childhood trauma. Explore how resilience can be developed and nurtured throughout the recovery journey.",
tags: ["Childhood Trauma", "Resilience", "Healing"],
image: "/images/default-blog-image.jpg",
publishDate: "2024-01-12",
readTime: "6 min read"
},
{
id: 3,
title: "The Role of Family Support in Trauma Recovery",
excerpt: "Family support plays a crucial role in trauma recovery. Learn how loved ones can provide effective support and create a healing environment for trauma survivors.",
tags: ["Family Support", "Recovery", "Relationships"],
image: "/images/default-blog-image.jpg",
publishDate: "2024-01-10",
readTime: "5 min read"
},
{
id: 4,
title: "Trauma-Informed Care: A Comprehensive Approach",
excerpt: "Explore the principles of trauma-informed care and how healthcare providers can create safe, supportive environments for trauma survivors seeking treatment.",
tags: ["Trauma-Informed Care", "Healthcare", "Best Practices"],
image: "/images/default-blog-image.jpg",
publishDate: "2024-01-08",
readTime: "7 min read"
},
{
id: 5,
title: "Mindfulness and Meditation for Trauma Healing",
excerpt: "Discover how mindfulness practices and meditation techniques can be powerful tools in trauma recovery, helping to regulate emotions and reduce anxiety.",
tags: ["Mindfulness", "Meditation", "Coping Strategies"],
image: "/images/default-blog-image.jpg",
publishDate: "2024-01-05",
readTime: "6 min read"
},
{
id: 6,
title: "Workplace Trauma: Recognition and Response",
excerpt: "Understanding workplace trauma and its impact on employees. Learn about creating supportive work environments and implementing effective response strategies.",
tags: ["Workplace Trauma", "Employee Support", "Mental Health"],
image: "/images/default-blog-image.jpg",
publishDate: "2024-01-03",
readTime: "9 min read"
}
];
}
}
export const blogService = new BlogService();