'use client'; import React, { useState } from 'react'; import { useRouter } from 'next/navigation'; import { AlertTriangle, Wifi, RefreshCw, ArrowLeft, Home, X, Info } from 'lucide-react'; import { ErrorDisplayProps } from './types'; import Button from '@/components/ui/Button'; /** * ErrorDisplay Component * * Provides standardized error display with 4 variants: * - full-screen: Full page error with navigation * - inline: Compact inline error message * - card: Error card for grid layouts * - toast: Toast notification style * * Features: * - Auto-detects retryable errors * - Shows user-friendly messages * - Provides navigation options * - Displays technical details in development * - Fully accessible with ARIA labels and keyboard navigation */ export function ErrorDisplay({ error, onRetry, variant = 'full-screen', showRetry: showRetryProp, showNavigation = true, actions = [], className = '', hideTechnicalDetails = false, ariaLabel = 'Error notification', }: ErrorDisplayProps) { const router = useRouter(); const [isRetrying, setIsRetrying] = useState(false); // Auto-detect retry capability const isRetryable = showRetryProp ?? error.isRetryable(); const isConnectivity = error.isConnectivityIssue(); const userMessage = error.getUserMessage(); const isDev = process.env.NODE_ENV === 'development' && !hideTechnicalDetails; const handleRetry = async () => { if (onRetry) { setIsRetrying(true); try { await onRetry(); } finally { setIsRetrying(false); } } }; const handleGoBack = () => { router.back(); }; const handleGoHome = () => { router.push('/'); }; const handleClose = () => { // For toast variant, this would typically close the notification // Implementation depends on how toast notifications are managed window.history.back(); }; // Icon based on error type const ErrorIcon = isConnectivity ? Wifi : AlertTriangle; // Render different variants switch (variant) { case 'full-screen': return (
{/* Header */}

{isConnectivity ? 'Connection Issue' : 'Something Went Wrong'}

Error {error.context.statusCode || 'N/A'}

{/* Body */}

{userMessage}

{/* Technical Details (Development Only) */} {isDev && (
Technical Details
Type: {error.type}
Endpoint: {error.context.endpoint || 'N/A'}
{error.context.statusCode &&
Status: {error.context.statusCode}
} {error.context.retryCount !== undefined && (
Retries: {error.context.retryCount}
)} {error.context.wasRetry &&
Was Retry: true
}
)} {/* Action Buttons */}
{isRetryable && onRetry && ( )} {showNavigation && (
)} {/* Custom Actions */} {actions.length > 0 && (
{actions.map((action, index) => ( ))}
)}
{/* Footer */}
If this persists, please contact support at{' '} support@gridpilot.com
); case 'inline': return (

{userMessage}

{isDev && (

[{error.type}] {error.context.statusCode || 'N/A'}

)}
{isRetryable && onRetry && ( )} {actions.map((action, index) => ( ))}
); case 'card': return (

Error

{userMessage}

{isDev && (

{error.type} | Status: {error.context.statusCode || 'N/A'}

)}
{isRetryable && onRetry && ( )} {actions.map((action, index) => ( ))}
); case 'toast': return (

{userMessage}

{isDev && (

[{error.type}] {error.context.statusCode || 'N/A'}

)}
{isRetryable && onRetry && ( )} {actions.slice(0, 2).map((action, index) => ( ))}
); default: return null; } } /** * Convenience component for full-screen error display */ export function FullScreenError({ error, onRetry, ...props }: ErrorDisplayProps) { return ( ); } /** * Convenience component for inline error display */ export function InlineError({ error, onRetry, ...props }: ErrorDisplayProps) { return ( ); } /** * Convenience component for card error display */ export function CardError({ error, onRetry, ...props }: ErrorDisplayProps) { return ( ); } /** * Convenience component for toast error display */ export function ToastError({ error, onRetry, ...props }: ErrorDisplayProps) { return ( ); }