@growsober/sdk 1.0.5 → 1.0.8

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 (70) hide show
  1. package/dist/__tests__/e2e.test.d.ts +30 -0
  2. package/dist/__tests__/e2e.test.js +959 -63
  3. package/dist/api/mutations/badges.d.ts +116 -0
  4. package/dist/api/mutations/badges.js +177 -0
  5. package/dist/api/mutations/brands.d.ts +251 -0
  6. package/dist/api/mutations/brands.js +242 -0
  7. package/dist/api/mutations/creators.d.ts +131 -0
  8. package/dist/api/mutations/creators.js +129 -0
  9. package/dist/api/mutations/event-chat.d.ts +2 -2
  10. package/dist/api/mutations/event-chat.js +9 -9
  11. package/dist/api/mutations/index.d.ts +4 -0
  12. package/dist/api/mutations/index.js +5 -1
  13. package/dist/api/mutations/jack.d.ts +29 -0
  14. package/dist/api/mutations/jack.js +41 -1
  15. package/dist/api/mutations/products.d.ts +175 -0
  16. package/dist/api/mutations/products.js +226 -0
  17. package/dist/api/mutations/support.d.ts +20 -1
  18. package/dist/api/mutations/support.js +36 -1
  19. package/dist/api/queries/badges.d.ts +221 -0
  20. package/dist/api/queries/badges.js +290 -0
  21. package/dist/api/queries/bookings.d.ts +1 -1
  22. package/dist/api/queries/brands.d.ts +248 -0
  23. package/dist/api/queries/brands.js +226 -0
  24. package/dist/api/queries/businesses.d.ts +61 -1
  25. package/dist/api/queries/businesses.js +27 -1
  26. package/dist/api/queries/creators.d.ts +332 -0
  27. package/dist/api/queries/creators.js +249 -0
  28. package/dist/api/queries/event-chat.d.ts +1 -1
  29. package/dist/api/queries/event-chat.js +4 -4
  30. package/dist/api/queries/events.d.ts +45 -0
  31. package/dist/api/queries/index.d.ts +5 -0
  32. package/dist/api/queries/index.js +6 -1
  33. package/dist/api/queries/jack.d.ts +80 -0
  34. package/dist/api/queries/jack.js +98 -1
  35. package/dist/api/queries/library.d.ts +8 -0
  36. package/dist/api/queries/products.d.ts +185 -0
  37. package/dist/api/queries/products.js +203 -0
  38. package/dist/api/queries/support.d.ts +46 -1
  39. package/dist/api/queries/support.js +48 -1
  40. package/dist/api/queries/venues.d.ts +304 -0
  41. package/dist/api/queries/venues.js +211 -0
  42. package/dist/api/types.d.ts +245 -0
  43. package/dist/api/types.js +6 -1
  44. package/dist/api/utils/eventGrouping.d.ts +104 -0
  45. package/dist/api/utils/eventGrouping.js +155 -0
  46. package/dist/index.d.ts +1 -0
  47. package/dist/index.js +5 -1
  48. package/package.json +5 -2
  49. package/src/__tests__/e2e.test.ts +996 -64
  50. package/src/api/mutations/badges.ts +228 -0
  51. package/src/api/mutations/brands.ts +376 -0
  52. package/src/api/mutations/creators.ts +171 -0
  53. package/src/api/mutations/event-chat.ts +8 -8
  54. package/src/api/mutations/index.ts +4 -0
  55. package/src/api/mutations/jack.ts +50 -1
  56. package/src/api/mutations/products.ts +336 -0
  57. package/src/api/mutations/support.ts +44 -0
  58. package/src/api/queries/badges.ts +385 -0
  59. package/src/api/queries/brands.ts +281 -0
  60. package/src/api/queries/businesses.ts +30 -1
  61. package/src/api/queries/creators.ts +308 -0
  62. package/src/api/queries/event-chat.ts +3 -3
  63. package/src/api/queries/index.ts +5 -0
  64. package/src/api/queries/jack.ts +139 -1
  65. package/src/api/queries/products.ts +312 -0
  66. package/src/api/queries/support.ts +54 -0
  67. package/src/api/queries/venues.ts +271 -0
  68. package/src/api/types.ts +317 -1
  69. package/src/api/utils/eventGrouping.ts +181 -0
  70. package/src/index.ts +6 -0
