11import React , { useEffect , useMemo } from 'react' ;
2- import { Link , useParams } from 'react-router-dom' ;
2+ import { useParams } from 'react-router-dom' ;
33import {
44 Box ,
5- ListItem ,
65 Text ,
7- List ,
86 Tag ,
9- Icon ,
107 Button ,
118 Flex ,
129 IconButton ,
@@ -20,26 +17,25 @@ import {
2017 Grid ,
2118 GridItem ,
2219 HStack ,
23- VisuallyHidden
20+ VisuallyHidden ,
21+ Skeleton ,
22+ SkeletonText
2423} from '@chakra-ui/react' ;
25- import { MdAccessTime , MdBalance , MdEdit } from 'react-icons/md' ;
2624import { useCollection , useStacSearch } from '@developmentseed/stac-react' ;
2725import {
2826 CollecticonEllipsisVertical ,
2927 CollecticonPencil ,
30- CollecticonPlusSmall ,
3128 CollecticonTrashBin
3229} from '@devseed-ui/collecticons-chakra' ;
33- import { StacCollection } from 'stac-ts' ;
30+ import { StacCollection , StacItem } from 'stac-ts' ;
3431
35- import { Loading } from '../../components' ;
3632import { usePageTitle } from '../../hooks' ;
37- import ItemResults from '../../components/ItemResults' ;
3833import CollectionMap from './CollectionMap' ;
3934import SmartLink from '$components/SmartLink' ;
4035import { InnerPageHeader } from '$components/InnerPageHeader' ;
4136import { StacBrowserMenuItem } from '$components/StacBrowserMenuItem' ;
42- import ItemCard from '$components/ItemCard' ;
37+ import { ItemCard , ItemCardLoading } from '$components/ItemCard' ;
38+ import { zeroPad } from '$utils/format' ;
4339
4440const dateFormat : Intl . DateTimeFormatOptions = {
4541 year : 'numeric' ,
@@ -50,10 +46,20 @@ const dateFormat: Intl.DateTimeFormatOptions = {
5046function CollectionDetail ( ) {
5147 const { collectionId } = useParams ( ) ;
5248 usePageTitle ( `Collection ${ collectionId } ` ) ;
49+
50+ // const [urlParams, setUrlParams] = useSearchParams({ page: '1' });
51+ // const page = parseInt(urlParams.get('page') || '1', 10);
52+ // const setPage = useCallback(
53+ // (v: number | ((v: number) => number)) => {
54+ // const newVal = typeof v === 'function' ? v(page) : v;
55+ // setUrlParams({ page: newVal.toString() });
56+ // },
57+ // [page]
58+ // );
59+
5360 const { collection, state } = useCollection ( collectionId ! ) ; // eslint-disable-line @typescript-eslint/no-non-null-assertion
5461
55- const { results, collections, setCollections, submit, ...stacSearch } =
56- useStacSearch ( ) ;
62+ const { results, collections, setCollections, submit } = useStacSearch ( ) ;
5763
5864 // Initialize the search with the current collection ID
5965 useEffect ( ( ) => {
@@ -93,7 +99,22 @@ function CollectionDetail() {
9399 } , [ collection ] ) ;
94100
95101 if ( ! collection || state === 'LOADING' ) {
96- return < Loading > Loading collection...</ Loading > ;
102+ return (
103+ < Box p = { 8 } >
104+ < Flex direction = 'column' gap = { 4 } >
105+ < Skeleton h = { 6 } maxW = '25rem' />
106+ < Skeleton h = { 12 } maxW = '30rem' />
107+ </ Flex >
108+
109+ < SkeletonText
110+ mt = { 8 }
111+ noOfLines = { 4 }
112+ spacing = '4'
113+ skeletonHeight = '2'
114+ maxW = '50rem'
115+ />
116+ </ Box >
117+ ) ;
97118 }
98119
99120 const { id, title, description, keywords, license } =
@@ -103,7 +124,7 @@ function CollectionDetail() {
103124 < Flex direction = 'column' gap = { 8 } >
104125 < InnerPageHeader
105126 overline = 'Viewing Collection'
106- title = { id }
127+ title = { title || id }
107128 actions = {
108129 < >
109130 < Button
@@ -115,7 +136,7 @@ function CollectionDetail() {
115136 >
116137 Edit
117138 </ Button >
118- < Menu >
139+ < Menu placement = 'bottom-end' >
119140 < MenuButton
120141 as = { IconButton }
121142 aria-label = 'Options'
@@ -159,50 +180,47 @@ function CollectionDetail() {
159180 gap = { 4 }
160181 minH = '100%'
161182 >
162- < Flex direction = 'column' gap = '2' >
163- < Heading size = 'sm' as = 'h3' >
164- Description
165- </ Heading >
166- < Text size = 'md' >
167- Lorem ipsum dolor sit, amet consectetur adipisicing elit. Non
168- impedit vitae tempore repellat neque sunt aut, veniam facere,
169- corporis nihil voluptas quis quia magni.
170- </ Text >
171- </ Flex >
183+ { description && (
184+ < Flex direction = 'column' gap = '2' >
185+ < Heading size = 'sm' as = 'h3' >
186+ Description
187+ </ Heading >
188+ < Text size = 'md' > { description } </ Text >
189+ </ Flex >
190+ ) }
172191
173- < Flex direction = 'column' gap = '2' >
174- < Heading size = 'sm' as = 'h3' >
175- Temporal extent
176- </ Heading >
177- < Text size = 'md' > 2020-12-01 16:50:26 UTC</ Text >
178- </ Flex >
192+ { dateLabel && (
193+ < Flex direction = 'column' gap = '2' >
194+ < Heading size = 'sm' as = 'h3' >
195+ Temporal extent
196+ </ Heading >
197+ < Text size = 'md' > { dateLabel } </ Text >
198+ </ Flex >
199+ ) }
179200
180- < Flex direction = 'column' gap = '2' >
181- < Heading size = 'sm' as = 'h3' >
182- License
183- </ Heading >
184- < Text size = 'md' > CC-BY-4.0</ Text >
185- </ Flex >
201+ { license && (
202+ < Flex direction = 'column' gap = '2' >
203+ < Heading size = 'sm' as = 'h3' >
204+ License
205+ </ Heading >
206+ < Text size = 'md' > { license } </ Text >
207+ </ Flex >
208+ ) }
186209
187- < Flex direction = 'column' gap = '2' >
188- < Heading size = 'sm' as = 'h3' >
189- Keywords
190- </ Heading >
191- < HStack spacing = { 2 } >
192- < Tag size = 'md' colorScheme = 'primary' as = 'a' href = '#' >
193- Tag
194- </ Tag >
195- < Tag size = 'md' colorScheme = 'primary' as = 'a' href = '#' >
196- Tag
197- </ Tag >
198- < Tag size = 'md' colorScheme = 'primary' as = 'a' href = '#' >
199- Tag
200- </ Tag >
201- < Tag size = 'md' colorScheme = 'primary' as = 'a' href = '#' >
202- Tag
203- </ Tag >
204- </ HStack >
205- </ Flex >
210+ { keywords && (
211+ < Flex direction = 'column' gap = '2' >
212+ < Heading size = 'sm' as = 'h3' >
213+ Keywords
214+ </ Heading >
215+ < HStack spacing = { 2 } >
216+ { keywords . map ( ( keyword ) => (
217+ < Tag key = { keyword } size = 'md' colorScheme = 'primary' >
218+ { keyword }
219+ </ Tag >
220+ ) ) }
221+ </ HStack >
222+ </ Flex >
223+ ) }
206224 </ Flex >
207225 </ GridItem >
208226 < GridItem colSpan = { 4 } >
@@ -231,10 +249,13 @@ function CollectionDetail() {
231249 < Flex direction = 'row' px = '8' gap = '8' as = 'header' >
232250 < Box flexBasis = '100%' >
233251 < Heading size = 'md' as = 'h2' >
234- Items < Badge variant = 'solid' > 04</ Badge >
252+ Items{ ' ' }
253+ { results && (
254+ < Badge variant = 'solid' > { zeroPad ( results . numberMatched ) } </ Badge >
255+ ) }
235256 </ Heading >
236257 </ Box >
237- < Flex direction = 'row' gap = '4' >
258+ { /* <Flex direction='row' gap='4'>
238259 <Button
239260 as={SmartLink}
240261 to='/item/new'
@@ -244,70 +265,58 @@ function CollectionDetail() {
244265 >
245266 Add new
246267 </Button>
247- </ Flex >
268+ </Flex> */ }
248269 </ Flex >
249-
250270 < SimpleGrid
251271 gap = { 8 }
252272 templateColumns = 'repeat(auto-fill, minmax(18rem, 1fr))'
253273 >
254- < ItemCard />
255- < ItemCard />
256- < ItemCard />
257- < ItemCard />
274+ { results ? (
275+ results . features . map ( ( item : StacItem ) => (
276+ < ItemCard
277+ key = { item . id }
278+ title = { item . id }
279+ to = { `/collections/${ id } /items/${ item . id } ` }
280+ renderMenu = { ( ) => {
281+ return (
282+ < Menu placement = 'bottom-end' >
283+ < MenuButton
284+ as = { IconButton }
285+ aria-label = 'Options'
286+ icon = { < CollecticonEllipsisVertical /> }
287+ variant = 'outline'
288+ size = 'sm'
289+ />
290+ < MenuList >
291+ < StacBrowserMenuItem
292+ resourcePath = { `/collections/${ id } /items/${ item . id } ` }
293+ />
294+ < MenuItem
295+ as = { SmartLink }
296+ to = { `/collections/${ id } /items/${ item . id } ` }
297+ >
298+ View
299+ </ MenuItem >
300+ </ MenuList >
301+ </ Menu >
302+ ) ;
303+ } }
304+ />
305+ ) )
306+ ) : (
307+ < >
308+ < ItemCardLoading mini />
309+ < ItemCardLoading mini />
310+ < ItemCardLoading mini />
311+ < ItemCardLoading mini />
312+ </ >
313+ ) }
258314 </ SimpleGrid >
259315 </ Flex >
260316
261- < Box
262- display = 'grid'
263- gap = '8'
264- gridTemplateColumns = '2fr 1fr'
265- borderBottom = '1px solid'
266- borderColor = 'gray.200'
267- pb = '8'
268- >
269- < Box height = '250px' >
270- < CollectionMap collection = { collection } />
271- </ Box >
272- < Box fontSize = 'sm' >
273- < Box display = 'flex' gap = '4' alignItems = 'baseline' >
274- < Text as = 'h2' fontSize = 'md' my = '0' flex = '1' >
275- About
276- </ Text >
277- < Link to = 'edit/' title = 'Edit collection' >
278- < Icon as = { MdEdit } boxSize = '4' />
279- </ Link >
280- </ Box >
281- { ( title || description ) && (
282- < Text mt = '0' >
283- { title && < Text as = 'b' > { title } </ Text > }
284- { description }
285- </ Text >
286- ) }
287- < Box color = 'gray.600' my = '4' >
288- < Box display = 'flex' gap = '1' alignItems = 'center' mb = '1' >
289- < Icon color = 'gray.600' as = { MdAccessTime } boxSize = '4' />
290- < Text m = '0' > { dateLabel } </ Text >
291- </ Box >
292- < Box display = 'flex' gap = '1' alignItems = 'center' mb = '1' >
293- < Icon color = 'gray.600' as = { MdBalance } boxSize = '4' />
294- < Text m = '0' > { license } </ Text >
295- </ Box >
296- </ Box >
297- { keywords && keywords . length > 0 && (
298- < List mt = '1' >
299- { keywords . map ( ( keyword ) => (
300- < Tag mr = '1' as = { ListItem } key = { keyword } >
301- { keyword }
302- </ Tag >
303- ) ) }
304- </ List >
305- ) }
306- </ Box >
307- </ Box >
308-
309- < Text as = 'h2' > Items in this collection</ Text >
310- < ItemResults results = { results } submit = { submit } { ...stacSearch } />
317+ { /* <Flex direction='column' alignItems='center'>
318+ <Pagination numPages={20} page={page} onPageChange={setPage} />
319+ </Flex> */ }
311320 </ Flex >
312321 ) ;
313322}
0 commit comments