webapp/src/components/Topic/Card.tsx

158 lines
5.1 KiB
TypeScript
Raw Normal View History

2022-11-09 19:02:12 +00:00
import { clsx } from 'clsx'
2024-02-04 11:25:21 +00:00
import { Show, createMemo, createSignal } from 'solid-js'
2024-01-31 12:34:15 +00:00
import { useFollowing } from '../../context/following'
import { useLocalize } from '../../context/localize'
2022-11-14 10:02:08 +00:00
import { useSession } from '../../context/session'
2024-01-31 12:34:15 +00:00
import { FollowingEntity, type Topic } from '../../graphql/schema/core.gen'
import { capitalize } from '../../utils/capitalize'
2024-02-04 11:25:21 +00:00
import { CardTopic } from '../Feed/CardTopic'
import { Button } from '../_shared/Button'
import { CheckButton } from '../_shared/CheckButton'
import { Icon } from '../_shared/Icon'
import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient'
2023-11-08 20:52:56 +00:00
import stylesButton from '../_shared/Button/Button.module.scss'
2024-02-04 11:25:21 +00:00
import styles from './Card.module.scss'
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-12-08 11:49:50 +00:00
const { t, lang } = useLocalize()
2024-01-31 12:34:15 +00:00
const title = createMemo(() =>
capitalize(lang() === 'en' ? props.topic.slug.replaceAll('-', ' ') : props.topic.title || ''),
)
2024-02-04 17:40:15 +00:00
const { author, requireAuthentication } = useSession()
2024-01-31 12:34:15 +00:00
const { setFollowing, loading: subLoading } = useFollowing()
const [followed, setFollowed] = createSignal()
2024-01-31 12:34:15 +00:00
const handleFollowClick = () => {
const value = !followed()
requireAuthentication(() => {
2024-01-31 12:34:15 +00:00
setFollowed(value)
setFollowing(FollowingEntity.Topic, props.topic.slug, value)
}, 'subscribe')
}
2023-11-02 22:02:11 +00:00
const subscribeValue = () => {
return (
<>
<Show when={props.iconButton}>
2024-01-31 12:34:15 +00:00
<Show when={followed()} fallback="+">
2023-11-02 22:02:11 +00:00
<Icon name="check-subscribed" />
</Show>
</Show>
<Show when={!props.iconButton}>
2024-01-31 12:34:15 +00:00
<Show when={followed()} fallback={t('Follow')}>
2023-11-08 20:52:56 +00:00
<span class={stylesButton.buttonSubscribeLabelHovered}>{t('Unfollow')}</span>
<span class={stylesButton.buttonSubscribeLabel}>{t('Following')}</span>
2023-11-02 22:02:11 +00:00
</Show>
</Show>
</>
)
}
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-06-05 20:46:55 +00:00
}}
>
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,
2024-02-04 17:40:15 +00:00
[clsx('col-sm-17 col-md-18', styles.topicDetails)]: !(
props.subscribeButtonBottom ||
props.isNarrow ||
props.compact
),
2023-09-27 21:28:32 +00:00
}}
>
2023-12-08 11:49:50 +00:00
<Show when={title() && !props.isCardMode}>
2023-06-05 20:46:55 +00:00
<h3 class={styles.topicTitle}>
2023-12-08 11:49:50 +00:00
<a href={`/topic/${props.topic.slug}`}>{title()}</a>
2023-06-05 20:46:55 +00:00
</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}`}>
2023-12-08 11:49:50 +00:00
<img src={props.topic.pic} alt={title()} />
2023-06-05 20:46:55 +00:00
</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>
</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,
2024-02-04 17:40:15 +00:00
'col-sm-7 col-md-6': !(props.subscribeButtonBottom || props.isNarrow || props.compact),
2023-09-27 21:28:32 +00:00
}}
2023-06-05 20:46:55 +00:00
>
<ShowOnlyOnClient>
2024-01-31 12:34:15 +00:00
<Show when={author()}>
<Show
when={!props.minimizeSubscribeButton}
fallback={
2024-01-31 12:34:15 +00:00
<CheckButton
text={t('Follow')}
checked={Boolean(followed())}
onClick={handleFollowClick}
/>
}
2023-06-05 20:46:55 +00:00
>
2023-11-02 22:02:11 +00:00
<Button
variant="bordered"
size="M"
value={subscribeValue()}
2024-01-31 12:34:15 +00:00
onClick={handleFollowClick}
2023-11-08 20:42:13 +00:00
isSubscribeButton={true}
2023-11-02 22:02:11 +00:00
class={clsx(styles.actionButton, {
2024-01-31 12:34:15 +00:00
[styles.isSubscribing]: subLoading(),
[stylesButton.subscribed]: followed(),
2023-11-02 22:02:11 +00:00
})}
2024-01-31 12:34:15 +00:00
// disabled={subLoading()}
2023-11-02 22:02:11 +00:00
/>
</Show>
2023-06-05 20:46:55 +00:00
</Show>
</ShowOnlyOnClient>
</div>
2022-09-09 11:53:35 +00:00
</div>
</div>
)
}