Spaces:
Sleeping
Sleeping
| import { useState } from "react"; | |
| import { zodResolver } from "@hookform/resolvers/zod"; | |
| import { useForm } from "react-hook-form"; | |
| import * as z from "zod"; | |
| import { Button } from "@/components/ui/button"; | |
| import { | |
| Dialog, | |
| DialogContent, | |
| DialogDescription, | |
| DialogFooter, | |
| DialogHeader, | |
| DialogTitle, | |
| } from "@/components/ui/dialog"; | |
| import { Input } from "@/components/ui/input"; | |
| import { | |
| Form, | |
| FormControl, | |
| FormField, | |
| FormItem, | |
| FormLabel, | |
| FormMessage, | |
| } from "@/components/ui/form"; | |
| import { | |
| Select, | |
| SelectContent, | |
| SelectItem, | |
| SelectTrigger, | |
| SelectValue, | |
| } from "@/components/ui/select"; | |
| import { | |
| Competency, | |
| CompetencyCategory, | |
| CompetencyCreateRequest, | |
| CompetencyUpdateRequest | |
| } from "@/types"; | |
| // Define form schema | |
| const formSchema = z.object({ | |
| title: z.string().min(2, { message: "Title must be at least 2 characters." }), | |
| category: z.enum(["Core", "Technical", "Leadership", "Communication", "Teamwork"] as const), | |
| weightage: z.coerce | |
| .number() | |
| .min(1, { message: "Weightage must be at least 1." }) | |
| .max(100, { message: "Weightage must be at most 100." }), | |
| }); | |
| interface CompetencyDialogProps { | |
| open: boolean; | |
| onOpenChange: (open: boolean) => void; | |
| onSubmit: (data: CompetencyCreateRequest | CompetencyUpdateRequest) => void; | |
| competencyToEdit?: Competency; | |
| isLoading?: boolean; | |
| } | |
| export function CompetencyDialog({ | |
| open, | |
| onOpenChange, | |
| onSubmit, | |
| competencyToEdit, | |
| isLoading = false, | |
| }: CompetencyDialogProps) { | |
| const [error, setError] = useState<string | null>(null); | |
| const form = useForm<z.infer<typeof formSchema>>({ | |
| resolver: zodResolver(formSchema), | |
| defaultValues: { | |
| title: competencyToEdit?.title || "", | |
| category: competencyToEdit?.category || "Core", | |
| weightage: competencyToEdit?.weightage || 10, | |
| }, | |
| }); | |
| function handleSubmit(values: z.infer<typeof formSchema>) { | |
| setError(null); | |
| if (competencyToEdit) { | |
| onSubmit({ | |
| competencyId: competencyToEdit.competencyId, | |
| title: values.title, | |
| category: values.category, | |
| weightage: values.weightage, | |
| }); | |
| } else { | |
| onSubmit({ | |
| title: values.title, | |
| category: values.category, | |
| weightage: values.weightage, | |
| }); | |
| } | |
| } | |
| return ( | |
| <Dialog open={open} onOpenChange={onOpenChange}> | |
| <DialogContent className="sm:max-w-[425px]"> | |
| <DialogHeader> | |
| <DialogTitle>{competencyToEdit ? "Edit Competency" : "Create Competency"}</DialogTitle> | |
| <DialogDescription> | |
| {competencyToEdit | |
| ? "Edit the details of this competency." | |
| : "Add a new competency to the system." | |
| } | |
| </DialogDescription> | |
| </DialogHeader> | |
| <Form {...form}> | |
| <form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4"> | |
| <FormField | |
| control={form.control} | |
| name="title" | |
| render={({ field }) => ( | |
| <FormItem> | |
| <FormLabel>Title</FormLabel> | |
| <FormControl> | |
| <Input placeholder="Problem Solving" {...field} /> | |
| </FormControl> | |
| <FormMessage /> | |
| </FormItem> | |
| )} | |
| /> | |
| <FormField | |
| control={form.control} | |
| name="category" | |
| render={({ field }) => ( | |
| <FormItem> | |
| <FormLabel>Category</FormLabel> | |
| <Select | |
| onValueChange={field.onChange} | |
| defaultValue={field.value} | |
| > | |
| <FormControl> | |
| <SelectTrigger> | |
| <SelectValue placeholder="Select a category" /> | |
| </SelectTrigger> | |
| </FormControl> | |
| <SelectContent> | |
| <SelectItem value="Core">Core</SelectItem> | |
| <SelectItem value="Technical">Technical</SelectItem> | |
| <SelectItem value="Leadership">Leadership</SelectItem> | |
| <SelectItem value="Communication">Communication</SelectItem> | |
| <SelectItem value="Teamwork">Teamwork</SelectItem> | |
| </SelectContent> | |
| </Select> | |
| <FormMessage /> | |
| </FormItem> | |
| )} | |
| /> | |
| <FormField | |
| control={form.control} | |
| name="weightage" | |
| render={({ field }) => ( | |
| <FormItem> | |
| <FormLabel>Weightage (%)</FormLabel> | |
| <FormControl> | |
| <Input | |
| type="number" | |
| min={1} | |
| max={100} | |
| placeholder="10" | |
| {...field} | |
| /> | |
| </FormControl> | |
| <FormMessage /> | |
| </FormItem> | |
| )} | |
| /> | |
| {error && <p className="text-sm font-medium text-destructive">{error}</p>} | |
| <DialogFooter> | |
| <Button | |
| type="button" | |
| variant="outline" | |
| onClick={() => onOpenChange(false)} | |
| disabled={isLoading} | |
| > | |
| Cancel | |
| </Button> | |
| <Button type="submit" disabled={isLoading}> | |
| {isLoading ? "Saving..." : competencyToEdit ? "Update" : "Create"} | |
| </Button> | |
| </DialogFooter> | |
| </form> | |
| </Form> | |
| </DialogContent> | |
| </Dialog> | |
| ); | |
| } |