"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { Loader2, Save } from "lucide-react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form"; import { PermissionPicker } from "./permission-picker"; const formSchema = z.object({ name: z.string().min(1, "Name is required").regex(/^[a-z0-9-]+$/, "Name must be lowercase with hyphens only"), description: z.string().optional(), permissions: z.record(z.string(), z.array(z.string())), }); type FormData = z.infer; interface Role { id: string; name: string; description: string | null; permissions: Record; is_system: boolean; } interface RoleFormProps { role?: Role; } export function RoleForm({ role }: RoleFormProps) { const router = useRouter(); const [isLoading, setIsLoading] = useState(false); const isEditing = !!role; const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { name: role?.name || "", description: role?.description || "", permissions: role?.permissions || {}, }, }); async function onSubmit(data: FormData) { setIsLoading(true); try { const url = isEditing ? `/api/admin/roles/${role.id}` : "/api/admin/roles"; const method = isEditing ? "PATCH" : "POST"; const response = await fetch(url, { method, headers: { "Content-Type": "application/json" }, body: JSON.stringify(data), }); if (!response.ok) { const result = await response.json(); throw new Error(result.error || `Failed to ${isEditing ? "update" : "create"} role`); } toast.success(`Role ${isEditing ? "updated" : "created"} successfully`); router.push("/admin/roles"); router.refresh(); } catch (error) { toast.error(error instanceof Error ? error.message : "An error occurred"); } finally { setIsLoading(false); } } return (
( Name Lowercase letters, numbers, and hyphens only )} /> ( Description