- Fix DOMPurify SSR crash (use isomorphic-dompurify) - Fix SanitizedHtml to sanitize by default - Add auth guards to studio/catalog maintenance pages - Add update/edit to vouchers CRUD - Add update/edit to rare-values CRUD - Add approve workflow to applications page - Add edit form to guilds detail page - Add SEO metadata to all public pages (21 pages) - Fix mobile nav accessibility (focus trap, aria attributes) - Fix missing labels and table accessibility - Add dynamic imports for heavy client components (6 components) - Fix silent error swallowing (40+ locations) - Add content scheduling for articles (publishAt, status) - Wire up 12 missing webhook notification triggers - Add global search to admin panel - Add bulk actions to admin users table - Fix JSON formatting and a11y issues
75 lines
1.7 KiB
TypeScript
75 lines
1.7 KiB
TypeScript
"use client";
|
|
|
|
import { useRouter } from "next/navigation";
|
|
import { useTranslations } from "next-intl";
|
|
import { useTransition } from "react";
|
|
import {
|
|
approveApplication,
|
|
dismissApplication,
|
|
} from "@/actions/admin-applications";
|
|
import { useConfirmDialog } from "@/components/admin/confirm-dialog";
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
export function ApplicationActions({ id }: { id: string }) {
|
|
const t = useTranslations("pages.admin.applications");
|
|
const router = useRouter();
|
|
const [pending, startTransition] = useTransition();
|
|
const { confirm, dialog: confirmDialog } = useConfirmDialog();
|
|
|
|
async function handleApprove() {
|
|
const ok = await confirm({
|
|
title: t("approve"),
|
|
description: t("confirmApprove"),
|
|
confirmLabel: t("approve"),
|
|
variant: "default",
|
|
});
|
|
if (!ok) return;
|
|
startTransition(async () => {
|
|
const fd = new FormData();
|
|
fd.set("id", id);
|
|
await approveApplication(fd);
|
|
router.refresh();
|
|
});
|
|
}
|
|
|
|
async function handleReject() {
|
|
const ok = await confirm({
|
|
title: t("reject"),
|
|
description: t("confirmReject"),
|
|
confirmLabel: t("reject"),
|
|
variant: "danger",
|
|
});
|
|
if (!ok) return;
|
|
startTransition(async () => {
|
|
const fd = new FormData();
|
|
fd.set("id", id);
|
|
await dismissApplication(fd);
|
|
router.refresh();
|
|
});
|
|
}
|
|
|
|
return (
|
|
<div className="flex gap-2">
|
|
{confirmDialog}
|
|
<Button
|
|
type="button"
|
|
variant="default"
|
|
size="sm"
|
|
disabled={pending}
|
|
onClick={handleApprove}
|
|
>
|
|
{t("approve")}
|
|
</Button>
|
|
<Button
|
|
type="button"
|
|
variant="destructive"
|
|
size="sm"
|
|
disabled={pending}
|
|
onClick={handleReject}
|
|
>
|
|
{t("reject")}
|
|
</Button>
|
|
</div>
|
|
);
|
|
}
|