InviteUserModal.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import { zodResolver } from '@hookform/resolvers/zod'
  2. import { PermissionAction } from '@supabase/shared-types/out/constants'
  3. import { useParams } from 'common'
  4. import { SubmitHandler, useForm } from 'react-hook-form'
  5. import { toast } from 'sonner'
  6. import { Button, Form, FormControl, FormField, Input, Modal } from 'ui'
  7. import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
  8. import * as z from 'zod'
  9. import { useUserInviteMutation } from '@/data/auth/user-invite-mutation'
  10. import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
  11. export type InviteUserModalProps = {
  12. visible: boolean
  13. setVisible: (visible: boolean) => void
  14. }
  15. const formSchema = z.object({
  16. email: z.string().min(1, 'Please enter a valid email').email('Please enter a valid email'),
  17. })
  18. const formId = 'invite-user-form'
  19. const InviteUserModal = ({ visible, setVisible }: InviteUserModalProps) => {
  20. const { ref: projectRef } = useParams()
  21. const form = useForm<z.infer<typeof formSchema>>({
  22. resolver: zodResolver(formSchema as any),
  23. defaultValues: {
  24. email: '',
  25. },
  26. })
  27. const handleToggle = () => setVisible(!visible)
  28. const { mutate: inviteUser, isPending: isInviting } = useUserInviteMutation({
  29. onSuccess: (_, variables) => {
  30. toast.success(`Sent invite email to ${variables.email}`)
  31. setVisible(false)
  32. },
  33. })
  34. const { can: canInviteUsers } = useAsyncCheckPermissions(
  35. PermissionAction.AUTH_EXECUTE,
  36. 'invite_user'
  37. )
  38. const onInviteUser: SubmitHandler<z.infer<typeof formSchema>> = async (values) => {
  39. if (!projectRef) return console.error('Project ref is required')
  40. inviteUser(
  41. { projectRef, email: values.email },
  42. {
  43. onSuccess: () => {
  44. form.reset()
  45. },
  46. }
  47. )
  48. }
  49. return (
  50. <Modal
  51. hideFooter
  52. size="small"
  53. key="invite-user-modal"
  54. visible={visible}
  55. header="Invite a new user"
  56. onCancel={handleToggle}
  57. >
  58. <Form {...form}>
  59. <Modal.Content>
  60. <form id={formId} onSubmit={form.handleSubmit(onInviteUser)} noValidate>
  61. <FormField
  62. control={form.control}
  63. name="email"
  64. render={({ field }) => (
  65. <FormItemLayout layout="vertical" label="User email">
  66. <FormControl className="relative col-span-6">
  67. <Input {...field} />
  68. </FormControl>
  69. </FormItemLayout>
  70. )}
  71. />
  72. </form>
  73. </Modal.Content>
  74. <Modal.Content>
  75. <Button
  76. form={formId}
  77. block
  78. size="small"
  79. htmlType="submit"
  80. loading={isInviting}
  81. disabled={!canInviteUsers || isInviting}
  82. >
  83. Invite user
  84. </Button>
  85. </Modal.Content>
  86. </Form>
  87. </Modal>
  88. )
  89. }
  90. export default InviteUserModal