# Daily Notification Plugin Integration Plan **Author**: Matthew Raymer **Date**: 2025-11-03 **Status**: 🎯 **PLANNING** - Feature planning phase **Feature**: Daily Notification Plugin Integration **Platform Scope**: Capacitor-only (Android/iOS) --- ## Executive Summary This plan outlines the integration of `@timesafari/daily-notification-plugin` into the TimeSafari application using the PlatformService interface pattern. The feature is implemented on all platforms via PlatformService, but only Capacitor platforms provide full functionality. Web and Electron platforms return `null` for unsupported operations. ### Key Requirements - **Platform**: All platforms (Capacitor provides full functionality, Web/Electron return null) - **Architecture**: PlatformService interface integration (all platforms implement, unsupported return null) - **Components**: AccountViewView integration (settings UI) with optional supporting components - **Store**: No store needed - state managed locally in AccountViewView --- ## Complexity Assessment ### Technical Complexity: **Medium** #### Code Changes - **Medium**: AccountViewView modification, optional supporting components - **Pattern**: Following PlatformService interface pattern (like camera, filesystem methods) - all platforms implement, unsupported return null - **Integration**: Plugin API integration with error handling - **UI Integration**: AccountViewView modification with new notification section and optional supporting components #### Platform Impact - **Single Platform**: Capacitor-only (Android/iOS) - **Conditional Loading**: Feature only loads on Capacitor platforms - **Graceful Degradation**: Web/Electron builds should not break when plugin unavailable #### Testing Requirements - **Comprehensive**: - Plugin availability detection - Permission request flows - Notification scheduling - Status checking - Cross-platform validation (ensure web/electron unaffected) - AccountViewView UI integration ### Dependency Complexity #### Internal Dependencies - **Medium**: - Optional supporting components (only if AccountViewView exceeds length limits) - Logger integration (replace console.* with project logger) - AccountViewView modifications - Settings schema updates #### External Dependencies - **Medium**: - `@timesafari/daily-notification-plugin` (external package) - `@capacitor/core` (already in project) - Capacitor core APIs - Platform detection utilities #### Infrastructure Dependencies - **Low**: - Package.json update (add plugin dependency) - Vite conditional imports for Capacitor builds only - No infrastructure changes required ### Risk Factors 1. **Plugin Availability**: Plugin may not be available in package registry - **Mitigation**: Verify package availability, consider local development setup 2. **Platform Implementation**: All platforms must implement interface methods - **Mitigation**: Follow PlatformService pattern - Capacitor provides full implementation, Web/Electron return null or throw errors 3. **Web/Electron Compatibility**: Feature must not break non-Capacitor builds - **Mitigation**: Use dynamic imports with platform checks, graceful fallbacks 4. **Store State Management**: Notification state persistence - **Mitigation**: State managed locally in AccountViewView - no store needed --- ## Platform Analysis ### Target Platform: Capacitor Only #### Capacitor Requirements - Android: API 21+ (already supported) - iOS: 13+ (already supported) - Native platform detection: `Capacitor.isNativePlatform()` #### Build Configuration - **Vite Config**: `vite.config.capacitor.mts` (already exists) - **Build Command**: `npm run build:capacitor` - **Conditional Import Pattern**: Dynamic import based on `process.env.VITE_PLATFORM === 'capacitor'` #### Platform Detection Strategy **Pattern**: PlatformService interface - all platforms implement methods **CRITICAL REQUIREMENT**: All notification scheduling components MUST hide themselves if the current device does not support scheduling. Components check PlatformService capabilities by calling methods and checking for `null` returns: ```typescript // Components check capability via PlatformService const platformService = PlatformServiceFactory.getInstance(); const status = await platformService.getDailyNotificationStatus(); if (status === null) { // Notifications not supported on this platform - hide UI return; } // Continue with notification features ``` **Why PlatformService Pattern?** - Consistent with existing platform capabilities (camera, filesystem) - All platforms implement the interface (contract compliance) - Unsupported platforms return `null` or throw clear errors - Components handle capability detection via method results, not environment variables **Component Visibility Requirements**: - **AccountViewView notification section**: Must use `v-if="notificationsSupported"` to hide section - **Supporting components** (if created): Must check platform support before rendering - **Any component providing scheduling UI**: Must verify `getDailyNotificationStatus() !== null` before showing scheduling controls ### Web/Electron Implementation Strategy #### Web Platform - **Implementation**: All notification methods implemented in `WebPlatformService` - **Behavior**: Methods return `null` for status/permissions, throw errors for scheduling - **UI**: Components check for `null` responses to hide notification UI - **Plugin Import**: No plugin imports - methods return null/throw errors directly #### Electron Platform - **Implementation**: All notification methods implemented in `ElectronPlatformService` - **Behavior**: Methods return `null` for status/permissions, throw errors for scheduling - **UI**: Components check for `null` responses to hide notification UI - **Plugin Import**: No plugin imports - methods return null/throw errors directly --- ## Architecture Design ### PlatformService Integration **Key Pattern**: Add notification methods directly to `PlatformService` interface, implemented on all platforms. Unsupported platforms return `null` or empty results. This follows the same pattern as other platform capabilities (camera, filesystem) where all platforms implement the interface, but unsupported platforms return null/empty results. ```typescript // src/services/PlatformService.ts - Add to interface export interface PlatformService { // ... existing methods ... // Daily notification operations /** * Get the status of scheduled daily notifications * @returns Promise resolving to notification status, or null if not supported */ getDailyNotificationStatus(): Promise; /** * Check notification permissions * @returns Promise resolving to permission status, or null if not supported */ checkNotificationPermissions(): Promise; /** * Request notification permissions * @returns Promise resolving to permission result, or null if not supported */ requestNotificationPermissions(): Promise; /** * Schedule a daily notification * @param options - Notification scheduling options * @returns Promise that resolves when scheduled, or rejects if not supported */ scheduleDailyNotification(options: ScheduleOptions): Promise; /** * Cancel scheduled daily notification * @returns Promise that resolves when cancelled, or rejects if not supported */ cancelDailyNotification(): Promise; /** * Configure native fetcher for background operations * @param config - Native fetcher configuration * @returns Promise that resolves when configured, or null if not supported */ configureNativeFetcher(config: NativeFetcherConfig): Promise; /** * Update starred plans for background fetcher * @param plans - Starred plan IDs * @returns Promise that resolves when updated, or null if not supported */ updateStarredPlans(plans: { planIds: string[] }): Promise; } ``` **Implementation Pattern**: - **CapacitorPlatformService**: Full implementation using `@timesafari/daily-notification-plugin` - **WebPlatformService**: Returns `null` for status/permissions, throws errors for scheduling operations - **ElectronPlatformService**: Returns `null` for status/permissions, throws errors for scheduling operations ### PlatformService Interface Extensions ```typescript // Types/interfaces for notification operations export interface NotificationStatus { isScheduled: boolean; scheduledTime?: string; // "HH:mm" format lastTriggered?: string; permissions: PermissionStatus; } export interface PermissionStatus { notifications: 'granted' | 'denied' | 'prompt'; exactAlarms?: 'granted' | 'denied' | 'prompt'; // Android only } export interface PermissionResult { notifications: boolean; exactAlarms?: boolean; // Android only } export interface ScheduleOptions { time: string; // "HH:mm" format in local time title: string; body: string; sound?: boolean; priority?: 'high' | 'normal' | 'low'; } export interface NativeFetcherConfig { apiServer: string; jwt: string; starredPlanHandleIds: string[]; } ``` **Implementation Behavior**: - **Capacitor**: Full implementation, all methods functional - **Web/Electron**: Status/permission methods return `null`, scheduling methods throw errors with clear messages ### Component Architecture #### Views Structure ``` src/views/ └── AccountViewView.vue (existing - add Daily Notifications section) ``` #### Supporting Components (Optional - Only if AccountViewView needs extraction) ``` src/components/notifications/ (optional) ├── NotificationToggle.vue (optional - extract toggle if AccountViewView too long) ├── NotificationTimePicker.vue (optional - extract time picker if needed) └── NotificationStatusDisplay.vue (optional - extract status display if needed) ``` **Note**: Supporting components should only be created if AccountViewView exceeds reasonable length limits (>200 lines). Keep everything in AccountViewView if possible. --- ## AccountViewView Integration Strategy ### Overview Integrate daily notification scheduling into `AccountViewView.vue`, allowing users to configure notification times directly from their account settings. ### Integration Approach ✅ **ACCEPTED** **Decision**: Create a separate "Daily Notifications" section This approach adds a dedicated "Daily Notifications" section that checks PlatformService capabilities. On Capacitor platforms, it provides full functionality. On other platforms, the UI is hidden when PlatformService returns `null` for notification methods. **Key Benefits**: - Uses PlatformService interface pattern (consistent with camera, filesystem) - Platform-specific features properly isolated - Can use native time picker (better UX on mobile) - Future-proof: Easy to extend with additional notification features - Graceful degradation on unsupported platforms ### UI Component Design #### 1. Platform Capability Detection ```typescript // In AccountViewView component async checkNotificationSupport(): Promise { const platformService = PlatformServiceFactory.getInstance(); const status = await platformService.getDailyNotificationStatus(); return status !== null; // null means not supported } ``` #### 2. State Management ```typescript // Component properties nativeNotificationEnabled: boolean = false; nativeNotificationTime: string = ""; // Display format: "9:00 AM" nativeNotificationTimeStorage: string = ""; // Plugin format: "09:00" nativeNotificationTitle: string = "Daily Update"; nativeNotificationMessage: string = "Your daily notification is ready!"; notificationsSupported: boolean = false; // Computed from PlatformService ``` #### 3. Template Section ```vue

