synor/apps/desktop-wallet/src/components/ErrorBoundary.tsx
Gulshan Yadav 81347ab15d feat(wallet): add comprehensive desktop wallet features
Add all-in-one desktop wallet with extensive feature set:

Infrastructure:
- Storage: IPFS-based decentralized file storage with upload/download
- Hosting: Domain registration and static site hosting
- Compute: GPU/CPU job marketplace for distributed computing
- Database: Multi-model database services (KV, Document, Vector, etc.)

Financial Features:
- Privacy: Confidential transactions with Pedersen commitments
- Bridge: Cross-chain transfers (Ethereum, Bitcoin, IBC/Cosmos)
- Governance: DAO proposals, voting, and delegation
- ZK-Rollup: L2 scaling with deposits, withdrawals, and transfers

UI/UX Improvements:
- Add ErrorBoundary component for graceful error handling
- Add LoadingStates components (spinners, skeletons, overlays)
- Add Animation components (FadeIn, SlideIn, CountUp, etc.)
- Update navigation with new feature sections

Testing:
- Add Playwright E2E smoke tests
- Test route accessibility and page rendering
- Verify build process and asset loading

Build:
- Fix TypeScript compilation errors
- Update Tauri plugin dependencies
- Successfully build macOS app bundle and DMG
2026-02-02 11:35:21 +05:30

79 lines
2.1 KiB
TypeScript

import { Component, ErrorInfo, ReactNode } from 'react';
import { AlertTriangle, RefreshCw } from 'lucide-react';
interface Props {
children: ReactNode;
fallback?: ReactNode;
}
interface State {
hasError: boolean;
error?: Error;
}
/**
* Error Boundary component for graceful error handling
*
* Catches JavaScript errors anywhere in the child component tree
* and displays a fallback UI instead of crashing the whole app.
*/
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('Uncaught error:', error, errorInfo);
}
private handleReset = () => {
this.setState({ hasError: false, error: undefined });
};
public render() {
if (this.state.hasError) {
if (this.props.fallback) {
return this.props.fallback;
}
return (
<div className="flex flex-col items-center justify-center min-h-[200px] p-8 bg-red-900/10 rounded-xl border border-red-800/50">
<AlertTriangle className="text-red-400 mb-4" size={48} />
<h2 className="text-xl font-semibold text-white mb-2">Something went wrong</h2>
<p className="text-gray-400 text-center mb-4 max-w-md">
{this.state.error?.message || 'An unexpected error occurred'}
</p>
<button
onClick={this.handleReset}
className="flex items-center gap-2 px-4 py-2 bg-red-600 hover:bg-red-700 rounded-lg text-white font-medium transition-colors"
>
<RefreshCw size={16} />
Try Again
</button>
</div>
);
}
return this.props.children;
}
}
/**
* HOC to wrap any component with error boundary
*/
export function withErrorBoundary<P extends object>(
WrappedComponent: React.ComponentType<P>,
fallback?: ReactNode
) {
return function WithErrorBoundary(props: P) {
return (
<ErrorBoundary fallback={fallback}>
<WrappedComponent {...props} />
</ErrorBoundary>
);
};
}