anky2002 commited on
Commit
84b4bfe
·
verified ·
1 Parent(s): 23949b2

feat: add reusable ErrorBoundary component for per-section error recovery

Browse files
src/components/ui/error-boundary.tsx ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import { Component, ReactNode } from "react"
4
+ import { AlertCircle, RefreshCw } from "lucide-react"
5
+ import { Button } from "@/components/ui/button"
6
+ import { Card, CardContent } from "@/components/ui/card"
7
+
8
+ interface ErrorBoundaryProps {
9
+ children: ReactNode
10
+ fallback?: ReactNode
11
+ section?: string
12
+ }
13
+
14
+ interface ErrorBoundaryState {
15
+ hasError: boolean
16
+ error: Error | null
17
+ }
18
+
19
+ /**
20
+ * Reusable error boundary for per-section error recovery.
21
+ * Prevents a single component crash from taking down the entire page.
22
+ *
23
+ * Usage:
24
+ * <ErrorBoundary section="Related Prompts">
25
+ * <RelatedPrompts ... />
26
+ * </ErrorBoundary>
27
+ */
28
+ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
29
+ constructor(props: ErrorBoundaryProps) {
30
+ super(props)
31
+ this.state = { hasError: false, error: null }
32
+ }
33
+
34
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState {
35
+ return { hasError: true, error }
36
+ }
37
+
38
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
39
+ console.error(`[ErrorBoundary${this.props.section ? `: ${this.props.section}` : ''}]`, error, errorInfo)
40
+ }
41
+
42
+ handleRetry = () => {
43
+ this.setState({ hasError: false, error: null })
44
+ }
45
+
46
+ render() {
47
+ if (this.state.hasError) {
48
+ if (this.props.fallback) {
49
+ return this.props.fallback
50
+ }
51
+
52
+ return (
53
+ <Card className="border-destructive/50 bg-destructive/5">
54
+ <CardContent className="p-6 flex flex-col items-center text-center gap-3">
55
+ <AlertCircle className="h-8 w-8 text-destructive" />
56
+ <div>
57
+ <h3 className="font-semibold text-sm">
58
+ {this.props.section ? `Error loading ${this.props.section}` : 'Something went wrong'}
59
+ </h3>
60
+ <p className="text-xs text-muted-foreground mt-1">
61
+ This section encountered an error. The rest of the page still works.
62
+ </p>
63
+ </div>
64
+ <Button
65
+ variant="outline"
66
+ size="sm"
67
+ onClick={this.handleRetry}
68
+ className="gap-2"
69
+ >
70
+ <RefreshCw className="h-3 w-3" />
71
+ Retry
72
+ </Button>
73
+ </CardContent>
74
+ </Card>
75
+ )
76
+ }
77
+
78
+ return this.props.children
79
+ }
80
+ }