diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index fbabe0a..fb07fab 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -54,6 +54,7 @@ public function share(Request $request): array 'image' => url('/assets/logo.png'), 'url' => $request->url(), ], + 'vapidPublicKey' => config('webpush.vapid.public_key'), ]; } } diff --git a/resources/js/components/notifications/index.ts b/resources/js/components/notifications/index.ts index 514300b..a0f9ce8 100644 --- a/resources/js/components/notifications/index.ts +++ b/resources/js/components/notifications/index.ts @@ -1,4 +1,5 @@ export { default as AlertError } from './alert-error'; export { FlashToast } from './flash-toast'; export { NotificationBell } from './notification-bell'; +export { NotificationPermissionPrompt } from './notification-permission-prompt'; export { PWAUpdateToast } from './pwa-update-toast'; diff --git a/resources/js/components/notifications/notification-permission-prompt.tsx b/resources/js/components/notifications/notification-permission-prompt.tsx new file mode 100644 index 0000000..55350c5 --- /dev/null +++ b/resources/js/components/notifications/notification-permission-prompt.tsx @@ -0,0 +1,31 @@ +import { usePage } from '@inertiajs/react'; +import { useEffect, useRef } from 'react'; +import { usePushNotification } from '@/hooks/use-push-notification'; + +export function NotificationPermissionPrompt() { + const { vapidPublicKey } = usePage().props as { vapidPublicKey?: string }; + const hasRequested = useRef(false); + + const { isSupported, requestPermission, subscribe } = + usePushNotification(); + + useEffect(() => { + if (!isSupported || hasRequested.current) { + return; + } + + if (Notification.permission !== 'default') { + return; + } + + hasRequested.current = true; + + void requestPermission().then(async (result) => { + if (result === 'granted' && vapidPublicKey) { + await subscribe(vapidPublicKey); + } + }); + }, [isSupported, requestPermission, subscribe, vapidPublicKey]); + + return null; +} diff --git a/resources/js/layouts/app-layout.tsx b/resources/js/layouts/app-layout.tsx index 6ad0543..aecbf25 100644 --- a/resources/js/layouts/app-layout.tsx +++ b/resources/js/layouts/app-layout.tsx @@ -1,3 +1,4 @@ +import { NotificationPermissionPrompt } from '@/components/notifications/notification-permission-prompt'; import { Toaster } from '@/components/ui/sonner'; import AppLayoutTemplate from '@/layouts/app/app-sidebar-layout'; import type { BreadcrumbItem } from '@/types'; @@ -13,6 +14,7 @@ export default function AppLayout({ {children} + ); }