"use client"; import React, { useState, useTransition, useEffect } from "react"; import { useRouter } from "next/navigation"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Label } from "@/components/ui/label"; import { toast } from "sonner"; import { updateForm } from "@/app/admin/form/actions"; import { Loader2, Save, ChevronDown } from "lucide-react"; import { getGuildRoles, DiscordRole } from "@/app/actions/discord"; import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area" interface FormExtraClientProps { form: { id: string; discordWebhookUrl: string | null; discordWebhookTemplate: string | null; discordWebhookUpdateTemplate: string | null; allowedRoles?: string[] | null; deniedRoles?: string[] | null; }; } export default function FormExtraClient({ form }: FormExtraClientProps) { const router = useRouter(); const [webhookUrl, setWebhookUrl] = useState(form.discordWebhookUrl || ""); const [webhookTemplate, setWebhookTemplate] = useState(form.discordWebhookTemplate || ""); const [webhookUpdateTemplate, setWebhookUpdateTemplate] = useState(form.discordWebhookUpdateTemplate || ""); const [allowedRoles, setAllowedRoles] = useState(form.allowedRoles || []); const [deniedRoles, setDeniedRoles] = useState(form.deniedRoles || []); const [roles, setRoles] = useState([]); const [loadingRoles, setLoadingRoles] = useState(true); const [isSaving, startSaveTransition] = useTransition(); useEffect(() => { getGuildRoles() .then(r => setRoles(r)) .catch(() => toast.error("Failed to load Discord roles.")) .finally(() => setLoadingRoles(false)); }, []); const handleSave = () => { startSaveTransition(async () => { try { await updateForm(form.id, { discordWebhookUrl: webhookUrl.trim() || null, discordWebhookTemplate: webhookTemplate.trim() || null, discordWebhookUpdateTemplate: webhookUpdateTemplate.trim() || null, allowedRoles, deniedRoles, }); toast.success("Extra settings saved!"); router.refresh(); } catch (err: any) { toast.error(err.message || "Failed to update settings."); } }); }; const toggleRole = (list: string[], setList: (v: string[]) => void, roleId: string) => { if (list.includes(roleId)) { setList(list.filter(id => id !== roleId)); } else { setList([...list, roleId]); } }; const renderRoleList = (list: string[], setList: (v: string[]) => void, label: string, desc: string) => { const selectedRoles = roles.filter(r => list.includes(r.id)); return (

{desc}

{loadingRoles ? (
Loading roles...
) : (
{roles.map(role => { const colorHex = role.color === 0 ? "#99aab5" : `#${role.color.toString(16).padStart(6, '0')}`; return ( toggleRole(list, setList, role.id)} onSelect={(e) => e.preventDefault()} >
{role.name}
); })} {roles.length === 0 && (
No roles found.
)}
)}
); }; return (
Access Control Restrict form access to specific Discord roles. {renderRoleList( allowedRoles, setAllowedRoles, "Allowed Roles", "Users must have at least one of these roles to access the form. Leave empty to allow all." )} {renderRoleList( deniedRoles, setDeniedRoles, "Denied Roles", "Users with any of these roles will be blocked from accessing the form, even if they have an allowed role." )} Discord Webhook Send notifications to a Discord channel when a new submission is received. Leave URL empty to disable.
setWebhookUrl(e.target.value)} placeholder="https://discord.com/api/webhooks/..." />