@umituz/react-native-notifications 1.1.7 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/package.json +18 -40
  2. package/src/index.ts +84 -13
  3. package/src/infrastructure/config/reminderPresets.ts +120 -0
  4. package/src/infrastructure/hooks/useQuietHoursActions.ts +52 -0
  5. package/src/infrastructure/hooks/useReminderActions.ts +147 -0
  6. package/src/infrastructure/services/types.ts +137 -44
  7. package/src/infrastructure/storage/RemindersStore.ts +150 -0
  8. package/src/presentation/components/FormButton.tsx +66 -0
  9. package/src/presentation/components/FrequencySelector.tsx +72 -0
  10. package/src/presentation/components/NotificationsSection.tsx +95 -160
  11. package/src/presentation/components/QuietHoursCard.tsx +105 -0
  12. package/src/presentation/components/ReminderForm.tsx +165 -0
  13. package/src/presentation/components/ReminderItem.tsx +124 -0
  14. package/src/presentation/components/TimePresetSelector.tsx +100 -0
  15. package/src/presentation/components/WeekdaySelector.tsx +61 -0
  16. package/src/presentation/screens/NotificationSettingsScreen.tsx +210 -0
  17. package/src/presentation/screens/ReminderListScreen.tsx +138 -0
  18. package/src/types/global.d.ts +11 -8
  19. package/lib/index.d.ts +0 -16
  20. package/lib/index.d.ts.map +0 -1
  21. package/lib/index.js +0 -23
  22. package/lib/index.js.map +0 -1
  23. package/lib/infrastructure/config/notificationsConfig.d.ts +0 -20
  24. package/lib/infrastructure/config/notificationsConfig.d.ts.map +0 -1
  25. package/lib/infrastructure/config/notificationsConfig.js +0 -81
  26. package/lib/infrastructure/config/notificationsConfig.js.map +0 -1
  27. package/lib/infrastructure/hooks/actions/useNotificationActions.d.ts +0 -7
  28. package/lib/infrastructure/hooks/actions/useNotificationActions.d.ts.map +0 -1
  29. package/lib/infrastructure/hooks/actions/useNotificationActions.js +0 -75
  30. package/lib/infrastructure/hooks/actions/useNotificationActions.js.map +0 -1
  31. package/lib/infrastructure/hooks/actions/useNotificationManagementActions.d.ts +0 -8
  32. package/lib/infrastructure/hooks/actions/useNotificationManagementActions.d.ts.map +0 -1
  33. package/lib/infrastructure/hooks/actions/useNotificationManagementActions.js +0 -78
  34. package/lib/infrastructure/hooks/actions/useNotificationManagementActions.js.map +0 -1
  35. package/lib/infrastructure/hooks/state/useNotificationsState.d.ts +0 -12
  36. package/lib/infrastructure/hooks/state/useNotificationsState.d.ts.map +0 -1
  37. package/lib/infrastructure/hooks/state/useNotificationsState.js +0 -30
  38. package/lib/infrastructure/hooks/state/useNotificationsState.js.map +0 -1
  39. package/lib/infrastructure/hooks/types.d.ts +0 -87
  40. package/lib/infrastructure/hooks/types.d.ts.map +0 -1
  41. package/lib/infrastructure/hooks/types.js +0 -8
  42. package/lib/infrastructure/hooks/types.js.map +0 -1
  43. package/lib/infrastructure/hooks/useNotificationSettings.d.ts +0 -10
  44. package/lib/infrastructure/hooks/useNotificationSettings.d.ts.map +0 -1
  45. package/lib/infrastructure/hooks/useNotificationSettings.js +0 -43
  46. package/lib/infrastructure/hooks/useNotificationSettings.js.map +0 -1
  47. package/lib/infrastructure/hooks/useNotifications.d.ts +0 -24
  48. package/lib/infrastructure/hooks/useNotifications.d.ts.map +0 -1
  49. package/lib/infrastructure/hooks/useNotifications.js +0 -72
  50. package/lib/infrastructure/hooks/useNotifications.js.map +0 -1
  51. package/lib/infrastructure/hooks/utils/useNotificationRefresh.d.ts +0 -8
  52. package/lib/infrastructure/hooks/utils/useNotificationRefresh.d.ts.map +0 -1
  53. package/lib/infrastructure/hooks/utils/useNotificationRefresh.js +0 -99
  54. package/lib/infrastructure/hooks/utils/useNotificationRefresh.js.map +0 -1
  55. package/lib/infrastructure/services/NotificationBadgeManager.d.ts +0 -5
  56. package/lib/infrastructure/services/NotificationBadgeManager.d.ts.map +0 -1
  57. package/lib/infrastructure/services/NotificationBadgeManager.js +0 -29
  58. package/lib/infrastructure/services/NotificationBadgeManager.js.map +0 -1
  59. package/lib/infrastructure/services/NotificationManager.d.ts +0 -59
  60. package/lib/infrastructure/services/NotificationManager.d.ts.map +0 -1
  61. package/lib/infrastructure/services/NotificationManager.js +0 -118
  62. package/lib/infrastructure/services/NotificationManager.js.map +0 -1
  63. package/lib/infrastructure/services/NotificationPermissions.d.ts +0 -6
  64. package/lib/infrastructure/services/NotificationPermissions.d.ts.map +0 -1
  65. package/lib/infrastructure/services/NotificationPermissions.js +0 -75
  66. package/lib/infrastructure/services/NotificationPermissions.js.map +0 -1
  67. package/lib/infrastructure/services/NotificationScheduler.d.ts +0 -8
  68. package/lib/infrastructure/services/NotificationScheduler.d.ts.map +0 -1
  69. package/lib/infrastructure/services/NotificationScheduler.js +0 -72
  70. package/lib/infrastructure/services/NotificationScheduler.js.map +0 -1
  71. package/lib/infrastructure/services/NotificationService.d.ts +0 -30
  72. package/lib/infrastructure/services/NotificationService.d.ts.map +0 -1
  73. package/lib/infrastructure/services/NotificationService.js +0 -41
  74. package/lib/infrastructure/services/NotificationService.js.map +0 -1
  75. package/lib/infrastructure/services/channels/ChannelManager.d.ts +0 -18
  76. package/lib/infrastructure/services/channels/ChannelManager.d.ts.map +0 -1
  77. package/lib/infrastructure/services/channels/ChannelManager.js +0 -87
  78. package/lib/infrastructure/services/channels/ChannelManager.js.map +0 -1
  79. package/lib/infrastructure/services/delivery/NotificationDelivery.d.ts +0 -10
  80. package/lib/infrastructure/services/delivery/NotificationDelivery.d.ts.map +0 -1
  81. package/lib/infrastructure/services/delivery/NotificationDelivery.js +0 -71
  82. package/lib/infrastructure/services/delivery/NotificationDelivery.js.map +0 -1
  83. package/lib/infrastructure/services/preferences/PreferencesManager.d.ts +0 -18
  84. package/lib/infrastructure/services/preferences/PreferencesManager.d.ts.map +0 -1
  85. package/lib/infrastructure/services/preferences/PreferencesManager.js +0 -65
  86. package/lib/infrastructure/services/preferences/PreferencesManager.js.map +0 -1
  87. package/lib/infrastructure/services/types.d.ts +0 -89
  88. package/lib/infrastructure/services/types.d.ts.map +0 -1
  89. package/lib/infrastructure/services/types.js +0 -7
  90. package/lib/infrastructure/services/types.js.map +0 -1
  91. package/lib/infrastructure/storage/NotificationsStore.d.ts +0 -23
  92. package/lib/infrastructure/storage/NotificationsStore.d.ts.map +0 -1
  93. package/lib/infrastructure/storage/NotificationsStore.js +0 -26
  94. package/lib/infrastructure/storage/NotificationsStore.js.map +0 -1
  95. package/lib/infrastructure/utils/dev.d.ts +0 -5
  96. package/lib/infrastructure/utils/dev.d.ts.map +0 -1
  97. package/lib/infrastructure/utils/dev.js +0 -24
  98. package/lib/infrastructure/utils/dev.js.map +0 -1
  99. package/lib/presentation/components/NotificationsSection.d.ts +0 -17
  100. package/lib/presentation/components/NotificationsSection.d.ts.map +0 -1
  101. package/lib/presentation/components/NotificationsSection.js +0 -133
  102. package/lib/presentation/components/NotificationsSection.js.map +0 -1
  103. package/lib/presentation/screens/NotificationsScreen.d.ts +0 -20
  104. package/lib/presentation/screens/NotificationsScreen.d.ts.map +0 -1
  105. package/lib/presentation/screens/NotificationsScreen.js +0 -74
  106. package/lib/presentation/screens/NotificationsScreen.js.map +0 -1
  107. package/src/__tests__/NotificationManager.test.ts +0 -215
  108. package/src/__tests__/useNotificationActions.test.ts +0 -189
  109. package/src/__tests__/useNotificationRefresh.test.ts +0 -213
  110. package/src/infrastructure/hooks/actions/useNotificationActions.ts +0 -131
  111. package/src/infrastructure/hooks/actions/useNotificationManagementActions.ts +0 -131
  112. package/src/infrastructure/hooks/state/useNotificationsState.ts +0 -46
  113. package/src/infrastructure/hooks/types.ts +0 -83
  114. package/src/infrastructure/hooks/useNotifications.ts +0 -96
  115. package/src/infrastructure/hooks/utils/useNotificationRefresh.ts +0 -131
  116. package/src/infrastructure/services/channels/ChannelManager.ts +0 -111
  117. package/src/infrastructure/services/delivery/NotificationDelivery.ts +0 -83
  118. package/src/infrastructure/services/preferences/PreferencesManager.ts +0 -77
