diff --git a/frontend/application/app/blog/[slug]/page.tsx b/frontend/application/app/blog/[slug]/page.tsx index 694f56d..e0e5074 100644 --- a/frontend/application/app/blog/[slug]/page.tsx +++ b/frontend/application/app/blog/[slug]/page.tsx @@ -4,30 +4,34 @@ import Link from 'next/link'; import Image from 'next/image'; import type { Metadata } from 'next'; -const API_URL = process.env.NEXT_PUBLIC_API_URL || 'https://apicanina.parsaaghayi.ir'; - -async function getBlog(slug: string) { +async function getBlog(rawSlug: string) { try { - const res = await fetch(`${API_URL}/api/blogs/${slug}`, { next: { revalidate: 60 } }); - if (!res.ok) throw new Error('Failed to fetch blog'); + const slug = decodeURIComponent(rawSlug); + const apiUrl = process.env.INTERNAL_API_URL || process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4001/api'; + const apiBase = apiUrl.endsWith('/api') ? apiUrl : `${apiUrl.replace(/\/$/, '')}/api`; + const res = await fetch(`${apiBase}/blogs/${encodeURIComponent(slug)}`, { next: { revalidate: 60 } }); + if (!res.ok) { + console.error(`[Blog] Failed to fetch blog ${slug}: ${res.status}`); + return null; + } const b = await res.json(); return { id: b.id, slug: b.slug, title: b.title, - excerpt: b.metaDescription || b.content.substring(0, 150).replace(/<[^>]+>/g, '') + '...', - image: b.imageUrl, - date: new Date(b.createdAt).toLocaleDateString('fa-IR'), - author: b.author ? `${b.author.firstName} ${b.author.lastName}` : 'نویسنده کنینا', - content: b.content + excerpt: b.metaDescription || (typeof b.content === 'string' ? b.content.substring(0, 150).replace(/<[^>]+>/g, '') + '...' : ''), + image: b.imageUrl || b.coverImage || '/assets/images/blog-placeholder.png', + date: b.createdAt ? new Date(b.createdAt).toLocaleDateString('fa-IR') : '', + author: b.author ? `${b.author.firstName || ''} ${b.author.lastName || ''}`.trim() : 'نویسنده کنینا', + content: b.content || '', }; } catch (error) { - console.error(error); + console.error('[Blog] Error fetching blog detail:', error); return null; } } -export const revalidate = 60; // ensure SSR dynamic revalidation works correctly +export const revalidate = 60; import { getSeoConfig, formatPageTitle } from "../../../lib/seo"; diff --git a/frontend/application/app/blog/page.tsx b/frontend/application/app/blog/page.tsx index 59ae00e..301fd33 100644 --- a/frontend/application/app/blog/page.tsx +++ b/frontend/application/app/blog/page.tsx @@ -11,24 +11,34 @@ export async function generateMetadata(): Promise { } async function getBlogs() { - const rawApiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://127.0.0.1:4001/api'; - const apiBase = rawApiUrl.endsWith('/api') ? rawApiUrl : `${rawApiUrl}/api`; + const apiUrl = process.env.INTERNAL_API_URL || process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4001/api'; + const apiBase = apiUrl.endsWith('/api') ? apiUrl : `${apiUrl.replace(/\/$/, '')}/api`; try { const res = await fetch(`${apiBase}/blogs`, { next: { revalidate: 60 } }); - if (!res.ok) throw new Error('Failed to fetch blogs'); + if (!res.ok) { + console.error(`[Blog] Failed to fetch blogs: ${res.status}`); + return []; + } const data = await res.json(); - return (data.data || data).map((b: Record) => ({ - id: String(b.id || ''), - slug: String(b.slug || ''), - title: String(b.title || ''), - excerpt: String(b.metaDescription || (typeof b.content === 'string' ? b.content.substring(0, 150).replace(/<[^>]+>/g, '') + '...' : '')), - category: String(b.category || 'تغذیه و سلامت'), - date: String(b.createdAt || new Date().toISOString()).split('T')[0], - readTime: '۵ دقیقه', - imageUrl: String(b.coverImage || 'https://images.unsplash.com/photo-1548767797-d8c844163c4c?auto=format&fit=crop&q=80&w=800'), - })); + const list = Array.isArray(data.data) ? data.data : Array.isArray(data) ? data : []; + return list.map((b: Record) => { + const authorObj = b.author as Record | undefined; + const authorName = authorObj ? `${authorObj.firstName || ''} ${authorObj.lastName || ''}`.trim() : 'نویسنده کنینا'; + return { + id: String(b.id || ''), + slug: String(b.slug || ''), + title: String(b.title || ''), + excerpt: String(b.metaDescription || (typeof b.content === 'string' ? b.content.substring(0, 150).replace(/<[^>]+>/g, '') + '...' : '')), + category: String(b.category || 'تغذیه و سلامت'), + date: b.createdAt ? new Date(String(b.createdAt)).toLocaleDateString('fa-IR') : '', + readTime: '۵ دقیقه', + image: String(b.imageUrl || b.coverImage || 'https://images.unsplash.com/photo-1548767797-d8c844163c4c?auto=format&fit=crop&q=80&w=800'), + author: authorName || 'نویسنده کنینا', + content: String(b.content || ''), + }; + }); } catch (error) { - console.error(error); + console.error('[Blog] Error fetching blogs:', error); return []; } }