@umituz/react-native-design-system 2.5.11 → 2.5.13
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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-design-system",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.13",
|
|
4
4
|
"description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography, responsive and safe area utilities",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Calendar Store (Zustand
|
|
2
|
+
* Calendar Store (Zustand)
|
|
3
3
|
*
|
|
4
4
|
* Global state management for calendar functionality.
|
|
5
5
|
* Manages calendar view state, selected date, and events.
|
|
6
6
|
*
|
|
7
7
|
* Design Philosophy:
|
|
8
|
-
* -
|
|
9
|
-
* - AsyncStorage persistence
|
|
8
|
+
* - Zustand for lightweight state
|
|
9
|
+
* - AsyncStorage for persistence
|
|
10
10
|
* - Generic event handling
|
|
11
11
|
* - Timezone-aware via CalendarService
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import { create } from 'zustand';
|
|
15
|
+
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
16
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
15
17
|
import type { CalendarEvent, CreateCalendarEventRequest, UpdateCalendarEventRequest } from '../../domain/entities/CalendarEvent.entity';
|
|
16
18
|
import { CalendarService } from '../services/CalendarService';
|
|
17
19
|
|
|
@@ -88,218 +90,225 @@ const initialState: CalendarState = {
|
|
|
88
90
|
/**
|
|
89
91
|
* Calendar Store
|
|
90
92
|
*/
|
|
91
|
-
export const useCalendarStore =
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Add a new event
|
|
125
|
-
*/
|
|
126
|
-
addEvent: async (request: CreateCalendarEventRequest) => {
|
|
127
|
-
set({ isLoading: true, error: null });
|
|
128
|
-
try {
|
|
129
|
-
const newEvent: CalendarEvent = {
|
|
130
|
-
id: generateId(),
|
|
131
|
-
...request,
|
|
132
|
-
isCompleted: false,
|
|
133
|
-
createdAt: new Date(),
|
|
134
|
-
updatedAt: new Date(),
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
const events = [...get().events, newEvent];
|
|
138
|
-
await storageRepository.setItem(STORAGE_KEY, events);
|
|
139
|
-
set({ events, isLoading: false });
|
|
140
|
-
} catch (error) {
|
|
141
|
-
set({
|
|
142
|
-
error: error instanceof Error ? error.message : 'Failed to add event',
|
|
143
|
-
isLoading: false,
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
},
|
|
93
|
+
export const useCalendarStore = create<CalendarState & { actions: CalendarActions }>()(
|
|
94
|
+
persist(
|
|
95
|
+
(set, get) => ({
|
|
96
|
+
...initialState,
|
|
97
|
+
actions: {
|
|
98
|
+
/**
|
|
99
|
+
* Load events from storage
|
|
100
|
+
*/
|
|
101
|
+
loadEvents: async () => {
|
|
102
|
+
set({ isLoading: true, error: null });
|
|
103
|
+
try {
|
|
104
|
+
const stored = await AsyncStorage.getItem(STORAGE_KEY);
|
|
105
|
+
if (stored) {
|
|
106
|
+
const parsed = JSON.parse(stored) as CalendarEvent[];
|
|
107
|
+
// Restore Date objects
|
|
108
|
+
const events = parsed.map((event) => ({
|
|
109
|
+
...event,
|
|
110
|
+
createdAt: new Date(event.createdAt),
|
|
111
|
+
updatedAt: new Date(event.updatedAt),
|
|
112
|
+
}));
|
|
113
|
+
set({ events, isLoading: false });
|
|
114
|
+
} else {
|
|
115
|
+
set({ isLoading: false });
|
|
116
|
+
}
|
|
117
|
+
} catch {
|
|
118
|
+
set({
|
|
119
|
+
error: 'Failed to load events',
|
|
120
|
+
isLoading: false,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
},
|
|
147
124
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return {
|
|
157
|
-
...event,
|
|
125
|
+
/**
|
|
126
|
+
* Add a new event
|
|
127
|
+
*/
|
|
128
|
+
addEvent: async (request: CreateCalendarEventRequest) => {
|
|
129
|
+
set({ isLoading: true, error: null });
|
|
130
|
+
try {
|
|
131
|
+
const newEvent: CalendarEvent = {
|
|
132
|
+
id: generateId(),
|
|
158
133
|
...request,
|
|
134
|
+
isCompleted: false,
|
|
135
|
+
createdAt: new Date(),
|
|
159
136
|
updatedAt: new Date(),
|
|
160
137
|
};
|
|
138
|
+
|
|
139
|
+
const events = [...get().events, newEvent];
|
|
140
|
+
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(events));
|
|
141
|
+
set({ events, isLoading: false });
|
|
142
|
+
} catch {
|
|
143
|
+
set({
|
|
144
|
+
error: 'Failed to add event',
|
|
145
|
+
isLoading: false,
|
|
146
|
+
});
|
|
161
147
|
}
|
|
162
|
-
|
|
163
|
-
});
|
|
148
|
+
},
|
|
164
149
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
150
|
+
/**
|
|
151
|
+
* Update an existing event
|
|
152
|
+
*/
|
|
153
|
+
updateEvent: async (request: UpdateCalendarEventRequest) => {
|
|
154
|
+
set({ isLoading: true, error: null });
|
|
155
|
+
try {
|
|
156
|
+
const events = get().events.map((event) => {
|
|
157
|
+
if (event.id === request.id) {
|
|
158
|
+
return {
|
|
159
|
+
...event,
|
|
160
|
+
...request,
|
|
161
|
+
updatedAt: new Date(),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
return event;
|
|
165
|
+
});
|
|
174
166
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
167
|
+
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(events));
|
|
168
|
+
set({ events, isLoading: false });
|
|
169
|
+
} catch {
|
|
170
|
+
set({
|
|
171
|
+
error: 'Failed to update event',
|
|
172
|
+
isLoading: false,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Delete an event
|
|
179
|
+
*/
|
|
180
|
+
deleteEvent: async (id: string) => {
|
|
181
|
+
set({ isLoading: true, error: null });
|
|
182
|
+
try {
|
|
183
|
+
const events = get().events.filter((event) => event.id !== id);
|
|
184
|
+
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(events));
|
|
185
|
+
set({ events, isLoading: false });
|
|
186
|
+
} catch {
|
|
187
|
+
set({
|
|
188
|
+
error: 'Failed to delete event',
|
|
189
|
+
isLoading: false,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
},
|
|
191
193
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
194
|
+
/**
|
|
195
|
+
* Mark event as completed
|
|
196
|
+
*/
|
|
197
|
+
completeEvent: async (id: string) => {
|
|
198
|
+
await get().actions.updateEvent({ id, isCompleted: true });
|
|
199
|
+
},
|
|
198
200
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
201
|
+
/**
|
|
202
|
+
* Mark event as incomplete
|
|
203
|
+
*/
|
|
204
|
+
uncompleteEvent: async (id: string) => {
|
|
205
|
+
await get().actions.updateEvent({ id, isCompleted: false });
|
|
206
|
+
},
|
|
205
207
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
208
|
+
/**
|
|
209
|
+
* Set selected date
|
|
210
|
+
*/
|
|
211
|
+
setSelectedDate: (date: Date) => {
|
|
212
|
+
set({ selectedDate: date });
|
|
213
|
+
},
|
|
212
214
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
215
|
+
/**
|
|
216
|
+
* Go to today's date
|
|
217
|
+
*/
|
|
218
|
+
goToToday: () => {
|
|
219
|
+
const today = new Date();
|
|
220
|
+
set({
|
|
221
|
+
selectedDate: today,
|
|
222
|
+
currentMonth: today,
|
|
223
|
+
});
|
|
224
|
+
},
|
|
223
225
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
226
|
+
/**
|
|
227
|
+
* Navigate to previous/next month
|
|
228
|
+
*/
|
|
229
|
+
navigateMonth: (direction: 'prev' | 'next') => {
|
|
230
|
+
const currentMonth = get().currentMonth;
|
|
231
|
+
const newMonth =
|
|
232
|
+
direction === 'prev'
|
|
233
|
+
? CalendarService.getPreviousMonth(currentMonth)
|
|
234
|
+
: CalendarService.getNextMonth(currentMonth);
|
|
233
235
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
+
set({ currentMonth: newMonth });
|
|
237
|
+
},
|
|
236
238
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
239
|
+
/**
|
|
240
|
+
* Navigate to previous/next week
|
|
241
|
+
*/
|
|
242
|
+
navigateWeek: (direction: 'prev' | 'next') => {
|
|
243
|
+
const selectedDate = get().selectedDate;
|
|
244
|
+
const newDate =
|
|
245
|
+
direction === 'prev'
|
|
246
|
+
? CalendarService.getPreviousWeek(selectedDate)
|
|
247
|
+
: CalendarService.getNextWeek(selectedDate);
|
|
246
248
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
+
set({ selectedDate: newDate });
|
|
250
|
+
},
|
|
249
251
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
252
|
+
/**
|
|
253
|
+
* Set current month directly
|
|
254
|
+
*/
|
|
255
|
+
setCurrentMonth: (date: Date) => {
|
|
256
|
+
set({ currentMonth: date });
|
|
257
|
+
},
|
|
256
258
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
259
|
+
/**
|
|
260
|
+
* Set view mode
|
|
261
|
+
*/
|
|
262
|
+
setViewMode: (mode: CalendarViewMode) => {
|
|
263
|
+
set({ viewMode: mode });
|
|
264
|
+
},
|
|
263
265
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
266
|
+
/**
|
|
267
|
+
* Get events for a specific date
|
|
268
|
+
*/
|
|
269
|
+
getEventsForDate: (date: Date) => {
|
|
270
|
+
const events = get().events;
|
|
271
|
+
return CalendarService.getEventsForDate(date, events);
|
|
272
|
+
},
|
|
271
273
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
274
|
+
/**
|
|
275
|
+
* Get events for a specific month
|
|
276
|
+
*/
|
|
277
|
+
getEventsForMonth: (year: number, month: number) => {
|
|
278
|
+
const events = get().events;
|
|
279
|
+
const firstDay = new Date(year, month, 1);
|
|
280
|
+
const lastDay = new Date(year, month + 1, 0);
|
|
281
|
+
return CalendarService.getEventsInRange(firstDay, lastDay, events);
|
|
282
|
+
},
|
|
281
283
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
284
|
+
/**
|
|
285
|
+
* Clear error state
|
|
286
|
+
*/
|
|
287
|
+
clearError: () => {
|
|
288
|
+
set({ error: null });
|
|
289
|
+
},
|
|
288
290
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
})
|
|
291
|
+
/**
|
|
292
|
+
* Clear all events (for testing/reset)
|
|
293
|
+
*/
|
|
294
|
+
clearAllEvents: async () => {
|
|
295
|
+
set({ isLoading: true, error: null });
|
|
296
|
+
try {
|
|
297
|
+
await AsyncStorage.removeItem(STORAGE_KEY);
|
|
298
|
+
set({ events: [], isLoading: false });
|
|
299
|
+
} catch {
|
|
300
|
+
set({
|
|
301
|
+
error: 'Failed to clear events',
|
|
302
|
+
isLoading: false,
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
}),
|
|
308
|
+
{
|
|
309
|
+
name: 'calendar-storage',
|
|
310
|
+
storage: createJSONStorage(() => AsyncStorage),
|
|
311
|
+
partialize: (state) => ({ events: state.events }),
|
|
312
|
+
}
|
|
313
|
+
)
|
|
314
|
+
);
|
|
@@ -76,6 +76,7 @@ export interface UseCalendarReturn {
|
|
|
76
76
|
* Main calendar hook
|
|
77
77
|
*/
|
|
78
78
|
export const useCalendar = (): UseCalendarReturn => {
|
|
79
|
+
const store = useCalendarStore();
|
|
79
80
|
const {
|
|
80
81
|
events,
|
|
81
82
|
selectedDate,
|
|
@@ -84,7 +85,7 @@ export const useCalendar = (): UseCalendarReturn => {
|
|
|
84
85
|
isLoading,
|
|
85
86
|
error,
|
|
86
87
|
actions,
|
|
87
|
-
} =
|
|
88
|
+
} = store;
|
|
88
89
|
|
|
89
90
|
// Load events on mount
|
|
90
91
|
useEffect(() => {
|
|
@@ -129,11 +130,12 @@ export const useCalendar = (): UseCalendarReturn => {
|
|
|
129
130
|
* Lightweight hook for just navigation actions
|
|
130
131
|
*/
|
|
131
132
|
export const useCalendarNavigation = () => {
|
|
133
|
+
const store = useCalendarStore();
|
|
132
134
|
const {
|
|
133
135
|
selectedDate,
|
|
134
136
|
currentMonth,
|
|
135
137
|
actions: { setSelectedDate, navigateMonth, goToToday, setCurrentMonth },
|
|
136
|
-
} =
|
|
138
|
+
} = store;
|
|
137
139
|
|
|
138
140
|
return {
|
|
139
141
|
selectedDate,
|
|
@@ -150,6 +152,7 @@ export const useCalendarNavigation = () => {
|
|
|
150
152
|
* Lightweight hook for just event operations
|
|
151
153
|
*/
|
|
152
154
|
export const useCalendarEvents = () => {
|
|
155
|
+
const store = useCalendarStore();
|
|
153
156
|
const {
|
|
154
157
|
events,
|
|
155
158
|
isLoading,
|
|
@@ -163,7 +166,7 @@ export const useCalendarEvents = () => {
|
|
|
163
166
|
uncompleteEvent,
|
|
164
167
|
clearError,
|
|
165
168
|
},
|
|
166
|
-
} =
|
|
169
|
+
} = store;
|
|
167
170
|
|
|
168
171
|
return {
|
|
169
172
|
events,
|