Posts engine (SQLite + auto-publisher via poller), public feed with clickable tags, reader, admin panel, submit/search/queue tools. BFF proxy to pipeline API. Clean dark design. Docker-ready.
74 lines
2.6 KiB
TypeScript
74 lines
2.6 KiB
TypeScript
import Link from "next/link"
|
|
import type { Post } from "@/lib/db"
|
|
import { formatDate } from "@/lib/utils"
|
|
import { TagBadge } from "@/components/tag-badge"
|
|
|
|
export function PostCard({ post, compact = false }: { post: Post; compact?: boolean }) {
|
|
if (compact) {
|
|
return (
|
|
<Link
|
|
href={`/p/${post.slug}`}
|
|
className="card card-hover group flex gap-4 overflow-hidden p-0"
|
|
>
|
|
<img
|
|
src={`/api/cover/${post.gid}`}
|
|
alt={post.title}
|
|
className="h-32 w-24 flex-shrink-0 object-cover"
|
|
loading="lazy"
|
|
/>
|
|
<div className="flex flex-1 flex-col gap-1.5 py-3 pr-4">
|
|
<h3 className="line-clamp-2 text-sm font-semibold leading-snug group-hover:text-[var(--accent)] transition-colors">
|
|
{post.title}
|
|
</h3>
|
|
{post.artist && (
|
|
<p className="text-xs text-[var(--muted)]">{post.artist}</p>
|
|
)}
|
|
<div className="flex flex-1 items-end gap-2">
|
|
{post.source && (
|
|
<span className="text-[10px] uppercase text-[var(--muted)]">{post.source}</span>
|
|
)}
|
|
{post.published_at && (
|
|
<span className="text-[10px] text-[var(--muted)]">{formatDate(post.published_at)}</span>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</Link>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<Link
|
|
href={`/p/${post.slug}`}
|
|
className="card card-hover group flex flex-col overflow-hidden p-0"
|
|
>
|
|
<div className="aspect-[3/4] overflow-hidden bg-[var(--surface)]">
|
|
<img
|
|
src={`/api/cover/${post.gid}`}
|
|
alt={post.title}
|
|
className="h-full w-full object-cover transition-transform duration-300 group-hover:scale-[1.03]"
|
|
loading="lazy"
|
|
/>
|
|
</div>
|
|
<div className="flex flex-1 flex-col gap-2 p-3">
|
|
<h3 className="line-clamp-2 text-sm font-semibold leading-snug group-hover:text-[var(--accent)] transition-colors">
|
|
{post.title}
|
|
</h3>
|
|
{post.artist && (
|
|
<p className="text-xs text-[var(--muted)]">{post.artist}</p>
|
|
)}
|
|
{post.tags && post.tags.length > 0 && (
|
|
<div className="flex flex-wrap gap-1">
|
|
{post.tags.slice(0, 3).map((tag) => (
|
|
<TagBadge key={tag} tag={tag} href={`/tag/${encodeURIComponent(tag)}`} />
|
|
))}
|
|
</div>
|
|
)}
|
|
<div className="mt-auto flex items-center gap-2 text-[10px] text-[var(--muted)]">
|
|
{post.num_pages > 0 && <span>{post.num_pages} pág</span>}
|
|
{post.published_at && <span>{formatDate(post.published_at)}</span>}
|
|
</div>
|
|
</div>
|
|
</Link>
|
|
)
|
|
}
|