function search({ currentPage, query, results }) { const body = { query, page: currentPage, filters: "categories:widget AND tags:app AND NOT _tags:hidden", }; asyncFetch("/api/search", { body: JSON.stringify(body), headers: { "Content-Type": "application/json", }, method: "POST", }) .then((res) => { State.update({ isLoading: false, results: [...results, ...res.body.hits], totalPages: res.body.nbPages, totalResults: res.body.nbHits, }); }) .catch((error) => { State.update({ isLoading: false, }); console.log(error); }); } function handleOnInput() { State.update({ currentPage: 0, totalPages: 0, totalResults: 0, isLoading: true, results: [], }); } function handleOnQueryChange(query) { State.update({ query, }); search({ currentPage: 0, results: [], query, }); } function loadMore() { State.update({ currentPage: state.currentPage + 1, isLoading: true, }); search({ currentPage: state.currentPage, results: state.results, query: state.query, }); } State.init({ currentPage: 0, totalPages: 0, totalResults: 0, isLoading: false, query: "", results: [], }); if (!state.isLoading && state.results.length === 0 && state.query === "") { State.update({ isLoading: true, }); search({ currentPage: 0, results: [], query: "", }); } const Wrapper = styled.div` display: flex; width: 100%; flex-direction: column; gap: 3rem; `; const H2 = styled.h2` font: var(--text-l); color: var(--sand12); margin: 0; font-weight: 600; `; const Text = styled.p` font: var(--${(p) => p.size ?? "text-base"}); font-weight: ${(p) => p.fontWeight}; color: var(--${(p) => p.color ?? "sand12"}); margin: 0; `; const ContentGrid = styled.div` display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2rem; @media (max-width: 650px) { grid-template-columns: minmax(0, 1fr); } `; return ( <Wrapper> <Widget src="near/widget/DIG.InputSearch" props={{ onInput: handleOnInput, onQueryChange: handleOnQueryChange, placeholder: "Type keywords to search all apps...", }} /> {state.query && state.results.length === 0 && !state.isLoading && ( <Text>No apps matched your search: "{state.query}"</Text> )} {state.results.length > 0 && ( <> {state.query && <Text>Showing {state.totalResults} results</Text>} <ContentGrid> {state.results.map((result) => { return ( <Widget key={`${result.author}/widget/${result.widget_name}`} src="near/widget/AppLibrary.AppCard" props={{ src: `${result.author}/widget/${result.widget_name}`, metadata: { image: result.image, name: result.name, tags: result.tags, }, blockHeight: result.receipt_block_height, }} /> ); })} </ContentGrid> </> )} {state.currentPage + 1 < state.totalPages && ( <Widget src="near/widget/DIG.Button" props={{ label: "Load More", fill: "outline", variant: "secondary", loading: state.isLoading, onClick: loadMore, }} /> )} </Wrapper> );