@spotsdev/sdk 1.0.0 → 1.1.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/dist/api/client.d.ts +1 -1
- package/dist/api/client.js +7 -3
- package/dist/api/entities.d.ts +316 -0
- package/dist/api/entities.js +9 -0
- package/dist/api/mutations/clubs.d.ts +6 -6
- package/dist/api/mutations/clubs.js +12 -10
- package/dist/api/mutations/conversations.d.ts +7 -7
- package/dist/api/mutations/conversations.js +17 -13
- package/dist/api/mutations/index.js +1 -1
- package/dist/api/mutations/notifications.d.ts +4 -4
- package/dist/api/mutations/notifications.js +7 -7
- package/dist/api/mutations/orders.d.ts +7 -7
- package/dist/api/mutations/orders.js +11 -13
- package/dist/api/mutations/posts.d.ts +13 -13
- package/dist/api/mutations/posts.js +41 -29
- package/dist/api/mutations/products.d.ts +5 -5
- package/dist/api/mutations/products.js +9 -13
- package/dist/api/mutations/spots.d.ts +42 -8
- package/dist/api/mutations/spots.js +51 -13
- package/dist/api/mutations/users.d.ts +12 -10
- package/dist/api/mutations/users.js +20 -18
- package/dist/api/queries/auth.d.ts +5 -5
- package/dist/api/queries/auth.js +7 -7
- package/dist/api/queries/clubs.d.ts +7 -7
- package/dist/api/queries/clubs.js +11 -11
- package/dist/api/queries/conversations.d.ts +5 -5
- package/dist/api/queries/conversations.js +7 -7
- package/dist/api/queries/index.js +1 -1
- package/dist/api/queries/misc.d.ts +8 -32
- package/dist/api/queries/misc.js +28 -66
- package/dist/api/queries/notifications.d.ts +4 -4
- package/dist/api/queries/notifications.js +5 -5
- package/dist/api/queries/orders.d.ts +4 -4
- package/dist/api/queries/orders.js +7 -7
- package/dist/api/queries/posts.d.ts +44 -7
- package/dist/api/queries/posts.js +118 -15
- package/dist/api/queries/products.d.ts +6 -10
- package/dist/api/queries/products.js +7 -9
- package/dist/api/queries/spots.d.ts +31 -16
- package/dist/api/queries/spots.js +113 -31
- package/dist/api/queries/templates.d.ts +6 -9
- package/dist/api/queries/templates.js +8 -13
- package/dist/api/queries/users.d.ts +25 -11
- package/dist/api/queries/users.js +75 -27
- package/dist/api/types.d.ts +36 -33
- package/dist/api/types.js +6 -7
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -8
- package/package.json +6 -21
- package/src/api/client.ts +45 -30
- package/src/api/entities.ts +420 -0
- package/src/api/mutations/clubs.ts +73 -40
- package/src/api/mutations/conversations.ts +91 -47
- package/src/api/mutations/index.ts +8 -8
- package/src/api/mutations/notifications.ts +48 -25
- package/src/api/mutations/orders.ts +101 -70
- package/src/api/mutations/posts.ts +229 -118
- package/src/api/mutations/products.ts +120 -81
- package/src/api/mutations/spots.ts +167 -55
- package/src/api/mutations/users.ts +109 -76
- package/src/api/queries/auth.ts +49 -24
- package/src/api/queries/clubs.ts +53 -38
- package/src/api/queries/conversations.ts +48 -30
- package/src/api/queries/index.ts +21 -21
- package/src/api/queries/misc.ts +53 -82
- package/src/api/queries/notifications.ts +32 -21
- package/src/api/queries/orders.ts +59 -42
- package/src/api/queries/posts.ts +203 -48
- package/src/api/queries/products.ts +51 -44
- package/src/api/queries/spots.ts +216 -85
- package/src/api/queries/templates.ts +39 -32
- package/src/api/queries/users.ts +157 -64
- package/src/api/types.ts +72 -118
- package/src/index.ts +5 -11
package/src/api/queries/posts.ts
CHANGED
|
@@ -4,9 +4,70 @@
|
|
|
4
4
|
* TanStack Query hooks for post/board operations.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
import {
|
|
8
|
+
useQuery,
|
|
9
|
+
type UseQueryOptions,
|
|
10
|
+
type UseQueryResult,
|
|
11
|
+
} from '@tanstack/react-query'
|
|
12
|
+
|
|
13
|
+
import {getApiClient} from '../client'
|
|
14
|
+
import {
|
|
15
|
+
type ApiResponse,
|
|
16
|
+
type Post,
|
|
17
|
+
type PostResponse,
|
|
18
|
+
type PostStatusDto,
|
|
19
|
+
type PostUpvotesResponse,
|
|
20
|
+
} from '../types'
|
|
21
|
+
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// HELPER FUNCTIONS
|
|
24
|
+
// ============================================================================
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Extract array data from API response
|
|
28
|
+
* API returns { success, data: { data: [...], meta: {...} } } or { success, data: [...] }
|
|
29
|
+
*/
|
|
30
|
+
function extractArrayData<T>(data: unknown): T[] {
|
|
31
|
+
// If already an array, return it
|
|
32
|
+
if (Array.isArray(data)) {
|
|
33
|
+
return data
|
|
34
|
+
}
|
|
35
|
+
// If it's an object with nested data property, extract it
|
|
36
|
+
if (data && typeof data === 'object' && 'data' in data) {
|
|
37
|
+
const nested = (data as {data: unknown}).data
|
|
38
|
+
if (Array.isArray(nested)) {
|
|
39
|
+
return nested
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return []
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Extract single object data from API response
|
|
47
|
+
* API returns { success, data: { data: {...} } } or { success, data: {...} }
|
|
48
|
+
*/
|
|
49
|
+
function extractObjectData<T>(data: unknown): T {
|
|
50
|
+
// If it's an object with nested data property (not an array), extract it
|
|
51
|
+
if (
|
|
52
|
+
data &&
|
|
53
|
+
typeof data === 'object' &&
|
|
54
|
+
'data' in data &&
|
|
55
|
+
!Array.isArray(data)
|
|
56
|
+
) {
|
|
57
|
+
const nested = (data as {data: unknown}).data
|
|
58
|
+
// Check if nested also has a data property (double-wrapped)
|
|
59
|
+
if (
|
|
60
|
+
nested &&
|
|
61
|
+
typeof nested === 'object' &&
|
|
62
|
+
'data' in nested &&
|
|
63
|
+
!Array.isArray(nested)
|
|
64
|
+
) {
|
|
65
|
+
return (nested as {data: T}).data
|
|
66
|
+
}
|
|
67
|
+
return nested as T
|
|
68
|
+
}
|
|
69
|
+
return data as T
|
|
70
|
+
}
|
|
10
71
|
|
|
11
72
|
// ============================================================================
|
|
12
73
|
// QUERY KEYS
|
|
@@ -15,13 +76,18 @@ import type { Post, PostResponse, ApiResponse, PostStatusDto } from '../types';
|
|
|
15
76
|
export const postKeys = {
|
|
16
77
|
all: ['posts'] as const,
|
|
17
78
|
lists: () => [...postKeys.all, 'list'] as const,
|
|
18
|
-
list: (filters?: Record<string, unknown>) =>
|
|
19
|
-
|
|
79
|
+
list: (filters?: Record<string, unknown>) =>
|
|
80
|
+
[...postKeys.lists(), filters] as const,
|
|
81
|
+
bySpot: (spotId: string, filters?: Record<string, unknown>) =>
|
|
82
|
+
[...postKeys.all, 'spot', spotId, filters] as const,
|
|
20
83
|
details: () => [...postKeys.all, 'detail'] as const,
|
|
21
84
|
detail: (id: string) => [...postKeys.details(), id] as const,
|
|
22
|
-
responses: (postId: string) =>
|
|
85
|
+
responses: (postId: string) =>
|
|
86
|
+
[...postKeys.detail(postId), 'responses'] as const,
|
|
23
87
|
status: (postId: string) => [...postKeys.detail(postId), 'status'] as const,
|
|
24
|
-
}
|
|
88
|
+
upvotes: (postId: string, filters?: {limit?: number; offset?: number}) =>
|
|
89
|
+
[...postKeys.detail(postId), 'upvotes', filters] as const,
|
|
90
|
+
}
|
|
25
91
|
|
|
26
92
|
// ============================================================================
|
|
27
93
|
// QUERY HOOKS
|
|
@@ -30,113 +96,202 @@ export const postKeys = {
|
|
|
30
96
|
/**
|
|
31
97
|
* Get posts for a spot
|
|
32
98
|
*
|
|
33
|
-
* @endpoint GET /
|
|
99
|
+
* @endpoint GET /spots/{spotId}/posts
|
|
34
100
|
*/
|
|
35
101
|
export function useSpotPosts(
|
|
36
102
|
spotId: string,
|
|
37
|
-
params?: {
|
|
38
|
-
options?: Omit<UseQueryOptions<Post[]>, 'queryKey' | 'queryFn'
|
|
103
|
+
params?: {postType?: string; status?: string; page?: number; limit?: number},
|
|
104
|
+
options?: Omit<UseQueryOptions<Post[]>, 'queryKey' | 'queryFn'>,
|
|
39
105
|
): UseQueryResult<Post[]> {
|
|
40
106
|
return useQuery({
|
|
41
107
|
queryKey: postKeys.bySpot(spotId, params),
|
|
42
108
|
queryFn: async (): Promise<Post[]> => {
|
|
43
|
-
const client = getApiClient()
|
|
44
|
-
const queryParams = new URLSearchParams()
|
|
45
|
-
if (params?.postType) queryParams.set('postType', params.postType)
|
|
46
|
-
if (params?.status) queryParams.set('status', params.status)
|
|
47
|
-
if (params?.page) queryParams.set('page', String(params.page))
|
|
48
|
-
if (params?.limit) queryParams.set('limit', String(params.limit))
|
|
49
|
-
const response = await client.get<ApiResponse<
|
|
50
|
-
|
|
109
|
+
const client = getApiClient()
|
|
110
|
+
const queryParams = new URLSearchParams()
|
|
111
|
+
if (params?.postType) queryParams.set('postType', params.postType)
|
|
112
|
+
if (params?.status) queryParams.set('status', params.status)
|
|
113
|
+
if (params?.page) queryParams.set('page', String(params.page))
|
|
114
|
+
if (params?.limit) queryParams.set('limit', String(params.limit))
|
|
115
|
+
const response = await client.get<ApiResponse<unknown>>(
|
|
116
|
+
`/spots/${spotId}/posts?${queryParams}`,
|
|
117
|
+
)
|
|
118
|
+
return extractArrayData<Post>(response.data.data)
|
|
51
119
|
},
|
|
52
120
|
enabled: !!spotId,
|
|
53
121
|
...options,
|
|
54
|
-
})
|
|
122
|
+
})
|
|
55
123
|
}
|
|
56
124
|
|
|
57
125
|
/**
|
|
58
126
|
* Get a single post by ID
|
|
59
127
|
*
|
|
60
|
-
* @endpoint GET /
|
|
128
|
+
* @endpoint GET /posts/{postId}
|
|
61
129
|
*/
|
|
62
130
|
export function usePost(
|
|
63
131
|
postId: string,
|
|
64
|
-
options?: Omit<UseQueryOptions<Post>, 'queryKey' | 'queryFn'
|
|
132
|
+
options?: Omit<UseQueryOptions<Post>, 'queryKey' | 'queryFn'>,
|
|
65
133
|
): UseQueryResult<Post> {
|
|
66
134
|
return useQuery({
|
|
67
135
|
queryKey: postKeys.detail(postId),
|
|
68
136
|
queryFn: async (): Promise<Post> => {
|
|
69
|
-
const client = getApiClient()
|
|
70
|
-
const response = await client.get<ApiResponse<
|
|
71
|
-
|
|
137
|
+
const client = getApiClient()
|
|
138
|
+
const response = await client.get<ApiResponse<unknown>>(
|
|
139
|
+
`/posts/${postId}`,
|
|
140
|
+
)
|
|
141
|
+
return extractObjectData<Post>(response.data.data)
|
|
72
142
|
},
|
|
73
143
|
enabled: !!postId,
|
|
74
144
|
...options,
|
|
75
|
-
})
|
|
145
|
+
})
|
|
76
146
|
}
|
|
77
147
|
|
|
78
148
|
/**
|
|
79
149
|
* Get responses for a post
|
|
80
150
|
*
|
|
81
|
-
* @endpoint GET /
|
|
151
|
+
* @endpoint GET /posts/{postId}/responses
|
|
82
152
|
*/
|
|
83
153
|
export function usePostResponses(
|
|
84
154
|
postId: string,
|
|
85
|
-
options?: Omit<UseQueryOptions<PostResponse[]>, 'queryKey' | 'queryFn'
|
|
155
|
+
options?: Omit<UseQueryOptions<PostResponse[]>, 'queryKey' | 'queryFn'>,
|
|
86
156
|
): UseQueryResult<PostResponse[]> {
|
|
87
157
|
return useQuery({
|
|
88
158
|
queryKey: postKeys.responses(postId),
|
|
89
159
|
queryFn: async (): Promise<PostResponse[]> => {
|
|
90
|
-
const client = getApiClient()
|
|
91
|
-
const response = await client.get<ApiResponse<
|
|
92
|
-
|
|
160
|
+
const client = getApiClient()
|
|
161
|
+
const response = await client.get<ApiResponse<unknown>>(
|
|
162
|
+
`/posts/${postId}/responses`,
|
|
163
|
+
)
|
|
164
|
+
return extractArrayData<PostResponse>(response.data.data)
|
|
93
165
|
},
|
|
94
166
|
enabled: !!postId,
|
|
95
167
|
...options,
|
|
96
|
-
})
|
|
168
|
+
})
|
|
97
169
|
}
|
|
98
170
|
|
|
99
171
|
/**
|
|
100
172
|
* Get all posts (with filters)
|
|
101
173
|
*
|
|
102
|
-
* @endpoint GET /
|
|
174
|
+
* @endpoint GET /posts
|
|
103
175
|
*/
|
|
104
176
|
export function usePosts(
|
|
105
|
-
params?: {
|
|
106
|
-
options?: Omit<UseQueryOptions<Post[]>, 'queryKey' | 'queryFn'
|
|
177
|
+
params?: {postType?: string; limit?: number},
|
|
178
|
+
options?: Omit<UseQueryOptions<Post[]>, 'queryKey' | 'queryFn'>,
|
|
107
179
|
): UseQueryResult<Post[]> {
|
|
108
180
|
return useQuery({
|
|
109
181
|
queryKey: postKeys.list(params),
|
|
110
182
|
queryFn: async (): Promise<Post[]> => {
|
|
111
|
-
const client = getApiClient()
|
|
112
|
-
const queryParams = new URLSearchParams()
|
|
113
|
-
if (params?.postType) queryParams.set('postType', params.postType)
|
|
114
|
-
if (params?.limit) queryParams.set('limit', String(params.limit))
|
|
115
|
-
const response = await client.get<ApiResponse<
|
|
116
|
-
|
|
183
|
+
const client = getApiClient()
|
|
184
|
+
const queryParams = new URLSearchParams()
|
|
185
|
+
if (params?.postType) queryParams.set('postType', params.postType)
|
|
186
|
+
if (params?.limit) queryParams.set('limit', String(params.limit))
|
|
187
|
+
const response = await client.get<ApiResponse<unknown>>(
|
|
188
|
+
`/posts?${queryParams}`,
|
|
189
|
+
)
|
|
190
|
+
return extractArrayData<Post>(response.data.data)
|
|
117
191
|
},
|
|
118
192
|
...options,
|
|
119
|
-
})
|
|
193
|
+
})
|
|
120
194
|
}
|
|
121
195
|
|
|
122
|
-
|
|
123
196
|
/**
|
|
124
197
|
* Get user's status for a post (read/hidden/pinned)
|
|
125
198
|
*
|
|
126
|
-
* @endpoint GET /
|
|
199
|
+
* @endpoint GET /posts/{postId}/status
|
|
127
200
|
*/
|
|
128
201
|
export function usePostStatus(
|
|
129
202
|
postId: string,
|
|
130
|
-
options?: Omit<UseQueryOptions<PostStatusDto>, 'queryKey' | 'queryFn'
|
|
203
|
+
options?: Omit<UseQueryOptions<PostStatusDto>, 'queryKey' | 'queryFn'>,
|
|
131
204
|
): UseQueryResult<PostStatusDto> {
|
|
132
205
|
return useQuery({
|
|
133
206
|
queryKey: postKeys.status(postId),
|
|
134
207
|
queryFn: async (): Promise<PostStatusDto> => {
|
|
135
|
-
const client = getApiClient()
|
|
136
|
-
const response = await client.get<ApiResponse<
|
|
137
|
-
|
|
208
|
+
const client = getApiClient()
|
|
209
|
+
const response = await client.get<ApiResponse<unknown>>(
|
|
210
|
+
`/posts/${postId}/status`,
|
|
211
|
+
)
|
|
212
|
+
return extractObjectData<PostStatusDto>(response.data.data)
|
|
213
|
+
},
|
|
214
|
+
enabled: !!postId,
|
|
215
|
+
...options,
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Get upvotes for a post (list of users who upvoted)
|
|
221
|
+
*
|
|
222
|
+
* @endpoint GET /posts/{postId}/upvotes
|
|
223
|
+
*/
|
|
224
|
+
export function usePostUpvotes(
|
|
225
|
+
postId: string,
|
|
226
|
+
params?: {limit?: number; offset?: number},
|
|
227
|
+
options?: Omit<UseQueryOptions<PostUpvotesResponse>, 'queryKey' | 'queryFn'>,
|
|
228
|
+
): UseQueryResult<PostUpvotesResponse> {
|
|
229
|
+
return useQuery({
|
|
230
|
+
queryKey: postKeys.upvotes(postId, params),
|
|
231
|
+
queryFn: async (): Promise<PostUpvotesResponse> => {
|
|
232
|
+
const client = getApiClient()
|
|
233
|
+
const queryParams = new URLSearchParams()
|
|
234
|
+
if (params?.limit) queryParams.set('limit', String(params.limit))
|
|
235
|
+
if (params?.offset) queryParams.set('offset', String(params.offset))
|
|
236
|
+
const queryString = queryParams.toString()
|
|
237
|
+
const response = await client.get<ApiResponse<PostUpvotesResponse>>(
|
|
238
|
+
`/posts/${postId}/upvotes${queryString ? `?${queryString}` : ''}`,
|
|
239
|
+
)
|
|
240
|
+
// Response structure: { success, data: { data: [...], meta: {...} } }
|
|
241
|
+
return response.data.data
|
|
138
242
|
},
|
|
139
243
|
enabled: !!postId,
|
|
140
244
|
...options,
|
|
141
|
-
})
|
|
245
|
+
})
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Get nearby posts feed
|
|
250
|
+
*
|
|
251
|
+
* @endpoint GET /posts/feed
|
|
252
|
+
*/
|
|
253
|
+
export function usePostsFeed(
|
|
254
|
+
params: {
|
|
255
|
+
lat: number
|
|
256
|
+
lng: number
|
|
257
|
+
radius?: number
|
|
258
|
+
postType?: string
|
|
259
|
+
cursor?: string
|
|
260
|
+
limit?: number
|
|
261
|
+
},
|
|
262
|
+
options?: Omit<
|
|
263
|
+
UseQueryOptions<{posts: Post[]; hasMore: boolean; nextCursor?: string}>,
|
|
264
|
+
'queryKey' | 'queryFn'
|
|
265
|
+
>,
|
|
266
|
+
): UseQueryResult<{posts: Post[]; hasMore: boolean; nextCursor?: string}> {
|
|
267
|
+
return useQuery({
|
|
268
|
+
queryKey: [...postKeys.lists(), 'feed', params] as const,
|
|
269
|
+
queryFn: async (): Promise<{
|
|
270
|
+
posts: Post[]
|
|
271
|
+
hasMore: boolean
|
|
272
|
+
nextCursor?: string
|
|
273
|
+
}> => {
|
|
274
|
+
const client = getApiClient()
|
|
275
|
+
const queryParams = new URLSearchParams()
|
|
276
|
+
queryParams.set('lat', String(params.lat))
|
|
277
|
+
queryParams.set('lng', String(params.lng))
|
|
278
|
+
if (params.radius) queryParams.set('radius', String(params.radius))
|
|
279
|
+
if (params.postType) queryParams.set('postType', params.postType)
|
|
280
|
+
if (params.cursor) queryParams.set('cursor', params.cursor)
|
|
281
|
+
if (params.limit) queryParams.set('limit', String(params.limit))
|
|
282
|
+
|
|
283
|
+
const response = await client.get<
|
|
284
|
+
ApiResponse<{posts: Post[]; hasMore: boolean; nextCursor?: string}>
|
|
285
|
+
>(`/posts/feed?${queryParams}`)
|
|
286
|
+
|
|
287
|
+
const data = response.data.data
|
|
288
|
+
return {
|
|
289
|
+
posts: data.posts ?? extractArrayData<Post>(data),
|
|
290
|
+
hasMore: data.hasMore ?? false,
|
|
291
|
+
nextCursor: data.nextCursor,
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
enabled: params.lat !== 0 && params.lng !== 0,
|
|
295
|
+
...options,
|
|
296
|
+
})
|
|
142
297
|
}
|
|
@@ -4,9 +4,16 @@
|
|
|
4
4
|
* TanStack Query hooks for product-related operations.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import type {
|
|
7
|
+
import {useQuery, type UseQueryOptions, type UseQueryResult} from '@tanstack/react-query'
|
|
8
|
+
import {getApiClient} from '../client'
|
|
9
|
+
import type {
|
|
10
|
+
Product,
|
|
11
|
+
ApiResponse,
|
|
12
|
+
PaginatedResponse,
|
|
13
|
+
ProductType,
|
|
14
|
+
ProductStatus,
|
|
15
|
+
Spot,
|
|
16
|
+
} from '../types'
|
|
10
17
|
|
|
11
18
|
// ============================================================================
|
|
12
19
|
// QUERY KEYS
|
|
@@ -15,31 +22,29 @@ import type { Product, ApiResponse, PaginatedResponse, ProductType, ProductStatu
|
|
|
15
22
|
export const productKeys = {
|
|
16
23
|
all: ['products'] as const,
|
|
17
24
|
lists: () => [...productKeys.all, 'list'] as const,
|
|
18
|
-
list: (filters?: Record<string, unknown>) =>
|
|
25
|
+
list: (filters?: Record<string, unknown>) =>
|
|
26
|
+
[...productKeys.lists(), filters] as const,
|
|
19
27
|
details: () => [...productKeys.all, 'detail'] as const,
|
|
20
28
|
detail: (id: string) => [...productKeys.details(), id] as const,
|
|
21
|
-
bySlug: (spotId: string, slug: string) =>
|
|
29
|
+
bySlug: (spotId: string, slug: string) =>
|
|
30
|
+
[...productKeys.all, 'slug', spotId, slug] as const,
|
|
22
31
|
bySpot: (spotId: string) => [...productKeys.all, 'spot', spotId] as const,
|
|
23
|
-
}
|
|
32
|
+
}
|
|
24
33
|
|
|
25
34
|
// ============================================================================
|
|
26
35
|
// TYPES
|
|
27
36
|
// ============================================================================
|
|
28
37
|
|
|
29
38
|
export interface ProductFilters {
|
|
30
|
-
spotId?: string
|
|
31
|
-
type?: ProductType
|
|
32
|
-
status?: ProductStatus
|
|
33
|
-
limit?: number
|
|
34
|
-
page?: number
|
|
39
|
+
spotId?: string
|
|
40
|
+
type?: ProductType
|
|
41
|
+
status?: ProductStatus
|
|
42
|
+
limit?: number
|
|
43
|
+
page?: number
|
|
35
44
|
}
|
|
36
45
|
|
|
37
46
|
export interface ProductWithSpot extends Product {
|
|
38
|
-
spot:
|
|
39
|
-
id: string;
|
|
40
|
-
name: string;
|
|
41
|
-
slug: string;
|
|
42
|
-
};
|
|
47
|
+
spot: Pick<Spot, 'id' | 'name' | 'slug'>
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
// ============================================================================
|
|
@@ -49,75 +54,77 @@ export interface ProductWithSpot extends Product {
|
|
|
49
54
|
/**
|
|
50
55
|
* Get products for a spot (public browse)
|
|
51
56
|
*
|
|
52
|
-
* @endpoint GET /
|
|
57
|
+
* @endpoint GET /spots/{spotId}/products
|
|
53
58
|
*/
|
|
54
59
|
export function useSpotProducts(
|
|
55
60
|
spotId: string,
|
|
56
|
-
params?: {
|
|
57
|
-
options?: Omit<
|
|
61
|
+
params?: {type?: ProductType; limit?: number; page?: number},
|
|
62
|
+
options?: Omit<
|
|
63
|
+
UseQueryOptions<PaginatedResponse<Product>>,
|
|
64
|
+
'queryKey' | 'queryFn'
|
|
65
|
+
>,
|
|
58
66
|
): UseQueryResult<PaginatedResponse<Product>> {
|
|
59
67
|
return useQuery({
|
|
60
68
|
queryKey: productKeys.bySpot(spotId),
|
|
61
69
|
queryFn: async (): Promise<PaginatedResponse<Product>> => {
|
|
62
|
-
const client = getApiClient()
|
|
63
|
-
const queryParams = new URLSearchParams()
|
|
64
|
-
if (params?.limit) queryParams.set('limit', String(params.limit))
|
|
65
|
-
if (params?.page) queryParams.set('page', String(params.page))
|
|
66
|
-
if (params?.type) queryParams.set('type', params.type)
|
|
70
|
+
const client = getApiClient()
|
|
71
|
+
const queryParams = new URLSearchParams()
|
|
72
|
+
if (params?.limit) queryParams.set('limit', String(params.limit))
|
|
73
|
+
if (params?.page) queryParams.set('page', String(params.page))
|
|
74
|
+
if (params?.type) queryParams.set('type', params.type)
|
|
67
75
|
const response = await client.get<ApiResponse<PaginatedResponse<Product>>>(
|
|
68
|
-
`/
|
|
69
|
-
)
|
|
70
|
-
return response.data.data
|
|
76
|
+
`/spots/${spotId}/products?${queryParams}`,
|
|
77
|
+
)
|
|
78
|
+
return response.data.data
|
|
71
79
|
},
|
|
72
80
|
enabled: !!spotId,
|
|
73
81
|
...options,
|
|
74
|
-
})
|
|
82
|
+
})
|
|
75
83
|
}
|
|
76
84
|
|
|
77
85
|
/**
|
|
78
86
|
* Get a product by ID
|
|
79
87
|
*
|
|
80
|
-
* @endpoint GET /
|
|
88
|
+
* @endpoint GET /products/{productId}
|
|
81
89
|
*/
|
|
82
90
|
export function useProduct(
|
|
83
91
|
productId: string,
|
|
84
|
-
options?: Omit<UseQueryOptions<ProductWithSpot>, 'queryKey' | 'queryFn'
|
|
92
|
+
options?: Omit<UseQueryOptions<ProductWithSpot>, 'queryKey' | 'queryFn'>,
|
|
85
93
|
): UseQueryResult<ProductWithSpot> {
|
|
86
94
|
return useQuery({
|
|
87
95
|
queryKey: productKeys.detail(productId),
|
|
88
96
|
queryFn: async (): Promise<ProductWithSpot> => {
|
|
89
|
-
const client = getApiClient()
|
|
90
|
-
const response = await client.get<ApiResponse<ProductWithSpot>>(
|
|
91
|
-
|
|
97
|
+
const client = getApiClient()
|
|
98
|
+
const response = await client.get<ApiResponse<ProductWithSpot>>(
|
|
99
|
+
`/products/${productId}`,
|
|
100
|
+
)
|
|
101
|
+
return response.data.data
|
|
92
102
|
},
|
|
93
103
|
enabled: !!productId,
|
|
94
104
|
...options,
|
|
95
|
-
})
|
|
105
|
+
})
|
|
96
106
|
}
|
|
97
107
|
|
|
98
108
|
/**
|
|
99
109
|
* Get a product by slug (within a spot)
|
|
100
110
|
*
|
|
101
|
-
* @endpoint GET /
|
|
111
|
+
* @endpoint GET /spots/{spotId}/products/slug/{slug}
|
|
102
112
|
*/
|
|
103
113
|
export function useProductBySlug(
|
|
104
114
|
spotId: string,
|
|
105
115
|
slug: string,
|
|
106
|
-
options?: Omit<UseQueryOptions<ProductWithSpot>, 'queryKey' | 'queryFn'
|
|
116
|
+
options?: Omit<UseQueryOptions<ProductWithSpot>, 'queryKey' | 'queryFn'>,
|
|
107
117
|
): UseQueryResult<ProductWithSpot> {
|
|
108
118
|
return useQuery({
|
|
109
119
|
queryKey: productKeys.bySlug(spotId, slug),
|
|
110
120
|
queryFn: async (): Promise<ProductWithSpot> => {
|
|
111
|
-
const client = getApiClient()
|
|
121
|
+
const client = getApiClient()
|
|
112
122
|
const response = await client.get<ApiResponse<ProductWithSpot>>(
|
|
113
|
-
`/
|
|
114
|
-
)
|
|
115
|
-
return response.data.data
|
|
123
|
+
`/spots/${spotId}/products/slug/${slug}`,
|
|
124
|
+
)
|
|
125
|
+
return response.data.data
|
|
116
126
|
},
|
|
117
127
|
enabled: !!spotId && !!slug,
|
|
118
128
|
...options,
|
|
119
|
-
})
|
|
129
|
+
})
|
|
120
130
|
}
|
|
121
|
-
|
|
122
|
-
// Note: To list products as a seller, use useSpotProducts with your spot ID.
|
|
123
|
-
// There is no cross-spot product listing endpoint currently.
|