ifixkart-storefront/components/LiveToast.tsx

123 lines
3.9 KiB
TypeScript

"use client";
import React, { useState, useEffect } from 'react';
import Image from 'next/image';
import { AnimatePresence, motion } from 'framer-motion';
import { CheckCircle2, X } from 'lucide-react';
interface Purchase {
name: string;
location: string;
product: string;
time: string;
image: string;
}
const mockPurchases: Purchase[] = [
{
name: 'Ben',
location: 'New York',
product: 'HP (23.8 Inch) with IPS Panel Technology',
time: '3 hours ago',
image: ''
},
{
name: 'Swaraa',
location: 'California',
product: 'HP LaserJet P1108 Mono Single Function Laser Printer',
time: '46 minutes ago',
image: ''
},
{
name: 'Alex',
location: 'London',
product: 'SwapME Braided Nylon Woven Smart Watch',
time: '12 minutes ago',
image: ''
},
{
name: 'Hiroshi',
location: 'Tokyo',
product: 'Ceptics India to Europe Travel Adapter Plug',
time: '5 minutes ago',
image: ''
}
];
export const LiveToast: React.FC = () => {
const [currentIndex, setCurrentIndex] = useState(0);
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
const initialTimeout = setTimeout(() => {
setIsVisible(true);
}, 4000);
const interval = setInterval(() => {
setIsVisible(false);
setTimeout(() => {
setCurrentIndex((prev) => (prev + 1) % mockPurchases.length);
setIsVisible(true);
}, 1000);
}, 15000);
return () => {
clearTimeout(initialTimeout);
clearInterval(interval);
};
}, []);
if (!mockPurchases.length) return null;
const currentPurchase = mockPurchases[currentIndex];
return (
<AnimatePresence>
{isVisible && (
<motion.div
initial={{ opacity: 0, y: 50, scale: 0.9 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
exit={{ opacity: 0, y: 20, scale: 0.9 }}
transition={{ type: 'spring', stiffness: 300, damping: 25 }}
className="fixed bottom-6 left-6 z-50 max-w-[340px] bg-white rounded-theme p-4 shadow-soft hover:shadow-soft-hover border border-gray-100 flex items-start gap-3"
>
{currentPurchase.image ? (
<img
src={currentPurchase.image}
alt={currentPurchase.product}
className="w-12 h-12 object-cover rounded-lg border border-gray-100 flex-shrink-0"
/>
) : (
<div className="w-12 h-12 bg-blue-50 text-primary rounded-lg border border-gray-100 flex items-center justify-center font-bold text-xs flex-shrink-0">
iF
</div>
)}
<div className="flex-1 min-w-0 pr-4">
<div className="flex items-center justify-between">
<p className="text-[11px] text-gray-500 font-medium">
<span className="font-bold text-gray-800">{currentPurchase.name}</span> from{' '}
<span className="font-semibold text-primary">{currentPurchase.location}</span>
</p>
<button
onClick={() => setIsVisible(false)}
className="text-gray-400 hover:text-gray-600 transition-colors"
>
<X size={12} />
</button>
</div>
<h4 className="text-[12px] font-bold text-gray-800 mt-0.5 leading-snug truncate">
{currentPurchase.product}
</h4>
<div className="flex items-center gap-1.5 mt-1.5">
<span className="text-[10px] text-gray-400 font-semibold">{currentPurchase.time}</span>
<span className="w-1 h-1 bg-gray-300 rounded-full" />
<div className="flex items-center gap-0.5 text-green-600">
<CheckCircle2 size={10} fill="currentColor" className="text-white" />
<span className="text-[9px] font-bold tracking-wider uppercase">Verified</span>
</div>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
);
};