Repository: supabase/supabase
File: apps/studio/components/interfaces/Support/LinkSupportTicketForm.tsx (TypeScript)

Code before:
  conversationId: string
  onSuccess: () => void
}

export function LinkSupportTicketForm({ conversationId, onSuccess }: LinkSupportTicketFormProps) {
  const { data: organizations } = useOrganizationsQuery()

  const form = useForm<LinkSupportTicketFormValues>({
    resolver: zodResolver(LinkSupportTicketFormSchema),
    defaultValues: {
      conversation_id: conversationId,
      organizationSlug: NO_ORG_MARKER,
      projectRef: NO_PROJECT_MARKER,
      category: '' as any,
      allowSupportAccess: true,
    },
    mode: 'onSubmit',
    reValidateMode: 'onBlur',
  })

  const { mutate: linkSupportTicket, isLoading } = useLinkSupportTicketMutation({
    onSuccess: () => {
      toast.success('Support ticket linked successfully!')
      onSuccess()
    },
    onError: (error) => {
      let errorMessage = error.message
      try {
        const parsed = JSON.parse(error.message)
        errorMessage = parsed?._error?.message || parsed?.message || error.message
      } catch {
        // If parsing fails, use the original message
      }
      toast.error(`Failed to link support ticket: ${errorMessage}`)
    },
  })

  const organizationSlug = form.watch('organizationSlug')
  const selectedOrgSlug = organizationSlug === NO_ORG_MARKER ? null : organizationSlug

  const onSubmit: SubmitHandler<LinkSupportTicketFormValues> = (values) => {
    if (!organizations) {
      toast.error('Organizations not loaded. Please try again.')
      return
    }

    const selectedOrg = organizations.find((org) => org.slug === values.organizationSlug)
    if (!selectedOrg) {
      toast.error('Selected organization not found. Please try again.')
      return
    }

Review comment (suggestion):
I added this as the error message we typically receive is a error message from front that is embedded in a json structure. Seemed reasonable to handle the error this way is it is localized to this link form

Code after:
  const form = useForm<LinkSupportTicketFormValues>({
    resolver: zodResolver(LinkSupportTicketFormSchema),
    defaultValues: {
      conversation_id: conversationId,
      organizationSlug: NO_ORG_MARKER,
      projectRef: NO_PROJECT_MARKER,
      category: '' as any,
      allowSupportAccess: true,
    },
    mode: 'onSubmit',
    reValidateMode: 'onBlur',
  })

  const { category, organizationSlug, projectRef } = form.watch()
  const selectedOrgSlug = organizationSlug === NO_ORG_MARKER ? null : organizationSlug
  const selectedProjectRef = projectRef === NO_PROJECT_MARKER ? null : projectRef
  const subscriptionPlanId = getOrgSubscriptionPlan(organizations, selectedOrgSlug)

  const { mutate: linkSupportTicket, isPending } = useLinkSupportTicketMutation({
    onSuccess: () => {
      toast.success('Support ticket linked successfully!')
      onSuccess()
    },
    onError: (error) => {
      let errorMessage = error.message
      try {
        const parsed = JSON.parse(error.message)
        errorMessage = parsed?._error?.message || parsed?.message || error.message
      } catch {}
      // If parsing fails, use the original message
      toast.error(`Failed to link support ticket: ${errorMessage}`)
    },
  })

  const onSubmit: SubmitHandler<LinkSupportTicketFormValues> = (values) => {
    if (!organizations) return toast.error('Organizations not loaded. Please try again.')

    const selectedOrg = organizations.find((org) => org.slug === values.organizationSlug)
    if (!selectedOrg) return toast.error('Selected organization not found. Please try again.')

    linkSupportTicket({
      conversation_id: values.conversation_id,
      org_id: selectedOrg.id,
      project_ref:
        values.projectRef && values.projectRef !== NO_PROJECT_MARKER
          ? values.projectRef
          : undefined,
      category: values.category,
      allow_support_access: SUPPORT_ACCESS_CATEGORIES.includes(values.category)
        ? values.allowSupportAccess
        : false,