webapp/src/components/Topic/Card.tsx

166 lines
5.5 KiB
TypeScript
Raw Normal View History

import { capitalize } from '../../utils'
2022-11-02 21:43:38 +00:00
import styles from './Card.module.scss'
2022-12-17 03:27:00 +00:00
import { createMemo, createSignal, Show } from 'solid-js'
2022-09-09 11:53:35 +00:00
import type { Topic } from '../../graphql/types.gen'
2022-09-13 09:59:04 +00:00
import { FollowingEntity } from '../../graphql/types.gen'
2023-02-17 09:21:02 +00:00
2022-09-13 09:59:04 +00:00
import { follow, unfollow } from '../../stores/zine/common'
2022-11-09 19:02:12 +00:00
import { clsx } from 'clsx'
2022-11-14 10:02:08 +00:00
import { useSession } from '../../context/session'
import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient'
import { Icon } from '../_shared/Icon'
2023-02-17 09:21:02 +00:00
import { useLocalize } from '../../context/localize'
2023-06-05 20:46:55 +00:00
import { CardTopic } from '../Feed/CardTopic'
import { CheckButton } from '../_shared/CheckButton'
2022-09-30 14:22:33 +00:00
2022-09-09 11:53:35 +00:00
interface TopicProps {
topic: Topic
compact?: boolean
subscribed?: boolean
shortDescription?: boolean
subscribeButtonBottom?: boolean
additionalClass?: string
isTopicInRow?: boolean
iconButton?: boolean
2022-11-16 21:08:04 +00:00
showPublications?: boolean
2023-05-17 20:27:24 +00:00
showDescription?: boolean
2023-06-05 20:46:55 +00:00
isCardMode?: boolean
minimizeSubscribeButton?: boolean
2023-09-27 21:28:32 +00:00
isNarrow?: boolean
2023-10-03 23:06:41 +00:00
withIcon?: boolean
2022-09-09 11:53:35 +00:00
}
export const TopicCard = (props: TopicProps) => {
2023-02-17 09:21:02 +00:00
const { t } = useLocalize()
const {
session,
2022-12-06 16:03:55 +00:00
isSessionLoaded,
actions: { loadSession, requireAuthentication }
} = useSession()
const [isSubscribing, setIsSubscribing] = createSignal(false)
2022-09-30 14:22:33 +00:00
2022-09-13 09:59:04 +00:00
const subscribed = createMemo(() => {
2022-10-04 12:16:07 +00:00
if (!session()?.user?.slug || !session()?.news?.topics) {
2022-09-30 14:22:33 +00:00
return false
}
2022-10-04 12:16:07 +00:00
return session()?.news.topics.includes(props.topic.slug)
2022-09-13 09:59:04 +00:00
})
2022-09-09 11:53:35 +00:00
2022-09-13 09:59:04 +00:00
const subscribe = async (really = true) => {
setIsSubscribing(true)
await (really
? follow({ what: FollowingEntity.Topic, slug: props.topic.slug })
: unfollow({ what: FollowingEntity.Topic, slug: props.topic.slug }))
await loadSession()
setIsSubscribing(false)
2022-09-13 09:59:04 +00:00
}
const handleSubscribe = () => {
requireAuthentication(() => {
subscribe(!subscribed())
}, 'subscribe')
}
2022-09-09 11:53:35 +00:00
return (
2023-06-05 20:46:55 +00:00
<div class={styles.topicContainer}>
<div
class={styles.topic}
classList={{
row: !props.subscribeButtonBottom,
[styles.topicCompact]: props.compact,
[styles.topicInRow]: props.isTopicInRow
}}
>
2023-09-27 21:28:32 +00:00
<div
classList={{
[clsx('col-sm-18 col-md-24 col-lg-14 col-xl-15', styles.topicDetails)]: props.isNarrow,
2023-10-09 21:22:06 +00:00
[clsx('col-24 col-sm-17 col-md-18', styles.topicDetails)]: props.compact,
2023-09-27 21:28:32 +00:00
[clsx('col-sm-17 col-md-18', styles.topicDetails)]:
!props.subscribeButtonBottom && !props.isNarrow && !props.compact
}}
>
2023-06-05 20:46:55 +00:00
<Show when={props.topic.title && !props.isCardMode}>
<h3 class={styles.topicTitle}>
<a href={`/topic/${props.topic.slug}`}>{capitalize(props.topic.title || '')}</a>
</h3>
</Show>
<Show when={props.isCardMode}>
<CardTopic title={props.topic.title} slug={props.topic.slug} class={styles.cardMode} />
</Show>
<Show when={props.topic.pic}>
<div class={styles.topicAvatar}>
<a href={`/topic/${props.topic.slug}`}>
<img src={props.topic.pic} alt={props.topic.title} />
</a>
</div>
</Show>
2022-09-09 11:53:35 +00:00
2023-06-05 20:46:55 +00:00
<Show when={props.showDescription && props.topic?.body}>
<div
class={clsx(styles.topicDescription, 'text-truncate')}
classList={{ [styles.topicDescriptionShort]: props.shortDescription }}
2022-11-16 21:08:04 +00:00
>
2023-06-05 20:46:55 +00:00
{props.topic.body}
</div>
</Show>
2023-10-03 23:06:41 +00:00
<Show when={props.showDescription && !props.topic?.body && props.topic.stat?.shouts > 0}>
<div
class={clsx(styles.topicDescription)}
classList={{ [styles.topicDescriptionShort]: props.shortDescription }}
>
{props.topic.stat?.shouts} публикаций
</div>
</Show>
2023-06-05 20:46:55 +00:00
</div>
<div
class={styles.controlContainer}
2023-09-27 21:28:32 +00:00
classList={{
'col-sm-6 col-md-24 col-lg-10 col-xl-9': props.isNarrow,
2023-10-09 21:22:06 +00:00
'col-24 col-sm-7 col-md-6': props.compact,
2023-09-27 21:28:32 +00:00
'col-sm-7 col-md-6': !props.subscribeButtonBottom && !props.isNarrow && !props.compact
}}
2023-06-05 20:46:55 +00:00
>
<ShowOnlyOnClient>
<Show when={isSessionLoaded()}>
<Show
when={!props.minimizeSubscribeButton}
fallback={
<CheckButton text={t('Follow')} checked={subscribed()} onClick={handleSubscribe} />
}
2023-06-05 20:46:55 +00:00
>
<button
onClick={handleSubscribe}
class="button--light button--subscribe-topic"
classList={{
[styles.isSubscribing]: isSubscribing(),
[styles.isSubscribed]: subscribed()
}}
disabled={isSubscribing()}
>
<Show when={props.iconButton}>
<Show when={subscribed()} fallback="+">
<Icon name="check-subscribed" />
</Show>
2023-06-05 20:46:55 +00:00
</Show>
<Show when={!props.iconButton}>
<Show when={subscribed()} fallback={t('Follow')}>
<span class={styles.buttonUnfollowLabel}>{t('Unfollow')}</span>
<span class={styles.buttonSubscribedLabel}>{t('You are subscribed')}</span>
</Show>
2023-06-05 20:46:55 +00:00
</Show>
</button>
</Show>
2023-06-05 20:46:55 +00:00
</Show>
</ShowOnlyOnClient>
</div>
2022-09-09 11:53:35 +00:00
</div>
</div>
)
}