import type { Author } from '../../graphql/schema/core.gen' import { Meta } from '@solidjs/meta' import { clsx } from 'clsx' import { createEffect, createMemo, createSignal, For, Show } from 'solid-js' import { useFollowing } from '../../context/following' import { useLocalize } from '../../context/localize' import { useRouter } from '../../stores/router' import { loadAuthors, setAuthorsSort, useAuthorsStore } from '../../stores/zine/authors' import { capitalize } from '../../utils/capitalize' import { isCyrillic } from '../../utils/cyrillic' import { dummyFilter } from '../../utils/dummyFilter' import { getImageUrl } from '../../utils/getImageUrl' import { translit } from '../../utils/ru2en' import { scrollHandler } from '../../utils/scroll' import { Loading } from '../_shared/Loading' import { SearchField } from '../_shared/SearchField' import { AuthorBadge } from '../Author/AuthorBadge' import styles from './AllAuthors.module.scss' type AllAuthorsPageSearchParams = { by: '' | 'name' | 'shouts' | 'followers' } type Props = { authors: Author[] isLoaded: boolean } const PAGE_SIZE = 20 export const AllAuthorsView = (props: Props) => { const { t, lang } = useLocalize() const ALPHABET = lang() === 'ru' ? [...'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ@'] : [...'ABCDEFGHIJKLMNOPQRSTUVWXYZ@'] const [offsetByShouts, setOffsetByShouts] = createSignal(0) const [offsetByFollowers, setOffsetByFollowers] = createSignal(0) const { searchParams, changeSearchParams } = useRouter() const { sortedAuthors } = useAuthorsStore({ authors: props.authors, sortBy: searchParams().by || 'name', }) const [searchQuery, setSearchQuery] = createSignal('') const offset = searchParams()?.by === 'shouts' ? offsetByShouts : offsetByFollowers createEffect(() => { let by = searchParams().by if (by) { setAuthorsSort(by) } else { by = 'name' changeSearchParams({ by }) } }) const loadMoreByShouts = async () => { await loadAuthors({ by: { order: 'shouts_stat' }, limit: PAGE_SIZE, offset: offsetByShouts() }) setOffsetByShouts((o) => o + PAGE_SIZE) } const loadMoreByFollowers = async () => { await loadAuthors({ by: { order: 'followers_stat' }, limit: PAGE_SIZE, offset: offsetByFollowers() }) setOffsetByFollowers((o) => o + PAGE_SIZE) } const isStatsLoaded = createMemo(() => sortedAuthors() && sortedAuthors().some((author) => author.stat)) createEffect(async () => { if (!isStatsLoaded()) { await loadMoreByShouts() await loadMoreByFollowers() } }) const showMore = async () => await { shouts: loadMoreByShouts, followers: loadMoreByFollowers, }[searchParams().by]() const translate = (author: Author) => lang() === 'en' && isCyrillic(author.name) ? capitalize(translit(author.name.replace(/ё/, 'e').replace(/ь/, '')).replace(/-/, ' '), true) : author.name const byLetter = createMemo<{ [letter: string]: Author[] }>(() => { return sortedAuthors().reduce( (acc, author) => { let letter = '' if (!letter && author && author.name) { const name = translate(author) .replace(/[^\dA-zА-я]/, ' ') .trim() const nameParts = name.trim().split(' ') const found = nameParts.filter(Boolean).pop() if (found && found.length > 0) { letter = found[0].toUpperCase() } } if (/[^ËА-яё]/.test(letter) && lang() === 'ru') letter = '@' if (/[^A-z]/.test(letter) && lang() === 'en') letter = '@' if (!acc[letter]) acc[letter] = [] author.name = translate(author) acc[letter].push(author) // Sort authors within each letter group alphabetically by name acc[letter].sort((a, b) => a.name.localeCompare(b.name)) return acc }, {} as { [letter: string]: Author[] }, ) }) const { isOwnerSubscribed } = useFollowing() const sortedKeys = createMemo(() => { const keys = Object.keys(byLetter()) keys.sort() keys.push(keys.shift()) return keys }) const filteredAuthors = createMemo(() => { return dummyFilter(sortedAuthors(), searchQuery(), lang()) }) const ogImage = getImageUrl('production/image/logo_image.png') const ogTitle = t('Authors') const description = t('List of authors of the open editorial community') return (
}>

{t('Authors')}

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

0}> {(letter) => (

{letter}

{(author) => (
{translate(author)} {author.stat.shouts}
)}
)}
{(author) => (
)}
PAGE_SIZE + offset() && searchParams().by !== 'name'}>
) }