diff --git a/doc/daily-notification-accountview-integration-strategy.md b/doc/daily-notification-accountview-integration-strategy.md new file mode 100644 index 00000000..7d7fd374 --- /dev/null +++ b/doc/daily-notification-accountview-integration-strategy.md @@ -0,0 +1,472 @@ +# Daily Notification Plugin - AccountViewView Integration Strategy + +**Author**: Matthew Raymer +**Date**: 2025-11-03 +**Status**: 🎯 **PLANNING** - UI integration strategy +**Feature**: Daily Notification Scheduling in Account Settings + +--- + +## Overview + +This document outlines the strategy for integrating daily notification scheduling into `AccountViewView.vue`, allowing users to configure notification times directly from their account settings. + +--- + +## Current State Analysis + +### Account Settings Context + +**Location**: `AccountViewView.vue` - Settings view for user account configuration + +**Integration Approach**: Add new "Daily Notifications" section for scheduling native daily notifications using PlatformService. + +--- + +## Integration Strategy + +**Approach**: 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 + +**Implementation**: +```vue + +
+

+ Daily Notifications + +

+ +
+
Daily Notification
+ +
+ +
+
+ + +
+
+ Scheduled for: {{ nativeNotificationTime }} + +
+
+
+``` + +--- + +## Approach Rationale + +**Decision Date**: 2025-11-03 +**Status**: ✅ **ACCEPTED** - Will proceed with separate native notification section + +1. **Clear Platform Distinction**: Users understand this is for mobile apps +2. **No Conflicts**: Doesn't interfere with disabled web notifications +3. **Better UX**: Can use native time picker on mobile +4. **Future-Proof**: Easy to extend with additional native notification features + +### Implementation Status + +- [x] Approach decision finalized +- [ ] Implementation begins (Phase 1) + +--- + +## 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!"; +``` + +### 3. 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. + +### 4. 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 + return; + } + + // 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 + // For complex editing (title, message), navigate to ScheduleView + 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 + +--- + +## Plugin Integration + +### PlatformService Usage + +```typescript +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 +} +``` + +### Key Operations (via PlatformService) + +1. **Check Status**: `getDailyNotificationStatus()` - Returns status or `null` if unsupported +2. **Check Permissions**: `checkNotificationPermissions()` - Returns permissions or `null` if unsupported +3. **Request Permissions**: `requestNotificationPermissions()` - Requests permissions or returns `null` if unsupported +4. **Schedule**: `scheduleDailyNotification(options)` - Schedules notification or throws error if unsupported +5. **Cancel**: `cancelDailyNotification()` - Cancels notification or throws error if unsupported + +--- + +## 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 Phases + +### Phase 1: Basic Integration +- [ ] Add platform detection property +- [ ] Create native notification section in template +- [ ] Add component state properties +- [ ] Implement toggle functionality +- [ ] Basic enable/disable operations + +### Phase 2: Time Management +- [ ] Add time input (HTML5 time picker) +- [ ] Implement time format conversion +- [ ] Add edit time functionality +- [ ] Save/load time from settings + +### Phase 3: Plugin Integration +- [ ] Integrate with DailyNotificationFactory +- [ ] Schedule notification on enable +- [ ] Cancel notification on disable +- [ ] Update notification on time change +- [ ] Sync plugin state with settings + +### Phase 4: Polish & Error Handling +- [ ] Permission request flow +- [ ] Error handling and user feedback +- [ ] Status verification +- [ ] Help/info dialogs +- [ ] Accessibility improvements + +--- + +## 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**: For complex editing (title, message changes), users can navigate to dedicated ScheduleView + +### 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 + +--- + +## Success Criteria + +- [ ] Native notification section appears only on Capacitor platforms +- [ ] Toggle enables/disables notifications via plugin +- [ ] Time can be set and edited +- [ ] Settings persist across app restarts +- [ ] Plugin state syncs with settings +- [ ] Error handling provides clear user feedback +- [ ] UI matches existing design patterns +- [ ] Accessibility requirements met + +--- + +## Related Components + +- **PlatformService**: Interface for platform capabilities (notification methods) +- **PlatformServiceFactory**: Factory for getting platform service instance +- **ScheduleView**: Dedicated scheduling interface (for complex editing) +- **AccountViewView**: Main settings view (integration target) + +--- + +## Next Steps + +1. ~~**Decide on Approach**: Separate native notification section~~ ✅ **DECIDED** +2. **Define Settings Schema**: Add native notification fields to Settings interface +3. **Create UI Components**: Build notification section in AccountViewView +4. **Integrate Plugin**: Connect UI to DailyNotificationFactory service +5. **Test Flow**: Verify enable/disable/edit workflows +6. **Add Help Content**: Create help documentation for native notifications + +--- + +**See also**: +- `doc/daily-notification-plugin-integration-plan.md` - Overall integration plan +- `src/views/AccountViewView.vue` - Target component for integration +- `src/services/PlatformService.ts` - PlatformService interface definition +- `src/services/PlatformServiceFactory.ts` - Factory for platform service instances + diff --git a/doc/daily-notification-plugin-integration-plan.md b/doc/daily-notification-plugin-integration-plan.md new file mode 100644 index 00000000..ba07104a --- /dev/null +++ b/doc/daily-notification-plugin-integration-plan.md @@ -0,0 +1,658 @@ +# 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**: Home view (diagnostics/status) + Schedule view (time setting) +- **Store**: Pinia store for notification state management +- **Routes**: New routes for schedule, notifications, history, settings views + +--- + +## Complexity Assessment + +### Technical Complexity: **Medium** + +#### Code Changes +- **Medium**: New Vue components, Pinia store, router routes +- **Pattern**: Following PlatformService interface pattern (like camera, filesystem methods) - all platforms implement, unsupported return null +- **Integration**: Plugin API integration with error handling + +#### 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) + +### Dependency Complexity + +#### Internal Dependencies +- **Medium**: + - Router configuration (new routes) + - Store creation (Pinia) + - Component dependencies (ActionCard, StatusCard) + - Logger integration (replace console.* with project logger) + +#### External Dependencies +- **Medium**: + - `@timesafari/daily-notification-plugin` (external package) + - 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**: Follow existing Pinia patterns in codebase + +--- + +## 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 + +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 + +### 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/ + ├── HomeView.vue (existing - modify to add notification diagnostics) + ├── ScheduleView.vue (new - notification scheduling) + ├── NotificationsView.vue (new - view scheduled notifications) + ├── NotificationHistoryView.vue (new - notification history) + └── NotificationSettingsView.vue (new - notification settings) +``` + +#### Supporting Components +``` +src/components/cards/ + ├── ActionCard.vue (new - reusable action card) + └── StatusCard.vue (new - reusable status card) +``` + +#### Store Structure +``` +src/stores/ + └── app.ts (new - Pinia store for app-wide state) + - notificationStatus: NotificationStatus | null + - platform: 'web' | 'capacitor' | 'electron' + - setNotificationStatus(status): void +``` + +### Router Integration + +```typescript +// src/router/index.ts - Add new routes +{ + path: "/schedule", + name: "schedule", + component: () => import("../views/ScheduleView.vue"), +}, +{ + path: "/notifications", + name: "notifications", + component: () => import("../views/NotificationsView.vue"), +}, +{ + path: "/history", + name: "notification-history", + component: () => import("../views/NotificationHistoryView.vue"), +}, +{ + path: "/settings", + name: "settings", + component: () => import("../views/NotificationSettingsView.vue"), +}, +``` + +--- + +## 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. **Pinia Store Setup** + - Create `src/stores/app.ts` with notification state + - Define `NotificationStatus` interface + - Implement `setNotificationStatus()` action + - Add platform detection to store + +4. **Native Fetcher Configuration Integration** + - Update HomeView `configureNativeFetcher()` to use active DID management + - Replace `TEST_USER_ZERO_CONFIG` references with `$getActiveIdentity()` + - Replace `generateEndorserJWT` with `createEndorserJwtForDid()` from `src/libs/endorserServer.ts` + - Get `apiServer` and `starredPlanHandleIds` from `$accountSettings()` + +5. **Router Routes** + - Add route definitions for schedule, notifications, history, settings + - Test route navigation + +#### Acceptance Criteria +- [ ] PlatformService interface extended with notification methods +- [ ] CapacitorPlatformService implements notification methods using plugin +- [ ] WebPlatformService and ElectronPlatformService return null/throw errors appropriately +- [ ] Pinia store created and tested +- [ ] HomeView `configureNativeFetcher()` updated to use active DID (no TEST_USER_ZERO_CONFIG) +- [ ] Routes added and accessible +- [ ] No build errors in web/electron builds + +--- + +### Phase 2: Core Components + +**Complexity**: Medium +**Goals**: Create reusable components and main views + +#### Tasks +1. **Reusable Components** + - Create `ActionCard.vue` component + - Create `StatusCard.vue` component + - Follow project styling patterns + - Add TypeScript interfaces + +2. **Home View Integration** + - Modify existing `HomeView.vue` OR create new notification home view + - Integrate plugin diagnostics + - Add system status display + - Connect to Pinia store + - Replace `console.*` with project logger + +3. **Schedule View** + - Create `ScheduleView.vue` (provided code as reference) + - Integrate with PlatformService via PlatformServiceFactory + - Add error handling + - Replace `console.*` with project logger + - Add loading states + +4. **AccountViewView Integration** ✅ **ACCEPTED: Option A** + - Add separate "Daily Notifications" section + - Check platform capabilities before showing UI + - 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 + +#### Acceptance Criteria +- [ ] ActionCard and StatusCard components created +- [ ] Home view shows notification diagnostics +- [ ] Schedule view allows notification scheduling +- [ ] AccountViewView has separate "Daily Notifications" section (Option A accepted) +- [ ] Notification section checks PlatformService capabilities before showing +- [ ] Toggle and time input functional in AccountViewView +- [ ] All logging uses project logger +- [ ] Error handling implemented +- [ ] Loading states visible + +--- + +### Phase 3: Supporting Views & Configuration + +**Complexity**: Medium +**Goals**: Complete all views and native fetcher configuration + +#### Tasks +1. **Supporting Views** + - Create `NotificationsView.vue` (list scheduled notifications) + - Create `NotificationHistoryView.vue` (notification history) + - Create `NotificationSettingsView.vue` (settings/preferences) + +2. **Native Fetcher Configuration** + - Integrate `configureNativeFetcher()` in HomeView + - Use `$getActiveIdentity()` to get active DID (replace TEST_USER_ZERO_CONFIG) + - Use `createEndorserJwtForDid()` for JWT generation + - Get `apiServer` and `starredPlanHandleIds` from `$accountSettings()` + - Add error handling for configuration failures + +3. **Permission Management** + - Implement permission request flow + - Handle permission denial gracefully + - Update status after permission changes + +#### Acceptance Criteria +- [ ] All supporting views created and functional +- [ ] Native fetcher configuration working +- [ ] Permission requests handled properly +- [ ] Status updates after permission changes +- [ ] Error handling for all failure cases + +--- + +### Phase 4: Testing & Validation + +**Complexity**: Medium-High +**Goals**: Comprehensive testing across platforms and scenarios + +#### Tasks +1. **Capacitor Testing** + - Test plugin availability detection + - Test notification scheduling on Android + - Test notification scheduling on iOS + - Test permission requests + - Test status updates + - Test native fetcher configuration + +2. **Cross-Platform Validation** + - Verify web build doesn't break + - Verify Electron build doesn't break + - Verify feature is hidden on non-Capacitor platforms + - Test graceful degradation + +3. **Integration Testing** + - Test full scheduling workflow + - Test status checking workflow + - Test navigation between views + - Test store state persistence + +4. **Error Scenarios** + - Test plugin unavailable scenarios + - Test permission denied scenarios + - Test network failures (for native fetcher) + - Test invalid configuration scenarios + +#### Acceptance Criteria +- [ ] All Capacitor tests passing +- [ ] Web/Electron builds unaffected +- [ ] Integration tests passing +- [ ] Error scenarios handled gracefully +- [ ] Documentation updated + +--- + +## Milestones + +### Milestone 1: Foundation Complete +**Success Criteria**: +- Factory service operational +- Store created and tested +- Routes accessible +- No build regressions + +### Milestone 2: Core Features Operational +**Success Criteria**: +- Home view shows diagnostics +- Schedule view functional +- Plugin integration working +- Logging standardized + +### Milestone 3: Full Feature Set +**Success Criteria**: +- All views created and functional +- Native fetcher configured +- Permissions managed properly +- Status updates working + +### Milestone 4: Production Ready +**Success Criteria**: +- All tests passing +- Cross-platform validation complete +- Error handling robust +- Documentation complete + +--- + +## Testing Strategy + +### Unit Tests +- Factory service platform detection +- Store actions and state management +- Component rendering and interactions + +### Integration Tests +- Plugin API calls +- Permission flows +- Status updates +- Navigation between views + +### Platform Tests +- **Capacitor Android**: Notification scheduling, permissions, status +- **Capacitor iOS**: Notification scheduling, permissions, status +- **Web**: Feature hidden, no errors +- **Electron**: Feature hidden, no errors + +### E2E Tests (Playwright) +- Full notification scheduling workflow +- Permission request flow +- Status checking workflow +- Error handling scenarios + +--- + +## Dependencies + +### External Dependencies +- `@timesafari/daily-notification-plugin` (to be added) +- `@capacitor/core` (already in project) +- `vue` (already in project) +- `vue-router` (already in project) +- `pinia` (already in project) + +### Internal Dependencies +- Logger service (`@/utils/logger`) +- Platform detection utilities +- Router configuration +- Existing component patterns + +### Configuration Dependencies +- **Active DID Management**: Use `$getActiveIdentity()` from `PlatformServiceMixin` (existing) +- **JWT Generation**: Use `createEndorserJwtForDid(activeDid, payload)` from `src/libs/endorserServer.ts` (existing) +- **Settings Access**: Use `$accountSettings()` for `apiServer` and `starredPlanHandleIds` (existing) +- **No new config files needed**: Replace `TEST_USER_ZERO_CONFIG` references with active DID and settings + +--- + +## Implementation Notes + +### 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 +- **Factory Pattern**: Like `QRScannerFactory` for conditional loading +- **Service Interface**: Abstract interface with platform implementations +- **Store Pattern**: Pinia store for state management +- **Composition API vs Class**: Use provided code style (Composition API for HomeView, Class for ScheduleView) + +### 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 + +### Risk 4: Configuration Dependencies (RESOLVED) +**Mitigation**: +- **Use existing active DID management**: Use `$getActiveIdentity()` from `PlatformServiceMixin` to get currently selected DID +- **Use existing JWT generation**: Use `createEndorserJwtForDid(activeDid, payload)` from `src/libs/endorserServer.ts` +- **Use existing settings**: Get `apiServer` and `starredPlanHandleIds` from `$accountSettings()` +- **No config files needed**: The HomeView component code references `TEST_USER_ZERO_CONFIG`, but should instead use the currently active DID and settings + +--- + +## Success Criteria Summary + +- [ ] Plugin integrated using factory architecture +- [ ] Feature works on Capacitor (Android/iOS) +- [ ] Feature hidden/graceful on Web/Electron +- [ ] All components created and functional +- [ ] Store manages notification state +- [ ] Router routes accessible +- [ ] Logging standardized (no console.*) +- [ ] Error handling robust +- [ ] Cross-platform testing complete +- [ ] Documentation updated +- [ ] No build regressions + +--- + +## Next Steps + +1. **Verify Plugin Package**: Confirm `@timesafari/daily-notification-plugin` availability +2. **Update HomeView Configuration**: Replace `TEST_USER_ZERO_CONFIG` references in HomeView with existing active DID management (`$getActiveIdentity()`, `createEndorserJwtForDid()`, `$accountSettings()`) +3. **Extend PlatformService**: Add notification methods to PlatformService interface and implement in all platform services +4. **Set Up Store**: Create Pinia store for notification state +5. **Begin Phase 1 Implementation**: Start with foundation tasks + +--- + +**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