@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.
- package/dist/__tests__/e2e.test.d.ts +30 -0
- package/dist/__tests__/e2e.test.js +959 -63
- package/dist/api/mutations/badges.d.ts +116 -0
- package/dist/api/mutations/badges.js +177 -0
- package/dist/api/mutations/brands.d.ts +251 -0
- package/dist/api/mutations/brands.js +242 -0
- package/dist/api/mutations/creators.d.ts +131 -0
- package/dist/api/mutations/creators.js +129 -0
- package/dist/api/mutations/event-chat.d.ts +2 -2
- package/dist/api/mutations/event-chat.js +9 -9
- package/dist/api/mutations/index.d.ts +4 -0
- package/dist/api/mutations/index.js +5 -1
- package/dist/api/mutations/jack.d.ts +29 -0
- package/dist/api/mutations/jack.js +41 -1
- package/dist/api/mutations/products.d.ts +175 -0
- package/dist/api/mutations/products.js +226 -0
- package/dist/api/mutations/support.d.ts +20 -1
- package/dist/api/mutations/support.js +36 -1
- package/dist/api/queries/badges.d.ts +221 -0
- package/dist/api/queries/badges.js +290 -0
- package/dist/api/queries/bookings.d.ts +1 -1
- package/dist/api/queries/brands.d.ts +248 -0
- package/dist/api/queries/brands.js +226 -0
- package/dist/api/queries/businesses.d.ts +61 -1
- package/dist/api/queries/businesses.js +27 -1
- package/dist/api/queries/creators.d.ts +332 -0
- package/dist/api/queries/creators.js +249 -0
- package/dist/api/queries/event-chat.d.ts +1 -1
- package/dist/api/queries/event-chat.js +4 -4
- package/dist/api/queries/events.d.ts +45 -0
- package/dist/api/queries/index.d.ts +5 -0
- package/dist/api/queries/index.js +6 -1
- package/dist/api/queries/jack.d.ts +80 -0
- package/dist/api/queries/jack.js +98 -1
- package/dist/api/queries/library.d.ts +8 -0
- package/dist/api/queries/products.d.ts +185 -0
- package/dist/api/queries/products.js +203 -0
- package/dist/api/queries/support.d.ts +46 -1
- package/dist/api/queries/support.js +48 -1
- package/dist/api/queries/venues.d.ts +304 -0
- package/dist/api/queries/venues.js +211 -0
- package/dist/api/types.d.ts +245 -0
- package/dist/api/types.js +6 -1
- package/dist/api/utils/eventGrouping.d.ts +104 -0
- package/dist/api/utils/eventGrouping.js +155 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -1
- package/package.json +5 -2
- package/src/__tests__/e2e.test.ts +996 -64
- package/src/api/mutations/badges.ts +228 -0
- package/src/api/mutations/brands.ts +376 -0
- package/src/api/mutations/creators.ts +171 -0
- package/src/api/mutations/event-chat.ts +8 -8
- package/src/api/mutations/index.ts +4 -0
- package/src/api/mutations/jack.ts +50 -1
- package/src/api/mutations/products.ts +336 -0
- package/src/api/mutations/support.ts +44 -0
- package/src/api/queries/badges.ts +385 -0
- package/src/api/queries/brands.ts +281 -0
- package/src/api/queries/businesses.ts +30 -1
- package/src/api/queries/creators.ts +308 -0
- package/src/api/queries/event-chat.ts +3 -3
- package/src/api/queries/index.ts +5 -0
- package/src/api/queries/jack.ts +139 -1
- package/src/api/queries/products.ts +312 -0
- package/src/api/queries/support.ts +54 -0
- package/src/api/queries/venues.ts +271 -0
- package/src/api/types.ts +317 -1
- package/src/api/utils/eventGrouping.ts +181 -0
- package/src/index.ts +6 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { useMutation, useQueryClient, UseMutationOptions } from '@tanstack/react-query';
|
|
2
|
+
import { getApiClient } from '../client';
|
|
3
|
+
import { badgeKeys, rewardKeys } from '../queries/badges';
|
|
4
|
+
import type {
|
|
5
|
+
PartnerRewardResponse,
|
|
6
|
+
PartnerRewardRedemptionResponse,
|
|
7
|
+
CreatePartnerRewardRequest,
|
|
8
|
+
} from '../types';
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// REWARD MUTATION HOOKS
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Redeem a partner reward
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* const redeemReward = useRedeemReward();
|
|
20
|
+
*
|
|
21
|
+
* const handleRedeem = async (rewardId: string) => {
|
|
22
|
+
* await redeemReward.mutateAsync(rewardId);
|
|
23
|
+
* // Show success message
|
|
24
|
+
* };
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function useRedeemReward(
|
|
28
|
+
options?: Omit<UseMutationOptions<PartnerRewardRedemptionResponse, Error, string>, 'mutationFn'>
|
|
29
|
+
) {
|
|
30
|
+
const queryClient = useQueryClient();
|
|
31
|
+
|
|
32
|
+
return useMutation({
|
|
33
|
+
mutationFn: async (rewardId: string): Promise<PartnerRewardRedemptionResponse> => {
|
|
34
|
+
const client = getApiClient();
|
|
35
|
+
const response = await client.post(`/api/v1/rewards/${rewardId}/redeem`);
|
|
36
|
+
return response.data?.data || response.data;
|
|
37
|
+
},
|
|
38
|
+
onSuccess: () => {
|
|
39
|
+
// Invalidate wallet, available and redeemed rewards
|
|
40
|
+
queryClient.invalidateQueries({ queryKey: rewardKeys.wallet() });
|
|
41
|
+
queryClient.invalidateQueries({ queryKey: rewardKeys.available() });
|
|
42
|
+
queryClient.invalidateQueries({ queryKey: rewardKeys.redeemed() });
|
|
43
|
+
},
|
|
44
|
+
...options,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Create a partner reward (for business dashboard)
|
|
50
|
+
*
|
|
51
|
+
* @param businessId - Business ID creating the reward
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* const createReward = useCreatePartnerReward('business-123');
|
|
56
|
+
*
|
|
57
|
+
* const handleCreate = async () => {
|
|
58
|
+
* await createReward.mutateAsync({
|
|
59
|
+
* badgeId: 'badge-week-warrior',
|
|
60
|
+
* title: 'Free Coffee',
|
|
61
|
+
* description: 'Show your badge for a free coffee',
|
|
62
|
+
* });
|
|
63
|
+
* };
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export function useCreatePartnerReward(
|
|
67
|
+
businessId: string,
|
|
68
|
+
options?: Omit<UseMutationOptions<PartnerRewardResponse, Error, CreatePartnerRewardRequest>, 'mutationFn'>
|
|
69
|
+
) {
|
|
70
|
+
const queryClient = useQueryClient();
|
|
71
|
+
|
|
72
|
+
return useMutation({
|
|
73
|
+
mutationFn: async (data: CreatePartnerRewardRequest): Promise<PartnerRewardResponse> => {
|
|
74
|
+
const client = getApiClient();
|
|
75
|
+
const response = await client.post(`/api/v1/businesses/${businessId}/rewards`, data);
|
|
76
|
+
return response.data?.data || response.data;
|
|
77
|
+
},
|
|
78
|
+
onSuccess: () => {
|
|
79
|
+
queryClient.invalidateQueries({ queryKey: rewardKeys.forBusiness(businessId) });
|
|
80
|
+
},
|
|
81
|
+
...options,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ============================================================================
|
|
86
|
+
// UNIFIED REWARD MUTATIONS (Venue & Brand)
|
|
87
|
+
// ============================================================================
|
|
88
|
+
|
|
89
|
+
interface CreateRewardRequest {
|
|
90
|
+
badgeId: string;
|
|
91
|
+
title: string;
|
|
92
|
+
description?: string;
|
|
93
|
+
code?: string;
|
|
94
|
+
redeemType?: 'IN_PERSON' | 'ONLINE' | 'BOTH';
|
|
95
|
+
maxRedemptions?: number;
|
|
96
|
+
perUserLimit?: number;
|
|
97
|
+
validFrom?: string;
|
|
98
|
+
validUntil?: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Create a reward for a venue
|
|
103
|
+
*
|
|
104
|
+
* @param venueId - Venue ID
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```tsx
|
|
108
|
+
* const createReward = useCreateVenueReward('venue-123');
|
|
109
|
+
*
|
|
110
|
+
* const handleCreate = async () => {
|
|
111
|
+
* await createReward.mutateAsync({
|
|
112
|
+
* badgeId: 'badge-week-warrior',
|
|
113
|
+
* title: 'Free Coffee',
|
|
114
|
+
* description: 'Show your badge for a free coffee',
|
|
115
|
+
* redeemType: 'IN_PERSON',
|
|
116
|
+
* });
|
|
117
|
+
* };
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export function useCreateVenueReward(
|
|
121
|
+
venueId: string,
|
|
122
|
+
options?: Omit<UseMutationOptions<unknown, Error, CreateRewardRequest>, 'mutationFn'>
|
|
123
|
+
) {
|
|
124
|
+
const queryClient = useQueryClient();
|
|
125
|
+
|
|
126
|
+
return useMutation({
|
|
127
|
+
mutationFn: async (data: CreateRewardRequest) => {
|
|
128
|
+
const client = getApiClient();
|
|
129
|
+
const response = await client.post(`/api/v1/venues/${venueId}/rewards`, data);
|
|
130
|
+
return response.data?.data || response.data;
|
|
131
|
+
},
|
|
132
|
+
onSuccess: () => {
|
|
133
|
+
queryClient.invalidateQueries({ queryKey: rewardKeys.forVenue(venueId) });
|
|
134
|
+
queryClient.invalidateQueries({ queryKey: rewardKeys.available() });
|
|
135
|
+
},
|
|
136
|
+
...options,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Create a reward for a brand
|
|
142
|
+
*
|
|
143
|
+
* @param brandId - Brand ID
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```tsx
|
|
147
|
+
* const createReward = useCreateBrandReward('brand-123');
|
|
148
|
+
*
|
|
149
|
+
* const handleCreate = async () => {
|
|
150
|
+
* await createReward.mutateAsync({
|
|
151
|
+
* badgeId: 'badge-week-warrior',
|
|
152
|
+
* title: '10% Off',
|
|
153
|
+
* description: 'Use code at checkout',
|
|
154
|
+
* code: 'SOBER10',
|
|
155
|
+
* redeemType: 'ONLINE',
|
|
156
|
+
* });
|
|
157
|
+
* };
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
export function useCreateBrandReward(
|
|
161
|
+
brandId: string,
|
|
162
|
+
options?: Omit<UseMutationOptions<unknown, Error, CreateRewardRequest>, 'mutationFn'>
|
|
163
|
+
) {
|
|
164
|
+
const queryClient = useQueryClient();
|
|
165
|
+
|
|
166
|
+
return useMutation({
|
|
167
|
+
mutationFn: async (data: CreateRewardRequest) => {
|
|
168
|
+
const client = getApiClient();
|
|
169
|
+
const response = await client.post(`/api/v1/brands/${brandId}/rewards`, data);
|
|
170
|
+
return response.data?.data || response.data;
|
|
171
|
+
},
|
|
172
|
+
onSuccess: () => {
|
|
173
|
+
queryClient.invalidateQueries({ queryKey: rewardKeys.forBrand(brandId) });
|
|
174
|
+
queryClient.invalidateQueries({ queryKey: rewardKeys.available() });
|
|
175
|
+
},
|
|
176
|
+
...options,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Update a partner reward (for business dashboard)
|
|
182
|
+
*
|
|
183
|
+
* @param businessId - Business ID
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```tsx
|
|
187
|
+
* const updateReward = useUpdatePartnerReward('business-123');
|
|
188
|
+
*
|
|
189
|
+
* const handleUpdate = async (rewardId: string) => {
|
|
190
|
+
* await updateReward.mutateAsync({
|
|
191
|
+
* id: rewardId,
|
|
192
|
+
* data: { title: 'Updated Title', isActive: false },
|
|
193
|
+
* });
|
|
194
|
+
* };
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
export function useUpdatePartnerReward(
|
|
198
|
+
businessId: string,
|
|
199
|
+
options?: Omit<
|
|
200
|
+
UseMutationOptions<
|
|
201
|
+
PartnerRewardResponse,
|
|
202
|
+
Error,
|
|
203
|
+
{ id: string; data: Partial<CreatePartnerRewardRequest & { isActive: boolean }> }
|
|
204
|
+
>,
|
|
205
|
+
'mutationFn'
|
|
206
|
+
>
|
|
207
|
+
) {
|
|
208
|
+
const queryClient = useQueryClient();
|
|
209
|
+
|
|
210
|
+
return useMutation({
|
|
211
|
+
mutationFn: async ({
|
|
212
|
+
id,
|
|
213
|
+
data,
|
|
214
|
+
}: {
|
|
215
|
+
id: string;
|
|
216
|
+
data: Partial<CreatePartnerRewardRequest & { isActive: boolean }>;
|
|
217
|
+
}): Promise<PartnerRewardResponse> => {
|
|
218
|
+
const client = getApiClient();
|
|
219
|
+
const response = await client.patch(`/api/v1/businesses/${businessId}/rewards/${id}`, data);
|
|
220
|
+
return response.data?.data || response.data;
|
|
221
|
+
},
|
|
222
|
+
onSuccess: () => {
|
|
223
|
+
queryClient.invalidateQueries({ queryKey: rewardKeys.forBusiness(businessId) });
|
|
224
|
+
queryClient.invalidateQueries({ queryKey: rewardKeys.available() });
|
|
225
|
+
},
|
|
226
|
+
...options,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
import { useMutation, useQueryClient, UseMutationOptions } from '@tanstack/react-query';
|
|
2
|
+
import { getApiClient } from '../client';
|
|
3
|
+
import { brandKeys } from '../queries/brands';
|
|
4
|
+
import type {
|
|
5
|
+
BrandResponse,
|
|
6
|
+
BrandOwnerResponse,
|
|
7
|
+
BrandCreatorResponse,
|
|
8
|
+
BrandOwnerRole,
|
|
9
|
+
CreateBrandRequest,
|
|
10
|
+
UpdateBrandRequest,
|
|
11
|
+
} from '../types';
|
|
12
|
+
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// MUTATION HOOKS
|
|
15
|
+
// ============================================================================
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Create a new brand
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const { mutateAsync: createBrand } = useCreateBrand();
|
|
23
|
+
*
|
|
24
|
+
* await createBrand({
|
|
25
|
+
* slug: 'wellness-co',
|
|
26
|
+
* name: 'Wellness Co',
|
|
27
|
+
* description: 'A wellness brand',
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function useCreateBrand(
|
|
32
|
+
options?: Omit<UseMutationOptions<BrandResponse, Error, CreateBrandRequest>, 'mutationFn'>
|
|
33
|
+
) {
|
|
34
|
+
const queryClient = useQueryClient();
|
|
35
|
+
|
|
36
|
+
return useMutation({
|
|
37
|
+
mutationFn: async (data: CreateBrandRequest): Promise<BrandResponse> => {
|
|
38
|
+
const client = getApiClient();
|
|
39
|
+
const response = await client.post('/api/v1/brands', data);
|
|
40
|
+
return response.data;
|
|
41
|
+
},
|
|
42
|
+
onSuccess: () => {
|
|
43
|
+
queryClient.invalidateQueries({ queryKey: brandKeys.all });
|
|
44
|
+
},
|
|
45
|
+
...options,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Update a brand
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```tsx
|
|
54
|
+
* const { mutateAsync: updateBrand } = useUpdateBrand();
|
|
55
|
+
*
|
|
56
|
+
* await updateBrand({
|
|
57
|
+
* id: 'brand-123',
|
|
58
|
+
* data: { description: 'Updated description' },
|
|
59
|
+
* });
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export function useUpdateBrand(
|
|
63
|
+
options?: Omit<
|
|
64
|
+
UseMutationOptions<BrandResponse, Error, { id: string; data: UpdateBrandRequest }>,
|
|
65
|
+
'mutationFn'
|
|
66
|
+
>
|
|
67
|
+
) {
|
|
68
|
+
const queryClient = useQueryClient();
|
|
69
|
+
|
|
70
|
+
return useMutation({
|
|
71
|
+
mutationFn: async ({ id, data }: { id: string; data: UpdateBrandRequest }): Promise<BrandResponse> => {
|
|
72
|
+
const client = getApiClient();
|
|
73
|
+
const response = await client.patch(`/api/v1/brands/${id}`, data);
|
|
74
|
+
return response.data;
|
|
75
|
+
},
|
|
76
|
+
onSuccess: (_, variables) => {
|
|
77
|
+
queryClient.invalidateQueries({ queryKey: brandKeys.detail(variables.id) });
|
|
78
|
+
},
|
|
79
|
+
...options,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Add a brand owner
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```tsx
|
|
88
|
+
* const { mutateAsync: addOwner } = useAddBrandOwner();
|
|
89
|
+
*
|
|
90
|
+
* await addOwner({
|
|
91
|
+
* brandId: 'brand-123',
|
|
92
|
+
* userId: 'user-456',
|
|
93
|
+
* role: 'MANAGER',
|
|
94
|
+
* });
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export function useAddBrandOwner(
|
|
98
|
+
options?: Omit<
|
|
99
|
+
UseMutationOptions<
|
|
100
|
+
BrandOwnerResponse,
|
|
101
|
+
Error,
|
|
102
|
+
{ brandId: string; userId: string; role: BrandOwnerRole }
|
|
103
|
+
>,
|
|
104
|
+
'mutationFn'
|
|
105
|
+
>
|
|
106
|
+
) {
|
|
107
|
+
const queryClient = useQueryClient();
|
|
108
|
+
|
|
109
|
+
return useMutation({
|
|
110
|
+
mutationFn: async ({
|
|
111
|
+
brandId,
|
|
112
|
+
userId,
|
|
113
|
+
role,
|
|
114
|
+
}: {
|
|
115
|
+
brandId: string;
|
|
116
|
+
userId: string;
|
|
117
|
+
role: BrandOwnerRole;
|
|
118
|
+
}): Promise<BrandOwnerResponse> => {
|
|
119
|
+
const client = getApiClient();
|
|
120
|
+
const response = await client.post(`/api/v1/brands/${brandId}/owners`, { userId, role });
|
|
121
|
+
return response.data;
|
|
122
|
+
},
|
|
123
|
+
onSuccess: (_, variables) => {
|
|
124
|
+
queryClient.invalidateQueries({ queryKey: brandKeys.owners(variables.brandId) });
|
|
125
|
+
},
|
|
126
|
+
...options,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Update a brand owner's role
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```tsx
|
|
135
|
+
* const { mutateAsync: updateOwnerRole } = useUpdateBrandOwnerRole();
|
|
136
|
+
*
|
|
137
|
+
* await updateOwnerRole({
|
|
138
|
+
* brandId: 'brand-123',
|
|
139
|
+
* userId: 'user-456',
|
|
140
|
+
* role: 'OWNER',
|
|
141
|
+
* });
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
export function useUpdateBrandOwnerRole(
|
|
145
|
+
options?: Omit<
|
|
146
|
+
UseMutationOptions<
|
|
147
|
+
BrandOwnerResponse,
|
|
148
|
+
Error,
|
|
149
|
+
{ brandId: string; userId: string; role: BrandOwnerRole }
|
|
150
|
+
>,
|
|
151
|
+
'mutationFn'
|
|
152
|
+
>
|
|
153
|
+
) {
|
|
154
|
+
const queryClient = useQueryClient();
|
|
155
|
+
|
|
156
|
+
return useMutation({
|
|
157
|
+
mutationFn: async ({
|
|
158
|
+
brandId,
|
|
159
|
+
userId,
|
|
160
|
+
role,
|
|
161
|
+
}: {
|
|
162
|
+
brandId: string;
|
|
163
|
+
userId: string;
|
|
164
|
+
role: BrandOwnerRole;
|
|
165
|
+
}): Promise<BrandOwnerResponse> => {
|
|
166
|
+
const client = getApiClient();
|
|
167
|
+
const response = await client.patch(`/api/v1/brands/${brandId}/owners/${userId}`, { role });
|
|
168
|
+
return response.data;
|
|
169
|
+
},
|
|
170
|
+
onSuccess: (_, variables) => {
|
|
171
|
+
queryClient.invalidateQueries({ queryKey: brandKeys.owners(variables.brandId) });
|
|
172
|
+
},
|
|
173
|
+
...options,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Remove a brand owner
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```tsx
|
|
182
|
+
* const { mutateAsync: removeOwner } = useRemoveBrandOwner();
|
|
183
|
+
*
|
|
184
|
+
* await removeOwner({
|
|
185
|
+
* brandId: 'brand-123',
|
|
186
|
+
* userId: 'user-456',
|
|
187
|
+
* });
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
export function useRemoveBrandOwner(
|
|
191
|
+
options?: Omit<
|
|
192
|
+
UseMutationOptions<void, Error, { brandId: string; userId: string }>,
|
|
193
|
+
'mutationFn'
|
|
194
|
+
>
|
|
195
|
+
) {
|
|
196
|
+
const queryClient = useQueryClient();
|
|
197
|
+
|
|
198
|
+
return useMutation({
|
|
199
|
+
mutationFn: async ({
|
|
200
|
+
brandId,
|
|
201
|
+
userId,
|
|
202
|
+
}: {
|
|
203
|
+
brandId: string;
|
|
204
|
+
userId: string;
|
|
205
|
+
}): Promise<void> => {
|
|
206
|
+
const client = getApiClient();
|
|
207
|
+
await client.delete(`/api/v1/brands/${brandId}/owners/${userId}`);
|
|
208
|
+
},
|
|
209
|
+
onSuccess: (_, variables) => {
|
|
210
|
+
queryClient.invalidateQueries({ queryKey: brandKeys.owners(variables.brandId) });
|
|
211
|
+
},
|
|
212
|
+
...options,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Add a creator partnership to a brand
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```tsx
|
|
221
|
+
* const { mutateAsync: addCreator } = useAddBrandCreator();
|
|
222
|
+
*
|
|
223
|
+
* await addCreator({
|
|
224
|
+
* brandId: 'brand-123',
|
|
225
|
+
* creatorId: 'creator-456',
|
|
226
|
+
* commissionRate: 0.15,
|
|
227
|
+
* });
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
export function useAddBrandCreator(
|
|
231
|
+
options?: Omit<
|
|
232
|
+
UseMutationOptions<
|
|
233
|
+
BrandCreatorResponse,
|
|
234
|
+
Error,
|
|
235
|
+
{
|
|
236
|
+
brandId: string;
|
|
237
|
+
creatorId: string;
|
|
238
|
+
startDate?: string;
|
|
239
|
+
endDate?: string;
|
|
240
|
+
commissionRate?: number;
|
|
241
|
+
isActive?: boolean;
|
|
242
|
+
}
|
|
243
|
+
>,
|
|
244
|
+
'mutationFn'
|
|
245
|
+
>
|
|
246
|
+
) {
|
|
247
|
+
const queryClient = useQueryClient();
|
|
248
|
+
|
|
249
|
+
return useMutation({
|
|
250
|
+
mutationFn: async ({
|
|
251
|
+
brandId,
|
|
252
|
+
creatorId,
|
|
253
|
+
startDate,
|
|
254
|
+
endDate,
|
|
255
|
+
commissionRate,
|
|
256
|
+
isActive,
|
|
257
|
+
}: {
|
|
258
|
+
brandId: string;
|
|
259
|
+
creatorId: string;
|
|
260
|
+
startDate?: string;
|
|
261
|
+
endDate?: string;
|
|
262
|
+
commissionRate?: number;
|
|
263
|
+
isActive?: boolean;
|
|
264
|
+
}): Promise<BrandCreatorResponse> => {
|
|
265
|
+
const client = getApiClient();
|
|
266
|
+
const response = await client.post(`/api/v1/brands/${brandId}/creators`, {
|
|
267
|
+
creatorId,
|
|
268
|
+
startDate,
|
|
269
|
+
endDate,
|
|
270
|
+
commissionRate,
|
|
271
|
+
isActive,
|
|
272
|
+
});
|
|
273
|
+
return response.data;
|
|
274
|
+
},
|
|
275
|
+
onSuccess: (_, variables) => {
|
|
276
|
+
queryClient.invalidateQueries({ queryKey: brandKeys.creators(variables.brandId) });
|
|
277
|
+
},
|
|
278
|
+
...options,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Update a creator partnership
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* ```tsx
|
|
287
|
+
* const { mutateAsync: updateCreator } = useUpdateBrandCreator();
|
|
288
|
+
*
|
|
289
|
+
* await updateCreator({
|
|
290
|
+
* brandId: 'brand-123',
|
|
291
|
+
* creatorId: 'creator-456',
|
|
292
|
+
* isActive: false,
|
|
293
|
+
* });
|
|
294
|
+
* ```
|
|
295
|
+
*/
|
|
296
|
+
export function useUpdateBrandCreator(
|
|
297
|
+
options?: Omit<
|
|
298
|
+
UseMutationOptions<
|
|
299
|
+
BrandCreatorResponse,
|
|
300
|
+
Error,
|
|
301
|
+
{
|
|
302
|
+
brandId: string;
|
|
303
|
+
creatorId: string;
|
|
304
|
+
startDate?: string;
|
|
305
|
+
endDate?: string;
|
|
306
|
+
commissionRate?: number;
|
|
307
|
+
isActive?: boolean;
|
|
308
|
+
}
|
|
309
|
+
>,
|
|
310
|
+
'mutationFn'
|
|
311
|
+
>
|
|
312
|
+
) {
|
|
313
|
+
const queryClient = useQueryClient();
|
|
314
|
+
|
|
315
|
+
return useMutation({
|
|
316
|
+
mutationFn: async ({
|
|
317
|
+
brandId,
|
|
318
|
+
creatorId,
|
|
319
|
+
...data
|
|
320
|
+
}: {
|
|
321
|
+
brandId: string;
|
|
322
|
+
creatorId: string;
|
|
323
|
+
startDate?: string;
|
|
324
|
+
endDate?: string;
|
|
325
|
+
commissionRate?: number;
|
|
326
|
+
isActive?: boolean;
|
|
327
|
+
}): Promise<BrandCreatorResponse> => {
|
|
328
|
+
const client = getApiClient();
|
|
329
|
+
const response = await client.patch(`/api/v1/brands/${brandId}/creators/${creatorId}`, data);
|
|
330
|
+
return response.data;
|
|
331
|
+
},
|
|
332
|
+
onSuccess: (_, variables) => {
|
|
333
|
+
queryClient.invalidateQueries({ queryKey: brandKeys.creators(variables.brandId) });
|
|
334
|
+
},
|
|
335
|
+
...options,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Remove a creator partnership from a brand
|
|
341
|
+
*
|
|
342
|
+
* @example
|
|
343
|
+
* ```tsx
|
|
344
|
+
* const { mutateAsync: removeCreator } = useRemoveBrandCreator();
|
|
345
|
+
*
|
|
346
|
+
* await removeCreator({
|
|
347
|
+
* brandId: 'brand-123',
|
|
348
|
+
* creatorId: 'creator-456',
|
|
349
|
+
* });
|
|
350
|
+
* ```
|
|
351
|
+
*/
|
|
352
|
+
export function useRemoveBrandCreator(
|
|
353
|
+
options?: Omit<
|
|
354
|
+
UseMutationOptions<void, Error, { brandId: string; creatorId: string }>,
|
|
355
|
+
'mutationFn'
|
|
356
|
+
>
|
|
357
|
+
) {
|
|
358
|
+
const queryClient = useQueryClient();
|
|
359
|
+
|
|
360
|
+
return useMutation({
|
|
361
|
+
mutationFn: async ({
|
|
362
|
+
brandId,
|
|
363
|
+
creatorId,
|
|
364
|
+
}: {
|
|
365
|
+
brandId: string;
|
|
366
|
+
creatorId: string;
|
|
367
|
+
}): Promise<void> => {
|
|
368
|
+
const client = getApiClient();
|
|
369
|
+
await client.delete(`/api/v1/brands/${brandId}/creators/${creatorId}`);
|
|
370
|
+
},
|
|
371
|
+
onSuccess: (_, variables) => {
|
|
372
|
+
queryClient.invalidateQueries({ queryKey: brandKeys.creators(variables.brandId) });
|
|
373
|
+
},
|
|
374
|
+
...options,
|
|
375
|
+
});
|
|
376
|
+
}
|