import * as Notifications from 'expo-notifications'; import Constants from 'expo-constants'; import { pb } from './pocketbase'; import { getOrCreateDeviceId } from './household'; Notifications.setNotificationHandler({ handleNotification: async () => ({ shouldShowAlert: true, shouldPlaySound: true, shouldSetBadge: false, shouldShowBanner: true, shouldShowList: true, }), }); export async function requestNotificationPermission(): Promise { const { status } = await Notifications.requestPermissionsAsync(); return status === 'granted'; } export async function getFcmToken(): Promise { try { const projectId = Constants.expoConfig?.extra?.eas?.projectId ?? (Constants as any).easConfig?.projectId; const token = await Notifications.getExpoPushTokenAsync( projectId ? { projectId } : {} ); return token.data; } catch { return null; } } export async function updateFcmToken(householdId: string, enabled: boolean): Promise { const deviceId = await getOrCreateDeviceId(); const token = enabled ? await getFcmToken() : null; const existing = await pb.collection('members').getFullList({ filter: `device_id = "${deviceId}" && household = "${householdId}"`, }); if (existing.length === 0) return; await pb.collection('members').update(existing[0].id, { fcm_token: token, notifications_enabled: enabled, }); } export async function sendShoppingListPush( householdId: string, itemName: string ): Promise { try { const deviceId = await getOrCreateDeviceId(); const members = await pb.collection('members').getFullList({ filter: `household = "${householdId}" && notifications_enabled = true && fcm_token != ""`, }); const tokens = members .filter((m) => m.device_id !== deviceId) .map((m) => m.fcm_token as string) .filter((t) => t?.startsWith('ExponentPushToken')); if (tokens.length === 0) return; await fetch('https://exp.host/--/api/v2/push/send', { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, body: JSON.stringify( tokens.map((to) => ({ to, title: 'Einkaufsliste', body: `${itemName} wurde hinzugefügt`, sound: 'default', })) ), }); } catch (e) { console.warn('sendShoppingListPush failed:', e); } } export async function scheduleExpiryCheck( items: Array<{ name: string; expiryDate: Date | null }> ) { await Notifications.cancelAllScheduledNotificationsAsync(); const now = new Date(); const threeDays = 3 * 24 * 60 * 60 * 1000; const expiringSoon = items.filter( (item) => item.expiryDate && item.expiryDate.getTime() - now.getTime() <= threeDays && item.expiryDate.getTime() > now.getTime() ); for (const item of expiringSoon) { await Notifications.scheduleNotificationAsync({ content: { title: 'MHD läuft ab', body: `${item.name} läuft in ≤ 3 Tagen ab!`, data: {}, }, trigger: null, }); } }