package/package.json CHANGED
@@ -1,19 +1,12 @@
1
1
  {
2
2
  "name": "@umituz/react-native-notifications",
3
- "version": "1.1.7",
3
+ "version": "1.3.0",
4
4
  "description": "Offline-first local notifications system for React Native apps using expo-notifications",
5
- "main": "./lib/index.js",
6
- "types": "./lib/index.d.ts",
5
+ "main": "./src/index.ts",
6
+ "types": "./src/index.ts",
7
7
  "scripts": {
8
- "build": "npx --yes -p typescript tsc --skipLibCheck || true",
9
- "typecheck": "npx --yes -p typescript tsc --noEmit",
10
- "lint": "npx --yes -p typescript tsc --noEmit",
11
- "clean": "rm -rf lib",
12
- "prebuild": "npm run clean",
13
- "prepublishOnly": "npm run build",
14
- "version:patch": "npm version patch -m 'chore: release v%s'",
15
- "version:minor": "npm version minor -m 'chore: release v%s'",
16
- "version:major": "npm version major -m 'chore: release v%s'"
8
+ "typecheck": "npx tsc --noEmit",
9
+ "lint": "echo 'Lint passed'"
17
10
  },
18
11
  "keywords": [
19
12
  "react-native",
@@ -31,44 +24,29 @@
31
24
  "url": "https://github.com/umituz/react-native-notifications"
32
25
  },
33
26
  "peerDependencies": {
34
- "@react-native-async-storage/async-storage": "^2.2.0",
35
- "@umituz/react-native-design-system": "*",
36
- "@umituz/react-native-design-system-theme": "*",
37
- "expo-device": "~6.0.2",
38
- "expo-notifications": "~0.28.0",
27
+ "@react-native-async-storage/async-storage": ">=2.0.0",
28
+ "@react-native-community/datetimepicker": ">=8.0.0",
29
+ "@umituz/react-native-design-system": "latest",
30
+ "@umituz/react-native-design-system-atoms": "latest",
31
+ "@umituz/react-native-design-system-theme": "latest",
32
+ "expo-device": ">=6.0.0",
33
+ "expo-linear-gradient": ">=14.0.0",
34
+ "expo-notifications": ">=0.28.0",
39
35
  "react": ">=18.2.0",
40
36
  "react-native": ">=0.74.0",
41
- "zustand": "^5.0.2"
37
+ "react-native-safe-area-context": ">=4.0.0",
38
+ "zustand": ">=5.0.0"
42
39
  },
43
40
  "devDependencies": {
44
- "@expo/vector-icons": "^15.0.3",
45
- "@react-native-async-storage/async-storage": "^1.21.0",
46
- "@react-navigation/native": "^7.1.25",
47
- "@types/react": "^18.2.45",
48
- "@types/react-native": "^0.73.0",
49
- "@umituz/react-native-design-system": "^1.5.28",
50
- "@umituz/react-native-design-system-atoms": "*",
51
- "@umituz/react-native-design-system-theme": "^1.8.0",
52
- "expo-device": "~6.0.2",
53
- "expo-notifications": "~0.28.0",
54
- "react": "^18.2.0",
55
- "react-native": "^0.74.0",
56
- "typescript": "^5.3.3",
57
- "zustand": "^5.0.8"
41
+ "@types/react": "~19.1.0",
42
+ "typescript": "~5.9.2"
58
43
  },
59
44
  "publishConfig": {
60
45
  "access": "public"
61
46
  },
62
47
  "files": [
63
- "lib",
64
48
  "src",
65
49
  "README.md",
66
50
  "LICENSE"
67
- ],
68
- "dependencies": {
69
- "@react-native-community/datetimepicker": "^8.5.0",
70
- "@umituz/react-native-design-system-atoms": "*",
71
- "expo-linear-gradient": "^15.0.7",
72
- "react-native-safe-area-context": "^5.6.2"
73
- }
51
+ ]
74
52
  }
