From fc7dc0406dc4c7514380bdb1e3ec4aaca7e23b53 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Wed, 3 Nov 2021 22:22:39 +0800 Subject: [PATCH 01/15] refactor(user-page): basic setup --- server/routes.js | 11 +- .../content/UserContent/styles/index.ts | 2 +- .../user/UserProfile/ContributeMap.js | 4 +- src/containers/user/UserProfile/NumbersPad.js | 77 +++++++---- .../user/UserProfile/SubscribedCommunities.js | 2 +- .../user/UserProfile/styles/numbers_pad.ts | 60 ++++++--- src/pages/user.js | 121 ------------------ src/pages/user/[login].tsx | 87 +++++++++++++ src/schemas/pages/user.ts | 18 --- src/spec/index.ts | 1 + src/spec/utils.ts | 2 + src/widgets/UserBrief/ExtraInfo.js | 13 +- src/widgets/UserBrief/NumbersPad.js | 23 ---- src/widgets/UserBrief/Operators.js | 27 ---- src/widgets/UserBrief/Operators.tsx | 34 +++++ src/widgets/UserBrief/SocialIcons.js | 52 ++++---- src/widgets/UserBrief/index.js | 86 ------------- src/widgets/UserBrief/index.tsx | 82 ++++++++++++ src/widgets/UserBrief/styles/index.ts | 11 +- src/widgets/UserBrief/styles/numbers_pad.ts | 20 --- utils/constant/user_thread.ts | 2 +- utils/constant/view.ts | 10 +- utils/index.ts | 1 + utils/seo.ts | 11 +- 24 files changed, 372 insertions(+), 385 deletions(-) delete mode 100755 src/pages/user.js create mode 100755 src/pages/user/[login].tsx delete mode 100644 src/widgets/UserBrief/NumbersPad.js delete mode 100755 src/widgets/UserBrief/Operators.js create mode 100755 src/widgets/UserBrief/Operators.tsx delete mode 100755 src/widgets/UserBrief/index.js create mode 100755 src/widgets/UserBrief/index.tsx delete mode 100644 src/widgets/UserBrief/styles/numbers_pad.ts diff --git a/server/routes.js b/server/routes.js index d4444b68d..f4637363d 100644 --- a/server/routes.js +++ b/server/routes.js @@ -79,8 +79,15 @@ router.route('/works/:id').get((req, res) => { }) // 用户页 -router.route('/user/:userId').get((req, res) => { - return renderAndCache({ req, res, path: '/user' }) +router.route('/u/:login').get((req, res) => { + const { login } = req.params + return renderAndCache({ req, res, path: `/user/${login}` }) +}) + +router.route('/user/:login').get((req, res) => { + const { login } = req.params + console.log('hello user ?: ', login) + return renderAndCache({ req, res, path: `/user/${login}` }) }) // 帖子页 diff --git a/src/containers/content/UserContent/styles/index.ts b/src/containers/content/UserContent/styles/index.ts index 0908d7697..c4275d110 100755 --- a/src/containers/content/UserContent/styles/index.ts +++ b/src/containers/content/UserContent/styles/index.ts @@ -32,7 +32,7 @@ export const ContentWrapper = styled.div` export const TabBarWrapper = styled.div` position: absolute; bottom: 0; - left: 380px; + left: 403px; width: 100%; ` export const MobileBottom = styled.div` diff --git a/src/containers/user/UserProfile/ContributeMap.js b/src/containers/user/UserProfile/ContributeMap.js index cc0f16c4d..3f0fbab17 100644 --- a/src/containers/user/UserProfile/ContributeMap.js +++ b/src/containers/user/UserProfile/ContributeMap.js @@ -64,7 +64,7 @@ const UserContributeMap = ({ data }) => { return (
- 过去1年共创作 {data.totalCount} 次内容 + 过去 1 年共创作 {data.totalCount} 次内容 潜水   @@ -73,7 +73,7 @@ const UserContributeMap = ({ data }) => { -  高产 +  活跃
diff --git a/src/containers/user/UserProfile/NumbersPad.js b/src/containers/user/UserProfile/NumbersPad.js index 6efb56fd2..fd87c99cb 100644 --- a/src/containers/user/UserProfile/NumbersPad.js +++ b/src/containers/user/UserProfile/NumbersPad.js @@ -1,28 +1,51 @@ import React from 'react' +import FollowButton from '@/widgets/Buttons/FollowButton' +import Button from '@/widgets/Buttons/Button' +import { Br } from '@/widgets/Common' +import Tooltip from '@/widgets/Tooltip' + import { Wrapper, Divider, Section, + GravitySection, + NormalSection, + FollowSection, Num, + Gravity, + InfoIcon, Title, - IDTitle, - IDNum, - GradeTitle, - GradeDesc, - GradeLetter, - GradeText, + JoinAt, + JoinSlash, } from './styles/numbers_pad' const Numberspad = ({ user }) => { return ( -
- TODO - 阅读总数 -
+ + 100 + + Gravity + + + + + -
+ + 37 + 关注者 + + + + 8 + 关注了 + + {/*
{user.achievement.articlesUpvotesCount} 收获点赞
@@ -30,26 +53,32 @@ const Numberspad = ({ user }) => {
{user.achievement.articlesCollectsCount} 被收藏 -
+
*/} -
+ {user.views} 主页被浏览 -
+
- - R - ocket - - 账户等级 + + 20 + / + 13 + / + 02 + + 注册于
-
- 账户 ID - {user.id} - 2020/02/13 -
+ +
+ +
+ +
) } diff --git a/src/containers/user/UserProfile/SubscribedCommunities.js b/src/containers/user/UserProfile/SubscribedCommunities.js index ce28de0d8..ce3c68d6e 100644 --- a/src/containers/user/UserProfile/SubscribedCommunities.js +++ b/src/containers/user/UserProfile/SubscribedCommunities.js @@ -5,7 +5,7 @@ import CommunityList from '@/widgets/CommunityList' import { Wrapper, Title, Divider } from './styles/subscribed_communities' const SubscribedCommunities = ({ items }) => { - if (!items.entries) return null + if (!items?.entries) return null return ( diff --git a/src/containers/user/UserProfile/styles/numbers_pad.ts b/src/containers/user/UserProfile/styles/numbers_pad.ts index b123e2ee5..ddf28c5a7 100644 --- a/src/containers/user/UserProfile/styles/numbers_pad.ts +++ b/src/containers/user/UserProfile/styles/numbers_pad.ts @@ -3,6 +3,7 @@ import styled from 'styled-components' // import Img from '@/Img' import { theme } from '@/utils/themes' import css from '@/utils/css' +import InfoSVG from '@/icons/Info' export const Wrapper = styled.div` ${css.flex('align-center', 'justify-between')}; @@ -18,38 +19,59 @@ export const Section = styled.div` width: 100px; height: 82px; ` +export const NormalSection = styled(Section)` + width: 70px; +` +export const FollowSection = styled(Section)` + width: 130px; + padding-right: 10px; +` +export const GravitySection = styled(Section)` + width: 130px; + padding-left: 10px; +` export const Num = styled.div` font-size: 18px; color: ${theme('thread.articleTitle')}; ` -export const Title = styled.div` +export const Gravity = styled.div` + ${css.flex('align-center')}; + color: ${theme('thread.articleDigest')}; margin-top: 4px; font-size: 12px; - color: ${theme('thread.articleDigest')}; - opacity: 0.8; + margin-left: 12px; ` -export const IDTitle = styled(Title)` - margin-top: 0; - font-size: 10px; -` -export const IDNum = styled(Num)` - font-size: 16px; +export const InfoIcon = styled(InfoSVG)` + ${css.size(10)}; + fill: ${theme('thread.articleDigest')}; + margin-left: 5px; + + opacity: 0.8; + cursor: pointer; ` -export const GradeTitle = styled(Title)` +export const Title = styled.div` margin-top: 4px; font-size: 12px; + color: ${theme('thread.articleDigest')}; + opacity: 0.8; ` -export const GradeDesc = styled.div` - ${css.flex('align-baseline')}; +export const JoinAt = styled(Num)` + ${css.flex('align-both')}; + position: relative; + font-size: 14px; + margin-top: 1px; + margin-bottom: 2px; ` -export const GradeLetter = styled.div` - color: ${theme('thread.articleTitle')}; - font-size: 18px; -` -export const GradeText = styled.div` +export const JoinSlash = styled.div` + font-size: 10px; color: ${theme('thread.articleDigest')}; - font-size: 13px; - margin-left: 1px; + font-weight: bolder; + font-family: monospace; + margin-right: 3px; + margin-left: 3px; + opacity: 0.8; + transform: rotate(-5deg); + margin-top: 2px; ` export const Divider = styled.div` height: 40px; diff --git a/src/pages/user.js b/src/pages/user.js deleted file mode 100755 index 83f8d5e2f..000000000 --- a/src/pages/user.js +++ /dev/null @@ -1,121 +0,0 @@ -/* - this page is for /user/xxx - */ -import React from 'react' -import { Provider } from 'mobx-react' -import { merge, toLower } from 'ramda' - -import { SITE_URL } from '@/config' -import { ROUTE, METRIC, USER_THREAD } from '@/constant' -import { - getJwtToken, - makeGQClient, - queryStringToJSON, - ssrParseURL, - nilOrEmpty, - pagedFilter, - ssrRescue, - parseTheme, -} from '@/utils' - -import { useStore } from '@/stores/init' - -import GlobalLayout from '@/containers/layout/GlobalLayout' -import UserContent from '@/containers/content/UserContent' - -import { P } from '@/schemas' - -const fetchData = async (props, opt) => { - const { realname } = merge({ realname: true }, opt) - - const token = realname ? getJwtToken(props) : null - const gqClient = makeGQClient(token) - const userHasLogin = nilOrEmpty(token) === false - const { subPath } = ssrParseURL(props.req) - const login = toLower(subPath) - - const sessionState = gqClient.request(P.sessionState) - const user = gqClient.request(P.user, { login, userHasLogin }) - - const filter = pagedFilter(1) - const subscribedCommunities = gqClient.request(P.subscribedCommunities, { - filter, - }) - - return { - ...(await sessionState), - ...(await user), - ...(await subscribedCommunities), - } -} - -export const getServerSideProps = async (props) => { - const query = queryStringToJSON(props.req.url) - - let resp - try { - resp = await fetchData(props) - } catch ({ response: { errors } }) { - if (ssrRescue.hasLoginError(errors)) { - resp = await fetchData(props, { tokenExpired: true }) - } else { - return { - props: { - errorCode: 404, - viewing: { - user: {}, - }, - }, - } - } - } - - const { sessionState, user, subscribedCommunities } = resp - - const initProps = { - theme: { - curTheme: parseTheme(sessionState), - }, - account: { - user: sessionState.user || {}, - isValidSession: sessionState.isValid, - userSubscribedCommunities: subscribedCommunities, - }, - route: { mainPath: ROUTE.USER, subPath: user.id, query }, - userContent: { activeThread: query.tab || USER_THREAD.PROFILE }, - viewing: { user }, - } - - return { - props: { errorCode: null, namespacesRequired: ['general'], ...initProps }, - } -} - -const UserPage = (props) => { - const store = useStore(props) - - const { viewing, errorCode } = props - - const { user } = viewing - - const seoConfig = { - name: `${user.nickname}`, - url: `${SITE_URL}/${ROUTE.USER}/${user.login}`, - sameAs: [], - } - - return ( - - - - - - ) -} - -export default UserPage diff --git a/src/pages/user/[login].tsx b/src/pages/user/[login].tsx new file mode 100755 index 000000000..460dd9930 --- /dev/null +++ b/src/pages/user/[login].tsx @@ -0,0 +1,87 @@ +/* + this page is for /user/xxx + */ +import { Provider } from 'mobx-react' + +import { SITE_URL } from '@/config' +import { ROUTE, METRIC, USER_THREAD } from '@/constant' +import { + queryStringToJSON, + ssrGetParam, + ssrFetchPrepare, + ssrBaseStates, + ssrError, + refreshIfneed, + userSEO, +} from '@/utils' + +import { useStore } from '@/stores/init' + +import GlobalLayout from '@/containers/layout/GlobalLayout' +import UserContent from '@/containers/content/UserContent' + +import { P } from '@/schemas' + +const fetchData = async (context, opt = {}) => { + const login = ssrGetParam(context, 'login') + + const { gqClient, userHasLogin } = ssrFetchPrepare(context, opt) + + const sessionState = gqClient.request(P.sessionState) + const user = gqClient.request(P.user, { login, userHasLogin }) + + return { + ...(await sessionState), + ...(await user), + } +} + +export const getServerSideProps = async (context) => { + // const query = queryStringToJSON(context.req.url) + + let resp + try { + resp = await fetchData(context) + const { user, sessionState } = resp + refreshIfneed(sessionState, `/user/${user.login}`, context) + } catch (e) { + console.log('#### error from server: ', e) + return ssrError(context, 'fetch', 500) + } + + const { user } = resp + + const initProps = { + ...ssrBaseStates(resp), + // route: { mainPath: ROUTE.USER, subPath: user.id, query }, + // userContent: { activeThread: query.tab || USER_THREAD.PROFILE }, + viewing: { user }, + } + + return { + props: { errorCode: null, namespacesRequired: ['general'], ...initProps }, + } +} + +const UserPage = (props) => { + const store = useStore(props) + + const { viewing } = props + const { user } = viewing + + const seoConfig = userSEO(user) + + return ( + + + + + + ) +} + +export default UserPage diff --git a/src/schemas/pages/user.ts b/src/schemas/pages/user.ts index c3b7d8a61..f49139910 100755 --- a/src/schemas/pages/user.ts +++ b/src/schemas/pages/user.ts @@ -45,25 +45,7 @@ export const user = ` } subscribedCommunitiesCount - subscribedCommunities { - entries { - ${F.community} - } - ${F.pagedCounts} - } - - editableCommunities { - entries { - ${F.community} - } - } - editableCommunities { - entries { - ${F.community} - } - totalCount - } insertedAt } } diff --git a/src/spec/index.ts b/src/spec/index.ts index 11c87c2bd..db0add680 100644 --- a/src/spec/index.ts +++ b/src/spec/index.ts @@ -66,6 +66,7 @@ export type { TCommunitySetterStyle, TToastType, TToastPos, + TView, } from './utils' export type { TGQLError } from './graphql' diff --git a/src/spec/utils.ts b/src/spec/utils.ts index 8667817ac..18069bdc7 100644 --- a/src/spec/utils.ts +++ b/src/spec/utils.ts @@ -4,6 +4,8 @@ export type Nullable = T | null export type TID = string +export type TView = 'desktop' | 'mobile' | 'MODELINE' | 'DRAWER' + export type TTestable = { testid?: string } diff --git a/src/widgets/UserBrief/ExtraInfo.js b/src/widgets/UserBrief/ExtraInfo.js index f200049f8..23f126da3 100755 --- a/src/widgets/UserBrief/ExtraInfo.js +++ b/src/widgets/UserBrief/ExtraInfo.js @@ -1,21 +1,22 @@ import React from 'react' -import { either, isNil, isEmpty } from 'ramda' +// import { either, isNil, isEmpty } from 'ramda' import { ICON_CMD } from '@/config' -import BackgroundList from './BackgroundList' +// import BackgroundList from './BackgroundList' import { Section, Icon, Desc } from './styles/extra_info' -const emptyBacgrounds = either(isNil, isEmpty) +// const emptyBacgrounds = either(isNil, isEmpty) const ExtraInfo = ({ user }) => { return (
{' '} - {user.location} + {/* {user.location} */} + 成都
- {!emptyBacgrounds(user.workBackgrounds) && ( + {/* {!emptyBacgrounds(user.workBackgrounds) && (
{' '} @@ -27,7 +28,7 @@ const ExtraInfo = ({ user }) => { {' '}
- )} + )} */}
) } diff --git a/src/widgets/UserBrief/NumbersPad.js b/src/widgets/UserBrief/NumbersPad.js deleted file mode 100644 index d3498330a..000000000 --- a/src/widgets/UserBrief/NumbersPad.js +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react' - -import { prettyNum } from '@/utils/helper' -import { Wrapper, Section, Title, Number } from './styles/numbers_pad' - -const NumbersPad = ({ user, listFollowers, listFollowings }) => ( - -
- {prettyNum(user.achievement.reputation)} - 声望 -
-
listFollowers(user)}> - {prettyNum(user.followersCount)} - 关注者 -
-
listFollowings(user)}> - {prettyNum(user.followingsCount)} - 关注中 -
-
-) - -export default React.memo(NumbersPad) diff --git a/src/widgets/UserBrief/Operators.js b/src/widgets/UserBrief/Operators.js deleted file mode 100755 index 6b5630255..000000000 --- a/src/widgets/UserBrief/Operators.js +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react' - -import { ICON_CMD } from '@/config' -import { withGuardian } from '@/hoc' - -import { - Wrapper, - EditIcon, - EditWrapper, - LogoutBtn, - LogoutIcon, - LogoutText, -} from './styles/operators' - -const Operators = ({ onEdit, onLogout }) => ( - - - - - - - 退出登陆? - - -) - -export default withGuardian(Operators) diff --git a/src/widgets/UserBrief/Operators.tsx b/src/widgets/UserBrief/Operators.tsx new file mode 100755 index 000000000..cdcacb928 --- /dev/null +++ b/src/widgets/UserBrief/Operators.tsx @@ -0,0 +1,34 @@ +import { FC } from 'react' + +import { ICON_CMD } from '@/config' +import { withGuardian } from '@/hoc' + +import { + Wrapper, + EditIcon, + EditWrapper, + LogoutBtn, + LogoutIcon, + LogoutText, +} from './styles/operators' + +type TProps = { + onEdit: () => void + onLogout: () => void +} + +const Operators: FC = ({ onEdit, onLogout }) => { + return ( + + + + + + + 退出登陆? + + + ) +} + +export default withGuardian(Operators) diff --git a/src/widgets/UserBrief/SocialIcons.js b/src/widgets/UserBrief/SocialIcons.js index 96e336076..0553cb89d 100755 --- a/src/widgets/UserBrief/SocialIcons.js +++ b/src/widgets/UserBrief/SocialIcons.js @@ -9,31 +9,33 @@ import Tooltip from '@/widgets/Tooltip' import { Wrapper, Linker, SocialIcon } from './styles/social_icons' const DisplayIcon = ({ user, social }) => { - if (nilOrEmpty(user.social[social.key])) return null - - if (!contains(social.key, ['qq', 'weichat'])) { - return ( - - - - ) - } - - return ( - -
- -
-
- ) + return null + + // if (nilOrEmpty(user.social[social.key])) return null + + // if (!contains(social.key, ['qq', 'weichat'])) { + // return ( + // + // + // + // ) + // } + + // return ( + // + //
+ // + //
+ //
+ // ) } const SocialIcons = ({ user }) => ( diff --git a/src/widgets/UserBrief/index.js b/src/widgets/UserBrief/index.js deleted file mode 100755 index f3b09e882..000000000 --- a/src/widgets/UserBrief/index.js +++ /dev/null @@ -1,86 +0,0 @@ -/* - * - * UserBrief - * - */ -import React from 'react' -import T from 'prop-types' - -import { VIEW } from '@/constant' - -import { buildLog } from '@/utils/logger' -import { Br } from '@/widgets/Common' - -import SocialIcons from './SocialIcons' -import ExtraInfo from './ExtraInfo' -import Operators from './Operators' -import NumbersPad from './NumbersPad' -import CommunityEditorInfo from './CommunityEditorInfo' - -import Avatar from './Avatar' - -import { - Wrapper, - BriefTextWrapper, - UserTitle, - Bio, - UserDesc, - Divider, -} from './styles' - -/* eslint-disable-next-line */ -const log = buildLog('c:UserBrief') - -const UserBrief = ({ user, view, onEdit, onLogout, viewingType }) => { - return ( - - - - - {user.nickname} - {viewingType === 'account' && ( - - )} - - {user.bio} -
- console.log('TODO: listFollowers')} - listFollowings={() => console.log('TODO: listFollowings')} - /> -
- - - {user.editableCommunities.length > 0 && } - - - - - -
-
- ) -} - -UserBrief.propTypes = { - user: T.object.isRequired, - view: T.oneOf([VIEW.DESKTOP, VIEW.DRAWER]), - viewingType: T.oneOf(['account', 'user']), - onEdit: T.func, - onLogout: T.func, -} - -UserBrief.defaultProps = { - view: VIEW.DESKTOP, - viewingType: 'user', - onEdit: log, - onLogout: log, -} - -export default React.memo(UserBrief) diff --git a/src/widgets/UserBrief/index.tsx b/src/widgets/UserBrief/index.tsx new file mode 100755 index 000000000..faa7d2c72 --- /dev/null +++ b/src/widgets/UserBrief/index.tsx @@ -0,0 +1,82 @@ +/* + * + * UserBrief + * + */ +import { FC, memo } from 'react' + +import type { TUser, TView } from '@/spec' +import { VIEW } from '@/constant' + +import { buildLog } from '@/utils/logger' +import { Br } from '@/widgets/Common' + +// import SocialIcons from './SocialIcons' +import ExtraInfo from './ExtraInfo' +import Operators from './Operators' +// import CommunityEditorInfo from './CommunityEditorInfo' + +import Avatar from './Avatar' + +import { + Wrapper, + BriefTextWrapper, + UserTitle, + ShortBio, + Bio, + // UserDesc, + Divider, +} from './styles' + +/* eslint-disable-next-line */ +const log = buildLog('c:UserBrief') + +type TProps = { + user: TUser + view?: TView + viewingType?: 'account' | 'user' + onEdit?: () => void + onLogout?: () => void +} + +const UserBrief: FC = ({ + user, + view = VIEW.DESKTOP, + onEdit = log, + onLogout = log, + viewingType = 'user', +}) => { + return ( + + + + + {user.nickname} + {viewingType === 'account' && ( + + )} + + 开发者@coderplanets +
+ {user.bio} +
+ + + + {/* {user.editableCommunities.length > 0 && } */} + {/* */} + + {/* + + */} +
+
+ ) +} + +export default memo(UserBrief) diff --git a/src/widgets/UserBrief/styles/index.ts b/src/widgets/UserBrief/styles/index.ts index bcd2e3923..a9a1aa0ad 100755 --- a/src/widgets/UserBrief/styles/index.ts +++ b/src/widgets/UserBrief/styles/index.ts @@ -15,14 +15,17 @@ export const BriefTextWrapper = styled.div` export const UserTitle = styled.div` ${css.flex()}; color: ${theme('thread.articleTitle')}; - font-size: 22px; - margin-bottom: 12px; + font-size: 25px; + margin-bottom: 2px; +` +export const ShortBio = styled.div` + color: ${theme('thread.articleDigest')}; + opacity: 0.8; ` export const Bio = styled.div` color: ${theme('thread.articleDigest')}; - font-size: 13px; + font-size: 14px; ` - type TUserDesc = { clickable: boolean; hide: boolean } export const UserDesc = styled.div` color: ${theme('banner.desc')}; diff --git a/src/widgets/UserBrief/styles/numbers_pad.ts b/src/widgets/UserBrief/styles/numbers_pad.ts deleted file mode 100644 index eb89d065c..000000000 --- a/src/widgets/UserBrief/styles/numbers_pad.ts +++ /dev/null @@ -1,20 +0,0 @@ -import styled from 'styled-components' -import { theme } from '@/utils/themes' -import css from '@/utils/css' - -export const Wrapper = styled.div` - ${css.flex('align-center')}; -` -export const Section = styled.div` - ${css.flexColumn('align-start')}; - width: 65px; -` -export const Title = styled.div` - font-size: 12px; - color: ${theme('thread.articleDigest')}; - opacity: 0.8; -` -export const Number = styled.div` - color: ${theme('thread.articleTitle')}; - font-size: 16px; -` diff --git a/utils/constant/user_thread.ts b/utils/constant/user_thread.ts index 638dea650..edf095986 100755 --- a/utils/constant/user_thread.ts +++ b/utils/constant/user_thread.ts @@ -1,5 +1,5 @@ const USER_THREAD = { - PROFILE: 'PROFILE', + PROFILE: 'profile', PUBLISH: 'publish', COMMENTS: 'comments', FAVORITES: 'favorites', diff --git a/utils/constant/view.ts b/utils/constant/view.ts index 57b486b99..b7d8acc48 100644 --- a/utils/constant/view.ts +++ b/utils/constant/view.ts @@ -1,8 +1,10 @@ +import type { TView } from '@/spec' + const VIEW = { - DESKTOP: 'desktop', - MOBILE: 'mobile', - MODELINE: 'MODELINE', - DRAWER: 'DRAWER', + DESKTOP: 'desktop' as TView, + MOBILE: 'mobile' as TView, + MODELINE: 'MODELINE' as TView, + DRAWER: 'DRAWER' as TView, } export default VIEW diff --git a/utils/index.ts b/utils/index.ts index 6593ec5ee..2b5a4917d 100755 --- a/utils/index.ts +++ b/utils/index.ts @@ -159,4 +159,5 @@ export { articleSEO, articlePublishSEO, articleUpdateSEO, + userSEO, } from './seo' diff --git a/utils/seo.ts b/utils/seo.ts index 5b0b6fd3f..310335f02 100644 --- a/utils/seo.ts +++ b/utils/seo.ts @@ -1,6 +1,6 @@ import { SITE_URL } from '@/config' -import type { TCommunity, TThread, TArticle } from '@/spec' +import type { TCommunity, TThread, TArticle, TUser } from '@/spec' import { ROUTE, THREAD } from '@/constant' import { plural } from './helper' @@ -14,6 +14,7 @@ type TSEO = { dateModified?: string authorName?: string images?: string[] + // user } export const communitySEO = (community: TCommunity, thread: TThread): TSEO => { @@ -142,3 +143,11 @@ export const articleUpdateSEO = (): TSEO => { description: '编辑帖子', } } + +export const userSEO = (user: TUser): TSEO => { + return { + title: `${user.nickname}`, + url: `${SITE_URL}/${ROUTE.USER}/${user.login}`, + description: user.bio, + } +} From a322f4081bf88cf225aac55586fe8704b3a2357f Mon Sep 17 00:00:00 2001 From: mydearxym Date: Thu, 4 Nov 2021 14:28:14 +0800 Subject: [PATCH 02/15] refactor(user-page): UserProfile Tab UI/UX improve --- .../{ContributeMap.js => ContributeMap.tsx} | 22 ++-- .../{NumbersPad.js => NumbersPad.tsx} | 59 +++++----- .../user/UserProfile/SubscribedCommunities.js | 25 ---- .../user/UserProfile/{index.js => index.tsx} | 30 +++-- .../user/UserProfile/{logic.js => logic.ts} | 7 +- src/containers/user/UserProfile/store.js | 32 ------ src/containers/user/UserProfile/store.tsx | 33 ++++++ .../user/UserProfile/styles/numbers_pad.ts | 28 ++--- .../styles/subscribed_communities.ts | 26 ----- src/spec/account.ts | 13 +++ src/widgets/Cards/UserCard.tsx | 4 +- src/widgets/CommunityList/index.js | 107 ------------------ src/widgets/CommunityList/index.tsx | 68 +++++++++++ src/widgets/CommunityList/styles/index.ts | 54 ++------- .../Header/DesktopView/ArticleLayout.tsx | 3 +- src/widgets/Icons/Blog.tsx | 14 ++- src/widgets/Icons/City.tsx | 18 +++ src/widgets/Icons/Company.tsx | 18 +++ src/widgets/Icons/Mail.tsx | 19 ++++ src/widgets/UserBrief/ExtraInfo.js | 36 ------ src/widgets/UserBrief/ExtraInfo.tsx | 41 +++++++ src/widgets/UserBrief/Footer.tsx | 30 +++++ src/widgets/UserBrief/index.tsx | 5 +- src/widgets/UserBrief/styles/extra_info.ts | 67 ++++++++++- src/widgets/UserBrief/styles/footer.ts | 42 +++++++ utils/mock.ts | 21 ++++ 26 files changed, 460 insertions(+), 362 deletions(-) rename src/containers/user/UserProfile/{ContributeMap.js => ContributeMap.tsx} (83%) rename src/containers/user/UserProfile/{NumbersPad.js => NumbersPad.tsx} (61%) delete mode 100644 src/containers/user/UserProfile/SubscribedCommunities.js rename src/containers/user/UserProfile/{index.js => index.tsx} (52%) rename src/containers/user/UserProfile/{logic.js => logic.ts} (73%) delete mode 100755 src/containers/user/UserProfile/store.js create mode 100755 src/containers/user/UserProfile/store.tsx delete mode 100644 src/containers/user/UserProfile/styles/subscribed_communities.ts delete mode 100755 src/widgets/CommunityList/index.js create mode 100755 src/widgets/CommunityList/index.tsx create mode 100644 src/widgets/Icons/City.tsx create mode 100644 src/widgets/Icons/Company.tsx create mode 100644 src/widgets/Icons/Mail.tsx delete mode 100755 src/widgets/UserBrief/ExtraInfo.js create mode 100755 src/widgets/UserBrief/ExtraInfo.tsx create mode 100755 src/widgets/UserBrief/Footer.tsx create mode 100644 src/widgets/UserBrief/styles/footer.ts diff --git a/src/containers/user/UserProfile/ContributeMap.js b/src/containers/user/UserProfile/ContributeMap.tsx similarity index 83% rename from src/containers/user/UserProfile/ContributeMap.js rename to src/containers/user/UserProfile/ContributeMap.tsx index 3f0fbab17..5f5ae11bf 100644 --- a/src/containers/user/UserProfile/ContributeMap.js +++ b/src/containers/user/UserProfile/ContributeMap.tsx @@ -4,10 +4,11 @@ * TODO: this component use global class as style * */ -import React from 'react' +import { FC, memo } from 'react' import CalendarHeatmap from 'react-calendar-heatmap' import ReactTooltip from 'react-tooltip' +import type { TUser } from '@/spec' import { buildLog } from '@/utils/logger' import { Wrapper, @@ -60,11 +61,16 @@ const getClass = (value) => { } } -const UserContributeMap = ({ data }) => { +type TProps = { + user: TUser +} + +const UserContributeMap: FC = ({ user }) => { + const { contributes } = user return (
- 过去 1 年共创作 {data.totalCount} 次内容 + 过去 1 年共创作 {contributes.totalCount} 次内容 潜水   @@ -78,16 +84,14 @@ const UserContributeMap = ({ data }) => {
log(value)} gutterSize={4} tooltipDataAttrs={customTooltipDataAttrs} monthLabels={monthLabels} - values={data.records} + values={contributes.records} classForValue={getClass} /> { ) } -export default React.memo(UserContributeMap) +export default memo(UserContributeMap) diff --git a/src/containers/user/UserProfile/NumbersPad.js b/src/containers/user/UserProfile/NumbersPad.tsx similarity index 61% rename from src/containers/user/UserProfile/NumbersPad.js rename to src/containers/user/UserProfile/NumbersPad.tsx index fd87c99cb..0a30b253d 100644 --- a/src/containers/user/UserProfile/NumbersPad.js +++ b/src/containers/user/UserProfile/NumbersPad.tsx @@ -1,26 +1,33 @@ -import React from 'react' +import { FC, memo } from 'react' +import type { TUser } from '@/spec' import FollowButton from '@/widgets/Buttons/FollowButton' import Button from '@/widgets/Buttons/Button' import { Br } from '@/widgets/Common' import Tooltip from '@/widgets/Tooltip' +import { mockCommunities } from '@/utils/mock' + +import CommunityList from '@/widgets/CommunityList' import { Wrapper, Divider, - Section, GravitySection, NormalSection, FollowSection, + JoinSection, + CommunitiesWrapper, Num, Gravity, InfoIcon, Title, - JoinAt, - JoinSlash, } from './styles/numbers_pad' -const Numberspad = ({ user }) => { +type TProps = { + user: TUser +} + +const Numberspad: FC = ({ user }) => { return ( @@ -37,39 +44,27 @@ const Numberspad = ({ user }) => { - 37 + {user.followersCount} 关注者 - 8 + {user.followingsCount} 关注了 - {/*
- {user.achievement.articlesUpvotesCount} - 收获点赞 -
- -
- {user.achievement.articlesCollectsCount} - 被收藏 -
*/} - - - {user.views} - 主页被浏览 - -
- - 20 - / - 13 - / - 02 - - 注册于 -
+ + + + + 加入的子社区 +
@@ -83,4 +78,4 @@ const Numberspad = ({ user }) => { ) } -export default React.memo(Numberspad) +export default memo(Numberspad) diff --git a/src/containers/user/UserProfile/SubscribedCommunities.js b/src/containers/user/UserProfile/SubscribedCommunities.js deleted file mode 100644 index ce3c68d6e..000000000 --- a/src/containers/user/UserProfile/SubscribedCommunities.js +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react' - -import CommunityList from '@/widgets/CommunityList' - -import { Wrapper, Title, Divider } from './styles/subscribed_communities' - -const SubscribedCommunities = ({ items }) => { - if (!items?.entries) return null - - return ( - - 关注的社区 - - - - ) -} - -export default React.memo(SubscribedCommunities) diff --git a/src/containers/user/UserProfile/index.js b/src/containers/user/UserProfile/index.tsx similarity index 52% rename from src/containers/user/UserProfile/index.js rename to src/containers/user/UserProfile/index.tsx index 8aca16331..56f776b8b 100755 --- a/src/containers/user/UserProfile/index.js +++ b/src/containers/user/UserProfile/index.tsx @@ -6,49 +6,45 @@ * */ -import React from 'react' -import T from 'prop-types' +import { FC } from 'react' import { buildLog } from '@/utils/logger' import { pluggedIn } from '@/utils/mobx' import NumbersPad from './NumbersPad' import ContributeMap from './ContributeMap' -import SubscribedCommunities from './SubscribedCommunities' import Activities from './Activities' +import type { TStore } from './store' import { Wrapper, ContributesWrapper } from './styles' import { useInit } from './logic' /* eslint-disable-next-line */ const log = buildLog('C:UserProfile') -const UserProfileContainer = ({ userProfile: store, testid }) => { +type TProps = { + userProfile?: TStore + testid?: string +} + +const UserProfileContainer: FC = ({ + userProfile: store, + testid = 'user-profile', +}) => { useInit(store) const { viewingUser } = store - // console.log('# viewingUser: ', viewingUser) return ( - + - ) } -UserProfileContainer.propTypes = { - userProfile: T.any.isRequired, - testid: T.string, -} - -UserProfileContainer.defaultProps = { - testid: 'user-profile', -} - -export default pluggedIn(UserProfileContainer) +export default pluggedIn(UserProfileContainer) as FC diff --git a/src/containers/user/UserProfile/logic.js b/src/containers/user/UserProfile/logic.ts similarity index 73% rename from src/containers/user/UserProfile/logic.js rename to src/containers/user/UserProfile/logic.ts index 694c1a49e..77902594b 100755 --- a/src/containers/user/UserProfile/logic.js +++ b/src/containers/user/UserProfile/logic.ts @@ -3,13 +3,14 @@ import { useEffect } from 'react' import { buildLog } from '@/utils/logger' // import S from './service' +import type { TStore } from './store' -let store = null +let store: TStore | undefined /* eslint-disable-next-line */ const log = buildLog('L:UserProfile') -export const someMethod = () => { +export const someMethod = (): void => { /* todo */ } @@ -17,7 +18,7 @@ export const someMethod = () => { // init & uninit handlers // ############################### -export const useInit = (_store) => { +export const useInit = (_store: TStore): void => { useEffect(() => { store = _store log('useInit: ', store) diff --git a/src/containers/user/UserProfile/store.js b/src/containers/user/UserProfile/store.js deleted file mode 100755 index b36640441..000000000 --- a/src/containers/user/UserProfile/store.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * UserProfile store - * - */ - -import { types as T, getParent } from 'mobx-state-tree' -// import {} from 'ramda' - -import { markStates, toJS } from '@/utils/mobx' - -const UserProfile = T.model('UserProfile', {}) - .views((self) => ({ - get root() { - return getParent(self) - }, - get isLogin() { - return self.root.account.isLogin - }, - get viewingUser() { - return toJS(self.root.viewing.user) - }, - })) - .actions((self) => ({ - setViewing(sobj) { - self.root.setViewing(sobj) - }, - mark(sobj) { - markStates(sobj, self) - }, - })) - -export default UserProfile diff --git a/src/containers/user/UserProfile/store.tsx b/src/containers/user/UserProfile/store.tsx new file mode 100755 index 000000000..ebad8d21e --- /dev/null +++ b/src/containers/user/UserProfile/store.tsx @@ -0,0 +1,33 @@ +/* + * UserProfile store + * + */ + +import { types as T, getParent, Instance } from 'mobx-state-tree' + +import type { TRootStore, TUser } from '@/spec' +import { markStates, toJS } from '@/utils/mobx' + +const UserProfile = T.model('UserProfile', {}) + .views((self) => ({ + get isLogin(): boolean { + const root = getParent(self) as TRootStore + return root.account.isLogin + }, + get viewingUser(): TUser { + const root = getParent(self) as TRootStore + return toJS(root.viewing.user) + }, + })) + .actions((self) => ({ + setViewing(sobj): void { + const root = getParent(self) as TRootStore + root.setViewing(sobj) + }, + mark(sobj: Record): void { + markStates(sobj, self) + }, + })) + +export type TStore = Instance +export default UserProfile diff --git a/src/containers/user/UserProfile/styles/numbers_pad.ts b/src/containers/user/UserProfile/styles/numbers_pad.ts index ddf28c5a7..3ec107b11 100644 --- a/src/containers/user/UserProfile/styles/numbers_pad.ts +++ b/src/containers/user/UserProfile/styles/numbers_pad.ts @@ -14,7 +14,7 @@ export const Wrapper = styled.div` margin-top: -15px; margin-bottom: 50px; ` -export const Section = styled.div` +const Section = styled.div` ${css.flexColumn('align-both')}; width: 100px; height: 82px; @@ -30,6 +30,13 @@ export const GravitySection = styled(Section)` width: 130px; padding-left: 10px; ` +export const JoinSection = styled(Section)` + width: 200px; +` +export const CommunitiesWrapper = styled.div` + margin-bottom: 5px; + margin-top: 4px; +` export const Num = styled.div` font-size: 18px; color: ${theme('thread.articleTitle')}; @@ -55,24 +62,7 @@ export const Title = styled.div` color: ${theme('thread.articleDigest')}; opacity: 0.8; ` -export const JoinAt = styled(Num)` - ${css.flex('align-both')}; - position: relative; - font-size: 14px; - margin-top: 1px; - margin-bottom: 2px; -` -export const JoinSlash = styled.div` - font-size: 10px; - color: ${theme('thread.articleDigest')}; - font-weight: bolder; - font-family: monospace; - margin-right: 3px; - margin-left: 3px; - opacity: 0.8; - transform: rotate(-5deg); - margin-top: 2px; -` + export const Divider = styled.div` height: 40px; width: 1px; diff --git a/src/containers/user/UserProfile/styles/subscribed_communities.ts b/src/containers/user/UserProfile/styles/subscribed_communities.ts deleted file mode 100644 index f7bd14ccd..000000000 --- a/src/containers/user/UserProfile/styles/subscribed_communities.ts +++ /dev/null @@ -1,26 +0,0 @@ -import styled from 'styled-components' - -import type { TTestable } from '@/spec' -import { theme } from '@/utils/themes' - -export const Wrapper = styled.div.attrs(({ testid }: TTestable) => ({ - 'data-test-id': testid, -}))` - margin-top: 50px; - padding: 0 10px; -` -export const Title = styled.div` - color: ${theme('thread.articleTitle')}; - width: 100%; - margin-bottom: 10px; - font-size: 14px; -` -export const Divider = styled.div` - width: 100%; - padding: 0 5px; - height: 1px; - background: ${theme('thread.articleDigest')}; - opacity: 0.2; - margin-top: 12px; - margin-bottom: 16px; -` diff --git a/src/spec/account.ts b/src/spec/account.ts index 3afb2b728..124ff6113 100644 --- a/src/spec/account.ts +++ b/src/spec/account.ts @@ -24,12 +24,25 @@ export type TSimpleUser = { avatar?: string } +type TContributes = { + records?: { + date: string + count: number + } + startDate?: string + endDate?: string + totalCount?: number +} + export type TUser = TSimpleUser & { id?: string // TODO: figure it out extraId?: string editableCommunities?: TPagedCommunities social?: TSocial + contributes?: TContributes + followersCount?: number + followingsCount?: number } export type TPagedUsers = { diff --git a/src/widgets/Cards/UserCard.tsx b/src/widgets/Cards/UserCard.tsx index 72a461f80..d5477a701 100644 --- a/src/widgets/Cards/UserCard.tsx +++ b/src/widgets/Cards/UserCard.tsx @@ -4,7 +4,7 @@ import { FC, memo } from 'react' -import type { TUser } from '@/spec' +import type { TAccount, TUser } from '@/spec' import { cutRest } from '@/utils/helper' import { @@ -20,7 +20,7 @@ import { } from './styles/user_card' type TProps = { - item: TUser + item: TUser | TAccount } const UserCard: FC = ({ item }) => { diff --git a/src/widgets/CommunityList/index.js b/src/widgets/CommunityList/index.js deleted file mode 100755 index 9d1038bbb..000000000 --- a/src/widgets/CommunityList/index.js +++ /dev/null @@ -1,107 +0,0 @@ -/* - * - * CommunityList - * - */ - -import React from 'react' -import T from 'prop-types' -import { isEmpty } from 'ramda' - -import { ICON } from '@/config' -import { buildLog } from '@/utils/logger' -import Tooltip from '@/widgets/Tooltip' - -import { - Wrapper, - Linker, - Logo, - PopoverInfo, - PopCommunityLogo, - PopCommunityInfo, - PopCommunityTitle, - PopCommunityDesc, - MoreWrapper, - MoreIcon, -} from './styles' - -/* eslint-disable-next-line */ -const log = buildLog('c:CommunityList:index') - -const CommunityList = ({ - items, - size, - bottom, - emptyHint, - right, - totalCount, - onMoreClick, -}) => { - if (isEmpty(items)) { - return !isEmpty(emptyHint) && <>{emptyHint} - } - - return ( - - {items.map((community) => ( - - - - {community.title} - {community.desc} - - - } - > - - - - - ))} - - {totalCount > items.length && ( - -
{totalCount}
{' '} - -
- )} -
- ) -} - -CommunityList.propTypes = { - items: T.arrayOf( - T.shape({ - id: T.string, - raw: T.string, - title: T.string, - logo: T.string, - }), - ), - size: T.number, - bottom: T.number, - right: T.number, - emptyHint: T.oneOfType([T.string, T.node]), - totalCount: T.number, - onMoreClick: T.func, -} - -CommunityList.defaultProps = { - items: [], - emptyHint: '', - size: 24, - bottom: 0, - right: 5, - totalCount: -1, - onMoreClick: log, -} - -export default React.memo(CommunityList) diff --git a/src/widgets/CommunityList/index.tsx b/src/widgets/CommunityList/index.tsx new file mode 100755 index 000000000..8f75c5aa5 --- /dev/null +++ b/src/widgets/CommunityList/index.tsx @@ -0,0 +1,68 @@ +/* + * + * CommunityList + * + */ + +import { FC, memo, ReactNode } from 'react' +import { isEmpty } from 'ramda' + +import type { TCommunity } from '@/spec' +import { buildLog } from '@/utils/logger' +import Tooltip from '@/widgets/Tooltip' +import CommunityCard from '@/widgets/Cards/CommunityCard' + +import { Wrapper, Linker, Logo, MoreWrapper } from './styles' + +/* eslint-disable-next-line */ +const log = buildLog('c:CommunityList:index') + +type TProps = { + items: TCommunity[] + size?: number + bottom?: number + right?: number + emptyHint?: ReactNode + totalCount?: number + onMoreClick?: () => void +} + +const CommunityList: FC = ({ + items, + size = 22, + bottom = 0, + right = 5, + emptyHint = '', + totalCount = -1, + onMoreClick = log, +}) => { + if (isEmpty(items)) { + return !isEmpty(emptyHint) && <>{emptyHint} + } + + return ( + + {items.map((community) => ( + } + > + + + + + ))} + + {totalCount > items.length && ( + {totalCount}+ + )} + + ) +} + +export default memo(CommunityList) diff --git a/src/widgets/CommunityList/styles/index.ts b/src/widgets/CommunityList/styles/index.ts index e842bd30a..004a1c26e 100755 --- a/src/widgets/CommunityList/styles/index.ts +++ b/src/widgets/CommunityList/styles/index.ts @@ -3,7 +3,7 @@ import styled from 'styled-components' import type { TSpace } from '@/spec' import { theme } from '@/utils/themes' import css from '@/utils/css' -import Img from '@/Img' +import CommunityFaceLogo from '@/widgets/CommunityFaceLogo' export const Wrapper = styled.div` ${css.flex('align-center')}; @@ -17,56 +17,24 @@ export const Linker = styled.a` text-decoration: underline; } ` -export const Logo = styled(Img)<{ size: string }>` +export const Logo = styled(CommunityFaceLogo)<{ size: number }>` fill: ${theme('thread.articleTitle')}; width: ${({ size }) => `${size}px`}; height: ${({ size }) => `${size}px`}; display: block; ` -export const PopoverInfo = styled.div` - ${css.flex()}; - padding: 5px 10px; - max-width: 240px; -` -export const PopCommunityLogo = styled(Img)` - ${css.size(40)}; - margin-right: 8px; -` -export const PopCommunityInfo = styled.div` - ${css.flexColumn()}; -` -export const PopCommunityTitle = styled.div` - font-weight: bold; - color: ${theme('thread.articleTitle')}; -` -export const PopCommunityDesc = styled.div` - color: ${theme('thread.articleDigest')}; - font-size: 0.8rem; -` -type TMoreWrapper = TSpace & { size: string } -export const MoreWrapper = styled.div` + +export const MoreWrapper = styled.div` ${css.flex('align-center')} - color: ${theme('thread.articleDigest')}; - width: ${({ size }) => size}; - height: ${({ size }) => size}; - margin-bottom: ${({ bottom }) => bottom}; - margin-left: 5px; + color: ${theme('button.primary')}; + font-weight: bold; + font-size: 12px; + margin-left: -2px; + opacity: 0.8; &:hover { - color: ${theme('thread.articleTitle')}; + opacity: 1; cursor: pointer; } - transition: all 0.25s; -` -export const MoreIcon = styled(Img)` - fill: ${theme('thread.articleDigest')}; - ${css.size(14)}; - transform: rotate(180deg); - margin-left: 2px; - - ${MoreWrapper}:hover & { - fill: ${theme('thread.articleTitle')}; - margin-left: 4px; - } - transition: all 0.25s; + transition: all 0.1s; ` diff --git a/src/widgets/Header/DesktopView/ArticleLayout.tsx b/src/widgets/Header/DesktopView/ArticleLayout.tsx index 41042b21a..665d88906 100644 --- a/src/widgets/Header/DesktopView/ArticleLayout.tsx +++ b/src/widgets/Header/DesktopView/ArticleLayout.tsx @@ -8,6 +8,7 @@ import { FC } from 'react' import { ICON } from '@/config' +import type { TUser } from '@/spec' import { buildLog } from '@/utils/logger' import { authWarn } from '@/utils/helper' @@ -49,7 +50,7 @@ const ArticleHeader: FC = ({ metric, c11n, community }) => { ) : ( } + content={} delay={0} placement="bottom" interactive={false} diff --git a/src/widgets/Icons/Blog.tsx b/src/widgets/Icons/Blog.tsx index a04484cba..a98375e64 100644 --- a/src/widgets/Icons/Blog.tsx +++ b/src/widgets/Icons/Blog.tsx @@ -1,3 +1,4 @@ +/* eslint-disable max-len */ import { memo, SVGProps } from 'react' const Blog = (props: SVGProps) => { @@ -10,9 +11,20 @@ const Blog = (props: SVGProps) => { height={200} {...props} > - + ) } export default memo(Blog) + +// +// +// diff --git a/src/widgets/Icons/City.tsx b/src/widgets/Icons/City.tsx new file mode 100644 index 000000000..c2d4a088d --- /dev/null +++ b/src/widgets/Icons/City.tsx @@ -0,0 +1,18 @@ +import { memo, SVGProps } from 'react' + +const City = (props: SVGProps) => { + return ( + + + + ) +} + +export default memo(City) diff --git a/src/widgets/Icons/Company.tsx b/src/widgets/Icons/Company.tsx new file mode 100644 index 000000000..d02add94b --- /dev/null +++ b/src/widgets/Icons/Company.tsx @@ -0,0 +1,18 @@ +import { memo, SVGProps } from 'react' + +const Company = (props: SVGProps) => { + return ( + + + + ) +} + +export default memo(Company) diff --git a/src/widgets/Icons/Mail.tsx b/src/widgets/Icons/Mail.tsx new file mode 100644 index 000000000..361134c11 --- /dev/null +++ b/src/widgets/Icons/Mail.tsx @@ -0,0 +1,19 @@ +/* eslint-disable max-len */ +import { memo, SVGProps } from 'react' + +const Mail = (props: SVGProps) => { + return ( + + + + ) +} + +export default memo(Mail) diff --git a/src/widgets/UserBrief/ExtraInfo.js b/src/widgets/UserBrief/ExtraInfo.js deleted file mode 100755 index 23f126da3..000000000 --- a/src/widgets/UserBrief/ExtraInfo.js +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react' -// import { either, isNil, isEmpty } from 'ramda' - -import { ICON_CMD } from '@/config' - -// import BackgroundList from './BackgroundList' -import { Section, Icon, Desc } from './styles/extra_info' - -// const emptyBacgrounds = either(isNil, isEmpty) - -const ExtraInfo = ({ user }) => { - return ( - -
- {' '} - {/* {user.location} */} - 成都 -
- {/* {!emptyBacgrounds(user.workBackgrounds) && ( -
- {' '} - -
- )} - - {!emptyBacgrounds(user.educationBackgrounds) && ( -
- {' '} - -
- )} */} -
- ) -} - -export default React.memo(ExtraInfo) diff --git a/src/widgets/UserBrief/ExtraInfo.tsx b/src/widgets/UserBrief/ExtraInfo.tsx new file mode 100755 index 000000000..cc84bbb72 --- /dev/null +++ b/src/widgets/UserBrief/ExtraInfo.tsx @@ -0,0 +1,41 @@ +import { FC, memo, Fragment } from 'react' + +import type { TUser } from '@/spec' +import { Section, ICON, Desc } from './styles/extra_info' + +type TProps = { + user: TUser +} + +const ExtraInfo: FC = ({ user }) => { + return ( + +
+ + 成都 +
+
+ + Groupher +
+
+ + https://mydearxym.qq.com +
+
+ + mydearxym +
+
+ + mydearxym +
+
+ + mydearxym@qq.com +
+
+ ) +} + +export default memo(ExtraInfo) diff --git a/src/widgets/UserBrief/Footer.tsx b/src/widgets/UserBrief/Footer.tsx new file mode 100755 index 000000000..a4ebe2d2c --- /dev/null +++ b/src/widgets/UserBrief/Footer.tsx @@ -0,0 +1,30 @@ +import { FC, memo, Fragment } from 'react' + +import type { TUser } from '@/spec' +import { Wrapper, Section, Text, JoinAt, JoinSlash } from './styles/footer' + +type TProps = { + user: TUser +} + +const Footer: FC = ({ user }) => { + return ( + +
+ 注册于 + + 2020 + / + 13 + / + 02 + +
+
+ 主页被浏览 456 次 +
+
+ ) +} + +export default memo(Footer) diff --git a/src/widgets/UserBrief/index.tsx b/src/widgets/UserBrief/index.tsx index faa7d2c72..2ab4d7062 100755 --- a/src/widgets/UserBrief/index.tsx +++ b/src/widgets/UserBrief/index.tsx @@ -14,6 +14,7 @@ import { Br } from '@/widgets/Common' // import SocialIcons from './SocialIcons' import ExtraInfo from './ExtraInfo' import Operators from './Operators' +import Footer from './Footer' // import CommunityEditorInfo from './CommunityEditorInfo' import Avatar from './Avatar' @@ -71,9 +72,7 @@ const UserBrief: FC = ({ {/* {user.editableCommunities.length > 0 && } */} {/* */} - {/* - - */} +