95 lines
3.0 KiB
TypeScript
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>
|
|
);
|
|
}
|