feat(admin): server-safe StatusCard and Import hub polish
CI / check (push) Failing after 8s
CI / release (push) Skipped
CI / deploy (push) Skipped

Split OnlineUsersWidget from StatusCard, decouple ad delete button, sync badge import to ExternalTexts+WebsiteBadges, add Import section hub with cancelable SSE jobs and upload SQL option.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
SimoandCursor committed 2026-08-01 15:48:21 +02:00
1 parent db957d7fb1
commit 9c4949186c
21 files changed
+576 -249

No files matched your search

+1 -1
View File
@@ -7,7 +7,7 @@ import { updateAd } from "@/actions/admin-ads";
import { Button } from "@/components/ui/button";
import { db, WebsiteAds } from "@/lib/db";
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
import { EditAdDeleteButton } from "../ads-table";
import { EditAdDeleteButton } from "../edit-ad-delete-button";
export default async function EditAd({
params,
-35
View File
@@ -84,38 +84,3 @@ export function AdsTable({ ads }: { ads: AdRow[] }) {
</>
);
}
export function EditAdDeleteButton({ id }: { id: string }) {
const t = useTranslations("pages.admin.ads");
const { run, isPending } = useServerAction();
const { confirm, dialog: confirmDialog } = useConfirmDialog();
async function handleDelete() {
const ok = await confirm({
title: t("delete"),
description: t("confirmDelete"),
confirmLabel: t("delete"),
cancelLabel: t("form.cancel"),
});
if (!ok) return;
run(() => deleteAd({ id }), {
successMessage: t("deleteSuccess"),
errorMessage: t("deleteError"),
redirectTo: "/admin/ads",
});
}
return (
<>
{confirmDialog}
<Button
type="button"
variant="destructive"
disabled={isPending}
onClick={handleDelete}
>
{t("form.deleteAd")}
</Button>
</>
);
}
@@ -0,0 +1,44 @@
"use client";
import { Trash2 } from "lucide-react";
import { useTranslations } from "next-intl";
import { deleteAd } from "@/actions/admin-ads";
import { useConfirmDialog } from "@/components/admin/confirm-dialog";
import { Button } from "@/components/ui/button";
import { useServerAction } from "@/hooks/use-server-action";
export function EditAdDeleteButton({ id }: { id: string }) {
const t = useTranslations("pages.admin.ads");
const { run, isPending } = useServerAction();
const { confirm, dialog: confirmDialog } = useConfirmDialog();
async function handleDelete() {
const ok = await confirm({
title: t("delete"),
description: t("confirmDelete"),
confirmLabel: t("delete"),
cancelLabel: t("form.cancel"),
});
if (!ok) return;
run(() => deleteAd({ id }), {
successMessage: t("deleteSuccess"),
errorMessage: t("deleteError"),
redirectTo: "/admin/ads",
});
}
return (
<>
{confirmDialog}
<Button
type="button"
variant="destructive"
disabled={isPending}
onClick={handleDelete}
>
<Trash2 className="mr-2 h-4 w-4" />
{t("form.deleteAd")}
</Button>
</>
);
}