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 { Textarea } from "@/components/ui/textarea"; | |
| import { | |
| Form, | |
| FormControl, | |
| FormField, | |
| FormItem, | |
| FormLabel, | |
| FormMessage, | |
| } from "@/components/ui/form"; | |
| import { | |
| Select, | |
| SelectContent, | |
| SelectItem, | |
| SelectTrigger, | |
| SelectValue, | |
| } from "@/components/ui/select"; | |
| import { | |
| Competency, | |
| CompetencyIndicator, | |
| CompetencyIndicatorCreateRequest, | |
| CompetencyIndicatorUpdateRequest | |
| } from "@/types"; | |
| // Define form schema | |
| const formSchema = z.object({ | |
| competencyId: z.number().min(1, { message: "Please select a competency." }), | |
| indicatorText: z.string().min(5, { message: "Indicator text must be at least 5 characters." }), | |
| }); | |
| interface CompetencyIndicatorDialogProps { | |
| open: boolean; | |
| onOpenChange: (open: boolean) => void; | |
| onSubmit: (data: CompetencyIndicatorCreateRequest | CompetencyIndicatorUpdateRequest) => void; | |
| indicatorToEdit?: CompetencyIndicator; | |
| competencies: Competency[]; | |
| isLoading?: boolean; | |
| } | |
| export function CompetencyIndicatorDialog({ | |
| open, | |
| onOpenChange, | |
| onSubmit, | |
| indicatorToEdit, | |
| competencies, | |
| isLoading = false, | |
| }: CompetencyIndicatorDialogProps) { | |
| const [error, setError] = useState<string | null>(null); | |
| const form = useForm<z.infer<typeof formSchema>>({ | |
| resolver: zodResolver(formSchema), | |
| defaultValues: { | |
| competencyId: indicatorToEdit?.competencyId || undefined, | |
| indicatorText: indicatorToEdit?.indicatorText || "", | |
| }, | |
| }); | |
| function handleSubmit(values: z.infer<typeof formSchema>) { | |
| setError(null); | |
| if (indicatorToEdit) { | |
| onSubmit({ | |
| indicatorId: indicatorToEdit.indicatorId, | |
| competencyId: values.competencyId, | |
| indicatorText: values.indicatorText, | |
| }); | |
| } else { | |
| onSubmit({ | |
| competencyId: values.competencyId, | |
| indicatorText: values.indicatorText, | |
| }); | |
| } | |
| } | |
| return ( | |
| <Dialog open={open} onOpenChange={onOpenChange}> | |
| <DialogContent className="sm:max-w-[425px]"> | |
| <DialogHeader> | |
| <DialogTitle>{indicatorToEdit ? "Edit Indicator" : "Create Indicator"}</DialogTitle> | |
| <DialogDescription> | |
| {indicatorToEdit | |
| ? "Edit the details of this competency indicator." | |
| : "Add a new competency indicator to the system." | |
| } | |
| </DialogDescription> | |
| </DialogHeader> | |
| <Form {...form}> | |
| <form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4"> | |
| <FormField | |
| control={form.control} | |
| name="competencyId" | |
| render={({ field }) => ( | |
| <FormItem> | |
| <FormLabel>Competency</FormLabel> | |
| <Select | |
| onValueChange={(value) => field.onChange(parseInt(value, 10))} | |
| value={field.value?.toString()} | |
| disabled={indicatorToEdit !== undefined} | |
| > | |
| <FormControl> | |
| <SelectTrigger> | |
| <SelectValue placeholder="Select a competency" /> | |
| </SelectTrigger> | |
| </FormControl> | |
| <SelectContent> | |
| {competencies.map((competency) => ( | |
| <SelectItem | |
| key={competency.competencyId} | |
| value={competency.competencyId.toString()} | |
| > | |
| {competency.title} ({competency.category}) | |
| </SelectItem> | |
| ))} | |
| </SelectContent> | |
| </Select> | |
| <FormMessage /> | |
| </FormItem> | |
| )} | |
| /> | |
| <FormField | |
| control={form.control} | |
| name="indicatorText" | |
| render={({ field }) => ( | |
| <FormItem> | |
| <FormLabel>Indicator Text</FormLabel> | |
| <FormControl> | |
| <Textarea | |
| placeholder="Consistently delivers high-quality work within deadlines" | |
| className="min-h-[100px]" | |
| {...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..." : indicatorToEdit ? "Update" : "Create"} | |
| </Button> | |
| </DialogFooter> | |
| </form> | |
| </Form> | |
| </DialogContent> | |
| </Dialog> | |
| ); | |
| } |