webapp/src/components/AuthorsList/AuthorsList.tsx
Ilya Y b1b3f8b435
auth modals fix logic (#420)
auth modals fix logic
2024-02-27 17:42:54 +03:00

112 lines
3.4 KiB
TypeScript

import { clsx } from 'clsx'
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'
import { Author } from '../../graphql/schema/core.gen'
import { setAuthorsByFollowers, setAuthorsByShouts, useAuthorsStore } from '../../stores/zine/authors'
import { AuthorBadge } from '../Author/AuthorBadge'
import { InlineLoader } from '../InlineLoader'
import { Button } from '../_shared/Button'
import styles from './AuthorsList.module.scss'
type Props = {
class?: string
query: 'followers' | 'shouts'
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 [allLoaded, setAllLoaded] = createSignal(false)
const fetchAuthors = async (queryType: Props['query'], page: number) => {
setLoading(true)
const offset = PAGE_SIZE * page
const result = await apiClient.loadAuthorsBy({
by: { order: queryType },
limit: PAGE_SIZE,
offset,
})
if (queryType === 'shouts') {
setAuthorsByShouts((prev) => [...prev, ...result])
} else {
setAuthorsByFollowers((prev) => [...prev, ...result])
}
setLoading(false)
}
const loadMoreAuthors = () => {
const nextPage = currentPage()[props.query] + 1
fetchAuthors(props.query, nextPage).then(() =>
setCurrentPage({ ...currentPage(), [props.query]: nextPage }),
)
}
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(props.allAuthorsLength === authorsList.length)
})
return (
<div class={clsx(styles.AuthorsList, props.class)}>
<For each={authorsList()}>
{(author) => (
<div class="row">
<div class="col-lg-20 col-xl-18">
<AuthorBadge
author={author}
isFollowed={{
loaded: !loading(),
value: isOwnerSubscribed(author.id),
}}
/>
</div>
</div>
)}
</For>
<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>
)
}