CreatePublishableAPIKeyDialog.tsx 4.2 KB

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