@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.
- package/README.md +276 -0
- package/dist/__tests__/e2e.test.d.ts +7 -0
- package/dist/__tests__/e2e.test.js +472 -0
- package/dist/api/client.d.ts +11 -0
- package/dist/api/client.js +61 -0
- package/dist/api/mutations/admin.d.ts +167 -0
- package/dist/api/mutations/admin.js +326 -0
- package/dist/api/mutations/ambassadors.d.ts +52 -0
- package/dist/api/mutations/ambassadors.js +148 -0
- package/dist/api/mutations/auth.d.ts +267 -0
- package/dist/api/mutations/auth.js +332 -0
- package/dist/api/mutations/bookings.d.ts +59 -0
- package/dist/api/mutations/bookings.js +143 -0
- package/dist/api/mutations/event-chat.d.ts +35 -0
- package/dist/api/mutations/event-chat.js +147 -0
- package/dist/api/mutations/events.d.ts +87 -0
- package/dist/api/mutations/events.js +205 -0
- package/dist/api/mutations/grow90.d.ts +36 -0
- package/dist/api/mutations/grow90.js +132 -0
- package/dist/api/mutations/hubs.d.ts +111 -0
- package/dist/api/mutations/hubs.js +240 -0
- package/dist/api/mutations/index.d.ts +22 -0
- package/dist/api/mutations/index.js +39 -0
- package/dist/api/mutations/jack.d.ts +61 -0
- package/dist/api/mutations/jack.js +104 -0
- package/dist/api/mutations/library.d.ts +67 -0
- package/dist/api/mutations/library.js +168 -0
- package/dist/api/mutations/map.d.ts +153 -0
- package/dist/api/mutations/map.js +181 -0
- package/dist/api/mutations/matching.d.ts +130 -0
- package/dist/api/mutations/matching.js +204 -0
- package/dist/api/mutations/notifications.d.ts +63 -0
- package/dist/api/mutations/notifications.js +106 -0
- package/dist/api/mutations/offers.d.ts +26 -0
- package/dist/api/mutations/offers.js +47 -0
- package/dist/api/mutations/subscriptions.d.ts +127 -0
- package/dist/api/mutations/subscriptions.js +140 -0
- package/dist/api/mutations/support.d.ts +165 -0
- package/dist/api/mutations/support.js +307 -0
- package/dist/api/mutations/users.d.ts +211 -0
- package/dist/api/mutations/users.js +261 -0
- package/dist/api/queries/admin.d.ts +257 -0
- package/dist/api/queries/admin.js +320 -0
- package/dist/api/queries/ambassadors.d.ts +53 -0
- package/dist/api/queries/ambassadors.js +98 -0
- package/dist/api/queries/auth.d.ts +16 -0
- package/dist/api/queries/auth.js +25 -0
- package/dist/api/queries/bookings.d.ts +91 -0
- package/dist/api/queries/bookings.js +102 -0
- package/dist/api/queries/businesses.d.ts +212 -0
- package/dist/api/queries/businesses.js +154 -0
- package/dist/api/queries/event-chat.d.ts +19 -0
- package/dist/api/queries/event-chat.js +75 -0
- package/dist/api/queries/events.d.ts +322 -0
- package/dist/api/queries/events.js +221 -0
- package/dist/api/queries/grow90.d.ts +26 -0
- package/dist/api/queries/grow90.js +85 -0
- package/dist/api/queries/hubs.d.ts +165 -0
- package/dist/api/queries/hubs.js +143 -0
- package/dist/api/queries/index.d.ts +23 -0
- package/dist/api/queries/index.js +40 -0
- package/dist/api/queries/jack.d.ts +63 -0
- package/dist/api/queries/jack.js +92 -0
- package/dist/api/queries/library.d.ts +132 -0
- package/dist/api/queries/library.js +120 -0
- package/dist/api/queries/map.d.ts +216 -0
- package/dist/api/queries/map.js +278 -0
- package/dist/api/queries/matching.d.ts +136 -0
- package/dist/api/queries/matching.js +161 -0
- package/dist/api/queries/notifications.d.ts +78 -0
- package/dist/api/queries/notifications.js +88 -0
- package/dist/api/queries/offers.d.ts +91 -0
- package/dist/api/queries/offers.js +103 -0
- package/dist/api/queries/subscriptions.d.ts +56 -0
- package/dist/api/queries/subscriptions.js +73 -0
- package/dist/api/queries/support.d.ts +106 -0
- package/dist/api/queries/support.js +202 -0
- package/dist/api/queries/users.d.ts +293 -0
- package/dist/api/queries/users.js +370 -0
- package/dist/api/types.d.ts +464 -0
- package/dist/api/types.js +9 -0
- package/dist/hooks/useAuth.d.ts +5 -0
- package/dist/hooks/useAuth.js +39 -0
- package/dist/hooks/useUser.d.ts +43 -0
- package/dist/hooks/useUser.js +44 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +67 -0
- package/package.json +62 -0
- package/src/__tests__/e2e.test.ts +502 -0
- package/src/api/client.ts +71 -0
- package/src/api/mutations/admin.ts +531 -0
- package/src/api/mutations/ambassadors.ts +185 -0
- package/src/api/mutations/auth.ts +350 -0
- package/src/api/mutations/bookings.ts +190 -0
- package/src/api/mutations/event-chat.ts +177 -0
- package/src/api/mutations/events.ts +273 -0
- package/src/api/mutations/grow90.ts +169 -0
- package/src/api/mutations/hubs.ts +385 -0
- package/src/api/mutations/index.ts +23 -0
- package/src/api/mutations/jack.ts +130 -0
- package/src/api/mutations/library.ts +212 -0
- package/src/api/mutations/map.ts +230 -0
- package/src/api/mutations/matching.ts +271 -0
- package/src/api/mutations/notifications.ts +114 -0
- package/src/api/mutations/offers.ts +73 -0
- package/src/api/mutations/subscriptions.ts +162 -0
- package/src/api/mutations/support.ts +390 -0
- package/src/api/mutations/users.ts +271 -0
- package/src/api/queries/admin.ts +480 -0
- package/src/api/queries/ambassadors.ts +139 -0
- package/src/api/queries/auth.ts +24 -0
- package/src/api/queries/bookings.ts +135 -0
- package/src/api/queries/businesses.ts +203 -0
- package/src/api/queries/event-chat.ts +78 -0
- package/src/api/queries/events.ts +272 -0
- package/src/api/queries/grow90.ts +98 -0
- package/src/api/queries/hubs.ts +211 -0
- package/src/api/queries/index.ts +24 -0
- package/src/api/queries/jack.ts +127 -0
- package/src/api/queries/library.ts +166 -0
- package/src/api/queries/map.ts +331 -0
- package/src/api/queries/matching.ts +238 -0
- package/src/api/queries/notifications.ts +103 -0
- package/src/api/queries/offers.ts +136 -0
- package/src/api/queries/subscriptions.ts +91 -0
- package/src/api/queries/support.ts +235 -0
- package/src/api/queries/users.ts +393 -0
- package/src/api/types.ts +596 -0
- 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
|