HelpPanel.tsx 4.9 KB

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