@growsober/sdk 1.0.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 (129) hide show
  1. package/README.md +276 -0
  2. package/dist/__tests__/e2e.test.d.ts +7 -0
  3. package/dist/__tests__/e2e.test.js +472 -0
  4. package/dist/api/client.d.ts +11 -0
  5. package/dist/api/client.js +61 -0
  6. package/dist/api/mutations/admin.d.ts +167 -0
  7. package/dist/api/mutations/admin.js +326 -0
  8. package/dist/api/mutations/ambassadors.d.ts +52 -0
  9. package/dist/api/mutations/ambassadors.js +148 -0
  10. package/dist/api/mutations/auth.d.ts +267 -0
  11. package/dist/api/mutations/auth.js +332 -0
  12. package/dist/api/mutations/bookings.d.ts +59 -0
  13. package/dist/api/mutations/bookings.js +143 -0
  14. package/dist/api/mutations/event-chat.d.ts +35 -0
  15. package/dist/api/mutations/event-chat.js +147 -0
  16. package/dist/api/mutations/events.d.ts +87 -0
  17. package/dist/api/mutations/events.js +205 -0
  18. package/dist/api/mutations/grow90.d.ts +36 -0
  19. package/dist/api/mutations/grow90.js +132 -0
  20. package/dist/api/mutations/hubs.d.ts +111 -0
  21. package/dist/api/mutations/hubs.js +240 -0
  22. package/dist/api/mutations/index.d.ts +22 -0
  23. package/dist/api/mutations/index.js +39 -0
  24. package/dist/api/mutations/jack.d.ts +61 -0
  25. package/dist/api/mutations/jack.js +104 -0
  26. package/dist/api/mutations/library.d.ts +67 -0
  27. package/dist/api/mutations/library.js +168 -0
  28. package/dist/api/mutations/map.d.ts +153 -0
  29. package/dist/api/mutations/map.js +181 -0
  30. package/dist/api/mutations/matching.d.ts +130 -0
  31. package/dist/api/mutations/matching.js +204 -0
  32. package/dist/api/mutations/notifications.d.ts +63 -0
  33. package/dist/api/mutations/notifications.js +106 -0
  34. package/dist/api/mutations/offers.d.ts +26 -0
  35. package/dist/api/mutations/offers.js +47 -0
  36. package/dist/api/mutations/subscriptions.d.ts +127 -0
  37. package/dist/api/mutations/subscriptions.js +140 -0
  38. package/dist/api/mutations/support.d.ts +165 -0
  39. package/dist/api/mutations/support.js +307 -0
  40. package/dist/api/mutations/users.d.ts +211 -0
  41. package/dist/api/mutations/users.js +261 -0
  42. package/dist/api/queries/admin.d.ts +257 -0
  43. package/dist/api/queries/admin.js +320 -0
  44. package/dist/api/queries/ambassadors.d.ts +53 -0
  45. package/dist/api/queries/ambassadors.js +98 -0
  46. package/dist/api/queries/auth.d.ts +16 -0
  47. package/dist/api/queries/auth.js +25 -0
  48. package/dist/api/queries/bookings.d.ts +91 -0
  49. package/dist/api/queries/bookings.js +102 -0
  50. package/dist/api/queries/businesses.d.ts +212 -0
  51. package/dist/api/queries/businesses.js +154 -0
  52. package/dist/api/queries/event-chat.d.ts +19 -0
  53. package/dist/api/queries/event-chat.js +75 -0
  54. package/dist/api/queries/events.d.ts +322 -0
  55. package/dist/api/queries/events.js +221 -0
  56. package/dist/api/queries/grow90.d.ts +26 -0
  57. package/dist/api/queries/grow90.js +85 -0
  58. package/dist/api/queries/hubs.d.ts +165 -0
  59. package/dist/api/queries/hubs.js +143 -0
  60. package/dist/api/queries/index.d.ts +23 -0
  61. package/dist/api/queries/index.js +40 -0
  62. package/dist/api/queries/jack.d.ts +63 -0
  63. package/dist/api/queries/jack.js +92 -0
  64. package/dist/api/queries/library.d.ts +132 -0
  65. package/dist/api/queries/library.js +120 -0
  66. package/dist/api/queries/map.d.ts +216 -0
  67. package/dist/api/queries/map.js +278 -0
  68. package/dist/api/queries/matching.d.ts +136 -0
  69. package/dist/api/queries/matching.js +161 -0
  70. package/dist/api/queries/notifications.d.ts +78 -0
  71. package/dist/api/queries/notifications.js +88 -0
  72. package/dist/api/queries/offers.d.ts +91 -0
  73. package/dist/api/queries/offers.js +103 -0
  74. package/dist/api/queries/subscriptions.d.ts +56 -0
  75. package/dist/api/queries/subscriptions.js +73 -0
  76. package/dist/api/queries/support.d.ts +106 -0
  77. package/dist/api/queries/support.js +202 -0
  78. package/dist/api/queries/users.d.ts +293 -0
  79. package/dist/api/queries/users.js +370 -0
  80. package/dist/api/types.d.ts +464 -0
  81. package/dist/api/types.js +9 -0
  82. package/dist/hooks/useAuth.d.ts +5 -0
  83. package/dist/hooks/useAuth.js +39 -0
  84. package/dist/hooks/useUser.d.ts +43 -0
  85. package/dist/hooks/useUser.js +44 -0
  86. package/dist/index.d.ts +36 -0
  87. package/dist/index.js +67 -0
  88. package/package.json +62 -0
  89. package/src/__tests__/e2e.test.ts +502 -0
  90. package/src/api/client.ts +71 -0
  91. package/src/api/mutations/admin.ts +531 -0
  92. package/src/api/mutations/ambassadors.ts +185 -0
  93. package/src/api/mutations/auth.ts +350 -0
  94. package/src/api/mutations/bookings.ts +190 -0
  95. package/src/api/mutations/event-chat.ts +177 -0
  96. package/src/api/mutations/events.ts +273 -0
  97. package/src/api/mutations/grow90.ts +169 -0
  98. package/src/api/mutations/hubs.ts +385 -0
  99. package/src/api/mutations/index.ts +23 -0
  100. package/src/api/mutations/jack.ts +130 -0
  101. package/src/api/mutations/library.ts +212 -0
  102. package/src/api/mutations/map.ts +230 -0
  103. package/src/api/mutations/matching.ts +271 -0
  104. package/src/api/mutations/notifications.ts +114 -0
  105. package/src/api/mutations/offers.ts +73 -0
  106. package/src/api/mutations/subscriptions.ts +162 -0
  107. package/src/api/mutations/support.ts +390 -0
  108. package/src/api/mutations/users.ts +271 -0
  109. package/src/api/queries/admin.ts +480 -0
  110. package/src/api/queries/ambassadors.ts +139 -0
  111. package/src/api/queries/auth.ts +24 -0
  112. package/src/api/queries/bookings.ts +135 -0
  113. package/src/api/queries/businesses.ts +203 -0
  114. package/src/api/queries/event-chat.ts +78 -0
  115. package/src/api/queries/events.ts +272 -0
  116. package/src/api/queries/grow90.ts +98 -0
  117. package/src/api/queries/hubs.ts +211 -0
  118. package/src/api/queries/index.ts +24 -0
  119. package/src/api/queries/jack.ts +127 -0
  120. package/src/api/queries/library.ts +166 -0
  121. package/src/api/queries/map.ts +331 -0
  122. package/src/api/queries/matching.ts +238 -0
  123. package/src/api/queries/notifications.ts +103 -0
  124. package/src/api/queries/offers.ts +136 -0
  125. package/src/api/queries/subscriptions.ts +91 -0
  126. package/src/api/queries/support.ts +235 -0
  127. package/src/api/queries/users.ts +393 -0
  128. package/src/api/types.ts +596 -0
  129. package/src/index.ts +57 -0
