Files
folx-tv/client/src/components/push-prompt-banner.tsx
T
sebastjanartic 0248e83a15 Fix banner not disappearing after enabling notifications
Modify the push notification banner component to immediately dismiss the banner upon user acceptance, ensuring the Chrome permission prompt can appear without obstruction and providing clearer error handling for subscription failures.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 23852c00-4779-460a-9e0c-d09fee4b6c92
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: be1d64b0-1371-4911-84cb-b3bb4611974c
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/23852c00-4779-460a-9e0c-d09fee4b6c92/tdiozLO
Replit-Helium-Checkpoint-Created: true
2026-03-08 06:59:01 +00:00

100 lines
3.6 KiB
TypeScript

import { useState, useEffect } from "react";
import { Bell, X } from "lucide-react";
import { Button } from "@/components/ui/button";
import { useToast } from "@/hooks/use-toast";
import { isPushSupported, getExistingSubscription, subscribeToPush } from "@/lib/push-utils";
const DISMISS_KEY = "folx-push-prompt-dismissed";
const DISMISS_DAYS = 7;
export default function PushPromptBanner() {
const [visible, setVisible] = useState(false);
const { toast } = useToast();
useEffect(() => {
if (!isPushSupported()) return;
if (Notification.permission === "denied") return;
const dismissedAt = localStorage.getItem(DISMISS_KEY);
if (dismissedAt) {
const elapsed = Date.now() - parseInt(dismissedAt, 10);
if (elapsed < DISMISS_DAYS * 24 * 60 * 60 * 1000) return;
}
const timer = setTimeout(async () => {
const sub = await getExistingSubscription();
if (!sub) setVisible(true);
}, 5000);
return () => clearTimeout(timer);
}, []);
const dismiss = () => {
setVisible(false);
localStorage.setItem(DISMISS_KEY, Date.now().toString());
};
const accept = async () => {
dismiss();
try {
await subscribeToPush();
toast({ title: "Benachrichtigungen aktiviert", description: "Sie werden über neue Inhalte informiert." });
} catch (err) {
if (Notification.permission === "denied") {
toast({ title: "Benachrichtigungen blockiert", description: "Bitte erlauben Sie Benachrichtigungen in Ihren Browsereinstellungen.", variant: "destructive" });
} else {
console.error("Push subscription error:", err);
toast({ title: "Fehler", description: "Benachrichtigungen konnten nicht aktiviert werden. Bitte versuchen Sie es später erneut.", variant: "destructive" });
}
}
};
if (!visible) return null;
return (
<div className="fixed bottom-4 left-4 right-4 md:left-auto md:right-6 md:max-w-sm z-50 animate-in slide-in-from-bottom-4 fade-in duration-500 pointer-events-none" data-testid="push-prompt-banner">
<div className="bg-card border border-card-border rounded-xl shadow-2xl p-3 sm:p-4 pointer-events-auto">
<div className="flex items-start gap-3">
<div className="flex-shrink-0 w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center">
<Bell className="w-5 h-5 text-primary" />
</div>
<div className="flex-1 min-w-0">
<p className="font-semibold text-foreground text-sm" data-testid="text-push-prompt-title">
Nichts mehr verpassen!
</p>
<p className="text-xs text-muted-foreground mt-1">
Erhalten Sie Benachrichtigungen über neue Artikel und Videos von FOLX TV.
</p>
<div className="flex items-center gap-2 mt-3">
<Button
size="sm"
onClick={accept}
className="text-xs h-8"
data-testid="button-push-prompt-accept"
>
Ja, gerne!
</Button>
<Button
variant="ghost"
size="sm"
onClick={dismiss}
className="text-xs h-8 text-muted-foreground"
data-testid="button-push-prompt-dismiss"
>
Nein, danke
</Button>
</div>
</div>
<button
onClick={dismiss}
className="text-muted-foreground hover:text-foreground transition-colors"
data-testid="button-push-prompt-close"
>
<X className="w-4 h-4" />
</button>
</div>
</div>
</div>
);
}