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>
63 lines
No EOL
1.5 KiB
TypeScript
63 lines
No EOL
1.5 KiB
TypeScript
'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,
|
|
};
|
|
} |