mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 18:44:16 +00:00
improve mobile mode for account
page
This commit is contained in:
parent
6c59b8b850
commit
0a54cc6f1a
@ -2,59 +2,6 @@
|
||||
|
||||
@borderRadius: 12px;
|
||||
|
||||
#root {
|
||||
&.mobile {
|
||||
.accountProfile {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.panels {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.tabMenuWrapper {
|
||||
position: fixed;
|
||||
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
|
||||
z-index: 300;
|
||||
|
||||
width: 100%;
|
||||
|
||||
height: @top_bar_height;
|
||||
|
||||
padding: @top_bar_padding;
|
||||
|
||||
box-shadow: @card-shadow-top;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
align-items: center;
|
||||
|
||||
opacity: 0;
|
||||
|
||||
.ant-menu {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.ant-menu-item {
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.topHidden {
|
||||
.tabMenuWrapper {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.accountProfile {
|
||||
display: flex;
|
||||
|
||||
@ -123,15 +70,18 @@
|
||||
.panels {
|
||||
position: relative;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-template-rows: 1fr;
|
||||
grid-column-gap: 20px;
|
||||
grid-row-gap: 0px;
|
||||
display: flex;
|
||||
// grid-template-columns: repeat(3, 1fr);
|
||||
// grid-template-rows: 1fr;
|
||||
// grid-column-gap: 20px;
|
||||
// grid-row-gap: 0px;
|
||||
|
||||
gap: 20px;
|
||||
|
||||
padding-top: 20px;
|
||||
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.leftPanel {
|
||||
position: sticky;
|
||||
@ -178,6 +128,7 @@
|
||||
|
||||
.content {
|
||||
height: 100%;
|
||||
width: 90%;
|
||||
|
||||
.fade-opacity-active {
|
||||
height: 100%;
|
||||
@ -196,19 +147,14 @@
|
||||
padding: 20px;
|
||||
|
||||
height: fit-content;
|
||||
width: 20vw;
|
||||
min-width: 400px;
|
||||
width: fit-content;
|
||||
//width: 20vw;
|
||||
// min-width: 400px;
|
||||
|
||||
justify-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
.details {
|
||||
background-color: var(--background-color-accent);
|
||||
padding: 20px;
|
||||
border-radius: @borderRadius;
|
||||
}
|
||||
|
||||
.followersList {
|
||||
background-color: var(--background-color-accent);
|
||||
padding: 20px;
|
||||
|
@ -4,11 +4,12 @@ import classnames from "classnames"
|
||||
|
||||
import { Translation } from "react-i18next"
|
||||
|
||||
import { createIconRender, Icons } from "components/Icons"
|
||||
import { Skeleton, FollowButton, UserCard } from "components"
|
||||
import { Skeleton } from "components"
|
||||
import { SessionModel, UserModel, FollowsModel } from "models"
|
||||
import { PagePanelWithNavMenu } from "components/PagePanels"
|
||||
|
||||
import { MobileUserCard } from "components/UserCard"
|
||||
|
||||
import DetailsTab from "./tabs/details"
|
||||
import PostsTab from "./tabs/posts"
|
||||
import FollowersTab from "./tabs/followers"
|
||||
@ -58,6 +59,59 @@ export default class Account extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount = async () => {
|
||||
app.layout.toggleCenteredContent(true)
|
||||
|
||||
this.loadUser()
|
||||
}
|
||||
|
||||
componentWillUnmount = () => {
|
||||
app.layout.toggleCenteredContent(false)
|
||||
}
|
||||
|
||||
toggleLike = async () => {
|
||||
const accept = await new Promise((resolve, reject) => {
|
||||
antd.Modal.confirm({
|
||||
title: <Translation>
|
||||
{t => t("Confirm")}
|
||||
</Translation>,
|
||||
content: <Translation>
|
||||
{t => t("Are you sure you want to unfollow this user?")}
|
||||
</Translation>,
|
||||
okText: <Translation>
|
||||
{t => t("Yes")}
|
||||
</Translation>,
|
||||
cancelText: <Translation>
|
||||
{t => t("No")}
|
||||
</Translation>,
|
||||
onOk: () => {
|
||||
resolve(true)
|
||||
},
|
||||
onCancel: () => {
|
||||
resolve(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
if (!accept) {
|
||||
return false
|
||||
}
|
||||
|
||||
const result = await FollowsModel.toggleFollow({
|
||||
username: this.state.requestedUser,
|
||||
}).catch((error) => {
|
||||
console.error(error)
|
||||
antd.message.error(error.message)
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
await this.setState({
|
||||
isFollowed: result.following,
|
||||
followers: result.followers,
|
||||
})
|
||||
}
|
||||
|
||||
loadUser = async () => {
|
||||
const token = await SessionModel.getDecodedToken()
|
||||
const location = window.app.history.location
|
||||
const query = new URLSearchParams(location.search)
|
||||
@ -137,18 +191,28 @@ export default class Account extends React.Component {
|
||||
"_mobile_account-profile",
|
||||
)}
|
||||
>
|
||||
<UserCard
|
||||
<MobileUserCard
|
||||
user={user}
|
||||
isSelf={this.state.isSelf}
|
||||
isFollowed={this.state.isFollowed}
|
||||
followers={this.state.followers}
|
||||
onClickFollow={this.toggleLike}
|
||||
/>
|
||||
|
||||
{/* <PagePanelWithNavMenu
|
||||
<PagePanelWithNavMenu
|
||||
tabs={Tabs}
|
||||
useSetQueryType
|
||||
transition
|
||||
tabProps={{
|
||||
state: this.state,
|
||||
}}
|
||||
/> */}
|
||||
onTabChange={() => {
|
||||
app.layout.scrollTo({
|
||||
top: 0,
|
||||
})
|
||||
}}
|
||||
no_top_padding
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
}
|
@ -1,10 +1,12 @@
|
||||
@import "theme/vars.less";
|
||||
|
||||
._mobile_account-profile {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
padding: 0 10px;
|
||||
|
||||
width: 100%;
|
||||
|
||||
padding-top: calc(@topBar_height + @top_bar_padding);
|
||||
|
||||
gap: 20px;
|
||||
}
|
@ -1,46 +1,113 @@
|
||||
import React from "react"
|
||||
import moment from "moment"
|
||||
import { DateTime } from "luxon"
|
||||
import { Skeleton } from "antd"
|
||||
import { UserBadges } from "components"
|
||||
|
||||
import "./details.less"
|
||||
|
||||
import { Icons } from "components/Icons"
|
||||
|
||||
export default React.memo((props) => {
|
||||
function getJoinLabel(jsDate) {
|
||||
const date = DateTime.fromJSDate(new Date(jsDate))
|
||||
|
||||
const month = String(date.toLocaleString({ month: "long" })).toTitleCase()
|
||||
const year = String(date.year)
|
||||
|
||||
return `${month} ${year}`
|
||||
}
|
||||
|
||||
export default (props) => {
|
||||
return <div id="details" className="details">
|
||||
{
|
||||
props.state.user.fullName &&
|
||||
<div>
|
||||
<h2>{props.state.user.fullName}</h2>
|
||||
props.state.user.roles.includes("admin") && <div className="inline_field">
|
||||
<div className="field_header">
|
||||
<div className="field_icon">
|
||||
<Icons.MdAdminPanelSettings />
|
||||
</div>
|
||||
|
||||
<span>
|
||||
Administrators Team
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div>
|
||||
<h3>
|
||||
@{props.state.user.username} #{props.state.user._id}
|
||||
</h3>
|
||||
|
||||
<div className="inline_field">
|
||||
<div className="field_header">
|
||||
<div className="field_icon">
|
||||
<Icons.MdTag />
|
||||
</div>
|
||||
|
||||
<span>
|
||||
ID
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="field_value">
|
||||
<p>
|
||||
{props.state.user._id}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
props.state.user.description &&
|
||||
<div>
|
||||
<h4>
|
||||
{props.state.user.description}
|
||||
</h4>
|
||||
|
||||
<div className="inline_field">
|
||||
<div className="field_header">
|
||||
<div className="field_icon">
|
||||
<Icons.Users />
|
||||
</div>
|
||||
|
||||
<span>
|
||||
Followers
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
props.state.user.roles.includes("admin") &&
|
||||
<div>
|
||||
<span><Icons.MdAdminPanelSettings /> Administrators Team</span>
|
||||
|
||||
<div className="field_value">
|
||||
<p>
|
||||
{props.state.followers.length}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
<div>
|
||||
<span><Icons.Users /> {props.state.followers.length} Followers</span>
|
||||
</div>
|
||||
{
|
||||
props.state.user?.badges.length > 0 &&
|
||||
<div>
|
||||
<span><Icons.Award /> {props.state.user?.badges.length} Badges collected</span>
|
||||
|
||||
<div className="inline_field">
|
||||
<div className="field_header">
|
||||
<div className="field_icon">
|
||||
<Icons.Calendar />
|
||||
</div>
|
||||
|
||||
<span>
|
||||
Joined at
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="field_value">
|
||||
<p>
|
||||
{
|
||||
getJoinLabel(Number(props.state.user.createdAt))
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
<div>
|
||||
<span><Icons.Calendar /> Joined at {moment(new Date(Number(props.state.user.createdAt))).format("YYYY")}</span>
|
||||
</div>
|
||||
|
||||
<div className="inline_field">
|
||||
<div className="field_header">
|
||||
<div className="field_icon">
|
||||
<Icons.Award />
|
||||
</div>
|
||||
|
||||
<span>
|
||||
Badges collected
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="field_value">
|
||||
<p>
|
||||
{props.state.user?.badges.length}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<React.Suspense fallback={<Skeleton />}>
|
||||
<UserBadges user_id={props.state.user?._id} />
|
||||
</React.Suspense>
|
||||
</div>
|
||||
})
|
||||
}
|
78
packages/app/src/pages/account/tabs/details.less
Normal file
78
packages/app/src/pages/account/tabs/details.less
Normal file
@ -0,0 +1,78 @@
|
||||
@border-radius: 12px;
|
||||
|
||||
.details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
justify-content: center;
|
||||
|
||||
width: 100%;
|
||||
|
||||
padding: 15px;
|
||||
|
||||
gap: 10px;
|
||||
|
||||
background-color: var(--background-color-accent);
|
||||
|
||||
border-radius: @border-radius;
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.inline_field {
|
||||
display: inline-flex;
|
||||
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
justify-content: space-between;
|
||||
|
||||
padding: 10px;
|
||||
|
||||
background-color: var(--background-color-primary);
|
||||
|
||||
border-radius: 12px;
|
||||
|
||||
.field_header {
|
||||
display: inline-flex;
|
||||
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
gap: 8px;
|
||||
|
||||
font-size: 0.8rem;
|
||||
|
||||
.field_icon {
|
||||
display: inline-flex;
|
||||
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
background-color: var(--background-color-primary);
|
||||
|
||||
border-radius: 100%;
|
||||
|
||||
padding: 5px;
|
||||
|
||||
font-size: 1rem;
|
||||
|
||||
svg {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.field_value {
|
||||
font-family: "DM Mono", monospace;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,8 @@ import React from "react"
|
||||
|
||||
import { FollowersList } from "components"
|
||||
|
||||
import "./followers.less"
|
||||
|
||||
export default React.memo((props) => {
|
||||
return <FollowersList
|
||||
user_id={props.state.user._id}
|
||||
|
3
packages/app/src/pages/account/tabs/followers.less
Normal file
3
packages/app/src/pages/account/tabs/followers.less
Normal file
@ -0,0 +1,3 @@
|
||||
.followersList {
|
||||
width: 100%;
|
||||
}
|
@ -28,8 +28,14 @@ export default class Home extends React.Component {
|
||||
tabs={Tabs}
|
||||
navMenuHeader={navMenuHeader}
|
||||
primaryPanelClassName="full"
|
||||
onTabChange={() => {
|
||||
app.layout.scrollTo({
|
||||
top: 0,
|
||||
})
|
||||
}}
|
||||
useSetQueryType
|
||||
transition
|
||||
masked
|
||||
/>
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user