parent
fe9fd37d9d
commit
73e1f575f8
|
@ -1,5 +1,5 @@
|
|||
import { clsx } from 'clsx'
|
||||
import { For, Show, createEffect, createSignal } from 'solid-js'
|
||||
import { For, Show, createEffect, createSignal, on, onMount } from 'solid-js'
|
||||
import { useFollowing } from '../../context/following'
|
||||
import { useLocalize } from '../../context/localize'
|
||||
import { apiClient } from '../../graphql/client/core'
|
||||
|
@ -11,24 +11,29 @@ import styles from './AuthorsList.module.scss'
|
|||
|
||||
type Props = {
|
||||
class?: string
|
||||
query: 'shouts' | 'followers'
|
||||
query: 'shouts' | 'authors'
|
||||
searchQuery?: string
|
||||
allAuthorsLength?: number
|
||||
}
|
||||
|
||||
const PAGE_SIZE = 20
|
||||
export const AuthorsList = (props: Props) => {
|
||||
const { t } = useLocalize()
|
||||
const { isOwnerSubscribed } = useFollowing()
|
||||
const { authorsByShouts, authorsByFollowers } = useAuthorsStore()
|
||||
const [loading, setLoading] = createSignal(false)
|
||||
const [currentPage, setCurrentPage] = createSignal({ shouts: 0, followers: 0 })
|
||||
const { authorsByShouts, authorsByFollowers } = useAuthorsStore()
|
||||
const [allLoaded, setAllLoaded] = createSignal(false)
|
||||
|
||||
const fetchAuthors = async (queryType: 'shouts' | 'followers', page: number) => {
|
||||
const fetchAuthors = async (queryType: 'shouts' | 'authors', page: number) => {
|
||||
setLoading(true)
|
||||
|
||||
console.log('!!! AAA:')
|
||||
const offset = PAGE_SIZE * page
|
||||
const result = await apiClient.loadAuthorsBy({
|
||||
by: { order: queryType },
|
||||
limit: PAGE_SIZE,
|
||||
offset: offset,
|
||||
offset,
|
||||
})
|
||||
|
||||
if (queryType === 'shouts') {
|
||||
|
@ -41,25 +46,38 @@ export const AuthorsList = (props: Props) => {
|
|||
}
|
||||
|
||||
const loadMoreAuthors = () => {
|
||||
const queryType = props.query
|
||||
const nextPage = currentPage()[queryType] + 1
|
||||
fetchAuthors(queryType, nextPage).then(() =>
|
||||
setCurrentPage({ ...currentPage(), [queryType]: nextPage }),
|
||||
const nextPage = currentPage()[props.query] + 1
|
||||
fetchAuthors(props.query, nextPage).then(() =>
|
||||
setCurrentPage({ ...currentPage(), [props.query]: nextPage }),
|
||||
)
|
||||
}
|
||||
|
||||
createEffect(() => {
|
||||
const queryType = props.query
|
||||
if (
|
||||
currentPage()[queryType] === 0 &&
|
||||
(authorsByShouts().length === 0 || authorsByFollowers().length === 0)
|
||||
) {
|
||||
loadMoreAuthors()
|
||||
}
|
||||
})
|
||||
createEffect(
|
||||
on(
|
||||
() => props.query,
|
||||
(query) => {
|
||||
const authorsList = query === 'shouts' ? authorsByShouts() : authorsByFollowers()
|
||||
if (authorsList.length === 0 || currentPage()[query] === 0) {
|
||||
setCurrentPage((prev) => ({ ...prev, [query]: 0 }))
|
||||
fetchAuthors(query, 0).then(() => setCurrentPage((prev) => ({ ...prev, [query]: 1 })))
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
const authorsList = () => (props.query === 'shouts' ? authorsByShouts() : authorsByFollowers())
|
||||
|
||||
// TODO: do it with backend
|
||||
// createEffect(() => {
|
||||
// if (props.searchQuery) {
|
||||
// // search logic
|
||||
// }
|
||||
// })
|
||||
|
||||
createEffect(() => {
|
||||
setAllLoaded(authorsByShouts().length === authorsList.length)
|
||||
})
|
||||
|
||||
return (
|
||||
<div class={clsx(styles.AuthorsList, props.class)}>
|
||||
<For each={authorsList()}>
|
||||
|
@ -77,13 +95,17 @@ export const AuthorsList = (props: Props) => {
|
|||
</div>
|
||||
)}
|
||||
</For>
|
||||
<div class={styles.action}>
|
||||
<Show when={!loading()}>
|
||||
<Button value={t('Load more')} onClick={loadMoreAuthors} />
|
||||
</Show>
|
||||
<Show when={loading()}>
|
||||
<InlineLoader />
|
||||
</Show>
|
||||
<div class="row">
|
||||
<div class="col-lg-20 col-xl-18">
|
||||
<div class={styles.action}>
|
||||
<Show when={!loading() && authorsList().length > 0 && !allLoaded()}>
|
||||
<Button value={t('Load more')} onClick={loadMoreAuthors} />
|
||||
</Show>
|
||||
<Show when={loading() && !allLoaded()}>
|
||||
<InlineLoader />
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -28,6 +28,7 @@ type Props = {
|
|||
|
||||
export const AllAuthors = (props: Props) => {
|
||||
const { t, lang } = useLocalize()
|
||||
const [searchQuery, setSearchQuery] = createSignal('')
|
||||
const ALPHABET =
|
||||
lang() === 'ru' ? [...'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ@'] : [...'ABCDEFGHIJKLMNOPQRSTUVWXYZ@']
|
||||
const { searchParams, changeSearchParams } = useRouter<AllAuthorsPageSearchParams>()
|
||||
|
@ -36,27 +37,22 @@ export const AllAuthors = (props: Props) => {
|
|||
sortBy: searchParams().by || 'name',
|
||||
})
|
||||
|
||||
const [searchQuery, setSearchQuery] = createSignal('')
|
||||
|
||||
createEffect(() => {
|
||||
let by = searchParams().by
|
||||
if (by) {
|
||||
setAuthorsSort(by)
|
||||
} else {
|
||||
by = 'name'
|
||||
changeSearchParams({ by })
|
||||
}
|
||||
const filteredAuthors = createMemo(() => {
|
||||
const query = searchQuery().toLowerCase()
|
||||
return sortedAuthors().filter((author) => {
|
||||
return author.name.toLowerCase().includes(query) // Предполагаем, что у автора есть свойство name
|
||||
})
|
||||
})
|
||||
|
||||
const byLetter = createMemo<{ [letter: string]: Author[] }>(() => {
|
||||
return sortedAuthors().reduce(
|
||||
const byLetterFiltered = createMemo<{ [letter: string]: Author[] }>(() => {
|
||||
return filteredAuthors().reduce(
|
||||
(acc, author) => authorLetterReduce(acc, author, lang()),
|
||||
{} as { [letter: string]: Author[] },
|
||||
)
|
||||
})
|
||||
|
||||
const sortedKeys = createMemo<string[]>(() => {
|
||||
const keys = Object.keys(byLetter())
|
||||
const keys = Object.keys(byLetterFiltered())
|
||||
keys.sort()
|
||||
keys.push(keys.shift())
|
||||
return keys
|
||||
|
@ -106,7 +102,7 @@ export const AllAuthors = (props: Props) => {
|
|||
>
|
||||
<a href="/authors?by=name">{t('By name')}</a>
|
||||
</li>
|
||||
<Show when={searchParams().by !== 'name'}>
|
||||
<Show when={searchParams().by === 'name'}>
|
||||
<li class="view-switcher__search">
|
||||
<SearchField onChange={(value) => setSearchQuery(value)} />
|
||||
</li>
|
||||
|
@ -122,7 +118,7 @@ export const AllAuthors = (props: Props) => {
|
|||
<For each={ALPHABET}>
|
||||
{(letter, index) => (
|
||||
<li>
|
||||
<Show when={letter in byLetter()} fallback={letter}>
|
||||
<Show when={letter in byLetterFiltered()} fallback={letter}>
|
||||
<a
|
||||
href={`/authors?by=name#letter-${index()}`}
|
||||
onClick={(event) => {
|
||||
|
@ -147,7 +143,7 @@ export const AllAuthors = (props: Props) => {
|
|||
<div class="row">
|
||||
<div class="col-lg-20">
|
||||
<div class="row">
|
||||
<For each={byLetter()[letter]}>
|
||||
<For each={byLetterFiltered()[letter]}>
|
||||
{(author) => (
|
||||
<div class={clsx(styles.topic, 'topic col-sm-12 col-md-8')}>
|
||||
<div class="topic-title">
|
||||
|
@ -167,8 +163,12 @@ export const AllAuthors = (props: Props) => {
|
|||
)}
|
||||
</For>
|
||||
</Show>
|
||||
<Show when={searchParams().by !== 'name' && props.isLoaded} fallback={<Loading />}>
|
||||
<AuthorsList query={searchParams().by === 'shouts' ? 'shouts' : 'followers'} />
|
||||
<Show when={searchParams().by !== 'name' && props.isLoaded}>
|
||||
<AuthorsList
|
||||
allAuthorsLength={sortedAuthors()?.length}
|
||||
searchQuery={searchQuery()}
|
||||
query={searchParams().by === 'shouts' ? 'shouts' : 'authors'}
|
||||
/>
|
||||
</Show>
|
||||
</div>
|
||||
</Show>
|
||||
|
|
|
@ -3,7 +3,6 @@ import { createSignal } from 'solid-js'
|
|||
|
||||
import { apiClient } from '../../graphql/client/core'
|
||||
import { Author, QueryLoad_Authors_ByArgs } from '../../graphql/schema/core.gen'
|
||||
import { byStat } from '../../utils/sortby'
|
||||
|
||||
export type AuthorsSortBy = 'shouts' | 'name' | 'followers'
|
||||
type SortedAuthorsSetter = (prev: Author[]) => Author[]
|
||||
|
@ -21,19 +20,7 @@ export const setAuthorsByShouts = (authors: SortedAuthorsSetter) => setSortedAut
|
|||
export const setAuthorsByFollowers = (authors: SortedAuthorsSetter) => setSortedAuthorsByFollowers(authors)
|
||||
|
||||
const sortedAuthors = createLazyMemo(() => {
|
||||
const authors = Object.values(authorEntities())
|
||||
switch (sortAllBy()) {
|
||||
case 'followers': {
|
||||
return authors.sort(byStat('followers'))
|
||||
}
|
||||
case 'shouts': {
|
||||
return authors.sort(byStat('shouts'))
|
||||
}
|
||||
case 'name': {
|
||||
return authors.sort((a, b) => a.name.localeCompare(b.name))
|
||||
}
|
||||
}
|
||||
return authors
|
||||
return Object.values(authorEntities())
|
||||
})
|
||||
|
||||
export const addAuthors = (authors: Author[]) => {
|
||||
|
|
Loading…
Reference in New Issue
Block a user