@@ -0,0 +1,385 @@
1
+ import { useQuery, UseQueryOptions } from '@tanstack/react-query';
2
+ import { getApiClient } from '../client';
3
+ import type {
4
+ BadgeResponse,
5
+ UserBadgeResponse,
6
+ BadgeWithProgress,
7
+ PartnerRewardResponse,
8
+ PartnerRewardRedemptionResponse,
9
+ RewardResponse,
10
+ UserWalletResponse,
11
+ } from '../types';
12
+
13
+ // ============================================================================
14
+ // QUERY KEY FACTORY
15
+ // ============================================================================
16
+
17
+ export const badgeKeys = {
18
+ all: ['badges'] as const,
19
+ lists: () => [...badgeKeys.all, 'list'] as const,
20
+ list: (userId?: string) => [...badgeKeys.lists(), userId] as const,
21
+ detail: (id: string) => [...badgeKeys.all, 'detail', id] as const,
22
+ user: (userId: string) => [...badgeKeys.all, 'user', userId] as const,
23
+ next: (userId: string) => [...badgeKeys.all, 'next', userId] as const,
24
+ };
25
+
26
+ export const rewardKeys = {
27
+ all: ['rewards'] as const,
28
+ available: () => [...rewardKeys.all, 'available'] as const,
29
+ forBadge: (badgeId: string) => [...rewardKeys.all, 'badge', badgeId] as const,
30
+ forBusiness: (businessId: string) => [...rewardKeys.all, 'business', businessId] as const,
31
+ forVenue: (venueId: string) => [...rewardKeys.all, 'venue', venueId] as const,
32
+ forBrand: (brandId: string) => [...rewardKeys.all, 'brand', brandId] as const,
33
+ redeemed: () => [...rewardKeys.all, 'redeemed'] as const,
34
+ wallet: () => [...rewardKeys.all, 'wallet'] as const,
35
+ };
36
+
37
+ // ============================================================================
38
+ // BADGE QUERY HOOKS
39
+ // ============================================================================
40
+
41
+ /**
42
+ * Get all available badges
43
+ *
44
+ * @example
45
+ * ```tsx
46
+ * const { data: badges } = useBadges();
47
+ * ```
48
+ */
49
+ export function useBadges(
50
+ options?: Omit<UseQueryOptions<BadgeResponse[]>, 'queryKey' | 'queryFn'>
51
+ ) {
52
+ return useQuery({
53
+ queryKey: badgeKeys.lists(),
54
+ queryFn: async (): Promise<BadgeResponse[]> => {
55
+ const client = getApiClient();
56
+ const response = await client.get('/api/v1/badges');
57
+ return response.data?.data || response.data || [];
58
+ },
59
+ ...options,
60
+ });
61
+ }
62
+
63
+ /**
64
+ * Get a single badge by ID
65
+ *
66
+ * @param id - Badge ID
67
+ * @example
68
+ * ```tsx
69
+ * const { data: badge } = useBadge('badge-123');
70
+ * ```
71
+ */
72
+ export function useBadge(
73
+ id: string,
74
+ options?: Omit<UseQueryOptions<BadgeResponse>, 'queryKey' | 'queryFn'>
75
+ ) {
76
+ return useQuery({
77
+ queryKey: badgeKeys.detail(id),
78
+ queryFn: async (): Promise<BadgeResponse> => {
79
+ const client = getApiClient();
80
+ const response = await client.get(`/api/v1/badges/${id}`);
81
+ return response.data?.data || response.data;
82
+ },
83
+ enabled: !!id,
84
+ ...options,
85
+ });
86
+ }
87
+
88
+ /**
89
+ * Get current user's earned badges
90
+ *
91
+ * @example
92
+ * ```tsx
93
+ * const { data: myBadges } = useMyBadges();
94
+ * ```
95
+ */
96
+ export function useMyBadges(
97
+ options?: Omit<UseQueryOptions<UserBadgeResponse[]>, 'queryKey' | 'queryFn'>
98
+ ) {
99
+ return useQuery({
100
+ queryKey: badgeKeys.user('me'),
101
+ queryFn: async (): Promise<UserBadgeResponse[]> => {
102
+ const client = getApiClient();
103
+ const response = await client.get('/api/v1/badges/me');
104
+ return response.data?.data || response.data || [];
105
+ },
106
+ ...options,
107
+ });
108
+ }
109
+
110
+ /**
111
+ * Get next badges user can earn (with progress)
112
+ *
113
+ * @example
114
+ * ```tsx
115
+ * const { data: nextBadges } = useNextBadges();
116
+ * // nextBadges = [{ badge: {...}, currentProgress: 5, requiredProgress: 10, percentComplete: 50 }, ...]
117
+ * ```
118
+ */
119
+ export function useNextBadges(
120
+ options?: Omit<UseQueryOptions<BadgeWithProgress[]>, 'queryKey' | 'queryFn'>
121
+ ) {
122
+ return useQuery({
123
+ queryKey: badgeKeys.next('me'),
124
+ queryFn: async (): Promise<BadgeWithProgress[]> => {
125
+ const client = getApiClient();
126
+ const response = await client.get('/api/v1/badges/next');
127
+ return response.data?.data || response.data || [];
128
+ },
129
+ ...options,
130
+ });
131
+ }
132
+
133
+ // ============================================================================
134
+ // PARTNER REWARD QUERY HOOKS
135
+ // ============================================================================
136
+
137
+ /**
138
+ * Get all rewards available to the current user (based on earned badges)
139
+ *
140
+ * @example
141
+ * ```tsx
142
+ * const { data: rewards } = useAvailableRewards();
143
+ * ```
144
+ */
145
+ export function useAvailableRewards(
146
+ options?: Omit<UseQueryOptions<PartnerRewardResponse[]>, 'queryKey' | 'queryFn'>
147
+ ) {
148
+ return useQuery({
149
+ queryKey: rewardKeys.available(),
150
+ queryFn: async (): Promise<PartnerRewardResponse[]> => {
151
+ const client = getApiClient();
152
+ const response = await client.get('/api/v1/rewards/available');
153
+ return response.data?.data || response.data || [];
154
+ },
155
+ ...options,
156
+ });
157
+ }
158
+
159
+ /**
160
+ * Get rewards for a specific badge
161
+ *
162
+ * @param badgeId - Badge ID
163
+ * @example
164
+ * ```tsx
165
+ * const { data: rewards } = useRewardsForBadge('badge-123');
166
+ * ```
167
+ */
168
+ export function useRewardsForBadge(
169
+ badgeId: string,
170
+ options?: Omit<UseQueryOptions<PartnerRewardResponse[]>, 'queryKey' | 'queryFn'>
171
+ ) {
172
+ return useQuery({
173
+ queryKey: rewardKeys.forBadge(badgeId),
174
+ queryFn: async (): Promise<PartnerRewardResponse[]> => {
175
+ const client = getApiClient();
176
+ const response = await client.get(`/api/v1/rewards/badge/${badgeId}`);
177
+ return response.data?.data || response.data || [];
178
+ },
179
+ enabled: !!badgeId,
180
+ ...options,
181
+ });
182
+ }
183
+
184
+ /**
185
+ * Get rewards offered by a specific business
186
+ *
187
+ * @param businessId - Business ID
188
+ * @example
189
+ * ```tsx
190
+ * const { data: rewards } = useBusinessRewards('business-123');
191
+ * ```
192
+ */
193
+ export function useBusinessRewards(
194
+ businessId: string,
195
+ options?: Omit<UseQueryOptions<PartnerRewardResponse[]>, 'queryKey' | 'queryFn'>
196
+ ) {
197
+ return useQuery({
198
+ queryKey: rewardKeys.forBusiness(businessId),
199
+ queryFn: async (): Promise<PartnerRewardResponse[]> => {
200
+ const client = getApiClient();
201
+ const response = await client.get(`/api/v1/rewards/business/${businessId}`);
202
+ return response.data?.data || response.data || [];
203
+ },
204
+ enabled: !!businessId,
205
+ ...options,
206
+ });
207
+ }
208
+
209
+ /**
210
+ * Get user's redeemed rewards
211
+ *
212
+ * @example
213
+ * ```tsx
214
+ * const { data: redeemed } = useRedeemedRewards();
215
+ * ```
216
+ */
217
+ export function useRedeemedRewards(
218
+ options?: Omit<UseQueryOptions<PartnerRewardRedemptionResponse[]>, 'queryKey' | 'queryFn'>
219
+ ) {
220
+ return useQuery({
221
+ queryKey: rewardKeys.redeemed(),
222
+ queryFn: async (): Promise<PartnerRewardRedemptionResponse[]> => {
223
+ const client = getApiClient();
224
+ const response = await client.get('/api/v1/rewards/redeemed');
225
+ return response.data?.data || response.data || [];
226
+ },
227
+ ...options,
228
+ });
229
+ }
230
+
231
+ // ============================================================================
232
+ // WALLET (Combined badges + rewards for Rewards tab)
233
+ // ============================================================================
234
+
235
+ /**
236
+ * Wallet reward card with QR token for redemption
237
+ */
238
+ export interface WalletReward {
239
+ id: string;
240
+ title: string;
241
+ description: string | null;
242
+ code: string | null;
243
+ validUntil: string | null;
244
+ badge: {
245
+ id: string;
246
+ name: string;
247
+ slug: string;
248
+ icon: string | null;
249
+ };
250
+ business: {
251
+ id: string;
252
+ name: string;
253
+ profileImage: string | null;
254
+ address: string | null;
255
+ };
256
+ }
257
+
258
+ export interface WalletRedemption {
259
+ id: string;
260
+ redeemedAt: string;
261
+ verifiedAt: string | null;
262
+ qrToken: string;
263
+ partnerReward: WalletReward;
264
+ }
265
+
266
+ export interface WalletBadge {
267
+ id: string;
268
+ badgeId: string;
269
+ userId: string;
270
+ awardedAt: string;
271
+ note: string | null;
272
+ badge: BadgeResponse;
273
+ availableRewards: WalletReward[];
274
+ redeemedRewards: WalletRedemption[];
275
+ }
276
+
277
+ export interface WalletResponse {
278
+ badges: WalletBadge[];
279
+ stats: {
280
+ totalBadges: number;
281
+ totalAvailableRewards: number;
282
+ totalRedeemedRewards: number;
283
+ };
284
+ }
285
+
286
+ /**
287
+ * Get user's wallet - all earned badges with available and redeemed rewards
288
+ * This is the main data source for the Rewards tab
289
+ *
290
+ * @example
291
+ * ```tsx
292
+ * const { data: wallet } = useRewardsWallet();
293
+ * // wallet.badges = [{ badge: {...}, availableRewards: [...], redeemedRewards: [...] }, ...]
294
+ * // wallet.stats = { totalBadges: 5, totalAvailableRewards: 3, totalRedeemedRewards: 2 }
295
+ * ```
296
+ */
297
+ export function useRewardsWallet(
298
+ options?: Omit<UseQueryOptions<WalletResponse>, 'queryKey' | 'queryFn'>
299
+ ) {
300
+ return useQuery({
301
+ queryKey: rewardKeys.wallet(),
302
+ queryFn: async (): Promise<WalletResponse> => {
303
+ const client = getApiClient();
304
+ const response = await client.get('/api/v1/rewards/wallet');
305
+ return response.data?.data || response.data;
306
+ },
307
+ ...options,
308
+ });
309
+ }
310
+
311
+ // ============================================================================
312
+ // UNIFIED REWARD HOOKS (Venue & Brand)
313
+ // ============================================================================
314
+
315
+ /**
316
+ * Get rewards for a specific venue (unified reward model)
317
+ *
318
+ * @param venueId - Venue ID
319
+ * @example
320
+ * ```tsx
321
+ * const { data: rewards } = useVenueRewards('venue-123');
322
+ * ```
323
+ */
324
+ export function useVenueRewards(
325
+ venueId: string,
326
+ options?: Omit<UseQueryOptions<RewardResponse[]>, 'queryKey' | 'queryFn'>
327
+ ) {
328
+ return useQuery({
329
+ queryKey: rewardKeys.forVenue(venueId),
330
+ queryFn: async (): Promise<RewardResponse[]> => {
331
+ const client = getApiClient();
332
+ const response = await client.get(`/api/v1/rewards/venue/${venueId}`);
333
+ return response.data?.data || response.data || [];
334
+ },
335
+ enabled: !!venueId,
336
+ ...options,
337
+ });
338
+ }
339
+
340
+ /**
341
+ * Get rewards for a specific brand (unified reward model)
342
+ *
343
+ * @param brandId - Brand ID
344
+ * @example
345
+ * ```tsx
346
+ * const { data: rewards } = useBrandRewardsQuery('brand-123');
347
+ * ```
348
+ */
349
+ export function useBrandRewardsQuery(
350
+ brandId: string,
351
+ options?: Omit<UseQueryOptions<RewardResponse[]>, 'queryKey' | 'queryFn'>
352
+ ) {
353
+ return useQuery({
354
+ queryKey: rewardKeys.forBrand(brandId),
355
+ queryFn: async (): Promise<RewardResponse[]> => {
356
+ const client = getApiClient();
357
+ const response = await client.get(`/api/v1/rewards/brand/${brandId}`);
358
+ return response.data?.data || response.data || [];
359
+ },
360
+ enabled: !!brandId,
361
+ ...options,
362
+ });
363
+ }
364
+
365
+ /**
366
+ * Get unified wallet with venue and brand rewards
367
+ *
368
+ * @example
369
+ * ```tsx
370
+ * const { data: wallet } = useUnifiedWallet();
371
+ * ```
372
+ */
373
+ export function useUnifiedWallet(
374
+ options?: Omit<UseQueryOptions<UserWalletResponse>, 'queryKey' | 'queryFn'>
375
+ ) {
376
+ return useQuery({
377
+ queryKey: [...rewardKeys.wallet(), 'unified'],
378
+ queryFn: async (): Promise<UserWalletResponse> => {
379
+ const client = getApiClient();
380
+ const response = await client.get('/api/v1/rewards/wallet');
381
+ return response.data?.data || response.data;
382
+ },
383
+ ...options,
384
+ });
385
+ }
@@ -0,0 +1,281 @@
1
+ import { useQuery, UseQueryOptions } from '@tanstack/react-query';
2
+ import { getApiClient } from '../client';
3
+ import type {
4
+ BrandResponse,
5
+ BrandOwnerResponse,
6
+ BrandCreatorResponse,
7
+ RewardResponse,
8
+ EventResponse,
9
+ } from '../types';
10
+
11
+ // ============================================================================
12
+ // QUERY KEY FACTORY
13
+ // ============================================================================
14
+
15
+ export const brandKeys = {
16
+ all: ['brands'] as const,
17
+ lists: () => [...brandKeys.all, 'list'] as const,
18
+ list: (filters?: BrandFilters) => [...brandKeys.lists(), filters] as const,
19
+ details: () => [...brandKeys.all, 'detail'] as const,
20
+ detail: (id: string) => [...brandKeys.details(), id] as const,
21
+ slug: (slug: string) => [...brandKeys.all, 'slug', slug] as const,
22
+ featured: () => [...brandKeys.all, 'featured'] as const,
23
+ owners: (brandId: string) => [...brandKeys.detail(brandId), 'owners'] as const,
24
+ creators: (brandId: string) => [...brandKeys.detail(brandId), 'creators'] as const,
25
+ rewards: (brandId: string) => [...brandKeys.detail(brandId), 'rewards'] as const,
26
+ events: (brandId: string) => [...brandKeys.detail(brandId), 'events'] as const,
27
+ };
28
+
29
+ // ============================================================================
30
+ // TYPES
31
+ // ============================================================================
32
+
33
+ export interface BrandFilters {
34
+ page?: number;
35
+ limit?: number;
36
+ search?: string;
37
+ isVerified?: boolean;
38
+ isFeatured?: boolean;
39
+ sortBy?: string;
40
+ sortOrder?: 'asc' | 'desc';
41
+ }
42
+
43
+ export interface PaginatedBrandsResponse {
44
+ brands: BrandResponse[];
45
+ meta: {
46
+ total: number;
47
+ page: number;
48
+ limit: number;
49
+ totalPages: number;
50
+ };
51
+ }
52
+
53
+ // ============================================================================
54
+ // QUERY HOOKS
55
+ // ============================================================================
56
+
57
+ /**
58
+ * Get paginated list of brands with optional filters
59
+ *
60
+ * @param filters - Query parameters for filtering and pagination
61
+ * @param options - TanStack Query options
62
+ *
63
+ * @example
64
+ * ```tsx
65
+ * const { data, isLoading } = useBrands({
66
+ * page: 1,
67
+ * limit: 20,
68
+ * isFeatured: true,
69
+ * });
70
+ * ```
71
+ */
72
+ export function useBrands(
73
+ filters?: BrandFilters,
74
+ options?: Omit<UseQueryOptions<PaginatedBrandsResponse>, 'queryKey' | 'queryFn'>
75
+ ) {
76
+ return useQuery({
77
+ queryKey: brandKeys.list(filters),
78
+ queryFn: async (): Promise<PaginatedBrandsResponse> => {
79
+ const client = getApiClient();
80
+ const response = await client.get('/api/v1/brands', {
81
+ params: filters,
82
+ });
83
+ return response.data;
84
+ },
85
+ ...options,
86
+ });
87
+ }
88
+
89
+ /**
90
+ * Get a single brand by ID
91
+ *
92
+ * @param id - Brand ID
93
+ * @param options - TanStack Query options
94
+ *
95
+ * @example
96
+ * ```tsx
97
+ * const { data, isLoading } = useBrand('brand-123');
98
+ * ```
99
+ */
100
+ export function useBrand(
101
+ id: string,
102
+ options?: Omit<UseQueryOptions<BrandResponse>, 'queryKey' | 'queryFn'>
103
+ ) {
104
+ return useQuery({
105
+ queryKey: brandKeys.detail(id),
106
+ queryFn: async (): Promise<BrandResponse> => {
107
+ const client = getApiClient();
108
+ const response = await client.get(`/api/v1/brands/${id}`);
109
+ return response.data;
110
+ },
111
+ enabled: !!id,
112
+ ...options,
113
+ });
114
+ }
115
+
116
+ /**
117
+ * Get a brand by its slug
118
+ *
119
+ * @param slug - Brand slug
120
+ * @param options - TanStack Query options
121
+ *
122
+ * @example
123
+ * ```tsx
124
+ * const { data, isLoading } = useBrandBySlug('wellness-co');
125
+ * ```
126
+ */
127
+ export function useBrandBySlug(
128
+ slug: string,
129
+ options?: Omit<UseQueryOptions<BrandResponse>, 'queryKey' | 'queryFn'>
130
+ ) {
131
+ return useQuery({
132
+ queryKey: brandKeys.slug(slug),
133
+ queryFn: async (): Promise<BrandResponse> => {
134
+ const client = getApiClient();
135
+ const response = await client.get(`/api/v1/brands/slug/${slug}`);
136
+ return response.data;
137
+ },
138
+ enabled: !!slug,
139
+ ...options,
140
+ });
141
+ }
142
+
143
+ /**
144
+ * Get featured brands
145
+ *
146
+ * @param limit - Maximum number of brands to return
147
+ * @param options - TanStack Query options
148
+ *
149
+ * @example
150
+ * ```tsx
151
+ * const { data, isLoading } = useFeaturedBrands(10);
152
+ * ```
153
+ */
154
+ export function useFeaturedBrands(
155
+ limit?: number,
156
+ options?: Omit<UseQueryOptions<BrandResponse[]>, 'queryKey' | 'queryFn'>
157
+ ) {
158
+ return useQuery({
159
+ queryKey: brandKeys.featured(),
160
+ queryFn: async (): Promise<BrandResponse[]> => {
161
+ const client = getApiClient();
162
+ const response = await client.get('/api/v1/brands/featured', {
163
+ params: { limit },
164
+ });
165
+ return response.data;
166
+ },
167
+ ...options,
168
+ });
169
+ }
170
+
171
+ /**
172
+ * Get brand owners
173
+ *
174
+ * @param brandId - Brand ID
175
+ * @param options - TanStack Query options
176
+ *
177
+ * @example
178
+ * ```tsx
179
+ * const { data, isLoading } = useBrandOwners('brand-123');
180
+ * ```
181
+ */
182
+ export function useBrandOwners(
183
+ brandId: string,
184
+ options?: Omit<UseQueryOptions<BrandOwnerResponse[]>, 'queryKey' | 'queryFn'>
185
+ ) {
186
+ return useQuery({
187
+ queryKey: brandKeys.owners(brandId),
188
+ queryFn: async (): Promise<BrandOwnerResponse[]> => {
189
+ const client = getApiClient();
190
+ const response = await client.get(`/api/v1/brands/${brandId}/owners`);
191
+ return response.data;
192
+ },
193
+ enabled: !!brandId,
194
+ ...options,
195
+ });
196
+ }
197
+
198
+ /**
199
+ * Get brand creator partnerships
200
+ *
201
+ * @param brandId - Brand ID
202
+ * @param options - TanStack Query options
203
+ *
204
+ * @example
205
+ * ```tsx
206
+ * const { data, isLoading } = useBrandCreators('brand-123');
207
+ * ```
208
+ */
209
+ export function useBrandCreators(
210
+ brandId: string,
211
+ options?: Omit<UseQueryOptions<BrandCreatorResponse[]>, 'queryKey' | 'queryFn'>
212
+ ) {
213
+ return useQuery({
214
+ queryKey: brandKeys.creators(brandId),
215
+ queryFn: async (): Promise<BrandCreatorResponse[]> => {
216
+ const client = getApiClient();
217
+ const response = await client.get(`/api/v1/brands/${brandId}/creators`);
218
+ return response.data;
219
+ },
220
+ enabled: !!brandId,
221
+ ...options,
222
+ });
223
+ }
224
+
225
+ /**
226
+ * Get brand rewards
227
+ *
228
+ * @param brandId - Brand ID
229
+ * @param options - TanStack Query options
230
+ *
231
+ * @example
232
+ * ```tsx
233
+ * const { data, isLoading } = useBrandRewards('brand-123');
234
+ * ```
235
+ */
236
+ export function useBrandRewards(
237
+ brandId: string,
238
+ options?: Omit<UseQueryOptions<RewardResponse[]>, 'queryKey' | 'queryFn'>
239
+ ) {
240
+ return useQuery({
241
+ queryKey: brandKeys.rewards(brandId),
242
+ queryFn: async (): Promise<RewardResponse[]> => {
243
+ const client = getApiClient();
244
+ const response = await client.get(`/api/v1/rewards/brand/${brandId}`);
245
+ return response.data;
246
+ },
247
+ enabled: !!brandId,
248
+ ...options,
249
+ });
250
+ }
251
+
252
+ /**
253
+ * Get events sponsored by a brand
254
+ *
255
+ * @param brandId - Brand ID
256
+ * @param upcoming - Whether to filter to upcoming events only (default: true)
257
+ * @param options - TanStack Query options
258
+ *
259
+ * @example
260
+ * ```tsx
261
+ * const { data, isLoading } = useBrandSponsoredEvents('brand-123');
262
+ * ```
263
+ */
264
+ export function useBrandSponsoredEvents(
265
+ brandId: string,
266
+ upcoming = true,
267
+ options?: Omit<UseQueryOptions<EventResponse[]>, 'queryKey' | 'queryFn'>
268
+ ) {
269
+ return useQuery({
270
+ queryKey: brandKeys.events(brandId),
271
+ queryFn: async (): Promise<EventResponse[]> => {
272
+ const client = getApiClient();
273
+ const response = await client.get(`/api/v1/brands/${brandId}/events`, {
274
+ params: { upcoming },
275
+ });
276
+ return response.data;
277
+ },
278
+ enabled: !!brandId,
279
+ ...options,
280
+ });
281
+ }
@@ -1,6 +1,6 @@
1
1
  import { useQuery, UseQueryOptions } from '@tanstack/react-query';
