import { Button } from "../ui/button"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "../ui/form"; import { Input } from "../ui/input"; import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import { z } from "zod"; import ActivityIndicator from "../indicators/activity-indicator"; import { useEffect, useState } from "react"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "../ui/dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "../ui/select"; import { Shield, User } from "lucide-react"; import { LuCheck, LuX } from "react-icons/lu"; type CreateUserOverlayProps = { show: boolean; onCreate: (user: string, password: string, role: "admin" | "viewer") => void; onCancel: () => void; }; export default function CreateUserDialog({ show, onCreate, onCancel, }: CreateUserOverlayProps) { const [isLoading, setIsLoading] = useState(false); const formSchema = z .object({ user: z .string() .min(1, "Username is required") .regex(/^[A-Za-z0-9._]+$/, { message: "Username may only include letters, numbers, . or _", }), password: z.string().min(1, "Password is required"), confirmPassword: z.string().min(1, "Please confirm your password"), role: z.enum(["admin", "viewer"]), }) .refine((data) => data.password === data.confirmPassword, { message: "Passwords don't match", path: ["confirmPassword"], }); const form = useForm>({ resolver: zodResolver(formSchema), mode: "onChange", defaultValues: { user: "", password: "", confirmPassword: "", role: "viewer", }, }); const onSubmit = async (values: z.infer) => { setIsLoading(true); await onCreate(values.user, values.password, values.role); form.reset(); setIsLoading(false); }; // Check if passwords match for real-time feedback const password = form.watch("password"); const confirmPassword = form.watch("confirmPassword"); const passwordsMatch = password === confirmPassword; const showMatchIndicator = password && confirmPassword; useEffect(() => { if (!show) { form.reset({ user: "", password: "", role: "viewer", }); } }, [show, form]); const handleCancel = () => { form.reset({ user: "", password: "", role: "viewer", }); onCancel(); }; return ( Create New User Add a new user account and specify an role for access to areas of the Frigate UI.
( Username Only letters, numbers, periods and underscores allowed. )} /> ( Password )} /> ( Confirm Password {showMatchIndicator && (
{passwordsMatch ? ( <> Passwords match ) : ( <> Passwords don't match )}
)}
)} /> ( Role Admins have full access to all features in the Frigate UI. Viewers are limited to viewing cameras, review items, and historical footage in the UI. )} />
); }