import { Head, usePage } from '@inertiajs/react'; import { Bell, Camera, MapPin } from 'lucide-react'; import { useCallback, useEffect, useState } from 'react'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; import { Switch } from '@/components/ui/switch'; import { usePushNotification } from '@/hooks/use-push-notification'; import { edit } from '@/routes/permissions'; type PermissionStatus = 'granted' | 'denied' | 'prompt' | 'unknown'; const isPWA = () => { return ( window.matchMedia('(display-mode: standalone)').matches || (window.navigator as { standalone?: boolean }).standalone === true ); }; const getPlatform = (): 'android' | 'ios' | 'desktop' => { const ua = navigator.userAgent.toLowerCase(); if (/android/.test(ua)) { return 'android'; } if (/iphone|ipad|ipod/.test(ua)) { return 'ios'; } return 'desktop'; }; const getDeniedMessage = (appName: string): string => { if (!isPWA()) { return 'Izin ditolak. Klik ikon gembok di address bar untuk mengaktifkannya.'; } const platform = getPlatform(); switch (platform) { case 'android': return `Izin ditolak. Buka Pengaturan > Aplikasi > ${appName} > Izin untuk mengaktifkannya.`; case 'ios': return `Izin ditolak. Buka Pengaturan > ${appName} > Safari > Izin untuk mengaktifkannya.`; default: return `Izin ditolak. Buka Pengaturan sistem untuk mengaktifkan izin ${appName}.`; } }; function getInitialNotificationPermission(): PermissionStatus { if (!('Notification' in window)) { return 'denied'; } return Notification.permission as PermissionStatus; } function getInitialCameraPermission(): PermissionStatus { if (!navigator.mediaDevices) { return 'denied'; } return 'unknown'; } function getInitialLocationPermission(): PermissionStatus { if (!('geolocation' in navigator)) { return 'denied'; } return 'unknown'; } export default function Permissions() { const { vapidPublicKey } = usePage().props as { vapidPublicKey?: string }; const [notifications, setNotifications] = useState( getInitialNotificationPermission, ); const [camera, setCamera] = useState( getInitialCameraPermission, ); const [location, setLocation] = useState( getInitialLocationPermission, ); const [isSubscribing, setIsSubscribing] = useState(false); const { isSupported, requestPermission, subscribe, unsubscribe } = usePushNotification(); const appName = 'DST Collection'; const checkCameraPermission = useCallback(async () => { if (!navigator.mediaDevices) { setCamera('denied'); return; } try { const stream = await navigator.mediaDevices.getUserMedia({ video: true, }); stream.getTracks().forEach((track) => track.stop()); setCamera('granted'); } catch { if ('permissions' in navigator) { try { const result = await navigator.permissions.query({ name: 'camera' as PermissionName, }); setCamera(result.state as PermissionStatus); } catch { setCamera('denied'); } } else { setCamera('denied'); } } }, []); const checkLocationPermission = useCallback(async () => { if (!('geolocation' in navigator)) { setLocation('denied'); return; } navigator.geolocation.getCurrentPosition( () => setLocation('granted'), async () => { if ('permissions' in navigator) { try { const result = await navigator.permissions.query({ name: 'geolocation', }); setLocation(result.state as PermissionStatus); } catch { setLocation('denied'); } } else { setLocation('denied'); } }, ); }, []); useEffect(() => { // eslint-disable-next-line react-hooks/set-state-in-effect -- permission check on mount is safe checkCameraPermission(); checkLocationPermission(); }, [checkCameraPermission, checkLocationPermission]); const handleNotifications = async (checked: boolean) => { if (isSubscribing) { return; } if (checked) { if (!isSupported || !('Notification' in window)) { return; } if (Notification.permission === 'denied') { setNotifications('denied'); return; } setIsSubscribing(true); try { const result = await requestPermission(); setNotifications(result); if (result === 'granted' && vapidPublicKey) { await subscribe(vapidPublicKey); } } finally { setIsSubscribing(false); } } else { await unsubscribe(); setNotifications('prompt'); } }; const handleCamera = async (checked: boolean) => { if (checked) { try { const stream = await navigator.mediaDevices.getUserMedia({ video: true, }); stream.getTracks().forEach((track) => track.stop()); setCamera('granted'); } catch { setCamera('denied'); } } else { setCamera('prompt'); } }; const handleLocation = async (checked: boolean) => { if (checked) { navigator.geolocation.getCurrentPosition( () => setLocation('granted'), () => setLocation('denied'), ); } else { setLocation('prompt'); } }; const isDenied = (status: PermissionStatus) => status === 'denied'; const deniedMessage = getDeniedMessage(appName); return ( <>

Izin

Notifikasi Izinkan aplikasi mengirimkan notifikasi push ke perangkat Anda. {isDenied(notifications) && (

{deniedMessage}

)}
Kamera Izinkan aplikasi mengakses kamera perangkat Anda untuk mengambil foto atau video. {isDenied(camera) && (

{deniedMessage}

)}
Lokasi Izinkan aplikasi mengakses lokasi perangkat Anda untuk menyediakan layanan berbasis lokasi. {isDenied(location) && (

{deniedMessage}

)}
); }