96 lines
3.4 KiB
React
96 lines
3.4 KiB
React
import React, { useState, useEffect, useCallback } from 'react';
|
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
import { X, Bell } from 'lucide-react';
|
|
|
|
const SmartPopup = () => {
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
|
|
// Konfigurasi (dalam milidetik)
|
|
const IDLE_THRESHOLD = 30 * 60 * 1000; // 30 Menit tidak aktif
|
|
const POPUP_DELAY = 10 * 1000; // Muncul setelah 10 detik aktif
|
|
|
|
const showPopup = useCallback(() => {
|
|
setIsOpen(true);
|
|
// Simpan timestamp kapan terakhir popup muncul
|
|
localStorage.setItem('last_popup_time', Date.now().toString());
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const handleActivity = () => {
|
|
const now = Date.now();
|
|
const lastPopup = parseInt(localStorage.getItem('last_popup_time') || '0');
|
|
const lastActivity = parseInt(localStorage.getItem('last_activity_time') || '0');
|
|
|
|
// Update waktu aktivitas terakhir di storage
|
|
localStorage.setItem('last_activity_time', now.toString());
|
|
|
|
// LOGIKA: Munculkan popup jika:
|
|
// 1. Belum pernah muncul (lastPopup === 0)
|
|
// 2. ATAU User sudah tidak aktif melebihi threshold (Idle)
|
|
if (lastPopup === 0 || (now - lastActivity > IDLE_THRESHOLD)) {
|
|
// Beri jeda 10 detik sebelum muncul sesuai request awal
|
|
const timer = setTimeout(() => {
|
|
showPopup();
|
|
}, POPUP_DELAY);
|
|
|
|
return () => clearTimeout(timer);
|
|
}
|
|
};
|
|
|
|
// Deteksi aktivitas user (mouse, ketik, scroll, sentuh)
|
|
const activityEvents = ['mousedown', 'mousemove', 'keydown', 'scroll', 'touchstart'];
|
|
|
|
// Jalankan pengecekan saat pertama kali load
|
|
handleActivity();
|
|
|
|
activityEvents.forEach(event =>
|
|
window.addEventListener(event, handleActivity, { passive: true })
|
|
);
|
|
|
|
return () => {
|
|
activityEvents.forEach(event =>
|
|
window.removeEventListener(event, handleActivity)
|
|
);
|
|
};
|
|
}, [showPopup, IDLE_THRESHOLD, POPUP_DELAY]);
|
|
|
|
return (
|
|
<AnimatePresence>
|
|
{isOpen && (
|
|
<div className="fixed inset-0 z-[999] flex items-center justify-center p-4 bg-slate-900/60 backdrop-blur-sm">
|
|
<motion.div
|
|
initial={{ opacity: 0, scale: 0.9 }}
|
|
animate={{ opacity: 1, scale: 1 }}
|
|
exit={{ opacity: 0, scale: 0.9 }}
|
|
className="bg-white rounded-2xl shadow-2xl max-w-sm w-full p-8 relative"
|
|
>
|
|
<button
|
|
onClick={() => setIsOpen(false)}
|
|
className="absolute top-4 right-4 text-slate-400 hover:text-slate-600"
|
|
>
|
|
<X size={20} />
|
|
</button>
|
|
|
|
<div className="text-center">
|
|
<div className="w-16 h-16 bg-amber-100 text-amber-600 rounded-full flex items-center justify-center mx-auto mb-4">
|
|
<Bell size={32} />
|
|
</div>
|
|
<h3 className="text-xl font-bold text-slate-900 mb-2">Selamat Datang Kembali!</h3>
|
|
<p className="text-slate-500 mb-6">
|
|
Kami mendeteksi aktivitas baru. Jangan lupa untuk memeriksa pembaruan data pertanian Anda hari ini.
|
|
</p>
|
|
<button
|
|
onClick={() => setIsOpen(false)}
|
|
className="w-full bg-amber-500 hover:bg-amber-600 text-white font-semibold py-3 rounded-xl transition-colors"
|
|
>
|
|
Lanjutkan Aktivitas
|
|
</button>
|
|
</div>
|
|
</motion.div>
|
|
</div>
|
|
)}
|
|
</AnimatePresence>
|
|
);
|
|
};
|
|
|
|
export default SmartPopup; |