2024-02-04 11:25:21 +00:00
|
|
|
import { For, Show, createSignal, onMount } from 'solid-js'
|
2023-11-14 15:10:00 +00:00
|
|
|
|
2024-06-24 17:50:27 +00:00
|
|
|
import { useSearchParams } from '@solidjs/router'
|
2024-07-04 07:51:15 +00:00
|
|
|
import { useFeed } from '~/context/feed'
|
|
|
|
import { useLocalize } from '~/context/localize'
|
|
|
|
import type { SearchResult } from '~/graphql/schema/core.gen'
|
|
|
|
import { restoreScrollPosition, saveScrollPosition } from '~/utils/scroll'
|
2023-11-14 15:10:00 +00:00
|
|
|
import { ArticleCard } from '../Feed/ArticleCard'
|
2022-09-22 09:37:49 +00:00
|
|
|
|
2024-06-24 17:50:27 +00:00
|
|
|
import '../../styles/Search.scss'
|
2022-09-09 11:53:35 +00:00
|
|
|
|
|
|
|
type Props = {
|
2022-09-22 09:37:49 +00:00
|
|
|
query: string
|
2023-12-19 13:06:54 +00:00
|
|
|
results: SearchResult[]
|
2022-09-09 11:53:35 +00:00
|
|
|
}
|
|
|
|
|
2022-11-17 23:20:40 +00:00
|
|
|
const LOAD_MORE_PAGE_SIZE = 50
|
|
|
|
|
2022-09-22 09:37:49 +00:00
|
|
|
export const SearchView = (props: Props) => {
|
2023-02-17 09:21:02 +00:00
|
|
|
const { t } = useLocalize()
|
2024-06-24 17:50:27 +00:00
|
|
|
const { sortedFeed, loadShoutsSearch } = useFeed()
|
2022-11-17 23:20:40 +00:00
|
|
|
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
|
|
|
|
const [query, setQuery] = createSignal(props.query)
|
|
|
|
const [offset, setOffset] = createSignal(0)
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2024-06-24 17:50:27 +00:00
|
|
|
const [searchParams] = useSearchParams<{ by?: string }>()
|
2022-11-17 23:20:40 +00:00
|
|
|
let searchEl: HTMLInputElement
|
2023-12-14 18:45:50 +00:00
|
|
|
const handleQueryChange = () => {
|
2022-11-17 23:20:40 +00:00
|
|
|
setQuery(searchEl.value)
|
2022-09-13 09:59:04 +00:00
|
|
|
}
|
|
|
|
|
2022-11-17 23:20:40 +00:00
|
|
|
const loadMore = async () => {
|
|
|
|
saveScrollPosition()
|
2023-12-25 04:01:52 +00:00
|
|
|
if (query()) {
|
|
|
|
console.log(query())
|
|
|
|
const { hasMore } = await loadShoutsSearch({
|
|
|
|
text: query(),
|
|
|
|
offset: offset(),
|
2024-06-26 08:22:05 +00:00
|
|
|
limit: LOAD_MORE_PAGE_SIZE
|
2023-12-25 04:01:52 +00:00
|
|
|
})
|
|
|
|
setIsLoadMoreButtonVisible(hasMore)
|
|
|
|
setOffset(offset() + LOAD_MORE_PAGE_SIZE)
|
|
|
|
} else {
|
|
|
|
console.warn('[SaerchView] no query found')
|
|
|
|
}
|
2022-11-17 23:20:40 +00:00
|
|
|
restoreScrollPosition()
|
2022-09-13 09:59:04 +00:00
|
|
|
}
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2024-02-05 15:04:23 +00:00
|
|
|
onMount(() => {
|
2023-12-25 04:01:52 +00:00
|
|
|
const q = window.location.pathname.replace('/search/', '') || props.query
|
|
|
|
setQuery(q)
|
2023-12-25 08:34:49 +00:00
|
|
|
searchEl.value = q
|
2023-12-25 04:01:52 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
// TODO: use score from the search results to sort by relevance
|
|
|
|
|
2022-09-09 11:53:35 +00:00
|
|
|
return (
|
|
|
|
<div class="search-page wide-container">
|
|
|
|
<form action="/search" class="search-form row">
|
2023-03-10 17:42:48 +00:00
|
|
|
<div class="col-sm-18">
|
2022-11-17 23:20:40 +00:00
|
|
|
<input
|
|
|
|
type="search"
|
|
|
|
name="q"
|
2024-06-24 17:50:27 +00:00
|
|
|
ref={(el) => (searchEl = el)}
|
2022-11-17 23:20:40 +00:00
|
|
|
onInput={handleQueryChange}
|
2024-02-04 09:03:15 +00:00
|
|
|
placeholder={query() || `${t('Enter text')}...`}
|
2022-11-17 23:20:40 +00:00
|
|
|
/>
|
2022-09-09 11:53:35 +00:00
|
|
|
</div>
|
2023-03-10 17:42:48 +00:00
|
|
|
<div class="col-sm-6">
|
2022-11-17 23:20:40 +00:00
|
|
|
<button class="button" type="submit" onClick={loadMore}>
|
2022-09-13 09:59:04 +00:00
|
|
|
{t('Search')}
|
|
|
|
</button>
|
2022-09-09 11:53:35 +00:00
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
|
|
|
|
<ul class="view-switcher">
|
2022-09-22 09:37:49 +00:00
|
|
|
<li
|
|
|
|
classList={{
|
2024-06-26 08:22:05 +00:00
|
|
|
'view-switcher__item--selected': searchParams?.by === 'relevance'
|
2022-09-22 09:37:49 +00:00
|
|
|
}}
|
|
|
|
>
|
2023-04-03 13:11:02 +00:00
|
|
|
<a href="?by=relevance">{t('By relevance')}</a>
|
2022-09-09 11:53:35 +00:00
|
|
|
</li>
|
2022-09-22 09:37:49 +00:00
|
|
|
<li
|
|
|
|
classList={{
|
2024-06-26 08:22:05 +00:00
|
|
|
'view-switcher__item--selected': searchParams?.by === 'rating'
|
2022-09-22 09:37:49 +00:00
|
|
|
}}
|
|
|
|
>
|
2023-04-03 13:11:02 +00:00
|
|
|
<a href="?by=rating">{t('Top rated')}</a>
|
2022-09-09 11:53:35 +00:00
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
|
2024-06-24 17:50:27 +00:00
|
|
|
<Show when={sortedFeed()?.length > 0}>
|
2022-09-09 11:53:35 +00:00
|
|
|
<h3>{t('Publications')}</h3>
|
|
|
|
|
|
|
|
<div class="floor">
|
|
|
|
<div class="row">
|
2024-06-24 17:50:27 +00:00
|
|
|
<For each={sortedFeed()}>
|
2022-09-09 11:53:35 +00:00
|
|
|
{(article) => (
|
2023-03-10 17:42:48 +00:00
|
|
|
<div class="col-md-6">
|
2023-11-18 14:10:02 +00:00
|
|
|
<ArticleCard article={article} desktopCoverSize="L" />
|
2022-09-09 11:53:35 +00:00
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</For>
|
|
|
|
|
2023-12-25 04:01:52 +00:00
|
|
|
<Show when={isLoadMoreButtonVisible()}>
|
|
|
|
<div class="col-md-6">
|
|
|
|
<a href={`/search/${query()}`} onClick={loadMore} class="search__show-more">
|
|
|
|
<span class="search__show-more-inner">{t('Load more')}</span>
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</Show>
|
2022-09-09 11:53:35 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Show>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|