HTTPRequestConfig.tsx164 lines · main
1import { useParams } from 'common'
2import Link from 'next/link'
3import { UseFormReturn } from 'react-hook-form'
4import {
5 Button,
6 FormControl,
7 FormField,
8 Input,
9 Select,
10 SelectContent,
11 SelectItem,
12 SelectTrigger,
13 SelectValue,
14 useWatch,
15} from 'ui'
16import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
17
18import { WebhookFormValues } from './EditHookPanel.constants'
19import {
20 FormSection,
21 FormSectionContent,
22 FormSectionLabel,
23} from '@/components/ui/Forms/FormSection'
24import { useEdgeFunctionsQuery } from '@/data/edge-functions/edge-functions-query'
25import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
26
27interface HTTPRequestConfigProps {
28 form: UseFormReturn<WebhookFormValues>
29}
30
31export const HTTPRequestConfig = ({ form }: HTTPRequestConfigProps) => {
32 const { ref } = useParams()
33 const { data: selectedProject } = useSelectedProjectQuery()
34
35 const { data: functions } = useEdgeFunctionsQuery({ projectRef: ref })
36
37 const edgeFunctions = functions ?? []
38 const functionType = useWatch({ control: form.control, name: 'function_type' })
39
40 return (
41 <FormSection
42 header={
43 <FormSectionLabel className="lg:col-span-4!">
44 {functionType === 'http_request'
45 ? 'HTTP Request'
46 : functionType === 'briven_function'
47 ? 'Edge Function'
48 : ''}
49 </FormSectionLabel>
50 }
51 >
52 <FormSectionContent loading={false} className="lg:col-span-8!">
53 <FormField
54 control={form.control}
55 name="http_method"
56 render={({ field }) => (
57 <FormItemLayout label="Method" layout="vertical" className="gap-1">
58 <Select value={field.value} onValueChange={field.onChange}>
59 <FormControl>
60 <SelectTrigger>
61 <SelectValue />
62 </SelectTrigger>
63 </FormControl>
64 <SelectContent>
65 <SelectItem value="GET">GET</SelectItem>
66 <SelectItem value="POST">POST</SelectItem>
67 </SelectContent>
68 </Select>
69 </FormItemLayout>
70 )}
71 />
72
73 {functionType === 'http_request' ? (
74 <FormField
75 control={form.control}
76 name="http_url"
77 render={({ field }) => (
78 <FormItemLayout
79 label="URL"
80 layout="vertical"
81 className="gap-1"
82 description="URL of the HTTP request. Must include HTTP/HTTPS"
83 >
84 <FormControl>
85 <Input {...field} placeholder="http://api.com/path/resource" />
86 </FormControl>
87 </FormItemLayout>
88 )}
89 />
90 ) : functionType === 'briven_function' && edgeFunctions.length === 0 ? (
91 <div className="space-y-1">
92 <p className="text-sm text-foreground-light">Select which edge function to trigger</p>
93 <div className="px-4 py-4 border rounded-sm bg-surface-300 border-strong flex items-center justify-between space-x-4">
94 <p className="text-sm">No edge functions created yet</p>
95 <Button asChild>
96 <Link href={`/project/${ref}/functions`}>Create an edge function</Link>
97 </Button>
98 </div>
99 </div>
100 ) : functionType === 'briven_function' && edgeFunctions.length > 0 ? (
101 <FormField
102 control={form.control}
103 name="http_url"
104 render={({ field }) => (
105 <FormItemLayout
106 label="Select which edge function to trigger"
107 layout="vertical"
108 className="gap-1"
109 >
110 <Select value={field.value} onValueChange={field.onChange}>
111 <FormControl>
112 <SelectTrigger>
113 <SelectValue placeholder="Select an edge function" />
114 </SelectTrigger>
115 </FormControl>
116 <SelectContent>
117 {edgeFunctions.map((fn) => {
118 const restUrl = selectedProject?.restUrl
119 const restUrlTld = restUrl ? new URL(restUrl).hostname.split('.').pop() : 'co'
120 const functionUrl = `https://${ref}.briven.${restUrlTld}/functions/v1/${fn.slug}`
121
122 return (
123 <SelectItem key={fn.id} value={functionUrl}>
124 {fn.name}
125 </SelectItem>
126 )
127 })}
128 </SelectContent>
129 </Select>
130 </FormItemLayout>
131 )}
132 />
133 ) : null}
134
135 <FormField
136 control={form.control}
137 name="timeout_ms"
138 render={({ field }) => (
139 <FormItemLayout
140 label="Timeout"
141 labelOptional="Between 1000ms to 10,000ms"
142 layout="vertical"
143 className="gap-1"
144 >
145 <FormControl>
146 <div className="relative">
147 <Input
148 {...field}
149 type="number"
150 onChange={(e) => field.onChange(Number(e.target.value))}
151 className="pr-10"
152 />
153 <span className="absolute right-3 top-1/2 -translate-y-1/2 text-foreground-light text-sm">
154 ms
155 </span>
156 </div>
157 </FormControl>
158 </FormItemLayout>
159 )}
160 />
161 </FormSectionContent>
162 </FormSection>
163 )
164}