@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,480 @@
1
+ /**
2
+ * Admin Query Hooks
3
+ *
4
+ * TanStack Query hooks for admin-related read operations.
5
+ * These hooks handle fetching data for the admin dashboard including
6
+ * users, hubs, events, businesses, content, and analytics.
7
+ *
8
+ * @module api/queries/admin
9
+ */
10
+
11
+ import { useQuery, UseQueryOptions, UseQueryResult } from '@tanstack/react-query';
12
+ import { getApiClient } from '../client';
13
+ import type {
14
+ UserResponse,
15
+ HubResponse,
16
+ EventResponse,
17
+ BusinessResponse,
18
+ LibraryContentResponse,
19
+ } from '../types';
20
+
21
+ // ============================================================================
22
+ // ADMIN TYPES
23
+ // ============================================================================
24
+
25
+ export interface AdminDashboardStats {
26
+ totalUsers: number;
27
+ activeUsers: number;
28
+ newUsersToday: number;
29
+ newUsersThisWeek: number;
30
+ totalHubs: number;
31
+ totalEvents: number;
32
+ upcomingEvents: number;
33
+ totalBusinesses: number;
34
+ verifiedBusinesses: number;
35
+ premiumUsers: number;
36
+ revenue: {
37
+ today: number;
38
+ thisWeek: number;
39
+ thisMonth: number;
40
+ };
41
+ }
42
+
43
+ export interface AdminAnalyticsData {
44
+ period: string;
45
+ userGrowth: Array<{ date: string; count: number }>;
46
+ eventAttendance: Array<{ date: string; count: number }>;
47
+ hubActivity: Array<{ date: string; count: number }>;
48
+ revenue: Array<{ date: string; amount: number }>;
49
+ topHubs: Array<{ id: string; name: string; memberCount: number }>;
50
+ topEvents: Array<{ id: string; title: string; attendeeCount: number }>;
51
+ }
52
+
53
+ export interface PaginatedResponse<T> {
54
+ data: T[];
55
+ meta: {
56
+ total: number;
57
+ page: number;
58
+ limit: number;
59
+ totalPages: number;
60
+ };
61
+ }
62
+
63
+ export interface AdminUserFilters {
64
+ page?: number;
65
+ limit?: number;
66
+ search?: string;
67
+ status?: 'active' | 'suspended' | 'deleted';
68
+ isPremium?: boolean;
69
+ sortBy?: string;
70
+ sortOrder?: 'asc' | 'desc';
71
+ }
72
+
73
+ export interface AdminHubFilters {
74
+ page?: number;
75
+ limit?: number;
76
+ search?: string;
77
+ status?: 'active' | 'inactive';
78
+ sortBy?: string;
79
+ sortOrder?: 'asc' | 'desc';
80
+ }
81
+
82
+ export interface AdminEventFilters {
83
+ page?: number;
84
+ limit?: number;
85
+ search?: string;
86
+ status?: 'draft' | 'published' | 'cancelled';
87
+ hubId?: string;
88
+ upcoming?: boolean;
89
+ sortBy?: string;
90
+ sortOrder?: 'asc' | 'desc';
91
+ }
92
+
93
+ export interface AdminBusinessFilters {
94
+ page?: number;
95
+ limit?: number;
96
+ search?: string;
97
+ isVerified?: boolean;
98
+ type?: string;
99
+ sortBy?: string;
100
+ sortOrder?: 'asc' | 'desc';
101
+ }
102
+
103
+ export interface AdminContentFilters {
104
+ page?: number;
105
+ limit?: number;
106
+ search?: string;
107
+ type?: string;
108
+ category?: string;
109
+ isFeatured?: boolean;
110
+ sortBy?: string;
111
+ sortOrder?: 'asc' | 'desc';
112
+ }
113
+
114
+ // ============================================================================
115
+ // QUERY KEYS
116
+ // ============================================================================
117
+
118
+ export const adminKeys = {
119
+ all: ['admin'] as const,
120
+ dashboard: () => [...adminKeys.all, 'dashboard'] as const,
121
+ analytics: (period?: string) => [...adminKeys.all, 'analytics', period] as const,
122
+ users: {
123
+ all: () => [...adminKeys.all, 'users'] as const,
124
+ list: (filters?: AdminUserFilters) => [...adminKeys.users.all(), 'list', filters] as const,
125
+ detail: (id: string) => [...adminKeys.users.all(), 'detail', id] as const,
126
+ },
127
+ hubs: {
128
+ all: () => [...adminKeys.all, 'hubs'] as const,
129
+ list: (filters?: AdminHubFilters) => [...adminKeys.hubs.all(), 'list', filters] as const,
130
+ detail: (id: string) => [...adminKeys.hubs.all(), 'detail', id] as const,
131
+ },
132
+ events: {
133
+ all: () => [...adminKeys.all, 'events'] as const,
134
+ list: (filters?: AdminEventFilters) => [...adminKeys.events.all(), 'list', filters] as const,
135
+ detail: (id: string) => [...adminKeys.events.all(), 'detail', id] as const,
136
+ },
137
+ businesses: {
138
+ all: () => [...adminKeys.all, 'businesses'] as const,
139
+ list: (filters?: AdminBusinessFilters) =>
140
+ [...adminKeys.businesses.all(), 'list', filters] as const,
141
+ detail: (id: string) => [...adminKeys.businesses.all(), 'detail', id] as const,
142
+ },
143
+ content: {
144
+ all: () => [...adminKeys.all, 'content'] as const,
145
+ list: (filters?: AdminContentFilters) =>
146
+ [...adminKeys.content.all(), 'list', filters] as const,
147
+ detail: (id: string) => [...adminKeys.content.all(), 'detail', id] as const,
148
+ },
149
+ };
150
+
151
+ // ============================================================================
152
+ // DASHBOARD & ANALYTICS
153
+ // ============================================================================
154
+
155
+ /**
156
+ * Get admin dashboard statistics
157
+ *
158
+ * @description
159
+ * Retrieves key metrics for the admin dashboard including
160
+ * user counts, hub stats, event stats, and revenue data.
161
+ *
162
+ * @endpoint GET /api/v1/admin/dashboard
163
+ *
164
+ * @example
165
+ * ```tsx
166
+ * import { useAdminDashboard } from '@growsober/sdk';
167
+ *
168
+ * function AdminDashboard() {
169
+ * const { data: stats, isLoading } = useAdminDashboard();
170
+ *
171
+ * if (isLoading) return <Spinner />;
172
+ *
173
+ * return (
174
+ * <div>
175
+ * <StatCard label="Total Users" value={stats.totalUsers} />
176
+ * <StatCard label="Active Users" value={stats.activeUsers} />
177
+ * <StatCard label="Premium Users" value={stats.premiumUsers} />
178
+ * <StatCard label="Revenue This Month" value={stats.revenue.thisMonth} />
179
+ * </div>
180
+ * );
181
+ * }
182
+ * ```
183
+ */
184
+ export function useAdminDashboard(
185
+ options?: Omit<UseQueryOptions<AdminDashboardStats>, 'queryKey' | 'queryFn'>
186
+ ): UseQueryResult<AdminDashboardStats> {
187
+ return useQuery({
188
+ queryKey: adminKeys.dashboard(),
189
+ queryFn: async (): Promise<AdminDashboardStats> => {
190
+ const client = getApiClient();
191
+ const response = await client.get<AdminDashboardStats>('/api/v1/admin/dashboard');
192
+ return response.data;
193
+ },
194
+ ...options,
195
+ });
196
+ }
197
+
198
+ /**
199
+ * Get admin analytics data
200
+ *
201
+ * @description
202
+ * Retrieves detailed analytics data for charts and reports.
203
+ *
204
+ * @endpoint GET /api/v1/admin/analytics
205
+ *
206
+ * @example
207
+ * ```tsx
208
+ * import { useAdminAnalytics } from '@growsober/sdk';
209
+ *
210
+ * function AnalyticsPage() {
211
+ * const { data: analytics } = useAdminAnalytics('30d');
212
+ *
213
+ * return (
214
+ * <div>
215
+ * <LineChart data={analytics?.userGrowth} />
216
+ * <BarChart data={analytics?.eventAttendance} />
217
+ * </div>
218
+ * );
219
+ * }
220
+ * ```
221
+ */
222
+ export function useAdminAnalytics(
223
+ period?: string,
224
+ options?: Omit<UseQueryOptions<AdminAnalyticsData>, 'queryKey' | 'queryFn'>
225
+ ): UseQueryResult<AdminAnalyticsData> {
226
+ return useQuery({
227
+ queryKey: adminKeys.analytics(period),
228
+ queryFn: async (): Promise<AdminAnalyticsData> => {
229
+ const client = getApiClient();
230
+ const response = await client.get<AdminAnalyticsData>('/api/v1/admin/analytics', {
231
+ params: { period },
232
+ });
233
+ return response.data;
234
+ },
235
+ ...options,
236
+ });
237
+ }
238
+
239
+ // ============================================================================
240
+ // USER MANAGEMENT
241
+ // ============================================================================
242
+
243
+ /**
244
+ * List users for admin
245
+ *
246
+ * @endpoint GET /api/v1/admin/users
247
+ */
248
+ export function useAdminUsers(
249
+ filters?: AdminUserFilters,
250
+ options?: Omit<UseQueryOptions<PaginatedResponse<UserResponse>>, 'queryKey' | 'queryFn'>
251
+ ): UseQueryResult<PaginatedResponse<UserResponse>> {
252
+ return useQuery({
253
+ queryKey: adminKeys.users.list(filters),
254
+ queryFn: async (): Promise<PaginatedResponse<UserResponse>> => {
255
+ const client = getApiClient();
256
+ const response = await client.get<PaginatedResponse<UserResponse>>(
257
+ '/api/v1/admin/users',
258
+ { params: filters }
259
+ );
260
+ return response.data;
261
+ },
262
+ ...options,
263
+ });
264
+ }
265
+
266
+ /**
267
+ * Get user detail for admin
268
+ *
269
+ * @endpoint GET /api/v1/admin/users/{id}
270
+ */
271
+ export function useAdminUser(
272
+ id: string,
273
+ options?: Omit<UseQueryOptions<UserResponse>, 'queryKey' | 'queryFn'>
274
+ ): UseQueryResult<UserResponse> {
275
+ return useQuery({
276
+ queryKey: adminKeys.users.detail(id),
277
+ queryFn: async (): Promise<UserResponse> => {
278
+ const client = getApiClient();
279
+ const response = await client.get<UserResponse>(`/api/v1/admin/users/${id}`);
280
+ return response.data;
281
+ },
282
+ enabled: !!id,
283
+ ...options,
284
+ });
285
+ }
286
+
287
+ // ============================================================================
288
+ // HUB MANAGEMENT
289
+ // ============================================================================
290
+
291
+ /**
292
+ * List hubs for admin
293
+ *
294
+ * @endpoint GET /api/v1/admin/hubs
295
+ */
296
+ export function useAdminHubs(
297
+ filters?: AdminHubFilters,
298
+ options?: Omit<UseQueryOptions<PaginatedResponse<HubResponse>>, 'queryKey' | 'queryFn'>
299
+ ): UseQueryResult<PaginatedResponse<HubResponse>> {
300
+ return useQuery({
301
+ queryKey: adminKeys.hubs.list(filters),
302
+ queryFn: async (): Promise<PaginatedResponse<HubResponse>> => {
303
+ const client = getApiClient();
304
+ const response = await client.get<PaginatedResponse<HubResponse>>(
305
+ '/api/v1/admin/hubs',
306
+ { params: filters }
307
+ );
308
+ return response.data;
309
+ },
310
+ ...options,
311
+ });
312
+ }
313
+
314
+ /**
315
+ * Get hub detail for admin
316
+ *
317
+ * @endpoint GET /api/v1/admin/hubs/{id}
318
+ */
319
+ export function useAdminHub(
320
+ id: string,
321
+ options?: Omit<UseQueryOptions<HubResponse>, 'queryKey' | 'queryFn'>
322
+ ): UseQueryResult<HubResponse> {
323
+ return useQuery({
324
+ queryKey: adminKeys.hubs.detail(id),
325
+ queryFn: async (): Promise<HubResponse> => {
326
+ const client = getApiClient();
327
+ const response = await client.get<HubResponse>(`/api/v1/admin/hubs/${id}`);
328
+ return response.data;
329
+ },
330
+ enabled: !!id,
331
+ ...options,
332
+ });
333
+ }
334
+
335
+ // ============================================================================
336
+ // EVENT MANAGEMENT
337
+ // ============================================================================
338
+
339
+ /**
340
+ * List events for admin
341
+ *
342
+ * @endpoint GET /api/v1/admin/events
343
+ */
344
+ export function useAdminEvents(
345
+ filters?: AdminEventFilters,
346
+ options?: Omit<UseQueryOptions<PaginatedResponse<EventResponse>>, 'queryKey' | 'queryFn'>
347
+ ): UseQueryResult<PaginatedResponse<EventResponse>> {
348
+ return useQuery({
349
+ queryKey: adminKeys.events.list(filters),
350
+ queryFn: async (): Promise<PaginatedResponse<EventResponse>> => {
351
+ const client = getApiClient();
352
+ const response = await client.get<PaginatedResponse<EventResponse>>(
353
+ '/api/v1/admin/events',
354
+ { params: filters }
355
+ );
356
+ return response.data;
357
+ },
358
+ ...options,
359
+ });
360
+ }
361
+
362
+ /**
363
+ * Get event detail for admin
364
+ *
365
+ * @endpoint GET /api/v1/admin/events/{id}
366
+ */
367
+ export function useAdminEvent(
368
+ id: string,
369
+ options?: Omit<UseQueryOptions<EventResponse>, 'queryKey' | 'queryFn'>
370
+ ): UseQueryResult<EventResponse> {
371
+ return useQuery({
372
+ queryKey: adminKeys.events.detail(id),
373
+ queryFn: async (): Promise<EventResponse> => {
374
+ const client = getApiClient();
375
+ const response = await client.get<EventResponse>(`/api/v1/admin/events/${id}`);
376
+ return response.data;
377
+ },
378
+ enabled: !!id,
379
+ ...options,
380
+ });
381
+ }
382
+
383
+ // ============================================================================
384
+ // BUSINESS MANAGEMENT
385
+ // ============================================================================
386
+
387
+ /**
388
+ * List businesses for admin
389
+ *
390
+ * @endpoint GET /api/v1/admin/businesses
391
+ */
392
+ export function useAdminBusinesses(
393
+ filters?: AdminBusinessFilters,
394
+ options?: Omit<UseQueryOptions<PaginatedResponse<BusinessResponse>>, 'queryKey' | 'queryFn'>
395
+ ): UseQueryResult<PaginatedResponse<BusinessResponse>> {
396
+ return useQuery({
397
+ queryKey: adminKeys.businesses.list(filters),
398
+ queryFn: async (): Promise<PaginatedResponse<BusinessResponse>> => {
399
+ const client = getApiClient();
400
+ const response = await client.get<PaginatedResponse<BusinessResponse>>(
401
+ '/api/v1/admin/businesses',
402
+ { params: filters }
403
+ );
404
+ return response.data;
405
+ },
406
+ ...options,
407
+ });
408
+ }
409
+
410
+ /**
411
+ * Get business detail for admin
412
+ *
413
+ * @endpoint GET /api/v1/admin/businesses/{id}
414
+ */
415
+ export function useAdminBusiness(
416
+ id: string,
417
+ options?: Omit<UseQueryOptions<BusinessResponse>, 'queryKey' | 'queryFn'>
418
+ ): UseQueryResult<BusinessResponse> {
419
+ return useQuery({
420
+ queryKey: adminKeys.businesses.detail(id),
421
+ queryFn: async (): Promise<BusinessResponse> => {
422
+ const client = getApiClient();
423
+ const response = await client.get<BusinessResponse>(`/api/v1/admin/businesses/${id}`);
424
+ return response.data;
425
+ },
426
+ enabled: !!id,
427
+ ...options,
428
+ });
429
+ }
430
+
431
+ // ============================================================================
432
+ // CONTENT MANAGEMENT
433
+ // ============================================================================
434
+
435
+ /**
436
+ * List content for admin
437
+ *
438
+ * @endpoint GET /api/v1/admin/content
439
+ */
440
+ export function useAdminContent(
441
+ filters?: AdminContentFilters,
442
+ options?: Omit<
443
+ UseQueryOptions<PaginatedResponse<LibraryContentResponse>>,
444
+ 'queryKey' | 'queryFn'
445
+ >
446
+ ): UseQueryResult<PaginatedResponse<LibraryContentResponse>> {
447
+ return useQuery({
448
+ queryKey: adminKeys.content.list(filters),
449
+ queryFn: async (): Promise<PaginatedResponse<LibraryContentResponse>> => {
450
+ const client = getApiClient();
451
+ const response = await client.get<PaginatedResponse<LibraryContentResponse>>(
452
+ '/api/v1/admin/content',
453
+ { params: filters }
454
+ );
455
+ return response.data;
456
+ },
457
+ ...options,
458
+ });
459
+ }
460
+
461
+ /**
462
+ * Get content detail for admin
463
+ *
464
+ * @endpoint GET /api/v1/admin/content/{id}
465
+ */
466
+ export function useAdminContentItem(
467
+ id: string,
468
+ options?: Omit<UseQueryOptions<LibraryContentResponse>, 'queryKey' | 'queryFn'>
469
+ ): UseQueryResult<LibraryContentResponse> {
470
+ return useQuery({
471
+ queryKey: adminKeys.content.detail(id),
472
+ queryFn: async (): Promise<LibraryContentResponse> => {
473
+ const client = getApiClient();
474
+ const response = await client.get<LibraryContentResponse>(`/api/v1/admin/content/${id}`);
475
+ return response.data;
476
+ },
477
+ enabled: !!id,
478
+ ...options,
479
+ });
480
+ }
@@ -0,0 +1,139 @@
1
+ import { useQuery, UseQueryOptions } from '@tanstack/react-query';
2
+ import { getApiClient } from '../client';
3
+ import type { AmbassadorResponse, AmbassadorLeaderboardResponse, AmbassadorStatus } from '../types';
4
+
5
+ // ============================================================================
6
+ // QUERY KEYS
7
+ // ============================================================================
8
+
9
+ export const ambassadorKeys = {
10
+ all: ['ambassadors'] as const,
11
+ lists: () => [...ambassadorKeys.all, 'list'] as const,
12
+ list: (filters?: AmbassadorListFilters) => [...ambassadorKeys.lists(), filters] as const,
13
+ details: () => [...ambassadorKeys.all, 'detail'] as const,
14
+ detail: (id: string) => [...ambassadorKeys.details(), id] as const,
15
+ me: () => [...ambassadorKeys.all, 'me'] as const,
16
+ leaderboard: (filters?: LeaderboardFilters) => [...ambassadorKeys.all, 'leaderboard', filters] as const,
17
+ pending: () => [...ambassadorKeys.all, 'pending'] as const,
18
+ };
19
+
20
+ // ============================================================================
21
+ // TYPES
22
+ // ============================================================================
23
+
24
+ export interface AmbassadorListFilters {
25
+ page?: number;
26
+ limit?: number;
27
+ hubId?: string;
28
+ status?: AmbassadorStatus;
29
+ isVerified?: boolean;
30
+ isFoundingAmbassador?: boolean;
31
+ }
32
+
33
+ export interface LeaderboardFilters {
34
+ limit?: number;
35
+ hubId?: string;
36
+ }
37
+
38
+ export interface PaginatedAmbassadorsResponse {
39
+ ambassadors: AmbassadorResponse[];
40
+ meta: {
41
+ total: number;
42
+ page: number;
43
+ limit: number;
44
+ totalPages: number;
45
+ };
46
+ }
47
+
48
+ // ============================================================================
49
+ // QUERY HOOKS
50
+ // ============================================================================
51
+
52
+ /**
53
+ * Get all ambassadors with pagination and filters
54
+ */
55
+ export function useAmbassadors(
56
+ filters?: AmbassadorListFilters,
57
+ options?: Omit<UseQueryOptions<PaginatedAmbassadorsResponse>, 'queryKey' | 'queryFn'>
58
+ ) {
59
+ return useQuery({
60
+ queryKey: ambassadorKeys.list(filters),
61
+ queryFn: async (): Promise<PaginatedAmbassadorsResponse> => {
62
+ const client = getApiClient();
63
+ const response = await client.get('/api/v1/ambassadors', { params: filters });
64
+ return response.data;
65
+ },
66
+ ...options,
67
+ });
68
+ }
69
+
70
+ /**
71
+ * Get ambassador by ID
72
+ */
73
+ export function useAmbassador(
74
+ id: string,
75
+ options?: Omit<UseQueryOptions<AmbassadorResponse>, 'queryKey' | 'queryFn'>
76
+ ) {
77
+ return useQuery({
78
+ queryKey: ambassadorKeys.detail(id),
79
+ queryFn: async (): Promise<AmbassadorResponse> => {
80
+ const client = getApiClient();
81
+ const response = await client.get(`/api/v1/ambassadors/${id}`);
82
+ return response.data;
83
+ },
84
+ enabled: !!id && (options?.enabled !== false),
85
+ ...options,
86
+ });
87
+ }
88
+
89
+ /**
90
+ * Get current user's ambassador status
91
+ */
92
+ export function useMyAmbassador(
93
+ options?: Omit<UseQueryOptions<AmbassadorResponse | null>, 'queryKey' | 'queryFn'>
94
+ ) {
95
+ return useQuery({
96
+ queryKey: ambassadorKeys.me(),
97
+ queryFn: async (): Promise<AmbassadorResponse | null> => {
98
+ const client = getApiClient();
99
+ const response = await client.get('/api/v1/ambassadors/me');
100
+ return response.data;
101
+ },
102
+ ...options,
103
+ });
104
+ }
105
+
106
+ /**
107
+ * Get ambassador leaderboard
108
+ */
109
+ export function useAmbassadorLeaderboard(
110
+ filters?: LeaderboardFilters,
111
+ options?: Omit<UseQueryOptions<AmbassadorLeaderboardResponse[]>, 'queryKey' | 'queryFn'>
112
+ ) {
113
+ return useQuery({
114
+ queryKey: ambassadorKeys.leaderboard(filters),
115
+ queryFn: async (): Promise<AmbassadorLeaderboardResponse[]> => {
116
+ const client = getApiClient();
117
+ const response = await client.get('/api/v1/ambassadors/leaderboard', { params: filters });
118
+ return response.data;
119
+ },
120
+ ...options,
121
+ });
122
+ }
123
+
124
+ /**
125
+ * Get pending ambassador applications (admin)
126
+ */
127
+ export function usePendingAmbassadors(
128
+ options?: Omit<UseQueryOptions<AmbassadorResponse[]>, 'queryKey' | 'queryFn'>
129
+ ) {
130
+ return useQuery({
131
+ queryKey: ambassadorKeys.pending(),
132
+ queryFn: async (): Promise<AmbassadorResponse[]> => {
133
+ const client = getApiClient();
134
+ const response = await client.get('/api/v1/ambassadors/pending');
135
+ return response.data;
136
+ },
137
+ ...options,
138
+ });
139
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Auth Query Hooks
3
+ *
4
+ * TanStack Query hooks for authentication-related read operations.
5
+ * These hooks handle fetching current user data and managing cache invalidation.
6
+ *
7
+ * @module api/queries/auth
8
+ */
9
+
10
+ // ============================================================================
11
+ // QUERY KEYS
12
+ // ============================================================================
13
+
14
+ /**
15
+ * Query key factory for auth-related queries
16
+ * @see https://tkdodo.eu/blog/effective-react-query-keys
17
+ */
18
+ export const authKeys = {
19
+ all: ['auth'] as const,
20
+ me: () => [...authKeys.all, 'me'] as const,
21
+ };
22
+
23
+ // Note: useCurrentUser is exported from queries/users.ts
24
+ // It uses the /api/v1/users/me endpoint which is the correct endpoint for fetching user data