2
2
  import { getApiClient } from '../client';
3
- import type { BusinessResponse, OfferResponse } from '../types';
3
+ import type { BusinessResponse, OfferResponse, EventResponse } from '../types';
4
4
 
5
5
  // ============================================================================
6
6
  // QUERY KEY FACTORY
@@ -15,6 +15,7 @@ export const businessKeys = {
15
15
  featured: () => [...businessKeys.all, 'featured'] as const,
16
16
  nearby: (params?: NearbyBusinessParams) => [...businessKeys.all, 'nearby', params] as const,
17
17
  offers: (businessId: string) => [...businessKeys.detail(businessId), 'offers'] as const,
18
+ events: (businessId: string) => [...businessKeys.detail(businessId), 'events'] as const,
18
19
  };
19
20
 
20
21
  // ============================================================================
@@ -201,3 +202,31 @@ export function useBusinessOffers(
201
202
  ...options,
202
203
  });
203
204
  }
205
+
206
+ /**
207
+ * Get all events for a specific business
208
+ *
209
+ * @param businessId - Business ID
210
+ * @param options - TanStack Query options
211
+ *
212
+ * @example
213
+ * ```tsx
214
+ * const { data, isLoading } = useBusinessEvents('business-123');
215
+ * ```
216
+ */
217
+ export function useBusinessEvents(
218
+ businessId: string,
219
+ options?: Omit<UseQueryOptions<EventResponse[]>, 'queryKey' | 'queryFn'>
220
+ ) {
221
+ return useQuery({
222
+ queryKey: businessKeys.events(businessId),
223
+ queryFn: async (): Promise<EventResponse[]> => {
224
+ const client = getApiClient();
225
+ const response = await client.get(`/api/v1/businesses/${businessId}/events`);
226
+ // Handle wrapped response
227
+ return response.data?.data || response.data || [];
228
+ },
229
+ enabled: !!businessId,
230
+ ...options,
231
+ });
232
+ }