HelpPanel.tsx132 lines · main
1import { IS_PLATFORM } from 'common'
2import { ChevronLeft, X } from 'lucide-react'
3import Image from 'next/image'
4import { useRouter } from 'next/router'
5import { useState } from 'react'
6import SVG from 'react-inlinesvg'
7import { Button } from 'ui'
8
9import { ASSISTANT_SUGGESTIONS } from './HelpPanel.constants'
10import { HelpSection } from './HelpSection'
11import type { SupportFormUrlKeys } from '@/components/interfaces/Support/SupportForm.utils'
12import {
13 SupportForm,
14 SupportFormStatusButton,
15} from '@/components/interfaces/Support/SupportSidebarForm'
16import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
17import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
18import { useAiAssistantStateSnapshot } from '@/state/ai-assistant-state'
19import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state'
20
21export const HelpPanel = ({
22 onClose,
23 projectRef,
24 supportLinkQueryParams,
25}: {
26 onClose: () => void
27 projectRef: string | undefined
28 supportLinkQueryParams: Partial<SupportFormUrlKeys> | undefined
29}) => {
30 const snap = useAiAssistantStateSnapshot()
31 const { openSidebar, closeSidebar } = useSidebarManagerSnapshot()
32 const router = useRouter()
33 const [view, setView] = useState<'home' | 'support'>('home')
34 const isSupportView = view === 'support'
35 const openAssistant = () => {
36 onClose()
37 openSidebar(SIDEBAR_KEYS.AI_ASSISTANT)
38 snap.newChat(ASSISTANT_SUGGESTIONS)
39 }
40
41 return (
42 <div className="flex h-full flex-col overflow-hidden">
43 <div className="flex h-(--header-height) items-center justify-between gap-2 border-b pl-4 pr-3">
44 <div className="flex min-w-0 items-center gap-1.5 text-xs">
45 {isSupportView && (
46 <ButtonTooltip
47 type="text"
48 className="h-7 w-7"
49 onClick={() => setView('home')}
50 icon={<ChevronLeft strokeWidth={1.5} />}
51 tooltip={{ content: { side: 'bottom', text: 'Back' } }}
52 />
53 )}
54 <span className="truncate">{isSupportView ? 'Contact support' : 'Help & Support'}</span>
55 </div>
56 <div className="flex items-center gap-2">
57 <SupportFormStatusButton />
58 <ButtonTooltip
59 type="text"
60 className="w-7 h-7"
61 onClick={() => closeSidebar(SIDEBAR_KEYS.HELP_PANEL)}
62 icon={<X strokeWidth={1.5} />}
63 tooltip={{ content: { side: 'bottom', text: 'Close' } }}
64 />
65 </div>
66 </div>
67 <div className="flex-1 overflow-hidden">
68 {isSupportView ? (
69 <SupportForm
70 initialParams={supportLinkQueryParams}
71 onFinish={() => {
72 setView('home')
73 }}
74 />
75 ) : (
76 <div className="flex h-full flex-col overflow-y-auto pb-5">
77 <HelpSection
78 excludeIds={['discord']}
79 isPlatform={IS_PLATFORM}
80 projectRef={projectRef}
81 supportLinkQueryParams={supportLinkQueryParams}
82 onAssistantClick={openAssistant}
83 onSupportClick={() => {
84 setView('support')
85 return false
86 }}
87 />
88 <div className="flex flex-col gap-4 border-t pt-5">
89 <div className="px-5 flex flex-col gap-0.5">
90 <h5 className="text-foreground">Community support</h5>
91 <p className="text-xs text-foreground-lighter text-balance">
92 Our Discord community can help with code-related issues. Many questions are
93 answered in minutes.
94 </p>
95 </div>
96 <div className="px-5">
97 <div
98 className="relative space-y-2 overflow-hidden rounded-sm px-4 py-4 pb-12 shadow-md"
99 style={{ background: '#404EED' }}
100 >
101 <a
102 href="https://discord.supabase.com"
103 target="_blank"
104 rel="noreferrer"
105 className="group dark block cursor-pointer"
106 >
107 <Image
108 className="absolute left-0 top-0 opacity-50 transition-opacity group-hover:opacity-40"
109 src={`${router.basePath}/img/support/discord-bg-small.jpg`}
110 layout="fill"
111 objectFit="cover"
112 alt="Discord illustration"
113 />
114 <Button
115 type="secondary"
116 size="tiny"
117 icon={
118 <SVG src={`${router.basePath}/img/discord-icon.svg`} className="h-4 w-4" />
119 }
120 >
121 <span style={{ color: '#404EED' }}>Join us on Discord</span>
122 </Button>
123 </a>
124 </div>
125 </div>
126 </div>
127 </div>
128 )}
129 </div>
130 </div>
131 )
132}