"use client";
import React, { useState, useCallback, useEffect, useRef } from 'react';
import { Flipper, Flipped } from 'react-flip-toolkit';
import { X } from 'lucide-react';
import { cn } from '../../lib/utils';
export interface NotificationUser {
avatarUrl?: string;
name: string;
initials?: string;
color?: string;
}
export interface NotificationItem {
id: string;
user: NotificationUser;
message: string;
timestamp?: string;
priority?: 'low' | 'medium' | 'high';
type?: 'info' | 'success' | 'warning' | 'error';
fadingOut?: boolean;
}
export interface AnimatedNotificationProps {
/** Maximum number of notifications to show at once */
maxNotifications?: number;
/** Interval between auto-generated notifications (in ms) */
autoInterval?: number;
/** Enable auto-generation of notifications */
autoGenerate?: boolean;
/** Custom notification data */
notifications?: NotificationItem[];
/** Custom messages for auto-generation */
customMessages?: string[];
/** Animation duration for fade transitions */
animationDuration?: number;
/** Position of the notification center */
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center';
/** Width of notification cards */
width?: number;
/** Enable/disable user avatars */
showAvatars?: boolean;
/** Enable/disable timestamps */
showTimestamps?: boolean;
/** Custom CSS class */
className?: string;
/** Callback when notification is clicked */
onNotificationClick?: (notification: NotificationItem) => void;
/** Callback when notification is dismissed */
onNotificationDismiss?: (notification: NotificationItem) => void;
/** Enable manual dismiss */
allowDismiss?: boolean;
/** Auto dismiss timeout (0 to disable) */
autoDismissTimeout?: number;
/** Custom API endpoint for fetching users */
userApiEndpoint?: string;
/** Theme variant */
variant?: 'default' | 'minimal' | 'glass' | 'bordered';
}
const defaultMessages = [
"Just completed a task! ✅",
"New feature deployed 🚀",
"Check out our latest update 📱",
"Server responded with 200 OK ✨",
"Background job finished 🔄",
"Data synced successfully! 💾",
"User logged in successfully 👋",
"Payment processed 💳",
"Email sent successfully 📧",
"Backup completed 🛡️"
];
const Avatar: React.FC<{
user: NotificationUser;
showAvatar: boolean;
}> = ({ user, showAvatar }) => {
if (!showAvatar) return null;
return (
{user.avatarUrl ? (

) : (
{user.initials || user.name.split(' ').map(n => n[0]).join('').slice(0, 2).toUpperCase()}
)}
);
};
const Notification: React.FC<{
notification: NotificationItem;
showAvatars: boolean;
showTimestamps: boolean;
variant: string;
onDismiss?: () => void;
onClick?: () => void;
allowDismiss: boolean;
}> = ({
notification,
showAvatars,
showTimestamps,
variant,
onDismiss,
onClick,
allowDismiss
}) => {
const getVariantStyles = () => {
switch (variant) {
case 'minimal':
return "bg-background/95 border border-border/50 backdrop-blur-xl";
case 'glass':
return "bg-background/30 backdrop-blur-2xl border border-white/20 dark:border-gray-800/20 shadow-2xl";
case 'bordered':
return "bg-card/95 border-2 border-primary/30 backdrop-blur-lg shadow-xl";
default:
return "bg-background/30 backdrop-blur-2xl border border-white/20 shadow-2xl";
}
};
const getPriorityStyles = () => {
switch (notification.priority) {
case 'high':
return 'border-l-4 border-l-red-500 shadow-red-500/20 dark:border-l-red-500 dark:shadow-red-500/20';
case 'medium':
return 'border-l-4 border-l-yellow-500 shadow-yellow-500/20 dark:border-l-yellow-500 dark:shadow-yellow-500/20';
case 'low':
return 'border-l-4 border-l-blue-500 shadow-blue-500/20 dark:border-l-blue-500 dark:shadow-blue-500/20';
default:
return 'border-l-4 border-l-primary/50 shadow-primary/20 dark:border-l-primary/50 dark:shadow-primary/20';
}
};
return (
{notification.user.name}
{showTimestamps && notification.timestamp && (
{notification.timestamp}
)}
{notification.message}
{allowDismiss && (
)}
);
};
async function fetchRandomUser(apiEndpoint?: string): Promise {
try {
const endpoint = apiEndpoint || "https://randomuser.me/api/";
const res = await fetch(endpoint);
const data = await res.json();
const user = data.results[0];
return {
avatarUrl: user.picture?.large,
name: `${user.name.first} ${user.name.last}`,
color: `hsl(${Math.floor(Math.random() * 360)}, 70%, 80%)`
};
} catch (error) {
const names = ['John Doe', 'Jane Smith', 'Alex Johnson', 'Sarah Wilson', 'Mike Brown'];
const randomName = names[Math.floor(Math.random() * names.length)];
return {
name: randomName,
color: `hsl(${Math.floor(Math.random() * 360)}, 70%, 80%)`
};
}
}
function getRandomMessage(customMessages?: string[]): string {
const messages = customMessages || defaultMessages;
return messages[Math.floor(Math.random() * messages.length)];
}
async function generateNotification(
customMessages?: string[],
userApiEndpoint?: string
): Promise {
const user = await fetchRandomUser(userApiEndpoint);
return {
id: crypto.randomUUID(),
user,
message: getRandomMessage(customMessages),
timestamp: new Date().toLocaleTimeString(),
priority: ['low', 'medium', 'high'][Math.floor(Math.random() * 3)] as 'low' | 'medium' | 'high'
};
}
const AnimatedNotification: React.FC = ({
maxNotifications = 3,
autoInterval = 1500,
autoGenerate = true,
notifications = [],
customMessages,
animationDuration = 800,
position = 'center',
width = 320,
showAvatars = true,
showTimestamps = true,
className,
onNotificationClick,
onNotificationDismiss,
allowDismiss = true,
autoDismissTimeout = 0,
userApiEndpoint,
variant = 'glass'
}) => {
const [notes, setNotes] = useState(notifications);
const timeoutRef = useRef(null);
const dismissTimeouts = useRef