144 lines
4.6 KiB
TypeScript
144 lines
4.6 KiB
TypeScript
import { notFound } from 'next/navigation';
|
|
import Image from 'next/image';
|
|
import Link from 'next/link';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import matter from 'gray-matter';
|
|
import { remark } from 'remark';
|
|
import html from 'remark-html';
|
|
import gfm from 'remark-gfm';
|
|
interface Props {
|
|
params: Promise<{ slug: string }>;
|
|
}
|
|
|
|
async function getPost(slug: string) {
|
|
const blogDir = path.join(process.cwd(), 'src/content/blog');
|
|
const filePath = path.join(blogDir, `${slug}.md`);
|
|
|
|
if (!fs.existsSync(filePath)) {
|
|
return null;
|
|
}
|
|
|
|
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
const { data, content } = matter(fileContent);
|
|
|
|
const processedContent = await remark()
|
|
.use(gfm)
|
|
.use(html, { sanitize: false })
|
|
.process(content);
|
|
const contentHtml = processedContent.toString();
|
|
|
|
// Support both 'category' and 'categories' field names
|
|
const category = data.category || (Array.isArray(data.categories) ? data.categories[0] : 'ทั่วไป');
|
|
// Support both 'image' and 'featuredImage' field names
|
|
const image = data.image || data.featuredImage || '/images/2021/03/ppr-pipe_000C.jpg';
|
|
|
|
return {
|
|
slug,
|
|
title: data.title || 'ไม่มีชื่อ',
|
|
excerpt: data.excerpt || '',
|
|
date: data.date || new Date().toISOString(),
|
|
author: data.author || 'ดีลพลัสเทค',
|
|
category,
|
|
image,
|
|
content: contentHtml,
|
|
};
|
|
}
|
|
|
|
export async function generateMetadata({ params }: Props) {
|
|
const { slug } = await params;
|
|
const decodedSlug = decodeURIComponent(slug);
|
|
const post = await getPost(decodedSlug);
|
|
if (!post) return { title: 'ไม่พบบทความ' };
|
|
|
|
return {
|
|
title: post.title,
|
|
description: post.excerpt,
|
|
};
|
|
}
|
|
|
|
export async function generateStaticParams() {
|
|
const blogDir = path.join(process.cwd(), 'src/content/blog');
|
|
const files = fs.readdirSync(blogDir).filter(f => f.endsWith('.md'));
|
|
|
|
return files.map(filename => ({
|
|
slug: filename.replace('.md', ''),
|
|
}));
|
|
}
|
|
|
|
export default async function BlogPostPage({ params }: Props) {
|
|
const { slug } = await params;
|
|
const decodedSlug = decodeURIComponent(slug);
|
|
const post = await getPost(decodedSlug);
|
|
|
|
if (!post) {
|
|
notFound();
|
|
}
|
|
|
|
return (
|
|
<div className="pt-32 pb-16">
|
|
<article className="container mx-auto px-4">
|
|
{/* Header */}
|
|
<header className="max-w-3xl mx-auto mb-8">
|
|
<Link
|
|
href="/blog"
|
|
className="inline-flex items-center text-primary-600 hover:text-primary-700 mb-4"
|
|
>
|
|
<svg className="w-4 h-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
|
|
</svg>
|
|
กลับไปหน้าบทความ
|
|
</Link>
|
|
|
|
<span className="industrial-badge">{post.category}</span>
|
|
|
|
<h1 className="text-3xl md:text-4xl lg:text-5xl font-bold text-secondary-900 mt-4 mb-4">
|
|
{post.title}
|
|
</h1>
|
|
|
|
<div className="flex items-center gap-4 text-secondary-600">
|
|
<span>{post.author}</span>
|
|
<span>•</span>
|
|
<time>
|
|
{new Date(post.date).toLocaleDateString('th-TH', {
|
|
year: 'numeric',
|
|
month: 'long',
|
|
day: 'numeric',
|
|
})}
|
|
</time>
|
|
</div>
|
|
</header>
|
|
|
|
{/* Featured Image */}
|
|
<div className="relative aspect-video max-w-4xl mx-auto rounded-xl overflow-hidden mb-8">
|
|
<Image
|
|
src={post.image}
|
|
alt={post.title}
|
|
fill
|
|
className="object-cover"
|
|
/>
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<div
|
|
className="max-w-3xl mx-auto prose prose-lg prose-headings:font-bold prose-headings:text-secondary-900 prose-p:text-secondary-600 prose-a:text-primary-600 prose-strong:text-secondary-900"
|
|
dangerouslySetInnerHTML={{ __html: post.content }}
|
|
/>
|
|
|
|
{/* CTA */}
|
|
<div className="max-w-3xl mx-auto mt-12 bg-secondary-800 rounded-2xl p-8 text-center">
|
|
<h2 className="text-2xl font-bold text-white mb-4">
|
|
สนใจสินค้าหรือบริการ?
|
|
</h2>
|
|
<p className="text-secondary-300 mb-6">
|
|
ติดต่อเราเพื่อรับคำปรึกษาและใบเสนอราคาฟรี
|
|
</p>
|
|
<Link href="/contact-us" className="btn-primary">
|
|
ติดต่อเรา
|
|
</Link>
|
|
</div>
|
|
</article>
|
|
</div>
|
|
);
|
|
}
|