forked from administration/panel
213 lines
6.6 KiB
TypeScript
213 lines
6.6 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { Button } from "../../ui/button";
|
|
import { useToast } from "../../ui/use-toast";
|
|
import type { Account } from "@/lib/db";
|
|
import { User } from "revolt-api";
|
|
import {
|
|
cancelAccountDeletion,
|
|
changeAccountEmail,
|
|
disableAccount,
|
|
queueAccountDeletion,
|
|
restoreAccount,
|
|
} from "@/lib/actions";
|
|
import dayjs from "dayjs";
|
|
|
|
import relativeTime from "dayjs/plugin/relativeTime";
|
|
import {
|
|
AlertDialog,
|
|
AlertDialogAction,
|
|
AlertDialogCancel,
|
|
AlertDialogContent,
|
|
AlertDialogFooter,
|
|
AlertDialogHeader,
|
|
AlertDialogTitle,
|
|
AlertDialogTrigger,
|
|
} from "../../ui/alert-dialog";
|
|
import { AlertDialogDescription } from "@radix-ui/react-alert-dialog";
|
|
import { Input } from "@/components/ui/input";
|
|
dayjs.extend(relativeTime);
|
|
|
|
export function AccountActions({
|
|
account,
|
|
user,
|
|
}: {
|
|
account: Account;
|
|
user?: User;
|
|
}) {
|
|
const { toast } = useToast();
|
|
|
|
const [accountDraft, setAccountDraft] = useState(account);
|
|
const [emailDraft, setEmailDraft] = useState("");
|
|
|
|
return (
|
|
<div className="flex gap-2">
|
|
<AlertDialog>
|
|
<AlertDialogTrigger asChild>
|
|
<Button className="flex-1">
|
|
Change Email
|
|
</Button>
|
|
</AlertDialogTrigger>
|
|
<AlertDialogContent>
|
|
<AlertDialogHeader>
|
|
<AlertDialogTitle>
|
|
Update account email
|
|
</AlertDialogTitle>
|
|
<AlertDialogDescription>
|
|
<Input
|
|
placeholder={account.email}
|
|
onChange={(e) => setEmailDraft(e.currentTarget.value)}
|
|
value={emailDraft}
|
|
/>
|
|
</AlertDialogDescription>
|
|
</AlertDialogHeader>
|
|
<AlertDialogFooter>
|
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
<AlertDialogAction
|
|
disabled={!/^.+@.+$/.test(emailDraft)}
|
|
onClick={async () => {
|
|
try {
|
|
await changeAccountEmail(account._id, emailDraft);
|
|
setEmailDraft("");
|
|
toast({ title: "Updated email" });
|
|
window.location.reload();
|
|
} catch (err) {
|
|
toast({
|
|
title: "Failed to execute action",
|
|
description: String(err),
|
|
variant: "destructive",
|
|
});
|
|
}
|
|
}}
|
|
>
|
|
Change
|
|
</AlertDialogAction>
|
|
</AlertDialogFooter>
|
|
</AlertDialogContent>
|
|
</AlertDialog>
|
|
|
|
<AlertDialog>
|
|
<AlertDialogTrigger asChild>
|
|
<Button
|
|
className="flex-1"
|
|
disabled={accountDraft.deletion?.status === "Scheduled"}
|
|
>
|
|
{accountDraft.disabled ? "Restore Access" : "Disable"}
|
|
</Button>
|
|
</AlertDialogTrigger>
|
|
<AlertDialogContent>
|
|
<AlertDialogHeader>
|
|
<AlertDialogTitle>
|
|
Are you sure you want to{" "}
|
|
{accountDraft.disabled ? "restore" : "disable"} this account?
|
|
</AlertDialogTitle>
|
|
</AlertDialogHeader>
|
|
<AlertDialogFooter>
|
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
<AlertDialogAction
|
|
onClick={async () => {
|
|
try {
|
|
if (accountDraft.disabled) {
|
|
await restoreAccount(account._id);
|
|
setAccountDraft((account) => ({
|
|
...account!,
|
|
disabled: false,
|
|
}));
|
|
toast({
|
|
title: "Restored account",
|
|
});
|
|
} else {
|
|
await disableAccount(account._id);
|
|
setAccountDraft((account) => ({
|
|
...account!,
|
|
disabled: true,
|
|
}));
|
|
toast({
|
|
title: "Disabled account",
|
|
});
|
|
}
|
|
} catch (err) {
|
|
toast({
|
|
title: "Failed to execute action",
|
|
description: String(err),
|
|
variant: "destructive",
|
|
});
|
|
}
|
|
}}
|
|
>
|
|
{accountDraft.disabled ? "Restore" : "Disable"}
|
|
</AlertDialogAction>
|
|
</AlertDialogFooter>
|
|
</AlertDialogContent>
|
|
</AlertDialog>
|
|
|
|
<AlertDialog>
|
|
<AlertDialogTrigger asChild>
|
|
<Button
|
|
className="flex-1"
|
|
disabled={
|
|
user?.flags
|
|
? user?.flags === 2 ||
|
|
accountDraft.deletion?.status !== "Scheduled"
|
|
: false
|
|
}
|
|
>
|
|
{accountDraft.deletion?.status === "Scheduled"
|
|
? `Cancel Deletion (${dayjs(
|
|
(account.deletion as any)?.after
|
|
).fromNow()})`
|
|
: "Queue Deletion"}
|
|
</Button>
|
|
</AlertDialogTrigger>
|
|
<AlertDialogContent>
|
|
<AlertDialogHeader>
|
|
<AlertDialogTitle>
|
|
Are you sure you want to{" "}
|
|
{accountDraft.deletion?.status === "Scheduled"
|
|
? "cancel deletion of"
|
|
: "queue deletion for"}{" "}
|
|
this account?
|
|
</AlertDialogTitle>
|
|
</AlertDialogHeader>
|
|
<AlertDialogFooter>
|
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
<AlertDialogAction
|
|
onClick={async () => {
|
|
try {
|
|
if (accountDraft.deletion?.status === "Scheduled") {
|
|
await cancelAccountDeletion(account._id);
|
|
setAccountDraft((account) => ({
|
|
...account,
|
|
deletion: null,
|
|
}));
|
|
toast({
|
|
title: "Cancelled account deletion",
|
|
});
|
|
} else {
|
|
const $set = await queueAccountDeletion(account._id);
|
|
setAccountDraft((account) => ({ ...account!, ...$set }));
|
|
toast({
|
|
title: "Queued account for deletion",
|
|
});
|
|
}
|
|
} catch (err) {
|
|
toast({
|
|
title: "Failed to execute action",
|
|
description: String(err),
|
|
variant: "destructive",
|
|
});
|
|
}
|
|
}}
|
|
>
|
|
{accountDraft.deletion?.status === "Scheduled"
|
|
? "Unqueue"
|
|
: "Queue"}
|
|
</AlertDialogAction>
|
|
</AlertDialogFooter>
|
|
</AlertDialogContent>
|
|
</AlertDialog>
|
|
</div>
|
|
);
|
|
}
|