Show user followers

This commit is contained in:
ilia tapazukk 2023-02-13 13:48:05 +00:00
parent 1cfbffc213
commit 63ea0b8d63
7 changed files with 70 additions and 23 deletions

View File

@ -1,6 +1,8 @@
.author { .author {
align-items: flex-start; align-items: flex-start;
display: flex; display: flex;
flex-direction: row;
flex-wrap: nowrap;
margin-bottom: 2.4rem; margin-bottom: 2.4rem;
&:last-child { &:last-child {
@ -293,6 +295,12 @@
} }
} }
.nowrapView {
flex-wrap: nowrap;
align-items: center;
margin: 0;
}
.authorComments { .authorComments {
.authorName { .authorName {
@include font-size(1.2rem); @include font-size(1.2rem);

View File

@ -30,6 +30,7 @@ interface AuthorCardProps {
liteButtons?: boolean liteButtons?: boolean
isComments?: boolean isComments?: boolean
isFeedMode?: boolean isFeedMode?: boolean
isNowrap?: boolean
} }
export const AuthorCard = (props: AuthorCardProps) => { export const AuthorCard = (props: AuthorCardProps) => {
@ -83,7 +84,8 @@ export const AuthorCard = (props: AuthorCardProps) => {
[styles.authorPage]: props.isAuthorPage, [styles.authorPage]: props.isAuthorPage,
[styles.authorComments]: props.isComments, [styles.authorComments]: props.isComments,
[styles.authorsListItem]: props.isAuthorsList, [styles.authorsListItem]: props.isAuthorsList,
[styles.feedMode]: props.isFeedMode [styles.feedMode]: props.isFeedMode,
[styles.nowrapView]: props.isNowrap
}} }}
> >
<Userpic <Userpic

View File

@ -55,4 +55,19 @@
max-height: 15em; max-height: 15em;
overflow: auto; overflow: auto;
position: relative; position: relative;
.subscriber {
white-space: nowrap;
display: flex;
flex-direction: row;
align-items: center;
margin: 0;
border-radius: 4px;
padding: 8px 4px;
transition: background 0.2s ease-in-out;
&:hover {
background: #f7f7f7;
}
}
} }

View File

