@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/spots.ts
CHANGED
|
@@ -4,9 +4,62 @@
|
|
|
4
4
|
* TanStack Query hooks for spot-related operations.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
import {
|
|
8
|
+
useQuery,
|
|
9
|
+
useInfiniteQuery,
|
|
10
|
+
type UseQueryOptions,
|
|
11
|
+
type UseQueryResult,
|
|
12
|
+
type UseInfiniteQueryOptions,
|
|
13
|
+
type UseInfiniteQueryResult,
|
|
14
|
+
} from '@tanstack/react-query'
|
|
15
|
+
|
|
16
|
+
import {getApiClient} from '../client'
|
|
17
|
+
import {type ApiResponse, type PaginatedResponse, type Spot, type SpotImage} from '../types'
|
|
18
|
+
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// HELPER FUNCTIONS
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Extract array data from API response
|
|
25
|
+
* API returns { success, data: { data: [...], meta: {...} } } or { success, data: [...] }
|
|
26
|
+
*/
|
|
27
|
+
function extractArrayData<T>(data: unknown): T[] {
|
|
28
|
+
if (Array.isArray(data)) {
|
|
29
|
+
return data
|
|
30
|
+
}
|
|
31
|
+
if (data && typeof data === 'object' && 'data' in data) {
|
|
32
|
+
const nested = (data as {data: unknown}).data
|
|
33
|
+
if (Array.isArray(nested)) {
|
|
34
|
+
return nested
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return []
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Extract single object data from API response
|
|
42
|
+
*/
|
|
43
|
+
function extractObjectData<T>(data: unknown): T {
|
|
44
|
+
if (
|
|
45
|
+
data &&
|
|
46
|
+
typeof data === 'object' &&
|
|
47
|
+
'data' in data &&
|
|
48
|
+
!Array.isArray(data)
|
|
49
|
+
) {
|
|
50
|
+
const nested = (data as {data: unknown}).data
|
|
51
|
+
if (
|
|
52
|
+
nested &&
|
|
53
|
+
typeof nested === 'object' &&
|
|
54
|
+
'data' in nested &&
|
|
55
|
+
!Array.isArray(nested)
|
|
56
|
+
) {
|
|
57
|
+
return (nested as {data: T}).data
|
|
58
|
+
}
|
|
59
|
+
return nested as T
|
|
60
|
+
}
|
|
61
|
+
return data as T
|
|
62
|
+
}
|
|
10
63
|
|
|
11
64
|
// ============================================================================
|
|
12
65
|
// QUERY KEYS
|
|
@@ -15,187 +68,265 @@ import type { Spot, SpotImage, ApiResponse, PaginatedResponse } from '../types';
|
|
|
15
68
|
export const spotKeys = {
|
|
16
69
|
all: ['spots'] as const,
|
|
17
70
|
lists: () => [...spotKeys.all, 'list'] as const,
|
|
18
|
-
list: (filters?: Record<string, unknown>) =>
|
|
71
|
+
list: (filters?: Record<string, unknown>) =>
|
|
72
|
+
[...spotKeys.lists(), filters] as const,
|
|
19
73
|
details: () => [...spotKeys.all, 'detail'] as const,
|
|
20
74
|
detail: (id: string) => [...spotKeys.details(), id] as const,
|
|
21
75
|
bySlug: (slug: string) => [...spotKeys.all, 'slug', slug] as const,
|
|
22
76
|
byQR: (qrCode: string) => [...spotKeys.all, 'qr', qrCode] as const,
|
|
23
77
|
images: (spotId: string) => [...spotKeys.detail(spotId), 'images'] as const,
|
|
24
|
-
}
|
|
78
|
+
}
|
|
25
79
|
|
|
26
80
|
// ============================================================================
|
|
27
81
|
// QUERY HOOKS
|
|
28
82
|
// ============================================================================
|
|
29
83
|
|
|
30
84
|
/**
|
|
31
|
-
* Get all spots
|
|
85
|
+
* Get all spots
|
|
32
86
|
*
|
|
33
|
-
* @endpoint GET /
|
|
34
|
-
* @returns PaginatedResponse with spots array and meta
|
|
87
|
+
* @endpoint GET /spots
|
|
35
88
|
*/
|
|
36
89
|
export function useSpots(
|
|
37
90
|
params?: {
|
|
38
|
-
limit?: number
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
search?: string
|
|
91
|
+
limit?: number
|
|
92
|
+
city?: string
|
|
93
|
+
type?: string
|
|
94
|
+
lat?: number
|
|
95
|
+
lng?: number
|
|
96
|
+
radius?: number
|
|
97
|
+
search?: string
|
|
98
|
+
vibes?: string
|
|
99
|
+
cityId?: string
|
|
100
|
+
page?: number
|
|
45
101
|
},
|
|
46
|
-
options?: Omit<UseQueryOptions<
|
|
47
|
-
): UseQueryResult<
|
|
102
|
+
options?: Omit<UseQueryOptions<Spot[]>, 'queryKey' | 'queryFn'>,
|
|
103
|
+
): UseQueryResult<Spot[]> {
|
|
48
104
|
return useQuery({
|
|
49
105
|
queryKey: spotKeys.list(params),
|
|
50
|
-
queryFn: async (): Promise<
|
|
51
|
-
const client = getApiClient()
|
|
52
|
-
const queryParams = new URLSearchParams()
|
|
53
|
-
if (params?.limit) queryParams.set('limit', String(params.limit))
|
|
54
|
-
if (params?.
|
|
55
|
-
if (params?.
|
|
56
|
-
if (params?.
|
|
57
|
-
if (params?.
|
|
58
|
-
if (params?.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (params?.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
106
|
+
queryFn: async (): Promise<Spot[]> => {
|
|
107
|
+
const client = getApiClient()
|
|
108
|
+
const queryParams = new URLSearchParams()
|
|
109
|
+
if (params?.limit) queryParams.set('limit', String(params.limit))
|
|
110
|
+
if (params?.city) queryParams.set('city', params.city)
|
|
111
|
+
if (params?.type) queryParams.set('type', params.type)
|
|
112
|
+
if (params?.lat) queryParams.set('lat', String(params.lat))
|
|
113
|
+
if (params?.lng) queryParams.set('lng', String(params.lng))
|
|
114
|
+
if (params?.radius) queryParams.set('radius', String(params.radius))
|
|
115
|
+
if (params?.search) queryParams.set('search', params.search)
|
|
116
|
+
if (params?.vibes) queryParams.set('vibeIds', params.vibes)
|
|
117
|
+
if (params?.cityId) queryParams.set('cityId', params.cityId)
|
|
118
|
+
if (params?.page) queryParams.set('page', String(params.page))
|
|
119
|
+
const response = await client.get<ApiResponse<unknown>>(
|
|
120
|
+
`/spots?${queryParams}`,
|
|
121
|
+
)
|
|
122
|
+
return extractArrayData<Spot>(response.data.data)
|
|
66
123
|
},
|
|
67
124
|
...options,
|
|
68
|
-
})
|
|
125
|
+
})
|
|
69
126
|
}
|
|
70
127
|
|
|
71
128
|
/**
|
|
72
129
|
* Get a spot by ID
|
|
73
130
|
*
|
|
74
|
-
* @endpoint GET /
|
|
131
|
+
* @endpoint GET /spots/{spotId}
|
|
75
132
|
*/
|
|
76
133
|
export function useSpot(
|
|
77
134
|
spotId: string,
|
|
78
|
-
options?: Omit<UseQueryOptions<Spot>, 'queryKey' | 'queryFn'
|
|
135
|
+
options?: Omit<UseQueryOptions<Spot>, 'queryKey' | 'queryFn'>,
|
|
79
136
|
): UseQueryResult<Spot> {
|
|
80
137
|
return useQuery({
|
|
81
138
|
queryKey: spotKeys.detail(spotId),
|
|
82
139
|
queryFn: async (): Promise<Spot> => {
|
|
83
|
-
const client = getApiClient()
|
|
84
|
-
const response = await client.get<ApiResponse<
|
|
85
|
-
|
|
140
|
+
const client = getApiClient()
|
|
141
|
+
const response = await client.get<ApiResponse<unknown>>(
|
|
142
|
+
`/spots/${spotId}`,
|
|
143
|
+
)
|
|
144
|
+
return extractObjectData<Spot>(response.data.data)
|
|
86
145
|
},
|
|
87
146
|
enabled: !!spotId,
|
|
88
147
|
...options,
|
|
89
|
-
})
|
|
148
|
+
})
|
|
90
149
|
}
|
|
91
150
|
|
|
92
151
|
/**
|
|
93
152
|
* Get a spot by slug
|
|
94
153
|
*
|
|
95
|
-
* @endpoint GET /
|
|
154
|
+
* @endpoint GET /spots/slug/{slug}
|
|
96
155
|
*/
|
|
97
156
|
export function useSpotBySlug(
|
|
98
157
|
slug: string,
|
|
99
|
-
options?: Omit<UseQueryOptions<Spot>, 'queryKey' | 'queryFn'
|
|
158
|
+
options?: Omit<UseQueryOptions<Spot>, 'queryKey' | 'queryFn'>,
|
|
100
159
|
): UseQueryResult<Spot> {
|
|
101
160
|
return useQuery({
|
|
102
161
|
queryKey: spotKeys.bySlug(slug),
|
|
103
162
|
queryFn: async (): Promise<Spot> => {
|
|
104
|
-
const client = getApiClient()
|
|
105
|
-
const response = await client.get<ApiResponse<
|
|
106
|
-
|
|
163
|
+
const client = getApiClient()
|
|
164
|
+
const response = await client.get<ApiResponse<unknown>>(
|
|
165
|
+
`/spots/slug/${slug}`,
|
|
166
|
+
)
|
|
167
|
+
return extractObjectData<Spot>(response.data.data)
|
|
107
168
|
},
|
|
108
169
|
enabled: !!slug,
|
|
109
170
|
...options,
|
|
110
|
-
})
|
|
171
|
+
})
|
|
111
172
|
}
|
|
112
173
|
|
|
113
174
|
/**
|
|
114
175
|
* Get a spot by QR code
|
|
115
176
|
*
|
|
116
|
-
* @endpoint GET /
|
|
177
|
+
* @endpoint GET /spots/qr/{qrCode}
|
|
117
178
|
*/
|
|
118
179
|
export function useSpotByQR(
|
|
119
180
|
qrCode: string,
|
|
120
|
-
options?: Omit<UseQueryOptions<Spot>, 'queryKey' | 'queryFn'
|
|
181
|
+
options?: Omit<UseQueryOptions<Spot>, 'queryKey' | 'queryFn'>,
|
|
121
182
|
): UseQueryResult<Spot> {
|
|
122
183
|
return useQuery({
|
|
123
184
|
queryKey: spotKeys.byQR(qrCode),
|
|
124
185
|
queryFn: async (): Promise<Spot> => {
|
|
125
|
-
const client = getApiClient()
|
|
126
|
-
const response = await client.get<ApiResponse<
|
|
127
|
-
|
|
186
|
+
const client = getApiClient()
|
|
187
|
+
const response = await client.get<ApiResponse<unknown>>(
|
|
188
|
+
`/spots/qr/${qrCode}`,
|
|
189
|
+
)
|
|
190
|
+
return extractObjectData<Spot>(response.data.data)
|
|
128
191
|
},
|
|
129
192
|
enabled: !!qrCode,
|
|
130
193
|
...options,
|
|
131
|
-
})
|
|
194
|
+
})
|
|
132
195
|
}
|
|
133
196
|
|
|
134
197
|
/**
|
|
135
198
|
* Get images for a spot
|
|
136
199
|
*
|
|
137
|
-
* @endpoint GET /
|
|
200
|
+
* @endpoint GET /spots/{spotId}/images
|
|
138
201
|
*/
|
|
139
202
|
export function useSpotImages(
|
|
140
203
|
spotId: string,
|
|
141
|
-
options?: Omit<UseQueryOptions<SpotImage[]>, 'queryKey' | 'queryFn'
|
|
204
|
+
options?: Omit<UseQueryOptions<SpotImage[]>, 'queryKey' | 'queryFn'>,
|
|
142
205
|
): UseQueryResult<SpotImage[]> {
|
|
143
206
|
return useQuery({
|
|
144
207
|
queryKey: spotKeys.images(spotId),
|
|
145
208
|
queryFn: async (): Promise<SpotImage[]> => {
|
|
146
|
-
const client = getApiClient()
|
|
147
|
-
const response = await client.get<ApiResponse<
|
|
148
|
-
|
|
209
|
+
const client = getApiClient()
|
|
210
|
+
const response = await client.get<ApiResponse<unknown>>(
|
|
211
|
+
`/spots/${spotId}/images`,
|
|
212
|
+
)
|
|
213
|
+
return extractArrayData<SpotImage>(response.data.data)
|
|
149
214
|
},
|
|
150
215
|
enabled: !!spotId,
|
|
151
216
|
...options,
|
|
152
|
-
})
|
|
217
|
+
})
|
|
153
218
|
}
|
|
154
219
|
|
|
155
220
|
/**
|
|
156
|
-
*
|
|
221
|
+
* Check if a spot is favorited by the current user
|
|
157
222
|
*
|
|
158
|
-
* @endpoint GET /
|
|
159
|
-
|
|
223
|
+
* @endpoint GET /spots/{spotId}/favorite
|
|
224
|
+
*/
|
|
225
|
+
export function useSpotFavoriteStatus(
|
|
226
|
+
spotId: string,
|
|
227
|
+
options?: Omit<
|
|
228
|
+
UseQueryOptions<{isFavorite: boolean}>,
|
|
229
|
+
'queryKey' | 'queryFn'
|
|
230
|
+
>,
|
|
231
|
+
): UseQueryResult<{isFavorite: boolean}> {
|
|
232
|
+
return useQuery({
|
|
233
|
+
queryKey: [...spotKeys.detail(spotId), 'favorite'] as const,
|
|
234
|
+
queryFn: async (): Promise<{isFavorite: boolean}> => {
|
|
235
|
+
const client = getApiClient()
|
|
236
|
+
const response = await client.get<ApiResponse<{isFavorite: boolean}>>(
|
|
237
|
+
`/spots/${spotId}/favorite`,
|
|
238
|
+
)
|
|
239
|
+
return extractObjectData<{isFavorite: boolean}>(response.data.data)
|
|
240
|
+
},
|
|
241
|
+
enabled: !!spotId,
|
|
242
|
+
...options,
|
|
243
|
+
})
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// ============================================================================
|
|
247
|
+
// INFINITE QUERY HOOKS
|
|
248
|
+
// ============================================================================
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Params for infinite spots query
|
|
160
252
|
*/
|
|
161
253
|
export interface InfiniteSpotsParams {
|
|
162
|
-
limit?: number
|
|
163
|
-
city?: string
|
|
164
|
-
cityId?: string
|
|
165
|
-
type?: string
|
|
166
|
-
templateSlugs?: string[]
|
|
167
|
-
vibeIds?: string[]
|
|
168
|
-
search?: string
|
|
254
|
+
limit?: number
|
|
255
|
+
city?: string
|
|
256
|
+
cityId?: string
|
|
257
|
+
type?: string
|
|
258
|
+
templateSlugs?: string[]
|
|
259
|
+
vibeIds?: string[]
|
|
260
|
+
search?: string
|
|
169
261
|
}
|
|
170
262
|
|
|
263
|
+
/**
|
|
264
|
+
* Infinite scroll query for spots
|
|
265
|
+
*
|
|
266
|
+
* @endpoint GET /spots (paginated)
|
|
267
|
+
* @returns Infinite query with pages of spots
|
|
268
|
+
*/
|
|
171
269
|
export function useInfiniteSpots(
|
|
172
270
|
params?: InfiniteSpotsParams,
|
|
173
|
-
options?: Omit<
|
|
174
|
-
|
|
271
|
+
options?: Omit<
|
|
272
|
+
UseInfiniteQueryOptions<
|
|
273
|
+
PaginatedResponse<Spot>,
|
|
274
|
+
Error,
|
|
275
|
+
{pages: PaginatedResponse<Spot>[]; pageParams: number[]}
|
|
276
|
+
>,
|
|
277
|
+
'queryKey' | 'queryFn' | 'getNextPageParam' | 'initialPageParam'
|
|
278
|
+
>,
|
|
279
|
+
): UseInfiniteQueryResult<
|
|
280
|
+
{pages: PaginatedResponse<Spot>[]; pageParams: number[]},
|
|
281
|
+
Error
|
|
282
|
+
> {
|
|
175
283
|
return useInfiniteQuery({
|
|
176
284
|
queryKey: [...spotKeys.lists(), 'infinite', params] as const,
|
|
177
|
-
queryFn: async ({
|
|
178
|
-
const client = getApiClient()
|
|
179
|
-
const queryParams = new URLSearchParams()
|
|
180
|
-
queryParams.set('page', String(pageParam))
|
|
181
|
-
if (params?.limit) queryParams.set('limit', String(params.limit))
|
|
182
|
-
if (params?.city) queryParams.set('city', params.city)
|
|
183
|
-
if (params?.cityId) queryParams.set('cityId', params.cityId)
|
|
184
|
-
if (params?.type && params.type !== 'All')
|
|
185
|
-
|
|
285
|
+
queryFn: async ({pageParam = 1}): Promise<PaginatedResponse<Spot>> => {
|
|
286
|
+
const client = getApiClient()
|
|
287
|
+
const queryParams = new URLSearchParams()
|
|
288
|
+
queryParams.set('page', String(pageParam))
|
|
289
|
+
if (params?.limit) queryParams.set('limit', String(params.limit))
|
|
290
|
+
if (params?.city) queryParams.set('city', params.city)
|
|
291
|
+
if (params?.cityId) queryParams.set('cityId', params.cityId)
|
|
292
|
+
if (params?.type && params.type !== 'All')
|
|
293
|
+
queryParams.set('type', params.type)
|
|
294
|
+
if (params?.search?.trim())
|
|
295
|
+
queryParams.set('search', params.search.trim())
|
|
186
296
|
if (params?.templateSlugs) {
|
|
187
|
-
params.templateSlugs.forEach(slug =>
|
|
297
|
+
params.templateSlugs.forEach((slug) =>
|
|
298
|
+
queryParams.append('templateSlugs', slug),
|
|
299
|
+
)
|
|
188
300
|
}
|
|
189
301
|
if (params?.vibeIds) {
|
|
190
|
-
params.vibeIds.forEach(id => queryParams.append('vibeIds', id))
|
|
302
|
+
params.vibeIds.forEach((id) => queryParams.append('vibeIds', id))
|
|
303
|
+
}
|
|
304
|
+
const response = await client.get<ApiResponse<PaginatedResponse<Spot>>>(
|
|
305
|
+
`/spots?${queryParams}`,
|
|
306
|
+
)
|
|
307
|
+
// Handle nested response structure
|
|
308
|
+
const data = response.data.data
|
|
309
|
+
if (data && typeof data === 'object' && 'data' in data) {
|
|
310
|
+
return data as PaginatedResponse<Spot>
|
|
311
|
+
}
|
|
312
|
+
// Fallback for array response
|
|
313
|
+
const page = pageParam as number
|
|
314
|
+
return {
|
|
315
|
+
data: extractArrayData<Spot>(data),
|
|
316
|
+
meta: {
|
|
317
|
+
total: 0,
|
|
318
|
+
page,
|
|
319
|
+
limit: params?.limit || 20,
|
|
320
|
+
totalPages: 1,
|
|
321
|
+
hasNextPage: false,
|
|
322
|
+
hasPreviousPage: page > 1,
|
|
323
|
+
},
|
|
191
324
|
}
|
|
192
|
-
const response = await client.get<ApiResponse<PaginatedResponse<Spot>>>(`/api/v1/spots?${queryParams}`);
|
|
193
|
-
return response.data.data;
|
|
194
325
|
},
|
|
195
326
|
initialPageParam: 1,
|
|
196
327
|
getNextPageParam: (lastPage) => {
|
|
197
|
-
return lastPage.meta.hasNextPage ? lastPage.meta.page + 1 : undefined
|
|
328
|
+
return lastPage.meta.hasNextPage ? lastPage.meta.page + 1 : undefined
|
|
198
329
|
},
|
|
199
330
|
...options,
|
|
200
|
-
})
|
|
331
|
+
})
|
|
201
332
|
}
|
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
* Templates Query Hooks
|
|
3
3
|
*
|
|
4
4
|
* TanStack Query hooks for post template operations.
|
|
5
|
-
*
|
|
6
|
-
* Templates are reference data (flat array), not paginated.
|
|
7
5
|
*/
|
|
8
6
|
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
import {
|
|
8
|
+
useQuery,
|
|
9
|
+
type UseQueryOptions,
|
|
10
|
+
type UseQueryResult,
|
|
11
|
+
} from '@tanstack/react-query'
|
|
12
|
+
|
|
13
|
+
import {getApiClient} from '../client'
|
|
14
|
+
import {type ApiResponse, type Template} from '../types'
|
|
12
15
|
|
|
13
16
|
// ============================================================================
|
|
14
17
|
// QUERY KEYS
|
|
@@ -17,79 +20,83 @@ import type { Template, ApiResponse } from '../types';
|
|
|
17
20
|
export const templateKeys = {
|
|
18
21
|
all: ['templates'] as const,
|
|
19
22
|
lists: () => [...templateKeys.all, 'list'] as const,
|
|
20
|
-
list: (filters?: {
|
|
23
|
+
list: (filters?: {spotType?: string}) =>
|
|
24
|
+
[...templateKeys.lists(), filters] as const,
|
|
21
25
|
details: () => [...templateKeys.all, 'detail'] as const,
|
|
22
26
|
detail: (id: string) => [...templateKeys.details(), id] as const,
|
|
23
27
|
bySlug: (slug: string) => [...templateKeys.all, 'slug', slug] as const,
|
|
24
|
-
}
|
|
28
|
+
}
|
|
25
29
|
|
|
26
30
|
// ============================================================================
|
|
27
31
|
// QUERY HOOKS
|
|
28
32
|
// ============================================================================
|
|
29
33
|
|
|
30
34
|
/**
|
|
31
|
-
* Get all templates
|
|
35
|
+
* Get all templates
|
|
32
36
|
*
|
|
33
|
-
* @endpoint GET /
|
|
34
|
-
* @returns Flat array of templates (not paginated)
|
|
37
|
+
* @endpoint GET /templates
|
|
35
38
|
*/
|
|
36
39
|
export function useTemplates(
|
|
37
|
-
params?: {
|
|
38
|
-
options?: Omit<UseQueryOptions<Template[]>, 'queryKey' | 'queryFn'
|
|
40
|
+
params?: {spotType?: string},
|
|
41
|
+
options?: Omit<UseQueryOptions<Template[]>, 'queryKey' | 'queryFn'>,
|
|
39
42
|
): UseQueryResult<Template[]> {
|
|
40
43
|
return useQuery({
|
|
41
44
|
queryKey: templateKeys.list(params),
|
|
42
45
|
queryFn: async (): Promise<Template[]> => {
|
|
43
|
-
const client = getApiClient()
|
|
44
|
-
const queryParams = new URLSearchParams()
|
|
45
|
-
if (params?.spotType) queryParams.set('spotType', params.spotType)
|
|
46
|
-
const response = await client.get<ApiResponse<Template[]>>(
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
const client = getApiClient()
|
|
47
|
+
const queryParams = new URLSearchParams()
|
|
48
|
+
if (params?.spotType) queryParams.set('spotType', params.spotType)
|
|
49
|
+
const response = await client.get<ApiResponse<Template[]>>(
|
|
50
|
+
`/templates?${queryParams}`,
|
|
51
|
+
)
|
|
52
|
+
return response.data.data
|
|
49
53
|
},
|
|
50
|
-
staleTime: 1000 * 60 * 60, // Cache for 1 hour (reference data)
|
|
51
54
|
...options,
|
|
52
|
-
})
|
|
55
|
+
})
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
/**
|
|
56
59
|
* Get a template by ID
|
|
57
60
|
*
|
|
58
|
-
* @endpoint GET /
|
|
61
|
+
* @endpoint GET /templates/{templateId}
|
|
59
62
|
*/
|
|
60
63
|
export function useTemplate(
|
|
61
64
|
templateId: string,
|
|
62
|
-
options?: Omit<UseQueryOptions<Template>, 'queryKey' | 'queryFn'
|
|
65
|
+
options?: Omit<UseQueryOptions<Template>, 'queryKey' | 'queryFn'>,
|
|
63
66
|
): UseQueryResult<Template> {
|
|
64
67
|
return useQuery({
|
|
65
68
|
queryKey: templateKeys.detail(templateId),
|
|
66
69
|
queryFn: async (): Promise<Template> => {
|
|
67
|
-
const client = getApiClient()
|
|
68
|
-
const response = await client.get<ApiResponse<Template>>(
|
|
69
|
-
|
|
70
|
+
const client = getApiClient()
|
|
71
|
+
const response = await client.get<ApiResponse<Template>>(
|
|
72
|
+
`/templates/${templateId}`,
|
|
73
|
+
)
|
|
74
|
+
return response.data.data
|
|
70
75
|
},
|
|
71
76
|
enabled: !!templateId,
|
|
72
77
|
...options,
|
|
73
|
-
})
|
|
78
|
+
})
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
/**
|
|
77
82
|
* Get a template by slug
|
|
78
83
|
*
|
|
79
|
-
* @endpoint GET /
|
|
84
|
+
* @endpoint GET /templates/slug/{slug}
|
|
80
85
|
*/
|
|
81
86
|
export function useTemplateBySlug(
|
|
82
87
|
slug: string,
|
|
83
|
-
options?: Omit<UseQueryOptions<Template>, 'queryKey' | 'queryFn'
|
|
88
|
+
options?: Omit<UseQueryOptions<Template>, 'queryKey' | 'queryFn'>,
|
|
84
89
|
): UseQueryResult<Template> {
|
|
85
90
|
return useQuery({
|
|
86
91
|
queryKey: templateKeys.bySlug(slug),
|
|
87
92
|
queryFn: async (): Promise<Template> => {
|
|
88
|
-
const client = getApiClient()
|
|
89
|
-
const response = await client.get<ApiResponse<Template>>(
|
|
90
|
-
|
|
93
|
+
const client = getApiClient()
|
|
94
|
+
const response = await client.get<ApiResponse<Template>>(
|
|
95
|
+
`/templates/slug/${slug}`,
|
|
96
|
+
)
|
|
97
|
+
return response.data.data
|
|
91
98
|
},
|
|
92
99
|
enabled: !!slug,
|
|
93
100
|
...options,
|
|
94
|
-
})
|
|
101
|
+
})
|
|
95
102
|
}
|