OverviewLearnMore.tsx 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import { useParams } from 'common'
  2. import { Logs } from 'icons'
  3. import { BookOpen } from 'lucide-react'
  4. import { useTheme } from 'next-themes'
  5. import Link from 'next/link'
  6. import { useEffect, useState } from 'react'
  7. import { AiIconAnimation, Button, Card, CardContent, CardHeader, CardTitle } from 'ui'
  8. import { Image } from 'ui-patterns/Image'
  9. import {
  10. PageSection,
  11. PageSectionContent,
  12. PageSectionMeta,
  13. PageSectionSummary,
  14. PageSectionTitle,
  15. } from 'ui-patterns/PageSection'
  16. import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
  17. import { BASE_PATH, DOCS_URL } from '@/lib/constants'
  18. import { useAiAssistantStateSnapshot } from '@/state/ai-assistant-state'
  19. import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state'
  20. export const OverviewLearnMore = () => {
  21. const [isMounted, setIsMounted] = useState(false)
  22. const { ref } = useParams()
  23. const aiSnap = useAiAssistantStateSnapshot()
  24. const { openSidebar } = useSidebarManagerSnapshot()
  25. const { resolvedTheme } = useTheme()
  26. useEffect(() => {
  27. setIsMounted(true)
  28. }, [])
  29. const isLight = resolvedTheme === 'light'
  30. const LearnMoreCards = [
  31. {
  32. label: 'Docs',
  33. title: 'Auth docs',
  34. description: 'Read more on Briven auth, managing users and more.',
  35. image: isLight
  36. ? `${BASE_PATH}/img/auth-overview/auth-overview-docs-light.jpg`
  37. : `${BASE_PATH}/img/auth-overview/auth-overview-docs.jpg`,
  38. actions: [
  39. {
  40. label: 'Docs',
  41. href: `${DOCS_URL}/guides/auth`,
  42. icon: <BookOpen />,
  43. },
  44. ],
  45. },
  46. {
  47. label: 'Assistant',
  48. title: 'Explain auth errors',
  49. description: 'Our Assistant can help you debug and fix authentication errors.',
  50. image: isLight
  51. ? `${BASE_PATH}/img/auth-overview/auth-overview-assistant-light.jpg`
  52. : `${BASE_PATH}/img/auth-overview/auth-overview-assistant.jpg`,
  53. actions: [
  54. {
  55. label: 'Ask Assistant',
  56. onClick: () => {
  57. openSidebar(SIDEBAR_KEYS.AI_ASSISTANT)
  58. aiSnap.newChat({
  59. name: 'Auth Help',
  60. initialInput:
  61. 'Look at my logs related to Briven Auth and help me debug the recent errors.',
  62. suggestions: {
  63. title: 'I can help you with authentication issues. Here are some common problems:',
  64. prompts: [
  65. {
  66. label: 'Login Issues',
  67. description: 'Why are users unable to log in to my app?',
  68. },
  69. {
  70. label: 'JWT Problems',
  71. description: 'Help me understand and fix JWT token issues',
  72. },
  73. {
  74. label: 'RLS Policies',
  75. description: 'Explain my Row Level Security policies and fix issues',
  76. },
  77. {
  78. label: 'Provider Setup',
  79. description: 'Help me configure OAuth providers correctly',
  80. },
  81. ],
  82. },
  83. })
  84. },
  85. icon: <AiIconAnimation size={14} />,
  86. },
  87. ],
  88. },
  89. {
  90. label: 'Logs',
  91. title: 'Dive into the logs',
  92. description: 'Auth logs provide a deeper view into your auth requests.',
  93. image: isLight
  94. ? `${BASE_PATH}/img/auth-overview/auth-overview-logs-light.jpg`
  95. : `${BASE_PATH}/img/auth-overview/auth-overview-logs.jpg`,
  96. actions: [
  97. {
  98. label: 'Go to logs',
  99. href: `/project/${ref}/logs/auth-logs`,
  100. icon: <Logs />,
  101. },
  102. ],
  103. },
  104. ]
  105. if (!isMounted) return null
  106. return (
  107. <PageSection>
  108. <PageSectionMeta>
  109. <PageSectionSummary>
  110. <PageSectionTitle>Learn more</PageSectionTitle>
  111. </PageSectionSummary>
  112. </PageSectionMeta>
  113. <PageSectionContent>
  114. <div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
  115. {LearnMoreCards.map((card) => (
  116. <Card key={card.label} className="relative">
  117. <CardHeader className="absolute top-0 left-0 right-0 border-b-0">
  118. <CardTitle className="text-foreground-lighter">{card.label}</CardTitle>
  119. </CardHeader>
  120. <CardContent className="p-0">
  121. <div className="bg-black/20 flex w-full">
  122. <Image
  123. src={card.image && card?.image}
  124. alt={card.title}
  125. width={620}
  126. height={324}
  127. className="object-fit"
  128. />
  129. </div>
  130. <div className="p-4 flex flex-col">
  131. <div className="flex flex-col gap-1 mb-4 flex-1">
  132. <h4>{card.title}</h4>
  133. <p className="text-sm text-foreground-lighter">{card.description}</p>
  134. </div>
  135. <div className="flex flex-col gap-2 items-start mt-auto">
  136. {card.actions.map((action) => {
  137. if ('href' in action) {
  138. return (
  139. <Button
  140. key={action.label}
  141. className="inline-flex"
  142. type="default"
  143. icon={action.icon}
  144. asChild
  145. >
  146. <Link href={action.href} className="inline-flex">
  147. {action.label}
  148. </Link>
  149. </Button>
  150. )
  151. } else {
  152. return (
  153. <Button
  154. key={action.label}
  155. onClick={action.onClick}
  156. type="default"
  157. className="inline-flex"
  158. icon={action.icon}
  159. >
  160. {action.label}
  161. </Button>
  162. )
  163. }
  164. })}
  165. </div>
  166. </div>
  167. </CardContent>
  168. </Card>
  169. ))}
  170. </div>
  171. </PageSectionContent>
  172. </PageSection>
  173. )
  174. }