Organize/components/admin/signup-mode-settings.tsx

95 lines
3.0 KiB
TypeScript

"use client";
import { useState } from "react";
import { toast } from "sonner";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Label } from "@/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { updateSignupMode } from "@/lib/actions/admin";
import { SignupMode } from "@/lib/generated/prisma/enums";
const OPTIONS: {
value: SignupMode;
label: string;
description: string;
disabled?: boolean;
}[] = [
{
value: SignupMode.OPEN,
label: "Open",
description: "Anyone can sign up and gets the User role right away.",
},
{
value: SignupMode.APPROVED,
label: "Approved",
description:
"Anyone can sign up, but starts Pending and can't log in until an admin changes their role to User or Administrator.",
},
{
value: SignupMode.CONFIRMED,
label: "Confirmed",
description: "Anyone can sign up, but starts Pending until they confirm their email.",
disabled: true,
},
{
value: SignupMode.CLOSED,
label: "Closed",
description:
"The site isn't accepting new accounts. The sign-up form and links are removed, and the sign-up action refuses new accounts.",
},
];
/** Lets an admin choose how the site handles new sign-ups. */
export function SignupModeSettings({ initialMode }: { initialMode: SignupMode }) {
const [current, setCurrent] = useState(initialMode);
const [pending, setPending] = useState(false);
async function handleChange(next: string) {
if (next === current || pending) return;
const prev = current;
setCurrent(next as SignupMode);
setPending(true);
const result = await updateSignupMode(next);
setPending(false);
if (result?.error) {
setCurrent(prev);
toast.error(result.error);
}
}
return (
<Card className="max-w-3xl">
<CardHeader>
<CardTitle>New sign-ups</CardTitle>
<CardDescription>Choose how the site handles people signing up for an account.</CardDescription>
</CardHeader>
<CardContent>
<RadioGroup value={current} onValueChange={handleChange}>
{OPTIONS.map((option) => (
<div
key={option.value}
className={`flex items-start gap-3 py-2 ${option.disabled ? "opacity-50" : ""}`}
>
<RadioGroupItem
value={option.value}
id={`signup-mode-${option.value}`}
disabled={option.disabled || pending}
className="mt-0.5"
/>
<div className="grid gap-1">
<Label htmlFor={`signup-mode-${option.value}`} className="gap-1.5">
{option.label}
{option.disabled && <Badge variant="outline">Coming soon</Badge>}
</Label>
<p className="text-sm text-muted-foreground">{option.description}</p>
</div>
</div>
))}
</RadioGroup>
</CardContent>
</Card>
);
}