webapp/src/stores/zine/authors.ts

104 lines
2.7 KiB
TypeScript
Raw Normal View History

2022-09-29 17:37:21 +00:00
import { createLazyMemo } from '@solid-primitives/memo'
import { createSignal } from 'solid-js'
2023-11-28 13:18:25 +00:00
import { apiClient } from '../../graphql/client/core'
2023-11-28 15:36:00 +00:00
import { Author } from '../../graphql/schema/core.gen'
2023-11-28 18:04:51 +00:00
import { byStat } from '../../utils/sortby'
2022-09-22 09:37:49 +00:00
export type AuthorsSortBy = 'shouts' | 'name' | 'followers'
2022-09-09 11:53:35 +00:00
2022-10-05 15:56:59 +00:00
const [sortAllBy, setSortAllBy] = createSignal<AuthorsSortBy>('shouts')
2022-10-21 18:17:04 +00:00
export const setAuthorsSort = (sortBy: AuthorsSortBy) => setSortAllBy(sortBy)
2022-09-09 11:53:35 +00:00
2022-09-28 20:16:44 +00:00
const [authorEntities, setAuthorEntities] = createSignal<{ [authorSlug: string]: Author }>({})
const [authorsByTopic, setAuthorsByTopic] = createSignal<{ [topicSlug: string]: Author[] }>({})
2022-09-13 09:59:04 +00:00
2022-09-29 17:37:21 +00:00
const sortedAuthors = createLazyMemo(() => {
2022-09-28 20:16:44 +00:00
const authors = Object.values(authorEntities())
switch (sortAllBy()) {
case 'followers': {
authors.sort(byStat('followers'))
2022-09-28 20:16:44 +00:00
break
2022-10-07 19:35:53 +00:00
}
case 'shouts': {
authors.sort(byStat('shouts'))
2022-10-05 15:56:59 +00:00
break
2022-10-07 19:35:53 +00:00
}
case 'name': {
2022-09-28 20:16:44 +00:00
authors.sort((a, b) => a.name.localeCompare(b.name))
break
2022-10-07 19:35:53 +00:00
}
2022-09-28 20:16:44 +00:00
}
return authors
})
2022-09-13 13:38:26 +00:00
2022-09-09 11:53:35 +00:00
const addAuthors = (authors: Author[]) => {
const newAuthorEntities = authors.filter(Boolean).reduce(
(acc, author) => {
acc[author.slug] = author
return acc
},
{} as Record<string, Author>,
)
2022-09-09 11:53:35 +00:00
setAuthorEntities((prevAuthorEntities) =>
Object.keys(newAuthorEntities).reduce(
(acc, authorSlug) => {
acc[authorSlug] = {
...acc[authorSlug],
...newAuthorEntities[authorSlug],
}
return acc
},
{ ...prevAuthorEntities },
),
)
2022-09-09 11:53:35 +00:00
}
export const loadAuthor = async ({ slug }: { slug: string }): Promise<Author> => {
const author = await apiClient.getAuthor({ slug })
2022-10-05 15:11:14 +00:00
addAuthors([author])
return author
2022-10-05 15:11:14 +00:00
}
2022-09-28 20:16:44 +00:00
export const addAuthorsByTopic = (newAuthorsByTopic: { [topicSlug: string]: Author[] }) => {
const allAuthors = Object.values(newAuthorsByTopic).flat()
2022-09-13 09:59:04 +00:00
addAuthors(allAuthors)
2022-09-28 20:16:44 +00:00
setAuthorsByTopic((prevAuthorsByTopic) => {
return Object.entries(newAuthorsByTopic).reduce((acc, [topicSlug, authors]) => {
2022-09-13 09:59:04 +00:00
if (!acc[topicSlug]) {
acc[topicSlug] = []
}
authors.forEach((author) => {
if (!acc[topicSlug].some((a) => a.slug === author.slug)) {
acc[topicSlug].push(author)
}
})
return acc
2022-09-28 20:16:44 +00:00
}, prevAuthorsByTopic)
})
2022-09-13 09:59:04 +00:00
}
2022-09-09 11:53:35 +00:00
export const loadAllAuthors = async (): Promise<void> => {
const authors = await apiClient.getAllAuthors()
addAuthors(authors)
}
2022-09-13 09:59:04 +00:00
type InitialState = {
authors?: Author[]
sortBy?: AuthorsSortBy
2022-09-13 09:59:04 +00:00
}
2022-09-23 07:38:48 +00:00
export const useAuthorsStore = (initialState: InitialState = {}) => {
if (initialState.sortBy) {
setSortAllBy(initialState.sortBy)
}
2022-09-28 20:16:44 +00:00
addAuthors([...(initialState.authors || [])])
2022-09-13 09:59:04 +00:00
2022-09-28 20:16:44 +00:00
return { authorEntities, sortedAuthors, authorsByTopic }
2022-09-09 11:53:35 +00:00
}