diff --git a/src/components/PushBanner.tsx b/src/components/PushBanner.tsx new file mode 100644 index 0000000..03ad80a --- /dev/null +++ b/src/components/PushBanner.tsx @@ -0,0 +1,73 @@ +import { useState, useEffect } from 'react' +import { Bell, X } from 'lucide-react' +import { isPushSupported, subscribeToPush } from '../lib/push' +import { api } from '../lib/api' + +const DISMISSED_KEY = 'hotelsync-push-banner-dismissed' + +export function PushBanner() { + const [visible, setVisible] = useState(false) + const [loading, setLoading] = useState(false) + + useEffect(() => { + if (!isPushSupported()) return + if (typeof Notification === 'undefined') return + if (Notification.permission !== 'default') return + if (localStorage.getItem(DISMISSED_KEY)) return + // Show after 3s so the UI settles + const t = setTimeout(() => setVisible(true), 3000) + return () => clearTimeout(t) + }, []) + + if (!visible) return null + + const dismiss = () => { + setVisible(false) + localStorage.setItem(DISMISSED_KEY, '1') + } + + const enable = async () => { + setLoading(true) + try { + const result = await Notification.requestPermission() + if (result === 'granted') { + const { publicKey } = await api.push.getVapidKey() + if (publicKey) { + const sub = await subscribeToPush(publicKey) + if (sub) { + const json = sub.toJSON() + if (json.endpoint && json.keys?.p256dh && json.keys?.auth) { + await api.push.subscribe({ endpoint: json.endpoint, p256dh: json.keys.p256dh, auth: json.keys.auth }) + } + } + } + } + } catch { /**/ } + finally { + setLoading(false) + dismiss() + } + } + + return ( +
+ Включите уведомления, чтобы не пропускать сообщения +
+