"use client";
import { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
CheckCircle,
XCircle,
AlertTriangle,
Info,
X,
Mail,
Database,
Save,
Trash2,
Upload,
Download
} from 'lucide-react';
export type ToastType = 'success' | 'error' | 'warning' | 'info';
export interface Toast {
id: string;
type: ToastType;
title: string;
message: string;
duration?: number;
action?: {
label: string;
onClick: () => void;
};
}
interface ToastProps {
toast: Toast;
onRemove: (id: string) => void;
}
const ToastItem = ({ toast, onRemove }: ToastProps) => {
const [isVisible, setIsVisible] = useState(true);
useEffect(() => {
if (toast.duration !== 0) {
const timer = setTimeout(() => {
setIsVisible(false);
setTimeout(() => onRemove(toast.id), 300);
}, toast.duration || 5000);
return () => clearTimeout(timer);
}
}, [toast.duration, toast.id, onRemove]);
const getIcon = () => {
switch (toast.type) {
case 'success':
return ;
case 'error':
return ;
case 'warning':
return ;
case 'info':
return ;
default:
return ;
}
};
const getColors = () => {
switch (toast.type) {
case 'success':
return 'bg-white border-green-300 text-green-900 shadow-lg';
case 'error':
return 'bg-white border-red-300 text-red-900 shadow-lg';
case 'warning':
return 'bg-white border-yellow-300 text-yellow-900 shadow-lg';
case 'info':
return 'bg-white border-blue-300 text-blue-900 shadow-lg';
default:
return 'bg-white border-gray-300 text-gray-900 shadow-lg';
}
};
return (
{getIcon()}
{toast.title}
{toast.message}
{toast.action && (
)}
{/* Progress bar */}
{toast.duration !== 0 && (
)}
);
};
// Toast context and provider
import { createContext, useContext, useCallback } from 'react';
interface ToastContextType {
showToast: (toast: Omit) => void;
showSuccess: (title: string, message?: string) => void;
showError: (title: string, message?: string) => void;
showWarning: (title: string, message?: string) => void;
showInfo: (title: string, message?: string) => void;
showEmailSent: (email: string) => void;
showEmailError: (error: string) => void;
showProjectSaved: (title: string) => void;
showProjectDeleted: (title: string) => void;
showImportSuccess: (count: number) => void;
showImportError: (error: string) => void;
}
const ToastContext = createContext(undefined);
export const useToast = () => {
const context = useContext(ToastContext);
if (!context) {
throw new Error('useToast must be used within a ToastProvider');
}
return context;
};
export const ToastProvider = ({ children }: { children: React.ReactNode }) => {
const [toasts, setToasts] = useState([]);
const addToast = useCallback((toast: Omit) => {
const id = Math.random().toString(36).substr(2, 9);
const newToast = { ...toast, id };
setToasts(prev => [...prev, newToast]);
}, []);
const removeToast = useCallback((id: string) => {
setToasts(prev => prev.filter(toast => toast.id !== id));
}, []);
const showToast = useCallback((toast: Omit) => {
addToast(toast);
}, [addToast]);
const showSuccess = useCallback((title: string, message?: string) => {
addToast({
type: 'success',
title,
message: message || '',
duration: 4000
});
}, [addToast]);
const showError = useCallback((title: string, message?: string) => {
addToast({
type: 'error',
title,
message: message || '',
duration: 6000
});
}, [addToast]);
const showWarning = useCallback((title: string, message?: string) => {
addToast({
type: 'warning',
title,
message: message || '',
duration: 5000
});
}, [addToast]);
const showInfo = useCallback((title: string, message?: string) => {
addToast({
type: 'info',
title,
message: message || '',
duration: 4000
});
}, [addToast]);
const showEmailSent = useCallback((email: string) => {
addToast({
type: 'success',
title: 'E-Mail gesendet! 📧',
message: `Deine Nachricht an ${email} wurde erfolgreich versendet.`,
duration: 5000,
});
}, [addToast]);
const showEmailError = useCallback((error: string) => {
addToast({
type: 'error',
title: 'E-Mail Fehler! ❌',
message: `Fehler beim Senden: ${error}`,
duration: 8000
});
}, [addToast]);
const showProjectSaved = useCallback((title: string) => {
addToast({
type: 'success',
title: 'Projekt gespeichert! 💾',
message: `"${title}" wurde erfolgreich in der Datenbank gespeichert.`,
duration: 4000,
});
}, [addToast]);
const showProjectDeleted = useCallback((title: string) => {
addToast({
type: 'warning',
title: 'Projekt gelöscht! 🗑️',
message: `"${title}" wurde aus der Datenbank entfernt.`,
duration: 4000,
});
}, [addToast]);
const showImportSuccess = useCallback((count: number) => {
addToast({
type: 'success',
title: 'Import erfolgreich! 📥',
message: `${count} Projekte wurden erfolgreich importiert.`,
duration: 5000,
});
}, [addToast]);
const showImportError = useCallback((error: string) => {
addToast({
type: 'error',
title: 'Import Fehler! ❌',
message: `Fehler beim Importieren: ${error}`,
duration: 8000,
});
}, [addToast]);
const contextValue: ToastContextType = {
showToast,
showSuccess,
showError,
showWarning,
showInfo,
showEmailSent,
showEmailError,
showProjectSaved,
showProjectDeleted,
showImportSuccess,
showImportError
};
return (
{children}
{/* Toast Container */}
{toasts.map((toast) => (
))}
);
};
export default ToastItem;