FormLayout2.tsx430 lines · main
1import { zodResolver } from '@hookform/resolvers/zod'
2import { Box, FileWarning } from 'lucide-react'
3import { useForm } from 'react-hook-form'
4import {
5 Badge,
6 Button,
7 Checkbox,
8 Form,
9 FormControl,
10 FormField,
11 RadioGroup,
12 RadioGroupItem,
13 Select,
14 SelectContent,
15 SelectItem,
16 SelectTrigger,
17 SelectValue,
18 Separator,
19 Sheet,
20 SheetContent,
21 SheetDescription,
22 SheetFooter,
23 SheetHeader,
24 SheetSection,
25 SheetTitle,
26 Switch,
27} from 'ui'
28import { z } from 'zod'
29
30import { Input } from '../DataInputs/Input'
31import { InfoTooltip } from '../info-tooltip'
32import { FormItemLayout } from './FormItemLayout/FormItemLayout'
33
34const items = [
35 {
36 id: 'recents',
37 label: 'Recents',
38 },
39 {
40 id: 'home',
41 label: 'Home',
42 },
43 {
44 id: 'applications',
45 label: 'Applications',
46 },
47 {
48 id: 'desktop',
49 label: 'Desktop',
50 },
51 {
52 id: 'downloads',
53 label: 'Downloads',
54 },
55 {
56 id: 'documents',
57 label: 'Documents',
58 },
59] as const
60
61export const Page = () => {
62 const FormSchema = z.object({
63 username: z.string().min(2, {
64 message: 'Username must be at least 2 characters.',
65 }),
66 kevins_input: z.string().min(6, {
67 message: 'Username must be at least 6 characters.',
68 }),
69 email: z
70 .string({
71 required_error: 'Please select an email to display.',
72 })
73 .email(),
74 consistent_settings: z.boolean().default(false).optional(),
75 switch_option: z.boolean().default(false).optional(),
76 items: z.array(z.string()).refine((value) => value.some((item) => item), {
77 message: 'You have to select at least one item.',
78 }),
79 type: z.enum(['all', 'mentions', 'none'], {
80 required_error: 'You need to select a notification type.',
81 }),
82 })
83
84 const form = useForm<z.infer<typeof FormSchema>>({
85 resolver: zodResolver(FormSchema),
86 defaultValues: {
87 username: '',
88 items: ['recents', 'home'],
89 },
90 })
91
92 function onSubmit(data: z.infer<typeof FormSchema>) {
93 console.log(data)
94 }
95
96 const UserIcon = () => {
97 return (
98 <div>
99 <img
100 className="relative h-4 w-4 rounded-full"
101 src="https://avatars.githubusercontent.com/u/8291514?v=4"
102 />
103 </div>
104 )
105 }
106
107 return (
108 <Sheet open={true}>
109 <SheetContent side="right" className="overflow-auto" size="default">
110 <SheetHeader>
111 <SheetTitle>Create a function</SheetTitle>
112 <SheetDescription>Create a function</SheetDescription>
113 </SheetHeader>
114 <Form {...form}>
115 <form onSubmit={form.handleSubmit(onSubmit)}>
116 <SheetSection>
117 <FormField
118 control={form.control}
119 name="username"
120 render={({ field }) => (
121 <FormItemLayout
122 label="Function name"
123 description="Name will also be used for the function name in postgres."
124 layout="horizontal"
125 labelOptional="Optional"
126 afterLabel={
127 <InfoTooltip side="right">You can also rename this later.</InfoTooltip>
128 }
129 >
130 <FormControl>
131 <Input placeholder="Name of function" {...field} />
132 </FormControl>
133 </FormItemLayout>
134 )}
135 />
136 </SheetSection>
137 <Separator />
138
139 {/* <FormField
140 control={form.control}
141 name="language"
142 render={({ field }) => (
143 <FormItem className="flex flex-col">
144 <FormLabel>Language</FormLabel>
145 <Popover>
146 <PopoverTrigger asChild>
147 <FormControl>
148 <Button
149 variant="outline"
150 role="combobox"
151 className={cn(
152 'w-[200px] justify-between',
153 !field.value && 'text-muted-foreground'
154 )}
155 >
156 {field.value
157 ? languages.find((language) => language.value === field.value)?.label
158 : 'Select language'}
159 <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
160 </Button>
161 </FormControl>
162 </PopoverTrigger>
163 <PopoverContent className="w-[200px] p-0">
164 <Command>
165 <CommandInput placeholder="Search language..." />
166 <CommandEmpty>No language found.</CommandEmpty>
167 <CommandGroup>
168 {languages.map((language) => (
169 <CommandItem
170 value={language.label}
171 key={language.value}
172 onSelect={() => {
173 form.setValue('language', language.value)
174 }}
175 >
176 <Check
177 className={cn(
178 'mr-2 h-4 w-4',
179 language.value === field.value ? 'opacity-100' : 'opacity-0'
180 )}
181 />
182 {language.label}
183 </CommandItem>
184 ))}
185 </CommandGroup>
186 </Command>
187 </PopoverContent>
188 </Popover>
189 <FormDescription>
190 This is the language that will be used in the dashboard.
191 </FormDescription>
192 <FormMessage />
193 </FormItem>
194 )}
195 /> */}
196 <SheetSection>
197 <FormField
198 control={form.control}
199 name="switch_option"
200 render={({ field }) => (
201 <FormItemLayout
202 afterLabel="Switch"
203 label="Use ./briven directory for everything"
204 description="This is an explanation."
205 layout="flex"
206 >
207 <FormControl>
208 <Switch checked={field.value} onCheckedChange={field.onChange} />
209 </FormControl>
210 </FormItemLayout>
211 )}
212 />
213 </SheetSection>
214 <Separator />
215 <SheetSection>
216 <FormField
217 control={form.control}
218 name="email"
219 render={({ field }) => (
220 <FormItemLayout
221 label="Choose user"
222 description="This is your public display name."
223 layout="horizontal"
224 >
225 <Select onValueChange={field.onChange} defaultValue={field.value}>
226 <FormControl className="w-full">
227 <SelectTrigger className="w-full">
228 <SelectValue
229 placeholder="Select a verified email"
230 className="flex gap-2"
231 />
232 </SelectTrigger>
233 </FormControl>
234 <SelectContent>
235 <SelectItem value="m@example.com">
236 <div className="flex gap-2 items-center">
237 <UserIcon />
238 <span>m@example.com</span>
239 </div>
240 </SelectItem>
241 <SelectItem value="m@google.com" className="flex gap-2">
242 <div className="flex gap-2 items-center">
243 <UserIcon />
244 UserIconm@google.com
245 </div>
246 </SelectItem>
247 <SelectItem value="m@support.com" className="flex gap-2">
248 <div className="flex gap-2 items-center">
249 <UserIcon />
250 m@support.com
251 </div>
252 </SelectItem>
253 </SelectContent>
254 </Select>
255 </FormItemLayout>
256 )}
257 />
258 </SheetSection>
259
260 <Separator />
261
262 <SheetSection>
263 <FormField
264 control={form.control}
265 name="kevins_input"
266 render={({ field }) => (
267 <FormItemLayout
268 afterLabel="Kevins input"
269 label="Kevins input"
270 description="This is your public display name."
271 layout="vertical"
272 labelOptional="Optional"
273 >
274 <FormControl>
275 <Input
276 icon={<Box strokeWidth={1.5} size={16} />}
277 placeholder="Needs to be 6 long"
278 {...field}
279 />
280 </FormControl>
281 </FormItemLayout>
282 )}
283 />
284 </SheetSection>
285
286 <Separator />
287
288 <SheetSection>
289 <FormField
290 control={form.control}
291 name="consistent_settings"
292 render={({ field }) => (
293 <FormItemLayout
294 afterLabel={
295 <Badge variant="destructive" className="flex gap-1">
296 <FileWarning size={12} strokeWidth={1.5} className="text-destructive-500" />
297 Danger
298 </Badge>
299 }
300 label="Use consistent settings"
301 description="This is your public display name."
302 layout="flex"
303 >
304 <FormControl>
305 <Checkbox checked={field.value} onCheckedChange={field.onChange} />
306 </FormControl>
307 </FormItemLayout>
308 )}
309 />
310 </SheetSection>
311
312 <Separator />
313
314 <SheetSection>
315 <FormField
316 control={form.control}
317 name="items"
318 render={() => (
319 <FormItemLayout
320 label="Sidebar"
321 description="Select the items you want to display in the sidebar."
322 layout="horizontal"
323 afterLabel={<InfoTooltip side="right">Please give me info</InfoTooltip>}
324 >
325 {/* <div className="mb-4">
326 <FormLabel className="text-base">Sidebar</FormLabel>
327 <FormDescription>
328 Select the items you want to display in the sidebar.
329 </FormDescription>
330 </div> */}
331 {items.map((item) => (
332 <FormField
333 key={item.id}
334 control={form.control}
335 name="items"
336 render={({ field }) => {
337 return (
338 <FormItemLayout
339 key={item.id}
340 className="flex flex-row items-start space-x-3 space-y-0"
341 label={item.label}
342 layout="flex"
343 hideMessage
344 >
345 <FormControl>
346 <Checkbox
347 checked={field.value?.includes(item.id)}
348 onCheckedChange={(checked) => {
349 return checked
350 ? field.onChange([...field.value, item.id])
351 : field.onChange(
352 field.value?.filter((value) => value !== item.id)
353 )
354 }}
355 />
356 </FormControl>
357 </FormItemLayout>
358 )
359 }}
360 />
361 ))}
362 {/* <FormMessage /> */}
363 </FormItemLayout>
364 )}
365 />
366 </SheetSection>
367
368 <SheetSection>
369 <FormField
370 control={form.control}
371 name="type"
372 render={({ field }) => (
373 <FormItemLayout
374 className="space-y-3"
375 label="Notify me about..."
376 description="I am descript"
377 layout="horizontal"
378 >
379 <FormControl>
380 <RadioGroup
381 onValueChange={field.onChange}
382 defaultValue={field.value}
383 className="flex flex-col space-y-1"
384 >
385 <FormItemLayout
386 className="flex items-center space-x-3 space-y-0"
387 label="All new messages"
388 layout="flex"
389 hideMessage
390 >
391 <FormControl>
392 <RadioGroupItem value="all" />
393 </FormControl>
394 </FormItemLayout>
395 <FormItemLayout
396 className="flex items-center space-x-3 space-y-0"
397 label="Direct messages and mentions"
398 layout="flex"
399 hideMessage
400 >
401 <FormControl>
402 <RadioGroupItem value="mentions" />
403 </FormControl>
404 </FormItemLayout>
405 <FormItemLayout
406 className="flex items-center space-x-3 space-y-0"
407 label="Nothing"
408 layout="flex"
409 hideMessage
410 >
411 <FormControl>
412 <RadioGroupItem value="none" />
413 </FormControl>
414 </FormItemLayout>
415 </RadioGroup>
416 </FormControl>
417 </FormItemLayout>
418 )}
419 />
420 </SheetSection>
421 <SheetFooter>
422 <Button type="default">Cancel</Button>
423 <Button htmlType="submit">Submit</Button>
424 </SheetFooter>
425 </form>
426 </Form>
427 </SheetContent>
428 </Sheet>
429 )
430}