Add voters list component

This commit is contained in:
ilya-bkv 2023-03-10 02:39:07 +03:00
parent 9e69f280cf
commit 21ad1bdf9e
8 changed files with 109 additions and 23 deletions

View File

@ -233,5 +233,7 @@
"By time": "By time",
"New only": "New only",
"Bookmarks": "Bookmarks",
"Logout": "Logout"
"Logout": "Logout",
"This comment has not yet been rated": "This comment has not yet been rated",
"This post has not been rated yet": "This post has not been rated yet"
}

View File

@ -251,5 +251,7 @@
"By time": "По порядку",
"New only": "Только новые",
"Bookmarks": "Закладки",
"Logout": "Выход"
"Logout": "Выход",
"This comment has not yet been rated": "Этот комментарий еще пока никто не оценил",
"This post has not been rated yet": "Эту публикацию еще пока никто не оценил"
}

View File

@ -4,11 +4,12 @@ import type { Reaction } from '../../graphql/types.gen'
import { ReactionKind } from '../../graphql/types.gen'
import { useSession } from '../../context/session'
import { useReactions } from '../../context/reactions'
import { createMemo, For } from 'solid-js'
import { createMemo } from 'solid-js'
import { loadShout } from '../../stores/zine/articles'
import { Popup } from '../_shared/Popup'
import { useLocalize } from '../../context/localize'
import { useSnackbar } from '../../context/snackbar'
import VotersList from '../_shared/VotersList'
type Props = {
comment: Reaction
@ -37,7 +38,7 @@ export const CommentRatingControl = (props: Props) => {
const isDownvoted = createMemo(() => checkReaction(ReactionKind.Dislike))
const canVote = createMemo(() => userSlug() !== props.comment.createdBy.slug)
const shoutRatingReactions = createMemo(() =>
const commentRatingReactions = createMemo(() =>
Object.values(reactionEntities).filter(
(r) =>
[ReactionKind.Like, ReactionKind.Dislike].includes(r.kind) &&
@ -45,6 +46,7 @@ export const CommentRatingControl = (props: Props) => {
r.replyTo === props.comment.id
)
)
const deleteCommentReaction = async (reactionKind: ReactionKind) => {
const reactionToDelete = Object.values(reactionEntities).find(
(r) =>
@ -102,15 +104,10 @@ export const CommentRatingControl = (props: Props) => {
}
variant="tiny"
>
<ul class={clsx('nodash')}>
<For each={shoutRatingReactions()}>
{(reaction) => (
<li>
{reaction.kind === ReactionKind.Like ? <>+1</> : <>&minus;1</>} {reaction.createdBy.name}
</li>
)}
</For>
</ul>
<VotersList
reactions={commentRatingReactions()}
fallbackMessage={t('This comment has not yet been rated')}
/>
</Popup>
<button
role="button"

View File

@ -6,6 +6,8 @@ import { loadShout } from '../../stores/zine/articles'
import { useSession } from '../../context/session'
import { useReactions } from '../../context/reactions'
import { Popup } from '../_shared/Popup'
import VotersList from '../_shared/VotersList'
import { useLocalize } from '../../context/localize'
interface ShoutRatingControlProps {
shout: Shout
@ -13,6 +15,7 @@ interface ShoutRatingControlProps {
}
export const ShoutRatingControl = (props: ShoutRatingControlProps) => {
const { t } = useLocalize()
const { userSlug } = useSession()
const {
@ -83,15 +86,10 @@ export const ShoutRatingControl = (props: ShoutRatingControlProps) => {
</button>
<Popup trigger={<span class={styles.ratingValue}>{props.shout.stat.rating}</span>} variant="tiny">
<ul class={clsx('nodash')}>
<For each={shoutRatingReactions()}>
{(reaction) => (
<li>
{reaction.kind === ReactionKind.Like ? <>+1</> : <>&minus;1</>} {reaction.createdBy.name}
</li>
)}
</For>
</ul>
<VotersList
reactions={shoutRatingReactions()}
fallbackMessage={t('This post has not been rated yet')}
/>
</Popup>
<button

View File

@ -1,4 +1,4 @@
import type { Author } from '../../graphql/types.gen'
import type { Author, User } from '../../graphql/types.gen'
import Userpic from './Userpic'
import { Icon } from '../_shared/Icon'
import styles from './Card.module.scss'

View File

@ -0,0 +1,40 @@
.VotersList {
.users {
margin: 0;
min-width: 220px;
max-height: 360px;
overflow: auto;
}
.item {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
.user {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
margin-right: 1.2rem;
a {
text-decoration: none;
border: none;
}
.userpic {
width: 24px;
height: 24px;
}
}
}
.commentRatingPositive {
color: #2bb452;
}
.commentRatingNegative {
color: #d00820;
}
}

View File

@ -0,0 +1,46 @@
import type { Reaction } from '../../../graphql/types.gen'
import { Author, ReactionKind } from '../../../graphql/types.gen'
import { For, Show } from 'solid-js'
import Userpic from '../../Author/Userpic'
import styles from './VotersList.module.scss'
import { clsx } from 'clsx'
type Props = {
reactions: Reaction[]
fallbackMessage: string
}
const VotersList = (props: Props) => {
return (
<div class={styles.VotersList}>
<ul class={clsx('nodash', styles.users)}>
<Show
when={props.reactions.length > 0}
fallback={
<li class={styles.item}>
<small>{props.fallbackMessage}</small>
</li>
}
>
<For each={props.reactions}>
{(reaction) => (
<li class={styles.item}>
<div class={styles.user}>
<Userpic user={reaction.createdBy as Author} isBig={false} isAuthorsList={false} />
<a href={`/author/${reaction.createdBy.slug}`}>{reaction.createdBy.name || ''}</a>
</div>
{reaction.kind === ReactionKind.Like ? (
<div class={styles.commentRatingPositive}>+1</div>
) : (
<div class={styles.commentRatingNegative}>&minus;1</div>
)}
</li>
)}
</For>
</Show>
</ul>
</div>
)
}
export default VotersList

View File

@ -0,0 +1 @@
export { default } from './VotersList'