/** * Client-side notification preference management * Stores user's per-review notification opt-in choices in localStorage */ interface NotificationPreferences { [reviewUri: string]: { stage2?: boolean stage3?: boolean } } const STORAGE_KEY = 'drydown:notification-prefs' export class NotificationService { /** * Get notification preferences for a specific review */ static getPreferences(reviewUri: string): { stage2: boolean; stage3: boolean } { const prefs = this.getAllPreferences() const reviewPrefs = prefs[reviewUri] || {} return { stage2: reviewPrefs.stage2 || false, stage3: reviewPrefs.stage3 || false } } /** * Set notification preference for a specific review stage */ static setPreference(reviewUri: string, stage: 'stage2' | 'stage3', enabled: boolean): void { const prefs = this.getAllPreferences() if (!prefs[reviewUri]) { prefs[reviewUri] = {} } prefs[reviewUri][stage] = enabled localStorage.setItem(STORAGE_KEY, JSON.stringify(prefs)) } /** * Check if user should be notified for a specific review + stage */ static shouldNotify(reviewUri: string, stage: 'stage2' | 'stage3'): boolean { const prefs = this.getPreferences(reviewUri) return prefs[stage] || false } /** * Request browser notification permission if needed * Returns true if permission is granted or was already granted */ static async requestPermission(): Promise { if (!('Notification' in window)) { return false } if (Notification.permission === 'granted') { return true } if (Notification.permission === 'default') { const result = await Notification.requestPermission() return result === 'granted' } return false } /** * Get all stored notification preferences */ private static getAllPreferences(): NotificationPreferences { try { const stored = localStorage.getItem(STORAGE_KEY) return stored ? JSON.parse(stored) : {} } catch (e) { console.error('Failed to parse notification preferences', e) return {} } } /** * Clear all notification preferences (for testing/debugging) */ static clearAll(): void { localStorage.removeItem(STORAGE_KEY) } }