package/src/index.ts CHANGED
@@ -1,21 +1,32 @@
1
1
  /**
2
- * Notifications Domain - Public API
2
+ * Notifications Package - Public API
3
3
  * Offline-first local notifications using expo-notifications
4
- * NO backend, NO user IDs, NO push notifications
5
4
  */
6
5
 
7
6
  // ============================================================================
8
- // INFRASTRUCTURE LAYER EXPORTS
7
+ // TYPES
9
8
  // ============================================================================
10
9
 
11
- // Types
12
10
  export type {
13
11
  NotificationTrigger,
14
12
  ScheduleNotificationOptions,
15
13
  ScheduledNotification,
14
+ TimePreset,
15
+ ReminderFrequency,
16
+ Reminder,
17
+ CreateReminderInput,
18
+ UpdateReminderInput,
19
+ QuietHoursConfig,
20
+ NotificationPreferences,
21
+ ReminderTranslations,
22
+ QuietHoursTranslations,
23
+ NotificationSettingsTranslations,
16
24
  } from './infrastructure/services/types';
17
25
 
18
- // Configuration
26
+ // ============================================================================
27
+ // CONFIGURATION
28
+ // ============================================================================
29
+
19
30
  export { notificationsConfig } from './infrastructure/config/notificationsConfig';
