diff --git a/.gitignore b/.gitignore index eee2a30..805424b 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ coverage/ # Misc *.tar.gz *.zip +.playwright-mcp/ diff --git a/frontend/app/article/[slug]/page.tsx b/frontend/app/article/[slug]/page.tsx index cac87cc..d4634f5 100644 --- a/frontend/app/article/[slug]/page.tsx +++ b/frontend/app/article/[slug]/page.tsx @@ -3,11 +3,12 @@ export const dynamic = "force-dynamic" import { notFound } from 'next/navigation' import Link from 'next/link' import Image from 'next/image' +import ShareButtons from '@/components/ShareButtons' async function getArticleWithTags(slug: string) { try { const { rows } = await sql` - SELECT + SELECT a.*, c.name as category_name, c.name_burmese as category_name_burmese, @@ -27,12 +28,9 @@ async function getArticleWithTags(slug: string) { WHERE a.slug = ${slug} AND a.status = 'published' GROUP BY a.id, c.id ` - if (rows.length === 0) return null - - // Increment view count + // Increment view count only here (not in generateMetadata) await sql`SELECT increment_view_count(${slug})` - return rows[0] } catch (error) { console.error('Error fetching article:', error) @@ -40,34 +38,46 @@ async function getArticleWithTags(slug: string) { } } +// Separate metadata fetch — no view count increment +async function getArticleMeta(slug: string) { + try { + const { rows } = await sql` + SELECT title_burmese, excerpt_burmese, featured_image + FROM articles + WHERE slug = ${slug} AND status = 'published' + LIMIT 1 + ` + return rows[0] || null + } catch { + return null + } +} + async function getRelatedArticles(articleId: number) { try { const { rows } = await sql`SELECT * FROM get_related_articles(${articleId}, 6)` return rows - } catch (error) { + } catch { return [] } } -export default async function ImprovedArticlePage({ params }: { params: { slug: string } }) { +export default async function ArticlePage({ params }: { params: { slug: string } }) { const article = await getArticleWithTags(params.slug) - - if (!article) { - notFound() - } - + if (!article) notFound() + const relatedArticles = await getRelatedArticles(article.id) const publishedDate = new Date(article.published_at).toLocaleDateString('my-MM', { year: 'numeric', month: 'long', - day: 'numeric' + day: 'numeric', }) return (
{/* Hero Cover Image */} {article.featured_image && ( -
+
{article.title_burmese} -
- +
+
-
- {/* Category */} +
{article.category_name_burmese} - - {/* Title */} -

+

{article.title_burmese}

- - {/* Meta */} -
+
{publishedDate} {article.reading_time} မိနစ် @@ -106,10 +111,10 @@ export default async function ImprovedArticlePage({ params }: { params: { slug: )} {/* Article Content */} -
+
{/* Tags */} {article.tags_burmese && article.tags_burmese.length > 0 && ( -
+
{article.tags_burmese.map((tag: string, idx: number) => ( )} - {/* Article Body */} + {/* Body */}
- - {/* Additional Images Gallery */} + + {/* Image Gallery */} {article.images && article.images.length > 1 && ( -
-

ဓာတ်ပုံများ

-
+
+

ဓာတ်ပုံများ

+
{article.images.slice(1).map((img: string, idx: number) => ( -
- {`${article.title_burmese} +
+ {`${article.title_burmese}
))}
)} - + {/* Videos */} {article.videos && article.videos.length > 0 && ( -
-

ဗီဒီယိုများ

+
+

ဗီဒီယိုများ

{article.videos.map((video: string, idx: number) => (
@@ -162,49 +162,36 @@ export default async function ImprovedArticlePage({ params }: { params: { slug: {/* Source Attribution */} {article.source_articles && article.source_articles.length > 0 && ( -
-

- +
+

+ မူရင်းသတင်းရင်းမြစ်များ

-

- ဤဆောင်းပါးကို အောက်ပါမူရင်းသတင်းများမှ စုစည်း၍ မြန်မာဘာသာသို့ ပြန်ဆိုထားခြင်း ဖြစ်ပါသည်။ အားလုံးသော အကြွေးအရ မူရင်းစာရေးသူများနှင့် ထုတ်ပြန်သူများကို သက်ဆိုင်ပါသည်။ +

+ ဤဆောင်းပါးကို အောက်ပါမူရင်းသတင်းများမှ စုစည်း၍ မြန်မာဘာသာသို့ ပြန်ဆိုထားသည်။

-
+
{article.source_articles.map((source: any, index: number) => ( -
-
- - {index + 1} - -
- - {source.title} - - {source.author && source.author !== 'Unknown' && ( -

- စာရေးသူ: {source.author} -

- )} -
+
+ + {index + 1} + +
- - - + {source.title} + {source.author && source.author !== 'Unknown' && ( +

+ စာရေးသူ: {source.author} +

+ )}
))} @@ -212,58 +199,39 @@ export default async function ImprovedArticlePage({ params }: { params: { slug:
)} - {/* Share Section */} -
-
-

မျှဝေပါ:

-
- - - -
-
+ {/* Share */} +
+

မျှဝေပါ:

+

{/* Related Articles */} {relatedArticles.length > 0 && ( -
-

- ဆက်စပ်ဆောင်းပါးများ -

-
- {relatedArticles.map((related: any) => ( - - {related.featured_image && ( -
- {related.title_burmese} +
+
+

+ ဆက်စပ်ဆောင်းပါးများ +

+
+ {relatedArticles.map((related: any) => ( + + {related.featured_image && ( +
+ {related.title_burmese} +
+ )} +
+

+ {related.title_burmese} +

+

+ {related.excerpt_burmese} +

- )} -
-

- {related.title_burmese} -

-

- {related.excerpt_burmese} -

-
- - ))} + + ))} +
)} @@ -272,30 +240,30 @@ export default async function ImprovedArticlePage({ params }: { params: { slug: } function formatContent(content: string): string { - let formatted = content - .replace(/\n\n/g, '

') - .replace(/## (.*?)\n/g, '

$1

') - .replace(/### (.*?)\n/g, '

$1

') + const formatted = content + .replace(/### (.*?)(\n|$)/g, '

$1

') + .replace(/## (.*?)(\n|$)/g, '

$1

') + .replace(/# (.*?)(\n|$)/g, '

$1

') .replace(/\*\*(.*?)\*\*/g, '$1') .replace(/\*(.*?)\*/g, '$1') - + .replace(/\n\n+/g, '

') + .replace(/\n/g, '
') return `

${formatted}

` } function renderVideo(videoUrl: string) { - let videoId = null - + let videoId: string | null = null if (videoUrl.includes('youtube.com/watch')) { - const match = videoUrl.match(/v=([^&]+)/) - videoId = match ? match[1] : null + const m = videoUrl.match(/v=([^&]+)/) + videoId = m ? m[1] : null } else if (videoUrl.includes('youtu.be/')) { - const match = videoUrl.match(/youtu\.be\/([^?]+)/) - videoId = match ? match[1] : null + const m = videoUrl.match(/youtu\.be\/([^?]+)/) + videoId = m ? m[1] : null } else if (videoUrl.includes('youtube.com/embed/')) { - const match = videoUrl.match(/embed\/([^?]+)/) - videoId = match ? match[1] : null + const m = videoUrl.match(/embed\/([^?]+)/) + videoId = m ? m[1] : null } - + if (videoId) { return (