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