@@ -0,0 +1,135 @@
1
+ import { useQuery, UseQueryOptions } from '@tanstack/react-query';
2
+ import { getApiClient } from '../client';
3
+ import type { BookingResponse } from '../types';
4
+
5
+ // ============================================================================
6
+ // QUERY KEY FACTORY
7
+ // ============================================================================
8
+
9
+ export const bookingKeys = {
10
+ all: ['bookings'] as const,
11
+ lists: () => [...bookingKeys.all, 'list'] as const,
12
+ list: (filters?: BookingFilters) => [...bookingKeys.lists(), filters] as const,
13
+ details: () => [...bookingKeys.all, 'detail'] as const,
14
+ detail: (id: string) => [...bookingKeys.details(), id] as const,
15
+ mine: (filters?: BookingFilters) => [...bookingKeys.all, 'mine', filters] as const,
16
+ qrCode: (id: string) => [...bookingKeys.detail(id), 'qr'] as const,
17
+ };
18
+
19
+ // ============================================================================
20
+ // TYPES
21
+ // ============================================================================
22
+
23
+ export interface BookingFilters {
24
+ page?: number;
25
+ limit?: number;
26
+ status?: 'CONFIRMED' | 'WAITLISTED' | 'CANCELLED';
27
+ eventId?: string;
28
+ }
29
+
30
+ export interface PaginatedBookingsResponse {
31
+ bookings: BookingResponse[];
32
+ total: number;
33
+ page: number;
34
+ limit: number;
35
+ totalPages: number;
36
+ }
37
+
38
+ export interface QrCodeResponse {
39
+ qrCode: string;
40
+ bookingId: string;
41
+ }
42
+
43
+ // ============================================================================
44
+ // QUERY HOOKS
45
+ // ============================================================================
46
+
47
+ /**
48
+ * Get a single booking by ID
49
+ *
50
+ * @param id - Booking ID
51
+ * @param options - TanStack Query options
52
+ *
53
+ * @example
54
+ * ```tsx
55
+ * const { data, isLoading } = useBooking('booking-123');
56
+ * ```
57
+ */
58
+ export function useBooking(
59
+ id: string,
60
+ options?: Omit<UseQueryOptions<BookingResponse>, 'queryKey' | 'queryFn'>
61
+ ) {
62
+ return useQuery({
63
+ queryKey: bookingKeys.detail(id),
64
+ queryFn: async (): Promise<BookingResponse> => {
65
+ const client = getApiClient();
66
+ const response = await client.get(`/api/v1/bookings/${id}`);
67
+ return response.data;
68
+ },
69
+ enabled: !!id,
70
+ ...options,
71
+ });
72
+ }
73
+
74
+ /**
75
+ * Get current user's bookings with optional filters
76
+ *
77
+ * @param filters - Query parameters for filtering and pagination
78
+ * @param options - TanStack Query options
79
+ *
80
+ * @example
81
+ * ```tsx
82
+ * const { data, isLoading } = useMyBookings({
83
+ * page: 1,
84
+ * limit: 20,
85
+ * status: 'CONFIRMED',
86
+ * eventId: 'event-123'
87
+ * });
88
+ * ```
89
+ */
90
+ export function useMyBookings(
91
+ filters?: BookingFilters,
92
+ options?: Omit<UseQueryOptions<PaginatedBookingsResponse>, 'queryKey' | 'queryFn'>
93
+ ) {
94
+ return useQuery({
95
+ queryKey: bookingKeys.mine(filters),
96
+ queryFn: async (): Promise<PaginatedBookingsResponse> => {
97
+ const client = getApiClient();
98
+ // Use /users/me/bookings - the existing API endpoint
99
+ const response = await client.get('/api/v1/users/me/bookings', {
100
+ params: filters,
101
+ });
102
+ // API returns { data: { bookings: [...] }, meta: {...} }
103
+ return response.data.data || response.data;
104
+ },
105
+ ...options,
106
+ });
107
+ }
108
+
109
+ /**
110
+ * Get QR code for a specific booking
111
+ *
112
+ * @param id - Booking ID
113
+ * @param options - TanStack Query options
114
+ *
115
+ * @example
116
+ * ```tsx
117
+ * const { data, isLoading } = useBookingQrCode('booking-123');
118
+ * // data.qrCode contains the QR code string for display
119
+ * ```
120
+ */
121
+ export function useBookingQrCode(
122
+ id: string,
123
+ options?: Omit<UseQueryOptions<QrCodeResponse>, 'queryKey' | 'queryFn'>
124
+ ) {
125
+ return useQuery({
126
+ queryKey: bookingKeys.qrCode(id),
127
+ queryFn: async (): Promise<QrCodeResponse> => {
128
+ const client = getApiClient();
129
+ const response = await client.get(`/api/v1/bookings/${id}/qr`);
130
+ return response.data;
131
+ },
132
+ enabled: !!id,
133
+ ...options,
134
+ });
135
+ }
@@ -0,0 +1,203 @@
1
+ import { useQuery, UseQueryOptions } from '@tanstack/react-query';
2
+ import { getApiClient } from '../client';
3
+ import type { BusinessResponse, OfferResponse } from '../types';
4
+
5
+ // ============================================================================
6
+ // QUERY KEY FACTORY
7
+ // ============================================================================
8
+
9
+ export const businessKeys = {
10
+ all: ['businesses'] as const,
11
+ lists: () => [...businessKeys.all, 'list'] as const,
12
+ list: (filters?: BusinessFilters) => [...businessKeys.lists(), filters] as const,
13
+ details: () => [...businessKeys.all, 'detail'] as const,
14
+ detail: (id: string) => [...businessKeys.details(), id] as const,
15
+ featured: () => [...businessKeys.all, 'featured'] as const,
16
+ nearby: (params?: NearbyBusinessParams) => [...businessKeys.all, 'nearby', params] as const,
17
+ offers: (businessId: string) => [...businessKeys.detail(businessId), 'offers'] as const,
18
+ };
19
+
20
+ // ============================================================================
21
+ // TYPES
22
+ // ============================================================================
23
+
24
+ export interface BusinessFilters {
25
+ page?: number;
26
+ limit?: number;
27
+ search?: string;
28
+ cityId?: string;
29
+ type?: string;
30
+ hasAfDrinks?: boolean;
31
+ isAfVenue?: boolean;
32
+ isFeatured?: boolean;
33
+ isPartner?: boolean;
34
+ lat?: number;
35
+ long?: number;
36
+ radius?: number;
37
+ sortBy?: string;
38
+ sortOrder?: 'asc' | 'desc';
39
+ }
40
+
41
+ export interface NearbyBusinessParams {
42
+ lat: number;
43
+ long: number;
44
+ radius?: number;
45
+ }
46
+
47
+ export interface PaginatedBusinessesResponse {
48
+ businesses: BusinessResponse[];
49
+ total: number;
50
+ page: number;
51
+ limit: number;
52
+ totalPages: number;
53
+ }
54
+
55
+ // ============================================================================
56
+ // QUERY HOOKS
57
+ // ============================================================================
58
+
59
+ /**
60
+ * Get paginated list of businesses with optional filters
61
+ *
62
+ * @param filters - Query parameters for filtering and pagination
63
+ * @param options - TanStack Query options
64
+ *
65
+ * @example
66
+ * ```tsx
67
+ * const { data, isLoading } = useBusinesses({
68
+ * page: 1,
69
+ * limit: 20,
70
+ * cityId: 'city-123',
71
+ * hasAfDrinks: true,
72
+ * sortBy: 'name',
73
+ * sortOrder: 'asc'
74
+ * });
75
+ * ```
76
+ */
77
+ export function useBusinesses(
78
+ filters?: BusinessFilters,
79
+ options?: Omit<UseQueryOptions<PaginatedBusinessesResponse>, 'queryKey' | 'queryFn'>
80
+ ) {
81
+ return useQuery({
82
+ queryKey: businessKeys.list(filters),
83
+ queryFn: async (): Promise<PaginatedBusinessesResponse> => {
84
+ const client = getApiClient();
85
+ const response = await client.get('/api/v1/businesses', {
86
+ params: filters,
87
+ });
88
+ return response.data;
89
+ },
90
+ ...options,
91
+ });
92
+ }
93
+
94
+ /**
95
+ * Get featured businesses
96
+ *
97
+ * @param options - TanStack Query options
98
+ *
99
+ * @example
100
+ * ```tsx
101
+ * const { data, isLoading } = useFeaturedBusinesses();
102
+ * ```
103
+ */
104
+ export function useFeaturedBusinesses(
105
+ options?: Omit<UseQueryOptions<BusinessResponse[]>, 'queryKey' | 'queryFn'>
106
+ ) {
107
+ return useQuery({
108
+ queryKey: businessKeys.featured(),
109
+ queryFn: async (): Promise<BusinessResponse[]> => {
110
+ const client = getApiClient();
111
+ const response = await client.get('/api/v1/businesses/featured');
112
+ return response.data;
113
+ },
114
+ ...options,
115
+ });
116
+ }
117
+
118
+ /**
119
+ * Get nearby businesses based on location
120
+ *
121
+ * @param params - Location parameters (latitude, longitude, radius)
122
+ * @param options - TanStack Query options
123
+ *
124
+ * @example
125
+ * ```tsx
126
+ * const { data, isLoading } = useNearbyBusinesses({
127
+ * lat: 51.5074,
128
+ * long: -0.1278,
129
+ * radius: 5000 // 5km radius
130
+ * });
131
+ * ```
132
+ */
133
+ export function useNearbyBusinesses(
134
+ params: NearbyBusinessParams,
135
+ options?: Omit<UseQueryOptions<BusinessResponse[]>, 'queryKey' | 'queryFn'>
136
+ ) {
137
+ return useQuery({
138
+ queryKey: businessKeys.nearby(params),
139
+ queryFn: async (): Promise<BusinessResponse[]> => {
140
+ const client = getApiClient();
141
+ const response = await client.get('/api/v1/businesses/nearby', {
142
+ params,
143
+ });
144
+ return response.data;
145
+ },
146
+ enabled: !!params.lat && !!params.long,
147
+ ...options,
148
+ });
149
+ }
150
+
151
+ /**
152
+ * Get a single business by ID
153
+ *
154
+ * @param id - Business ID
155
+ * @param options - TanStack Query options
156
+ *
157
+ * @example
158
+ * ```tsx
159
+ * const { data, isLoading } = useBusiness('business-123');
160
+ * ```
161
+ */
162
+ export function useBusiness(
163
+ id: string,
164
+ options?: Omit<UseQueryOptions<BusinessResponse>, 'queryKey' | 'queryFn'>
165
+ ) {
166
+ return useQuery({
167
+ queryKey: businessKeys.detail(id),
168
+ queryFn: async (): Promise<BusinessResponse> => {
169
+ const client = getApiClient();
170
+ const response = await client.get(`/api/v1/businesses/${id}`);
171
+ return response.data;
172
+ },
173
+ enabled: !!id,
174
+ ...options,
175
+ });
176
+ }
177
+
178
+ /**
179
+ * Get all offers for a specific business
180
+ *
181
+ * @param businessId - Business ID
182
+ * @param options - TanStack Query options
183
+ *
184
+ * @example
185
+ * ```tsx
186
+ * const { data, isLoading } = useBusinessOffers('business-123');
187
+ * ```
188
+ */
189
+ export function useBusinessOffers(
190
+ businessId: string,
191
+ options?: Omit<UseQueryOptions<OfferResponse[]>, 'queryKey' | 'queryFn'>
192
+ ) {
193
+ return useQuery({
194
+ queryKey: businessKeys.offers(businessId),
195
+ queryFn: async (): Promise<OfferResponse[]> => {
196
+ const client = getApiClient();
197
+ const response = await client.get(`/api/v1/businesses/${businessId}/offers`);
198
+ return response.data;
199
+ },
200
+ enabled: !!businessId,
201
+ ...options,
202
+ });
203
+ }
@@ -0,0 +1,78 @@
1
+ import { useQuery, useInfiniteQuery } from '@tanstack/react-query';
2
+ import { getApiClient } from '../client';
3
+ import type {
4
+ EventChatResponse,
5
+ ChatMemberResponse,
6
+ PaginatedMessagesResponse,
7
+ } from '../types';
8
+
9
+ // ============================================================================
10
+ // QUERY KEYS
11
+ // ============================================================================
12
+
13
+ export const eventChatKeys = {
14
+ all: ['event-chat'] as const,
15
+ chat: (eventId: string) => [...eventChatKeys.all, 'chat', eventId] as const,
16
+ members: (eventId: string) => [...eventChatKeys.all, 'members', eventId] as const,
17
+ messages: (eventId: string) => [...eventChatKeys.all, 'messages', eventId] as const,
18
+ };
19
+
20
+ // ============================================================================
21
+ // HOOKS
22
+ // ============================================================================
23
+
24
+ /**
25
+ * Get or create chat for an event
26
+ */
27
+ export function useEventChat(eventId: string | undefined) {
28
+ return useQuery({
29
+ queryKey: eventChatKeys.chat(eventId || ''),
30
+ queryFn: async () => {
31
+ if (!eventId) throw new Error('Event ID is required');
32
+ const client = getApiClient();
33
+ const response = await client.get<EventChatResponse>(`/events/${eventId}/chat`);
34
+ return response.data;
35
+ },
36
+ enabled: !!eventId,
37
+ });
38
+ }
39
+
40
+ /**
41
+ * Get chat members
42
+ */
43
+ export function useEventChatMembers(eventId: string | undefined) {
44
+ return useQuery({
45
+ queryKey: eventChatKeys.members(eventId || ''),
46
+ queryFn: async () => {
47
+ if (!eventId) throw new Error('Event ID is required');
48
+ const client = getApiClient();
49
+ const response = await client.get<ChatMemberResponse[]>(`/events/${eventId}/chat/members`);
50
+ return response.data;
51
+ },
52
+ enabled: !!eventId,
53
+ });
54
+ }
55
+
56
+ /**
57
+ * Get chat messages with infinite scroll pagination
58
+ */
59
+ export function useEventChatMessages(eventId: string | undefined, limit = 50) {
60
+ return useInfiniteQuery({
61
+ queryKey: eventChatKeys.messages(eventId || ''),
62
+ queryFn: async ({ pageParam }) => {
63
+ if (!eventId) throw new Error('Event ID is required');
64
+ const client = getApiClient();
65
+ const params = new URLSearchParams({ limit: String(limit) });
66
+ if (pageParam) {
67
+ params.append('cursor', pageParam);
68
+ }
69
+ const response = await client.get<PaginatedMessagesResponse>(
70
+ `/events/${eventId}/chat/messages?${params.toString()}`
71
+ );
72
+ return response.data;
73
+ },
74
+ initialPageParam: undefined as string | undefined,
75
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
76
+ enabled: !!eventId,
77
+ });
78
+ }
@@ -0,0 +1,272 @@
1
+ import { useQuery, UseQueryOptions } from '@tanstack/react-query';
2
+ import { getApiClient } from '../client';
3
+ import type { EventResponse } from '../types';
4
+
5
+ // ============================================================================
6
+ // QUERY KEY FACTORY
7
+ // ============================================================================
8
+
9
+ export const eventKeys = {
10
+ all: ['events'] as const,
11
+ lists: () => [...eventKeys.all, 'list'] as const,
12
+ list: (filters?: EventFilters) => [...eventKeys.lists(), filters] as const,
13
+ details: () => [...eventKeys.all, 'detail'] as const,
14
+ detail: (id: string) => [...eventKeys.details(), id] as const,
15
+ detailBySlug: (slug: string) => [...eventKeys.details(), 'slug', slug] as const,
16
+ upcoming: (limit?: number) => [...eventKeys.all, 'upcoming', limit] as const,
17
+ featured: (limit?: number) => [...eventKeys.all, 'featured', limit] as const,
18
+ ambient: (filters?: AmbientEventFilters) => [...eventKeys.all, 'ambient', filters] as const,
19
+ bookings: (eventId: string) => [...eventKeys.detail(eventId), 'bookings'] as const,
20
+ };
21
+
22
+ // ============================================================================
23
+ // TYPES
24
+ // ============================================================================
25
+
26
+ export interface EventFilters {
27
+ page?: number;
28
+ limit?: number;
29
+ hubId?: string;
30
+ cityId?: string;
31
+ eventType?: string;
32
+ status?: 'DRAFT' | 'PUBLISHED' | 'CANCELLED';
33
+ startAfter?: string;
34
+ startBefore?: string;
35
+ isFeatured?: boolean;
36
+ isAmbient?: boolean;
37
+ }
38
+
39
+ export interface AmbientEventFilters {
40
+ limit?: number;
41
+ cityId?: string;
42
+ }
43
+
44
+ export interface PaginatedEventsResponse {
45
+ events: EventResponse[];
46
+ total: number;
47
+ page: number;
48
+ limit: number;
49
+ totalPages: number;
50
+ }
51
+
52
+ // ============================================================================
53
+ // QUERY HOOKS
54
+ // ============================================================================
55
+
56
+ /**
57
+ * Get paginated list of events with optional filters
58
+ *
59
+ * @param filters - Query parameters for filtering and pagination
60
+ * @param options - TanStack Query options
61
+ *
62
+ * @example
63
+ * ```tsx
64
+ * const { data, isLoading } = useEvents({
65
+ * page: 1,
66
+ * limit: 20,
67
+ * hubId: 'hub-123',
68
+ * isFeatured: true
69
+ * });
70
+ * ```
71
+ */
72
+ export function useEvents(
73
+ filters?: EventFilters,
74
+ options?: Omit<UseQueryOptions<PaginatedEventsResponse>, 'queryKey' | 'queryFn'>
75
+ ) {
76
+ return useQuery({
77
+ queryKey: eventKeys.list(filters),
78
+ queryFn: async (): Promise<PaginatedEventsResponse> => {
79
+ const client = getApiClient();
80
+ const response = await client.get('/api/v1/events', {
81
+ params: filters,
82
+ });
83
+ return response.data;
84
+ },
85
+ ...options,
86
+ });
87
+ }
88
+
89
+ /**
90
+ * Get a single event by ID
91
+ *
92
+ * @param id - Event ID
93
+ * @param options - TanStack Query options
94
+ *
95
+ * @example
96
+ * ```tsx
97
+ * const { data, isLoading } = useEvent('event-123');
98
+ * ```
99
+ */
100
+ export function useEvent(
101
+ id: string,
102
+ options?: Omit<UseQueryOptions<EventResponse>, 'queryKey' | 'queryFn'>
103
+ ) {
104
+ return useQuery({
105
+ queryKey: eventKeys.detail(id),
106
+ queryFn: async (): Promise<EventResponse> => {
107
+ const client = getApiClient();
108
+ const response = await client.get(`/api/v1/events/${id}`);
109
+ return response.data;
110
+ },
111
+ enabled: !!id,
112
+ ...options,
113
+ });
114
+ }
115
+
116
+ /**
117
+ * Get a single event by slug
118
+ *
119
+ * @param slug - Event slug
120
+ * @param options - TanStack Query options
121
+ *
122
+ * @example
123
+ * ```tsx
124
+ * const { data, isLoading } = useEventBySlug('yoga-in-the-park');
125
+ * ```
126
+ */
127
+ export function useEventBySlug(
128
+ slug: string,
129
+ options?: Omit<UseQueryOptions<EventResponse>, 'queryKey' | 'queryFn'>
130
+ ) {
131
+ return useQuery({
132
+ queryKey: eventKeys.detailBySlug(slug),
133
+ queryFn: async (): Promise<EventResponse> => {
134
+ const client = getApiClient();
135
+ const response = await client.get(`/api/v1/events/slug/${slug}`);
136
+ return response.data;
137
+ },
138
+ enabled: !!slug,
139
+ ...options,
140
+ });
141
+ }
142
+
143
+ /**
144
+ * Get upcoming events
145
+ *
146
+ * @param limit - Maximum number of events to return (default: 10)
147
+ * @param options - TanStack Query options
148
+ *
149
+ * @example
150
+ * ```tsx
151
+ * const { data, isLoading } = useUpcomingEvents(20);
152
+ * ```
153
+ */
154
+ export function useUpcomingEvents(
155
+ limit?: number,
156
+ options?: Omit<UseQueryOptions<EventResponse[]>, 'queryKey' | 'queryFn'>
157
+ ) {
158
+ return useQuery({
159
+ queryKey: eventKeys.upcoming(limit),
160
+ queryFn: async (): Promise<EventResponse[]> => {
161
+ const client = getApiClient();
162
+ const response = await client.get('/api/v1/events/upcoming', {
163
+ params: { limit },
164
+ });
165
+ return response.data;
166
+ },
167
+ ...options,
168
+ });
169
+ }
170
+
171
+ /**
172
+ * Get featured events
173
+ *
174
+ * Note: This uses the main events endpoint with isFeatured filter
175
+ *
176
+ * @param limit - Maximum number of events to return (default: 10)
177
+ * @param options - TanStack Query options
178
+ *
179
+ * @example
180
+ * ```tsx
181
+ * const { data, isLoading } = useFeaturedEvents(5);
182
+ * ```
183
+ */
184
+ export function useFeaturedEvents(
185
+ limit: number = 10,
186
+ options?: Omit<UseQueryOptions<EventResponse[]>, 'queryKey' | 'queryFn'>
187
+ ) {
188
+ return useQuery({
189
+ queryKey: eventKeys.featured(limit),
190
+ queryFn: async (): Promise<EventResponse[]> => {
191
+ const client = getApiClient();
192
+ const response = await client.get('/api/v1/events', {
193
+ params: {
194
+ isFeatured: true,
195
+ limit,
196
+ page: 1,
197
+ },
198
+ });
199
+ return response.data.events || response.data;
200
+ },
201
+ ...options,
202
+ });
203
+ }
204
+
205
+ /**
206
+ * Get ambient events (auto-generated social activities)
207
+ *
208
+ * @param filters - Optional filters (limit, cityId)
209
+ * @param options - TanStack Query options
210
+ *
211
+ * @example
212
+ * ```tsx
213
+ * const { data, isLoading } = useAmbientEvents({ limit: 10 });
214
+ * ```
215
+ */
216
+ export function useAmbientEvents(
217
+ filters?: AmbientEventFilters,
218
+ options?: Omit<UseQueryOptions<EventResponse[]>, 'queryKey' | 'queryFn'>
219
+ ) {
220
+ return useQuery({
221
+ queryKey: eventKeys.ambient(filters),
222
+ queryFn: async (): Promise<EventResponse[]> => {
223
+ const client = getApiClient();
224
+ const response = await client.get('/api/v1/events', {
225
+ params: {
226
+ isAmbient: true,
227
+ limit: filters?.limit || 20,
228
+ cityId: filters?.cityId,
229
+ startFrom: new Date().toISOString(),
230
+ sortBy: 'startDate',
231
+ sortOrder: 'asc',
232
+ },
233
+ });
234
+ // API returns { data: { events: [...], meta: {...} }, meta: {...} }
235
+ return response.data.data?.events || response.data.events || response.data;
236
+ },
237
+ ...options,
238
+ });
239
+ }
240
+
241
+ /**
242
+ * Get bookings for a specific event
243
+ *
244
+ * Note: This endpoint may not be available in the current API.
245
+ * Consider using admin endpoints or user bookings endpoints instead.
246
+ * This hook is provided for future compatibility.
247
+ *
248
+ * @param eventId - Event ID
249
+ * @param options - TanStack Query options
250
+ *
251
+ * @example
252
+ * ```tsx
253
+ * const { data, isLoading } = useEventBookings('event-123');
254
+ * ```
255
+ */
256
+ export function useEventBookings(
257
+ eventId: string,
258
+ options?: Omit<UseQueryOptions<any[]>, 'queryKey' | 'queryFn'>
259
+ ) {
260
+ return useQuery({
261
+ queryKey: eventKeys.bookings(eventId),
262
+ queryFn: async (): Promise<any[]> => {
263
+ const client = getApiClient();
264
+ // Note: This endpoint may not exist in the current API
265
+ // Adjust the path based on your actual API implementation
266
+ const response = await client.get(`/api/v1/events/${eventId}/bookings`);
267
+ return response.data;
268
+ },
269
+ enabled: !!eventId,
270
+ ...options,
271
+ });
272
+ }