UI/UX Improvements: Modern design + hashtag system + cover images

- Added modern CSS design system with better typography
- Created hashtag/tag functionality with auto-tagging
- Improved homepage with hero section and trending tags
- Enhanced article pages with full-width cover images
- Added tag pages for filtering articles by hashtag
- Better mobile responsive design
- Smoother animations and transitions
- Auto-tag system analyzes content and assigns relevant tags
- 30+ predefined AI-related tags (ChatGPT, OpenAI, etc.)
This commit is contained in:
Zeya Phyo
2026-02-19 13:49:45 +00:00
parent afa8fb8d78
commit 161dce1501
8 changed files with 1616 additions and 0 deletions

View File

@@ -0,0 +1,336 @@
import { sql } from '@vercel/postgres'
import { notFound } from 'next/navigation'
import Link from 'next/link'
import Image from 'next/image'
async function getArticleWithTags(slug: string) {
try {
const { rows } = await sql`
SELECT
a.*,
c.name as category_name,
c.name_burmese as category_name_burmese,
c.slug as category_slug,
COALESCE(
array_agg(t.name_burmese) FILTER (WHERE t.id IS NOT NULL),
ARRAY[]::VARCHAR[]
) as tags_burmese,
COALESCE(
array_agg(t.slug) FILTER (WHERE t.id IS NOT NULL),
ARRAY[]::VARCHAR[]
) as tag_slugs
FROM articles a
JOIN categories c ON a.category_id = c.id
LEFT JOIN article_tags at ON a.id = at.article_id
LEFT JOIN tags t ON at.tag_id = t.id
WHERE a.slug = ${slug} AND a.status = 'published'
GROUP BY a.id, c.id
`
if (rows.length === 0) return null
// Increment view count
await sql`SELECT increment_view_count(${slug})`
return rows[0]
} catch (error) {
console.error('Error fetching article:', error)
return null
}
}
async function getRelatedArticles(articleId: number) {
try {
const { rows } = await sql`SELECT * FROM get_related_articles(${articleId}, 6)`
return rows
} catch (error) {
return []
}
}
export default async function ImprovedArticlePage({ params }: { params: { slug: string } }) {
const article = await getArticleWithTags(params.slug)
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'
})
return (
<div className="min-h-screen bg-white">
{/* Hero Cover Image */}
{article.featured_image && (
<div className="relative h-[70vh] w-full overflow-hidden">
<Image
src={article.featured_image}
alt={article.title_burmese}
fill
className="object-cover"
priority
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent" />
<div className="absolute inset-0 flex items-end">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 pb-16 w-full">
{/* Category */}
<Link
href={`/category/${article.category_slug}`}
className="inline-block mb-4 px-4 py-2 bg-primary rounded-full text-white font-semibold text-sm hover:bg-primary-dark transition-colors"
>
{article.category_name_burmese}
</Link>
{/* Title */}
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6 font-burmese leading-tight">
{article.title_burmese}
</h1>
{/* Meta */}
<div className="flex flex-wrap items-center gap-4 text-white/90">
<span className="font-burmese">{publishedDate}</span>
<span></span>
<span className="font-burmese">{article.reading_time} </span>
<span></span>
<span>{article.view_count} views</span>
</div>
</div>
</div>
</div>
)}
{/* Article Content */}
<article className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
{/* Tags */}
{article.tags_burmese && article.tags_burmese.length > 0 && (
<div className="flex flex-wrap gap-2 mb-8 pb-8 border-b">
{article.tags_burmese.map((tag: string, idx: number) => (
<Link
key={idx}
href={`/tag/${article.tag_slugs[idx]}`}
className="tag tag-burmese"
>
#{tag}
</Link>
))}
</div>
)}
{/* Article Body */}
<div className="article-content">
<div dangerouslySetInnerHTML={{ __html: formatContent(article.content_burmese) }} />
{/* Additional Images Gallery */}
{article.images && article.images.length > 1 && (
<div className="my-12">
<h3 className="text-2xl font-bold mb-6 font-burmese"></h3>
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
{article.images.slice(1).map((img: string, idx: number) => (
<div key={idx} className="relative h-56 rounded-xl overflow-hidden image-zoom">
<Image
src={img}
alt={`${article.title_burmese} - ${idx + 2}`}
fill
className="object-cover"
/>
</div>
))}
</div>
</div>
)}
{/* Videos */}
{article.videos && article.videos.length > 0 && (
<div className="my-12">
<h3 className="text-2xl font-bold mb-6 font-burmese"></h3>
<div className="space-y-6">
{article.videos.map((video: string, idx: number) => (
<div key={idx} className="relative aspect-video rounded-xl overflow-hidden bg-gray-900 shadow-xl">
{renderVideo(video)}
</div>
))}
</div>
</div>
)}
</div>
{/* Source Attribution */}
{article.source_articles && article.source_articles.length > 0 && (
<div className="mt-16 p-8 bg-gradient-to-br from-blue-50 to-indigo-50 rounded-2xl shadow-lg">
<h3 className="text-2xl font-bold text-gray-900 mb-4 font-burmese flex items-center">
<svg className="w-7 h-7 mr-3 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</h3>
<p className="text-sm text-gray-700 mb-6 font-burmese leading-relaxed">
က က က က က
</p>
<div className="space-y-4">
{article.source_articles.map((source: any, index: number) => (
<div key={index} className="bg-white p-5 rounded-xl shadow-sm hover:shadow-md transition-shadow border border-gray-100">
<div className="flex items-start gap-4">
<span className="flex-shrink-0 w-8 h-8 bg-primary text-white rounded-full flex items-center justify-center text-sm font-bold">
{index + 1}
</span>
<div className="flex-1 min-w-0">
<a
href={source.url}
target="_blank"
rel="noopener noreferrer"
className="text-primary hover:text-primary-dark font-medium break-words hover:underline"
>
{source.title}
</a>
{source.author && source.author !== 'Unknown' && (
<p className="text-sm text-gray-600 mt-2">
<span className="font-burmese font-semibold">:</span> {source.author}
</p>
)}
</div>
<a
href={source.url}
target="_blank"
rel="noopener noreferrer"
className="flex-shrink-0 text-primary hover:text-primary-dark"
title="Open source"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
</a>
</div>
</div>
))}
</div>
</div>
)}
{/* Share Section */}
<div className="mt-12 py-8 border-y border-gray-200">
<div className="flex items-center justify-between">
<p className="font-burmese text-gray-700 font-semibold">:</p>
<div className="flex gap-3">
<button className="px-4 py-2 bg-blue-600 text-white rounded-full hover:bg-blue-700 transition-colors">
Facebook
</button>
<button className="px-4 py-2 bg-sky-500 text-white rounded-full hover:bg-sky-600 transition-colors">
Twitter
</button>
<button className="px-4 py-2 bg-green-600 text-white rounded-full hover:bg-green-700 transition-colors">
WhatsApp
</button>
</div>
</div>
</div>
</article>
{/* Related Articles */}
{relatedArticles.length > 0 && (
<section className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16 bg-gray-50">
<h2 className="text-3xl font-bold text-gray-900 mb-10 font-burmese">
က
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{relatedArticles.map((related: any) => (
<Link
key={related.id}
href={`/article/${related.slug}`}
className="card card-hover"
>
{related.featured_image && (
<div className="relative h-48 w-full image-zoom">
<Image
src={related.featured_image}
alt={related.title_burmese}
fill
className="object-cover"
/>
</div>
)}
<div className="p-6">
<h3 className="font-bold text-gray-900 font-burmese line-clamp-2 hover:text-primary transition-colors text-lg mb-3">
{related.title_burmese}
</h3>
<p className="text-sm text-gray-600 font-burmese line-clamp-2">
{related.excerpt_burmese}
</p>
</div>
</Link>
))}
</div>
</section>
)}
</div>
)
}
function formatContent(content: string): string {
let formatted = content
.replace(/\n\n/g, '</p><p>')
.replace(/## (.*?)\n/g, '<h2>$1</h2>')
.replace(/### (.*?)\n/g, '<h3>$1</h3>')
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.*?)\*/g, '<em>$1</em>')
return `<p>${formatted}</p>`
}
function renderVideo(videoUrl: string) {
let videoId = null
if (videoUrl.includes('youtube.com/watch')) {
const match = videoUrl.match(/v=([^&]+)/)
videoId = match ? match[1] : null
} else if (videoUrl.includes('youtu.be/')) {
const match = videoUrl.match(/youtu\.be\/([^?]+)/)
videoId = match ? match[1] : null
} else if (videoUrl.includes('youtube.com/embed/')) {
const match = videoUrl.match(/embed\/([^?]+)/)
videoId = match ? match[1] : null
}
if (videoId) {
return (
<iframe
src={`https://www.youtube.com/embed/${videoId}`}
className="w-full h-full"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
/>
)
}
return (
<iframe
src={videoUrl}
className="w-full h-full"
allowFullScreen
/>
)
}
export async function generateMetadata({ params }: { params: { slug: string } }) {
const article = await getArticleWithTags(params.slug)
if (!article) {
return {
title: 'Article Not Found',
}
}
return {
title: `${article.title_burmese} - Burmddit`,
description: article.excerpt_burmese,
openGraph: {
title: article.title_burmese,
description: article.excerpt_burmese,
images: article.featured_image ? [article.featured_image] : [],
},
}
}