@ -18,6 +18,7 @@ import { Popup } from '../_shared/Popup'
import { AuthorCard } from '../Author/Card' import { AuthorCard } from '../Author/Card'
import { apiClient } from '../../utils/apiClient' import { apiClient } from '../../utils/apiClient'
import { Comment } from '../Article/Comment' import { Comment } from '../Article/Comment'
import DialogAvatar from '../Inbox/DialogAvatar'
// TODO: load reactions on client // TODO: load reactions on client
type AuthorProps = { type AuthorProps = {
@ -43,7 +44,16 @@ export const AuthorView = (props: AuthorProps) => {
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false) const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
const author = createMemo(() => authorEntities()[props.authorSlug]) const author = createMemo(() => authorEntities()[props.authorSlug])
const subscribers = Array.from({ length: 12 }).fill(author()) const [followers, setFollowers] = createSignal<Author[]>([])
onMount(async () => {
try {
const authorSubscribers = await apiClient.getAuthorFollowers({ slug: props.author.slug })
setFollowers(authorSubscribers)
} catch (error) {
console.log('[getAuthorSubscribers]', error)
}
})
const { searchParams, changeSearchParam } = useRouter<AuthorPageSearchParams>() const { searchParams, changeSearchParam } = useRouter<AuthorPageSearchParams>()
changeSearchParam('by', 'rating') changeSearchParam('by', 'rating')
@ -136,19 +146,36 @@ export const AuthorView = (props: AuthorProps) => {
{...props} {...props}
trigger={ trigger={
<div class={styles.subscribers}> <div class={styles.subscribers}>
<Userpic user={author()} class={styles.userpic} /> <Switch>
<Userpic user={author()} class={styles.userpic} /> <Match when={followers().length <= 3}>
<Userpic user={author()} class={styles.userpic} /> <For each={followers().slice(0, 3)}>
<div class={clsx(styles.userpic, styles.subscribersCounter)}>12</div> {(f) => <Userpic user={f} class={styles.userpic} />}
</For>
</Match>
<Match when={followers().length > 3}>
<For each={followers().slice(0, 2)}>
{(f) => <Userpic user={f} class={styles.userpic} />}
</For>
<div class={clsx(styles.userpic, styles.subscribersCounter)}>
{followers().length}
</div>
</Match>
</Switch>
</div> </div>
} }
variant="tiny" variant="tiny"
> >
<ul class={clsx('nodash', styles.subscribersList)}> <ul class={clsx('nodash', styles.subscribersList)}>
<For each={subscribers}> <For each={followers()}>
{(item: Author) => ( {(item: Author) => (
<li> <li class={styles.subscriber}>
<AuthorCard author={item} hideDescription={true} hideFollow={true} hasLink={true} /> <AuthorCard
author={item}
isNowrap={true}
hideDescription={true}
hideFollow={true}
hasLink={true}
/>
</li> </li>
)} )}
</For> </For>
@ -156,7 +183,7 @@ export const AuthorView = (props: AuthorProps) => {
</Popup> </Popup>
<div class={styles.ratingContainer}> <div class={styles.ratingContainer}>
Карма {t('Karma')}
<RatingControl rating={19} class={styles.ratingControl} /> <RatingControl rating={19} class={styles.ratingControl} />
</div> </div>
</div> </div>

View File

@ -2,22 +2,12 @@ import { gql } from '@urql/core'
export default gql` export default gql`
query UserSubscribersQuery($slug: String!) { query UserSubscribersQuery($slug: String!) {
userSubcribers(slug: $slug) { userFollowers(slug: $slug) {
_id: slug _id: slug
id id
slug slug
name name
bio
userpic userpic
communities
links
createdAt
lastSeen
ratings {
_id: rater
rater
value
}
} }
} }
` `

View File

@ -237,5 +237,6 @@
"Header": "Заголовок", "Header": "Заголовок",
"Subheader": "Подзаголовок", "Subheader": "Подзаголовок",
"A short introduction to keep the reader interested": "Небольшое вступление, чтобы заинтересовать читателя", "A short introduction to keep the reader interested": "Небольшое вступление, чтобы заинтересовать читателя",
"Publish": "Опубликовать" "Publish": "Опубликовать",
"Karma": "Карма"
} }

View File

@ -37,6 +37,7 @@ import createArticle from '../graphql/mutation/article-create'
import myChats from '../graphql/query/chats-load' import myChats from '../graphql/query/chats-load'
import chatMessagesLoadBy from '../graphql/query/chat-messages-load-by' import chatMessagesLoadBy from '../graphql/query/chat-messages-load-by'
import authorBySlug from '../graphql/query/author-by-slug' import authorBySlug from '../graphql/query/author-by-slug'
import userSubscribers from '../graphql/query/author-followers'
import topicBySlug from '../graphql/query/topic-by-slug' import topicBySlug from '../graphql/query/topic-by-slug'
import createChat from '../graphql/mutation/create-chat' import createChat from '../graphql/mutation/create-chat'
import reactionsLoadBy from '../graphql/query/reactions-load-by' import reactionsLoadBy from '../graphql/query/reactions-load-by'
@ -217,9 +218,12 @@ export const apiClient = {
const response = await publicGraphQLClient.query(authorBySlug, { slug }).toPromise() const response = await publicGraphQLClient.query(authorBySlug, { slug }).toPromise()
return response.data.getAuthor return response.data.getAuthor
}, },
getAuthorFollowers: async ({ slug }: { slug: string }): Promise<Author[]> => {
const response = await publicGraphQLClient.query(userSubscribers, { slug }).toPromise()
return response.data.userFollowers
},
updateProfile: async (input: ProfileInput) => { updateProfile: async (input: ProfileInput) => {
const response = await privateGraphQLClient.mutation(updateProfile, { profile: input }).toPromise() const response = await privateGraphQLClient.mutation(updateProfile, { profile: input }).toPromise()
console.log('!!! response.data.getAuthor:', response.data.updateProfile)
return response.data.updateProfile return response.data.updateProfile
}, },
getTopic: async ({ slug }: { slug: string }): Promise<Topic> => { getTopic: async ({ slug }: { slug: string }): Promise<Topic> => {