live blog implemented

This commit is contained in:
dimitar committed 2026-01-29 04:01:55 +01:00
1 parent e8893c1aae
commit 0351726eeb
36 files changed
+7759 -253

No files matched your search

@@ -0,0 +1,97 @@
import { useQuery } from '@tanstack/react-query'
import { Link } from '@tanstack/react-router'
import * as api from '@/lib/api'
export function ArticleDetailComponent({ id }: { id: string }) {
const { data, isLoading, error } = useQuery({
queryKey: ['article', id],
queryFn: () => api.fetchArticleById(id),
})
if (isLoading) {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="text-lg">Loading article...</div>
</div>
)
}
if (error) {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="text-lg text-red-500">Error loading article</div>
</div>
)
}
if (!data) {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="text-lg">Article not found</div>
</div>
)
}
return (
<article className="max-w-3xl mx-auto">
<Link
to="/articles"
className="inline-flex items-center gap-2 text-muted-foreground hover:text-foreground mb-8"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="m15 18-6-6 6-6" />
<path d="M19 6H5" />
</svg>
Back to articles
</Link>
<h1 className="text-4xl font-bold mb-6">{data.title}</h1>
<div className="flex items-center gap-4 text-sm text-muted-foreground mb-8">
<span>
{new Date(data.createdAt).toLocaleDateString('mk-MK', {
day: 'numeric',
month: 'long',
year: 'numeric',
})}
</span>
<span>•</span>
<span>{data.views} views</span>
{data.author && (
<>
<span>•</span>
<span>By {data.author.name}</span>
</>
)}
</div>
{data.featuredImage && (
<img
src={data.featuredImage}
alt={data.title}
className="w-full h-64 md:h-96 object-cover rounded-xl mb-8"
/>
)}
<div className="prose prose-slate max-w-none">
<p className="text-lg leading-relaxed mb-6">{data.content}</p>
</div>
{data.tags && Array.isArray(data.tags) && data.tags.length > 0 && (
<div className="mt-8 pt-8 border-t">
<h3 className="text-sm font-semibold mb-4 text-muted-foreground">Tags</h3>
<div className="flex flex-wrap gap-2">
{data.tags.map((tag) => (
<span
key={tag}
className="px-3 py-1 text-sm rounded-full bg-secondary text-secondary-foreground"
>
{tag}
</span>
))}
</div>
</div>
)}
</article>
)
}