Skip to content

Commit b2572db

Browse files
authored
BREAKING: User Page & API update (#53)
* Updated user page link to username-based. * Added UserPage and route.
1 parent dd4ac2a commit b2572db

File tree

6 files changed

+109
-5
lines changed

6 files changed

+109
-5
lines changed

src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { connect } from 'react-redux';
55
import Helmet from 'react-helmet';
66

77
import DefaultPage from './pages/DefaultPage';
8+
import UserPage from './pages/UserPage';
89
import ArticlePage from './pages/ArticlePage';
910
import EditorPage from './pages/EditorPage';
1011
import LoadingPage from './pages/LoadingPage';
@@ -125,6 +126,7 @@ class App extends React.Component<IAppProps, IAppState> {
125126
<div className="app">
126127
<div className="app__background" style={backgroundStyle}/>
127128
<Route exact={true} path="/" component={DefaultPage} />
129+
<Route exact={true} path="/u/:username" component={UserPage} />
128130
<Route path="/p/:articleUrlId" component={ArticlePage} />
129131
<Route path="/editor" component={EditorPage} isAuthenticated={false} authorId=""/>
130132
</div>

src/pages/UserPage.tsx

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import React, { useEffect, useState } from 'react';
2+
import { RouteComponentProps } from 'react-router';
3+
import Helmet from 'react-helmet';
4+
import DefaultNavbar from '../parts/Navbar/DefaultNavbar';
5+
import ArticleListing from '../parts/ArticleListing/ArticleListing';
6+
7+
import { getArticlesListing, getUserDataByUsername } from '../parts/ApiCaller/ApiCaller';
8+
import { IGetArticleListData } from '../parts/ApiCaller/ApiCaller.d';
9+
import { sortArticleListingByCreated } from '../util';
10+
import { metaTitleTags, metaDescriptionTags, metaKeywordsTag} from '../metaUtils';
11+
12+
import { defaultTheme as theme } from '../style/themes';
13+
14+
const defaultPageStyle = {
15+
marginTop: theme.navbarHeight + theme.topBottomMargin,
16+
marginBottom: theme.topBottomMargin
17+
};
18+
19+
const META_KEYWORDS = ['user'];
20+
21+
interface IUserPageMatchParams {
22+
username: string;
23+
}
24+
25+
interface IUserPageProps extends RouteComponentProps<IUserPageMatchParams> {}
26+
27+
export default function UserPage(props: IUserPageProps) {
28+
const { username } = props.match.params;
29+
const [articles, setArticles] = useState([] as IGetArticleListData[]);
30+
const [userDisplayName, setUserDisplayName] = useState("");
31+
const [errMessage, setErrMessage] = useState("");
32+
33+
// Article Listing
34+
useEffect(() => {
35+
getArticlesListing({ authorUsername: username })
36+
.then(({ data: resData }) => {
37+
let articleListData = sortArticleListingByCreated(resData.data);
38+
let err = resData.err;
39+
if (err) {
40+
return setErrMessage("getArticlesListing:" + err);
41+
}
42+
setArticles(articleListData);
43+
})
44+
.catch(err => setErrMessage("getArticlesListing:" + err.message));
45+
}, [username]);
46+
47+
// User Data
48+
useEffect(() => {
49+
getUserDataByUsername(username)
50+
.then(({ data: resData }) => {
51+
const userData = resData.data;
52+
const err = resData.err;
53+
if (err) {
54+
return setErrMessage("getUserDataByUsername:" + err);
55+
}
56+
setUserDisplayName(userData.userDisplayName);
57+
//setUserDisplayName(userData.)
58+
})
59+
.catch(err => setErrMessage("getUserDataByUsername:" + err.message));
60+
}, [username]);
61+
62+
const helmet = (
63+
<Helmet>
64+
{metaTitleTags(userDisplayName)}
65+
{metaDescriptionTags(`User profile of ${userDisplayName}.`)}
66+
{metaKeywordsTag(META_KEYWORDS)}
67+
</Helmet>
68+
);
69+
70+
function userPageRender(body: any) {
71+
return (
72+
<div className="user-page" style={defaultPageStyle}>
73+
{helmet}
74+
<DefaultNavbar />
75+
<p>{errMessage}</p>
76+
<h1 className="user-page__title" style={theme.articleTitleStyle}>
77+
{userDisplayName}
78+
</h1>
79+
{body}
80+
</div>
81+
)
82+
}
83+
84+
// NO ARTICLES (yet)
85+
if (articles.length === 0) {
86+
return userPageRender((
87+
<p>(No Articles)</p>
88+
));
89+
}
90+
91+
// ARTICLES FOUND
92+
return userPageRender((
93+
<ArticleListing articlesListData={articles} />
94+
))
95+
}

src/parts/ApiCaller/ApiCaller.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ if (isLocalhost()) {
4242
const API_PATH = {
4343
articlesListing: apiPath('/article/listing'),
4444
newArticle: apiPath('/article/new'),
45+
articleDataById: apiPath('/article/data'),
4546
articleData: apiPath('/article/data'),
4647
userData: apiPath('/user/data'),
4748
editorLogin: apiPath('/editor/login'),
@@ -213,7 +214,13 @@ export function getUserData(userId: string): Promise<IGetUserDataResponse> {
213214
return promise;
214215
} else {
215216
// api
216-
const url = API_PATH.userData + '/' + userId;
217+
const url = API_PATH.userData + '/id/' + userId;
217218
return axios.get(url, wCred());
218219
}
220+
}
221+
222+
export function getUserDataByUsername(username: string): Promise<IGetUserDataResponse> {
223+
// api
224+
const url = API_PATH.userData + '/username/' + username;
225+
return axios.get(url, wCred());
219226
}

src/parts/ArticleListing/ArticleListItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export default function ArticleListItem(props: IArticleListItemProps) {
1919
<a className="article-list-item__link" href={util.articleLink(props.articleUrlId)}>
2020
<h3 className="article-list-item__title" style={titleStyle}>{props.articleTitle}</h3>
2121
</a>
22-
<a className="article-list-item__author" href={util.userLink(props.authorId)}>{props.authorName}</a>
22+
<a className="article-list-item__author" href={util.userPageLink(props.authorUsername)}>{props.authorName}</a>
2323
<ArticleSub articleSub={props.articleSub} />
2424
<p className="article-list-item__description">{props.articleDescription}</p>
2525
<p className="article-list-item__date"><span style={{color:'#555'}}>Updated </span>{util.minDateString(props.articleUpdatedAt)}</p>

src/parts/EditorArticleListing/EditorArticleListItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export default class EditorArticleListItem extends React.Component<IEditorArticl
3636
<a className="editor-article-list-item__link" href={editorArticleLink(this.props.articleId)}>
3737
<h3 className="editor-article-list-item__title" style={theme.articleTitleStyle}>{this.props.articleTitle}</h3>
3838
</a>
39-
<a className="editor-article-list-item__author" href={util.userLink(this.props.authorId)}>{this.props.authorName}</a>
39+
<a className="editor-article-list-item__author" href={util.userPageLink(this.props.authorUsername)}>{this.props.authorName}</a>
4040
<a className="editor-article-list-item__sub" href={subHref}>
4141
{aSub}
4242
</a>

src/util.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ export function articleLink(articleUrlId: string) {
182182
return "/p/" + articleUrlId;
183183
}
184184

185-
export function userLink(userId: string) {
186-
return "/u/" + userId;
185+
export function userPageLink(username: string) {
186+
return "/u/" + username;
187187
}
188188

189189
export function arrayToMap(array: any[], keyField: any): object {

0 commit comments

Comments
 (0)