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
63
lib/useToast.ts
Normal file
63
lib/useToast.ts
Normal file
|
@ -0,0 +1,63 @@
|
|||
'use client';
|
||||
|
||||
import { useState, useCallback } from 'react';
|
||||
import { Toast, ToastType } from '@/components/Toast';
|
||||
|
||||
export function useToast() {
|
||||
const [toasts, setToasts] = useState<Toast[]>([]);
|
||||
|
||||
const addToast = useCallback((
|
||||
type: ToastType,
|
||||
title: string,
|
||||
message?: string,
|
||||
duration?: number
|
||||
) => {
|
||||
const id = Math.random().toString(36).substr(2, 9);
|
||||
const toast: Toast = {
|
||||
id,
|
||||
type,
|
||||
title,
|
||||
message,
|
||||
duration: duration ?? (type === 'error' ? 7000 : 5000), // Errors stay longer
|
||||
};
|
||||
|
||||
setToasts((prev) => [...prev, toast]);
|
||||
return id;
|
||||
}, []);
|
||||
|
||||
const removeToast = useCallback((id: string) => {
|
||||
setToasts((prev) => prev.filter((toast) => toast.id !== id));
|
||||
}, []);
|
||||
|
||||
const clearAllToasts = useCallback(() => {
|
||||
setToasts([]);
|
||||
}, []);
|
||||
|
||||
// Convenience methods
|
||||
const showSuccess = useCallback((title: string, message?: string) => {
|
||||
return addToast('success', title, message);
|
||||
}, [addToast]);
|
||||
|
||||
const showError = useCallback((title: string, message?: string) => {
|
||||
return addToast('error', title, message);
|
||||
}, [addToast]);
|
||||
|
||||
const showWarning = useCallback((title: string, message?: string) => {
|
||||
return addToast('warning', title, message);
|
||||
}, [addToast]);
|
||||
|
||||
const showInfo = useCallback((title: string, message?: string) => {
|
||||
return addToast('info', title, message);
|
||||
}, [addToast]);
|
||||
|
||||
return {
|
||||
toasts,
|
||||
addToast,
|
||||
removeToast,
|
||||
clearAllToasts,
|
||||
showSuccess,
|
||||
showError,
|
||||
showWarning,
|
||||
showInfo,
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue