Fix articles list crash by moving interactive card to client component
Local Build and Deploy / deploy (push) Successful in 1m4s

Extract the article card (thumbnail onError fallback, delete confirmation)
into a Client Component so the admin articles list server page no longer
passes event handlers to server-rendered elements.
This commit is contained in:
openhands committed 2026-07-18 17:45:15 +02:00
1 parent 6215074331
commit 243f8007d9
2 files changed
+88 -61

No files matched your search

+79
View File
@@ -0,0 +1,79 @@
"use client";
import Link from "next/link";
import { useTranslations } from "next-intl";
import { deleteArticle } from "@/actions/admin-articles";
export function ArticleCard({
id,
title,
slug,
image,
createdAt,
author,
}: {
id: string;
title: string;
slug: string;
image: string;
createdAt: string | null;
author?: string;
}) {
const t = useTranslations("pages.admin.articles");
return (
<div className="admin-card overflow-hidden flex flex-col">
<div className="relative w-full aspect-[16/9] bg-[var(--admin-canvas)]">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={image || ""}
alt={title}
className="w-full h-full object-cover block"
onError={(e) => {
e.currentTarget.style.visibility = "hidden";
}}
/>
</div>
<div className="p-3 flex flex-col flex-1">
<Link
href={`/admin/articles/${id}`}
className="font-semibold text-[var(--admin-text)] hover:text-[var(--admin-accent)] line-clamp-2"
style={{ textDecoration: "none" }}
>
{title}
</Link>
<p className="text-xs text-[var(--admin-text-muted)] mt-1 mb-3 flex items-center gap-2 flex-wrap">
<span>{createdAt ? createdAt.slice(0, 10) : "—"}</span>
{author ? (
<>
<span>·</span>
<span>{author}</span>
</>
) : null}
</p>
<div className="flex gap-2 mt-auto">
<Link
href={`/admin/articles/${id}`}
className="btn btn-primary flex-1 text-center"
>
{t("edit")}
</Link>
<form action={deleteArticle} className="m-0">
<input type="hidden" name="id" value={id} />
<button
type="submit"
className="btn btn-danger"
onClick={(e) => {
if (!window.confirm(t("confirmDelete", { title }))) {
e.preventDefault();
}
}}
>
{t("delete")}
</button>
</form>
</div>
</div>
</div>
);
}