webapp/src/components/Article/FullArticle.tsx

205 lines
6.1 KiB
TypeScript
Raw Normal View History

2022-09-09 11:53:35 +00:00
import { capitalize } from '../../utils'
import './Full.scss'
2022-09-22 09:37:49 +00:00
import { Icon } from '../Nav/Icon'
2022-09-09 11:53:35 +00:00
import ArticleComment from './Comment'
import { AuthorCard } from '../Author/Card'
2022-10-07 11:02:34 +00:00
import { createMemo, For, onMount, Show } from 'solid-js'
2022-09-09 11:53:35 +00:00
import type { Author, Reaction, Shout } from '../../graphql/types.gen'
import { t } from '../../utils/intl'
import { showModal } from '../../stores/ui'
2022-09-22 09:37:49 +00:00
import { incrementView } from '../../stores/zine/articles'
2022-10-07 11:02:34 +00:00
import MD from './MD'
2022-10-25 15:36:32 +00:00
import { SharePopup } from './SharePopup'
import { useAuth } from '../../context/auth'
2022-09-13 09:59:04 +00:00
2022-09-09 11:53:35 +00:00
const MAX_COMMENT_LEVEL = 6
const getCommentLevel = (comment: Reaction, level = 0) => {
if (comment && comment.replyTo && level < MAX_COMMENT_LEVEL) {
return 0 // FIXME: getCommentLevel(commentsById[c.replyTo], level + 1)
}
return level
}
interface ArticleProps {
article: Shout
reactions: Reaction[]
isCommentsLoading: boolean
}
const formatDate = (date: Date) => {
return date
.toLocaleDateString('ru', {
month: 'long',
day: 'numeric',
year: 'numeric'
})
.replace(' г.', '')
}
export const FullArticle = (props: ArticleProps) => {
const { session } = useAuth()
2022-09-13 09:59:04 +00:00
2022-09-14 11:28:43 +00:00
onMount(() => {
incrementView({ articleSlug: props.article.slug })
})
2022-09-09 11:53:35 +00:00
const formattedDate = createMemo(() => formatDate(new Date(props.article.createdAt)))
const mainTopic = () =>
(props.article.topics?.find((topic) => topic?.slug === props.article.mainTopic)?.title || '').replace(
' ',
'&nbsp;'
)
onMount(() => {
const windowHash = window.location.hash
if (windowHash?.length > 0) {
const comments = document.querySelector(windowHash)
if (comments) {
window.scrollTo({
top: comments.getBoundingClientRect().top,
behavior: 'smooth'
})
}
}
})
return (
<div class="shout wide-container">
<article class="col-md-6 shift-content">
<div class="shout__header">
<div class="shout__topic">
<a href={`/topic/${props.article.mainTopic}`} innerHTML={mainTopic() || ''} />
</div>
<h1>{props.article.title}</h1>
<Show when={props.article.subtitle}>
<h4>{capitalize(props.article.subtitle, false)}</h4>
</Show>
<div class="shout__author">
<For each={props.article.authors}>
{(a: Author, index) => (
<>
<Show when={index() > 0}>, </Show>
<a href={`/author/${a.slug}`}>{a.name}</a>
</>
)}
</For>
</div>
<div class="shout__cover" style={{ 'background-image': `url('${props.article.cover}')` }} />
</div>
2022-10-09 10:56:39 +00:00
<Show when={Boolean(props.article.body)}>
<div class="shout__body">
<Show
when={!props.article.body.startsWith('<')}
fallback={<div innerHTML={props.article.body} />}
>
<MD body={props.article.body} />
</Show>
</div>
</Show>
2022-09-09 11:53:35 +00:00
</article>
<div class="col-md-8 shift-content">
<div class="shout-stats">
<div class="shout-stats__item shout-stats__item--likes">
<Icon name="like" />
{props.article.stat?.rating || ''}
</div>
<div class="shout-stats__item">
<Icon name="comment" />
{props.article.stat?.commented || ''}
</div>
<div class="shout-stats__item">
<Icon name="view" />
{props.article.stat?.viewed}
</div>
{/*FIXME*/}
{/*<div class="shout-stats__item">*/}
{/* <a href="#bookmark" onClick={() => console.log(props.article.slug, 'articles')}>*/}
{/* <Icon name={'bookmark' + (bookmarked() ? '' : '-x')} />*/}
{/* </a>*/}
{/*</div>*/}
<div class="shout-stats__item">
2022-10-25 15:36:32 +00:00
<SharePopup
trigger={
<a href="#" onClick={(event) => event.preventDefault()}>
<Icon name="share" />
</a>
}
/>
2022-09-09 11:53:35 +00:00
</div>
{/*FIXME*/}
{/*<Show when={canEdit()}>*/}
{/* <div class="shout-stats__item">*/}
{/* <a href="/edit">*/}
{/* <Icon name="edit" />*/}
{/* {t('Edit')}*/}
{/* </a>*/}
{/* </div>*/}
{/*</Show>*/}
<div class="shout-stats__item shout-stats__item--date">{formattedDate}</div>
</div>
2022-09-13 09:59:04 +00:00
<div class="topics-list">
<For each={props.article.topics}>
{(topic) => (
<div class="shout__topic">
<a href={`/topic/${topic.slug}`}>{topic.title}</a>
</div>
)}
</For>
</div>
2022-09-09 11:53:35 +00:00
<div class="shout__authors-list">
<Show when={props.article?.authors?.length > 1}>
<h4>{t('Authors')}</h4>
</Show>
<For each={props.article?.authors}>
{(a: Author) => <AuthorCard author={a} compact={false} hasLink={true} />}
</For>
</div>
<Show when={props.reactions?.length}>
<h2 id="comments">
{t('Comments')} {props.reactions?.length.toString() || ''}
</h2>
<For each={props.reactions?.filter((r) => r.body)}>
{(reaction) => (
<ArticleComment
comment={reaction}
level={getCommentLevel(reaction)}
2022-09-30 14:22:33 +00:00
canEdit={reaction.createdBy?.slug === session()?.user?.slug}
2022-09-09 11:53:35 +00:00
/>
)}
</For>
</Show>
2022-09-30 14:22:33 +00:00
<Show when={!session()?.user?.slug}>
2022-09-13 09:59:04 +00:00
<div class="comment-warning" id="comments">
{t('To leave a comment you please')}
<a
href={''}
onClick={(evt) => {
evt.preventDefault()
showModal('auth')
}}
>
<i>{t('sign up or sign in')}</i>
</a>
</div>
</Show>
2022-09-30 14:22:33 +00:00
<Show when={session()?.user?.slug}>
2022-09-13 09:59:04 +00:00
<textarea class="write-comment" rows="1" placeholder={t('Write comment')} />
</Show>
2022-09-09 11:53:35 +00:00
</div>
</div>
)
}