reimplement account style

This commit is contained in:
srgooglo 2022-03-15 04:24:48 +01:00
parent fbb1f9a62b
commit 79231d2c6a
2 changed files with 191 additions and 87 deletions

View File

@ -1,10 +1,10 @@
import React from "react" import React from "react"
import * as antd from "antd" import * as antd from "antd"
import { Translation } from "react-i18next" import classnames from "classnames"
import moment from "moment" import moment from "moment"
import { Icons } from "components/Icons" import { Icons } from "components/Icons"
import { Skeleton, PostsFeed, FollowButton } from "components" import { Skeleton, PostsFeed, FollowButton, FollowersList } from "components"
import { Session, User } from "models" import { Session, User } from "models"
import "./index.less" import "./index.less"
@ -13,6 +13,9 @@ export default class Account extends React.Component {
static bindApp = ["userController", "sessionController"] static bindApp = ["userController", "sessionController"]
state = { state = {
transitionActive: false,
activeKey: "posts",
isSelf: false, isSelf: false,
isFollowed: false, isFollowed: false,
user: null, user: null,
@ -44,15 +47,16 @@ export default class Account extends React.Component {
if (!isSelf) { if (!isSelf) {
const followedResult = await this.api.get.isFollowed(undefined, { user_id: user._id }).catch(() => false) const followedResult = await this.api.get.isFollowed(undefined, { user_id: user._id }).catch(() => false)
const followersResult = await this.api.get.followers(undefined, { user_id: user._id }).catch(() => false)
if (followedResult) { if (followedResult) {
isFollowed = followedResult.isFollowed isFollowed = followedResult.isFollowed
} }
}
if (followersResult) { const followersResult = await this.api.get.followers(undefined, { user_id: user._id }).catch(() => false)
followers = followersResult
} if (followersResult) {
followers = followersResult
} }
} }
@ -92,6 +96,28 @@ export default class Account extends React.Component {
}) })
} }
handlePageTransition = (key) => {
if (this.state.activeKey === key) {
return false
}
this.setState({
transitionActive: true,
})
setTimeout(() => {
this.setState({
activeKey: key
})
setTimeout(() => {
this.setState({
transitionActive: false,
})
}, 100)
}, 100)
}
render() { render() {
const user = this.state.user const user = this.state.user
@ -99,58 +125,82 @@ export default class Account extends React.Component {
return <Skeleton /> return <Skeleton />
} }
const createdAtYear = moment(new Date(Number(user.createdAt))).format("YYYY")
return ( return (
<div className="accountProfile"> <div className="accountProfile">
<div className="card"> {user.cover && <div className="cover" style={{ backgroundImage: `url("${user.cover}")` }} />}
<div className="header"> <div className="profileCard">
<div className="user"> <div className="basicData">
<div> <div className="title">
<img src={user.avatar} /> <div className="field">
<div className="avatar">
<img src={user.avatar} />
</div>
</div> </div>
<div>
<div className="field">
<div> <div>
<h1>{user.fullName ?? user.username}</h1> <h1>{user.fullName ?? user.username}</h1>
<span>@{user.username}</span> {user.verified && <Icons.verifiedBadge />}
</div> </div>
<div id="statistics" className="statistics"> <span>@{user.username}</span>
<div>
<span><Icons.Users /> {this.state.followers.length} Followers</span>
</div>
<div>
<span><Icons.FileText /> 0 Posts</span>
</div>
<div>
<span>Joined at {createdAtYear}</span>
</div>
</div>
</div> </div>
</div> </div>
{!this.state.isSelf && <div> {!this.state.isSelf && <div>
<FollowButton <FollowButton
count={this.state.followers.length}
onClick={this.onClickFollow} onClick={this.onClickFollow}
followed={this.state.isFollowed} followed={this.state.isFollowed}
/> />
</div>} </div>}
</div> </div>
<div className="extension"> <div className="description">
<div className="badgesList"> <p>
{user.badges.map((role, index) => { {user.description}
return <antd.Tag>{role}</antd.Tag> </p>
})}
</div>
</div> </div>
</div> </div>
<antd.Tabs
<div className="posts"> className="tabs"
<PostsFeed type="card"
fromUserId={user._id} activeKey={this.state.activeKey}
/> onTabClick={this.handlePageTransition}
</div> destroyInactiveTabPane
>
<antd.Tabs.TabPane tab={<Icons.Inbox />} key="posts">
<div className={classnames("fade-opacity-active", { "fade-opacity-leave": this.state.transitionActive })}>
<div className="posts">
<PostsFeed
fromUserId={user._id}
/>
</div>
</div>
</antd.Tabs.TabPane>
<antd.Tabs.TabPane tab={<Icons.Users />} key="followers">
<div className={classnames("fade-opacity-active", { "fade-opacity-leave": this.state.transitionActive })}>
<FollowersList
followers={this.state.followers}
/>
</div>
</antd.Tabs.TabPane>
<antd.Tabs.TabPane tab={<Icons.Info />} key="details">
<div className={classnames("fade-opacity-active", { "fade-opacity-leave": this.state.transitionActive })}>
<div id="statistics" className="statistics">
<div>
<span><Icons.Users /> {this.state.followers.length} Followers</span>
</div>
<div>
<span><Icons.FileText /> 0 Posts</span>
</div>
<div>
<span>Joined at {moment(new Date(Number(user.createdAt))).format("YYYY")}</span>
</div>
</div>
</div>
</antd.Tabs.TabPane>
</antd.Tabs>
</div> </div>
) )
} }

