webapp/src/components/Views/Feed.tsx

147 lines
4.8 KiB
TypeScript
Raw Normal View History

2022-09-09 12:18:09 +00:00
import { createMemo, For, Show } from 'solid-js'
2022-09-13 09:59:04 +00:00
import type { Shout, Reaction } from '../../graphql/types.gen'
2022-09-09 11:53:35 +00:00
import '../../styles/Feed.scss'
import Icon from '../Nav/Icon'
import { byCreated, sortBy } from '../../utils/sortby'
import { TopicCard } from '../Topic/Card'
import { ArticleCard } from '../Feed/Card'
2022-09-13 09:59:04 +00:00
import { AuthorCard } from '../Author/Card'
2022-09-09 11:53:35 +00:00
import { t } from '../../utils/intl'
import { useStore } from '@nanostores/solid'
2022-09-13 09:59:04 +00:00
import { FeedSidebar } from '../Feed/Sidebar'
2022-09-09 11:53:35 +00:00
import { session } from '../../stores/auth'
import CommentCard from '../Article/Comment'
2022-09-13 09:59:04 +00:00
import { loadRecentArticles, useArticlesStore } from '../../stores/zine/articles'
2022-09-09 11:53:35 +00:00
import { useReactionsStore } from '../../stores/zine/reactions'
import { useAuthorsStore } from '../../stores/zine/authors'
2022-09-09 12:18:09 +00:00
import { useTopicsStore } from '../../stores/zine/topics'
2022-09-09 11:53:35 +00:00
interface FeedProps {
2022-09-13 09:59:04 +00:00
articles: Shout[]
2022-09-09 11:53:35 +00:00
reactions: Reaction[]
2022-09-13 09:59:04 +00:00
page?: number
size?: number
2022-09-09 11:53:35 +00:00
}
2022-09-13 09:59:04 +00:00
// const AUTHORSHIP_REACTIONS = [
// ReactionKind.Accept,
// ReactionKind.Reject,
// ReactionKind.Propose,
// ReactionKind.Ask
// ]
2022-09-09 11:53:35 +00:00
export const FeedPage = (props: FeedProps) => {
// state
2022-09-13 09:59:04 +00:00
const { getSortedArticles: articles } = useArticlesStore({ sortedArticles: props.articles })
2022-09-09 11:53:35 +00:00
const reactions = useReactionsStore(props.reactions)
2022-09-13 09:59:04 +00:00
const { getTopAuthors, getSortedAuthors: authors } = useAuthorsStore()
const { getTopTopics } = useTopicsStore()
2022-09-09 11:53:35 +00:00
const auth = useStore(session)
2022-09-13 09:59:04 +00:00
const topReactions = createMemo(() => sortBy(reactions(), byCreated))
2022-09-09 11:53:35 +00:00
2022-09-13 09:59:04 +00:00
// const expectingFocus = createMemo<Shout[]>(() => {
// // 1 co-author notifications needs
// // TODO: list of articles where you are co-author
// // TODO: preload proposals
// // TODO: (maybe?) and changes history
// console.debug(reactions().filter((r) => r.kind in AUTHORSHIP_REACTIONS))
//
// // 2 community self-regulating mechanics
// // TODO: query all new posts to be rated for publishing
// // TODO: query all reactions where user is in authors list
// return []
// })
2022-09-09 14:08:17 +00:00
2022-09-13 09:59:04 +00:00
const loadMore = () => {
const page = (props.page || 1) + 1
loadRecentArticles({ page })
}
2022-09-09 11:53:35 +00:00
return (
<>
<div class="container feed">
<div class="row">
<div class="col-md-3 feed-navigation">
<FeedSidebar authors={authors()} />
</div>
<div class="col-md-6">
<ul class="feed-filter">
<Show when={!!auth()?.user?.slug}>
<li class="selected">
<a href="/feed/my">{t('My feed')}</a>
</li>
</Show>
<li>
<a href="?by=views">{t('Most read')}</a>
</li>
<li>
<a href="?by=rating">{t('Top rated')}</a>
</li>
<li>
<a href="?by=comments">{t('Most commented')}</a>
</li>
</ul>
2022-09-09 12:18:09 +00:00
<Show when={articles().length > 0}>
<For each={articles().slice(0, 4)}>
2022-09-09 11:53:35 +00:00
{(article) => <ArticleCard article={article} settings={{ isFeedMode: true }} />}
</For>
<div class="beside-column-title">
<h4>{t('Popular authors')}</h4>
<a href="/user/list">
{t('All authors')}
<Icon name="arrow-right" />
</a>
</div>
2022-09-09 12:18:09 +00:00
<ul class="beside-column">
2022-09-13 09:59:04 +00:00
<For each={getTopAuthors()}>
{(author) => (
2022-09-09 12:18:09 +00:00
<li>
<AuthorCard author={author} compact={true} hasLink={true} />
</li>
)}
</For>
</ul>
2022-09-09 11:53:35 +00:00
2022-09-09 12:18:09 +00:00
<For each={articles().slice(4)}>
2022-09-09 11:53:35 +00:00
{(article) => <ArticleCard article={article} settings={{ isFeedMode: true }} />}
</For>
</Show>
<p class="load-more-container">
<button class="button">{t('Load more')}</button>
</p>
</div>
<aside class="col-md-3">
<section class="feed-comments">
<h4>{t('Comments')}</h4>
2022-09-13 09:59:04 +00:00
<For each={topReactions()}>
{(comment) => <CommentCard comment={comment} compact={true} />}
2022-09-09 11:53:35 +00:00
</For>
</section>
2022-09-13 09:59:04 +00:00
<Show when={getTopTopics().length > 0}>
2022-09-09 11:53:35 +00:00
<section class="feed-topics">
<h4>{t('Topics')}</h4>
2022-09-13 09:59:04 +00:00
<For each={getTopTopics()}>
2022-09-09 11:53:35 +00:00
{(topic) => <TopicCard topic={topic} subscribeButtonBottom={true} />}
</For>
</section>
</Show>
</aside>
</div>
2022-09-13 09:59:04 +00:00
2022-09-09 11:53:35 +00:00
<p class="load-more-container">
2022-09-13 09:59:04 +00:00
<button class="button" onClick={loadMore}>
2022-09-09 11:53:35 +00:00
{t('Load more')}
</button>
</p>
</div>
</>
)
}