import { Meta } from '@solidjs/meta' import { A, useSearchParams } from '@solidjs/router' import { clsx } from 'clsx' import { For, Show, createEffect, createMemo, createSignal, on, onMount } from 'solid-js' import { Loading } from '~/components/_shared/Loading' import { SearchField } from '~/components/_shared/SearchField' import { useLocalize } from '~/context/localize' import { useTopics } from '~/context/topics' import type { Topic } from '~/graphql/schema/core.gen' import enKeywords from '~/intl/locales/en/keywords.json' import ruKeywords from '~/intl/locales/ru/keywords.json' import { dummyFilter } from '~/lib/dummyFilter' import { getImageUrl } from '~/lib/getImageUrl' import { capitalize } from '~/utils/capitalize' import { scrollHandler } from '~/utils/scroll' import { TopicBadge } from '../../Topic/TopicBadge' import styles from './AllTopics.module.scss' type Props = { topics: Topic[] } export const TOPICS_PER_PAGE = 50 export const ABC = { ru: 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ#', en: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ#' } export const AllTopics = (props: Props) => { const { t, lang } = useLocalize() const alphabet = createMemo(() => ABC[lang()]) const { setTopicsSort, sortedTopics } = useTopics() const topics = createMemo(() => sortedTopics() || props.topics) const [searchParams, changeSearchParams] = useSearchParams<{ by?: string }>() createEffect(on(() => searchParams?.by || 'shouts', setTopicsSort, { defer: true })) onMount(() => setTimeout(() => !searchParams?.by && changeSearchParams({ by: 'shouts' }), 1)) // sorted derivative const byLetter = createMemo<{ [letter: string]: Topic[] }>(() => { return topics().reduce( (acc, topic) => { let letter = lang() === 'en' ? topic.slug[0].toUpperCase() : (topic?.title?.[0] || '').toUpperCase() if (/[^ËА-яё]/.test(letter) && lang() === 'ru') letter = '#' if (/[^A-z]/.test(letter) && lang() === 'en') letter = '#' if (!acc[letter]) acc[letter] = [] acc[letter].push(topic) return acc }, {} as { [letter: string]: Topic[] } ) }) // helper memo const sortedKeys = createMemo(() => { const keys = Object.keys(byLetter()) if (keys) { keys.sort() const firstKey: string = keys.shift() || '' keys.push(firstKey) } return keys }) // limit/offset based pagination aka 'show more' logic const [limit, setLimit] = createSignal(TOPICS_PER_PAGE) const showMore = () => setLimit((oldLimit) => oldLimit + TOPICS_PER_PAGE) // filter const [searchQuery, setSearchQuery] = createSignal('') const [filteredResults, setFilteredResults] = createSignal([]) createEffect(() => setFilteredResults((_prev: Topic[]) => dummyFilter(topics(), searchQuery(), lang()) as Topic[]) ) // subcomponent const AllTopicsHead = () => (

{t('Topics')}

{t('Subscribe what you like to tune your personal feed')}

) // meta const ogImage = getImageUrl('production/image/logo_image.png') const ogTitle = t('Themes and plots') const description = t( 'Thematic table of contents of the magazine. Here you can find all the topics that the community authors wrote about' ) return (
}>
0}> {(letter) => ( )}
{(topic) => ( <> )}
limit() && searchParams?.by !== 'title'}>
) }