Files
supabase/apps/studio/components/interfaces/APIKeys/CreatePublishableAPIKeyDialog.tsx
Joshen Lim 5e2e6690ad chore(studio): Deprecate usage of useQueryStateWithSelect in more files (#42500)
## Context

Related to FE-2461

Just following from the previous part
[here](https://github.com/supabase/supabase/pull/41819)
PR removes the usage of `useQueryStateWithSelect` in
- Publishable API Keys (Delete)
- Secret API Keys (Delete)
- Auth Hooks (Edit)
- Database Indexes (Edit + Delete)
-
Ensures that the appropriate behaviours are in place too
- Toast should show when landing on a page with an invalid ID param that
entity doesn't exist
- Toast should not show when deleting the param (which
useQueryStateWithSelect was using useRef as a workaround prior)

## To test

- [ ] API keys (Both publishable and secret key)
  - URL updates when deleting a key
  - Refresh the page, delete dialog should open with the right key
- Update the query param to something invalid, should see the "not
found" toast
  - Delete a key, should only see a success toast
- [ ] Auth Hooks
  - URL updates when adding / edit a hook
  - Refresh the page, panel should open with the right hook
- Update the query param to something invalid, should see the "not
found" toast
- [ ] Database Indexes
  - URL updates when editing/deleting an index
  - Refresh the page, delete dialog should open with the right index
- Update the query param to something invalid, should see the "not
found" toast
  - Delete an index, should only see a success toast

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Improved error handling and user notifications when API keys, hooks,
or indexes are deleted or become unavailable; users now see clear toasts
when a target item cannot be found.
* **Refactoring**
* Internal state and dialog visibility handling for API keys, hooks, and
database indexes have been simplified to make UI flows more reliable and
consistent.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-02-06 12:32:53 +08:00

142 lines
4.3 KiB
TypeScript

import { zodResolver } from '@hookform/resolvers/zod'
import { useAPIKeyCreateMutation } from 'data/api-keys/api-key-create-mutation'
import { Plus } from 'lucide-react'
import { useParams } from 'next/navigation'
import { parseAsString, useQueryState } from 'nuqs'
import { SubmitHandler, useForm } from 'react-hook-form'
import {
Button,
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogSection,
DialogSectionSeparator,
DialogTitle,
DialogTrigger,
Form_Shadcn_,
FormControl_Shadcn_,
FormField_Shadcn_,
Input_Shadcn_,
} from 'ui'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import * as z from 'zod'
const FORM_ID = 'create-publishable-api-key'
const SCHEMA = z.object({
name: z.string(),
description: z.string().trim(),
})
export interface CreatePublishableAPIKeyDialogProps {
projectRef: string
}
export const CreatePublishableAPIKeyDialog = () => {
const params = useParams()
const projectRef = params?.ref as string
const [visible, setVisible] = useQueryState('new', parseAsString.withDefault(''))
const onOpenChange = (value: boolean) => {
if (value) setVisible('publishable')
else setVisible('')
}
const defaultValues = { name: '', description: '' }
const form = useForm<z.infer<typeof SCHEMA>>({
resolver: zodResolver(SCHEMA),
defaultValues: {
name: '',
description: '',
},
})
const { mutate: createAPIKey, isPending: isCreatingAPIKey } = useAPIKeyCreateMutation()
const onSubmit: SubmitHandler<z.infer<typeof SCHEMA>> = async (values) => {
createAPIKey(
{
projectRef,
type: 'publishable',
name: values.name,
description: values.description,
},
{
onSuccess: () => {
form.reset(defaultValues)
onOpenChange(false)
},
}
)
}
return (
<Dialog open={visible === 'publishable'} onOpenChange={onOpenChange}>
<DialogTrigger asChild>
<Button type="default" icon={<Plus />}>
New publishable key
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Create new publishable API key</DialogTitle>
<DialogDescription>
Publishable API keys are used to authorize requests to your project from the web, mobile
or desktop apps, CLIs or other public components of your application. They are safe to
be published online and embedded in code.
</DialogDescription>
</DialogHeader>
<DialogSectionSeparator />
<DialogSection className="flex flex-col gap-4">
<Form_Shadcn_ {...form}>
<form
className="flex flex-col gap-4"
id={FORM_ID}
onSubmit={form.handleSubmit(onSubmit)}
>
<FormField_Shadcn_
key="name"
name="name"
control={form.control}
render={({ field }) => (
<FormItemLayout
label="Name"
description="A short name of lowercase alphanumeric characters and underscore, must start with letter or underscore."
>
<FormControl_Shadcn_>
<Input_Shadcn_ {...field} />
</FormControl_Shadcn_>
</FormItemLayout>
)}
/>
<FormField_Shadcn_
key="description"
name="description"
control={form.control}
render={({ field }) => (
<FormItemLayout
label="Description"
description="Provide a description about what this key is used for."
>
<FormControl_Shadcn_>
<Input_Shadcn_ {...field} placeholder="(Optional)" />
</FormControl_Shadcn_>
</FormItemLayout>
)}
/>
</form>
</Form_Shadcn_>
</DialogSection>
<DialogFooter>
<Button form={FORM_ID} htmlType="submit" loading={isCreatingAPIKey}>
Create Publishable API key
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
)
}