@growsober/sdk 1.0.5 → 1.0.6

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.
@@ -97,6 +97,8 @@ export declare function useEvent(id: string, options?: Omit<UseQueryOptions<Even
97
97
  isCancelled: boolean;
98
98
  isAmbient: boolean;
99
99
  ambientCategory?: Record<string, never>;
100
+ vibe?: "CHILL" | "ACTIVE" | "SOCIAL" | "CREATIVE" | "DEEP_TALK" | "ADVENTURE";
101
+ city?: import("@growsober/types/dist/generated").components["schemas"]["EventCityDto"];
100
102
  bookingCount: number;
101
103
  checkinCount: number;
102
104
  createdAt: string;
@@ -147,6 +149,8 @@ export declare function useEventBySlug(slug: string, options?: Omit<UseQueryOpti
147
149
  isCancelled: boolean;
148
150
  isAmbient: boolean;
149
151
  ambientCategory?: Record<string, never>;
152
+ vibe?: "CHILL" | "ACTIVE" | "SOCIAL" | "CREATIVE" | "DEEP_TALK" | "ADVENTURE";
153
+ city?: import("@growsober/types/dist/generated").components["schemas"]["EventCityDto"];
150
154
  bookingCount: number;
151
155
  checkinCount: number;
152
156
  createdAt: string;
@@ -197,6 +201,8 @@ export declare function useUpcomingEvents(limit?: number, options?: Omit<UseQuer
197
201
  isCancelled: boolean;
198
202
  isAmbient: boolean;
199
203
  ambientCategory?: Record<string, never>;
204
+ vibe?: "CHILL" | "ACTIVE" | "SOCIAL" | "CREATIVE" | "DEEP_TALK" | "ADVENTURE";
205
+ city?: import("@growsober/types/dist/generated").components["schemas"]["EventCityDto"];
200
206
  bookingCount: number;
201
207
  checkinCount: number;
202
208
  createdAt: string;
@@ -249,6 +255,8 @@ export declare function useFeaturedEvents(limit?: number, options?: Omit<UseQuer
249
255
  isCancelled: boolean;
250
256
  isAmbient: boolean;
251
257
  ambientCategory?: Record<string, never>;
258
+ vibe?: "CHILL" | "ACTIVE" | "SOCIAL" | "CREATIVE" | "DEEP_TALK" | "ADVENTURE";
259
+ city?: import("@growsober/types/dist/generated").components["schemas"]["EventCityDto"];
252
260
  bookingCount: number;
253
261
  checkinCount: number;
254
262
  createdAt: string;
@@ -299,6 +307,8 @@ export declare function useAmbientEvents(filters?: AmbientEventFilters, options?
299
307
  isCancelled: boolean;
300
308
  isAmbient: boolean;
301
309
  ambientCategory?: Record<string, never>;
310
+ vibe?: "CHILL" | "ACTIVE" | "SOCIAL" | "CREATIVE" | "DEEP_TALK" | "ADVENTURE";
311
+ city?: import("@growsober/types/dist/generated").components["schemas"]["EventCityDto"];
302
312
  bookingCount: number;
303
313
  checkinCount: number;
304
314
  createdAt: string;
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Event Grouping Utilities
3
+ *
4
+ * Utilities for organizing events by time of day.
5
+ * Used in the Gatherings screen to show events grouped by
6
+ * Morning, Afternoon, and Evening.
7
+ *
8
+ * @module api/utils/eventGrouping
9
+ */
10
+ import { EventResponse } from '../types';
11
+ export type TimeOfDay = 'MORNING' | 'AFTERNOON' | 'EVENING';
12
+ export interface GroupedEvents {
13
+ morning: EventResponse[];
14
+ afternoon: EventResponse[];
15
+ evening: EventResponse[];
16
+ }
17
+ export interface TimeOfDayInfo {
18
+ key: TimeOfDay;
19
+ label: string;
20
+ emoji: string;
21
+ hours: {
22
+ start: number;
23
+ end: number;
24
+ };
25
+ }
26
+ export declare const TIME_OF_DAY_CONFIG: Record<TimeOfDay, TimeOfDayInfo>;
27
+ /**
28
+ * Get time of day for a given date
29
+ *
30
+ * @param date - Date string or Date object
31
+ * @returns TimeOfDay - MORNING, AFTERNOON, or EVENING
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * const timeOfDay = getTimeOfDay('2024-03-15T10:00:00Z');
36
+ * console.log(timeOfDay); // 'MORNING'
37
+ * ```
38
+ */
39
+ export declare function getTimeOfDay(date: Date | string): TimeOfDay;
40
+ /**
41
+ * Get label for time of day
42
+ *
43
+ * @param timeOfDay - TimeOfDay enum value
44
+ * @returns Human-readable label
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * const label = getTimeOfDayLabel('MORNING');
49
+ * console.log(label); // 'Morning'
50
+ * ```
51
+ */
52
+ export declare function getTimeOfDayLabel(timeOfDay: TimeOfDay): string;
53
+ /**
54
+ * Group events by time of day
55
+ *
56
+ * @param events - Array of events to group
57
+ * @returns GroupedEvents object with morning, afternoon, and evening arrays
58
+ *
59
+ * @example
60
+ * ```tsx
61
+ * import { useUpcomingEvents, groupEventsByTimeOfDay } from '@growsober/sdk';
62
+ *
63
+ * function GatheringsList() {
64
+ * const { data: events } = useUpcomingEvents(30);
65
+ * const grouped = useMemo(() => {
66
+ * if (!events) return null;
67
+ * return groupEventsByTimeOfDay(events);
68
+ * }, [events]);
69
+ *
70
+ * return (
71
+ * <SectionList
72
+ * sections={[
73
+ * { title: 'Morning', data: grouped?.morning || [] },
74
+ * { title: 'Afternoon', data: grouped?.afternoon || [] },
75
+ * { title: 'Evening', data: grouped?.evening || [] },
76
+ * ]}
77
+ * ...
78
+ * />
79
+ * );
80
+ * }
81
+ * ```
82
+ */
83
+ export declare function groupEventsByTimeOfDay(events: EventResponse[]): GroupedEvents;
84
+ /**
85
+ * Convert grouped events to section list data format
86
+ *
87
+ * @param events - Array of events to group
88
+ * @returns Array of sections with title and data
89
+ *
90
+ * @example
91
+ * ```tsx
92
+ * const sections = getEventSections(events);
93
+ * // [
94
+ * // { title: 'Morning', data: [...] },
95
+ * // { title: 'Afternoon', data: [...] },
96
+ * // { title: 'Evening', data: [...] },
97
+ * // ]
98
+ * ```
99
+ */
100
+ export declare function getEventSections(events: EventResponse[]): Array<{
101
+ title: string;
102
+ timeOfDay: TimeOfDay;
103
+ data: EventResponse[];
104
+ }>;
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ /**
3
+ * Event Grouping Utilities
4
+ *
5
+ * Utilities for organizing events by time of day.
6
+ * Used in the Gatherings screen to show events grouped by
7
+ * Morning, Afternoon, and Evening.
8
+ *
9
+ * @module api/utils/eventGrouping
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.TIME_OF_DAY_CONFIG = void 0;
13
+ exports.getTimeOfDay = getTimeOfDay;
14
+ exports.getTimeOfDayLabel = getTimeOfDayLabel;
15
+ exports.groupEventsByTimeOfDay = groupEventsByTimeOfDay;
16
+ exports.getEventSections = getEventSections;
17
+ // ============================================================================
18
+ // CONSTANTS
19
+ // ============================================================================
20
+ exports.TIME_OF_DAY_CONFIG = {
21
+ MORNING: {
22
+ key: 'MORNING',
23
+ label: 'Morning',
24
+ emoji: '',
25
+ hours: { start: 5, end: 11 }, // 5:00 AM - 11:59 AM
26
+ },
27
+ AFTERNOON: {
28
+ key: 'AFTERNOON',
29
+ label: 'Afternoon',
30
+ emoji: '',
31
+ hours: { start: 12, end: 16 }, // 12:00 PM - 4:59 PM
32
+ },
33
+ EVENING: {
34
+ key: 'EVENING',
35
+ label: 'Evening',
36
+ emoji: '',
37
+ hours: { start: 17, end: 4 }, // 5:00 PM - 4:59 AM (next day)
38
+ },
39
+ };
40
+ // ============================================================================
41
+ // FUNCTIONS
42
+ // ============================================================================
43
+ /**
44
+ * Get time of day for a given date
45
+ *
46
+ * @param date - Date string or Date object
47
+ * @returns TimeOfDay - MORNING, AFTERNOON, or EVENING
48
+ *
49
+ * @example
50
+ * ```tsx
51
+ * const timeOfDay = getTimeOfDay('2024-03-15T10:00:00Z');
52
+ * console.log(timeOfDay); // 'MORNING'
53
+ * ```
54
+ */
55
+ function getTimeOfDay(date) {
56
+ const d = typeof date === 'string' ? new Date(date) : date;
57
+ const hour = d.getHours();
58
+ if (hour >= 5 && hour < 12)
59
+ return 'MORNING';
60
+ if (hour >= 12 && hour < 17)
61
+ return 'AFTERNOON';
62
+ return 'EVENING';
63
+ }
64
+ /**
65
+ * Get label for time of day
66
+ *
67
+ * @param timeOfDay - TimeOfDay enum value
68
+ * @returns Human-readable label
69
+ *
70
+ * @example
71
+ * ```tsx
72
+ * const label = getTimeOfDayLabel('MORNING');
73
+ * console.log(label); // 'Morning'
74
+ * ```
75
+ */
76
+ function getTimeOfDayLabel(timeOfDay) {
77
+ return exports.TIME_OF_DAY_CONFIG[timeOfDay].label;
78
+ }
79
+ /**
80
+ * Group events by time of day
81
+ *
82
+ * @param events - Array of events to group
83
+ * @returns GroupedEvents object with morning, afternoon, and evening arrays
84
+ *
85
+ * @example
86
+ * ```tsx
87
+ * import { useUpcomingEvents, groupEventsByTimeOfDay } from '@growsober/sdk';
88
+ *
89
+ * function GatheringsList() {
90
+ * const { data: events } = useUpcomingEvents(30);
91
+ * const grouped = useMemo(() => {
92
+ * if (!events) return null;
93
+ * return groupEventsByTimeOfDay(events);
94
+ * }, [events]);
95
+ *
96
+ * return (
97
+ * <SectionList
98
+ * sections={[
99
+ * { title: 'Morning', data: grouped?.morning || [] },
100
+ * { title: 'Afternoon', data: grouped?.afternoon || [] },
101
+ * { title: 'Evening', data: grouped?.evening || [] },
102
+ * ]}
103
+ * ...
104
+ * />
105
+ * );
106
+ * }
107
+ * ```
108
+ */
109
+ function groupEventsByTimeOfDay(events) {
110
+ const grouped = {
111
+ morning: [],
112
+ afternoon: [],
113
+ evening: [],
114
+ };
115
+ for (const event of events) {
116
+ const timeOfDay = getTimeOfDay(event.startDate);
117
+ switch (timeOfDay) {
118
+ case 'MORNING':
119
+ grouped.morning.push(event);
120
+ break;
121
+ case 'AFTERNOON':
122
+ grouped.afternoon.push(event);
123
+ break;
124
+ case 'EVENING':
125
+ grouped.evening.push(event);
126
+ break;
127
+ }
128
+ }
129
+ return grouped;
130
+ }
131
+ /**
132
+ * Convert grouped events to section list data format
133
+ *
134
+ * @param events - Array of events to group
135
+ * @returns Array of sections with title and data
136
+ *
137
+ * @example
138
+ * ```tsx
139
+ * const sections = getEventSections(events);
140
+ * // [
141
+ * // { title: 'Morning', data: [...] },
142
+ * // { title: 'Afternoon', data: [...] },
143
+ * // { title: 'Evening', data: [...] },
144
+ * // ]
145
+ * ```
146
+ */
147
+ function getEventSections(events) {
148
+ const grouped = groupEventsByTimeOfDay(events);
149
+ return [
150
+ { title: 'Morning', timeOfDay: 'MORNING', data: grouped.morning },
151
+ { title: 'Afternoon', timeOfDay: 'AFTERNOON', data: grouped.afternoon },
152
+ { title: 'Evening', timeOfDay: 'EVENING', data: grouped.evening },
153
+ ].filter(section => section.data.length > 0);
154
+ }
155
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnRHcm91cGluZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcGkvdXRpbHMvZXZlbnRHcm91cGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7O0dBUUc7OztBQWdFSCxvQ0FPQztBQWNELDhDQUVDO0FBZ0NELHdEQXVCQztBQWtCRCw0Q0FZQztBQXJKRCwrRUFBK0U7QUFDL0UsWUFBWTtBQUNaLCtFQUErRTtBQUVsRSxRQUFBLGtCQUFrQixHQUFxQztJQUNsRSxPQUFPLEVBQUU7UUFDUCxHQUFHLEVBQUUsU0FBUztRQUNkLEtBQUssRUFBRSxTQUFTO1FBQ2hCLEtBQUssRUFBRSxFQUFFO1FBQ1QsS0FBSyxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUscUJBQXFCO0tBQ3BEO0lBQ0QsU0FBUyxFQUFFO1FBQ1QsR0FBRyxFQUFFLFdBQVc7UUFDaEIsS0FBSyxFQUFFLFdBQVc7UUFDbEIsS0FBSyxFQUFFLEVBQUU7UUFDVCxLQUFLLEVBQUUsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxxQkFBcUI7S0FDckQ7SUFDRCxPQUFPLEVBQUU7UUFDUCxHQUFHLEVBQUUsU0FBUztRQUNkLEtBQUssRUFBRSxTQUFTO1FBQ2hCLEtBQUssRUFBRSxFQUFFO1FBQ1QsS0FBSyxFQUFFLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUUsK0JBQStCO0tBQzlEO0NBQ0YsQ0FBQztBQUVGLCtFQUErRTtBQUMvRSxZQUFZO0FBQ1osK0VBQStFO0FBRS9FOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsU0FBZ0IsWUFBWSxDQUFDLElBQW1CO0lBQzlDLE1BQU0sQ0FBQyxHQUFHLE9BQU8sSUFBSSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUMzRCxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7SUFFMUIsSUFBSSxJQUFJLElBQUksQ0FBQyxJQUFJLElBQUksR0FBRyxFQUFFO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDN0MsSUFBSSxJQUFJLElBQUksRUFBRSxJQUFJLElBQUksR0FBRyxFQUFFO1FBQUUsT0FBTyxXQUFXLENBQUM7SUFDaEQsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQztBQUVEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsU0FBZ0IsaUJBQWlCLENBQUMsU0FBb0I7SUFDcEQsT0FBTywwQkFBa0IsQ0FBQyxTQUFTLENBQUMsQ0FBQyxLQUFLLENBQUM7QUFDN0MsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTZCRztBQUNILFNBQWdCLHNCQUFzQixDQUFDLE1BQXVCO0lBQzVELE1BQU0sT0FBTyxHQUFrQjtRQUM3QixPQUFPLEVBQUUsRUFBRTtRQUNYLFNBQVMsRUFBRSxFQUFFO1FBQ2IsT0FBTyxFQUFFLEVBQUU7S0FDWixDQUFDO0lBRUYsS0FBSyxNQUFNLEtBQUssSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUMzQixNQUFNLFNBQVMsR0FBRyxZQUFZLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ2hELFFBQVEsU0FBUyxFQUFFLENBQUM7WUFDbEIsS0FBSyxTQUFTO2dCQUNaLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUM1QixNQUFNO1lBQ1IsS0FBSyxXQUFXO2dCQUNkLE9BQU8sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUM5QixNQUFNO1lBQ1IsS0FBSyxTQUFTO2dCQUNaLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUM1QixNQUFNO1FBQ1YsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsU0FBZ0IsZ0JBQWdCLENBQUMsTUFBdUI7SUFLdEQsTUFBTSxPQUFPLEdBQUcsc0JBQXNCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFFL0MsT0FBTztRQUNMLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsU0FBc0IsRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLE9BQU8sRUFBRTtRQUM5RSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLFdBQXdCLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxTQUFTLEVBQUU7UUFDcEYsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxTQUFzQixFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsT0FBTyxFQUFFO0tBQy9FLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFDL0MsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRXZlbnQgR3JvdXBpbmcgVXRpbGl0aWVzXG4gKlxuICogVXRpbGl0aWVzIGZvciBvcmdhbml6aW5nIGV2ZW50cyBieSB0aW1lIG9mIGRheS5cbiAqIFVzZWQgaW4gdGhlIEdhdGhlcmluZ3Mgc2NyZWVuIHRvIHNob3cgZXZlbnRzIGdyb3VwZWQgYnlcbiAqIE1vcm5pbmcsIEFmdGVybm9vbiwgYW5kIEV2ZW5pbmcuXG4gKlxuICogQG1vZHVsZSBhcGkvdXRpbHMvZXZlbnRHcm91cGluZ1xuICovXG5cbmltcG9ydCB7IEV2ZW50UmVzcG9uc2UgfSBmcm9tICcuLi90eXBlcyc7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFRZUEVTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCB0eXBlIFRpbWVPZkRheSA9ICdNT1JOSU5HJyB8ICdBRlRFUk5PT04nIHwgJ0VWRU5JTkcnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdyb3VwZWRFdmVudHMge1xuICBtb3JuaW5nOiBFdmVudFJlc3BvbnNlW107XG4gIGFmdGVybm9vbjogRXZlbnRSZXNwb25zZVtdO1xuICBldmVuaW5nOiBFdmVudFJlc3BvbnNlW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGltZU9mRGF5SW5mbyB7XG4gIGtleTogVGltZU9mRGF5O1xuICBsYWJlbDogc3RyaW5nO1xuICBlbW9qaTogc3RyaW5nO1xuICBob3VyczogeyBzdGFydDogbnVtYmVyOyBlbmQ6IG51bWJlciB9O1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBDT05TVEFOVFNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGNvbnN0IFRJTUVfT0ZfREFZX0NPTkZJRzogUmVjb3JkPFRpbWVPZkRheSwgVGltZU9mRGF5SW5mbz4gPSB7XG4gIE1PUk5JTkc6IHtcbiAgICBrZXk6ICdNT1JOSU5HJyxcbiAgICBsYWJlbDogJ01vcm5pbmcnLFxuICAgIGVtb2ppOiAnJyxcbiAgICBob3VyczogeyBzdGFydDogNSwgZW5kOiAxMSB9LCAvLyA1OjAwIEFNIC0gMTE6NTkgQU1cbiAgfSxcbiAgQUZURVJOT09OOiB7XG4gICAga2V5OiAnQUZURVJOT09OJyxcbiAgICBsYWJlbDogJ0FmdGVybm9vbicsXG4gICAgZW1vamk6ICcnLFxuICAgIGhvdXJzOiB7IHN0YXJ0OiAxMiwgZW5kOiAxNiB9LCAvLyAxMjowMCBQTSAtIDQ6NTkgUE1cbiAgfSxcbiAgRVZFTklORzoge1xuICAgIGtleTogJ0VWRU5JTkcnLFxuICAgIGxhYmVsOiAnRXZlbmluZycsXG4gICAgZW1vamk6ICcnLFxuICAgIGhvdXJzOiB7IHN0YXJ0OiAxNywgZW5kOiA0IH0sIC8vIDU6MDAgUE0gLSA0OjU5IEFNIChuZXh0IGRheSlcbiAgfSxcbn07XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEdldCB0aW1lIG9mIGRheSBmb3IgYSBnaXZlbiBkYXRlXG4gKlxuICogQHBhcmFtIGRhdGUgLSBEYXRlIHN0cmluZyBvciBEYXRlIG9iamVjdFxuICogQHJldHVybnMgVGltZU9mRGF5IC0gTU9STklORywgQUZURVJOT09OLCBvciBFVkVOSU5HXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzeFxuICogY29uc3QgdGltZU9mRGF5ID0gZ2V0VGltZU9mRGF5KCcyMDI0LTAzLTE1VDEwOjAwOjAwWicpO1xuICogY29uc29sZS5sb2codGltZU9mRGF5KTsgLy8gJ01PUk5JTkcnXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFRpbWVPZkRheShkYXRlOiBEYXRlIHwgc3RyaW5nKTogVGltZU9mRGF5IHtcbiAgY29uc3QgZCA9IHR5cGVvZiBkYXRlID09PSAnc3RyaW5nJyA/IG5ldyBEYXRlKGRhdGUpIDogZGF0ZTtcbiAgY29uc3QgaG91ciA9IGQuZ2V0SG91cnMoKTtcblxuICBpZiAoaG91ciA+PSA1ICYmIGhvdXIgPCAxMikgcmV0dXJuICdNT1JOSU5HJztcbiAgaWYgKGhvdXIgPj0gMTIgJiYgaG91ciA8IDE3KSByZXR1cm4gJ0FGVEVSTk9PTic7XG4gIHJldHVybiAnRVZFTklORyc7XG59XG5cbi8qKlxuICogR2V0IGxhYmVsIGZvciB0aW1lIG9mIGRheVxuICpcbiAqIEBwYXJhbSB0aW1lT2ZEYXkgLSBUaW1lT2ZEYXkgZW51bSB2YWx1ZVxuICogQHJldHVybnMgSHVtYW4tcmVhZGFibGUgbGFiZWxcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHN4XG4gKiBjb25zdCBsYWJlbCA9IGdldFRpbWVPZkRheUxhYmVsKCdNT1JOSU5HJyk7XG4gKiBjb25zb2xlLmxvZyhsYWJlbCk7IC8vICdNb3JuaW5nJ1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRUaW1lT2ZEYXlMYWJlbCh0aW1lT2ZEYXk6IFRpbWVPZkRheSk6IHN0cmluZyB7XG4gIHJldHVybiBUSU1FX09GX0RBWV9DT05GSUdbdGltZU9mRGF5XS5sYWJlbDtcbn1cblxuLyoqXG4gKiBHcm91cCBldmVudHMgYnkgdGltZSBvZiBkYXlcbiAqXG4gKiBAcGFyYW0gZXZlbnRzIC0gQXJyYXkgb2YgZXZlbnRzIHRvIGdyb3VwXG4gKiBAcmV0dXJucyBHcm91cGVkRXZlbnRzIG9iamVjdCB3aXRoIG1vcm5pbmcsIGFmdGVybm9vbiwgYW5kIGV2ZW5pbmcgYXJyYXlzXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzeFxuICogaW1wb3J0IHsgdXNlVXBjb21pbmdFdmVudHMsIGdyb3VwRXZlbnRzQnlUaW1lT2ZEYXkgfSBmcm9tICdAZ3Jvd3NvYmVyL3Nkayc7XG4gKlxuICogZnVuY3Rpb24gR2F0aGVyaW5nc0xpc3QoKSB7XG4gKiAgIGNvbnN0IHsgZGF0YTogZXZlbnRzIH0gPSB1c2VVcGNvbWluZ0V2ZW50cygzMCk7XG4gKiAgIGNvbnN0IGdyb3VwZWQgPSB1c2VNZW1vKCgpID0+IHtcbiAqICAgICBpZiAoIWV2ZW50cykgcmV0dXJuIG51bGw7XG4gKiAgICAgcmV0dXJuIGdyb3VwRXZlbnRzQnlUaW1lT2ZEYXkoZXZlbnRzKTtcbiAqICAgfSwgW2V2ZW50c10pO1xuICpcbiAqICAgcmV0dXJuIChcbiAqICAgICA8U2VjdGlvbkxpc3RcbiAqICAgICAgIHNlY3Rpb25zPXtbXG4gKiAgICAgICAgIHsgdGl0bGU6ICdNb3JuaW5nJywgZGF0YTogZ3JvdXBlZD8ubW9ybmluZyB8fCBbXSB9LFxuICogICAgICAgICB7IHRpdGxlOiAnQWZ0ZXJub29uJywgZGF0YTogZ3JvdXBlZD8uYWZ0ZXJub29uIHx8IFtdIH0sXG4gKiAgICAgICAgIHsgdGl0bGU6ICdFdmVuaW5nJywgZGF0YTogZ3JvdXBlZD8uZXZlbmluZyB8fCBbXSB9LFxuICogICAgICAgXX1cbiAqICAgICAgIC4uLlxuICogICAgIC8+XG4gKiAgICk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdyb3VwRXZlbnRzQnlUaW1lT2ZEYXkoZXZlbnRzOiBFdmVudFJlc3BvbnNlW10pOiBHcm91cGVkRXZlbnRzIHtcbiAgY29uc3QgZ3JvdXBlZDogR3JvdXBlZEV2ZW50cyA9IHtcbiAgICBtb3JuaW5nOiBbXSxcbiAgICBhZnRlcm5vb246IFtdLFxuICAgIGV2ZW5pbmc6IFtdLFxuICB9O1xuXG4gIGZvciAoY29uc3QgZXZlbnQgb2YgZXZlbnRzKSB7XG4gICAgY29uc3QgdGltZU9mRGF5ID0gZ2V0VGltZU9mRGF5KGV2ZW50LnN0YXJ0RGF0ZSk7XG4gICAgc3dpdGNoICh0aW1lT2ZEYXkpIHtcbiAgICAgIGNhc2UgJ01PUk5JTkcnOlxuICAgICAgICBncm91cGVkLm1vcm5pbmcucHVzaChldmVudCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnQUZURVJOT09OJzpcbiAgICAgICAgZ3JvdXBlZC5hZnRlcm5vb24ucHVzaChldmVudCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnRVZFTklORyc6XG4gICAgICAgIGdyb3VwZWQuZXZlbmluZy5wdXNoKGV2ZW50KTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGdyb3VwZWQ7XG59XG5cbi8qKlxuICogQ29udmVydCBncm91cGVkIGV2ZW50cyB0byBzZWN0aW9uIGxpc3QgZGF0YSBmb3JtYXRcbiAqXG4gKiBAcGFyYW0gZXZlbnRzIC0gQXJyYXkgb2YgZXZlbnRzIHRvIGdyb3VwXG4gKiBAcmV0dXJucyBBcnJheSBvZiBzZWN0aW9ucyB3aXRoIHRpdGxlIGFuZCBkYXRhXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzeFxuICogY29uc3Qgc2VjdGlvbnMgPSBnZXRFdmVudFNlY3Rpb25zKGV2ZW50cyk7XG4gKiAvLyBbXG4gKiAvLyAgIHsgdGl0bGU6ICdNb3JuaW5nJywgZGF0YTogWy4uLl0gfSxcbiAqIC8vICAgeyB0aXRsZTogJ0FmdGVybm9vbicsIGRhdGE6IFsuLi5dIH0sXG4gKiAvLyAgIHsgdGl0bGU6ICdFdmVuaW5nJywgZGF0YTogWy4uLl0gfSxcbiAqIC8vIF1cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RXZlbnRTZWN0aW9ucyhldmVudHM6IEV2ZW50UmVzcG9uc2VbXSk6IEFycmF5PHtcbiAgdGl0bGU6IHN0cmluZztcbiAgdGltZU9mRGF5OiBUaW1lT2ZEYXk7XG4gIGRhdGE6IEV2ZW50UmVzcG9uc2VbXTtcbn0+IHtcbiAgY29uc3QgZ3JvdXBlZCA9IGdyb3VwRXZlbnRzQnlUaW1lT2ZEYXkoZXZlbnRzKTtcblxuICByZXR1cm4gW1xuICAgIHsgdGl0bGU6ICdNb3JuaW5nJywgdGltZU9mRGF5OiAnTU9STklORycgYXMgVGltZU9mRGF5LCBkYXRhOiBncm91cGVkLm1vcm5pbmcgfSxcbiAgICB7IHRpdGxlOiAnQWZ0ZXJub29uJywgdGltZU9mRGF5OiAnQUZURVJOT09OJyBhcyBUaW1lT2ZEYXksIGRhdGE6IGdyb3VwZWQuYWZ0ZXJub29uIH0sXG4gICAgeyB0aXRsZTogJ0V2ZW5pbmcnLCB0aW1lT2ZEYXk6ICdFVkVOSU5HJyBhcyBUaW1lT2ZEYXksIGRhdGE6IGdyb3VwZWQuZXZlbmluZyB9LFxuICBdLmZpbHRlcihzZWN0aW9uID0+IHNlY3Rpb24uZGF0YS5sZW5ndGggPiAwKTtcbn1cbiJdfQ==
package/dist/index.d.ts CHANGED
@@ -34,3 +34,4 @@ export type { SDKConfig } from './api/client';
34
34
  export * from './api/types';
35
35
  export * from './api/queries';
36
36
  export * from './api/mutations';
37
+ export * from './api/utils/eventGrouping';
package/dist/index.js CHANGED
@@ -64,4 +64,8 @@ __exportStar(require("./api/queries"), exports);
64
64
  // MUTATION HOOKS
65
65
  // ============================================================================
66
66
  __exportStar(require("./api/mutations"), exports);
67
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E4Qkc7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUgsK0VBQStFO0FBQy9FLGFBQWE7QUFDYiwrRUFBK0U7QUFFL0UsdUNBQTBEO0FBQWpELHNHQUFBLFlBQVksT0FBQTtBQUFFLHNHQUFBLFlBQVksT0FBQTtBQUduQywrRUFBK0U7QUFDL0UsUUFBUTtBQUNSLCtFQUErRTtBQUUvRSw4Q0FBNEI7QUFFNUIsK0VBQStFO0FBQy9FLGNBQWM7QUFDZCwrRUFBK0U7QUFFL0UsZ0RBQThCO0FBRTlCLCtFQUErRTtBQUMvRSxpQkFBaUI7QUFDakIsK0VBQStFO0FBRS9FLGtEQUFnQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR3Jvd1NvYmVyIFNES1xuICpcbiAqIFR5cGVTY3JpcHQgU0RLIGZvciB0aGUgR3Jvd1NvYmVyIEFQSSB3aXRoIFRhblN0YWNrIFF1ZXJ5IGhvb2tzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0c3hcbiAqIGltcG9ydCB7IGNvbmZpZ3VyZVNESywgdXNlQ3VycmVudFVzZXIsIHVzZUxvZ2luIH0gZnJvbSAnQGdyb3dzb2Jlci9zZGsnO1xuICpcbiAqIC8vIENvbmZpZ3VyZSBTREsgd2l0aCB5b3VyIEFQSSBiYXNlIFVSTCBhbmQgdG9rZW4gbWFuYWdlbWVudFxuICogY29uZmlndXJlU0RLKHtcbiAqICAgYmFzZVVSTDogJ2h0dHBzOi8vYXBpLmdyb3dzb2Jlci5hcHAnLFxuICogICBnZXRBY2Nlc3NUb2tlbjogKCkgPT4gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2FjY2Vzc1Rva2VuJyksXG4gKiAgIHJlZnJlc2hBY2Nlc3NUb2tlbjogYXN5bmMgKCkgPT4ge1xuICogICAgIC8vIFlvdXIgdG9rZW4gcmVmcmVzaCBsb2dpY1xuICogICAgIHJldHVybiBuZXdBY2Nlc3NUb2tlbjtcbiAqICAgfSxcbiAqICAgb25VbmF1dGhvcml6ZWQ6ICgpID0+IHtcbiAqICAgICAvLyBIYW5kbGUgdW5hdXRob3JpemVkIGFjY2Vzc1xuICogICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gJy9sb2dpbic7XG4gKiAgIH0sXG4gKiB9KTtcbiAqXG4gKiAvLyBVc2UgaG9va3MgaW4geW91ciBjb21wb25lbnRzXG4gKiBmdW5jdGlvbiBBcHAoKSB7XG4gKiAgIGNvbnN0IHsgZGF0YTogdXNlciB9ID0gdXNlQ3VycmVudFVzZXIoKTtcbiAqICAgY29uc3QgeyBtdXRhdGU6IGxvZ2luIH0gPSB1c2VMb2dpbigpO1xuICogICAvLyAuLi5cbiAqIH1cbiAqIGBgYFxuICovXG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEFQSSBDTElFTlRcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IHsgY29uZmlndXJlU0RLLCBnZXRBcGlDbGllbnQgfSBmcm9tICcuL2FwaS9jbGllbnQnO1xuZXhwb3J0IHR5cGUgeyBTREtDb25maWcgfSBmcm9tICcuL2FwaS9jbGllbnQnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUWVBFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgKiBmcm9tICcuL2FwaS90eXBlcyc7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFFVRVJZIEhPT0tTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCAqIGZyb20gJy4vYXBpL3F1ZXJpZXMnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBNVVRBVElPTiBIT09LU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgKiBmcm9tICcuL2FwaS9tdXRhdGlvbnMnO1xuXG4iXX0=
67
+ // ============================================================================
68
+ // UTILITIES
69
+ // ============================================================================
70
+ __exportStar(require("./api/utils/eventGrouping"), exports);
71
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E4Qkc7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUgsK0VBQStFO0FBQy9FLGFBQWE7QUFDYiwrRUFBK0U7QUFFL0UsdUNBQTBEO0FBQWpELHNHQUFBLFlBQVksT0FBQTtBQUFFLHNHQUFBLFlBQVksT0FBQTtBQUduQywrRUFBK0U7QUFDL0UsUUFBUTtBQUNSLCtFQUErRTtBQUUvRSw4Q0FBNEI7QUFFNUIsK0VBQStFO0FBQy9FLGNBQWM7QUFDZCwrRUFBK0U7QUFFL0UsZ0RBQThCO0FBRTlCLCtFQUErRTtBQUMvRSxpQkFBaUI7QUFDakIsK0VBQStFO0FBRS9FLGtEQUFnQztBQUVoQywrRUFBK0U7QUFDL0UsWUFBWTtBQUNaLCtFQUErRTtBQUUvRSw0REFBMEMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdyb3dTb2JlciBTREtcbiAqXG4gKiBUeXBlU2NyaXB0IFNESyBmb3IgdGhlIEdyb3dTb2JlciBBUEkgd2l0aCBUYW5TdGFjayBRdWVyeSBob29rcy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHN4XG4gKiBpbXBvcnQgeyBjb25maWd1cmVTREssIHVzZUN1cnJlbnRVc2VyLCB1c2VMb2dpbiB9IGZyb20gJ0Bncm93c29iZXIvc2RrJztcbiAqXG4gKiAvLyBDb25maWd1cmUgU0RLIHdpdGggeW91ciBBUEkgYmFzZSBVUkwgYW5kIHRva2VuIG1hbmFnZW1lbnRcbiAqIGNvbmZpZ3VyZVNESyh7XG4gKiAgIGJhc2VVUkw6ICdodHRwczovL2FwaS5ncm93c29iZXIuYXBwJyxcbiAqICAgZ2V0QWNjZXNzVG9rZW46ICgpID0+IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdhY2Nlc3NUb2tlbicpLFxuICogICByZWZyZXNoQWNjZXNzVG9rZW46IGFzeW5jICgpID0+IHtcbiAqICAgICAvLyBZb3VyIHRva2VuIHJlZnJlc2ggbG9naWNcbiAqICAgICByZXR1cm4gbmV3QWNjZXNzVG9rZW47XG4gKiAgIH0sXG4gKiAgIG9uVW5hdXRob3JpemVkOiAoKSA9PiB7XG4gKiAgICAgLy8gSGFuZGxlIHVuYXV0aG9yaXplZCBhY2Nlc3NcbiAqICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9ICcvbG9naW4nO1xuICogICB9LFxuICogfSk7XG4gKlxuICogLy8gVXNlIGhvb2tzIGluIHlvdXIgY29tcG9uZW50c1xuICogZnVuY3Rpb24gQXBwKCkge1xuICogICBjb25zdCB7IGRhdGE6IHVzZXIgfSA9IHVzZUN1cnJlbnRVc2VyKCk7XG4gKiAgIGNvbnN0IHsgbXV0YXRlOiBsb2dpbiB9ID0gdXNlTG9naW4oKTtcbiAqICAgLy8gLi4uXG4gKiB9XG4gKiBgYGBcbiAqL1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBBUEkgQ0xJRU5UXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCB7IGNvbmZpZ3VyZVNESywgZ2V0QXBpQ2xpZW50IH0gZnJvbSAnLi9hcGkvY2xpZW50JztcbmV4cG9ydCB0eXBlIHsgU0RLQ29uZmlnIH0gZnJvbSAnLi9hcGkvY2xpZW50JztcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVFlQRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0ICogZnJvbSAnLi9hcGkvdHlwZXMnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBRVUVSWSBIT09LU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgKiBmcm9tICcuL2FwaS9xdWVyaWVzJztcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gTVVUQVRJT04gSE9PS1Ncbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0ICogZnJvbSAnLi9hcGkvbXV0YXRpb25zJztcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVVRJTElUSUVTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCAqIGZyb20gJy4vYXBpL3V0aWxzL2V2ZW50R3JvdXBpbmcnO1xuXG4iXX0=
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growsober/sdk",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Shared TypeScript SDK for GrowSober API - TanStack Query hooks, API client, and utilities",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Event Grouping Utilities
3
+ *
4
+ * Utilities for organizing events by time of day.
5
+ * Used in the Gatherings screen to show events grouped by
6
+ * Morning, Afternoon, and Evening.
7
+ *
8
+ * @module api/utils/eventGrouping
9
+ */
10
+
11
+ import { EventResponse } from '../types';
12
+
13
+ // ============================================================================
14
+ // TYPES
15
+ // ============================================================================
16
+
17
+ export type TimeOfDay = 'MORNING' | 'AFTERNOON' | 'EVENING';
18
+
19
+ export interface GroupedEvents {
20
+ morning: EventResponse[];
21
+ afternoon: EventResponse[];
22
+ evening: EventResponse[];
23
+ }
24
+
25
+ export interface TimeOfDayInfo {
26
+ key: TimeOfDay;
27
+ label: string;
28
+ emoji: string;
29
+ hours: { start: number; end: number };
30
+ }
31
+
32
+ // ============================================================================
33
+ // CONSTANTS
34
+ // ============================================================================
35
+
36
+ export const TIME_OF_DAY_CONFIG: Record<TimeOfDay, TimeOfDayInfo> = {
37
+ MORNING: {
38
+ key: 'MORNING',
39
+ label: 'Morning',
40
+ emoji: '',
41
+ hours: { start: 5, end: 11 }, // 5:00 AM - 11:59 AM
42
+ },
43
+ AFTERNOON: {
44
+ key: 'AFTERNOON',
45
+ label: 'Afternoon',
46
+ emoji: '',
47
+ hours: { start: 12, end: 16 }, // 12:00 PM - 4:59 PM
48
+ },
49
+ EVENING: {
50
+ key: 'EVENING',
51
+ label: 'Evening',
52
+ emoji: '',
53
+ hours: { start: 17, end: 4 }, // 5:00 PM - 4:59 AM (next day)
54
+ },
55
+ };
56
+
57
+ // ============================================================================
58
+ // FUNCTIONS
59
+ // ============================================================================
60
+
61
+ /**
62
+ * Get time of day for a given date
63
+ *
64
+ * @param date - Date string or Date object
65
+ * @returns TimeOfDay - MORNING, AFTERNOON, or EVENING
66
+ *
67
+ * @example
68
+ * ```tsx
69
+ * const timeOfDay = getTimeOfDay('2024-03-15T10:00:00Z');
70
+ * console.log(timeOfDay); // 'MORNING'
71
+ * ```
72
+ */
73
+ export function getTimeOfDay(date: Date | string): TimeOfDay {
74
+ const d = typeof date === 'string' ? new Date(date) : date;
75
+ const hour = d.getHours();
76
+
77
+ if (hour >= 5 && hour < 12) return 'MORNING';
78
+ if (hour >= 12 && hour < 17) return 'AFTERNOON';
79
+ return 'EVENING';
80
+ }
81
+
82
+ /**
83
+ * Get label for time of day
84
+ *
85
+ * @param timeOfDay - TimeOfDay enum value
86
+ * @returns Human-readable label
87
+ *
88
+ * @example
89
+ * ```tsx
90
+ * const label = getTimeOfDayLabel('MORNING');
91
+ * console.log(label); // 'Morning'
92
+ * ```
93
+ */
94
+ export function getTimeOfDayLabel(timeOfDay: TimeOfDay): string {
95
+ return TIME_OF_DAY_CONFIG[timeOfDay].label;
96
+ }
97
+
98
+ /**
99
+ * Group events by time of day
100
+ *
101
+ * @param events - Array of events to group
102
+ * @returns GroupedEvents object with morning, afternoon, and evening arrays
103
+ *
104
+ * @example
105
+ * ```tsx
106
+ * import { useUpcomingEvents, groupEventsByTimeOfDay } from '@growsober/sdk';
107
+ *
108
+ * function GatheringsList() {
109
+ * const { data: events } = useUpcomingEvents(30);
110
+ * const grouped = useMemo(() => {
111
+ * if (!events) return null;
112
+ * return groupEventsByTimeOfDay(events);
113
+ * }, [events]);
114
+ *
115
+ * return (
116
+ * <SectionList
117
+ * sections={[
118
+ * { title: 'Morning', data: grouped?.morning || [] },
119
+ * { title: 'Afternoon', data: grouped?.afternoon || [] },
120
+ * { title: 'Evening', data: grouped?.evening || [] },
121
+ * ]}
122
+ * ...
123
+ * />
124
+ * );
125
+ * }
126
+ * ```
127
+ */
128
+ export function groupEventsByTimeOfDay(events: EventResponse[]): GroupedEvents {
129
+ const grouped: GroupedEvents = {
130
+ morning: [],
131
+ afternoon: [],
132
+ evening: [],
133
+ };
134
+
135
+ for (const event of events) {
136
+ const timeOfDay = getTimeOfDay(event.startDate);
137
+ switch (timeOfDay) {
138
+ case 'MORNING':
139
+ grouped.morning.push(event);
140
+ break;
141
+ case 'AFTERNOON':
142
+ grouped.afternoon.push(event);
143
+ break;
144
+ case 'EVENING':
145
+ grouped.evening.push(event);
146
+ break;
147
+ }
148
+ }
149
+
150
+ return grouped;
151
+ }
152
+
153
+ /**
154
+ * Convert grouped events to section list data format
155
+ *
156
+ * @param events - Array of events to group
157
+ * @returns Array of sections with title and data
158
+ *
159
+ * @example
160
+ * ```tsx
161
+ * const sections = getEventSections(events);
162
+ * // [
163
+ * // { title: 'Morning', data: [...] },
164
+ * // { title: 'Afternoon', data: [...] },
165
+ * // { title: 'Evening', data: [...] },
166
+ * // ]
167
+ * ```
168
+ */
169
+ export function getEventSections(events: EventResponse[]): Array<{
170
+ title: string;
171
+ timeOfDay: TimeOfDay;
172
+ data: EventResponse[];
173
+ }> {
174
+ const grouped = groupEventsByTimeOfDay(events);
175
+
176
+ return [
177
+ { title: 'Morning', timeOfDay: 'MORNING' as TimeOfDay, data: grouped.morning },
178
+ { title: 'Afternoon', timeOfDay: 'AFTERNOON' as TimeOfDay, data: grouped.afternoon },
179
+ { title: 'Evening', timeOfDay: 'EVENING' as TimeOfDay, data: grouped.evening },
180
+ ].filter(section => section.data.length > 0);
181
+ }
package/src/index.ts CHANGED
@@ -55,3 +55,9 @@ export * from './api/queries';
55
55
 
56
56
  export * from './api/mutations';
57
57
 
58
+ // ============================================================================
59
+ // UTILITIES
60
+ // ============================================================================
61
+
62
+ export * from './api/utils/eventGrouping';
63
+