# Vue3 Notification Implementation Guide **Author**: Matthew Raymer **Date**: October 20, 2025 **Version**: 1.0.0 **Status**: Implementation Planning ## Overview This document provides a comprehensive guide for implementing scheduled local notifications and API-based change detection in the Vue3 example app using the DailyNotification plugin. It covers both basic notification scheduling and advanced TimeSafari API integration. ## Table of Contents 1. [Current Plugin Capabilities](#current-plugin-capabilities) 2. [Implementation Strategy](#implementation-strategy) 3. [Architecture Design](#architecture-design) 4. [Implementation Workflow](#implementation-workflow) 5. [UI/UX Considerations](#uiux-considerations) 6. [Technical Considerations](#technical-considerations) 7. [Success Metrics](#success-metrics) 8. [Code Examples](#code-examples) 9. [Testing Strategy](#testing-strategy) 10. [Deployment Checklist](#deployment-checklist) ## Current Plugin Capabilities ### Available Scheduling Methods The `DailyNotification` plugin provides several key methods for scheduling: #### 1. Basic Scheduling Methods - `scheduleDailyNotification(options)` - Simple daily notifications - `scheduleDailyReminder(options)` - More advanced reminder system - `scheduleContentFetch(config)` - Background content fetching - `scheduleUserNotification(config)` - User-facing notifications - `scheduleDualNotification(config)` - Combined content fetch + user notification #### 2. Available Parameters **Basic Notification Options:** ```typescript interface BasicNotificationOptions { time: string; // HH:mm format (e.g., "09:00") title: string; // Notification title body: string; // Notification message sound?: boolean; // Enable sound (default: true) priority?: string; // Priority level (default: "default") url?: string; // Optional deep link } ``` **Advanced Reminder Options:** ```typescript interface AdvancedReminderOptions { id: string; // Unique reminder identifier title: string; // Reminder title body: string; // Reminder message time: string; // HH:mm format sound?: boolean; // Enable sound (default: true) vibration?: boolean; // Enable vibration (default: true) priority?: string; // Priority level (default: "normal") repeatDaily?: boolean; // Repeat daily (default: true) timezone?: string; // Timezone (default: "UTC") } ``` ## Implementation Strategy ### Phase 1: Basic Scheduled Local Notifications #### 1.1 Enhance ScheduleView.vue **Current State:** ```typescript // Current TODO in ScheduleView.vue line 55: // TODO: call plugin ``` **Implementation:** ```typescript async scheduleNotification() { this.isScheduling = true try { const { DailyNotification } = await import('@timesafari/daily-notification-plugin') await DailyNotification.scheduleDailyNotification({ time: this.scheduleTime, title: this.notificationTitle, body: this.notificationMessage, sound: true, priority: "default" }) // Show success message this.showSuccessMessage('Notification scheduled successfully!') } catch (error) { console.error('Failed to schedule notification:', error) this.showErrorMessage('Failed to schedule notification: ' + error.message) } finally { this.isScheduling = false } } ``` #### 1.2 Create Reminder Management System **New Component: ReminderManager.vue** ```typescript interface Reminder { id: string title: string body: string time: string enabled: boolean lastTriggered?: number createdAt: number updatedAt: number } // Methods for managing reminders: - scheduleReminder(reminder: Reminder) - cancelReminder(id: string) - updateReminder(id: string, updates: Partial) - getScheduledReminders() - toggleReminder(id: string, enabled: boolean) ``` ### Phase 2: API-Based Change Detection #### 2.1 TimeSafari Integration Service **New Service: TimeSafariApiService.ts** ```typescript class TimeSafariApiService { private integrationService: TimeSafariIntegrationService private activeDid: string = '' private apiServer: string = 'https://endorser.ch' async initialize(activeDid: string, apiServer: string) { this.activeDid = activeDid this.apiServer = apiServer this.integrationService = TimeSafariIntegrationService.getInstance() await this.integrationService.initialize({ activeDid, storageAdapter: this.getStorageAdapter(), endorserApiBaseUrl: apiServer, starredProjectsConfig: { enabled: true, starredPlanHandleIds: [], lastAckedJwtId: '', fetchInterval: '0 8 * * *' // Daily at 8 AM } }) } async checkForChanges(): Promise { try { const changes = await this.integrationService.getStarredProjectsWithChanges( this.activeDid, this.starredPlanHandleIds, this.lastAckedJwtId ) return this.mapToChangeNotifications(changes) } catch (error) { console.error('Failed to check for changes:', error) return [] } } private mapToChangeNotifications(changes: any): ChangeNotification[] { // Map API response to change notifications return changes.data.map((change: any) => ({ id: change.id, type: this.determineChangeType(change), title: change.title || 'Project Update', message: change.description || 'A project you follow has been updated', timestamp: Date.now(), actionUrl: change.url })) } } ``` #### 2.2 Change Detection Workflow **Change Notification Interface:** ```typescript interface ChangeNotification { id: string type: 'offer' | 'project_update' | 'new_plan' | 'status_change' title: string message: string timestamp: number actionUrl?: string read: boolean dismissed: boolean } ``` **Implementation in HomeView.vue:** ```typescript async checkForApiChanges() { try { const changes = await this.timeSafariService.checkForChanges() if (changes.length > 0) { // Show notification for each change for (const change of changes) { await this.showChangeNotification(change) } // Update UI this.updateChangeIndicator(changes.length) // Store changes for history this.storeChangeHistory(changes) } } catch (error) { console.error('Failed to check for changes:', error) this.showErrorMessage('Failed to check for changes') } } async showChangeNotification(change: ChangeNotification) { try { await DailyNotification.scheduleUserNotification({ schedule: 'immediate', title: change.title, body: change.message, actions: [ { id: 'view', title: 'View' }, { id: 'dismiss', title: 'Dismiss' } ] }) } catch (error) { console.error('Failed to show change notification:', error) } } ``` ## Architecture Design ### Service Layer Structure ``` src/services/ ├── NotificationService.ts // Basic notification management ├── TimeSafariApiService.ts // API integration ├── ChangeDetectionService.ts // Change detection logic ├── ReminderService.ts // Reminder management └── StorageService.ts // Local storage management ``` ### Vue Components Enhancement ``` src/views/ ├── ScheduleView.vue // Enhanced with plugin integration ├── NotificationsView.vue // Full notification management ├── ChangeDetectionView.vue // New: API change monitoring ├── ReminderManagerView.vue // New: Reminder management └── ChangeHistoryView.vue // New: Change history display ``` ### Store Integration **Enhanced App Store:** ```typescript interface AppState { // Existing properties isLoading: boolean errorMessage: string | null platform: string isNative: boolean notificationStatus: NotificationStatus | null // New properties for notifications scheduledReminders: Reminder[] pendingChanges: ChangeNotification[] changeHistory: ChangeNotification[] apiConnectionStatus: 'connected' | 'disconnected' | 'error' lastChangeCheck: number notificationPreferences: NotificationPreferences } interface NotificationPreferences { enableScheduledReminders: boolean enableChangeNotifications: boolean enableSystemNotifications: boolean quietHoursStart: string quietHoursEnd: string preferredNotificationTimes: string[] changeTypes: string[] } ``` ## Implementation Workflow ### Step 1: Basic Notification Scheduling 1. **Enhance ScheduleView.vue** - Implement the TODO with plugin calls - Add form validation for time format and required fields - Add success/error message handling - Test scheduling functionality 2. **Add Error Handling** - Show user-friendly error messages - Handle permission denials gracefully - Provide fallback options when plugin unavailable 3. **Add Validation** - Ensure time format is HH:mm - Validate required fields (title, body, time) - Check for duplicate reminders 4. **Test Scheduling** - Verify notifications appear at scheduled times - Test on both Android and iOS platforms - Verify notification content and actions ### Step 2: Reminder Management 1. **Create ReminderService** - Implement CRUD operations for reminders - Add persistence using app store - Handle reminder state management 2. **Build ReminderManagerView** - Create UI for managing reminders - Add reminder creation/editing forms - Implement reminder list with actions 3. **Add Persistence** - Store reminders in app store - Add localStorage backup - Handle data migration 4. **Implement Cancellation** - Allow users to cancel/modify reminders - Handle reminder updates - Add bulk operations ### Step 3: API Integration 1. **Create TimeSafariApiService** - Implement API communication - Handle authentication (JWT/DID) - Add error handling and retry logic 2. **Implement Change Detection** - Poll for changes at configurable intervals - Handle different change types - Implement change filtering 3. **Add Change Notifications** - Show notifications when changes detected - Handle notification actions - Track notification engagement 4. **Add Change History** - Store change history - Provide history viewing interface - Implement change management (mark as read, dismiss) ### Step 4: Advanced Features 1. **Background Sync** - Use plugin's background fetching capabilities - Implement efficient polling strategies - Handle offline scenarios 2. **Smart Scheduling** - Adapt to user behavior patterns - Implement intelligent notification timing - Add user preference learning 3. **Change Filtering** - Allow users to filter change types - Implement notification preferences - Add quiet hours functionality 4. **Analytics** - Track notification effectiveness - Monitor user engagement - Collect performance metrics ## UI/UX Considerations ### Notification Types 1. **Scheduled Reminders** - User-initiated, recurring notifications - Customizable timing and content - User-controlled enable/disable 2. **Change Notifications** - API-triggered, immediate notifications - Contextual information and actions - Batch handling for multiple changes 3. **System Notifications** - Plugin status updates - Error notifications - Permission requests ### User Controls 1. **Enable/Disable Options** - Toggle different notification types - Granular control over notification sources - Quick enable/disable for all notifications 2. **Time Preferences** - Set preferred notification times - Configure quiet hours - Timezone handling 3. **Change Filters** - Choose which changes to be notified about - Filter by change type or source - Set notification frequency limits 4. **Visual Customization** - Custom notification sounds - Vibration patterns - Notification appearance options ### Visual Indicators 1. **Badge Counts** - Show pending changes count - Display unread notifications - Update in real-time 2. **Status Indicators** - API connection status - Plugin availability status - Last sync time 3. **History Views** - Show past notifications - Display change history - Provide search and filtering ## Technical Considerations ### Plugin Integration Points 1. **Permission Handling** - Request notification permissions on app start - Handle permission denials gracefully - Provide permission request retry mechanisms 2. **Platform Differences** - Handle Android/iOS notification differences - Adapt to platform-specific limitations - Test on multiple device types 3. **Error Recovery** - Handle plugin failures gracefully - Implement fallback notification methods - Provide user feedback on errors 4. **Background Execution** - Ensure background tasks work correctly - Handle app lifecycle events - Test background notification delivery ### API Integration Challenges 1. **Authentication** - Handle JWT/DID authentication - Manage token refresh - Handle authentication failures 2. **Rate Limiting** - Respect API rate limits - Implement exponential backoff - Handle rate limit exceeded errors 3. **Offline Handling** - Cache changes when offline - Sync when connection restored - Handle offline notification scenarios 4. **Error Handling** - Graceful degradation on API failures - Retry mechanisms for transient errors - User feedback for persistent errors ### Performance Optimization 1. **Efficient Polling** - Minimize API calls while maintaining responsiveness - Implement smart polling intervals - Use push notifications when available 2. **Caching** - Cache API responses appropriately - Implement cache invalidation strategies - Handle cache size limits 3. **Background Processing** - Use plugin's background capabilities - Minimize foreground processing - Optimize for battery life 4. **Memory Management** - Clean up old notifications/changes - Implement data retention policies - Monitor memory usage ## Success Metrics ### Notification Reliability 1. **Delivery Rate** - Percentage of notifications delivered successfully - Track delivery failures and reasons - Monitor platform-specific delivery rates 2. **Timing Accuracy** - How close notifications appear to scheduled time - Track timing variations across platforms - Monitor system clock accuracy impact 3. **User Engagement** - Click-through rates on notifications - User interaction with notification actions - Notification dismissal patterns ### Change Detection Effectiveness 1. **Detection Speed** - Time from change occurrence to notification - API response time monitoring - Background processing efficiency 2. **False Positives** - Unwanted or irrelevant notifications - User feedback on notification relevance - Filter effectiveness 3. **User Satisfaction** - User feedback on notification usefulness - Preference setting usage - Notification frequency satisfaction ### System Performance 1. **API Efficiency** - Minimal API calls for maximum coverage - Request/response size optimization - Network usage monitoring 2. **Battery Impact** - Battery drain from background processing - Notification frequency impact - Platform-specific optimization 3. **Storage Usage** - Efficient data storage - Cache size management - Data retention policy effectiveness ## Code Examples ### Complete ScheduleView.vue Implementation ```vue ``` ### TimeSafariApiService Implementation ```typescript /** * TimeSafari API Service * * Handles integration with TimeSafari API for change detection * and notification management. * * @author Matthew Raymer * @version 1.0.0 */ import { TimeSafariIntegrationService } from '@timesafari/daily-notification-plugin' export interface ChangeNotification { id: string type: 'offer' | 'project_update' | 'new_plan' | 'status_change' title: string message: string timestamp: number actionUrl?: string read: boolean dismissed: boolean } export interface TimeSafariConfig { activeDid: string apiServer: string starredPlanHandleIds: string[] lastAckedJwtId: string pollingInterval: number } export class TimeSafariApiService { private integrationService: TimeSafariIntegrationService | null = null private config: TimeSafariConfig | null = null private pollingTimer: NodeJS.Timeout | null = null private isPolling = false async initialize(config: TimeSafariConfig): Promise { try { this.config = config this.integrationService = TimeSafariIntegrationService.getInstance() await this.integrationService.initialize({ activeDid: config.activeDid, storageAdapter: this.getStorageAdapter(), endorserApiBaseUrl: config.apiServer, starredProjectsConfig: { enabled: true, starredPlanHandleIds: config.starredPlanHandleIds, lastAckedJwtId: config.lastAckedJwtId, fetchInterval: '0 8 * * *' // Daily at 8 AM } }) console.log('TimeSafari API Service initialized successfully') } catch (error) { console.error('Failed to initialize TimeSafari API Service:', error) throw error } } async checkForChanges(): Promise { if (!this.integrationService || !this.config) { throw new Error('Service not initialized') } try { const changes = await this.integrationService.getStarredProjectsWithChanges( this.config.activeDid, this.config.starredPlanHandleIds, this.config.lastAckedJwtId ) return this.mapToChangeNotifications(changes) } catch (error) { console.error('Failed to check for changes:', error) return [] } } startPolling(callback: (changes: ChangeNotification[]) => void): void { if (this.isPolling) { return } this.isPolling = true const poll = async () => { try { const changes = await this.checkForChanges() if (changes.length > 0) { callback(changes) } } catch (error) { console.error('Polling error:', error) } } // Initial poll poll() // Set up interval this.pollingTimer = setInterval(poll, this.config?.pollingInterval || 300000) // 5 minutes default } stopPolling(): void { if (this.pollingTimer) { clearInterval(this.pollingTimer) this.pollingTimer = null } this.isPolling = false } private mapToChangeNotifications(changes: any): ChangeNotification[] { if (!changes.data || !Array.isArray(changes.data)) { return [] } return changes.data.map((change: any) => ({ id: change.id || `change_${Date.now()}_${Math.random()}`, type: this.determineChangeType(change), title: change.title || 'Project Update', message: change.description || 'A project you follow has been updated', timestamp: Date.now(), actionUrl: change.url, read: false, dismissed: false })) } private determineChangeType(change: any): ChangeNotification['type'] { if (change.type) { return change.type } // Determine type based on content if (change.title?.toLowerCase().includes('offer')) { return 'offer' } else if (change.title?.toLowerCase().includes('project')) { return 'project_update' } else if (change.title?.toLowerCase().includes('new')) { return 'new_plan' } else { return 'status_change' } } private getStorageAdapter(): any { // Return appropriate storage adapter return { store: (key: string, value: any, ttl?: number) => { // Implementation depends on platform if (typeof localStorage !== 'undefined') { localStorage.setItem(key, JSON.stringify({ value, ttl, timestamp: Date.now() })) } }, retrieve: (key: string) => { if (typeof localStorage !== 'undefined') { const item = localStorage.getItem(key) if (item) { const { value, ttl, timestamp } = JSON.parse(item) if (ttl && Date.now() - timestamp > ttl) { localStorage.removeItem(key) return null } return value } } return null } } } } export default TimeSafariApiService ``` ## Testing Strategy ### Unit Tests 1. **Service Layer Testing** - Test notification scheduling logic - Test API integration methods - Test error handling scenarios 2. **Component Testing** - Test form validation - Test user interactions - Test state management 3. **Plugin Integration Testing** - Test plugin method calls - Test permission handling - Test platform differences ### Integration Tests 1. **End-to-End Notification Flow** - Test complete notification scheduling - Test notification delivery - Test user interactions 2. **API Integration Flow** - Test change detection - Test notification triggering - Test error scenarios 3. **Cross-Platform Testing** - Test on Android devices - Test on iOS devices - Test on web browsers ### Manual Testing 1. **Device Testing** - Test on various Android versions - Test on various iOS versions - Test on different screen sizes 2. **Network Testing** - Test with poor connectivity - Test offline scenarios - Test API failures 3. **User Experience Testing** - Test notification timing - Test user interface responsiveness - Test error message clarity ## Deployment Checklist ### Pre-Deployment - [ ] All unit tests passing - [ ] Integration tests passing - [ ] Manual testing completed - [ ] Code review completed - [ ] Documentation updated - [ ] Performance testing completed ### Deployment Steps 1. **Build Process** - [ ] Run `npm run build` - [ ] Run `npx cap sync android` - [ ] Run fix script for capacitor.plugins.json - [ ] Verify plugin registration 2. **Testing** - [ ] Test on Android device - [ ] Test notification scheduling - [ ] Test API integration - [ ] Test error handling 3. **Monitoring** - [ ] Monitor notification delivery rates - [ ] Monitor API response times - [ ] Monitor error rates - [ ] Monitor user feedback ### Post-Deployment - [ ] Monitor system performance - [ ] Collect user feedback - [ ] Track success metrics - [ ] Plan future improvements ## Conclusion This implementation guide provides a comprehensive roadmap for adding scheduled local notifications and API-based change detection to the Vue3 example app. The approach leverages the existing DailyNotification plugin capabilities while building a robust, user-friendly notification system. Key benefits of this implementation: 1. **Native-First Approach**: Uses platform-specific notification systems for reliable delivery 2. **Offline-First Design**: Works even when the app is closed or offline 3. **User-Controlled**: Provides granular control over notification preferences 4. **Scalable Architecture**: Supports future enhancements and additional notification types 5. **Cross-Platform**: Works consistently across Android, iOS, and web platforms The implementation follows the TimeSafari development principles of learning through implementation, designing for failure, and measuring everything to ensure a robust and reliable notification system.