canina/frontend/application/app/blog/page.tsx
parsa aghaei fa1a35c835
Some checks failed
Deploy Canina / deploy (push) Successful in 1m34s
E2E Playwright Tests / Run Full E2E & Security Suites (push) Failing after 6s
feat(media): implement nextjs media proxy API routes (/api/uploads & /api/media) with server-side caching and streaming
2026-08-29 12:13:16 +03:30

81 lines
3.3 KiB
TypeScript

import BlogPage from "../../components/BlogPage";
import type { Metadata } from 'next';
import { getPageMetadata } from "../../lib/seo";
import { getMediaUrl } from "../../lib/media";
export async function generateMetadata(): Promise<Metadata> {
return getPageMetadata('blog', {
canonicalPath: '/blog',
fallbackTitle: 'مجله سلامت و دانشنامه مقالات تخصصی پت',
fallbackDesc: 'جدیدترین مقالات علمی، راهنمای تغذیه، بیماری‌های سگ و گربه و توصیه‌های بالینی متخصصان و دامپزشکان کنینا.',
});
}
export const revalidate = 3600;
async function getCategories() {
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/categories`, {
next: { tags: ['blogs', 'blog-categories'], revalidate: 3600 },
});
if (!res.ok) return [];
const json = await res.json();
return json.data || json || [];
} catch (err) {
console.error('[Blog] Error fetching categories:', err);
return [];
}
}
async function getBlogs() {
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?limit=50`, {
next: { tags: ['blogs'], revalidate: 3600 },
});
if (!res.ok) {
console.error(`[Blog] Failed to fetch blogs: ${res.status}`);
return [];
}
const data = await res.json();
const list = Array.isArray(data.data) ? data.data : Array.isArray(data) ? data : [];
return list.map((b: any) => {
const authorObj = b.author as Record<string, string> | 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.excerpt || b.metaDescription || (typeof b.content === 'string' ? b.content.substring(0, 150).replace(/<[^>]+>/g, '') + '...' : '')),
category: b.category?.name || 'دانشنامه و سلامت',
categoryId: b.categoryId || undefined,
tags: b.tags || [],
date: b.publishedAt
? new Date(String(b.publishedAt)).toLocaleDateString('fa-IR')
: b.createdAt
? new Date(String(b.createdAt)).toLocaleDateString('fa-IR')
: '',
readingTime: b.readingTime || 3,
image: getMediaUrl(String(b.imageUrl || b.coverImage || '/assets/images/blog-placeholder.png')),
imageAlt: b.imageAlt || b.title,
author: authorName || 'نویسنده کنینا',
content: String(b.content || ''),
featured: Boolean(b.featured),
viewCount: Number(b.viewCount) || 0,
};
});
} catch (error) {
console.error('[Blog] Error fetching blogs:', error);
return [];
}
}
export default async function Blog() {
const [blogs, categories] = await Promise.all([getBlogs(), getCategories()]);
return <BlogPage blogs={blogs} categories={categories} />;
}