From dc6dda4745ca9bcba751a9560f99d6e1270d9703 Mon Sep 17 00:00:00 2001
From: kvakazyambra
Date: Sun, 8 Jan 2023 18:45:33 +0400
Subject: [PATCH] Profile (#81)
- Show profile tabs (comments and about)
- Save profile fields
Co-authored-by: ilya-bkv
---
.../Article/RatingControl.module.scss | 3 +-
src/components/Author/Card.module.scss | 38 ++++-
src/components/Author/Card.tsx | 4 +-
src/components/Author/Full.scss | 15 +-
src/components/Author/Full.tsx | 2 +-
src/components/Author/Userpic.module.scss | 6 +-
src/components/Views/Author.module.scss | 55 +++++++
src/components/Views/Author.tsx | 143 +++++++++++++-----
.../_shared/Popup/Popup.module.scss | 31 ++--
src/locales/ru.json | 1 +
src/utils/apiClient.ts | 14 +-
11 files changed, 249 insertions(+), 63 deletions(-)
create mode 100644 src/components/Views/Author.module.scss
diff --git a/src/components/Article/RatingControl.module.scss b/src/components/Article/RatingControl.module.scss
index 68001845..1d871050 100644
--- a/src/components/Article/RatingControl.module.scss
+++ b/src/components/Article/RatingControl.module.scss
@@ -16,8 +16,7 @@
justify-content: center;
height: 0.9em;
line-height: 0;
- @include font-size(3.6rem);
-
+ font-size: 1.6em;
padding: 0;
width: 0.9em;
diff --git a/src/components/Author/Card.module.scss b/src/components/Author/Card.module.scss
index 19df71b5..e8f9062a 100644
--- a/src/components/Author/Card.module.scss
+++ b/src/components/Author/Card.module.scss
@@ -54,6 +54,10 @@
padding: 0 0 0 42px;
}
+ @include media-breakpoint-down(md) {
+ flex-wrap: wrap;
+ }
+
a {
background: #f7f7f7;
border: none;
@@ -136,6 +140,17 @@
}
}
+.authorSubscribeSocial {
+ align-items: center;
+ display: flex;
+
+ @include media-breakpoint-down(sm) {
+ flex: 1 100%;
+ justify-content: center;
+ margin-top: 1em;
+ }
+}
+
.buttonSubscribe {
align-items: center;
aspect-ratio: 1/1;
@@ -180,9 +195,12 @@
}
.authorPage {
+ @include media-breakpoint-down(md) {
+ justify-content: center;
+ }
+
.authorName {
@include font-size(3.4rem);
-
font-weight: 500;
margin-bottom: 0.2em;
}
@@ -195,10 +213,18 @@
.authorSubscribe {
margin-top: 2rem;
padding-left: 0;
+
+ @include media-breakpoint-down(md) {
+ justify-content: center;
+ }
}
.authorDetails {
display: block;
+
+ @include media-breakpoint-down(md) {
+ flex: 1 100%;
+ }
}
.buttonLabel {
@@ -237,6 +263,16 @@
.button {
margin-right: 1.6rem;
vertical-align: middle;
+
+ &:last-of-type {
+ margin-right: 0;
+ }
+
+ @include media-breakpoint-down(sm) {
+ display: block;
+ margin-bottom: 0.5em;
+ margin-right: 0;
+ }
}
}
diff --git a/src/components/Author/Card.tsx b/src/components/Author/Card.tsx
index 3daa4a10..680e2b8c 100644
--- a/src/components/Author/Card.tsx
+++ b/src/components/Author/Card.tsx
@@ -177,7 +177,9 @@ export const AuthorCard = (props: AuthorCardProps) => {
- {(link) => }
+
diff --git a/src/components/Author/Full.scss b/src/components/Author/Full.scss
index 13f5e9ca..801cd85c 100644
--- a/src/components/Author/Full.scss
+++ b/src/components/Author/Full.scss
@@ -1,11 +1,22 @@
.user-details {
- margin-bottom: 5.4rem;
+ margin: 0 0 5.4rem;
+
+ @include media-breakpoint-up(md) {
+ margin-left: 160px;
+ }
+
+ @include media-breakpoint-up(lg) {
+ margin-left: 235px;
+ }
+
+ @include media-breakpoint-down(md) {
+ text-align: center;
+ }
}
.author-page {
.view-switcher {
@include font-size(1.5rem);
-
margin-top: 0;
button {
diff --git a/src/components/Author/Full.tsx b/src/components/Author/Full.tsx
index b240ae2b..0d621af4 100644
--- a/src/components/Author/Full.tsx
+++ b/src/components/Author/Full.tsx
@@ -5,7 +5,7 @@ import './Full.scss'
export const AuthorFull = (props: { author: Author }) => {
return (
-
diff --git a/src/components/Author/Userpic.module.scss b/src/components/Author/Userpic.module.scss
index 20ed085e..18855e50 100644
--- a/src/components/Author/Userpic.module.scss
+++ b/src/components/Author/Userpic.module.scss
@@ -35,12 +35,16 @@
}
.big.circlewrap {
- margin-right: 4.8rem;
+ margin-right: 0;
max-width: 168px;
min-width: 168px;
height: 168px;
width: 168px;
+ @include media-breakpoint-up(md) {
+ margin-right: 4.8rem;
+ }
+
.userpic {
font-size: 2em;
line-height: 168px;
diff --git a/src/components/Views/Author.module.scss b/src/components/Views/Author.module.scss
new file mode 100644
index 00000000..9b279d03
--- /dev/null
+++ b/src/components/Views/Author.module.scss
@@ -0,0 +1,55 @@
+.ratingContainer {
+ @include font-size(1.5rem);
+ display: inline-block;
+ vertical-align: top;
+}
+
+.ratingControl {
+ @include font-size(1.5rem);
+ display: inline-flex;
+ margin-left: 1em;
+ vertical-align: middle;
+}
+
+.additionalControls {
+ white-space: nowrap;
+
+ @include media-breakpoint-up(md) {
+ text-align: right;
+ }
+}
+
+.userpic {
+ background: #fff;
+ box-shadow: 0 0 0 2px #fff;
+ display: inline-block;
+ margin-right: -1.2rem;
+ vertical-align: top;
+}
+
+.subscribers {
+ cursor: pointer;
+ display: inline-block;
+ margin: -0.4rem 2em 0 0;
+ vertical-align: top;
+}
+
+.subscribersCounter {
+ background: #fff;
+ border: 2px solid #000;
+ border-radius: 100%;
+ @include font-size(1rem);
+ font-weight: bold;
+ height: 32px;
+ line-height: 30px;
+ position: relative;
+ text-align: center;
+ width: 32px;
+ z-index: 1;
+}
+
+.subscribersList {
+ max-height: 15em;
+ overflow: auto;
+ position: relative;
+}
diff --git a/src/components/Views/Author.tsx b/src/components/Views/Author.tsx
index 37b3030a..a2aa1e99 100644
--- a/src/components/Views/Author.tsx
+++ b/src/components/Views/Author.tsx
@@ -1,7 +1,7 @@
-import { Show, createMemo, createSignal, For, onMount } from 'solid-js'
+import { Show, createMemo, createSignal, Switch, onMount, For, Match, createEffect } from 'solid-js'
import type { Author, Shout } from '../../graphql/types.gen'
+import { Row1 } from '../Feed/Row1'
import { Row2 } from '../Feed/Row2'
-import { Row3 } from '../Feed/Row3'
import { AuthorFull } from '../Author/Full'
import { t } from '../../utils/intl'
import { useAuthorsStore } from '../../stores/zine/authors'
@@ -9,9 +9,17 @@ import { loadShouts, useArticlesStore } from '../../stores/zine/articles'
import { useTopicsStore } from '../../stores/zine/topics'
import { useRouter } from '../../stores/router'
-import { Beside } from '../Feed/Beside'
import { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll'
import { splitToPages } from '../../utils/splitToPages'
+import { RatingControl } from '../Article/RatingControl'
+import styles from './Author.module.scss'
+import { clsx } from 'clsx'
+import Userpic from '../Author/Userpic'
+import { Popup } from '../_shared/Popup'
+import { AuthorCard } from '../Author/Card'
+import { loadReactionsBy, REACTIONS_AMOUNT_PER_PAGE } from '../../stores/zine/reactions'
+import { apiClient } from '../../utils/apiClient'
+import Comment from '../Article/Comment'
// TODO: load reactions on client
type AuthorProps = {
@@ -23,7 +31,7 @@ type AuthorProps = {
}
type AuthorPageSearchParams = {
- by: '' | 'viewed' | 'rating' | 'commented' | 'recent' | 'followed'
+ by: '' | 'viewed' | 'rating' | 'commented' | 'recent' | 'followed' | 'about' | 'popular'
}
export const PRERENDERED_ARTICLES_COUNT = 12
@@ -38,6 +46,7 @@ export const AuthorView = (props: AuthorProps) => {
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
const author = createMemo(() => authorEntities()[props.authorSlug])
+ const subscribers = Array.from({ length: 12 }).fill(author())
const { searchParams, changeSearchParam } = useRouter
()
const loadMore = async () => {
@@ -69,6 +78,23 @@ export const AuthorView = (props: AuthorProps) => {
splitToPages(sortedArticles(), PRERENDERED_ARTICLES_COUNT, LOAD_MORE_PAGE_SIZE)
)
+ console.log('!!! authorEntities():', author())
+ const [commented, setCommented] = createSignal([])
+ createEffect(async () => {
+ if (searchParams().by === 'commented') {
+ try {
+ const data = await apiClient.getReactionsBy({
+ by: { comment: true, createdBy: props.authorSlug },
+ limit: 100,
+ offset: 0
+ })
+ setCommented(data)
+ } catch (error) {
+ console.log('!!! error:', error)
+ }
+ }
+ })
+
return (
{t('Loading')}
}>
@@ -89,52 +115,91 @@ export const AuthorView = (props: AuthorProps) => {
+
+
+
+
+
+
-
-
- {`${t('Show')} `}
-
{t('All posts')}
+
+ }
+ variant="tiny"
+ >
+
+
+ {(item: Author) => (
+ -
+
+
+ )}
+
+
+
+
+
+ Карма
+
-
-
-
-
-
+ дефолтное состояние
}>
+
+ About
+ {JSON.stringify(authorEntities())}
+
+
+ {(comment) => }
+
+
+
+
+
+
+
+
-
- {(page) => (
- <>
-
-
-
- >
- )}
-
+
+ {(page) => (
+ <>
+
+
+
+
+
+
+ >
+ )}
+
-
-
-
-
-
+
+
+
+
+
+
+
)
diff --git a/src/components/_shared/Popup/Popup.module.scss b/src/components/_shared/Popup/Popup.module.scss
index b1890f63..3325cc7c 100644
--- a/src/components/_shared/Popup/Popup.module.scss
+++ b/src/components/_shared/Popup/Popup.module.scss
@@ -4,18 +4,19 @@
.popup {
background: #fff;
- top: calc(100% + 8px);
- opacity: 1;
color: #000;
- position: absolute;
- z-index: 100;
min-width: 144px;
+ opacity: 1;
+ position: absolute;
+ top: calc(100% + 8px);
+ z-index: 100;
ul {
margin-bottom: 0;
li {
position: relative;
+
&:last-child {
margin-bottom: 0;
}
@@ -24,11 +25,12 @@
&.bordered {
@include font-size(1.6rem);
-
border: 2px solid #000;
padding: 2.4rem;
+
ul li {
margin-bottom: 1.6rem;
+
&:last-child {
margin-bottom: 0;
}
@@ -37,11 +39,12 @@
&.tiny {
@include font-size(1.4rem);
-
box-shadow: 0 4px 60px rgba(0, 0, 0, 0.1);
padding: 1rem;
+
ul li {
margin-bottom: 1rem;
+
&:last-child {
margin-bottom: 0;
}
@@ -67,22 +70,22 @@
white-space: nowrap;
&:hover {
- img {
+ .icon img {
filter: invert(0);
}
}
}
- img {
- filter: invert(1);
- max-height: 2rem;
- max-width: 2rem;
- transition: filter 0.3s;
- }
-
.icon {
display: inline-block;
width: 3.6rem;
+
+ img {
+ filter: invert(1);
+ max-height: 2rem;
+ max-width: 2rem;
+ transition: filter 0.3s;
+ }
}
}
diff --git a/src/locales/ru.json b/src/locales/ru.json
index b9e8c8db..6eda3234 100644
--- a/src/locales/ru.json
+++ b/src/locales/ru.json
@@ -52,6 +52,7 @@
"Fill email": "Введите почту",
"Follow": "Подписаться",
"Follow the topic": "Подписаться на тему",
+ "Followers": "Подписчики",
"Forgot password?": "Забыли пароль?",
"Full name": "Имя и фамилия",
"Get to know the most intelligent people of our time, edit and discuss the articles, share your expertise, rate and decide what to publish in the magazine": "Познакомитесь с выдающимися людьми нашего времени, участвуйте в редактировании и обсуждении статей, выступайте экспертом, оценивайте материалы других авторов со всего мира и определяйте, какие статьи будут опубликованы в журнале",
diff --git a/src/utils/apiClient.ts b/src/utils/apiClient.ts
index 113047bd..a3132aa6 100644
--- a/src/utils/apiClient.ts
+++ b/src/utils/apiClient.ts
@@ -12,7 +12,8 @@ import type {
MutationCreateMessageArgs,
Chat,
QueryLoadRecipientsArgs,
- ProfileInput
+ ProfileInput,
+ ReactionBy
} from '../graphql/types.gen'
import { publicGraphQLClient } from '../graphql/publicGraphQLClient'
import { getToken, privateGraphQLClient } from '../graphql/privateGraphQLClient'
@@ -269,7 +270,16 @@ export const apiClient = {
if (resp.error) console.debug(resp)
return resp.data.loadShouts
},
- getReactionsBy: async ({ by, limit = REACTIONS_AMOUNT_PER_PAGE, offset = 0 }) => {
+
+ getReactionsBy: async ({
+ by,
+ limit = REACTIONS_AMOUNT_PER_PAGE,
+ offset = 0
+ }: {
+ by: ReactionBy
+ limit: number
+ offset: number
+ }) => {
const resp = await publicGraphQLClient.query(reactionsLoadBy, { by, limit, offset }).toPromise()
console.debug(resp)
return resp.data.loadReactionsBy