erp-platform/company/src/pages/BlogDetail.tsx

113 lines
3.3 KiB
TypeScript
Raw Normal View History

2025-06-19 21:42:16 +00:00
import React, { useState, useEffect } from "react";
import { Link, useParams } from "react-router-dom";
import { useLanguage } from "../context/LanguageContext";
2025-07-28 20:20:06 +00:00
import { BlogPost, blogService } from "../services/blog.service";
2025-06-19 21:42:16 +00:00
import { format } from "date-fns";
import { tr } from "date-fns/locale";
interface PostData {
image?: string;
author?: {
id: string;
name: string;
avatar?: string;
};
}
2025-05-15 10:48:03 +00:00
const BlogDetail: React.FC = () => {
const { id } = useParams<{ id: string }>();
2025-06-22 12:44:11 +00:00
const { language, setLanguage, t } = useLanguage();
2025-06-19 21:42:16 +00:00
const [blogPost, setBlogPost] = useState<BlogPost | null>(null);
const [postData, setPostData] = useState<PostData | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
2025-05-15 10:48:03 +00:00
2025-06-19 21:42:16 +00:00
useEffect(() => {
const fetchBlogPost = async () => {
setLoading(true);
setError(null);
try {
if (id) {
const response = await blogService.getPostBySlug(id);
setBlogPost(response);
setPostData({
image: response.coverImage,
author: response.author,
});
} else {
setError("Blog post ID is missing.");
}
} catch (error: any) {
setError(error.message || "Failed to fetch blog post.");
} finally {
setLoading(false);
}
};
2025-05-15 10:48:03 +00:00
2025-06-19 21:42:16 +00:00
fetchBlogPost();
}, [id]);
if (loading) {
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<h1 className="text-2xl font-bold text-gray-900">Loading...</h1>
</div>
);
}
2025-05-15 10:48:03 +00:00
2025-06-19 21:42:16 +00:00
if (error) {
2025-05-15 10:48:03 +00:00
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
2025-06-19 21:42:16 +00:00
<h1 className="text-2xl font-bold text-gray-900">Error: {error}</h1>
</div>
);
}
if (!blogPost || !postData) {
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<h1 className="text-2xl font-bold text-gray-900">
{t("blog.notFound")}
</h1>
2025-05-15 10:48:03 +00:00
</div>
);
}
return (
2025-06-19 21:42:16 +00:00
<div className="min-h-screen bg-gray-50 pt-32 pb-16">
2025-05-15 10:48:03 +00:00
<div className="container mx-auto px-4">
2025-06-19 21:42:16 +00:00
<Link
to="/blog"
className="text-blue-600 hover:underline mb-4 inline-block"
>
&larr; {t("blog.backToBlog")}
2025-05-15 10:48:03 +00:00
</Link>
{postData.image && (
<img
2025-06-19 21:42:16 +00:00
src={postData.image}
alt={t(blogPost.title)}
2025-05-15 10:48:03 +00:00
className="w-full h-96 object-cover rounded-lg mb-8"
/>
)}
2025-06-19 21:42:16 +00:00
<h1 className="text-4xl font-bold text-gray-900 mb-6">
{t(blogPost.title)}
</h1>
2025-05-15 10:48:03 +00:00
<div className="flex items-center text-sm text-gray-500 space-x-4 mb-8">
<div className="flex items-center">
2025-06-19 21:42:16 +00:00
<span>{postData.author?.name}</span>
2025-05-15 10:48:03 +00:00
</div>
<div className="flex items-center">
2025-06-19 21:42:16 +00:00
{blogPost.publishedAt &&
format(new Date(blogPost.publishedAt), "dd MMM yyyy", {
locale: tr,
})}
2025-05-15 10:48:03 +00:00
</div>
</div>
2025-06-22 12:44:11 +00:00
<div className="prose max-w-none text-gray-800" dangerouslySetInnerHTML={{ __html: language == "tr" ? t(blogPost.contentTr!!) : t(blogPost.contentEn!!) }} />
2025-05-15 10:48:03 +00:00
</div>
</div>
);
};
export default BlogDetail;