TroubleshootingSections.tsx174 lines · main
1'use client'
2
3import { ExternalLink } from 'lucide-react'
4import { useState } from 'react'
5import { AccordionContent, AccordionItem, AccordionTrigger, Button } from 'ui'
6
7import { RestartProjectDialog } from './RestartProjectDialog'
8import { AiAssistantDropdown } from '@/components/ui/AiAssistantDropdown'
9import { useTrack } from '@/lib/telemetry/track'
10
11interface StepTriggerProps {
12 number: number
13 title: string
14}
15
16function StepTrigger({ number, title }: StepTriggerProps) {
17 return (
18 <AccordionTrigger className="py-3 hover:no-underline">
19 <div className="flex items-center gap-2.5">
20 <span className="shrink-0 w-6 h-6 border border-button-hover text-foreground font-mono tabular-nums bg-button rounded-md text-xs font-medium flex items-center justify-center">
21 {number}
22 </span>
23 <span className="text-sm font-medium text-foreground text-left">{title}</span>
24 </div>
25 </AccordionTrigger>
26 )
27}
28
29interface RestartDatabaseTroubleshootingSectionProps {
30 number: number
31 errorType: string
32 /** Override the restart handler. If not provided, opens the restart dialog internally. */
33 onRestartProject?: () => void
34}
35
36export function RestartDatabaseTroubleshootingSection({
37 number,
38 errorType,
39 onRestartProject,
40}: RestartDatabaseTroubleshootingSectionProps) {
41 const track = useTrack()
42 const [showDialog, setShowDialog] = useState(false)
43
44 const handleClick = () => {
45 track('inline_error_troubleshooter_action_clicked', {
46 errorType,
47 ctaType: 'restart_db',
48 })
49 if (onRestartProject) {
50 onRestartProject()
51 } else {
52 setShowDialog(true)
53 }
54 }
55
56 return (
57 <>
58 <AccordionItem
59 value={`step-${number}`}
60 className="border-b border-default last:border-b-0 px-3 py-2"
61 >
62 <StepTrigger number={number} title="Try restarting your project" />
63 <AccordionContent className="pt-1">
64 <div className="px-2">
65 <p className="text-sm text-foreground-light mb-3">
66 Restarting your project can help resolve timeout errors or stale connections.
67 </p>
68 <Button type="default" size="tiny" onClick={handleClick}>
69 Restart project
70 </Button>
71 </div>
72 </AccordionContent>
73 </AccordionItem>
74
75 <RestartProjectDialog
76 visible={showDialog}
77 onClose={() => setShowDialog(false)}
78 restartType="database"
79 />
80 </>
81 )
82}
83
84interface TroubleshootingGuideSectionProps {
85 number: number
86 errorType: string
87 href: string
88 title?: string
89 description?: string
90}
91
92export function TroubleshootingGuideSection({
93 number,
94 errorType,
95 href,
96 title = 'Try our troubleshooting guide',
97 description,
98}: TroubleshootingGuideSectionProps) {
99 const track = useTrack()
100
101 return (
102 <AccordionItem
103 value={`step-${number}`}
104 className="border-b border-default last:border-b-0 px-3 py-2"
105 >
106 <StepTrigger number={number} title={title} />
107 <AccordionContent className="pt-1">
108 <div className="px-2">
109 {description && <p className="text-sm text-foreground-light mb-3">{description}</p>}
110 <Button
111 asChild
112 type="default"
113 size="tiny"
114 onClick={() =>
115 track('inline_error_troubleshooter_action_clicked', {
116 errorType,
117 ctaType: 'troubleshooting_guide',
118 })
119 }
120 iconRight={<ExternalLink />}
121 >
122 <a href={href} target="_blank" rel="noopener noreferrer">
123 View troubleshooting guide
124 </a>
125 </Button>
126 </div>
127 </AccordionContent>
128 </AccordionItem>
129 )
130}
131
132interface FixWithAITroubleshootingSectionProps {
133 number: number
134 errorType: string
135 description?: string
136 onDebugWithAI?: (prompt: string) => void
137 buildPrompt: () => string
138}
139
140export function FixWithAITroubleshootingSection({
141 number,
142 errorType,
143 description = 'Let our AI assistant help diagnose and suggest solutions.',
144 onDebugWithAI,
145 buildPrompt,
146}: FixWithAITroubleshootingSectionProps) {
147 const track = useTrack()
148
149 return (
150 <AccordionItem
151 value={`step-${number}`}
152 className="border-b border-default last:border-b-0 px-3 py-2"
153 >
154 <StepTrigger number={number} title="Debug with AI" />
155 <AccordionContent className="pt-1">
156 <div className="px-2">
157 <p className="text-sm text-foreground-light mb-3">{description}</p>
158 <AiAssistantDropdown
159 label="Debug with AI"
160 buildPrompt={buildPrompt}
161 onOpenAssistant={() => {
162 track('inline_error_troubleshooter_action_clicked', {
163 errorType,
164 ctaType: 'ask_ai',
165 })
166 onDebugWithAI?.(buildPrompt())
167 }}
168 size="tiny"
169 />
170 </div>
171 </AccordionContent>
172 </AccordionItem>
173 )
174}