mirror of
https://github.com/fosrl/pangolin.git
synced 2026-06-11 18:09:05 +00:00
✨ Create label dialog
This commit is contained in:
125
src/components/OrgLabelForm.tsx
Normal file
125
src/components/OrgLabelForm.tsx
Normal file
@@ -0,0 +1,125 @@
|
||||
"use client";
|
||||
|
||||
import z from "zod";
|
||||
import { Input } from "./ui/input";
|
||||
import { useTranslations } from "use-intl";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage
|
||||
} from "./ui/form";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue
|
||||
} from "./ui/select";
|
||||
import { LABEL_COLORS } from "./labels-selector";
|
||||
|
||||
const labelFormSchema = z.object({
|
||||
name: z.string().nonempty(),
|
||||
color: z
|
||||
.string()
|
||||
.regex(/^#?([0-9a-f]{6}|[0-9a-f]{3})$/i)
|
||||
.nonempty()
|
||||
});
|
||||
|
||||
export type LabelFormData = z.infer<typeof labelFormSchema>;
|
||||
|
||||
export type OrgLabelFormProps = {
|
||||
onSubmit: (data: LabelFormData) => void;
|
||||
};
|
||||
|
||||
export function OrgLabelForm({ onSubmit }: OrgLabelFormProps) {
|
||||
const t = useTranslations();
|
||||
|
||||
const colorValues = Object.values(LABEL_COLORS);
|
||||
const randomColor =
|
||||
colorValues[Math.floor(Math.random() * colorValues.length)];
|
||||
|
||||
const form = useForm({
|
||||
resolver: zodResolver(labelFormSchema),
|
||||
defaultValues: {
|
||||
name: "",
|
||||
color: randomColor
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form
|
||||
id="org-label-form"
|
||||
className="flex flex-col gap-4"
|
||||
action={async () => {
|
||||
if (await form.trigger()) {
|
||||
onSubmit(form.getValues());
|
||||
}
|
||||
}}
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="name"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("labelNameField")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
placeholder={t("labelPlaceholder")}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="color"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("labelColorField")}</FormLabel>
|
||||
<Select
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue
|
||||
placeholder={t("selectColor")}
|
||||
/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{Object.entries(LABEL_COLORS).map(
|
||||
([color, value]) => (
|
||||
<SelectItem
|
||||
value={value}
|
||||
key={color}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<div
|
||||
className="size-4 rounded-full bg-(--color) flex-none"
|
||||
style={{
|
||||
// @ts-expect-error css color
|
||||
"--color": value
|
||||
}}
|
||||
/>
|
||||
<span data-name>{color}</span>
|
||||
</SelectItem>
|
||||
)
|
||||
)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user