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;
|
@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 {
|
.accountProfile {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
@ -123,15 +70,18 @@
|
|||||||
.panels {
|
.panels {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
// grid-template-columns: repeat(3, 1fr);
|
||||||
grid-template-rows: 1fr;
|
// grid-template-rows: 1fr;
|
||||||
grid-column-gap: 20px;
|
// grid-column-gap: 20px;
|
||||||
grid-row-gap: 0px;
|
// grid-row-gap: 0px;
|
||||||
|
|
||||||
|
gap: 20px;
|
||||||
|
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
.leftPanel {
|
.leftPanel {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
@ -178,6 +128,7 @@
|
|||||||
|
|
||||||
.content {
|
.content {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
width: 90%;
|
||||||
|
|
||||||
.fade-opacity-active {
|
.fade-opacity-active {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -196,19 +147,14 @@
|
|||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
width: 20vw;
|
width: fit-content;
|
||||||
min-width: 400px;
|
//width: 20vw;
|
||||||
|
// min-width: 400px;
|
||||||
|
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.details {
|
|
||||||
background-color: var(--background-color-accent);
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: @borderRadius;
|
|
||||||
}
|
|
||||||
|
|
||||||
.followersList {
|
.followersList {
|
||||||
background-color: var(--background-color-accent);
|
background-color: var(--background-color-accent);
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
@ -4,11 +4,12 @@ import classnames from "classnames"
|
|||||||
|
|
||||||
import { Translation } from "react-i18next"
|
import { Translation } from "react-i18next"
|
||||||
|
|
||||||
import { createIconRender, Icons } from "components/Icons"
|
import { Skeleton } from "components"
|
||||||
import { Skeleton, FollowButton, UserCard } from "components"
|
|
||||||
import { SessionModel, UserModel, FollowsModel } from "models"
|
import { SessionModel, UserModel, FollowsModel } from "models"
|
||||||
import { PagePanelWithNavMenu } from "components/PagePanels"
|
import { PagePanelWithNavMenu } from "components/PagePanels"
|
||||||
|
|
||||||
|
import { MobileUserCard } from "components/UserCard"
|
||||||
|
|
||||||
import DetailsTab from "./tabs/details"
|
import DetailsTab from "./tabs/details"
|
||||||
import PostsTab from "./tabs/posts"
|
import PostsTab from "./tabs/posts"
|
||||||
import FollowersTab from "./tabs/followers"
|
import FollowersTab from "./tabs/followers"
|
||||||
@ -58,6 +59,59 @@ export default class Account extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount = async () => {
|
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 token = await SessionModel.getDecodedToken()
|
||||||
const location = window.app.history.location
|
const location = window.app.history.location
|
||||||
const query = new URLSearchParams(location.search)
|
const query = new URLSearchParams(location.search)
|
||||||
@ -137,18 +191,28 @@ export default class Account extends React.Component {
|
|||||||
"_mobile_account-profile",
|
"_mobile_account-profile",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<UserCard
|
<MobileUserCard
|
||||||
user={user}
|
user={user}
|
||||||
|
isSelf={this.state.isSelf}
|
||||||
|
isFollowed={this.state.isFollowed}
|
||||||
|
followers={this.state.followers}
|
||||||
|
onClickFollow={this.toggleLike}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* <PagePanelWithNavMenu
|
<PagePanelWithNavMenu
|
||||||
tabs={Tabs}
|
tabs={Tabs}
|
||||||
useSetQueryType
|
useSetQueryType
|
||||||
transition
|
transition
|
||||||
tabProps={{
|
tabProps={{
|
||||||
state: this.state,
|
state: this.state,
|
||||||
}}
|
}}
|
||||||
/> */}
|
onTabChange={() => {
|
||||||
|
app.layout.scrollTo({
|
||||||
|
top: 0,
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
no_top_padding
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,12 @@
|
|||||||
|
@import "theme/vars.less";
|
||||||
|
|
||||||
._mobile_account-profile {
|
._mobile_account-profile {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
padding: 0 10px;
|
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
padding-top: calc(@topBar_height + @top_bar_padding);
|
||||||
|
|
||||||
|
gap: 20px;
|
||||||
}
|
}
|
@ -1,46 +1,113 @@
|
|||||||
import React from "react"
|
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"
|
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">
|
return <div id="details" className="details">
|
||||||
{
|
{
|
||||||
props.state.user.fullName &&
|
props.state.user.roles.includes("admin") && <div className="inline_field">
|
||||||
<div>
|
<div className="field_header">
|
||||||
<h2>{props.state.user.fullName}</h2>
|
<div className="field_icon">
|
||||||
|
<Icons.MdAdminPanelSettings />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
Administrators Team
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div>
|
|
||||||
<h3>
|
<div className="inline_field">
|
||||||
@{props.state.user.username} #{props.state.user._id}
|
<div className="field_header">
|
||||||
</h3>
|
<div className="field_icon">
|
||||||
|
<Icons.MdTag />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
ID
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="field_value">
|
||||||
|
<p>
|
||||||
|
{props.state.user._id}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{
|
|
||||||
props.state.user.description &&
|
<div className="inline_field">
|
||||||
<div>
|
<div className="field_header">
|
||||||
<h4>
|
<div className="field_icon">
|
||||||
{props.state.user.description}
|
<Icons.Users />
|
||||||
</h4>
|
</div>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
Followers
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
|
||||||
{
|
<div className="field_value">
|
||||||
props.state.user.roles.includes("admin") &&
|
<p>
|
||||||
<div>
|
{props.state.followers.length}
|
||||||
<span><Icons.MdAdminPanelSettings /> Administrators Team</span>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
|
||||||
<div>
|
|
||||||
<span><Icons.Users /> {props.state.followers.length} Followers</span>
|
|
||||||
</div>
|
</div>
|
||||||
{
|
|
||||||
props.state.user?.badges.length > 0 &&
|
<div className="inline_field">
|
||||||
<div>
|
<div className="field_header">
|
||||||
<span><Icons.Award /> {props.state.user?.badges.length} Badges collected</span>
|
<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>
|
||||||
}
|
|
||||||
<div>
|
|
||||||
<span><Icons.Calendar /> Joined at {moment(new Date(Number(props.state.user.createdAt))).format("YYYY")}</span>
|
|
||||||
</div>
|
</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>
|
</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 { FollowersList } from "components"
|
||||||
|
|
||||||
|
import "./followers.less"
|
||||||
|
|
||||||
export default React.memo((props) => {
|
export default React.memo((props) => {
|
||||||
return <FollowersList
|
return <FollowersList
|
||||||
user_id={props.state.user._id}
|
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}
|
tabs={Tabs}
|
||||||
navMenuHeader={navMenuHeader}
|
navMenuHeader={navMenuHeader}
|
||||||
primaryPanelClassName="full"
|
primaryPanelClassName="full"
|
||||||
|
onTabChange={() => {
|
||||||
|
app.layout.scrollTo({
|
||||||
|
top: 0,
|
||||||
|
})
|
||||||
|
}}
|
||||||
useSetQueryType
|
useSetQueryType
|
||||||
transition
|
transition
|
||||||
|
masked
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user