Add Notification and new mini desing
This commit is contained in:
95
frontend/src/components/NotificationSystem.jsx
Normal file
95
frontend/src/components/NotificationSystem.jsx
Normal file
@@ -0,0 +1,95 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { X, CheckCircle, AlertCircle, Info, AlertTriangle } from 'lucide-react';
|
||||
|
||||
export default function NotificationSystem({ theme }) {
|
||||
const [notifications, setNotifications] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
// Слушаем события уведомлений
|
||||
const handleNotification = (event) => {
|
||||
const { type, title, message } = event.detail;
|
||||
addNotification(type, title, message);
|
||||
};
|
||||
|
||||
window.addEventListener('notification', handleNotification);
|
||||
return () => window.removeEventListener('notification', handleNotification);
|
||||
}, []);
|
||||
|
||||
const addNotification = (type, title, message) => {
|
||||
const id = Date.now();
|
||||
const notification = { id, type, title, message };
|
||||
|
||||
setNotifications(prev => [...prev, notification]);
|
||||
|
||||
// Автоматически удаляем через 5 секунд
|
||||
setTimeout(() => {
|
||||
removeNotification(id);
|
||||
}, 5000);
|
||||
};
|
||||
|
||||
const removeNotification = (id) => {
|
||||
setNotifications(prev => prev.filter(n => n.id !== id));
|
||||
};
|
||||
|
||||
const getIcon = (type) => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return <CheckCircle className="w-5 h-5" />;
|
||||
case 'error':
|
||||
return <AlertCircle className="w-5 h-5" />;
|
||||
case 'warning':
|
||||
return <AlertTriangle className="w-5 h-5" />;
|
||||
case 'info':
|
||||
default:
|
||||
return <Info className="w-5 h-5" />;
|
||||
}
|
||||
};
|
||||
|
||||
const getColors = (type) => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return 'bg-green-600 border-green-500';
|
||||
case 'error':
|
||||
return 'bg-red-600 border-red-500';
|
||||
case 'warning':
|
||||
return 'bg-yellow-600 border-yellow-500';
|
||||
case 'info':
|
||||
default:
|
||||
return 'bg-blue-600 border-blue-500';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="fixed top-4 right-4 z-50 space-y-2 max-w-sm">
|
||||
{notifications.map((notification) => (
|
||||
<div
|
||||
key={notification.id}
|
||||
className={`${getColors(notification.type)} border-l-4 rounded-lg shadow-2xl p-4 text-white animate-slide-in-right`}
|
||||
>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex-shrink-0 mt-0.5">
|
||||
{getIcon(notification.type)}
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<h4 className="font-semibold text-sm mb-1">{notification.title}</h4>
|
||||
<p className="text-sm opacity-90">{notification.message}</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => removeNotification(notification.id)}
|
||||
className="flex-shrink-0 hover:bg-white hover:bg-opacity-20 rounded p-1 transition"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Вспомогательная функция для отправки уведомлений
|
||||
export const notify = (type, title, message) => {
|
||||
window.dispatchEvent(new CustomEvent('notification', {
|
||||
detail: { type, title, message }
|
||||
}));
|
||||
};
|
||||
Reference in New Issue
Block a user