/** * TimeSafari Starred Plans Integration Example * * Demonstrates how to integrate the Daily Notification Plugin's starred plans * management with the TimeSafari app's starred projects functionality. * * This example shows: * 1. How to update starred plan IDs when users star/unstar projects * 2. How to sync starred plans on app startup * 3. How to verify stored plan IDs * * @author Matthew Raymer * @version 1.0.0 */ import { DailyNotification } from '@timesafari/daily-notification-plugin'; import { logger } from './logger'; // Assuming a logger utility /** * TimeSafari Starred Plans Manager * * Integrates with the Daily Notification Plugin to keep starred plan IDs * synchronized with the TimeSafari app's account settings. */ export class TimeSafariStarredPlansManager { private plugin: DailyNotification; private currentPlanIds: string[] = []; constructor(plugin: DailyNotification) { this.plugin = plugin; } /** * Sync starred plans from account settings to the plugin * * Call this when: * - App starts up * - User logs in * - Account settings are refreshed * * @param starredPlanHandleIds Array of plan handle IDs from account settings */ async syncStarredPlansFromAccount( starredPlanHandleIds: string[] ): Promise { try { logger.info('Syncing starred plans to plugin', { count: starredPlanHandleIds.length }); // Update plugin with current starred plan IDs const result = await this.plugin.updateStarredPlans({ planIds: starredPlanHandleIds }); if (result.success) { this.currentPlanIds = starredPlanHandleIds; logger.info('Starred plans synced successfully', { count: result.planIdsCount, updatedAt: new Date(result.updatedAt).toISOString() }); } else { logger.error('Failed to sync starred plans to plugin'); } } catch (error) { logger.error('Error syncing starred plans', error); throw error; } } /** * Update starred plans when a user stars a project * * Call this when: * - User clicks star on a project * - Star action completes successfully * * @param planHandleId The plan handle ID that was starred */ async addStarredPlan(planHandleId: string): Promise { try { // Get current starred plans from plugin (to avoid duplicate updates) const current = await this.plugin.getStarredPlans(); // Add new plan ID if not already present if (!current.planIds.includes(planHandleId)) { const updatedPlanIds = [...current.planIds, planHandleId]; await this.plugin.updateStarredPlans({ planIds: updatedPlanIds }); this.currentPlanIds = updatedPlanIds; logger.info('Starred plan added', { planHandleId }); } else { logger.debug('Plan already starred', { planHandleId }); } } catch (error) { logger.error('Error adding starred plan', error); throw error; } } /** * Update starred plans when a user unstars a project * * Call this when: * - User clicks unstar on a project * - Unstar action completes successfully * * @param planHandleId The plan handle ID that was unstarred */ async removeStarredPlan(planHandleId: string): Promise { try { // Get current starred plans from plugin const current = await this.plugin.getStarredPlans(); // Remove plan ID if present const updatedPlanIds = current.planIds.filter( id => id !== planHandleId ); if (updatedPlanIds.length !== current.planIds.length) { await this.plugin.updateStarredPlans({ planIds: updatedPlanIds }); this.currentPlanIds = updatedPlanIds; logger.info('Starred plan removed', { planHandleId }); } else { logger.debug('Plan not in starred list', { planHandleId }); } } catch (error) { logger.error('Error removing starred plan', error); throw error; } } /** * Get current starred plans from plugin * * Useful for verifying synchronization or displaying current state. * * @returns Current starred plan IDs stored in the plugin */ async getCurrentStarredPlans(): Promise { try { const result = await this.plugin.getStarredPlans(); this.currentPlanIds = result.planIds; return result.planIds; } catch (error) { logger.error('Error getting starred plans', error); throw error; } } /** * Verify starred plans synchronization * * Compares account settings with plugin storage to ensure they match. * Useful for debugging or validation after sync operations. * * @param accountPlanIds Plan IDs from account settings * @returns Object with sync status and any mismatches */ async verifySync(accountPlanIds: string[]): Promise<{ inSync: boolean; accountCount: number; pluginCount: number; mismatches: { inAccountNotPlugin: string[]; inPluginNotAccount: string[]; }; }> { try { const pluginResult = await this.plugin.getStarredPlans(); const pluginPlanIds = pluginResult.planIds; const inAccountNotPlugin = accountPlanIds.filter( id => !pluginPlanIds.includes(id) ); const inPluginNotAccount = pluginPlanIds.filter( id => !accountPlanIds.includes(id) ); const inSync = inAccountNotPlugin.length === 0 && inPluginNotAccount.length === 0; return { inSync, accountCount: accountPlanIds.length, pluginCount: pluginPlanIds.length, mismatches: { inAccountNotPlugin, inPluginNotAccount } }; } catch (error) { logger.error('Error verifying sync', error); throw error; } } } /** * Example integration with TimeSafari's searchStarred method * * This shows how to integrate the starred plans manager with the existing * TimeSafari searchStarred method. */ export async function integrateWithSearchStarred( plugin: DailyNotification, accountSettings: { starredPlanHandleIds?: string[] } ): Promise { const manager = new TimeSafariStarredPlansManager(plugin); try { // Get starred plan IDs from account settings const starredIds = accountSettings.starredPlanHandleIds || []; if (starredIds.length === 0) { logger.info('No starred plans to sync'); return; } // Sync to plugin await manager.syncStarredPlansFromAccount(starredIds); // Verify sync (optional, for debugging) const syncStatus = await manager.verifySync(starredIds); if (!syncStatus.inSync) { logger.warn('Starred plans sync verification failed', syncStatus); // Optionally retry sync if verification fails await manager.syncStarredPlansFromAccount(starredIds); } else { logger.info('Starred plans sync verified'); } } catch (error) { logger.error('Error integrating with searchStarred', error); // Don't throw - allow searchStarred to continue even if plugin sync fails } } /** * Example: Hook into star/unstar actions * * This shows how to update the plugin when users star or unstar projects. */ export async function handleStarAction( plugin: DailyNotification, planHandleId: string, isStarring: boolean ): Promise { const manager = new TimeSafariStarredPlansManager(plugin); try { if (isStarring) { await manager.addStarredPlan(planHandleId); } else { await manager.removeStarredPlan(planHandleId); } } catch (error) { logger.error('Error handling star action', error); // Don't throw - allow star action to complete even if plugin update fails } }