@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,212 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useMutation,
|
|
3
|
+
useQueryClient,
|
|
4
|
+
UseMutationOptions,
|
|
5
|
+
UseMutationResult,
|
|
6
|
+
} from '@tanstack/react-query';
|
|
7
|
+
import { getApiClient } from '../client';
|
|
8
|
+
import type { LibraryProgressResponse } from '../types';
|
|
9
|
+
import { libraryKeys } from '../queries/library';
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// MUTATION HOOKS
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Mark a library item as viewed
|
|
17
|
+
*
|
|
18
|
+
* @param options - TanStack Query mutation options
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const { mutate, isPending } = useMarkViewed();
|
|
23
|
+
*
|
|
24
|
+
* mutate('lib-123');
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function useMarkViewed(
|
|
28
|
+
options?: Omit<
|
|
29
|
+
UseMutationOptions<LibraryProgressResponse, Error, string>,
|
|
30
|
+
'mutationFn'
|
|
31
|
+
>
|
|
32
|
+
): UseMutationResult<LibraryProgressResponse, Error, string> {
|
|
33
|
+
const queryClient = useQueryClient();
|
|
34
|
+
|
|
35
|
+
return useMutation({
|
|
36
|
+
mutationFn: async (id: string): Promise<LibraryProgressResponse> => {
|
|
37
|
+
const client = getApiClient();
|
|
38
|
+
const response = await client.post(`/api/v1/library/${id}/view`);
|
|
39
|
+
return response.data;
|
|
40
|
+
},
|
|
41
|
+
onSuccess: (data, id, context) => {
|
|
42
|
+
// Invalidate the specific item to reflect updated view status
|
|
43
|
+
queryClient.invalidateQueries({ queryKey: libraryKeys.detail(id) });
|
|
44
|
+
|
|
45
|
+
// Invalidate lists to update view counts
|
|
46
|
+
queryClient.invalidateQueries({ queryKey: libraryKeys.lists() });
|
|
47
|
+
|
|
48
|
+
// Call user's onSuccess if provided
|
|
49
|
+
// User's onSuccess is handled by spreading options
|
|
50
|
+
},
|
|
51
|
+
...options,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Mark a library item as completed
|
|
57
|
+
*
|
|
58
|
+
* @param options - TanStack Query mutation options
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```tsx
|
|
62
|
+
* const { mutate, isPending } = useMarkCompleted();
|
|
63
|
+
*
|
|
64
|
+
* mutate('lib-123');
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export function useMarkCompleted(
|
|
68
|
+
options?: Omit<
|
|
69
|
+
UseMutationOptions<LibraryProgressResponse, Error, string>,
|
|
70
|
+
'mutationFn'
|
|
71
|
+
>
|
|
72
|
+
): UseMutationResult<LibraryProgressResponse, Error, string> {
|
|
73
|
+
const queryClient = useQueryClient();
|
|
74
|
+
|
|
75
|
+
return useMutation({
|
|
76
|
+
mutationFn: async (id: string): Promise<LibraryProgressResponse> => {
|
|
77
|
+
const client = getApiClient();
|
|
78
|
+
const response = await client.post(`/api/v1/library/${id}/complete`);
|
|
79
|
+
return response.data;
|
|
80
|
+
},
|
|
81
|
+
onSuccess: (data, id, context) => {
|
|
82
|
+
// Invalidate the specific item to reflect completion status
|
|
83
|
+
queryClient.invalidateQueries({ queryKey: libraryKeys.detail(id) });
|
|
84
|
+
|
|
85
|
+
// Invalidate lists
|
|
86
|
+
queryClient.invalidateQueries({ queryKey: libraryKeys.lists() });
|
|
87
|
+
|
|
88
|
+
// Call user's onSuccess if provided
|
|
89
|
+
// User's onSuccess is handled by spreading options
|
|
90
|
+
},
|
|
91
|
+
...options,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Toggle like status for a library item
|
|
97
|
+
*
|
|
98
|
+
* @param options - TanStack Query mutation options
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```tsx
|
|
102
|
+
* const { mutate, isPending } = useToggleLike();
|
|
103
|
+
*
|
|
104
|
+
* mutate('lib-123');
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export function useToggleLike(
|
|
108
|
+
options?: Omit<
|
|
109
|
+
UseMutationOptions<LibraryProgressResponse, Error, string>,
|
|
110
|
+
'mutationFn'
|
|
111
|
+
>
|
|
112
|
+
): UseMutationResult<LibraryProgressResponse, Error, string> {
|
|
113
|
+
const queryClient = useQueryClient();
|
|
114
|
+
|
|
115
|
+
return useMutation({
|
|
116
|
+
mutationFn: async (id: string): Promise<LibraryProgressResponse> => {
|
|
117
|
+
const client = getApiClient();
|
|
118
|
+
const response = await client.post(`/api/v1/library/${id}/like`);
|
|
119
|
+
return response.data;
|
|
120
|
+
},
|
|
121
|
+
onSuccess: (data, id, context) => {
|
|
122
|
+
// Invalidate the specific item to reflect like status
|
|
123
|
+
queryClient.invalidateQueries({ queryKey: libraryKeys.detail(id) });
|
|
124
|
+
|
|
125
|
+
// Invalidate lists to update like counts
|
|
126
|
+
queryClient.invalidateQueries({ queryKey: libraryKeys.lists() });
|
|
127
|
+
|
|
128
|
+
// Call user's onSuccess if provided
|
|
129
|
+
// User's onSuccess is handled by spreading options
|
|
130
|
+
},
|
|
131
|
+
...options,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Add a bookmark to a library item
|
|
137
|
+
*
|
|
138
|
+
* @param options - TanStack Query mutation options
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```tsx
|
|
142
|
+
* const { mutate, isPending } = useAddBookmark();
|
|
143
|
+
*
|
|
144
|
+
* mutate('lib-123');
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
export function useAddBookmark(
|
|
148
|
+
options?: Omit<
|
|
149
|
+
UseMutationOptions<LibraryProgressResponse, Error, string>,
|
|
150
|
+
'mutationFn'
|
|
151
|
+
>
|
|
152
|
+
): UseMutationResult<LibraryProgressResponse, Error, string> {
|
|
153
|
+
const queryClient = useQueryClient();
|
|
154
|
+
|
|
155
|
+
return useMutation({
|
|
156
|
+
mutationFn: async (id: string): Promise<LibraryProgressResponse> => {
|
|
157
|
+
const client = getApiClient();
|
|
158
|
+
const response = await client.post(`/api/v1/library/${id}/bookmark`);
|
|
159
|
+
return response.data;
|
|
160
|
+
},
|
|
161
|
+
onSuccess: (data, id, context) => {
|
|
162
|
+
// Invalidate the specific item to reflect bookmark status
|
|
163
|
+
queryClient.invalidateQueries({ queryKey: libraryKeys.detail(id) });
|
|
164
|
+
|
|
165
|
+
// Invalidate lists
|
|
166
|
+
queryClient.invalidateQueries({ queryKey: libraryKeys.lists() });
|
|
167
|
+
|
|
168
|
+
// Call user's onSuccess if provided
|
|
169
|
+
// User's onSuccess is handled by spreading options
|
|
170
|
+
},
|
|
171
|
+
...options,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Remove a bookmark from a library item
|
|
177
|
+
*
|
|
178
|
+
* @param options - TanStack Query mutation options
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```tsx
|
|
182
|
+
* const { mutate, isPending } = useRemoveBookmark();
|
|
183
|
+
*
|
|
184
|
+
* mutate('lib-123');
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
export function useRemoveBookmark(
|
|
188
|
+
options?: Omit<
|
|
189
|
+
UseMutationOptions<void, Error, string>,
|
|
190
|
+
'mutationFn'
|
|
191
|
+
>
|
|
192
|
+
): UseMutationResult<void, Error, string> {
|
|
193
|
+
const queryClient = useQueryClient();
|
|
194
|
+
|
|
195
|
+
return useMutation({
|
|
196
|
+
mutationFn: async (id: string): Promise<void> => {
|
|
197
|
+
const client = getApiClient();
|
|
198
|
+
await client.delete(`/api/v1/library/${id}/bookmark`);
|
|
199
|
+
},
|
|
200
|
+
onSuccess: (data, id, context) => {
|
|
201
|
+
// Invalidate the specific item to reflect bookmark removal
|
|
202
|
+
queryClient.invalidateQueries({ queryKey: libraryKeys.detail(id) });
|
|
203
|
+
|
|
204
|
+
// Invalidate lists
|
|
205
|
+
queryClient.invalidateQueries({ queryKey: libraryKeys.lists() });
|
|
206
|
+
|
|
207
|
+
// Call user's onSuccess if provided
|
|
208
|
+
// User's onSuccess is handled by spreading options
|
|
209
|
+
},
|
|
210
|
+
...options,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map Mutation Hooks
|
|
3
|
+
*
|
|
4
|
+
* TanStack Query mutation hooks for map-related write operations.
|
|
5
|
+
* These hooks handle updating user location and visibility settings.
|
|
6
|
+
*
|
|
7
|
+
* @module api/mutations/map
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
useMutation,
|
|
12
|
+
UseMutationOptions,
|
|
13
|
+
UseMutationResult,
|
|
14
|
+
useQueryClient,
|
|
15
|
+
} from '@tanstack/react-query';
|
|
16
|
+
import { getApiClient } from '../client';
|
|
17
|
+
import { mapKeys } from '../queries/map';
|
|
18
|
+
import { userKeys } from '../queries/users';
|
|
19
|
+
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// REQUEST TYPES
|
|
22
|
+
// ============================================================================
|
|
23
|
+
|
|
24
|
+
export interface UpdateLocationRequest {
|
|
25
|
+
lat: number;
|
|
26
|
+
lng: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface UpdateOpenToMeetRequest {
|
|
30
|
+
openToMeet: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// RESPONSE TYPES
|
|
35
|
+
// ============================================================================
|
|
36
|
+
|
|
37
|
+
export interface LocationUpdateResponse {
|
|
38
|
+
success: boolean;
|
|
39
|
+
message: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface OpenToMeetResponse {
|
|
43
|
+
openToMeet: boolean;
|
|
44
|
+
message: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// MUTATION HOOKS
|
|
49
|
+
// ============================================================================
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Update current user's location
|
|
53
|
+
*
|
|
54
|
+
* @description
|
|
55
|
+
* Updates the authenticated user's location for display on the member map.
|
|
56
|
+
* Location is only visible to other users if the user has enabled "open to meet".
|
|
57
|
+
*
|
|
58
|
+
* @endpoint PUT /api/v1/map/location
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```tsx
|
|
62
|
+
* import { useUpdateLocation } from '@growsober/sdk';
|
|
63
|
+
*
|
|
64
|
+
* function LocationUpdater() {
|
|
65
|
+
* const updateLocation = useUpdateLocation();
|
|
66
|
+
*
|
|
67
|
+
* const handleLocationUpdate = async () => {
|
|
68
|
+
* // Get current position from device
|
|
69
|
+
* navigator.geolocation.getCurrentPosition(
|
|
70
|
+
* async (position) => {
|
|
71
|
+
* await updateLocation.mutateAsync({
|
|
72
|
+
* lat: position.coords.latitude,
|
|
73
|
+
* lng: position.coords.longitude,
|
|
74
|
+
* });
|
|
75
|
+
* },
|
|
76
|
+
* (error) => console.error('Location error:', error)
|
|
77
|
+
* );
|
|
78
|
+
* };
|
|
79
|
+
*
|
|
80
|
+
* return (
|
|
81
|
+
* <button onClick={handleLocationUpdate} disabled={updateLocation.isPending}>
|
|
82
|
+
* Update My Location
|
|
83
|
+
* </button>
|
|
84
|
+
* );
|
|
85
|
+
* }
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* With Expo Location:
|
|
90
|
+
* ```tsx
|
|
91
|
+
* import * as Location from 'expo-location';
|
|
92
|
+
* import { useUpdateLocation } from '@growsober/sdk';
|
|
93
|
+
*
|
|
94
|
+
* function App() {
|
|
95
|
+
* const updateLocation = useUpdateLocation();
|
|
96
|
+
*
|
|
97
|
+
* useEffect(() => {
|
|
98
|
+
* (async () => {
|
|
99
|
+
* const { status } = await Location.requestForegroundPermissionsAsync();
|
|
100
|
+
* if (status === 'granted') {
|
|
101
|
+
* const location = await Location.getCurrentPositionAsync({});
|
|
102
|
+
* updateLocation.mutate({
|
|
103
|
+
* lat: location.coords.latitude,
|
|
104
|
+
* lng: location.coords.longitude,
|
|
105
|
+
* });
|
|
106
|
+
* }
|
|
107
|
+
* })();
|
|
108
|
+
* }, []);
|
|
109
|
+
* }
|
|
110
|
+
* ```
|
|
111
|
+
*
|
|
112
|
+
* @param options - TanStack Query mutation options
|
|
113
|
+
* @returns TanStack Query mutation result
|
|
114
|
+
*/
|
|
115
|
+
export function useUpdateLocation(
|
|
116
|
+
options?: Omit<
|
|
117
|
+
UseMutationOptions<LocationUpdateResponse, Error, UpdateLocationRequest>,
|
|
118
|
+
'mutationFn'
|
|
119
|
+
>
|
|
120
|
+
): UseMutationResult<LocationUpdateResponse, Error, UpdateLocationRequest> {
|
|
121
|
+
const queryClient = useQueryClient();
|
|
122
|
+
|
|
123
|
+
return useMutation({
|
|
124
|
+
mutationFn: async (data: UpdateLocationRequest): Promise<LocationUpdateResponse> => {
|
|
125
|
+
const client = getApiClient();
|
|
126
|
+
const response = await client.put<LocationUpdateResponse>(
|
|
127
|
+
'/api/v1/map/location',
|
|
128
|
+
data
|
|
129
|
+
);
|
|
130
|
+
return response.data;
|
|
131
|
+
},
|
|
132
|
+
onSuccess: () => {
|
|
133
|
+
// Invalidate map queries to reflect new location
|
|
134
|
+
queryClient.invalidateQueries({ queryKey: mapKeys.members() });
|
|
135
|
+
// Also invalidate user data as location is stored on user
|
|
136
|
+
queryClient.invalidateQueries({ queryKey: userKeys.me() });
|
|
137
|
+
},
|
|
138
|
+
...options,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Toggle "open to meet" status
|
|
144
|
+
*
|
|
145
|
+
* @description
|
|
146
|
+
* Updates the user's "open to meet" visibility setting.
|
|
147
|
+
* When enabled, the user's location will be visible to other premium members on the map.
|
|
148
|
+
* Premium feature.
|
|
149
|
+
*
|
|
150
|
+
* @endpoint PUT /api/v1/map/open-to-meet
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```tsx
|
|
154
|
+
* import { useUpdateOpenToMeet } from '@growsober/sdk';
|
|
155
|
+
*
|
|
156
|
+
* function OpenToMeetToggle() {
|
|
157
|
+
* const updateOpenToMeet = useUpdateOpenToMeet();
|
|
158
|
+
* const [isOpen, setIsOpen] = useState(false);
|
|
159
|
+
*
|
|
160
|
+
* const handleToggle = async () => {
|
|
161
|
+
* const newValue = !isOpen;
|
|
162
|
+
* await updateOpenToMeet.mutateAsync({ openToMeet: newValue });
|
|
163
|
+
* setIsOpen(newValue);
|
|
164
|
+
* };
|
|
165
|
+
*
|
|
166
|
+
* return (
|
|
167
|
+
* <Switch
|
|
168
|
+
* checked={isOpen}
|
|
169
|
+
* onChange={handleToggle}
|
|
170
|
+
* disabled={updateOpenToMeet.isPending}
|
|
171
|
+
* />
|
|
172
|
+
* );
|
|
173
|
+
* }
|
|
174
|
+
* ```
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* With user state:
|
|
178
|
+
* ```tsx
|
|
179
|
+
* import { useCurrentUser, useUpdateOpenToMeet } from '@growsober/sdk';
|
|
180
|
+
*
|
|
181
|
+
* function OpenToMeetSetting() {
|
|
182
|
+
* const { data: user } = useCurrentUser();
|
|
183
|
+
* const updateOpenToMeet = useUpdateOpenToMeet({
|
|
184
|
+
* onSuccess: (data) => {
|
|
185
|
+
* console.log(data.openToMeet ? 'Now visible on map!' : 'Hidden from map');
|
|
186
|
+
* },
|
|
187
|
+
* });
|
|
188
|
+
*
|
|
189
|
+
* return (
|
|
190
|
+
* <div>
|
|
191
|
+
* <label>Open to Meet</label>
|
|
192
|
+
* <Switch
|
|
193
|
+
* checked={user?.openToMeet}
|
|
194
|
+
* onChange={(checked) => updateOpenToMeet.mutate({ openToMeet: checked })}
|
|
195
|
+
* />
|
|
196
|
+
* <p>Show your location to other members</p>
|
|
197
|
+
* </div>
|
|
198
|
+
* );
|
|
199
|
+
* }
|
|
200
|
+
* ```
|
|
201
|
+
*
|
|
202
|
+
* @param options - TanStack Query mutation options
|
|
203
|
+
* @returns TanStack Query mutation result
|
|
204
|
+
*/
|
|
205
|
+
export function useUpdateOpenToMeet(
|
|
206
|
+
options?: Omit<
|
|
207
|
+
UseMutationOptions<OpenToMeetResponse, Error, UpdateOpenToMeetRequest>,
|
|
208
|
+
'mutationFn'
|
|
209
|
+
>
|
|
210
|
+
): UseMutationResult<OpenToMeetResponse, Error, UpdateOpenToMeetRequest> {
|
|
211
|
+
const queryClient = useQueryClient();
|
|
212
|
+
|
|
213
|
+
return useMutation({
|
|
214
|
+
mutationFn: async (data: UpdateOpenToMeetRequest): Promise<OpenToMeetResponse> => {
|
|
215
|
+
const client = getApiClient();
|
|
216
|
+
const response = await client.put<OpenToMeetResponse>(
|
|
217
|
+
'/api/v1/map/open-to-meet',
|
|
218
|
+
data
|
|
219
|
+
);
|
|
220
|
+
return response.data;
|
|
221
|
+
},
|
|
222
|
+
onSuccess: () => {
|
|
223
|
+
// Invalidate user data to reflect new setting
|
|
224
|
+
queryClient.invalidateQueries({ queryKey: userKeys.me() });
|
|
225
|
+
// Invalidate map queries as visibility has changed
|
|
226
|
+
queryClient.invalidateQueries({ queryKey: mapKeys.members() });
|
|
227
|
+
},
|
|
228
|
+
...options,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useMutation,
|
|
3
|
+
useQueryClient,
|
|
4
|
+
UseMutationOptions,
|
|
5
|
+
UseMutationResult,
|
|
6
|
+
} from '@tanstack/react-query';
|
|
7
|
+
import { getApiClient } from '../client';
|
|
8
|
+
import { matchingKeys, MatchResponse, BuddyResponse } from '../queries/matching';
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// REQUEST TYPES
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
export interface CreateMatchRequest {
|
|
15
|
+
matchedUserId: string;
|
|
16
|
+
message?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface UpdateMatchRequest {
|
|
20
|
+
status: 'ACCEPTED' | 'DECLINED' | 'BLOCKED';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface CreateBuddyRequest {
|
|
24
|
+
buddyId: string;
|
|
25
|
+
message?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface UpdateBuddyRequest {
|
|
29
|
+
status: 'ACCEPTED' | 'DECLINED' | 'ENDED';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface LogBuddyActivityRequest {
|
|
33
|
+
type: 'CHECK_IN' | 'MESSAGE' | 'SUPPORT';
|
|
34
|
+
note?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// MUTATION HOOKS
|
|
39
|
+
// ============================================================================
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Create a new match request
|
|
43
|
+
*
|
|
44
|
+
* @endpoint POST /api/v1/matching/matches
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* const createMatch = useCreateMatch();
|
|
49
|
+
* await createMatch.mutateAsync({ matchedUserId: 'user-123' });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export function useCreateMatch(
|
|
53
|
+
options?: Omit<UseMutationOptions<MatchResponse, Error, CreateMatchRequest>, 'mutationFn'>
|
|
54
|
+
): UseMutationResult<MatchResponse, Error, CreateMatchRequest> {
|
|
55
|
+
const queryClient = useQueryClient();
|
|
56
|
+
|
|
57
|
+
return useMutation({
|
|
58
|
+
mutationFn: async (data: CreateMatchRequest): Promise<MatchResponse> => {
|
|
59
|
+
const client = getApiClient();
|
|
60
|
+
const response = await client.post('/api/v1/matching/matches', data);
|
|
61
|
+
return response.data?.data || response.data;
|
|
62
|
+
},
|
|
63
|
+
onSuccess: () => {
|
|
64
|
+
queryClient.invalidateQueries({ queryKey: matchingKeys.matches() });
|
|
65
|
+
queryClient.invalidateQueries({ queryKey: matchingKeys.stats() });
|
|
66
|
+
},
|
|
67
|
+
...options,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Update match status (accept/decline/block)
|
|
73
|
+
*
|
|
74
|
+
* @endpoint PUT /api/v1/matching/matches/:matchId
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```tsx
|
|
78
|
+
* const updateMatch = useUpdateMatch();
|
|
79
|
+
* await updateMatch.mutateAsync({ matchId: 'match-123', status: 'ACCEPTED' });
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export function useUpdateMatch(
|
|
83
|
+
options?: Omit<
|
|
84
|
+
UseMutationOptions<MatchResponse, Error, { matchId: string; data: UpdateMatchRequest }>,
|
|
85
|
+
'mutationFn'
|
|
86
|
+
>
|
|
87
|
+
): UseMutationResult<MatchResponse, Error, { matchId: string; data: UpdateMatchRequest }> {
|
|
88
|
+
const queryClient = useQueryClient();
|
|
89
|
+
|
|
90
|
+
return useMutation({
|
|
91
|
+
mutationFn: async ({ matchId, data }): Promise<MatchResponse> => {
|
|
92
|
+
const client = getApiClient();
|
|
93
|
+
const response = await client.put(`/api/v1/matching/matches/${matchId}`, data);
|
|
94
|
+
return response.data?.data || response.data;
|
|
95
|
+
},
|
|
96
|
+
onSuccess: () => {
|
|
97
|
+
queryClient.invalidateQueries({ queryKey: matchingKeys.matches() });
|
|
98
|
+
queryClient.invalidateQueries({ queryKey: matchingKeys.stats() });
|
|
99
|
+
},
|
|
100
|
+
...options,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Accept a match (convenience hook)
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```tsx
|
|
109
|
+
* const acceptMatch = useAcceptMatch();
|
|
110
|
+
* await acceptMatch.mutateAsync('match-123');
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export function useAcceptMatch(
|
|
114
|
+
options?: Omit<UseMutationOptions<MatchResponse, Error, string>, 'mutationFn'>
|
|
115
|
+
): UseMutationResult<MatchResponse, Error, string> {
|
|
116
|
+
const updateMatch = useUpdateMatch();
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
...updateMatch,
|
|
120
|
+
mutate: (matchId: string, mutateOptions?: any) =>
|
|
121
|
+
updateMatch.mutate({ matchId, data: { status: 'ACCEPTED' } }, mutateOptions),
|
|
122
|
+
mutateAsync: (matchId: string) =>
|
|
123
|
+
updateMatch.mutateAsync({ matchId, data: { status: 'ACCEPTED' } }),
|
|
124
|
+
} as UseMutationResult<MatchResponse, Error, string>;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Decline a match (convenience hook)
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```tsx
|
|
132
|
+
* const declineMatch = useDeclineMatch();
|
|
133
|
+
* await declineMatch.mutateAsync('match-123');
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
export function useDeclineMatch(
|
|
137
|
+
options?: Omit<UseMutationOptions<MatchResponse, Error, string>, 'mutationFn'>
|
|
138
|
+
): UseMutationResult<MatchResponse, Error, string> {
|
|
139
|
+
const updateMatch = useUpdateMatch();
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
...updateMatch,
|
|
143
|
+
mutate: (matchId: string, mutateOptions?: any) =>
|
|
144
|
+
updateMatch.mutate({ matchId, data: { status: 'DECLINED' } }, mutateOptions),
|
|
145
|
+
mutateAsync: (matchId: string) =>
|
|
146
|
+
updateMatch.mutateAsync({ matchId, data: { status: 'DECLINED' } }),
|
|
147
|
+
} as UseMutationResult<MatchResponse, Error, string>;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Delete a match
|
|
152
|
+
*
|
|
153
|
+
* @endpoint DELETE /api/v1/matching/matches/:matchId
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```tsx
|
|
157
|
+
* const deleteMatch = useDeleteMatch();
|
|
158
|
+
* await deleteMatch.mutateAsync('match-123');
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
export function useDeleteMatch(
|
|
162
|
+
options?: Omit<UseMutationOptions<void, Error, string>, 'mutationFn'>
|
|
163
|
+
): UseMutationResult<void, Error, string> {
|
|
164
|
+
const queryClient = useQueryClient();
|
|
165
|
+
|
|
166
|
+
return useMutation({
|
|
167
|
+
mutationFn: async (matchId: string): Promise<void> => {
|
|
168
|
+
const client = getApiClient();
|
|
169
|
+
await client.delete(`/api/v1/matching/matches/${matchId}`);
|
|
170
|
+
},
|
|
171
|
+
onSuccess: () => {
|
|
172
|
+
queryClient.invalidateQueries({ queryKey: matchingKeys.matches() });
|
|
173
|
+
queryClient.invalidateQueries({ queryKey: matchingKeys.stats() });
|
|
174
|
+
},
|
|
175
|
+
...options,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Request someone as accountability buddy
|
|
181
|
+
*
|
|
182
|
+
* @endpoint POST /api/v1/matching/buddies
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```tsx
|
|
186
|
+
* const requestBuddy = useRequestBuddy();
|
|
187
|
+
* await requestBuddy.mutateAsync({ buddyId: 'user-123' });
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
export function useRequestBuddy(
|
|
191
|
+
options?: Omit<UseMutationOptions<BuddyResponse, Error, CreateBuddyRequest>, 'mutationFn'>
|
|
192
|
+
): UseMutationResult<BuddyResponse, Error, CreateBuddyRequest> {
|
|
193
|
+
const queryClient = useQueryClient();
|
|
194
|
+
|
|
195
|
+
return useMutation({
|
|
196
|
+
mutationFn: async (data: CreateBuddyRequest): Promise<BuddyResponse> => {
|
|
197
|
+
const client = getApiClient();
|
|
198
|
+
const response = await client.post('/api/v1/matching/buddies', data);
|
|
199
|
+
return response.data?.data || response.data;
|
|
200
|
+
},
|
|
201
|
+
onSuccess: () => {
|
|
202
|
+
queryClient.invalidateQueries({ queryKey: matchingKeys.buddies() });
|
|
203
|
+
queryClient.invalidateQueries({ queryKey: matchingKeys.buddyRequests() });
|
|
204
|
+
},
|
|
205
|
+
...options,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Update buddy request (accept/decline/end)
|
|
211
|
+
*
|
|
212
|
+
* @endpoint PUT /api/v1/matching/buddies/:buddyId
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```tsx
|
|
216
|
+
* const updateBuddy = useUpdateBuddy();
|
|
217
|
+
* await updateBuddy.mutateAsync({ buddyId: 'buddy-123', data: { status: 'ACCEPTED' } });
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
export function useUpdateBuddy(
|
|
221
|
+
options?: Omit<
|
|
222
|
+
UseMutationOptions<BuddyResponse, Error, { buddyId: string; data: UpdateBuddyRequest }>,
|
|
223
|
+
'mutationFn'
|
|
224
|
+
>
|
|
225
|
+
): UseMutationResult<BuddyResponse, Error, { buddyId: string; data: UpdateBuddyRequest }> {
|
|
226
|
+
const queryClient = useQueryClient();
|
|
227
|
+
|
|
228
|
+
return useMutation({
|
|
229
|
+
mutationFn: async ({ buddyId, data }): Promise<BuddyResponse> => {
|
|
230
|
+
const client = getApiClient();
|
|
231
|
+
const response = await client.put(`/api/v1/matching/buddies/${buddyId}`, data);
|
|
232
|
+
return response.data?.data || response.data;
|
|
233
|
+
},
|
|
234
|
+
onSuccess: () => {
|
|
235
|
+
queryClient.invalidateQueries({ queryKey: matchingKeys.buddies() });
|
|
236
|
+
queryClient.invalidateQueries({ queryKey: matchingKeys.buddyRequests() });
|
|
237
|
+
},
|
|
238
|
+
...options,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Log activity with buddy (check-in, message)
|
|
244
|
+
*
|
|
245
|
+
* @endpoint POST /api/v1/matching/buddies/:buddyId/activity
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* ```tsx
|
|
249
|
+
* const logActivity = useLogBuddyActivity();
|
|
250
|
+
* await logActivity.mutateAsync({ buddyId: 'buddy-123', data: { type: 'CHECK_IN' } });
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
253
|
+
export function useLogBuddyActivity(
|
|
254
|
+
options?: Omit<
|
|
255
|
+
UseMutationOptions<void, Error, { buddyId: string; data: LogBuddyActivityRequest }>,
|
|
256
|
+
'mutationFn'
|
|
257
|
+
>
|
|
258
|
+
): UseMutationResult<void, Error, { buddyId: string; data: LogBuddyActivityRequest }> {
|
|
259
|
+
const queryClient = useQueryClient();
|
|
260
|
+
|
|
261
|
+
return useMutation({
|
|
262
|
+
mutationFn: async ({ buddyId, data }): Promise<void> => {
|
|
263
|
+
const client = getApiClient();
|
|
264
|
+
await client.post(`/api/v1/matching/buddies/${buddyId}/activity`, data);
|
|
265
|
+
},
|
|
266
|
+
onSuccess: () => {
|
|
267
|
+
queryClient.invalidateQueries({ queryKey: matchingKeys.buddies() });
|
|
268
|
+
},
|
|
269
|
+
...options,
|
|
270
|
+
});
|
|
271
|
+
}
|