@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,190 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useMutation,
|
|
3
|
+
useQueryClient,
|
|
4
|
+
UseMutationOptions,
|
|
5
|
+
UseMutationResult,
|
|
6
|
+
} from '@tanstack/react-query';
|
|
7
|
+
import { getApiClient } from '../client';
|
|
8
|
+
import type { BookingResponse } from '../types';
|
|
9
|
+
import { bookingKeys } from '../queries/bookings';
|
|
10
|
+
import { eventKeys } from '../queries/events';
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// MUTATION HOOKS
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Create a new booking for an event
|
|
18
|
+
*
|
|
19
|
+
* @param options - TanStack Query mutation options
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* const { mutate, isPending } = useCreateBooking();
|
|
24
|
+
*
|
|
25
|
+
* // Simple usage - just pass eventId
|
|
26
|
+
* mutate({ eventId: 'event-123' });
|
|
27
|
+
*
|
|
28
|
+
* // With optional data
|
|
29
|
+
* mutate({
|
|
30
|
+
* eventId: 'event-123',
|
|
31
|
+
* ticketCount: 2,
|
|
32
|
+
* notes: 'Vegetarian meal preferred'
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function useCreateBooking(
|
|
37
|
+
options?: Omit<
|
|
38
|
+
UseMutationOptions<
|
|
39
|
+
BookingResponse,
|
|
40
|
+
Error,
|
|
41
|
+
{ eventId: string; ticketCount?: number; notes?: string }
|
|
42
|
+
>,
|
|
43
|
+
'mutationFn'
|
|
44
|
+
>
|
|
45
|
+
): UseMutationResult<
|
|
46
|
+
BookingResponse,
|
|
47
|
+
Error,
|
|
48
|
+
{ eventId: string; ticketCount?: number; notes?: string }
|
|
49
|
+
> {
|
|
50
|
+
const queryClient = useQueryClient();
|
|
51
|
+
|
|
52
|
+
return useMutation({
|
|
53
|
+
mutationFn: async ({
|
|
54
|
+
eventId,
|
|
55
|
+
ticketCount,
|
|
56
|
+
notes,
|
|
57
|
+
}: {
|
|
58
|
+
eventId: string;
|
|
59
|
+
ticketCount?: number;
|
|
60
|
+
notes?: string;
|
|
61
|
+
}): Promise<BookingResponse> => {
|
|
62
|
+
const client = getApiClient();
|
|
63
|
+
const data: any = {};
|
|
64
|
+
if (ticketCount) data.ticketCount = ticketCount;
|
|
65
|
+
if (notes) data.notes = notes;
|
|
66
|
+
const response = await client.post(`/api/v1/events/${eventId}/book`, data);
|
|
67
|
+
return response.data;
|
|
68
|
+
},
|
|
69
|
+
onSuccess: (newBooking, variables, context) => {
|
|
70
|
+
// Invalidate user's bookings list
|
|
71
|
+
queryClient.invalidateQueries({ queryKey: bookingKeys.mine() });
|
|
72
|
+
|
|
73
|
+
// Invalidate all booking lists
|
|
74
|
+
queryClient.invalidateQueries({ queryKey: bookingKeys.lists() });
|
|
75
|
+
|
|
76
|
+
// Invalidate the event to reflect updated booking count
|
|
77
|
+
queryClient.invalidateQueries({
|
|
78
|
+
queryKey: eventKeys.detail(variables.eventId)
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Invalidate event bookings if applicable
|
|
82
|
+
queryClient.invalidateQueries({
|
|
83
|
+
queryKey: eventKeys.bookings(variables.eventId)
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Invalidate ambient events
|
|
87
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.ambient() });
|
|
88
|
+
|
|
89
|
+
// Call user's onSuccess if provided
|
|
90
|
+
},
|
|
91
|
+
...options,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Cancel a booking
|
|
97
|
+
*
|
|
98
|
+
* @param options - TanStack Query mutation options
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```tsx
|
|
102
|
+
* const { mutate, isPending } = useCancelBooking();
|
|
103
|
+
*
|
|
104
|
+
* mutate('booking-123');
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export function useCancelBooking(
|
|
108
|
+
options?: Omit<UseMutationOptions<void, Error, string>, 'mutationFn'>
|
|
109
|
+
): UseMutationResult<void, Error, string> {
|
|
110
|
+
const queryClient = useQueryClient();
|
|
111
|
+
|
|
112
|
+
return useMutation({
|
|
113
|
+
mutationFn: async (id: string): Promise<void> => {
|
|
114
|
+
const client = getApiClient();
|
|
115
|
+
await client.delete(`/api/v1/bookings/${id}`);
|
|
116
|
+
},
|
|
117
|
+
onSuccess: (data, bookingId, context) => {
|
|
118
|
+
// Remove the booking from cache
|
|
119
|
+
queryClient.removeQueries({ queryKey: bookingKeys.detail(bookingId) });
|
|
120
|
+
|
|
121
|
+
// Invalidate user's bookings list
|
|
122
|
+
queryClient.invalidateQueries({ queryKey: bookingKeys.mine() });
|
|
123
|
+
|
|
124
|
+
// Invalidate all booking lists
|
|
125
|
+
queryClient.invalidateQueries({ queryKey: bookingKeys.lists() });
|
|
126
|
+
|
|
127
|
+
// Invalidate QR code cache
|
|
128
|
+
queryClient.removeQueries({ queryKey: bookingKeys.qrCode(bookingId) });
|
|
129
|
+
|
|
130
|
+
// Invalidate events to reflect updated booking counts
|
|
131
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.lists() });
|
|
132
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.upcoming() });
|
|
133
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.ambient() });
|
|
134
|
+
|
|
135
|
+
// Call user's onSuccess if provided
|
|
136
|
+
},
|
|
137
|
+
...options,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Check in a booking
|
|
143
|
+
*
|
|
144
|
+
* Note: This is typically used by event hosts/ambassadors to check in attendees
|
|
145
|
+
*
|
|
146
|
+
* @param options - TanStack Query mutation options
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```tsx
|
|
150
|
+
* const { mutate, isPending } = useCheckInBooking();
|
|
151
|
+
*
|
|
152
|
+
* mutate('booking-123');
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
export function useCheckInBooking(
|
|
156
|
+
options?: Omit<UseMutationOptions<BookingResponse, Error, string>, 'mutationFn'>
|
|
157
|
+
): UseMutationResult<BookingResponse, Error, string> {
|
|
158
|
+
const queryClient = useQueryClient();
|
|
159
|
+
|
|
160
|
+
return useMutation({
|
|
161
|
+
mutationFn: async (id: string): Promise<BookingResponse> => {
|
|
162
|
+
const client = getApiClient();
|
|
163
|
+
const response = await client.post(`/api/v1/bookings/${id}/check-in`);
|
|
164
|
+
return response.data;
|
|
165
|
+
},
|
|
166
|
+
onSuccess: (checkedInBooking, bookingId, context) => {
|
|
167
|
+
// Update the booking in cache
|
|
168
|
+
queryClient.setQueryData(
|
|
169
|
+
bookingKeys.detail(bookingId),
|
|
170
|
+
checkedInBooking
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
// Invalidate user's bookings list to reflect check-in status
|
|
174
|
+
queryClient.invalidateQueries({ queryKey: bookingKeys.mine() });
|
|
175
|
+
|
|
176
|
+
// Invalidate all booking lists
|
|
177
|
+
queryClient.invalidateQueries({ queryKey: bookingKeys.lists() });
|
|
178
|
+
|
|
179
|
+
// Invalidate event bookings if applicable
|
|
180
|
+
if (checkedInBooking.eventId) {
|
|
181
|
+
queryClient.invalidateQueries({
|
|
182
|
+
queryKey: eventKeys.bookings(checkedInBooking.eventId)
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Call user's onSuccess if provided
|
|
187
|
+
},
|
|
188
|
+
...options,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
2
|
+
import { getApiClient } from '../client';
|
|
3
|
+
import { eventChatKeys } from '../queries/event-chat';
|
|
4
|
+
import type {
|
|
5
|
+
ChatMemberResponse,
|
|
6
|
+
MessageResponse,
|
|
7
|
+
EventChatResponse,
|
|
8
|
+
SendMessageRequest,
|
|
9
|
+
UpdateMessageRequest,
|
|
10
|
+
UpdateChatSettingsRequest,
|
|
11
|
+
UpdateMemberSettingsRequest,
|
|
12
|
+
} from '../types';
|
|
13
|
+
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// CHAT MANAGEMENT
|
|
16
|
+
// ============================================================================
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Update chat settings (hosts only)
|
|
20
|
+
*/
|
|
21
|
+
export function useUpdateChatSettings(eventId: string) {
|
|
22
|
+
const queryClient = useQueryClient();
|
|
23
|
+
|
|
24
|
+
return useMutation({
|
|
25
|
+
mutationFn: async (data: UpdateChatSettingsRequest) => {
|
|
26
|
+
const client = getApiClient();
|
|
27
|
+
const response = await client.put<EventChatResponse>(
|
|
28
|
+
`/events/${eventId}/chat/settings`,
|
|
29
|
+
data
|
|
30
|
+
);
|
|
31
|
+
return response.data;
|
|
32
|
+
},
|
|
33
|
+
onSuccess: () => {
|
|
34
|
+
queryClient.invalidateQueries({ queryKey: eventChatKeys.chat(eventId) });
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ============================================================================
|
|
40
|
+
// MEMBER MANAGEMENT
|
|
41
|
+
// ============================================================================
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Join event chat
|
|
45
|
+
*/
|
|
46
|
+
export function useJoinEventChat(eventId: string) {
|
|
47
|
+
const queryClient = useQueryClient();
|
|
48
|
+
|
|
49
|
+
return useMutation({
|
|
50
|
+
mutationFn: async () => {
|
|
51
|
+
const client = getApiClient();
|
|
52
|
+
const response = await client.post<ChatMemberResponse>(
|
|
53
|
+
`/events/${eventId}/chat/join`
|
|
54
|
+
);
|
|
55
|
+
return response.data;
|
|
56
|
+
},
|
|
57
|
+
onSuccess: () => {
|
|
58
|
+
queryClient.invalidateQueries({ queryKey: eventChatKeys.chat(eventId) });
|
|
59
|
+
queryClient.invalidateQueries({ queryKey: eventChatKeys.members(eventId) });
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Leave event chat
|
|
66
|
+
*/
|
|
67
|
+
export function useLeaveEventChat(eventId: string) {
|
|
68
|
+
const queryClient = useQueryClient();
|
|
69
|
+
|
|
70
|
+
return useMutation({
|
|
71
|
+
mutationFn: async () => {
|
|
72
|
+
const client = getApiClient();
|
|
73
|
+
await client.post(`/events/${eventId}/chat/leave`);
|
|
74
|
+
},
|
|
75
|
+
onSuccess: () => {
|
|
76
|
+
queryClient.invalidateQueries({ queryKey: eventChatKeys.chat(eventId) });
|
|
77
|
+
queryClient.invalidateQueries({ queryKey: eventChatKeys.members(eventId) });
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Update member settings (mute, nickname)
|
|
84
|
+
*/
|
|
85
|
+
export function useUpdateMemberSettings(eventId: string) {
|
|
86
|
+
const queryClient = useQueryClient();
|
|
87
|
+
|
|
88
|
+
return useMutation({
|
|
89
|
+
mutationFn: async (data: UpdateMemberSettingsRequest) => {
|
|
90
|
+
const client = getApiClient();
|
|
91
|
+
const response = await client.put<ChatMemberResponse>(
|
|
92
|
+
`/events/${eventId}/chat/settings/me`,
|
|
93
|
+
data
|
|
94
|
+
);
|
|
95
|
+
return response.data;
|
|
96
|
+
},
|
|
97
|
+
onSuccess: () => {
|
|
98
|
+
queryClient.invalidateQueries({ queryKey: eventChatKeys.members(eventId) });
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Mark messages as read
|
|
105
|
+
*/
|
|
106
|
+
export function useMarkMessagesAsRead(eventId: string) {
|
|
107
|
+
return useMutation({
|
|
108
|
+
mutationFn: async () => {
|
|
109
|
+
const client = getApiClient();
|
|
110
|
+
await client.post(`/events/${eventId}/chat/read`);
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ============================================================================
|
|
116
|
+
// MESSAGES
|
|
117
|
+
// ============================================================================
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Send a message
|
|
121
|
+
*/
|
|
122
|
+
export function useSendEventChatMessage(eventId: string) {
|
|
123
|
+
const queryClient = useQueryClient();
|
|
124
|
+
|
|
125
|
+
return useMutation({
|
|
126
|
+
mutationFn: async (data: SendMessageRequest) => {
|
|
127
|
+
const client = getApiClient();
|
|
128
|
+
const response = await client.post<MessageResponse>(
|
|
129
|
+
`/events/${eventId}/chat/messages`,
|
|
130
|
+
data
|
|
131
|
+
);
|
|
132
|
+
return response.data;
|
|
133
|
+
},
|
|
134
|
+
onSuccess: () => {
|
|
135
|
+
queryClient.invalidateQueries({ queryKey: eventChatKeys.messages(eventId) });
|
|
136
|
+
queryClient.invalidateQueries({ queryKey: eventChatKeys.chat(eventId) });
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Update a message
|
|
143
|
+
*/
|
|
144
|
+
export function useUpdateEventChatMessage(eventId: string) {
|
|
145
|
+
const queryClient = useQueryClient();
|
|
146
|
+
|
|
147
|
+
return useMutation({
|
|
148
|
+
mutationFn: async ({ messageId, content }: { messageId: string } & UpdateMessageRequest) => {
|
|
149
|
+
const client = getApiClient();
|
|
150
|
+
const response = await client.put<MessageResponse>(
|
|
151
|
+
`/events/${eventId}/chat/messages/${messageId}`,
|
|
152
|
+
{ content }
|
|
153
|
+
);
|
|
154
|
+
return response.data;
|
|
155
|
+
},
|
|
156
|
+
onSuccess: () => {
|
|
157
|
+
queryClient.invalidateQueries({ queryKey: eventChatKeys.messages(eventId) });
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Delete a message
|
|
164
|
+
*/
|
|
165
|
+
export function useDeleteEventChatMessage(eventId: string) {
|
|
166
|
+
const queryClient = useQueryClient();
|
|
167
|
+
|
|
168
|
+
return useMutation({
|
|
169
|
+
mutationFn: async (messageId: string) => {
|
|
170
|
+
const client = getApiClient();
|
|
171
|
+
await client.delete(`/events/${eventId}/chat/messages/${messageId}`);
|
|
172
|
+
},
|
|
173
|
+
onSuccess: () => {
|
|
174
|
+
queryClient.invalidateQueries({ queryKey: eventChatKeys.messages(eventId) });
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useMutation,
|
|
3
|
+
useQueryClient,
|
|
4
|
+
UseMutationOptions,
|
|
5
|
+
UseMutationResult,
|
|
6
|
+
} from '@tanstack/react-query';
|
|
7
|
+
import { getApiClient } from '../client';
|
|
8
|
+
import type { EventResponse, CreateEventRequest, UpdateEventRequest } from '../types';
|
|
9
|
+
import { eventKeys } from '../queries/events';
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// MUTATION HOOKS
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Create a new event
|
|
17
|
+
*
|
|
18
|
+
* @param options - TanStack Query mutation options
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const { mutate, isPending } = useCreateEvent();
|
|
23
|
+
*
|
|
24
|
+
* mutate({
|
|
25
|
+
* title: 'Yoga in the Park',
|
|
26
|
+
* description: 'Join us for morning yoga',
|
|
27
|
+
* startDate: new Date('2025-01-15T10:00:00Z'),
|
|
28
|
+
* // ... other fields
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export function useCreateEvent(
|
|
33
|
+
options?: Omit<
|
|
34
|
+
UseMutationOptions<EventResponse, Error, CreateEventRequest>,
|
|
35
|
+
'mutationFn'
|
|
36
|
+
>
|
|
37
|
+
): UseMutationResult<EventResponse, Error, CreateEventRequest> {
|
|
38
|
+
const queryClient = useQueryClient();
|
|
39
|
+
|
|
40
|
+
return useMutation({
|
|
41
|
+
mutationFn: async (data: CreateEventRequest): Promise<EventResponse> => {
|
|
42
|
+
const client = getApiClient();
|
|
43
|
+
const response = await client.post('/api/v1/events', data);
|
|
44
|
+
return response.data;
|
|
45
|
+
},
|
|
46
|
+
onSuccess: (newEvent, variables, context) => {
|
|
47
|
+
// Invalidate all event lists to include the new event
|
|
48
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.lists() });
|
|
49
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.upcoming() });
|
|
50
|
+
|
|
51
|
+
// If the event is featured, invalidate featured events
|
|
52
|
+
if (newEvent.isFeatured) {
|
|
53
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.featured() });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Call user's onSuccess if provided
|
|
57
|
+
},
|
|
58
|
+
...options,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Update an existing event
|
|
64
|
+
*
|
|
65
|
+
* @param options - TanStack Query mutation options
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```tsx
|
|
69
|
+
* const { mutate, isPending } = useUpdateEvent();
|
|
70
|
+
*
|
|
71
|
+
* mutate({
|
|
72
|
+
* id: 'event-123',
|
|
73
|
+
* data: {
|
|
74
|
+
* title: 'Updated Event Title',
|
|
75
|
+
* isFeatured: true,
|
|
76
|
+
* }
|
|
77
|
+
* });
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export function useUpdateEvent(
|
|
81
|
+
options?: Omit<
|
|
82
|
+
UseMutationOptions<
|
|
83
|
+
EventResponse,
|
|
84
|
+
Error,
|
|
85
|
+
{ id: string; data: UpdateEventRequest }
|
|
86
|
+
>,
|
|
87
|
+
'mutationFn'
|
|
88
|
+
>
|
|
89
|
+
): UseMutationResult<EventResponse, Error, { id: string; data: UpdateEventRequest }> {
|
|
90
|
+
const queryClient = useQueryClient();
|
|
91
|
+
|
|
92
|
+
return useMutation({
|
|
93
|
+
mutationFn: async ({
|
|
94
|
+
id,
|
|
95
|
+
data,
|
|
96
|
+
}: {
|
|
97
|
+
id: string;
|
|
98
|
+
data: UpdateEventRequest;
|
|
99
|
+
}): Promise<EventResponse> => {
|
|
100
|
+
const client = getApiClient();
|
|
101
|
+
const response = await client.put(`/api/v1/events/${id}`, data);
|
|
102
|
+
return response.data;
|
|
103
|
+
},
|
|
104
|
+
onSuccess: (updatedEvent, variables, context) => {
|
|
105
|
+
// Update the specific event in cache
|
|
106
|
+
queryClient.setQueryData(
|
|
107
|
+
eventKeys.detail(variables.id),
|
|
108
|
+
updatedEvent
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
// If the event has a slug, update the slug-based query too
|
|
112
|
+
if (updatedEvent.slug && typeof updatedEvent.slug === 'string') {
|
|
113
|
+
queryClient.setQueryData(
|
|
114
|
+
eventKeys.detailBySlug(updatedEvent.slug),
|
|
115
|
+
updatedEvent
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Invalidate lists to reflect changes in ordering/filtering
|
|
120
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.lists() });
|
|
121
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.upcoming() });
|
|
122
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.featured() });
|
|
123
|
+
|
|
124
|
+
// Call user's onSuccess if provided
|
|
125
|
+
},
|
|
126
|
+
...options,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Delete an event
|
|
132
|
+
*
|
|
133
|
+
* @param options - TanStack Query mutation options
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```tsx
|
|
137
|
+
* const { mutate, isPending } = useDeleteEvent();
|
|
138
|
+
*
|
|
139
|
+
* mutate('event-123');
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
export function useDeleteEvent(
|
|
143
|
+
options?: Omit<UseMutationOptions<void, Error, string>, 'mutationFn'>
|
|
144
|
+
): UseMutationResult<void, Error, string> {
|
|
145
|
+
const queryClient = useQueryClient();
|
|
146
|
+
|
|
147
|
+
return useMutation({
|
|
148
|
+
mutationFn: async (id: string): Promise<void> => {
|
|
149
|
+
const client = getApiClient();
|
|
150
|
+
await client.delete(`/api/v1/events/${id}`);
|
|
151
|
+
},
|
|
152
|
+
onSuccess: (data, eventId, context) => {
|
|
153
|
+
// Remove the event from cache
|
|
154
|
+
queryClient.removeQueries({ queryKey: eventKeys.detail(eventId) });
|
|
155
|
+
|
|
156
|
+
// Invalidate all lists
|
|
157
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.lists() });
|
|
158
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.upcoming() });
|
|
159
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.featured() });
|
|
160
|
+
|
|
161
|
+
// Call user's onSuccess if provided
|
|
162
|
+
},
|
|
163
|
+
...options,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Cancel an event
|
|
169
|
+
*
|
|
170
|
+
* @param options - TanStack Query mutation options
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```tsx
|
|
174
|
+
* const { mutate, isPending } = useCancelEvent();
|
|
175
|
+
*
|
|
176
|
+
* mutate('event-123');
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
export function useCancelEvent(
|
|
180
|
+
options?: Omit<UseMutationOptions<EventResponse, Error, string>, 'mutationFn'>
|
|
181
|
+
): UseMutationResult<EventResponse, Error, string> {
|
|
182
|
+
const queryClient = useQueryClient();
|
|
183
|
+
|
|
184
|
+
return useMutation({
|
|
185
|
+
mutationFn: async (id: string): Promise<EventResponse> => {
|
|
186
|
+
const client = getApiClient();
|
|
187
|
+
const response = await client.post(`/api/v1/events/${id}/cancel`);
|
|
188
|
+
return response.data;
|
|
189
|
+
},
|
|
190
|
+
onSuccess: (cancelledEvent, eventId, context) => {
|
|
191
|
+
// Update the specific event in cache
|
|
192
|
+
queryClient.setQueryData(
|
|
193
|
+
eventKeys.detail(eventId),
|
|
194
|
+
cancelledEvent
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
// If the event has a slug, update the slug-based query too
|
|
198
|
+
if (cancelledEvent.slug && typeof cancelledEvent.slug === 'string') {
|
|
199
|
+
queryClient.setQueryData(
|
|
200
|
+
eventKeys.detailBySlug(cancelledEvent.slug),
|
|
201
|
+
cancelledEvent
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Invalidate lists to reflect the cancelled status
|
|
206
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.lists() });
|
|
207
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.upcoming() });
|
|
208
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.featured() });
|
|
209
|
+
|
|
210
|
+
// Invalidate bookings for this event
|
|
211
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.bookings(eventId) });
|
|
212
|
+
|
|
213
|
+
// Call user's onSuccess if provided
|
|
214
|
+
},
|
|
215
|
+
...options,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Publish an event
|
|
221
|
+
*
|
|
222
|
+
* Note: This mutation is provided for future compatibility.
|
|
223
|
+
* The API endpoint exists but may require specific permissions.
|
|
224
|
+
*
|
|
225
|
+
* @param options - TanStack Query mutation options
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* ```tsx
|
|
229
|
+
* const { mutate, isPending } = usePublishEvent();
|
|
230
|
+
*
|
|
231
|
+
* mutate('event-123');
|
|
232
|
+
* ```
|
|
233
|
+
*/
|
|
234
|
+
export function usePublishEvent(
|
|
235
|
+
options?: Omit<UseMutationOptions<EventResponse, Error, string>, 'mutationFn'>
|
|
236
|
+
): UseMutationResult<EventResponse, Error, string> {
|
|
237
|
+
const queryClient = useQueryClient();
|
|
238
|
+
|
|
239
|
+
return useMutation({
|
|
240
|
+
mutationFn: async (id: string): Promise<EventResponse> => {
|
|
241
|
+
const client = getApiClient();
|
|
242
|
+
const response = await client.post(`/api/v1/events/${id}/publish`);
|
|
243
|
+
return response.data;
|
|
244
|
+
},
|
|
245
|
+
onSuccess: (publishedEvent, eventId, context) => {
|
|
246
|
+
// Update the specific event in cache
|
|
247
|
+
queryClient.setQueryData(
|
|
248
|
+
eventKeys.detail(eventId),
|
|
249
|
+
publishedEvent
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
// If the event has a slug, update the slug-based query too
|
|
253
|
+
if (publishedEvent.slug && typeof publishedEvent.slug === 'string') {
|
|
254
|
+
queryClient.setQueryData(
|
|
255
|
+
eventKeys.detailBySlug(publishedEvent.slug),
|
|
256
|
+
publishedEvent
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Invalidate lists to reflect the published status
|
|
261
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.lists() });
|
|
262
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.upcoming() });
|
|
263
|
+
|
|
264
|
+
// If the event is featured, invalidate featured events
|
|
265
|
+
if (publishedEvent.isFeatured) {
|
|
266
|
+
queryClient.invalidateQueries({ queryKey: eventKeys.featured() });
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Call user's onSuccess if provided
|
|
270
|
+
},
|
|
271
|
+
...options,
|
|
272
|
+
});
|
|
273
|
+
}
|