forked from UKSOURCE/hailearning.edu.vn
feat: Implement blog API service and refactor components for improved data fetching
This commit is contained in:
@@ -9,19 +9,25 @@ interface NewsDetailsContentProps {
|
||||
}
|
||||
|
||||
export default function NewsDetailsContent({ post }: NewsDetailsContentProps) {
|
||||
// Get comments from post (already included in API response)
|
||||
// Lấy comments từ post (đã được bao gồm trong API response)
|
||||
const postComments = post.comments || [];
|
||||
|
||||
// Get base URL for EditorJS images
|
||||
// Lấy base URL cho EditorJS images
|
||||
const baseUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:3001";
|
||||
|
||||
// Convert EditorJS content to HTML
|
||||
// URL tuyệt đối của bài viết để share lên mạng xã hội
|
||||
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || "http://localhost:3000";
|
||||
const postUrl = `${siteUrl}/blog/${post.slug}`;
|
||||
const encodedPostUrl = encodeURIComponent(postUrl);
|
||||
const encodedTitle = encodeURIComponent(post.title);
|
||||
|
||||
// Chuyển đổi EditorJS content sang HTML
|
||||
const renderContent = () => {
|
||||
const html = editorjsToHtml(post.content, baseUrl);
|
||||
return { __html: html };
|
||||
};
|
||||
|
||||
// Convert EditorJS contentAfterQuote to HTML
|
||||
// Chuyển đổi EditorJS contentAfterQuote sang HTML
|
||||
const renderContentAfterQuote = () => {
|
||||
const html = editorjsToHtml(post.contentAfterQuote, baseUrl);
|
||||
return { __html: html };
|
||||
@@ -49,13 +55,13 @@ export default function NewsDetailsContent({ post }: NewsDetailsContentProps) {
|
||||
</li>
|
||||
</ul>
|
||||
<h2>{post.title}</h2>
|
||||
<div dangerouslySetInnerHTML={renderContent()} />
|
||||
<div className="editorjs-render" dangerouslySetInnerHTML={renderContent()} />
|
||||
|
||||
{/* Gallery Images */}
|
||||
{/* Hình ảnh gallery */}
|
||||
{post.galleryImages && post.galleryImages.length > 0 && (
|
||||
<div className="row g-4 mt-4">
|
||||
<div className="row g-4 gallery-images-row">
|
||||
{post.galleryImages.map((image, index) => (
|
||||
<div key={index} className={post.galleryImages!.length === 1 ? "col-12" : "col-lg-6"}>
|
||||
<div key={index} className={post.galleryImages!.length === 1 ? "col-12" : "col-lg-6 gallery-item"}>
|
||||
<div className="thumb">
|
||||
<img src={getCmsImageUrl(image)} alt={`${post.title} - Image ${index + 1}`} />
|
||||
</div>
|
||||
@@ -71,18 +77,21 @@ export default function NewsDetailsContent({ post }: NewsDetailsContentProps) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Content After Quote */}
|
||||
{/* Nội dung sau Quote */}
|
||||
{post.contentAfterQuote && (
|
||||
<div dangerouslySetInnerHTML={renderContentAfterQuote()} />
|
||||
<div
|
||||
className="editorjs-render"
|
||||
dangerouslySetInnerHTML={renderContentAfterQuote()}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Tags and Social Share */}
|
||||
{/* Tags và Social Share */}
|
||||
<div className="row tag-share-wrap mt-4 mb-5">
|
||||
<div className="col-lg-8 col-12">
|
||||
<div className="tagcloud">
|
||||
<span>Tags:</span>
|
||||
{post.tags.map((tagName) => {
|
||||
// Generate slug from tag name (Vietnamese-friendly)
|
||||
// Tạo slug từ tên tag (hỗ trợ tiếng Việt)
|
||||
const tagSlug = toSlug(tagName);
|
||||
return (
|
||||
<Link key={tagName} href={`/blog/tag/${tagSlug}`}>
|
||||
@@ -94,17 +103,37 @@ export default function NewsDetailsContent({ post }: NewsDetailsContentProps) {
|
||||
</div>
|
||||
<div className="col-lg-4 col-12 mt-3 mt-lg-0 text-lg-end">
|
||||
<div className="social-share">
|
||||
<a href="#" aria-label="Share on Twitter">
|
||||
<a
|
||||
href={`https://twitter.com/intent/tweet?url=${encodedPostUrl}&text=${encodedTitle}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label="Share on Twitter"
|
||||
>
|
||||
<i className="fab fa-twitter"></i>
|
||||
</a>
|
||||
<a href="#" aria-label="Share on YouTube">
|
||||
<i className="fa-brands fa-youtube"></i>
|
||||
<a
|
||||
href={`https://www.facebook.com/sharer/sharer.php?u=${encodedPostUrl}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label="Share on Facebook"
|
||||
>
|
||||
<i className="fab fa-facebook-f"></i>
|
||||
</a>
|
||||
<a href="#" aria-label="Share on LinkedIn">
|
||||
<a
|
||||
href={`https://www.linkedin.com/sharing/share-offsite/?url=${encodedPostUrl}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label="Share on LinkedIn"
|
||||
>
|
||||
<i className="fab fa-linkedin-in"></i>
|
||||
</a>
|
||||
<a href="#" aria-label="Share on Facebook">
|
||||
<i className="fab fa-facebook-f"></i>
|
||||
<a
|
||||
href={postUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label="Open blog post"
|
||||
>
|
||||
<i className="fa-solid fa-link"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user