File size: 4,078 Bytes
227c43a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import React from 'react';
import { motion } from 'framer-motion';
import { AlertTriangle, RefreshCw, Home } from 'lucide-react';
import Button from '../design-system/components/Button';
import Card from '../design-system/components/Card';

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { 
      hasError: false, 
      error: null, 
      errorInfo: null,
      retryCount: 0 
    };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    this.setState({
      error,
      errorInfo,
    });

    // Log error to monitoring service in production
    if (process.env.NODE_ENV === 'production') {
      console.error('Error caught by boundary:', error, errorInfo);
      // Here you would typically send to error monitoring service
      // e.g., Sentry.captureException(error, { extra: errorInfo });
    }
  }

  handleRetry = () => {
    this.setState(prevState => ({
      hasError: false,
      error: null,
      errorInfo: null,
      retryCount: prevState.retryCount + 1
    }));
  };

  handleGoHome = () => {
    window.location.href = '/';
  };

  render() {
    if (this.state.hasError) {
      return (
        <div className="min-h-screen bg-gradient-to-br from-neutral-50 to-neutral-100 flex items-center justify-center p-4">

          <motion.div

            initial={{ opacity: 0, y: 20 }}

            animate={{ opacity: 1, y: 0 }}

            className="w-full max-w-md"

          >

            <Card variant="elevated" padding="lg" className="text-center">

              <motion.div

                initial={{ scale: 0 }}

                animate={{ scale: 1 }}

                transition={{ delay: 0.2, type: "spring" }}

                className="w-16 h-16 bg-error-100 rounded-full flex items-center justify-center mx-auto mb-4"

              >

                <AlertTriangle size={32} className="text-error-500" />

              </motion.div>



              <Card.Title className="text-xl mb-2">

                Oops! Something went wrong

              </Card.Title>



              <Card.Description className="mb-6">

                We encountered an unexpected error. This has been logged and our team will investigate.

              </Card.Description>



              {process.env.NODE_ENV === 'development' && this.state.error && (

                <details className="text-left mb-6 p-4 bg-neutral-50 rounded-lg">

                  <summary className="cursor-pointer text-sm font-medium text-neutral-700 mb-2">

                    Error Details (Development)

                  </summary>

                  <pre className="text-xs text-error-600 overflow-auto">

                    {this.state.error.toString()}

                    {this.state.errorInfo.componentStack}

                  </pre>

                </details>

              )}



              <div className="flex gap-3">

                <Button

                  variant="outline"

                  onClick={this.handleRetry}

                  icon={<RefreshCw size={16} />}

                  className="flex-1"

                >

                  Try Again

                </Button>

                <Button

                  onClick={this.handleGoHome}

                  icon={<Home size={16} />}

                  className="flex-1"

                >

                  Go Home

                </Button>

              </div>



              {this.state.retryCount > 2 && (

                <motion.p

                  initial={{ opacity: 0 }}

                  animate={{ opacity: 1 }}

                  className="text-sm text-neutral-600 mt-4"

                >

                  Still having issues? Try refreshing the page or contact support.

                </motion.p>

              )}

            </Card>

          </motion.div>

        </div>
      );
    }

    return this.props.children;
  }
}

export default ErrorBoundary;