CreatePublishableAPIKeyDialog.tsx142 lines · main
1import { zodResolver } from '@hookform/resolvers/zod'
2import { Plus } from 'lucide-react'
3import { useParams } from 'next/navigation'
4import { parseAsString, useQueryState } from 'nuqs'
5import { SubmitHandler, useForm } from 'react-hook-form'
6import {
7 Button,
8 Dialog,
9 DialogContent,
10 DialogDescription,
11 DialogFooter,
12 DialogHeader,
13 DialogSection,
14 DialogSectionSeparator,
15 DialogTitle,
16 DialogTrigger,
17 Form,
18 FormControl,
19 FormField,
20 Input,
21} from 'ui'
22import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
23import * as z from 'zod'
24
25import { useAPIKeyCreateMutation } from '@/data/api-keys/api-key-create-mutation'
26
27const FORM_ID = 'create-publishable-api-key'
28const SCHEMA = z.object({
29 name: z.string(),
30 description: z.string().trim(),
31})
32
33export interface CreatePublishableAPIKeyDialogProps {
34 projectRef: string
35}
36
37export const CreatePublishableAPIKeyDialog = () => {
38 const params = useParams()
39 const projectRef = params?.ref as string
40
41 const [visible, setVisible] = useQueryState('new', parseAsString.withDefault(''))
42
43 const onOpenChange = (value: boolean) => {
44 if (value) setVisible('publishable')
45 else setVisible('')
46 }
47
48 const defaultValues = { name: '', description: '' }
49
50 const form = useForm<z.infer<typeof SCHEMA>>({
51 resolver: zodResolver(SCHEMA as any),
52 defaultValues: {
53 name: '',
54 description: '',
55 },
56 })
57
58 const { mutate: createAPIKey, isPending: isCreatingAPIKey } = useAPIKeyCreateMutation()
59
60 const onSubmit: SubmitHandler<z.infer<typeof SCHEMA>> = async (values) => {
61 createAPIKey(
62 {
63 projectRef,
64 type: 'publishable',
65 name: values.name,
66 description: values.description,
67 },
68 {
69 onSuccess: () => {
70 form.reset(defaultValues)
71 onOpenChange(false)
72 },
73 }
74 )
75 }
76
77 return (
78 <Dialog open={visible === 'publishable'} onOpenChange={onOpenChange}>
79 <DialogTrigger asChild>
80 <Button type="default" icon={<Plus />}>
81 New publishable key
82 </Button>
83 </DialogTrigger>
84 <DialogContent>
85 <DialogHeader>
86 <DialogTitle>Create new publishable API key</DialogTitle>
87 <DialogDescription>
88 Publishable API keys are used to authorize requests to your project from the web, mobile
89 or desktop apps, CLIs or other public components of your application. They are safe to
90 be published online and embedded in code.
91 </DialogDescription>
92 </DialogHeader>
93 <DialogSectionSeparator />
94 <DialogSection className="flex flex-col gap-4">
95 <Form {...form}>
96 <form
97 className="flex flex-col gap-4"
98 id={FORM_ID}
99 onSubmit={form.handleSubmit(onSubmit)}
100 >
101 <FormField
102 key="name"
103 name="name"
104 control={form.control}
105 render={({ field }) => (
106 <FormItemLayout
107 label="Name"
108 description="A short name of lowercase alphanumeric characters and underscore, must start with letter or underscore."
109 >
110 <FormControl>
111 <Input {...field} />
112 </FormControl>
113 </FormItemLayout>
114 )}
115 />
116 <FormField
117 key="description"
118 name="description"
119 control={form.control}
120 render={({ field }) => (
121 <FormItemLayout
122 label="Description"
123 description="Provide a description about what this key is used for."
124 >
125 <FormControl>
126 <Input {...field} placeholder="(Optional)" />
127 </FormControl>
128 </FormItemLayout>
129 )}
130 />
131 </form>
132 </Form>
133 </DialogSection>
134 <DialogFooter>
135 <Button form={FORM_ID} htmlType="submit" loading={isCreatingAPIKey}>
136 Create Publishable API key
137 </Button>
138 </DialogFooter>
139 </DialogContent>
140 </Dialog>
141 )
142}