topics and authors grouped by letter

This commit is contained in:
Igor Lobanov 2022-10-05 17:56:59 +02:00
parent e63b018efa
commit 71cec8a6c2
3 changed files with 93 additions and 71 deletions

View File

@ -1,15 +1,14 @@
import { createEffect, createSignal, For, Show } from 'solid-js' import { createEffect, createMemo, createSignal, For, Show } from 'solid-js'
import type { Author } from '../../graphql/types.gen' import type { Author } from '../../graphql/types.gen'
import { AuthorCard } from '../Author/Card' import { AuthorCard } from '../Author/Card'
import { byFirstChar, sortBy } from '../../utils/sortby'
import { groupByName } from '../../utils/groupby'
import { Icon } from '../Nav/Icon' import { Icon } from '../Nav/Icon'
import { t } from '../../utils/intl' import { t } from '../../utils/intl'
import { useAuthorsStore } from '../../stores/zine/authors' import { useAuthorsStore, setSortAllBy as setSortAllAuthorsBy } from '../../stores/zine/authors'
import { handleClientRouteLinkClick, useRouter } from '../../stores/router' import { handleClientRouteLinkClick, useRouter } from '../../stores/router'
import { useAuthStore } from '../../stores/auth' import { useAuthStore } from '../../stores/auth'
import { getLogger } from '../../utils/logger' import { getLogger } from '../../utils/logger'
import '../../styles/AllTopics.scss' import '../../styles/AllTopics.scss'
import { Topic } from '../../graphql/types.gen'
const log = getLogger('AllAuthorsView') const log = getLogger('AllAuthorsView')
@ -23,31 +22,37 @@ type Props = {
export const AllAuthorsView = (props: Props) => { export const AllAuthorsView = (props: Props) => {
const { sortedAuthors } = useAuthorsStore({ authors: props.authors }) const { sortedAuthors } = useAuthorsStore({ authors: props.authors })
const [sortedKeys, setSortedKeys] = createSignal<string[]>([])
const [abc, setAbc] = createSignal([])
const { session } = useAuthStore() const { session } = useAuthStore()
createEffect(() => {
setSortAllAuthorsBy(getSearchParams().by || 'shouts')
})
const subscribed = (s) => Boolean(session()?.news?.authors && session()?.news?.authors?.includes(s || '')) const subscribed = (s) => Boolean(session()?.news?.authors && session()?.news?.authors?.includes(s || ''))
const { getSearchParams } = useRouter<AllAuthorsPageSearchParams>() const { getSearchParams } = useRouter<AllAuthorsPageSearchParams>()
createEffect(() => { const byLetter = createMemo<{ [letter: string]: Author[] }>(() => {
if ((!getSearchParams().by || getSearchParams().by === 'name') && abc().length === 0) { return sortedAuthors().reduce((acc, author) => {
console.log('[authors] default grouping by abc') const letter = author.name[0]
const grouped = { ...groupByName(sortedAuthors()) } if (!acc[letter]) {
grouped['A-Z'] = sortBy(grouped['A-Z'], byFirstChar) acc[letter] = []
setAbc(grouped) }
const keys = Object.keys(abc)
keys.sort() acc[letter].push(author)
setSortedKeys(keys)
} else { return acc
console.log('[authors] sorting by ' + getSearchParams().by) }, {} as { [letter: string]: Author[] })
///setSortedAuthors(sortBy(authorList(), getSearchParams().by))
}
}) })
log.debug(getSearchParams()) const sortedKeys = createMemo<string[]>(() => {
const keys = Object.keys(byLetter())
keys.sort()
return keys
})
// log.debug(getSearchParams())
return ( return (
<div class="all-topics-page"> <div class="all-topics-page">
@ -108,7 +113,7 @@ export const AllAuthorsView = (props: Props) => {
<h2>{letter}</h2> <h2>{letter}</h2>
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<For each={abc()[letter]}> <For each={byLetter()[letter]}>
{(author: Author) => ( {(author: Author) => (
<div class="topic col-sm-6 col-md-3"> <div class="topic col-sm-6 col-md-3">
<div class="topic-title"> <div class="topic-title">

View File

@ -1,4 +1,4 @@
import { createEffect, For, Show } from 'solid-js' import { createEffect, createMemo, For, Show } from 'solid-js'
import type { Topic } from '../../graphql/types.gen' import type { Topic } from '../../graphql/types.gen'
import { Icon } from '../Nav/Icon' import { Icon } from '../Nav/Icon'
import { t } from '../../utils/intl' import { t } from '../../utils/intl'
@ -33,6 +33,25 @@ export const AllTopicsView = (props: AllTopicsViewProps) => {
setSortAllTopicsBy(getSearchParams().by || 'shouts') setSortAllTopicsBy(getSearchParams().by || 'shouts')
}) })
const byLetter = createMemo<{ [letter: string]: Topic[] }>(() => {
return sortedTopics().reduce((acc, topic) => {
const letter = topic.title[0]
if (!acc[letter]) {
acc[letter] = []
}
acc[letter].push(topic)
return acc
}, {} as { [letter: string]: Topic[] })
})
const sortedKeys = createMemo<string[]>(() => {
const keys = Object.keys(byLetter())
keys.sort()
return keys
})
const subscribed = (s) => Boolean(session()?.news?.topics && session()?.news?.topics?.includes(s || '')) const subscribed = (s) => Boolean(session()?.news?.topics && session()?.news?.topics?.includes(s || ''))
return ( return (
@ -80,48 +99,39 @@ export const AllTopicsView = (props: AllTopicsViewProps) => {
</li> </li>
</ul> </ul>
<div class="stats"> <Show
<For each={sortedTopics()}> when={getSearchParams().by === 'title'}
{(topic) => ( fallback={() => (
<TopicCard topic={topic} compact={false} subscribed={subscribed(topic.slug)} /> <div class="stats">
<For each={sortedTopics()}>
{(topic) => (
<TopicCard topic={topic} compact={false} subscribed={subscribed(topic.slug)} />
)}
</For>
</div>
)}
>
<For each={sortedKeys()}>
{(letter) => (
<div class="group">
<h2>{letter}</h2>
<div class="container">
<div class="row">
<For each={byLetter()[letter]}>
{(topic) => (
<div class="topic col-sm-6 col-md-3">
<div class="topic-title">
<a href={`/topic/${topic.slug}`}>{topic.title}</a>
</div>
</div>
)}
</For>
</div>
</div>
</div>
)} )}
</For> </For>
</div> </Show>
{/*FIXME*/}
{/*<Show*/}
{/* when={params()['by'] === 'abc'}*/}
{/* fallback={() => (*/}
{/* <div class="stats">*/}
{/* <For each={getSortedTopics()}>*/}
{/* {(topic: Topic) => (*/}
{/* <TopicCard topic={topic} compact={false} subscribed={subscribed(topic.slug)} />*/}
{/* )}*/}
{/* </For>*/}
{/* </div>*/}
{/* )}*/}
{/*>*/}
{/* <For each={sortedKeys() || []}>*/}
{/* {(letter: string) => (*/}
{/* <div class="group">*/}
{/* <h2>{letter}</h2>*/}
{/* <div class="container">*/}
{/* <div class="row">*/}
{/* <For each={abc()[letter]}>*/}
{/* {(topic: Partial<Topic>) => (*/}
{/* <div class="topic col-sm-6 col-md-3">*/}
{/* <div class="topic-title">*/}
{/* <a href={`/topic/${topic.slug}`}>{topic.title}</a>*/}
{/* </div>*/}
{/* </div>*/}
{/* )}*/}
{/* </For>*/}
{/* </div>*/}
{/* </div>*/}
{/* </div>*/}
{/* )}*/}
{/* </For>*/}
{/*</Show>*/}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
import { apiClient } from '../../utils/apiClient' import { apiClient } from '../../utils/apiClient'
import type { Author } from '../../graphql/types.gen' import type { Author } from '../../graphql/types.gen'
import { byCreated } from '../../utils/sortby' import { byCreated, byStat, byTopicStatDesc } from '../../utils/sortby'
import { getLogger } from '../../utils/logger' import { getLogger } from '../../utils/logger'
import { createSignal } from 'solid-js' import { createSignal } from 'solid-js'
@ -8,9 +8,11 @@ import { createLazyMemo } from '@solid-primitives/memo'
const log = getLogger('authors store') const log = getLogger('authors store')
export type AuthorsSortBy = 'created' | 'name' export type AuthorsSortBy = 'shouts' | 'name' | 'rating'
const [sortAllBy, setSortAllBy] = createSignal<AuthorsSortBy>('created') const [sortAllBy, setSortAllBy] = createSignal<AuthorsSortBy>('shouts')
export { setSortAllBy }
const [authorEntities, setAuthorEntities] = createSignal<{ [authorSlug: string]: Author }>({}) const [authorEntities, setAuthorEntities] = createSignal<{ [authorSlug: string]: Author }>({})
const [authorsByTopic, setAuthorsByTopic] = createSignal<{ [topicSlug: string]: Author[] }>({}) const [authorsByTopic, setAuthorsByTopic] = createSignal<{ [topicSlug: string]: Author[] }>({})
@ -18,16 +20,21 @@ const [authorsByTopic, setAuthorsByTopic] = createSignal<{ [topicSlug: string]:
const sortedAuthors = createLazyMemo(() => { const sortedAuthors = createLazyMemo(() => {
const authors = Object.values(authorEntities()) const authors = Object.values(authorEntities())
switch (sortAllBy()) { switch (sortAllBy()) {
case 'created': { // case 'created': {
log.debug('sorted by created') // log.debug('sorted by created')
authors.sort(byCreated) // authors.sort(byCreated)
// break
// }
case 'rating':
// TODO:
break break
} case 'shouts':
case 'name': { // TODO:
break
case 'name':
log.debug('sorted by name') log.debug('sorted by name')
authors.sort((a, b) => a.name.localeCompare(b.name)) authors.sort((a, b) => a.name.localeCompare(b.name))
break break
}
} }
return authors return authors
}) })