@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,169 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useMutation,
|
|
3
|
+
useQueryClient,
|
|
4
|
+
UseMutationOptions,
|
|
5
|
+
UseMutationResult,
|
|
6
|
+
} from '@tanstack/react-query';
|
|
7
|
+
import { getApiClient } from '../client';
|
|
8
|
+
import type {
|
|
9
|
+
Grow90EnrollmentResponse,
|
|
10
|
+
Grow90ProgressResponse,
|
|
11
|
+
EnrollGrow90Request,
|
|
12
|
+
UpdateGrow90ProgressRequest,
|
|
13
|
+
UpdateGrow90SettingsRequest,
|
|
14
|
+
} from '../types';
|
|
15
|
+
import { grow90Keys } from '../queries/grow90';
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// MUTATION HOOKS
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Enroll in GROW90 program
|
|
23
|
+
*/
|
|
24
|
+
export function useEnrollGrow90(
|
|
25
|
+
options?: Omit<
|
|
26
|
+
UseMutationOptions<Grow90EnrollmentResponse, Error, EnrollGrow90Request>,
|
|
27
|
+
'mutationFn'
|
|
28
|
+
>
|
|
29
|
+
): UseMutationResult<Grow90EnrollmentResponse, Error, EnrollGrow90Request> {
|
|
30
|
+
const queryClient = useQueryClient();
|
|
31
|
+
|
|
32
|
+
return useMutation({
|
|
33
|
+
mutationFn: async (data: EnrollGrow90Request): Promise<Grow90EnrollmentResponse> => {
|
|
34
|
+
const client = getApiClient();
|
|
35
|
+
const response = await client.post('/api/v1/grow90/enroll', data);
|
|
36
|
+
// API returns { data: {...}, meta: {...} }, extract the data
|
|
37
|
+
const enrollment = 'data' in response.data ? response.data.data : response.data;
|
|
38
|
+
return enrollment;
|
|
39
|
+
},
|
|
40
|
+
onSuccess: (enrollment) => {
|
|
41
|
+
queryClient.setQueryData(grow90Keys.enrollment(), enrollment);
|
|
42
|
+
queryClient.invalidateQueries({ queryKey: grow90Keys.today() });
|
|
43
|
+
queryClient.invalidateQueries({ queryKey: grow90Keys.progress() });
|
|
44
|
+
queryClient.invalidateQueries({ queryKey: grow90Keys.stats() });
|
|
45
|
+
},
|
|
46
|
+
...options,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Update progress for a specific day
|
|
52
|
+
*/
|
|
53
|
+
export function useUpdateGrow90Progress(
|
|
54
|
+
options?: Omit<
|
|
55
|
+
UseMutationOptions<Grow90ProgressResponse, Error, { day: number; data: UpdateGrow90ProgressRequest }>,
|
|
56
|
+
'mutationFn'
|
|
57
|
+
>
|
|
58
|
+
): UseMutationResult<Grow90ProgressResponse, Error, { day: number; data: UpdateGrow90ProgressRequest }> {
|
|
59
|
+
const queryClient = useQueryClient();
|
|
60
|
+
|
|
61
|
+
return useMutation({
|
|
62
|
+
mutationFn: async ({ day, data }): Promise<Grow90ProgressResponse> => {
|
|
63
|
+
const client = getApiClient();
|
|
64
|
+
const response = await client.put(`/api/v1/grow90/progress/${day}`, data);
|
|
65
|
+
// API returns { data: {...}, meta: {...} }, extract the data
|
|
66
|
+
return response.data?.data || response.data;
|
|
67
|
+
},
|
|
68
|
+
onSuccess: () => {
|
|
69
|
+
queryClient.invalidateQueries({ queryKey: grow90Keys.today() });
|
|
70
|
+
queryClient.invalidateQueries({ queryKey: grow90Keys.progress() });
|
|
71
|
+
queryClient.invalidateQueries({ queryKey: grow90Keys.stats() });
|
|
72
|
+
queryClient.invalidateQueries({ queryKey: grow90Keys.enrollment() });
|
|
73
|
+
},
|
|
74
|
+
...options,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Update GROW90 settings
|
|
80
|
+
*/
|
|
81
|
+
export function useUpdateGrow90Settings(
|
|
82
|
+
options?: Omit<
|
|
83
|
+
UseMutationOptions<Grow90EnrollmentResponse, Error, UpdateGrow90SettingsRequest>,
|
|
84
|
+
'mutationFn'
|
|
85
|
+
>
|
|
86
|
+
): UseMutationResult<Grow90EnrollmentResponse, Error, UpdateGrow90SettingsRequest> {
|
|
87
|
+
const queryClient = useQueryClient();
|
|
88
|
+
|
|
89
|
+
return useMutation({
|
|
90
|
+
mutationFn: async (data: UpdateGrow90SettingsRequest): Promise<Grow90EnrollmentResponse> => {
|
|
91
|
+
const client = getApiClient();
|
|
92
|
+
const response = await client.put('/api/v1/grow90/settings', data);
|
|
93
|
+
// API returns { data: {...}, meta: {...} }, extract the data
|
|
94
|
+
return response.data?.data || response.data;
|
|
95
|
+
},
|
|
96
|
+
onSuccess: (enrollment) => {
|
|
97
|
+
queryClient.setQueryData(grow90Keys.enrollment(), enrollment);
|
|
98
|
+
},
|
|
99
|
+
...options,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Pause GROW90 program
|
|
105
|
+
*/
|
|
106
|
+
export function usePauseGrow90(
|
|
107
|
+
options?: Omit<UseMutationOptions<Grow90EnrollmentResponse, Error, void>, 'mutationFn'>
|
|
108
|
+
): UseMutationResult<Grow90EnrollmentResponse, Error, void> {
|
|
109
|
+
const queryClient = useQueryClient();
|
|
110
|
+
|
|
111
|
+
return useMutation({
|
|
112
|
+
mutationFn: async (): Promise<Grow90EnrollmentResponse> => {
|
|
113
|
+
const client = getApiClient();
|
|
114
|
+
const response = await client.post('/api/v1/grow90/pause');
|
|
115
|
+
// API returns { data: {...}, meta: {...} }, extract the data
|
|
116
|
+
return response.data?.data || response.data;
|
|
117
|
+
},
|
|
118
|
+
onSuccess: (enrollment) => {
|
|
119
|
+
queryClient.setQueryData(grow90Keys.enrollment(), enrollment);
|
|
120
|
+
},
|
|
121
|
+
...options,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Resume GROW90 program
|
|
127
|
+
*/
|
|
128
|
+
export function useResumeGrow90(
|
|
129
|
+
options?: Omit<UseMutationOptions<Grow90EnrollmentResponse, Error, void>, 'mutationFn'>
|
|
130
|
+
): UseMutationResult<Grow90EnrollmentResponse, Error, void> {
|
|
131
|
+
const queryClient = useQueryClient();
|
|
132
|
+
|
|
133
|
+
return useMutation({
|
|
134
|
+
mutationFn: async (): Promise<Grow90EnrollmentResponse> => {
|
|
135
|
+
const client = getApiClient();
|
|
136
|
+
const response = await client.post('/api/v1/grow90/resume');
|
|
137
|
+
// API returns { data: {...}, meta: {...} }, extract the data
|
|
138
|
+
return response.data?.data || response.data;
|
|
139
|
+
},
|
|
140
|
+
onSuccess: (enrollment) => {
|
|
141
|
+
queryClient.setQueryData(grow90Keys.enrollment(), enrollment);
|
|
142
|
+
queryClient.invalidateQueries({ queryKey: grow90Keys.today() });
|
|
143
|
+
},
|
|
144
|
+
...options,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Abandon GROW90 program
|
|
150
|
+
*/
|
|
151
|
+
export function useAbandonGrow90(
|
|
152
|
+
options?: Omit<UseMutationOptions<{ success: boolean }, Error, void>, 'mutationFn'>
|
|
153
|
+
): UseMutationResult<{ success: boolean }, Error, void> {
|
|
154
|
+
const queryClient = useQueryClient();
|
|
155
|
+
|
|
156
|
+
return useMutation({
|
|
157
|
+
mutationFn: async (): Promise<{ success: boolean }> => {
|
|
158
|
+
const client = getApiClient();
|
|
159
|
+
const response = await client.post('/api/v1/grow90/abandon');
|
|
160
|
+
// API returns { data: {...}, meta: {...} }, extract the data
|
|
161
|
+
return response.data?.data || response.data;
|
|
162
|
+
},
|
|
163
|
+
onSuccess: () => {
|
|
164
|
+
queryClient.setQueryData(grow90Keys.enrollment(), null);
|
|
165
|
+
queryClient.invalidateQueries({ queryKey: grow90Keys.all });
|
|
166
|
+
},
|
|
167
|
+
...options,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useMutation,
|
|
3
|
+
useQueryClient,
|
|
4
|
+
UseMutationOptions,
|
|
5
|
+
UseMutationResult,
|
|
6
|
+
} from '@tanstack/react-query';
|
|
7
|
+
import { getApiClient } from '../client';
|
|
8
|
+
import type { HubResponse, CreateHubRequest, UpdateHubRequest } from '../types';
|
|
9
|
+
import { hubKeys } from '../queries/hubs';
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// TYPES
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
export interface UpdateMemberRoleRequest {
|
|
16
|
+
role: 'OWNER' | 'ADMIN' | 'MEMBER';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface JoinHubResponse {
|
|
20
|
+
message: string;
|
|
21
|
+
membership: {
|
|
22
|
+
id: string;
|
|
23
|
+
hubId: string;
|
|
24
|
+
userId: string;
|
|
25
|
+
role: 'MEMBER';
|
|
26
|
+
status: 'ACTIVE' | 'PENDING';
|
|
27
|
+
joinedAt: string;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface LeaveHubResponse {
|
|
32
|
+
message: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ApproveMemberResponse {
|
|
36
|
+
message: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface UpdateMemberRoleResponse {
|
|
40
|
+
message: string;
|
|
41
|
+
role: 'OWNER' | 'ADMIN' | 'MEMBER';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface RemoveMemberResponse {
|
|
45
|
+
message: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// MUTATION HOOKS
|
|
50
|
+
// ============================================================================
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Create a new hub
|
|
54
|
+
*
|
|
55
|
+
* @param options - React Query mutation options
|
|
56
|
+
* @returns Mutation result
|
|
57
|
+
*/
|
|
58
|
+
export function useCreateHub(
|
|
59
|
+
options?: Omit<
|
|
60
|
+
UseMutationOptions<HubResponse, Error, CreateHubRequest>,
|
|
61
|
+
'mutationFn'
|
|
62
|
+
>
|
|
63
|
+
): UseMutationResult<HubResponse, Error, CreateHubRequest> {
|
|
64
|
+
const queryClient = useQueryClient();
|
|
65
|
+
|
|
66
|
+
return useMutation({
|
|
67
|
+
mutationFn: async (data: CreateHubRequest): Promise<HubResponse> => {
|
|
68
|
+
const client = getApiClient();
|
|
69
|
+
const response = await client.post('/api/v1/hubs', data);
|
|
70
|
+
return response.data;
|
|
71
|
+
},
|
|
72
|
+
onSuccess: (newHub, variables, context) => {
|
|
73
|
+
// Invalidate all hub lists to refetch with the new hub
|
|
74
|
+
queryClient.invalidateQueries({ queryKey: hubKeys.lists() });
|
|
75
|
+
// Invalidate my hubs list
|
|
76
|
+
queryClient.invalidateQueries({ queryKey: hubKeys.myHubs() });
|
|
77
|
+
// Set the new hub in the cache
|
|
78
|
+
queryClient.setQueryData(hubKeys.detail(newHub.id), newHub);
|
|
79
|
+
|
|
80
|
+
// Call user's onSuccess if provided
|
|
81
|
+
},
|
|
82
|
+
...options,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Update an existing hub
|
|
88
|
+
*
|
|
89
|
+
* @param options - React Query mutation options
|
|
90
|
+
* @returns Mutation result
|
|
91
|
+
*/
|
|
92
|
+
export function useUpdateHub(
|
|
93
|
+
options?: Omit<
|
|
94
|
+
UseMutationOptions<HubResponse, Error, { id: string; data: UpdateHubRequest }>,
|
|
95
|
+
'mutationFn'
|
|
96
|
+
>
|
|
97
|
+
): UseMutationResult<HubResponse, Error, { id: string; data: UpdateHubRequest }> {
|
|
98
|
+
const queryClient = useQueryClient();
|
|
99
|
+
|
|
100
|
+
return useMutation({
|
|
101
|
+
mutationFn: async ({
|
|
102
|
+
id,
|
|
103
|
+
data,
|
|
104
|
+
}: {
|
|
105
|
+
id: string;
|
|
106
|
+
data: UpdateHubRequest;
|
|
107
|
+
}): Promise<HubResponse> => {
|
|
108
|
+
const client = getApiClient();
|
|
109
|
+
const response = await client.put(`/api/v1/hubs/${id}`, data);
|
|
110
|
+
return response.data;
|
|
111
|
+
},
|
|
112
|
+
onSuccess: (updatedHub, variables, context) => {
|
|
113
|
+
// Update the hub in the cache
|
|
114
|
+
queryClient.setQueryData(hubKeys.detail(updatedHub.id), updatedHub);
|
|
115
|
+
// Invalidate hub lists to refetch with updated data
|
|
116
|
+
queryClient.invalidateQueries({ queryKey: hubKeys.lists() });
|
|
117
|
+
// Invalidate my hubs list
|
|
118
|
+
queryClient.invalidateQueries({ queryKey: hubKeys.myHubs() });
|
|
119
|
+
// Invalidate slug-based query since slug might have changed
|
|
120
|
+
queryClient.invalidateQueries({
|
|
121
|
+
queryKey: hubKeys.bySlug(updatedHub.slug)
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Call user's onSuccess if provided
|
|
125
|
+
},
|
|
126
|
+
...options,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Delete a hub
|
|
132
|
+
*
|
|
133
|
+
* @param options - React Query mutation options
|
|
134
|
+
* @returns Mutation result
|
|
135
|
+
*/
|
|
136
|
+
export function useDeleteHub(
|
|
137
|
+
options?: Omit<UseMutationOptions<void, Error, string>, 'mutationFn'>
|
|
138
|
+
): UseMutationResult<void, Error, string> {
|
|
139
|
+
const queryClient = useQueryClient();
|
|
140
|
+
|
|
141
|
+
return useMutation({
|
|
142
|
+
mutationFn: async (id: string): Promise<void> => {
|
|
143
|
+
const client = getApiClient();
|
|
144
|
+
await client.delete(`/api/v1/hubs/${id}`);
|
|
145
|
+
},
|
|
146
|
+
onSuccess: (data, id, context) => {
|
|
147
|
+
// Remove the hub from the cache
|
|
148
|
+
queryClient.removeQueries({ queryKey: hubKeys.detail(id) });
|
|
149
|
+
// Invalidate all hub lists to refetch without the deleted hub
|
|
150
|
+
queryClient.invalidateQueries({ queryKey: hubKeys.lists() });
|
|
151
|
+
// Invalidate my hubs list
|
|
152
|
+
queryClient.invalidateQueries({ queryKey: hubKeys.myHubs() });
|
|
153
|
+
|
|
154
|
+
// Call user's onSuccess if provided
|
|
155
|
+
// User's onSuccess is handled by spreading options
|
|
156
|
+
},
|
|
157
|
+
...options,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Join a hub
|
|
163
|
+
*
|
|
164
|
+
* @param options - React Query mutation options
|
|
165
|
+
* @returns Mutation result
|
|
166
|
+
*/
|
|
167
|
+
export function useJoinHub(
|
|
168
|
+
options?: Omit<UseMutationOptions<JoinHubResponse, Error, string>, 'mutationFn'>
|
|
169
|
+
): UseMutationResult<JoinHubResponse, Error, string> {
|
|
170
|
+
const queryClient = useQueryClient();
|
|
171
|
+
|
|
172
|
+
return useMutation({
|
|
173
|
+
mutationFn: async (id: string): Promise<JoinHubResponse> => {
|
|
174
|
+
const client = getApiClient();
|
|
175
|
+
const response = await client.post(`/api/v1/hubs/${id}/join`);
|
|
176
|
+
return response.data;
|
|
177
|
+
},
|
|
178
|
+
onSuccess: (data, id, context) => {
|
|
179
|
+
// Invalidate membership status for this hub
|
|
180
|
+
queryClient.invalidateQueries({ queryKey: hubKeys.membership(id) });
|
|
181
|
+
// Invalidate my hubs list
|
|
182
|
+
queryClient.invalidateQueries({ queryKey: hubKeys.myHubs() });
|
|
183
|
+
// Invalidate hub members list
|
|
184
|
+
queryClient.invalidateQueries({ queryKey: hubKeys.members(id) });
|
|
185
|
+
// Refetch hub details to update member count
|
|
186
|
+
queryClient.invalidateQueries({ queryKey: hubKeys.detail(id) });
|
|
187
|
+
|
|
188
|
+
// Call user's onSuccess if provided
|
|
189
|
+
// User's onSuccess is handled by spreading options
|
|
190
|
+
},
|
|
191
|
+
...options,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Leave a hub
|
|
197
|
+
*
|
|
198
|
+
* @param options - React Query mutation options
|
|
199
|
+
* @returns Mutation result
|
|
200
|
+
*/
|
|
201
|
+
export function useLeaveHub(
|
|
202
|
+
options?: Omit<UseMutationOptions<LeaveHubResponse, Error, string>, 'mutationFn'>
|
|
203
|
+
): UseMutationResult<LeaveHubResponse, Error, string> {
|
|
204
|
+
const queryClient = useQueryClient();
|
|
205
|
+
|
|
206
|
+
return useMutation({
|
|
207
|
+
mutationFn: async (id: string): Promise<LeaveHubResponse> => {
|
|
208
|
+
const client = getApiClient();
|
|
209
|
+
const response = await client.post(`/api/v1/hubs/${id}/leave`);
|
|
210
|
+
return response.data;
|
|
211
|
+
},
|
|
212
|
+
onSuccess: (data, id, context) => {
|
|
213
|
+
// Invalidate membership status for this hub
|
|
214
|
+
queryClient.invalidateQueries({ queryKey: hubKeys.membership(id) });
|
|
215
|
+
// Invalidate my hubs list
|
|
216
|
+
queryClient.invalidateQueries({ queryKey: hubKeys.myHubs() });
|
|
217
|
+
// Invalidate hub members list
|
|
218
|
+
queryClient.invalidateQueries({ queryKey: hubKeys.members(id) });
|
|
219
|
+
// Refetch hub details to update member count
|
|
220
|
+
queryClient.invalidateQueries({ queryKey: hubKeys.detail(id) });
|
|
221
|
+
|
|
222
|
+
// Call user's onSuccess if provided
|
|
223
|
+
// User's onSuccess is handled by spreading options
|
|
224
|
+
},
|
|
225
|
+
...options,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Approve a pending member
|
|
231
|
+
*
|
|
232
|
+
* @param options - React Query mutation options
|
|
233
|
+
* @returns Mutation result
|
|
234
|
+
*/
|
|
235
|
+
export function useApproveMember(
|
|
236
|
+
options?: Omit<
|
|
237
|
+
UseMutationOptions<
|
|
238
|
+
ApproveMemberResponse,
|
|
239
|
+
Error,
|
|
240
|
+
{ hubId: string; memberId: string }
|
|
241
|
+
>,
|
|
242
|
+
'mutationFn'
|
|
243
|
+
>
|
|
244
|
+
): UseMutationResult<
|
|
245
|
+
ApproveMemberResponse,
|
|
246
|
+
Error,
|
|
247
|
+
{ hubId: string; memberId: string }
|
|
248
|
+
> {
|
|
249
|
+
const queryClient = useQueryClient();
|
|
250
|
+
|
|
251
|
+
return useMutation({
|
|
252
|
+
mutationFn: async ({
|
|
253
|
+
hubId,
|
|
254
|
+
memberId,
|
|
255
|
+
}: {
|
|
256
|
+
hubId: string;
|
|
257
|
+
memberId: string;
|
|
258
|
+
}): Promise<ApproveMemberResponse> => {
|
|
259
|
+
const client = getApiClient();
|
|
260
|
+
const response = await client.post(
|
|
261
|
+
`/api/v1/hubs/${hubId}/members/${memberId}/approve`
|
|
262
|
+
);
|
|
263
|
+
return response.data;
|
|
264
|
+
},
|
|
265
|
+
onSuccess: (data, variables, context) => {
|
|
266
|
+
// Invalidate hub members list to refetch with updated status
|
|
267
|
+
queryClient.invalidateQueries({
|
|
268
|
+
queryKey: hubKeys.members(variables.hubId)
|
|
269
|
+
});
|
|
270
|
+
// Refetch hub details to update member count
|
|
271
|
+
queryClient.invalidateQueries({
|
|
272
|
+
queryKey: hubKeys.detail(variables.hubId)
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// Call user's onSuccess if provided
|
|
276
|
+
// User's onSuccess is handled by spreading options
|
|
277
|
+
},
|
|
278
|
+
...options,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Update a member's role
|
|
284
|
+
*
|
|
285
|
+
* @param options - React Query mutation options
|
|
286
|
+
* @returns Mutation result
|
|
287
|
+
*/
|
|
288
|
+
export function useUpdateMemberRole(
|
|
289
|
+
options?: Omit<
|
|
290
|
+
UseMutationOptions<
|
|
291
|
+
UpdateMemberRoleResponse,
|
|
292
|
+
Error,
|
|
293
|
+
{ hubId: string; memberId: string; data: UpdateMemberRoleRequest }
|
|
294
|
+
>,
|
|
295
|
+
'mutationFn'
|
|
296
|
+
>
|
|
297
|
+
): UseMutationResult<
|
|
298
|
+
UpdateMemberRoleResponse,
|
|
299
|
+
Error,
|
|
300
|
+
{ hubId: string; memberId: string; data: UpdateMemberRoleRequest }
|
|
301
|
+
> {
|
|
302
|
+
const queryClient = useQueryClient();
|
|
303
|
+
|
|
304
|
+
return useMutation({
|
|
305
|
+
mutationFn: async ({
|
|
306
|
+
hubId,
|
|
307
|
+
memberId,
|
|
308
|
+
data,
|
|
309
|
+
}: {
|
|
310
|
+
hubId: string;
|
|
311
|
+
memberId: string;
|
|
312
|
+
data: UpdateMemberRoleRequest;
|
|
313
|
+
}): Promise<UpdateMemberRoleResponse> => {
|
|
314
|
+
const client = getApiClient();
|
|
315
|
+
const response = await client.put(
|
|
316
|
+
`/api/v1/hubs/${hubId}/members/${memberId}/role`,
|
|
317
|
+
data
|
|
318
|
+
);
|
|
319
|
+
return response.data;
|
|
320
|
+
},
|
|
321
|
+
onSuccess: (data, variables, context) => {
|
|
322
|
+
// Invalidate hub members list to refetch with updated role
|
|
323
|
+
queryClient.invalidateQueries({
|
|
324
|
+
queryKey: hubKeys.members(variables.hubId)
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
// Call user's onSuccess if provided
|
|
328
|
+
// User's onSuccess is handled by spreading options
|
|
329
|
+
},
|
|
330
|
+
...options,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Remove a member from a hub
|
|
336
|
+
*
|
|
337
|
+
* @param options - React Query mutation options
|
|
338
|
+
* @returns Mutation result
|
|
339
|
+
*/
|
|
340
|
+
export function useRemoveMember(
|
|
341
|
+
options?: Omit<
|
|
342
|
+
UseMutationOptions<
|
|
343
|
+
RemoveMemberResponse,
|
|
344
|
+
Error,
|
|
345
|
+
{ hubId: string; memberId: string }
|
|
346
|
+
>,
|
|
347
|
+
'mutationFn'
|
|
348
|
+
>
|
|
349
|
+
): UseMutationResult<
|
|
350
|
+
RemoveMemberResponse,
|
|
351
|
+
Error,
|
|
352
|
+
{ hubId: string; memberId: string }
|
|
353
|
+
> {
|
|
354
|
+
const queryClient = useQueryClient();
|
|
355
|
+
|
|
356
|
+
return useMutation({
|
|
357
|
+
mutationFn: async ({
|
|
358
|
+
hubId,
|
|
359
|
+
memberId,
|
|
360
|
+
}: {
|
|
361
|
+
hubId: string;
|
|
362
|
+
memberId: string;
|
|
363
|
+
}): Promise<RemoveMemberResponse> => {
|
|
364
|
+
const client = getApiClient();
|
|
365
|
+
const response = await client.delete(
|
|
366
|
+
`/api/v1/hubs/${hubId}/members/${memberId}`
|
|
367
|
+
);
|
|
368
|
+
return response.data;
|
|
369
|
+
},
|
|
370
|
+
onSuccess: (data, variables, context) => {
|
|
371
|
+
// Invalidate hub members list to refetch without removed member
|
|
372
|
+
queryClient.invalidateQueries({
|
|
373
|
+
queryKey: hubKeys.members(variables.hubId)
|
|
374
|
+
});
|
|
375
|
+
// Refetch hub details to update member count
|
|
376
|
+
queryClient.invalidateQueries({
|
|
377
|
+
queryKey: hubKeys.detail(variables.hubId)
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
// Call user's onSuccess if provided
|
|
381
|
+
// User's onSuccess is handled by spreading options
|
|
382
|
+
},
|
|
383
|
+
...options,
|
|
384
|
+
});
|
|
385
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mutation Hooks
|
|
3
|
+
*
|
|
4
|
+
* Re-exports all mutation hooks for API endpoints.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export * from './admin';
|
|
8
|
+
export * from './auth';
|
|
9
|
+
export * from './bookings';
|
|
10
|
+
export * from './events';
|
|
11
|
+
export * from './hubs';
|
|
12
|
+
export * from './library';
|
|
13
|
+
export * from './map';
|
|
14
|
+
export * from './notifications';
|
|
15
|
+
export * from './offers';
|
|
16
|
+
export * from './subscriptions';
|
|
17
|
+
export * from './support';
|
|
18
|
+
export * from './users';
|
|
19
|
+
export * from './jack';
|
|
20
|
+
export * from './ambassadors';
|
|
21
|
+
export * from './grow90';
|
|
22
|
+
export * from './matching';
|
|
23
|
+
export * from './event-chat';
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { useMutation, useQueryClient, UseMutationOptions } from '@tanstack/react-query';
|
|
2
|
+
import { getApiClient } from '../client';
|
|
3
|
+
import { jackKeys } from '../queries/jack';
|
|
4
|
+
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// TYPES
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
export interface ChatRequest {
|
|
10
|
+
message: string;
|
|
11
|
+
conversationId?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface ChatResponse {
|
|
15
|
+
message: string;
|
|
16
|
+
conversationId: string;
|
|
17
|
+
messageId: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface NewConversationResponse {
|
|
21
|
+
conversationId: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// MUTATION HOOKS
|
|
26
|
+
// ============================================================================
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Send a message to Jack and get a response
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* const chatMutation = useChatWithJack();
|
|
34
|
+
*
|
|
35
|
+
* const handleSend = async (message: string) => {
|
|
36
|
+
* const response = await chatMutation.mutateAsync({
|
|
37
|
+
* message,
|
|
38
|
+
* conversationId: currentConversationId, // optional
|
|
39
|
+
* });
|
|
40
|
+
* console.log('Jack says:', response.message);
|
|
41
|
+
* };
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export function useChatWithJack(
|
|
45
|
+
options?: Omit<UseMutationOptions<ChatResponse, Error, ChatRequest>, 'mutationFn'>
|
|
46
|
+
) {
|
|
47
|
+
const queryClient = useQueryClient();
|
|
48
|
+
|
|
49
|
+
return useMutation({
|
|
50
|
+
mutationFn: async (data: ChatRequest): Promise<ChatResponse> => {
|
|
51
|
+
const client = getApiClient();
|
|
52
|
+
const response = await client.post('/api/v1/support/jack/chat', data);
|
|
53
|
+
// API wraps response in { data: {...}, meta: {...} }
|
|
54
|
+
return response.data?.data || response.data;
|
|
55
|
+
},
|
|
56
|
+
onSuccess: (data) => {
|
|
57
|
+
// Invalidate conversation queries to refresh the list
|
|
58
|
+
queryClient.invalidateQueries({ queryKey: jackKeys.conversations() });
|
|
59
|
+
queryClient.invalidateQueries({ queryKey: jackKeys.history() });
|
|
60
|
+
if (data.conversationId) {
|
|
61
|
+
queryClient.invalidateQueries({ queryKey: jackKeys.conversation(data.conversationId) });
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
...options,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Start a new conversation with Jack
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```tsx
|
|
73
|
+
* const newConversation = useStartJackConversation();
|
|
74
|
+
*
|
|
75
|
+
* const handleNewChat = async () => {
|
|
76
|
+
* const { conversationId } = await newConversation.mutateAsync();
|
|
77
|
+
* setCurrentConversationId(conversationId);
|
|
78
|
+
* };
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export function useStartJackConversation(
|
|
82
|
+
options?: Omit<UseMutationOptions<NewConversationResponse, Error, void>, 'mutationFn'>
|
|
83
|
+
) {
|
|
84
|
+
const queryClient = useQueryClient();
|
|
85
|
+
|
|
86
|
+
return useMutation({
|
|
87
|
+
mutationFn: async (): Promise<NewConversationResponse> => {
|
|
88
|
+
const client = getApiClient();
|
|
89
|
+
const response = await client.post('/api/v1/support/jack/conversations/new');
|
|
90
|
+
// API wraps response in { data: {...}, meta: {...} }
|
|
91
|
+
return response.data?.data || response.data;
|
|
92
|
+
},
|
|
93
|
+
onSuccess: () => {
|
|
94
|
+
queryClient.invalidateQueries({ queryKey: jackKeys.conversations() });
|
|
95
|
+
},
|
|
96
|
+
...options,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Archive a conversation with Jack
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```tsx
|
|
105
|
+
* const archiveConversation = useArchiveJackConversation();
|
|
106
|
+
*
|
|
107
|
+
* const handleArchive = async (conversationId: string) => {
|
|
108
|
+
* await archiveConversation.mutateAsync(conversationId);
|
|
109
|
+
* };
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export function useArchiveJackConversation(
|
|
113
|
+
options?: Omit<UseMutationOptions<{ success: boolean }, Error, string>, 'mutationFn'>
|
|
114
|
+
) {
|
|
115
|
+
const queryClient = useQueryClient();
|
|
116
|
+
|
|
117
|
+
return useMutation({
|
|
118
|
+
mutationFn: async (conversationId: string): Promise<{ success: boolean }> => {
|
|
119
|
+
const client = getApiClient();
|
|
120
|
+
const response = await client.delete(`/api/v1/support/jack/conversations/${conversationId}`);
|
|
121
|
+
// API wraps response in { data: {...}, meta: {...} }
|
|
122
|
+
return response.data?.data || response.data;
|
|
123
|
+
},
|
|
124
|
+
onSuccess: () => {
|
|
125
|
+
queryClient.invalidateQueries({ queryKey: jackKeys.conversations() });
|
|
126
|
+
queryClient.invalidateQueries({ queryKey: jackKeys.history() });
|
|
127
|
+
},
|
|
128
|
+
...options,
|
|
129
|
+
});
|
|
130
|
+
}
|