1
1
import type { UseFileUploadReturn } from "@chakra-ui/react" ;
2
- import { useQuery } from "@tanstack/react-query" ;
2
+ import {
3
+ useInfiniteQuery ,
4
+ useQuery ,
5
+ type DefaultError ,
6
+ type InfiniteData ,
7
+ type QueryKey ,
8
+ } from "@tanstack/react-query" ;
3
9
import { isParquetFile , useDuckDb } from "duckdb-wasm-kit" ;
4
10
import { useEffect , useState } from "react" ;
5
- import type { StacCollection } from "stac-ts" ;
11
+ import type { StacCollection , StacItem } from "stac-ts" ;
6
12
import { toaster } from "../ui/toaster" ;
7
13
import type {
8
14
NaturalLanguageCollectionSearchResult ,
9
15
StacCollections ,
10
16
StacItemCollection ,
17
+ StacSearchRequest ,
11
18
StacValue ,
12
19
} from "./types" ;
13
20
@@ -79,6 +86,7 @@ export function useStacValue(
79
86
return null ;
80
87
}
81
88
} ,
89
+ enabled : ! ! href ,
82
90
} ) ;
83
91
84
92
useEffect ( ( ) => {
@@ -110,7 +118,6 @@ export function useStacValue(
110
118
111
119
export function useStacCollections ( href : string | undefined ) {
112
120
const [ currentHref , setCurrentHref ] = useState < string | undefined > ( ) ;
113
- const [ pages , setPages ] = useState < StacCollections [ ] > ( [ ] ) ;
114
121
const [ collections , setCollections ] = useState <
115
122
StacCollection [ ] | undefined
116
123
> ( ) ;
@@ -131,11 +138,11 @@ export function useStacCollections(href: string | undefined) {
131
138
return null ;
132
139
}
133
140
} ,
141
+ enabled : ! ! href ,
134
142
} ) ;
135
143
136
144
useEffect ( ( ) => {
137
145
setCurrentHref ( href ) ;
138
- setPages ( [ ] ) ;
139
146
setCollections ( undefined ) ;
140
147
} , [ href ] ) ;
141
148
@@ -151,7 +158,10 @@ export function useStacCollections(href: string | undefined) {
151
158
152
159
useEffect ( ( ) => {
153
160
if ( data ) {
154
- setPages ( ( pages ) => [ ...pages , data ] ) ;
161
+ setCollections ( ( collections ) => [
162
+ ...( collections ?? [ ] ) ,
163
+ ...data . collections ,
164
+ ] ) ;
155
165
if ( data ) {
156
166
const nextLink = data . links ?. find ( ( link ) => link . rel == "next" ) ;
157
167
if ( nextLink ) {
@@ -161,15 +171,103 @@ export function useStacCollections(href: string | undefined) {
161
171
}
162
172
} , [ data ] ) ;
163
173
174
+ return { collections, isPending, error } ;
175
+ }
176
+
177
+ export function useItemSearch ( searchRequest : StacSearchRequest | undefined ) {
178
+ const [ items , setItems ] = useState < StacItem [ ] | undefined > ( ) ;
179
+ const [ numberMatched , setNumberMatched ] = useState < number | undefined > ( ) ;
180
+
181
+ const { data, error, hasNextPage, isFetching, fetchNextPage } =
182
+ useInfiniteQuery <
183
+ StacItemCollection | null ,
184
+ DefaultError ,
185
+ InfiniteData < StacItemCollection | null > ,
186
+ QueryKey ,
187
+ StacSearchRequest | undefined
188
+ > ( {
189
+ queryKey : [ "item-search" , searchRequest ] ,
190
+ queryFn : async ( { pageParam } ) => {
191
+ if ( pageParam ) {
192
+ const url = new URL ( pageParam . link . href ) ;
193
+ const method = ( pageParam . link . method as string | undefined ) || "GET" ;
194
+ const init : RequestInit = {
195
+ method,
196
+ headers : {
197
+ Accept : "application/json" ,
198
+ "Content-Type" : "application/json" ,
199
+ } ,
200
+ } ;
201
+ if ( method === "GET" ) {
202
+ if ( pageParam . search . collections ) {
203
+ url . searchParams . set (
204
+ "collections" ,
205
+ pageParam . search . collections . join ( "," ) ,
206
+ ) ;
207
+ }
208
+ } else {
209
+ if ( pageParam . link . body ) {
210
+ init . body = JSON . stringify ( pageParam . link . body ) ;
211
+ } else {
212
+ init . body = JSON . stringify ( pageParam . search ) ;
213
+ }
214
+ }
215
+ return await fetch ( url , init ) . then ( ( response ) => {
216
+ if ( response . ok ) {
217
+ return response . json ( ) ;
218
+ } else {
219
+ throw new Error (
220
+ `Error while searching ${ url } : ${ response . statusText } ` ,
221
+ ) ;
222
+ }
223
+ } ) ;
224
+ } else {
225
+ return null ;
226
+ }
227
+ } ,
228
+ initialPageParam : searchRequest ,
229
+ getNextPageParam : ( lastPage : StacItemCollection | null ) => {
230
+ if ( lastPage ) {
231
+ const nextLink = lastPage . links ?. find ( ( link ) => link . rel == "next" ) ;
232
+ if ( nextLink && searchRequest ) {
233
+ return {
234
+ search : searchRequest . search ,
235
+ link : nextLink ,
236
+ } ;
237
+ }
238
+ }
239
+ } ,
240
+ enabled : ! ! searchRequest ,
241
+ } ) ;
242
+
164
243
useEffect ( ( ) => {
165
- if ( pages . length > 0 ) {
166
- setCollections ( pages . flatMap ( ( page ) => page . collections ) ) ;
244
+ if ( data ) {
245
+ setItems ( data . pages . flatMap ( ( page ) => page ?. features || [ ] ) ) ;
246
+ if ( data . pages . length > 0 && data . pages [ 0 ] ?. numberMatched ) {
247
+ setNumberMatched ( data . pages [ 0 ] . numberMatched ) ;
248
+ }
167
249
} else {
168
- setCollections ( undefined ) ;
250
+ setItems ( undefined ) ;
169
251
}
170
- } , [ pages ] ) ;
252
+ } , [ data ] ) ;
171
253
172
- return { collections, isPending, error } ;
254
+ useEffect ( ( ) => {
255
+ if ( searchRequest && hasNextPage && ! isFetching ) {
256
+ fetchNextPage ( ) ;
257
+ }
258
+ } , [ searchRequest , hasNextPage , isFetching , fetchNextPage ] ) ;
259
+
260
+ useEffect ( ( ) => {
261
+ if ( error ) {
262
+ toaster . create ( {
263
+ type : "error" ,
264
+ title : "Error while searching" ,
265
+ description : error . message ,
266
+ } ) ;
267
+ }
268
+ } , [ error ] ) ;
269
+
270
+ return { items, hasNextPage, numberMatched } ;
173
271
}
174
272
175
273
export function useNaturalLanguageCollectionSearch (
0 commit comments