diff --git a/packages/app/src/pages/account/index.jsx b/packages/app/src/pages/account/index.jsx index f46738f7..3f513ed0 100644 --- a/packages/app/src/pages/account/index.jsx +++ b/packages/app/src/pages/account/index.jsx @@ -9,6 +9,63 @@ import { Session, User } from "models" import "./index.less" +const TabsComponent = { + "posts": React.memo((props) => { + return
+ +
+ }), + "followers": React.memo((props) => { + return + }), + "details": React.memo((props) => { + return
+
+ {props.state.followers.length} Followers +
+
+ 0 Posts +
+
+ Joined at {moment(new Date(Number(props.state.user.createdAt))).format("YYYY")} +
+
+ }) +} + +const TabRender = React.memo((props) => { + const [transitionActive, setTransitionActive] = React.useState(false) + const [activeKey, setActiveKey] = React.useState(props.renderKey) + + React.useEffect(() => { + setTransitionActive(true) + + setTimeout(() => { + setActiveKey(props.renderKey) + + setTimeout(() => { + setTransitionActive(false) + }, 100) + }, 100) + }, [props.renderKey]) + + const Tab = TabsComponent[activeKey] + + if (!Tab) { + return

Nothing to see here...

+ } + + return
+ +
+}) + +// TODO: profileCard scroll effect (Hide description and wrap with entire body when cover image is not visible) + export default class Account extends React.Component { state = { requestedUser: null, @@ -20,7 +77,7 @@ export default class Account extends React.Component { isFollowed: false, transitionActive: false, - activeKey: "posts", + tabActiveKey: "posts", isNotExistent: false, } @@ -93,13 +150,12 @@ export default class Account extends React.Component { onClickFollow = async () => { const result = await this.api.put.followUser({ username: this.state.requestedUser, - }) - .catch((error) => { - console.error(error) - antd.message.error(error.message) + }).catch((error) => { + console.error(error) + antd.message.error(error.message) - return false - }) + return false + }) await this.setState({ isFollowed: result.following, @@ -108,25 +164,20 @@ export default class Account extends React.Component { } handlePageTransition = (key) => { - if (this.state.activeKey === key) { + if (typeof key !== "string") { + console.error("Cannot handle page transition. Invalid key, only valid passing string", key) + return + } + + key = key.toLowerCase() + + if (this.state.tabActiveKey === key) { return false } this.setState({ - transitionActive: true, + tabActiveKey: key }) - - setTimeout(() => { - this.setState({ - activeKey: key - }) - - setTimeout(() => { - this.setState({ - transitionActive: false, - }) - }, 100) - }, 100) } render() { @@ -145,86 +196,61 @@ export default class Account extends React.Component { return } - return ( -
- {user.cover &&
} -
-
-
-
-
- ProfileImage -
-
- -
-
-

{user.fullName ?? user.username}

- {user.verified && } -
- - @{user.username} -
-
- - {!this.state.isSelf &&
- -
} -
- -
-

- {user.description} -

-
-
- - Posts} key="posts"> -
-
- + {user.cover &&
} +
+
+
+
+
+ ProfileImage
- - Followers} key="followers"> -
- -
-
- Details} key="details"> -
-
-
- {this.state.followers.length} Followers -
-
- 0 Posts -
-
- Joined at {moment(new Date(Number(user.createdAt))).format("YYYY")} -
+ +
+
+

{user.fullName ?? user.username}

+ {user.verified && }
+ + @{user.username}
- - +
+ + {!this.state.isSelf &&
+ +
} +
+ +
+

+ {user.description} +

+
+ +
+ key.toTitleCase())} + value={this.state.tabActiveKey.toTitleCase()} + onChange={this.handlePageTransition} + /> +
- ) + +
+ +
+
} } \ No newline at end of file diff --git a/packages/app/src/pages/account/index.less b/packages/app/src/pages/account/index.less index c54e1e22..fab80b78 100644 --- a/packages/app/src/pages/account/index.less +++ b/packages/app/src/pages/account/index.less @@ -1,7 +1,11 @@ @borderRadius: 12px; .accountProfile { - padding: 0 20px; + width: 100%; + height: 100%; + + // max-width: 70vw; + // min-width: 900px; .cover { z-index: 50; @@ -16,14 +20,16 @@ background-position: center; background-size: cover; - height: 18vh; + height: 25vh; transform: translate(0, 10px); } .profileCard { - z-index: 51; - position: relative; + position: sticky; + top: 0; + + z-index: 151; display: flex; flex-direction: column; @@ -32,7 +38,7 @@ background-color: var(--background-color-primary); border: 1px solid var(--border-color); - border-radius: @borderRadius; + border-radius: @borderRadius @borderRadius 0 @borderRadius; padding: 20px 15px; @@ -110,6 +116,27 @@ border-radius: 0 0 @borderRadius @borderRadius; } + .switchTab { + position: absolute; + bottom: 0; + right: -1px; + + border: 1px solid var(--border-color); + border-top: none; + + transform: translate(0, 33px); + background-color: var(--background-color-primary); + border-radius: 0 0 8px 8px; + + // .ant-segmented { + // background-color: transparent; + // } + + // .ant-segmented-item-selected { + // background-color: var(--background-color-accent)!important; + // } + } + h1, h2, h3, @@ -122,6 +149,10 @@ } } + .tabContent { + margin-top: 45px; + } + .tabs { transform: translate(0, -20px); position: relative; @@ -133,6 +164,11 @@ .ant-tabs-nav { margin: 0 20px 20px 0; + + z-index: 152; + + position: sticky; + top: 0; } .ant-tabs-nav::before {