import * as Sentry from '@sentry/nextjs' import { Loader2, Wrench } from 'lucide-react' import Link from 'next/link' import { useCallback, useReducer, type Dispatch, type PropsWithChildren } from 'react' import type { UseFormReturn } from 'react-hook-form' import SVG from 'react-inlinesvg' import { toast } from 'sonner' import { Button, cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui' import { Admonition } from 'ui-patterns/Admonition' import { AIAssistantOption } from './AIAssistantOption' import { DiscordCTACard } from './DiscordCTACard' import { IncidentAdmonition } from './IncidentAdmonition' import { Success } from './Success' import type { ExtendedSupportCategories } from './Support.constants' import type { SupportFormValues } from './SupportForm.schema' import { createInitialSupportFormState, supportFormReducer, type SupportFormActions, type SupportFormState, } from './SupportForm.state' import { NO_PROJECT_MARKER } from './SupportForm.utils' import { SupportFormV2 } from './SupportFormV2' import { DEFAULT_STATUS_PAGE_URL, getSupportStatusLabel } from './SupportStatus.utils' import { useSupportForm } from './useSupportForm' import { useSupportStatus } from './useSupportStatus' import CopyButton from '@/components/ui/CopyButton' import { useStateTransition } from '@/hooks/misc/useStateTransition' import { BASE_PATH, DOCS_URL } from '@/lib/constants' import { useTrack } from '@/lib/telemetry/track' export { SupportForm, SupportFormStatusButton } from './SupportSidebarForm' function useSupportFormTelemetry() { const track = useTrack() return useCallback( ({ projectRef, orgSlug, category, }: { projectRef: string | undefined orgSlug: string | undefined category: ExtendedSupportCategories }) => track( 'support_ticket_submitted', { ticketCategory: category }, { project: projectRef, organization: orgSlug } ), [track] ) } export function SupportFormPage() { return } function SupportFormPageContent() { const [state, dispatch] = useReducer(supportFormReducer, undefined, createInitialSupportFormState) const { form, initialError, projectRef, orgSlug } = useSupportForm(dispatch) const supportStatus = useSupportStatus() const hasActiveIncidents = supportStatus.status === 'success' && supportStatus.hasActiveIncidents const admonition = supportStatus.status === 'success' ? supportStatus.admonition : null const statusPageUrl = supportStatus.status === 'success' ? supportStatus.pageUrl : DEFAULT_STATUS_PAGE_URL const sendTelemetry = useSupportFormTelemetry() useStateTransition(state, 'submitting', 'success', (_, curr) => { toast.success('Support request sent. Thank you!') sendTelemetry({ projectRef: curr.sentProjectRef, orgSlug: curr.sentOrgSlug, category: curr.sentCategory, }) }) useStateTransition(state, 'submitting', 'error', (_, curr) => { toast.error(`Failed to submit support ticket: ${curr.message}`) if (curr.code !== 429) { Sentry.captureMessage(`Failed to submit Support Form: ${curr.message}`) } dispatch({ type: 'RETURN_TO_EDITING' }) }) const isSuccess = state.type === 'success' return ( {!isSuccess && !hasActiveIncidents && (
)} {!isSuccess && }
) } function SupportFormWrapper({ children }: PropsWithChildren) { return (
{children}
) } function SupportFormHeader() { const supportStatus = useSupportStatus() const isLoading = supportStatus.status === 'pending' const isIncident = supportStatus.status === 'success' && supportStatus.hasActiveIncidents const statusPageUrl = supportStatus.status === 'success' ? supportStatus.pageUrl : DEFAULT_STATUS_PAGE_URL return (

Supabase support

Check the Supabase status page
) } interface SupportFormDirectEmailInfoProps { projectRef: string | null } function SupportFormDirectEmailInfo({ projectRef }: SupportFormDirectEmailInfoProps) { const hasProjectRef = projectRef && projectRef !== NO_PROJECT_MARKER return (

Please email us directly. Include your project ID and as much information as possible.

Email:{' '} support@supabase.com toast.success('Copied email address to clipboard')} />

{hasProjectRef && (

Project ID:{' '} {projectRef} toast.success('Copied project ID to clipboard')} />

)} } /> ) } interface SupportFromBodyProps { form: UseFormReturn state: SupportFormState dispatch: Dispatch initialError: string | null selectedProjectRef: string | null } function SupportFormBody({ form, state, dispatch, initialError, selectedProjectRef, }: SupportFromBodyProps) { const isSuccess = state.type === 'success' return (
{isSuccess ? ( ) : ( )}
) }