export const SEARCH_KINDS = ['works', 'people', 'organizations', 'containers']
export const SEARCH_KIND_DEFAULT = 'works'
export const SEARCH_FACETS = [
{ key: 'year', param: 'year', counts: 'years', label: { works: 'search.facet_year' } },
{ key: 'lang', param: 'lang', counts: 'languages', label: { works: 'search.facet_language' } },
{ key: 'type', param: 'type', counts: 'types', label: { works: 'search.facet_type', organizations: 'org.types' } },
{ key: 'fos', param: 'fos', counts: 'subjects', label: { works: 'search.facet_subject' } },
{ key: 'country', param: 'country', counts: 'countries', label: { people: 'entity.country', organizations: 'org.location' } },
]
export function searchFacetsFor(kind) {
return SEARCH_FACETS.filter(facet => facet.label[kind]).map(facet => ({
...facet,
heading: facet.label[kind],
}))
}
export const SEARCH_ALL = '*'
export function isSearchableQuery(q) {
const query = (q ?? '').trim()
return query === SEARCH_ALL || query.length >= 2
}
export const noSearchFilters = () =>
Object.fromEntries(SEARCH_FACETS.map(({ key }) => [key, []]))
export const searchFilterValues = (filters, key) => {
const picked = filters?.[key]
if (Array.isArray(picked)) return picked.filter(value => value || value === 0)
return picked ? [picked] : []
}
export const anySearchFilter = filters =>
SEARCH_FACETS.some(({ key }) => searchFilterValues(filters, key).length > 0)
export const isSearchFilterPicked = (filters, key, value) =>
searchFilterValues(filters, key).includes(value)
export function toggleSearchFilter(filters, key, value) {
const picked = searchFilterValues(filters, key)
return {
...filters,
[key]: picked.includes(value)
? picked.filter(v => v !== value)
: [...picked, value],
}
}
export function searchStateFromSearch(search) {
const params = new URLSearchParams(search ?? '')
const values = key => {
const picked = []
for (const value of params.getAll(key)) {
const trimmed = value.trim()
if (trimmed && !picked.includes(trimmed)) picked.push(trimmed)
}
return picked
}
const kind = params.get('kind')
const page = Number(params.get('page'))
return {
q: params.get('q') ?? '',
kind: SEARCH_KINDS.includes(kind) ? kind : SEARCH_KIND_DEFAULT,
filters: Object.fromEntries(
SEARCH_FACETS.map(({ key, param }) => [key, values(param)]),
),
page: Number.isFinite(page) && page >= 1 ? Math.floor(page) : 1,
}
}
export function searchHrefFor({ q = '', kind = SEARCH_KIND_DEFAULT, filters = {}, page = 1 } = {}) {
const params = new URLSearchParams()
if (q.trim()) params.set('q', q.trim())
if (kind && kind !== SEARCH_KIND_DEFAULT) params.set('kind', kind)
for (const { key, param } of SEARCH_FACETS) {
for (const value of searchFilterValues(filters, key)) params.append(param, value)
}
if (page > 1) params.set('page', String(page))
const query = params.toString()
return query ? `/?${query}` : '/'
}