webapp/src/components/Author/Card.tsx
Ilya Y 1977493dcd
Delete reaction (#85)
* Delete reactions
2023-01-20 07:40:55 +03:00

195 lines
6.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { Author } from '../../graphql/types.gen'
import Userpic from './Userpic'
import { Icon } from '../_shared/Icon'
import styles from './Card.module.scss'
import { createMemo, createSignal, For, Show } from 'solid-js'
import { translit } from '../../utils/ru2en'
import { t } from '../../utils/intl'
import { locale } from '../../stores/ui'
import { follow, unfollow } from '../../stores/zine/common'
import { clsx } from 'clsx'
import { useSession } from '../../context/session'
import { StatMetrics } from '../_shared/StatMetrics'
import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient'
import { FollowingEntity } from '../../graphql/types.gen'
import { router, useRouter } from '../../stores/router'
import { openPage } from '@nanostores/router'
interface AuthorCardProps {
caption?: string
compact?: boolean
hideDescription?: boolean
hideFollow?: boolean
hasLink?: boolean
subscribed?: boolean
author: Author
isAuthorPage?: boolean
noSocialButtons?: boolean
isAuthorsList?: boolean
truncateBio?: boolean
liteButtons?: boolean
isComments?: boolean
}
export const AuthorCard = (props: AuthorCardProps) => {
const {
session,
isSessionLoaded,
actions: { loadSession }
} = useSession()
if (!props.author) return false // FIXME: с сервера должен приходить автор реакции (ApiClient.CreateReaction)
const [isSubscribing, setIsSubscribing] = createSignal(false)
const subscribed = createMemo<boolean>(() => {
return session()?.news?.authors?.some((u) => u === props.author.slug) || false
})
const subscribe = async (really = true) => {
setIsSubscribing(true)
await (really
? follow({ what: FollowingEntity.Author, slug: props.author.slug })
: unfollow({ what: FollowingEntity.Author, slug: props.author.slug }))
await loadSession()
setIsSubscribing(false)
}
const canFollow = createMemo(() => !props.hideFollow && session()?.user?.slug !== props.author.slug)
const name = createMemo(() => {
if (locale() !== 'ru') {
if (props.author.name === 'Дискурс') {
return 'Discours'
}
return translit(props.author.name)
}
return props.author.name
})
// TODO: reimplement AuthorCard
const { changeSearchParam } = useRouter()
const initChat = () => {
openPage(router, `inbox`)
changeSearchParam('initChat', `${props.author.id}`)
}
return (
<div
class={clsx(styles.author)}
classList={{
[styles.authorPage]: props.isAuthorPage,
[styles.authorComments]: props.isComments,
[styles.authorsListItem]: props.isAuthorsList
}}
>
<Userpic
user={props.author}
hasLink={props.hasLink}
isBig={props.isAuthorPage}
isAuthorsList={props.isAuthorsList}
class={styles.circlewrap}
/>
<div class={styles.authorDetails}>
<div class={styles.authorDetailsWrapper}>
<Show when={props.hasLink}>
<a class={styles.authorName} href={`/author/${props.author.slug}`}>
{name()}
</a>
</Show>
<Show when={!props.hasLink}>
<div class={styles.authorName}>{name()}</div>
</Show>
<Show when={!props.hideDescription && props.author.bio}>
{props.isAuthorsList}
<div
class={styles.authorAbout}
classList={{ 'text-truncate': props.truncateBio }}
innerHTML={props.author.bio}
/>
</Show>
<Show when={props.author.stat}>
<StatMetrics fields={['shouts', 'followers', 'comments']} stat={props.author.stat} />
</Show>
</div>
<ShowOnlyOnClient>
<Show when={isSessionLoaded()}>
<Show when={canFollow()}>
<div class={styles.authorSubscribe}>
<Show
when={subscribed()}
fallback={
<button
onClick={() => subscribe(true)}
class={clsx('button', styles.button)}
classList={{
[styles.buttonSubscribe]: !props.isAuthorsList,
'button--subscribe': !props.isAuthorsList,
'button--subscribe-topic': props.isAuthorsList,
[styles.buttonWrite]: props.isAuthorsList,
[styles.isSubscribing]: isSubscribing()
}}
disabled={isSubscribing()}
>
<Show when={!props.isAuthorsList}>
<Icon name="author-subscribe" class={styles.icon} />
</Show>
<span class={styles.buttonLabel}>{t('Follow')}</span>
</button>
}
>
<button
onClick={() => subscribe(false)}
class={clsx('button', styles.button)}
classList={{
[styles.buttonSubscribe]: !props.isAuthorsList,
'button--subscribe': !props.isAuthorsList,
'button--subscribe-topic': props.isAuthorsList,
[styles.buttonWrite]: props.isAuthorsList,
[styles.isSubscribing]: isSubscribing()
}}
disabled={isSubscribing()}
>
<Show when={!props.isAuthorsList}>
<Icon name="author-unsubscribe" class={styles.icon} />
</Show>
<span class={styles.buttonLabel}>{t('Unfollow')}</span>
</button>
</Show>
<Show when={!props.compact && !props.isAuthorsList}>
<button
class={styles.button}
classList={{
[styles.buttonSubscribe]: !props.isAuthorsList,
'button--subscribe': !props.isAuthorsList,
'button--subscribe-topic': props.isAuthorsList,
[styles.buttonWrite]: props.liteButtons && props.isAuthorsList
}}
onClick={initChat}
>
<Icon name="comment" class={styles.icon} />
<Show when={!props.liteButtons}>{t('Write')}</Show>
</button>
<Show when={!props.noSocialButtons}>
<div class={styles.authorSubscribeSocial}>
<For each={props.author.links}>{(link) => <a href={link} />}</For>
</div>
</Show>
</Show>
</div>
</Show>
</Show>
</ShowOnlyOnClient>
</div>
</div>
)
}