Daily Notifications

Daily Notification
Scheduled for: {{ nativeNotificationTime }}
``` #### 4. Time Input ✅ **SELECTED: HTML5 Time Input** **Decision**: Use HTML5 `` for native mobile experience ```vue ``` **Benefits**: - Native mobile time picker UI on Capacitor platforms - Simpler implementation (no custom time parsing needed) - Automatic 24-hour format output (compatible with plugin) - System handles locale-specific time formatting - Better UX on mobile devices **Note**: HTML5 time input provides time in "HH:mm" format (24-hour) which matches the plugin's expected format perfectly. #### 5. Time Format Conversion (Using System Time) **Key Principle**: Use device's local system time - no timezone conversions needed. The plugin handles system time natively. ```typescript // Convert "09:00" (plugin storage format) to "9:00 AM" (display) function formatTimeForDisplay(time24: string): string { const [hours, minutes] = time24.split(':'); const hourNum = parseInt(hours); const isPM = hourNum >= 12; const displayHour = hourNum === 0 ? 12 : hourNum > 12 ? hourNum - 12 : hourNum; return `${displayHour}:${minutes} ${isPM ? 'PM' : 'AM'}`; } // HTML5 time input provides "HH:mm" in local time - use directly // No UTC conversion needed - plugin handles local timezone function getTimeFromInput(timeInput: string): string { // timeInput is already in "HH:mm" format from // This is in the user's local timezone - pass directly to plugin return timeInput; // e.g., "09:00" in user's local time } ``` **Time Handling**: - **PlatformService Integration**: Uses device's local system time directly - NO UTC conversion needed. The plugin schedules notifications on the device itself, using the device's timezone. **Implementation Principles**: - HTML5 `` provides time in device's local timezone - Plugin receives time in "HH:mm" format and schedules relative to device's local time - No manual timezone conversion or UTC calculations needed - System automatically handles: - Timezone changes - Daylight saving time transitions - Device timezone updates - User sets "9:00 AM" in their local time → plugin schedules for 9:00 AM local time every day ### Data Flow #### 1. Initialization ```typescript async initializeState() { // ... existing initialization ... const platformService = PlatformServiceFactory.getInstance(); // Check if notifications are supported on this platform const status = await platformService.getDailyNotificationStatus(); if (status === null) { // Notifications not supported - don't initialize this.notificationsSupported = false; return; } this.notificationsSupported = true; // Load from settings const nativeNotificationTime = settings.nativeNotificationTime || ""; this.nativeNotificationEnabled = !!nativeNotificationTime; this.nativeNotificationTimeStorage = nativeNotificationTime; if (nativeNotificationTime) { this.nativeNotificationTime = formatTimeForDisplay(nativeNotificationTime); } // Update UI with current status this.notificationStatus = status; } ``` #### 2. Enable Notification ```typescript async enableNativeNotification() { try { const platformService = PlatformServiceFactory.getInstance(); // 1. Request permissions if needed const permissions = await platformService.checkNotificationPermissions(); if (permissions === null || permissions.notifications !== 'granted') { const result = await platformService.requestNotificationPermissions(); if (result === null || !result.notifications) { throw new Error("Notification permissions denied"); } } // 2. Schedule notification via PlatformService // Time is in device's local system time (from HTML5 time input) // PlatformService handles timezone and scheduling internally await platformService.scheduleDailyNotification({ time: this.nativeNotificationTimeStorage, // "09:00" in local time title: this.nativeNotificationTitle, body: this.nativeNotificationMessage, sound: true, priority: 'high' }); // 3. Save to settings await this.$saveSettings({ nativeNotificationTime: this.nativeNotificationTimeStorage, nativeNotificationTitle: this.nativeNotificationTitle, nativeNotificationMessage: this.nativeNotificationMessage, }); // 4. Update UI state this.nativeNotificationEnabled = true; this.notify.success("Daily notification scheduled successfully", TIMEOUTS.SHORT); } catch (error) { logger.error("Failed to enable notification:", error); this.notify.error("Failed to schedule notification. Please try again.", TIMEOUTS.LONG); } } ``` #### 3. Disable Notification ```typescript async disableNativeNotification() { try { const platformService = PlatformServiceFactory.getInstance(); // 1. Cancel notification via PlatformService await platformService.cancelDailyNotification(); // 2. Clear settings await this.$saveSettings({ nativeNotificationTime: "", nativeNotificationTitle: "", nativeNotificationMessage: "", }); // 3. Update UI state this.nativeNotificationEnabled = false; this.nativeNotificationTime = ""; this.nativeNotificationTimeStorage = ""; this.notify.success("Daily notification disabled", TIMEOUTS.SHORT); } catch (error) { logger.error("Failed to disable native notification:", error); this.notify.error("Failed to disable notification. Please try again.", TIMEOUTS.LONG); } } ``` #### 4. Edit Time **Approach**: Use inline HTML5 time input for quick edits ```typescript async editNativeNotificationTime() { // Show inline HTML5 time input for quick changes this.showTimeEdit = true; } ``` **Implementation Note**: HTML5 time input provides native mobile picker experience when shown inline, making it ideal for quick time adjustments in AccountViewView. ### Settings Schema #### New Settings Fields ```typescript // Add to Settings interface in src/db/tables/settings.ts interface Settings { // ... existing fields ... // Native notification settings (Capacitor only) nativeNotificationTime?: string; // "09:00" format (24-hour) nativeNotificationTitle?: string; // Default: "Daily Update" nativeNotificationMessage?: string; // Default message } ``` #### Settings Persistence - Store in `settings` table via `$saveSettings()` - Use same pattern as `notifyingNewActivityTime` - Persist across app restarts - Sync with plugin state on component mount ### UI/UX Considerations #### Visual Design - **Section Style**: Match existing notification section (`bg-slate-100 rounded-md`) - **Toggle Switch**: Reuse existing custom toggle pattern - **Time Display**: Show in user-friendly format ("9:00 AM") - **Edit Button**: Small, subtle link/button to edit time #### User Feedback - **Success**: Toast notification when scheduled successfully - **Error**: Clear error message with troubleshooting guidance - **Loading**: Show loading state during plugin operations - **Permission Request**: Handle gracefully if denied #### Accessibility - **ARIA Labels**: Proper labels for all interactive elements - **Keyboard Navigation**: Full keyboard support - **Screen Reader**: Clear announcements for state changes ### Implementation Decisions ✅ #### Time Input Format ✅ - **Selected**: HTML5 `` for Capacitor platforms - **Rationale**: Native mobile experience, simpler code, automatic 24-hour format #### Edit Approach ✅ - **Selected**: Inline HTML5 time input for quick edits in AccountViewView - **Note**: All editing happens within AccountViewView - no separate views needed #### Settings Field Names ✅ - **Selected**: `nativeNotificationTime`, `nativeNotificationTitle`, `nativeNotificationMessage` - **Rationale**: Clear distinction from web push notification fields #### Notification Title/Message ✅ - **Selected**: Allow customization, default to "Daily Update" / "Your daily notification is ready!" - **Rationale**: Flexibility for users, sensible defaults --- ## Phase Breakdown ### Phase 1: Foundation & Infrastructure **Complexity**: Low-Medium **Goals**: Set up factory architecture, store, and conditional loading #### Tasks 1. **Package Dependency** - Add `@timesafari/daily-notification-plugin` to `package.json` - Verify package availability/version - Document in dependencies section 2. **PlatformService Interface Extension** - Add notification methods to `PlatformService` interface - Define notification types/interfaces (NotificationStatus, ScheduleOptions, etc.) - Implement in `CapacitorPlatformService` using `@timesafari/daily-notification-plugin` - Implement in `WebPlatformService` with null returns / error throws - Implement in `ElectronPlatformService` with null returns / error throws 3. **Settings Schema Extension** - Add notification settings fields to Settings interface - Update settings persistence methods if needed #### Acceptance Criteria - [ ] PlatformService interface extended with notification methods - [ ] CapacitorPlatformService implements notification methods using plugin - [ ] WebPlatformService and ElectronPlatformService return null/throw errors appropriately - [ ] Settings schema extended with notification fields - [ ] No build errors in web/electron builds --- ### Phase 2: AccountViewView Integration **Complexity**: Medium **Goals**: Integrate notification scheduling into AccountViewView with optional supporting components #### Tasks 1. **Supporting Components (Optional)** - Create supporting components only if AccountViewView exceeds length limits - Consider: `NotificationToggle.vue`, `NotificationTimePicker.vue`, `NotificationStatusDisplay.vue` - Follow project styling patterns - Add TypeScript interfaces - Keep components focused and reusable within AccountViewView context 2. **AccountViewView Integration** ✅ **ACCEPTED** - Add separate "Daily Notifications" section - Check platform capabilities before showing UI (`v-if="notificationsSupported"`) - Add computed property for platform capability detection - Add toggle switch for enabling/disabling notifications - Add HTML5 time input for scheduling time - Integrate with PlatformService via PlatformServiceFactory - Save/load settings from `settings` table - Implement time format conversion (display vs storage) - Add enable/disable notification methods - Add edit time functionality - Add permission request flow - Add error handling and user feedback #### Acceptance Criteria - [ ] Supporting components created only if AccountViewView exceeds length limits - [ ] AccountViewView has separate "Daily Notifications" section - [ ] **AccountViewView notification section hidden on unsupported platforms** (`v-if="notificationsSupported"`) - [ ] Notification section checks PlatformService capabilities before showing - [ ] Toggle and time input functional in AccountViewView - [ ] Settings persist across app restarts - [ ] Plugin state syncs with settings - [ ] All logging uses project logger - [ ] Error handling implemented - [ ] Loading states visible - [ ] UI matches existing design patterns --- ### Phase 3: Polish & Testing **Complexity**: Medium **Goals**: Complete AccountViewView integration, error handling, and testing #### Tasks 1. **Permission Management** - Implement permission request flow in AccountViewView - Handle permission denial gracefully - Update status after permission changes - Show appropriate user feedback 2. **Error Handling & User Feedback** - Add comprehensive error handling for all plugin operations - Implement loading states during async operations - Add success/error toast notifications - Handle edge cases (permission denied, plugin unavailable, etc.) 3. **Testing & Validation** - Test AccountViewView integration on Capacitor platforms - Verify component hiding on Web/Electron - Test all user workflows (enable, disable, edit time) - Verify settings persistence #### Acceptance Criteria - [ ] Permission requests handled properly - [ ] Status updates after permission changes - [ ] Error handling for all failure cases - [ ] User feedback (toasts, loading states) implemented - [ ] AccountViewView tested on all platforms - [ ] Component hiding verified on unsupported platforms --- --- ## Milestones ### Milestone 1: Foundation Complete **Success Criteria**: - PlatformService interface extended - Settings schema extended - No build regressions ### Milestone 2: AccountViewView Integration Complete **Success Criteria**: - AccountViewView notification section functional - Plugin integration working - Settings persistence working - Component hiding verified on unsupported platforms ### Milestone 3: Production Ready **Success Criteria**: - All tests passing - Cross-platform validation complete - Error handling robust - User feedback implemented - Documentation complete --- ## Testing Strategy ### Unit Tests - PlatformService platform detection - AccountViewView notification section rendering - Supporting component rendering (if created) ### Integration Tests - Plugin API calls from AccountViewView - Permission flows - Status updates - AccountViewView enable/disable/edit workflows - Settings persistence ### Platform Tests - **Capacitor Android**: Notification scheduling, permissions, status, AccountViewView UI - **Capacitor iOS**: Notification scheduling, permissions, status, AccountViewView UI - **Web**: Feature hidden, no errors, AccountViewView section hidden - **Electron**: Feature hidden, no errors, AccountViewView section hidden ### E2E Tests (Playwright) - AccountViewView notification configuration workflow - Permission request flow - Enable/disable notification workflow - Edit notification time workflow - Error handling scenarios --- ## Dependencies ### External Dependencies - `@timesafari/daily-notification-plugin` (to be added) - `@capacitor/core` (already in project) - `vue` (already in project) ### Internal Dependencies - Logger service (`@/utils/logger`) - Platform detection utilities - Existing component patterns - AccountViewView component - Settings schema and persistence ### Configuration Dependencies - **Settings Access**: Use `$accountSettings()` and `$saveSettings()` for persistence (existing) --- ## Implementation Notes ### Component Visibility Requirements **CRITICAL**: All components that provide notification scheduling UI MUST hide themselves if the current device does not support scheduling. #### Required Pattern for All Scheduling Components ```typescript // In component mounted/created lifecycle async mounted() { const platformService = PlatformServiceFactory.getInstance(); const status = await platformService.getDailyNotificationStatus(); if (status === null) { // Device does not support scheduling - hide component this.notificationsSupported = false; return; } // Device supports scheduling - proceed with initialization this.notificationsSupported = true; // ... rest of initialization } ``` #### Template Pattern ```vue
``` #### Components That Must Implement This Pattern 1. **AccountViewView.vue**: Daily Notifications section uses `v-if="notificationsSupported"` 2. **Supporting components** (if created): Must check support before rendering any scheduling UI 3. **Any component providing scheduling UI**: Must verify `getDailyNotificationStatus() !== null` before showing scheduling controls #### Verification Checklist - [ ] AccountViewView notification section hidden via `v-if` on unsupported platforms - [ ] Supporting components (if created) check and hide on unsupported platforms - [ ] All components tested on Web/Electron to verify hiding works - [ ] No console errors when components are hidden ### Code Quality Standards - **Logging**: Use `logger` from `@/utils/logger`, not `console.*` - **File Documentation**: Add file-level documentation headers - **Method Documentation**: Rich method-level documentation - **Type Safety**: Full TypeScript typing - **PEP8/Prettier**: Follow code style guidelines - **Line Length**: Keep methods < 80 columns when possible ### Architecture Patterns to Follow - **Service Interface**: Abstract interface with platform implementations - **Component Organization**: Keep AccountViewView concise - extract supporting components if needed to maintain < 200 lines - **PlatformService Pattern**: Check capabilities via method results, not environment variables ### PlatformService Integration Strategy **Pattern**: Direct integration into PlatformService interface (like camera, filesystem methods) ```typescript // In components - use PlatformServiceFactory pattern import { PlatformServiceFactory } from '@/services/PlatformServiceFactory'; const platformService = PlatformServiceFactory.getInstance(); // Check if notifications are supported const status = await platformService.getDailyNotificationStatus(); if (status === null) { // Notifications not supported on this platform - hide UI return; } // Schedule notification await platformService.scheduleDailyNotification({ time: "09:00", title: "Daily Update", body: "Your daily notification is ready!", }); ``` **Key Points**: - Methods available on all PlatformService implementations - CapacitorPlatformService provides full implementation - WebPlatformService/ElectronPlatformService return `null` or throw errors - Components check for `null` responses to hide/show UI appropriately - No separate factory needed - uses existing PlatformServiceFactory pattern --- ## Risk Mitigation ### Risk 1: Plugin Package Unavailable **Mitigation**: - Verify package exists and is accessible - Consider local development setup if needed - Document package installation requirements ### Risk 2: Platform Detection Failures **Mitigation**: - Use proven patterns from `QRScannerFactory` - Test on all platforms - Add fallback logic ### Risk 3: Web/Electron Build Breaks **Mitigation**: - Use dynamic imports exclusively - Test web/electron builds after each phase - Ensure no static plugin imports - Verify AccountViewView section properly hidden ### Risk 4: AccountViewView Integration Issues **Mitigation**: - Use platform capability detection before showing UI - Test on all platforms to ensure proper hiding - Follow existing UI patterns for consistency - Add comprehensive error handling ### Risk 5: Components Visible on Unsupported Platforms **Mitigation**: - **REQUIRED**: All scheduling components must check `getDailyNotificationStatus()` and hide if `null` - Use `v-if="notificationsSupported"` pattern consistently - Add explicit verification in acceptance criteria - Test on Web/Electron builds to verify hiding works - Document required pattern in Implementation Notes section --- ## Success Criteria Summary - [ ] Plugin integrated using PlatformService architecture - [ ] Feature works on Capacitor (Android/iOS) - [ ] Feature hidden/graceful on Web/Electron - [ ] AccountViewView integration complete and functional - [ ] **AccountViewView notification section hides itself on unsupported platforms** - [ ] Settings persist across app restarts - [ ] Logging standardized (no console.*) - [ ] Error handling robust - [ ] Cross-platform testing complete - [ ] **Verified component hiding on Web/Electron platforms** - [ ] Documentation updated - [ ] No build regressions --- ## Next Steps 1. **Verify Plugin Package**: Confirm `@timesafari/daily-notification-plugin` availability 2. **Extend PlatformService**: Add notification methods to PlatformService interface and implement in all platform services 3. **Extend Settings Schema**: Add notification fields to Settings interface 4. **Begin Phase 1 Implementation**: Start with foundation tasks 5. **AccountViewView Integration**: Implement Daily Notifications section in Phase 2 --- **See also**: - `.cursor/rules/meta_feature_planning.mdc` - Feature planning workflow - `.cursor/rules/app/architectural_patterns.mdc` - Architecture patterns - `.cursor/rules/app/timesafari_platforms.mdc` - Platform requirements - `src/services/QRScanner/QRScannerFactory.ts` - Factory pattern reference - `src/views/AccountViewView.vue` - Target component for integration