2022-09-28 20:16:44 +00:00
|
|
|
import { createMemo, createSignal } from 'solid-js'
|
2022-09-09 11:53:35 +00:00
|
|
|
import { apiClient } from '../../utils/apiClient'
|
|
|
|
import type { Topic } from '../../graphql/types.gen'
|
2022-10-08 16:40:58 +00:00
|
|
|
import { byTopicStatDesc } from '../../utils/sortby'
|
2022-09-29 17:37:21 +00:00
|
|
|
import { createLazyMemo } from '@solid-primitives/memo'
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2022-10-08 16:40:58 +00:00
|
|
|
export type TopicsSortBy = 'followers' | 'title' | 'authors' | 'shouts'
|
2022-09-22 09:37:49 +00:00
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
const [sortAllBy, setSortAllBy] = createSignal<TopicsSortBy>('shouts')
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2022-10-21 18:17:04 +00:00
|
|
|
export const setTopicsSort = (sortBy: TopicsSortBy) => setSortAllBy(sortBy)
|
2022-09-22 09:37:49 +00:00
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
const [topicEntities, setTopicEntities] = createSignal<{ [topicSlug: string]: Topic }>({})
|
|
|
|
const [randomTopics, setRandomTopics] = createSignal<Topic[]>([])
|
|
|
|
const [topicsByAuthor, setTopicByAuthor] = createSignal<{ [authorSlug: string]: Topic[] }>({})
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2022-09-29 17:37:21 +00:00
|
|
|
const sortedTopics = createLazyMemo<Topic[]>(() => {
|
|
|
|
const topics = Object.values(topicEntities())
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2022-10-04 12:42:11 +00:00
|
|
|
switch (sortAllBy()) {
|
2022-10-08 16:40:58 +00:00
|
|
|
case 'followers': {
|
|
|
|
// console.debug('[store.topics] sorted by followers')
|
|
|
|
topics.sort(byTopicStatDesc('followers'))
|
2022-09-28 20:16:44 +00:00
|
|
|
break
|
2022-10-07 19:35:53 +00:00
|
|
|
}
|
|
|
|
case 'shouts': {
|
2022-10-04 12:42:11 +00:00
|
|
|
// log.debug(`sorted by shouts`)
|
|
|
|
topics.sort(byTopicStatDesc('shouts'))
|
|
|
|
break
|
2022-10-07 19:35:53 +00:00
|
|
|
}
|
|
|
|
case 'authors': {
|
2022-10-04 12:42:11 +00:00
|
|
|
// log.debug(`sorted by authors`)
|
|
|
|
topics.sort(byTopicStatDesc('authors'))
|
2022-09-28 20:16:44 +00:00
|
|
|
break
|
2022-10-07 19:35:53 +00:00
|
|
|
}
|
|
|
|
case 'title': {
|
2022-10-08 16:40:58 +00:00
|
|
|
// console.debug('[store.topics] sorted by title')
|
2022-09-28 20:16:44 +00:00
|
|
|
topics.sort((a, b) => a.title.localeCompare(b.title))
|
|
|
|
break
|
2022-10-07 19:35:53 +00:00
|
|
|
}
|
|
|
|
default: {
|
2022-10-08 16:40:58 +00:00
|
|
|
console.error(`Unknown sort: ${sortAllBy()}`)
|
2022-10-07 19:35:53 +00:00
|
|
|
}
|
2022-09-22 09:37:49 +00:00
|
|
|
}
|
2022-09-29 17:37:21 +00:00
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
return topics
|
|
|
|
})
|
|
|
|
|
|
|
|
const topTopics = createMemo(() => {
|
|
|
|
const topics = Object.values(topicEntities())
|
|
|
|
topics.sort(byTopicStatDesc('shouts'))
|
|
|
|
return topics
|
|
|
|
})
|
2022-09-13 13:38:26 +00:00
|
|
|
|
2022-09-13 09:59:04 +00:00
|
|
|
const addTopics = (...args: Topic[][]) => {
|
2022-11-15 16:16:31 +00:00
|
|
|
const allTopics = args.flatMap((topics) => (topics || []).filter(Boolean))
|
2022-09-13 09:59:04 +00:00
|
|
|
|
|
|
|
const newTopicEntities = allTopics.reduce((acc, topic) => {
|
2022-09-09 11:53:35 +00:00
|
|
|
acc[topic.slug] = topic
|
|
|
|
return acc
|
|
|
|
}, {} as Record<string, Topic>)
|
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
setTopicEntities((prevTopicEntities) => {
|
|
|
|
return {
|
|
|
|
...prevTopicEntities,
|
2022-09-09 11:53:35 +00:00
|
|
|
...newTopicEntities
|
2022-09-28 20:16:44 +00:00
|
|
|
}
|
|
|
|
})
|
2022-09-09 11:53:35 +00:00
|
|
|
}
|
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
export const addTopicsByAuthor = (newTopicsByAuthors: { [authorSlug: string]: Topic[] }) => {
|
|
|
|
const allTopics = Object.values(newTopicsByAuthors).flat()
|
2022-09-13 09:59:04 +00:00
|
|
|
addTopics(allTopics)
|
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
setTopicByAuthor((prevTopicsByAuthor) => {
|
|
|
|
return Object.entries(newTopicsByAuthors).reduce((acc, [authorSlug, topics]) => {
|
2022-09-13 09:59:04 +00:00
|
|
|
if (!acc[authorSlug]) {
|
|
|
|
acc[authorSlug] = []
|
|
|
|
}
|
|
|
|
|
|
|
|
topics.forEach((topic) => {
|
|
|
|
if (!acc[authorSlug].some((t) => t.slug === topic.slug)) {
|
|
|
|
acc[authorSlug].push(topic)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
return acc
|
2022-09-28 20:16:44 +00:00
|
|
|
}, prevTopicsByAuthor)
|
|
|
|
})
|
2022-09-13 09:59:04 +00:00
|
|
|
}
|
|
|
|
|
2022-09-09 11:53:35 +00:00
|
|
|
export const loadAllTopics = async (): Promise<void> => {
|
|
|
|
const topics = await apiClient.getAllTopics()
|
|
|
|
addTopics(topics)
|
|
|
|
}
|
|
|
|
|
2022-11-22 03:02:11 +00:00
|
|
|
export const loadRandomTopics = async ({ amount }: { amount: number }): Promise<void> => {
|
|
|
|
const topics = await apiClient.getRandomTopics({ amount })
|
2022-10-05 15:11:14 +00:00
|
|
|
setRandomTopics(topics)
|
|
|
|
}
|
|
|
|
|
|
|
|
export const loadTopic = async ({ slug }: { slug: string }): Promise<void> => {
|
2022-11-13 19:35:57 +00:00
|
|
|
const topic = await apiClient.getTopic({ slug })
|
2022-10-05 15:11:14 +00:00
|
|
|
addTopics([topic])
|
|
|
|
}
|
|
|
|
|
2022-09-09 11:53:35 +00:00
|
|
|
type InitialState = {
|
|
|
|
topics?: Topic[]
|
|
|
|
randomTopics?: Topic[]
|
2022-09-22 09:37:49 +00:00
|
|
|
sortBy?: TopicsSortBy
|
2022-09-09 11:53:35 +00:00
|
|
|
}
|
|
|
|
|
2022-09-23 07:38:48 +00:00
|
|
|
export const useTopicsStore = (initialState: InitialState = {}) => {
|
|
|
|
if (initialState.sortBy) {
|
2022-09-28 20:16:44 +00:00
|
|
|
setSortAllBy(initialState.sortBy)
|
2022-09-16 07:45:56 +00:00
|
|
|
}
|
2022-09-22 09:37:49 +00:00
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
addTopics(initialState.topics, initialState.randomTopics)
|
2022-09-22 09:37:49 +00:00
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
if (initialState.randomTopics) {
|
|
|
|
setRandomTopics(initialState.randomTopics)
|
2022-09-13 09:59:04 +00:00
|
|
|
}
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
return { topicEntities, sortedTopics, randomTopics, topTopics, topicsByAuthor }
|
2022-09-09 11:53:35 +00:00
|
|
|
}
|