diff --git a/apps/studio/components/interfaces/Support/AIAssistantOption.tsx b/apps/studio/components/interfaces/Support/AIAssistantOption.tsx index 7d1a3372548..f0381dbeab0 100644 --- a/apps/studio/components/interfaces/Support/AIAssistantOption.tsx +++ b/apps/studio/components/interfaces/Support/AIAssistantOption.tsx @@ -2,25 +2,19 @@ import { AnimatePresence, motion } from 'framer-motion' import { MessageSquare } from 'lucide-react' import Link from 'next/link' import { useCallback, useEffect, useState } from 'react' -// End of third-party imports import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { Button } from 'ui' +import { AiIconAnimation, Button } from 'ui' import { NO_ORG_MARKER, NO_PROJECT_MARKER } from './SupportForm.utils' interface AIAssistantOptionProps { projectRef?: string | null organizationSlug?: string | null - isCondensed?: boolean } -export const AIAssistantOption = ({ - projectRef, - organizationSlug, - isCondensed = false, -}: AIAssistantOptionProps) => { +export const AIAssistantOption = ({ projectRef, organizationSlug }: AIAssistantOptionProps) => { const { mutate: sendEvent } = useSendEventMutation() - const [isVisible, setIsVisible] = useState(isCondensed) + const [isVisible, setIsVisible] = useState(false) useEffect(() => { const timer = setTimeout(() => setIsVisible(true), 800) @@ -46,57 +40,56 @@ export const AIAssistantOption = ({ if (!organizationSlug || organizationSlug === NO_ORG_MARKER) return null return ( - + {isVisible && ( - -
+
-

Try the AI Assistant

+
Try Supabase Assistant

- Ask the AI assistant to help you with your support issue + Ask our AI assistant to help you with your support issue.

-
- {!isCondensed && ( -
-
-
-
- -
-
-

- Hi! I'm your AI assistant. How can I help you today? -

-
+ {/* Decorative background */} +
+
+
+
+
-
-
-

- I can help you with database queries, API endpoints, or any other technical - questions you might have. -

-
+
+

+ Hi! I'm your AI assistant. How can I help you today? +

+
+
+
+
+

+ I can help you with database queries, API endpoints, or any other technical + questions you might have. +

-
- )} +
+
- + )} ) diff --git a/apps/studio/components/interfaces/Support/DiscordCTACard.tsx b/apps/studio/components/interfaces/Support/DiscordCTACard.tsx new file mode 100644 index 00000000000..376db759eca --- /dev/null +++ b/apps/studio/components/interfaces/Support/DiscordCTACard.tsx @@ -0,0 +1,81 @@ +import { useOrganizationsQuery } from 'data/organizations/organizations-query' +import { AnimatePresence, motion } from 'framer-motion' +import Link from 'next/link' +import router from 'next/router' +import { useEffect, useState } from 'react' +import SVG from 'react-inlinesvg' +import { Button } from 'ui' +import { NO_ORG_MARKER } from './SupportForm.utils' + +interface DiscordCTACardProps { + organizationSlug?: string | null +} + +export const DiscordCTACard = ({ organizationSlug }: DiscordCTACardProps) => { + const { data: organizations } = useOrganizationsQuery() + const [isVisible, setIsVisible] = useState(false) + + const selectedOrg = organizations?.find((org) => org.slug === organizationSlug) + const isFreePlan = selectedOrg?.plan.id === 'free' + + useEffect(() => { + const timer = setTimeout(() => setIsVisible(true), 800) + return () => clearTimeout(timer) + }, []) + + return ( + + {isVisible && isFreePlan && organizationSlug !== NO_ORG_MARKER && ( + +
+ {/* Decorative background */} +
+ {/* Content */} +
+
+
+
Ask the Discord community
+

+ Many code-related questions are answered within minutes. +

+
+ + + + +
+
+
+ + )} + + ) +} diff --git a/apps/studio/components/interfaces/Support/SupportFormPage.tsx b/apps/studio/components/interfaces/Support/SupportFormPage.tsx index 4043ef900a1..2034a4067e5 100644 --- a/apps/studio/components/interfaces/Support/SupportFormPage.tsx +++ b/apps/studio/components/interfaces/Support/SupportFormPage.tsx @@ -10,12 +10,14 @@ import { toast } from 'sonner' import CopyButton from 'components/ui/CopyButton' import InformationBox from 'components/ui/InformationBox' import { InlineLink, InlineLinkClassName } from 'components/ui/InlineLink' +import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { usePlatformStatusQuery } from 'data/platform/platform-status-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useStateTransition } from 'hooks/misc/useStateTransition' import { BASE_PATH, DOCS_URL } from 'lib/constants' import { Button, cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui' import { AIAssistantOption } from './AIAssistantOption' +import { DiscordCTACard } from './DiscordCTACard' import { HighlightProjectRefProvider, useHighlightProjectRefContext } from './HighlightContext' import { Success } from './Success' import type { ExtendedSupportCategories } from './Support.constants' @@ -65,9 +67,12 @@ export function SupportFormPage() { } function SupportFormPageContent() { + const { data: organizations } = useOrganizationsQuery() const [state, dispatch] = useReducer(supportFormReducer, undefined, createInitialSupportFormState) const { form, initialError, projectRef, orgSlug } = useSupportForm(dispatch) + const selectedOrg = organizations?.find((org) => org.slug === orgSlug) + const isFreePlan = selectedOrg?.plan.id === 'free' const sendTelemetry = useSupportFormTelemetry() useStateTransition(state, 'submitting', 'success', (_, curr) => { @@ -88,7 +93,12 @@ function SupportFormPageContent() { return ( - + +
+ + +
+ + { + takeBreadcrumbSnapshot() + props.onClick?.(event) + }} + > {children} ) diff --git a/apps/studio/components/interfaces/Support/__tests__/SupportFormPage.test.tsx b/apps/studio/components/interfaces/Support/__tests__/SupportFormPage.test.tsx index 6dcb98600a1..2d2e3d9ddb4 100644 --- a/apps/studio/components/interfaces/Support/__tests__/SupportFormPage.test.tsx +++ b/apps/studio/components/interfaces/Support/__tests__/SupportFormPage.test.tsx @@ -1036,7 +1036,7 @@ describe('SupportFormPage', () => { renderSupportFormPage() await waitFor(() => { - expect(screen.getByText('Try the AI Assistant')).toBeInTheDocument() + expect(screen.getByText('Try Supabase Assistant')).toBeInTheDocument() }) }) diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx index a2565cdd617..6b0f47d34af 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx @@ -134,17 +134,22 @@ export const HelpPopover = () => { {IS_PLATFORM && ( <> } - asChild > Supabase status - }> - Contact support + }> + setIsOpen(false)} + > + Contact support + )}