85 lines
2.9 KiB
TypeScript
85 lines
2.9 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { usePushNotifications } from '@/hooks/usePushNotifications';
|
|
import { Bell, X } from 'lucide-react';
|
|
|
|
const DISMISSED_KEY = 'push-banner-dismissed';
|
|
const SHOW_DELAY = 3000;
|
|
|
|
function getInitiallyDismissed(): boolean {
|
|
if (typeof window === 'undefined') return false;
|
|
return !!localStorage.getItem(DISMISSED_KEY);
|
|
}
|
|
|
|
export function NotificationBanner() {
|
|
const [isVisible, setIsVisible] = useState(false);
|
|
const [isDismissed, setIsDismissed] = useState(getInitiallyDismissed);
|
|
const { isSupported, isSubscribed, isLoading, subscribe } =
|
|
usePushNotifications();
|
|
|
|
useEffect(() => {
|
|
if (isSupported && !isSubscribed && !isDismissed) {
|
|
const timer = setTimeout(() => {
|
|
setIsVisible(true);
|
|
}, SHOW_DELAY);
|
|
return () => clearTimeout(timer);
|
|
}
|
|
}, [isSupported, isSubscribed, isDismissed]);
|
|
|
|
const handleDismiss = () => {
|
|
setIsVisible(false);
|
|
localStorage.setItem(DISMISSED_KEY, 'true');
|
|
setIsDismissed(true);
|
|
};
|
|
|
|
const handleSubscribe = async () => {
|
|
const success = await subscribe();
|
|
if (success) {
|
|
setIsVisible(false);
|
|
}
|
|
};
|
|
|
|
if (!isVisible || isSubscribed || isDismissed) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<div className="fixed bottom-4 right-4 z-50 max-w-sm animate-slide-in-right">
|
|
<div className="flex items-start gap-3 rounded-lg border-2 border-foreground bg-card p-4 shadow-brutal">
|
|
<div className="flex-shrink-0">
|
|
<Bell className="h-5 w-5 text-accent" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<p className="font-body text-sm font-medium uppercase tracking-wider">
|
|
Останете информирани
|
|
</p>
|
|
<p className="mt-1 font-body text-xs text-muted-foreground">
|
|
Добијте известувања за нови статии и live ажурирања
|
|
</p>
|
|
<div className="mt-3 flex gap-2">
|
|
<button
|
|
onClick={handleSubscribe}
|
|
disabled={isLoading}
|
|
className="border-2 border-foreground bg-foreground px-3 py-1.5 font-body text-xs font-medium uppercase tracking-wider text-background transition-all hover:bg-accent hover:text-foreground disabled:opacity-50"
|
|
>
|
|
{isLoading ? 'Се вклучува...' : 'Вклучи'}
|
|
</button>
|
|
<button
|
|
onClick={handleDismiss}
|
|
className="border-2 border-foreground px-3 py-1.5 font-body text-xs font-medium uppercase tracking-wider transition-all hover:bg-muted"
|
|
>
|
|
Не сега
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<button
|
|
onClick={handleDismiss}
|
|
className="flex-shrink-0 text-muted-foreground transition-colors hover:text-foreground"
|
|
aria-label="Затвори"
|
|
>
|
|
<X className="h-4 w-4" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|