import { __ } from '@wordpress/i18n' import React, { useId, useState } from 'react' import classnames from 'classnames' import { Spinner } from '@wordpress/components' import { useRestAPI } from '../../../hooks/useRestAPI' import { REST_BASES } from '../../../utils/restAPI' import { isCloudSnippetDownloadable } from '../../../utils/snippets/snippets' import { TableNav } from '../../common/ListTable/TableNavigation' import { LoadingStatusNotices } from '../../common/LoadingStatusNotices' import { SnippetViewToggle } from '../../common/SnippetViewToggle' import { CloudSnippetsTable } from './CloudSnippetsTable' import { CloudSnippetAuthor, SearchResult } from './SearchResult' import { useCloudSearch } from './WithCloudSearchContext' import { SearchFilters } from './SearchFilters' import type { CloudSearchResults } from './WithCloudSearchContext' import type { TableNavProps } from '../../common/ListTable/TableNavigation' import type { CloudSnippetSchema } from '../../../types/schema/CloudSnippetSchema' import type { SnippetView } from '../../../types/SnippetView' import type { ListTableAction } from '../../common/ListTable' import type { Dispatch, FormEventHandler, SetStateAction } from 'react' const SearchBox = () => { const { searchParams, updateSearchParams, isSearching, doSearch } = useCloudSearch() const searchMethodId = useId() const [query, setQuery] = useState(searchParams.query) const handleSubmit: FormEventHandler = event => { event.preventDefault() doSearch({ query }) } return (
setQuery(event.target.value)} placeholder={__('e.g. Remove unused JavaScript…', 'code-snippets')} /> {isSearching && ( {__('Searching…', 'code-snippets')} )}
) } interface SearchResultsGridProps { snippets: CloudSnippetSchema[] selected: Set setSelected: Dispatch>> } const SearchResultsGrid: React.FC = ({ snippets, selected, setSelected }) =>
    selected.has(snippet.id)) })} > {snippets.map(result => } isSelected={selected.has(result.id)} onSelectedChange={isCloudSnippetDownloadable(result) ? isSelected => { setSelected(previous => { const updated = new Set(previous) if (isSelected) { updated.add(result.id) } else { updated.delete(result.id) } return updated }) } : undefined} />)}
interface SearchResultsViewProps { snippetView: SnippetView setSnippetView: (view: SnippetView) => void } type CloudSearchAction = 'download' const CLOUD_BULK_ACTIONS: ListTableAction[] = [ { key: 'download', label: __('Download', 'code-snippets') } ] interface CloudSearchSnippetsProps { snippetView: SnippetView snippets: CloudSnippetSchema[] selected: Set setSelected: Dispatch>> } const CloudSearchSnippets: React.FC = ({ snippetView, ...props }) => 'card' === snippetView ? : interface SearchResultsTableNavProps extends Omit, 'totalItems' | 'totalPages' | 'currentPage' | 'setCurrentPage'> { which: 'top' | 'bottom' doSearch: ReturnType['doSearch'] isSearching: boolean searchResults: CloudSearchResults } const SearchResultsTableNav: React.FC = ({ which, doSearch, isSearching, searchResults, ...props }) => doSearch({ page })} {...props} /> const SearchResultsTable: React.FC = ({ snippetView, setSnippetView }) => { const { api } = useRestAPI() const { searchResults, isSearching, doSearch } = useCloudSearch() const [selected, setSelected] = useState>(new Set()) if (!searchResults) { return null } const doAction = async ( action: CloudSearchAction | undefined, selectedIds: Set ): Promise => { if ('download' === action) { await Promise.all(searchResults.snippets .filter(snippet => selectedIds.has(snippet.id) && isCloudSnippetDownloadable(snippet)) .map(({ id }) => api.post(`${REST_BASES.cloud.snippets}/${id}/download`))) doSearch() } } return (
isCloudSnippetDownloadable(snippet)) .map(snippet => snippet.id) : undefined} extraTableNav={() => } endTableNav={which => 'top' === which ? : null} />
) } const SearchResults: React.FC = ({ snippetView, setSnippetView }) => { const { searchResults, searchParams } = useCloudSearch() if (!searchResults) { return null } if (0 < searchResults.page && 0 === searchResults.snippets.length) { return (

{'codevault' === searchParams.method ? __('Could not find a codevault with that name. Please try again.', 'code-snippets') : __('No snippets could be found with that search term. Please try again.', 'code-snippets') }

) } return searchResults.snippets.length ? <> {searchResults.isFeatured ?

{__('Featured Snippets', 'code-snippets')}

:

{__('Search Results', 'code-snippets')}

} : null } const SearchStatus = () => { const { isErrored, isLoading } = useCloudSearch() return isErrored || isLoading ? : null } export interface CloudSearchProps { snippetView: SnippetView setSnippetView: (view: SnippetView) => void } export const CloudSearch: React.FC = ({ snippetView, setSnippetView }) =>