feat(ops): health-fail alerts, optional DB backup, admin UX polish

Wire jobs-worker health probes to Discord/email alerts with cooldown, optional mysqldump, rate-limit /api/health, mark-all-read alerts, ConfirmDialog on destructive admin actions, and raise coverage floors.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
SimoandCursor committed 2026-08-01 15:25:47 +02:00
1 parent 3bd712e744
commit 725e1cb338
16 files changed
+327 -32

No files matched your search

+31 -14
View File
@@ -1,8 +1,11 @@
"use client";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useTranslations } from "next-intl";
import { useTransition } from "react";
import { deleteArticle } from "@/actions/admin-articles";
import { useConfirmDialog } from "@/components/admin/confirm-dialog";
export function ArticleCard({
id,
@@ -18,9 +21,29 @@ export function ArticleCard({
author?: string;
}) {
const t = useTranslations("pages.admin.articles");
const router = useRouter();
const [pending, startTransition] = useTransition();
const { confirm, dialog: confirmDialog } = useConfirmDialog();
async function handleDelete() {
const ok = await confirm({
title: t("delete"),
description: t("confirmDelete", { title }),
confirmLabel: t("delete"),
variant: "danger",
});
if (!ok) return;
startTransition(async () => {
const fd = new FormData();
fd.set("id", id);
await deleteArticle(fd);
router.refresh();
});
}
return (
<div className="admin-card overflow-hidden flex flex-col">
{confirmDialog}
<div className="relative w-full aspect-[16/9] bg-[var(--admin-canvas)]">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
@@ -56,20 +79,14 @@ export function ArticleCard({
>
{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>
<button
type="button"
className="btn btn-danger"
disabled={pending}
onClick={handleDelete}
>
{t("delete")}
</button>
</div>
</div>
</div>