View File

@@ -0,0 +1,267 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
/* Modern Design System for Burmddit */
@layer base {
:root {
--primary: #2563eb;
--primary-dark: #1e40af;
--accent: #f59e0b;
--text: #1f2937;
--text-light: #6b7280;
--bg: #ffffff;
--bg-secondary: #f9fafb;
--border: #e5e7eb;
}
* {
@apply border-border;
}
body {
@apply bg-bg-secondary text-text antialiased;
font-feature-settings: "cv11", "ss01";
}
}
/* Burmese Fonts - Better rendering */
@font-face {
font-family: 'Pyidaungsu';
src: url('https://myanmar-tools-website.appspot.com/fonts/Pyidaungsu-2.5.3_Regular.ttf') format('truetype');
font-weight: 400;
font-display: swap;
font-feature-settings: "liga" 1;
}
@font-face {
font-family: 'Pyidaungsu';
src: url('https://myanmar-tools-website.appspot.com/fonts/Pyidaungsu-2.5.3_Bold.ttf') format('truetype');
font-weight: 700;
font-display: swap;
}
.font-burmese {
font-family: 'Pyidaungsu', 'Noto Sans Myanmar', 'Myanmar Text', sans-serif;
letter-spacing: 0.01em;
}
/* Modern Card Design */
.card {
@apply bg-white rounded-xl shadow-sm hover:shadow-xl transition-all duration-300 overflow-hidden;
@apply border border-gray-100;
}
.card-hover {
@apply transform hover:-translate-y-1 hover:scale-[1.02];
}
/* Cover Image with Overlay */
.cover-image-container {
@apply relative overflow-hidden;
}
.cover-image-overlay {
@apply absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent;
}
.cover-image-text {
@apply absolute bottom-0 left-0 right-0 p-6 text-white;
}
/* Tag/Hashtag Design */
.tag {
@apply inline-flex items-center px-3 py-1 rounded-full text-xs font-medium;
@apply bg-primary/10 text-primary hover:bg-primary hover:text-white;
@apply transition-all duration-200 cursor-pointer;
}
.tag-burmese {
@apply font-burmese text-sm;
}
/* Article Content - Better Typography */
.article-content {
@apply font-burmese text-gray-800 leading-loose;
font-size: 1.125rem;
line-height: 1.9;
}
.article-content h1 {
@apply text-4xl font-bold mt-10 mb-6 text-gray-900;
@apply font-burmese leading-tight;
}
.article-content h2 {
@apply text-3xl font-bold mt-8 mb-5 text-gray-900;
@apply font-burmese leading-snug;
}
.article-content h3 {
@apply text-2xl font-semibold mt-6 mb-4 text-gray-800;
@apply font-burmese;
}
.article-content p {
@apply mb-6 text-lg leading-loose text-gray-700;
}
.article-content a {
@apply text-primary hover:text-primary-dark underline decoration-2 underline-offset-2;
@apply transition-colors duration-200;
}
.article-content ul, .article-content ol {
@apply ml-6 mb-6 space-y-3;
}
.article-content li {
@apply text-lg text-gray-700 leading-relaxed;
@apply pl-2;
}
.article-content ul li {
@apply list-disc;
}
.article-content ol li {
@apply list-decimal;
}
.article-content code {
@apply bg-gray-100 px-2 py-1 rounded text-sm font-mono text-gray-800;
@apply border border-gray-200;
}
.article-content pre {
@apply bg-gray-900 text-gray-100 p-5 rounded-xl overflow-x-auto mb-6;
@apply shadow-lg;
}
.article-content blockquote {
@apply border-l-4 border-primary pl-6 italic my-6 text-gray-700;
@apply bg-primary/5 py-4 rounded-r-lg;
}
/* Hero Section */
.hero-gradient {
background: linear-gradient(135deg, #2563eb 0%, #7c3aed 100%);
}
/* Glassmorphism Effect */
.glass {
@apply bg-white/80 backdrop-blur-lg border border-white/20;
}
/* Image Zoom on Hover */
.image-zoom {
@apply overflow-hidden;
}
.image-zoom img {
@apply transition-transform duration-500 ease-out;
}
.image-zoom:hover img {
@apply scale-110;
}
/* Loading Skeleton */
.skeleton {
@apply animate-pulse bg-gradient-to-r from-gray-200 via-gray-300 to-gray-200;
@apply bg-[length:200%_100%];
animation: shimmer 1.5s infinite;
}
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
/* Smooth Page Transitions */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.fade-in {
animation: fadeIn 0.4s ease-out;
}
/* Badge Design */
.badge {
@apply inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold;
@apply shadow-sm;
}
.badge-primary {
@apply bg-primary text-white;
}
.badge-accent {
@apply bg-accent text-white;
}
/* Hover Effects */
.hover-lift {
@apply transition-all duration-300;
}
.hover-lift:hover {
@apply transform -translate-y-2 shadow-2xl;
}
/* Focus Styles */
*:focus-visible {
@apply outline-none ring-2 ring-primary ring-offset-2 rounded;
}
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-track {
@apply bg-gray-100;
}
::-webkit-scrollbar-thumb {
@apply bg-gray-400 rounded-full;
}
::-webkit-scrollbar-thumb:hover {
@apply bg-gray-500;
}
/* Mobile Optimizations */
@media (max-width: 640px) {
.article-content {
font-size: 1rem;
line-height: 1.8;
}
.article-content h1 {
@apply text-3xl;
}
.article-content h2 {
@apply text-2xl;
}
.article-content h3 {
@apply text-xl;
}
}
/* Print Styles */
@media print {
.no-print {
display: none !important;
}
.article-content {
@apply text-black;
}
}

View File

@@ -0,0 +1,235 @@
import { sql } from '@vercel/postgres'
import Image from 'next/image'
import Link from 'next/link'
async function getArticlesWithTags() {
try {
const { rows } = await sql`
SELECT * FROM articles_with_tags
ORDER BY published_at DESC
LIMIT 20
`
return rows
} catch (error) {
console.error('Error fetching articles:', error)
return []
}
}
async function getFeaturedArticle() {
try {
const { rows } = await sql`
SELECT * FROM articles_with_tags
ORDER BY view_count DESC
LIMIT 1
`
return rows[0] || null
} catch (error) {
return null
}
}
async function getTrendingTags() {
try {
const { rows } = await sql`
SELECT t.name_burmese, t.slug, COUNT(at.article_id) as count
FROM tags t
JOIN article_tags at ON t.id = at.tag_id
JOIN articles a ON at.article_id = a.id
WHERE a.status = 'published'
GROUP BY t.id
ORDER BY count DESC
LIMIT 15
`
return rows
} catch (error) {
return []
}
}
export default async function ImprovedHome() {
const [articles, featured, trendingTags] = await Promise.all([
getArticlesWithTags(),
getFeaturedArticle(),
getTrendingTags()
])
return (
<div className="min-h-screen bg-gradient-to-b from-gray-50 to-white">
{/* Hero Section with Featured Article */}
{featured && (
<section className="relative h-[600px] w-full overflow-hidden fade-in">
<Image
src={featured.featured_image || '/placeholder.jpg'}
alt={featured.title_burmese}
fill
className="object-cover"
priority
/>
<div className="absolute inset-0 bg-gradient-to-t from-black via-black/60 to-transparent" />
<div className="absolute inset-0 flex items-end">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-16 w-full">
<div className="max-w-3xl">
{/* Category Badge */}
<Link
href={`/category/${featured.category_slug}`}
className="inline-block mb-4 px-4 py-2 bg-primary rounded-full text-white font-semibold text-sm hover:bg-primary-dark transition-colors"
>
{featured.category_name_burmese}
</Link>
{/* Title */}
<h1 className="text-5xl md:text-6xl font-bold text-white mb-4 font-burmese leading-tight">
<Link href={`/article/${featured.slug}`} className="hover:text-gray-200 transition-colors">
{featured.title_burmese}
</Link>
</h1>
{/* Excerpt */}
<p className="text-xl text-gray-200 mb-6 font-burmese line-clamp-2">
{featured.excerpt_burmese}
</p>
{/* Tags */}
{featured.tags_burmese && featured.tags_burmese.length > 0 && (
<div className="flex flex-wrap gap-2 mb-6">
{featured.tags_burmese.slice(0, 5).map((tag: string, idx: number) => (
<Link
key={idx}
href={`/tag/${featured.tag_slugs[idx]}`}
className="px-3 py-1 bg-white/20 backdrop-blur-sm text-white rounded-full text-sm hover:bg-white/30 transition-colors"
>
#{tag}
</Link>
))}
</div>
)}
{/* Read More Button */}
<Link
href={`/article/${featured.slug}`}
className="inline-flex items-center px-8 py-4 bg-white text-gray-900 rounded-full font-semibold hover:bg-gray-100 transition-all hover:shadow-xl font-burmese"
>
</Link>
</div>
</div>
</div>
</section>
)}
{/* Main Content */}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
{/* Trending Tags */}
{trendingTags.length > 0 && (
<section className="mb-12 fade-in">
<h2 className="text-2xl font-bold text-gray-900 mb-6 font-burmese flex items-center">
🔥 ကက က
</h2>
<div className="flex flex-wrap gap-3">
{trendingTags.map((tag: any) => (
<Link
key={tag.slug}
href={`/tag/${tag.slug}`}
className="tag tag-burmese"
>
#{tag.name_burmese}
<span className="ml-2 text-xs opacity-60">({tag.count})</span>
</Link>
))}
</div>
</section>
)}
{/* Article Grid */}
<section className="fade-in">
<h2 className="text-3xl font-bold text-gray-900 mb-8 font-burmese">
က
</h2>
{articles.length === 0 ? (
<div className="text-center py-20 bg-white rounded-2xl shadow-sm">
<div className="text-6xl mb-4">📰</div>
<p className="text-xl text-gray-500 font-burmese">
က က
</p>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{articles.map((article: any) => (
<article key={article.id} className="card card-hover fade-in">
{/* Cover Image */}
{article.featured_image && (
<Link href={`/article/${article.slug}`} className="block image-zoom">
<div className="relative h-56 w-full">
<Image
src={article.featured_image}
alt={article.title_burmese}
fill
className="object-cover"
/>
</div>
</Link>
)}
<div className="p-6">
{/* Category Badge */}
<Link
href={`/category/${article.category_slug}`}
className="inline-block mb-3 px-3 py-1 bg-primary/10 text-primary rounded-full text-xs font-semibold hover:bg-primary hover:text-white transition-all"
>
{article.category_name_burmese}
</Link>
{/* Title */}
<h3 className="text-xl font-bold text-gray-900 mb-3 font-burmese line-clamp-2 hover:text-primary transition-colors">
<Link href={`/article/${article.slug}`}>
{article.title_burmese}
</Link>
</h3>
{/* Excerpt */}
<p className="text-gray-600 mb-4 font-burmese line-clamp-3 text-sm leading-relaxed">
{article.excerpt_burmese}
</p>
{/* Tags */}
{article.tags_burmese && article.tags_burmese.length > 0 && (
<div className="flex flex-wrap gap-2 mb-4">
{article.tags_burmese.slice(0, 3).map((tag: string, idx: number) => (
<Link
key={idx}
href={`/tag/${article.tag_slugs[idx]}`}
className="text-xs px-2 py-1 bg-gray-100 text-gray-700 rounded hover:bg-gray-200 transition-colors"
>
#{tag}
</Link>
))}
</div>
)}
{/* Meta */}
<div className="flex items-center justify-between text-sm text-gray-500 pt-4 border-t border-gray-100">
<span className="font-burmese">{article.reading_time} </span>
<span>{article.view_count} views</span>
</div>
</div>
</article>
))}
</div>
)}
</section>
{/* Load More Button */}
{articles.length >= 20 && (
<div className="text-center mt-12">
<button className="px-8 py-4 bg-primary text-white rounded-full font-semibold hover:bg-primary-dark transition-all hover:shadow-xl font-burmese">
က
</button>
</div>
)}
</div>
</div>
)
}

View File

@@ -0,0 +1,133 @@
import { sql } from '@vercel/postgres'
import { notFound } from 'next/navigation'
import Link from 'next/link'
import Image from 'next/image'
async function getTag(slug: string) {
try {
const { rows } = await sql`
SELECT * FROM tags WHERE slug = ${slug}
`
return rows[0] || null
} catch (error) {
return null
}
}
async function getArticlesByTag(tagSlug: string) {
try {
const { rows } = await sql`
SELECT DISTINCT a.*, c.name_burmese as category_name_burmese, c.slug as category_slug
FROM articles a
JOIN categories c ON a.category_id = c.id
JOIN article_tags at ON a.id = at.article_id
JOIN tags t ON at.tag_id = t.id
WHERE t.slug = ${tagSlug} AND a.status = 'published'
ORDER BY a.published_at DESC
LIMIT 50
`
return rows
} catch (error) {
return []
}
}
export default async function TagPage({ params }: { params: { slug: string } }) {
const [tag, articles] = await Promise.all([
getTag(params.slug),
getArticlesByTag(params.slug)
])
if (!tag) {
notFound()
}
return (
<div className="min-h-screen bg-gray-50">
{/* Header */}
<div className="bg-gradient-to-r from-primary to-indigo-600 text-white py-16">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-center gap-3 mb-4">
<span className="text-5xl">#</span>
<h1 className="text-5xl font-bold font-burmese">
{tag.name_burmese}
</h1>
</div>
<p className="text-xl text-white/90">
{articles.length}
</p>
</div>
</div>
{/* Articles */}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
{articles.length === 0 ? (
<div className="text-center py-20 bg-white rounded-2xl shadow-sm">
<div className="text-6xl mb-4">🏷</div>
<p className="text-xl text-gray-500 font-burmese">
tag က
</p>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{articles.map((article: any) => (
<article key={article.id} className="card card-hover">
{article.featured_image && (
<Link href={`/article/${article.slug}`} className="block image-zoom">
<div className="relative h-56 w-full">
<Image
src={article.featured_image}
alt={article.title_burmese}
fill
className="object-cover"
/>
</div>
</Link>
)}
<div className="p-6">
<Link
href={`/category/${article.category_slug}`}
className="inline-block mb-3 px-3 py-1 bg-primary/10 text-primary rounded-full text-xs font-semibold"
>
{article.category_name_burmese}
</Link>
<h3 className="text-xl font-bold text-gray-900 mb-3 font-burmese line-clamp-2 hover:text-primary transition-colors">
<Link href={`/article/${article.slug}`}>
{article.title_burmese}
</Link>
</h3>
<p className="text-gray-600 mb-4 font-burmese line-clamp-3 text-sm">
{article.excerpt_burmese}
</p>
<div className="flex items-center justify-between text-sm text-gray-500 pt-4 border-t">
<span className="font-burmese">{article.reading_time} </span>
<span>{article.view_count} views</span>
</div>
</div>
</article>
))}
</div>
)}
</div>
</div>
)
}
export async function generateMetadata({ params }: { params: { slug: string } }) {
const tag = await getTag(params.slug)
if (!tag) {
return {
title: 'Tag Not Found',
}
}
return {
title: `#${tag.name_burmese} - Burmddit`,
description: `${tag.name_burmese} အကြောင်းအရာဖြင့် ဆောင်းပါးများ`,
}
}