Openstatus www.openstatus.dev
at main 127 lines 3.6 kB view raw
1"use client"; 2 3import { 4 FormControl, 5 FormDescription, 6 FormField, 7 FormItem, 8 FormLabel, 9 FormMessage, 10} from "@/components/ui/form"; 11 12import { 13 FormCard, 14 FormCardContent, 15 FormCardDescription, 16 FormCardFooter, 17 FormCardHeader, 18 FormCardTitle, 19} from "@/components/forms/form-card"; 20import { Button } from "@/components/ui/button"; 21import { Form } from "@/components/ui/form"; 22import { Input } from "@/components/ui/input"; 23import { zodResolver } from "@hookform/resolvers/zod"; 24import { useTransition } from "react"; 25import { useForm } from "react-hook-form"; 26import { toast } from "sonner"; 27import { z } from "zod"; 28 29const DEGRADED = 30_000; 30const TIMEOUT = 45_000; 31 32const schema = z.object({ 33 degradedAfter: z.coerce.number<number>().optional(), 34 timeout: z.coerce.number<number>(), 35}); 36 37type FormValues = z.input<typeof schema>; 38 39export function FormResponseTime({ 40 defaultValues, 41 onSubmit, 42 ...props 43}: Omit<React.ComponentProps<"form">, "onSubmit"> & { 44 defaultValues?: FormValues; 45 onSubmit: (values: FormValues) => Promise<void>; 46}) { 47 const form = useForm<FormValues>({ 48 resolver: zodResolver(schema), 49 defaultValues: defaultValues ?? { 50 degradedAfter: DEGRADED, 51 timeout: TIMEOUT, 52 }, 53 }); 54 const [isPending, startTransition] = useTransition(); 55 56 function submitAction(values: FormValues) { 57 if (isPending) return; 58 59 startTransition(async () => { 60 try { 61 const promise = onSubmit(values); 62 toast.promise(promise, { 63 loading: "Saving...", 64 success: () => "Saved", 65 error: "Failed to save", 66 }); 67 await promise; 68 } catch (error) { 69 console.error(error); 70 } 71 }); 72 } 73 74 return ( 75 <Form {...form}> 76 <form onSubmit={form.handleSubmit(submitAction)} {...props}> 77 <FormCard> 78 <FormCardHeader> 79 <FormCardTitle>Response Time Thresholds</FormCardTitle> 80 <FormCardDescription> 81 Configure your degraded and timeout thresholds. 82 </FormCardDescription> 83 </FormCardHeader> 84 <FormCardContent className="grid gap-4 sm:grid-cols-2"> 85 <FormField 86 control={form.control} 87 name="degradedAfter" 88 render={({ field }) => ( 89 <FormItem className="self-start"> 90 <FormLabel>Degraded (in ms.)</FormLabel> 91 <FormControl> 92 <Input placeholder="30000" type="number" {...field} /> 93 </FormControl> 94 <FormDescription> 95 Time after which the endpoint is considered degraded. 96 </FormDescription> 97 <FormMessage /> 98 </FormItem> 99 )} 100 /> 101 <FormField 102 control={form.control} 103 name="timeout" 104 render={({ field }) => ( 105 <FormItem className="self-start"> 106 <FormLabel>Timeout (in ms.)</FormLabel> 107 <FormControl> 108 <Input placeholder="45000" type="number" {...field} /> 109 </FormControl> 110 <FormDescription> 111 Max. time allowed for request to complete. 112 </FormDescription> 113 <FormMessage /> 114 </FormItem> 115 )} 116 /> 117 </FormCardContent> 118 <FormCardFooter> 119 <Button type="submit" disabled={isPending}> 120 {isPending ? "Submitting..." : "Submit"} 121 </Button> 122 </FormCardFooter> 123 </FormCard> 124 </form> 125 </Form> 126 ); 127}