View File

@ -1,67 +1,89 @@
@borderColor : #dddddd;
@borderRadius: 12px; @borderRadius: 12px;
.accountProfile { .accountProfile {
.card { padding: 0 20px;
.cover {
z-index : 50;
position : relative;
border-radius: @borderRadius @borderRadius 0 0;
outline: 1px solid var(--border-color);
content: "";
width: 100%;
background-position: center;
background-size : cover;
height: 18vh;
transform: translate(0, 10px);
}
.profileCard {
z-index : 51;
position: relative;
display : flex; display : flex;
flex-direction: column; flex-direction: column;
color : var(--background-color-contrast);
h1, color : var(--background-color-contrast);
h2, background-color: var(--background-color-primary);
h3,
h4,
h5,
h6,
span {
color: var(--background-color-contrast);
}
.header { border : 1px solid var(--border-color);
position: relative; border-radius: @borderRadius;
display : inline-flex;
align-items : center; padding: 20px 15px;
.basicData {
display : inline-flex;
flex-direction : row;
justify-content: space-between; justify-content: space-between;
z-index: 15; margin-bottom: 15px;
width : 100%;
padding: 12px 24px;
font-family: "Roboto Mono", monospace;
color : var(--background-color-contrast);
border : 1px solid var(--border-color);
border-radius: @borderRadius;
word-break: break-all;
.user {
display: inline-flex;
flex-direction: row;
> div {
align-self: flex-start;
margin-right: 15px;
> div {
margin-bottom: 5px;
}
}
.avatar {
img { img {
width : 70px; width : 70px;
height: 70px; height : 70px;
border-radius: 4px; border-radius: 4px;
} }
}
h1 {
margin : 0;
font-size: 35px; svg {
fill: var(--appColor);
}
.title {
display : inline-flex;
flex-direction: row;
align-items : center;
}
.field {
display : inline-flex;
flex-direction: column;
margin-right: 15px;
h1 {
margin: 0;
font-size : 35px;
line-height: 37px; line-height: 37px;
} }
>div {
display: inline-flex;
}
}
}
.description {
p {
word-break: break-all;
margin : 0;
} }
} }
@ -84,9 +106,41 @@
border-radius: 0 0 @borderRadius @borderRadius; border-radius: 0 0 @borderRadius @borderRadius;
} }
h1,
h2,
h3,
h4,
h5,
h6,
span,
p {
user-select: text;
}
} }
>div { .tabs {
margin-bottom: 10px; .ant-tabs-nav {
margin: 0 30px 20px 30px;
}
.ant-tabs-nav::before {
border: none !important;
}
.ant-tabs-tab {
padding : 8px 20px !important;
border-color : var(--border-color) !important;
margin-right : 20px !important;
background-color: var(--background-color-primary) !important;
border-top : 0 !important;
border-radius : 0 0 4px 4px !important;
svg {
font-size: 1rem;
margin : 0 !important;
}
}
} }
} }