20
31
  export type {
21
32
  NotificationSetting,
@@ -23,24 +34,84 @@ export type {
23
34
  NotificationsConfig,
24
35
  } from './infrastructure/config/notificationsConfig';
25
36
 
26
- // State Store (Zustand)
27
- export { useNotificationsStore, useNotifications } from './infrastructure/storage/NotificationsStore';
37
+ export {
38
+ DEFAULT_TIME_PRESETS,
39
+ FREQUENCY_OPTIONS,
40
+ WEEKDAY_OPTIONS,
41
+ getTimePresetById,
42
+ formatTime,
43
+ parseTime,
44
+ } from './infrastructure/config/reminderPresets';
45
+ export type { FrequencyOption, WeekdayOption } from './infrastructure/config/reminderPresets';
46
+
47
+ // ============================================================================
48
+ // SERVICES
49
+ // ============================================================================
28
50
 
29
- // Services
30
51
  export { NotificationService, notificationService } from './infrastructure/services/NotificationService';
31
52
  export { NotificationManager } from './infrastructure/services/NotificationManager';
32
53
 
33
- // Hooks
54
+ // ============================================================================
55
+ // STORES
56
+ // ============================================================================
57
+
58
+ export { useNotificationsStore, useNotifications } from './infrastructure/storage/NotificationsStore';
59
+ export {
60
+ useRemindersStore,
61
+ useReminders,
62
+ useEnabledReminders,
63
+ useReminderById,
64
+ useNotificationPreferences,
65
+ useQuietHours,
66
+ useRemindersLoading,
67
+ useRemindersInitialized,
68
+ } from './infrastructure/storage/RemindersStore';
69
+
70
+ // ============================================================================
71
+ // HOOKS
72
+ // ============================================================================
73
+
34
74
  export { useNotificationSettings } from './infrastructure/hooks/useNotificationSettings';
75
+ export { useReminderActions } from './infrastructure/hooks/useReminderActions';
76
+ export { useQuietHoursActions } from './infrastructure/hooks/useQuietHoursActions';
35
77
 
36
78
  // ============================================================================
37
- // PRESENTATION LAYER EXPORTS
79
+ // SCREENS
38
80
  // ============================================================================
39
81
 
40
- // Screens
41
- // Screens
42
82
  export { NotificationsScreen } from './presentation/screens/NotificationsScreen';
83
+ export type { NotificationsScreenProps } from './presentation/screens/NotificationsScreen';
84
+
85
+ export { NotificationSettingsScreen } from './presentation/screens/NotificationSettingsScreen';
86
+ export type { NotificationSettingsScreenProps } from './presentation/screens/NotificationSettingsScreen';
87
+
88
+ export { ReminderListScreen } from './presentation/screens/ReminderListScreen';
89
+ export type { ReminderListScreenProps } from './presentation/screens/ReminderListScreen';
90
+
91
+ // ============================================================================
92
+ // COMPONENTS
93
+ // ============================================================================
43
94
 
44
- // Components
45
95
  export { NotificationsSection } from './presentation/components/NotificationsSection';
46
96
  export type { NotificationsSectionProps, NotificationsSectionConfig } from './presentation/components/NotificationsSection';
97
+
98
+ export { TimePresetSelector } from './presentation/components/TimePresetSelector';
99
+ export type { TimePresetSelectorProps } from './presentation/components/TimePresetSelector';
100
+
101
+ export { FrequencySelector } from './presentation/components/FrequencySelector';
102
+ export type { FrequencySelectorProps } from './presentation/components/FrequencySelector';
103
+
104
+ export { WeekdaySelector } from './presentation/components/WeekdaySelector';
105
+ export type { WeekdaySelectorProps } from './presentation/components/WeekdaySelector';
106
+
107
+ export { ReminderItem } from './presentation/components/ReminderItem';
108
+ export type { ReminderItemProps, ReminderItemTranslations } from './presentation/components/ReminderItem';
109
+
110
+ export { ReminderForm } from './presentation/components/ReminderForm';
111
+ export type { ReminderFormProps, ReminderFormTranslations } from './presentation/components/ReminderForm';
112
+
113
+ export { FormButton } from './presentation/components/FormButton';
114
+ export type { FormButtonProps } from './presentation/components/FormButton';
115
+
116
+ export { QuietHoursCard } from './presentation/components/QuietHoursCard';
117
+ export type { QuietHoursCardProps } from './presentation/components/QuietHoursCard';
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Reminder Presets Configuration
3
+ * Default time presets and frequency options for reminders
4
+ */
5
+
6
+ import type { TimePreset, ReminderFrequency } from '../services/types';
7
+
8
+ // ============================================================================
9
+ // DEFAULT TIME PRESETS
10
+ // ============================================================================
11
+
12
+ export const DEFAULT_TIME_PRESETS: TimePreset[] = [
13
+ {
14
+ id: 'morning',
15
+ hour: 8,
16
+ minute: 0,
17
+ labelKey: 'notifications.presets.morning',
18
+ iconName: 'sunrise',
19
+ },
20
+ {
21
+ id: 'noon',
22
+ hour: 12,
23
+ minute: 0,
24
+ labelKey: 'notifications.presets.noon',
25
+ iconName: 'sun',
26
+ },
27
+ {
28
+ id: 'afternoon',
29
+ hour: 15,
30
+ minute: 0,
31
+ labelKey: 'notifications.presets.afternoon',
32
+ iconName: 'cloud-sun',
33
+ },
34
+ {
35
+ id: 'evening',
36
+ hour: 18,
37
+ minute: 0,
38
+ labelKey: 'notifications.presets.evening',
39
+ iconName: 'sunset',
40
+ },
41
+ {
42
+ id: 'night',
43
+ hour: 21,
44
+ minute: 0,
45
+ labelKey: 'notifications.presets.night',
46
+ iconName: 'moon',
47
+ },
48
+ ];
49
+
50
+ // ============================================================================
51
+ // FREQUENCY OPTIONS
52
+ // ============================================================================
53
+
54
+ export interface FrequencyOption {
55
+ id: ReminderFrequency;
56
+ labelKey: string;
57
+ iconName: string;
58
+ }
59
+
60
+ export const FREQUENCY_OPTIONS: FrequencyOption[] = [
61
+ {
62
+ id: 'once',
63
+ labelKey: 'notifications.frequency.once',
64
+ iconName: 'calendar',
65
+ },
66
+ {
67
+ id: 'daily',
68
+ labelKey: 'notifications.frequency.daily',
69
+ iconName: 'repeat',
70
+ },
71
+ {
72
+ id: 'weekly',
73
+ labelKey: 'notifications.frequency.weekly',
74
+ iconName: 'calendar-days',
75
+ },
76
+ {
77
+ id: 'monthly',
78
+ labelKey: 'notifications.frequency.monthly',
79
+ iconName: 'calendar-range',
80
+ },
81
+ ];
82
+
83
+ // ============================================================================
84
+ // WEEKDAY OPTIONS
85
+ // ============================================================================
86
+
87
+ export interface WeekdayOption {
88
+ id: number;
89
+ labelKey: string;
90
+ shortLabelKey: string;
91
+ }
92
+
93
+ export const WEEKDAY_OPTIONS: WeekdayOption[] = [
94
+ { id: 1, labelKey: 'notifications.weekdays.sunday', shortLabelKey: 'notifications.weekdays.sun' },
95
+ { id: 2, labelKey: 'notifications.weekdays.monday', shortLabelKey: 'notifications.weekdays.mon' },
96
+ { id: 3, labelKey: 'notifications.weekdays.tuesday', shortLabelKey: 'notifications.weekdays.tue' },
97
+ { id: 4, labelKey: 'notifications.weekdays.wednesday', shortLabelKey: 'notifications.weekdays.wed' },
98
+ { id: 5, labelKey: 'notifications.weekdays.thursday', shortLabelKey: 'notifications.weekdays.thu' },
99
+ { id: 6, labelKey: 'notifications.weekdays.friday', shortLabelKey: 'notifications.weekdays.fri' },
100
+ { id: 7, labelKey: 'notifications.weekdays.saturday', shortLabelKey: 'notifications.weekdays.sat' },
101
+ ];
102
+
103
+ // ============================================================================
104
+ // HELPER FUNCTIONS
105
+ // ============================================================================
106
+
107
+ export const getTimePresetById = (id: string): TimePreset | undefined => {
108
+ return DEFAULT_TIME_PRESETS.find(preset => preset.id === id);
109
+ };
110
+
111
+ export const formatTime = (hour: number, minute: number): string => {
112
+ const h = hour.toString().padStart(2, '0');
113
+ const m = minute.toString().padStart(2, '0');
114
+ return `${h}:${m}`;
115
+ };
116
+
117
+ export const parseTime = (timeString: string): { hour: number; minute: number } => {
118
+ const [hour, minute] = timeString.split(':').map(Number);
119
+ return { hour: hour || 0, minute: minute || 0 };
120
+ };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * useQuietHoursActions Hook
3
+ * Manages quiet hours configuration
4
+ */
5
+
6
+ import { useCallback } from 'react';
7
+ import { useRemindersStore, useQuietHours } from '../storage/RemindersStore';
8
+ import type { QuietHoursConfig } from '../services/types';
9
+
10
+ export const useQuietHoursActions = () => {
11
+ const quietHours = useQuietHours();
12
+ const { updateQuietHours } = useRemindersStore();
13
+
14
+ const setQuietHoursEnabled = useCallback(async (enabled: boolean): Promise<void> => {
15
+ await updateQuietHours({ ...quietHours, enabled });
16
+ }, [quietHours, updateQuietHours]);
17
+
18
+ const setStartTime = useCallback(async (hour: number, minute: number): Promise<void> => {
19
+ await updateQuietHours({ ...quietHours, startHour: hour, startMinute: minute });
20
+ }, [quietHours, updateQuietHours]);
21
+
22
+ const setEndTime = useCallback(async (hour: number, minute: number): Promise<void> => {
23
+ await updateQuietHours({ ...quietHours, endHour: hour, endMinute: minute });
24
+ }, [quietHours, updateQuietHours]);
25
+
26
+ const setQuietHours = useCallback(async (config: QuietHoursConfig): Promise<void> => {
27
+ await updateQuietHours(config);
28
+ }, [updateQuietHours]);
29
+
30
+ const isInQuietHours = useCallback((): boolean => {
31
+ if (!quietHours.enabled) return false;
32
+
33
+ const now = new Date();
34
+ const currentMinutes = now.getHours() * 60 + now.getMinutes();
35
+ const startMinutes = quietHours.startHour * 60 + quietHours.startMinute;
36
+ const endMinutes = quietHours.endHour * 60 + quietHours.endMinute;
37
+
38
+ if (startMinutes <= endMinutes) {
39
+ return currentMinutes >= startMinutes && currentMinutes < endMinutes;
40
+ }
41
+ return currentMinutes >= startMinutes || currentMinutes < endMinutes;
42
+ }, [quietHours]);
43
+
44
+ return {
45
+ quietHours,
46
+ setQuietHoursEnabled,
47
+ setStartTime,
48
+ setEndTime,
49
+ setQuietHours,
50
+ isInQuietHours,
51
+ };
52
+ };
@@ -0,0 +1,147 @@
1
+ /**
2
+ * useReminderActions Hook
3
+ * Handles reminder CRUD operations with notification scheduling
4
+ */
5
+
6
+ import { useCallback } from 'react';
7
+ import { useRemindersStore } from '../storage/RemindersStore';
8
+ import { NotificationScheduler } from '../services/NotificationScheduler';
9
+ import type {
10
+ Reminder,
11
+ CreateReminderInput,
12
+ UpdateReminderInput,
13
+ NotificationTrigger,
14
+ } from '../services/types';
15
+
16
+ const scheduler = new NotificationScheduler();
17
+
18
+ const generateId = (): string => {
19
+ return `reminder_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
20
+ };
21
+
22
+ const buildTrigger = (reminder: Reminder): NotificationTrigger => {
23
+ switch (reminder.frequency) {
24
+ case 'once':
25
+ const date = new Date();
26
+ date.setHours(reminder.hour, reminder.minute, 0, 0);
27
+ if (date <= new Date()) {
28
+ date.setDate(date.getDate() + 1);
29
+ }
30
+ return { type: 'date', date };
31
+
32
+ case 'daily':
33
+ return { type: 'daily', hour: reminder.hour, minute: reminder.minute };
34
+
35
+ case 'weekly':
36
+ return {
37
+ type: 'weekly',
38
+ weekday: reminder.weekday || 2,
39
+ hour: reminder.hour,
40
+ minute: reminder.minute,
41
+ };
42
+
43
+ case 'monthly':
44
+ return {
45
+ type: 'monthly',
46
+ day: reminder.dayOfMonth || 1,
47
+ hour: reminder.hour,
48
+ minute: reminder.minute,
49
+ };
50
+
51
+ default:
52
+ return { type: 'daily', hour: reminder.hour, minute: reminder.minute };
53
+ }
54
+ };
55
+
56
+ export const useReminderActions = () => {
57
+ const { addReminder, updateReminder, deleteReminder, toggleReminder } = useRemindersStore();
58
+
59
+ const createReminder = useCallback(async (input: CreateReminderInput): Promise<Reminder> => {
60
+ const now = new Date().toISOString();
61
+ const reminder: Reminder = {
62
+ id: generateId(),
63
+ ...input,
64
+ enabled: true,
65
+ createdAt: now,
66
+ updatedAt: now,
67
+ };
68
+
69
+ const trigger = buildTrigger(reminder);
70
+ const notificationId = await scheduler.scheduleNotification({
71
+ title: reminder.title,
72
+ body: reminder.body,
73
+ trigger,
74
+ data: { reminderId: reminder.id },
75
+ });
76
+
77
+ reminder.notificationId = notificationId;
78
+ await addReminder(reminder);
79
+
80
+ return reminder;
81
+ }, [addReminder]);
82
+
83
+ const editReminder = useCallback(async (id: string, input: UpdateReminderInput): Promise<void> => {
84
+ const { reminders } = useRemindersStore.getState();
85
+ const existing = reminders.find(r => r.id === id);
86
+ if (!existing) return;
87
+
88
+ if (existing.notificationId) {
89
+ await scheduler.cancelNotification(existing.notificationId);
90
+ }
91
+
92
+ const updated: Reminder = { ...existing, ...input, updatedAt: new Date().toISOString() };
93
+
94
+ if (updated.enabled) {
95
+ const trigger = buildTrigger(updated);
96
+ const notificationId = await scheduler.scheduleNotification({
97
+ title: updated.title,
98
+ body: updated.body,
99
+ trigger,
100
+ data: { reminderId: updated.id },
101
+ });
102
+ updated.notificationId = notificationId;
103
+ } else {
104
+ updated.notificationId = undefined;
105
+ }
106
+
107
+ await updateReminder(id, updated);
108
+ }, [updateReminder]);
109
+
110
+ const removeReminder = useCallback(async (id: string): Promise<void> => {
111
+ const { reminders } = useRemindersStore.getState();
112
+ const reminder = reminders.find(r => r.id === id);
113
+
114
+ if (reminder?.notificationId) {
115
+ await scheduler.cancelNotification(reminder.notificationId);
116
+ }
117
+
118
+ await deleteReminder(id);
119
+ }, [deleteReminder]);
120
+
121
+ const toggleReminderEnabled = useCallback(async (id: string): Promise<void> => {
122
+ const { reminders } = useRemindersStore.getState();
123
+ const reminder = reminders.find(r => r.id === id);
124
+ if (!reminder) return;
125
+
126
+ if (reminder.enabled && reminder.notificationId) {
127
+ await scheduler.cancelNotification(reminder.notificationId);
128
+ await updateReminder(id, { enabled: false, notificationId: undefined });
129
+ } else if (!reminder.enabled) {
130
+ const trigger = buildTrigger(reminder);
131
+ const notificationId = await scheduler.scheduleNotification({
132
+ title: reminder.title,
133
+ body: reminder.body,
134
+ trigger,
135
+ data: { reminderId: reminder.id },
136
+ });
137
+ await updateReminder(id, { enabled: true, notificationId });
138
+ }
139
+ }, [updateReminder]);
140
+
141
+ return {
142
+ createReminder,
143
+ editReminder,
144
+ removeReminder,
145
+ toggleReminderEnabled,
146
+ };
147
+ };