Implement professional error handling and user feedback system
Major UX Improvements: - Replace all alert() dialogs with elegant toast notifications - Add comprehensive loading states for all async operations - Implement client-side form validation with visual feedback - Add React Error Boundary for graceful error recovery Components Added: - Toast notification system with success/error/warning/info types - useToast hook for easy notification management - ErrorBoundary component with development error details - Form validation with real-time feedback User Experience: - Professional toast notifications instead of browser alerts - Loading indicators prevent double-clicks and show progress - Immediate validation feedback prevents submission errors - Graceful error recovery with retry options - Enhanced accessibility with proper ARIA labels 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
dc1e3a62a1
commit
b6ff9a3cb6
5 changed files with 350 additions and 26 deletions
76
components/ErrorBoundary.tsx
Normal file
76
components/ErrorBoundary.tsx
Normal file
|
@ -0,0 +1,76 @@
|
|||
'use client';
|
||||
|
||||
import { Component, ErrorInfo, ReactNode } from 'react';
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
fallback?: ReactNode;
|
||||
}
|
||||
|
||||
interface State {
|
||||
hasError: boolean;
|
||||
error?: Error;
|
||||
}
|
||||
|
||||
export class ErrorBoundary extends Component<Props, State> {
|
||||
public state: State = {
|
||||
hasError: false,
|
||||
};
|
||||
|
||||
public static getDerivedStateFromError(error: Error): State {
|
||||
return { hasError: true, error };
|
||||
}
|
||||
|
||||
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
console.error('ErrorBoundary caught an error:', error, errorInfo);
|
||||
}
|
||||
|
||||
public render() {
|
||||
if (this.state.hasError) {
|
||||
if (this.props.fallback) {
|
||||
return this.props.fallback;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="glass p-8 text-center max-w-md mx-auto mt-8">
|
||||
<div className="text-6xl mb-4">⚠️</div>
|
||||
<h2 className="text-xl font-semibold mb-4 text-red-400">
|
||||
Something went wrong
|
||||
</h2>
|
||||
<p className="text-white/80 mb-6">
|
||||
An unexpected error occurred. Please refresh the page or try again later.
|
||||
</p>
|
||||
<div className="button-group" style={{ justifyContent: 'center' }}>
|
||||
<button
|
||||
onClick={() => window.location.reload()}
|
||||
className="btn btn-success"
|
||||
>
|
||||
<span className="icon">🔄</span>
|
||||
Refresh Page
|
||||
</button>
|
||||
<button
|
||||
onClick={() => this.setState({ hasError: false, error: undefined })}
|
||||
className="btn-secondary"
|
||||
>
|
||||
<span className="icon">🔄</span>
|
||||
Try Again
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{process.env.NODE_ENV === 'development' && this.state.error && (
|
||||
<details className="mt-6 text-left">
|
||||
<summary className="text-red-400 cursor-pointer font-mono text-sm">
|
||||
Error Details (Development)
|
||||
</summary>
|
||||
<pre className="text-red-300 text-xs mt-2 p-3 bg-red-500/10 rounded border border-red-500/20 overflow-auto">
|
||||
{this.state.error.stack}
|
||||
</pre>
|
||||
</details>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue