Skip to content

Commit 359612d

Browse files
committed
GAME-205 profile pages updates
1 parent d21ec47 commit 359612d

File tree

11 files changed

+390
-5
lines changed

11 files changed

+390
-5
lines changed

src/shared/actions/page/profile.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ async function getGamificationBadgesInit(handle) {
2121
* @param {String} handle Topcoder member handle.
2222
* @return {Action}
2323
*/
24-
async function getGamificationBadgesDone(handle) {
24+
async function getGamificationBadgesDone(handle, limit) {
2525
try {
2626
const memberInfo = await fetch(`${config.API.V5}/members/${handle}`)
2727
.then(response => response.json());
28-
const badges = await fetch(`${config.API.V5}/gamification/badges/assigned/${memberInfo.userId}?organization_id=${config.GAMIFICATION.ORG_ID}`)
28+
const badges = await fetch(`${config.API.V5}/gamification/badges/assigned/${memberInfo.userId}?organization_id=${config.GAMIFICATION.ORG_ID}&limit=${limit || 4}`)
2929
.then(response => response.json());
3030

3131
return {
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import React, { useState } from 'react';
2+
import PT from 'prop-types';
3+
import { Link } from 'react-router-dom';
4+
import { get } from 'lodash';
5+
import { Modal } from 'topcoder-react-ui-kit';
6+
import IconClose from 'assets/images/tc-edu/icon-close-big.svg';
7+
import FallBackAwardIcon from 'assets/images/default-award.svg';
8+
import md from 'utils/markdown';
9+
import AwardModal from '../ProfilePage/Awards/AwardModal';
10+
11+
import style from './styles.scss';
12+
13+
const ProfileBadges = ({ badges, handleParam }) => {
14+
const [showModal, setShowModal] = useState(false);
15+
const [modalData, setModalData] = useState({});
16+
17+
return (
18+
<div styleName="outer-container">
19+
<Link
20+
to={`/members/${handleParam}`}
21+
styleName="memberPageBackLink"
22+
>
23+
<svg
24+
xmlns="http://www.w3.org/2000/svg"
25+
width="14"
26+
height="12"
27+
fill="none"
28+
viewBox="0 0 14 12"
29+
>
30+
<path
31+
fill="#137D60"
32+
fillRule="evenodd"
33+
d="M6.766 11.366a.8.8 0 01-1.132 0l-4.8-4.8a.8.8 0 010-1.132l4.8-4.8a.8.8 0 111.132 1.132L3.33 5.2h9.27a.8.8 0 010 1.6H3.33l3.435 3.434a.8.8 0 010 1.132z"
34+
clipRule="evenodd"
35+
/>
36+
</svg>
37+
Return to Profile
38+
</Link>
39+
<div styleName="badgesWrap">
40+
<div styleName="seactionTitle">COMMUNITY AWARDS & HONORS</div>
41+
<div styleName="badgesGrid">
42+
{
43+
badges.rows.map((reward) => {
44+
const title = get(reward, 'org_badge.badge_name');
45+
const imageUrl = get(reward, 'org_badge.badge_image_url');
46+
let description = get(reward, 'org_badge.badge_description');
47+
if (description) {
48+
description = md(description);
49+
}
50+
51+
return (
52+
<div
53+
role="presentation"
54+
styleName="awardBadge"
55+
onClick={() => {
56+
setShowModal(true);
57+
setModalData({
58+
title,
59+
description,
60+
imageUrl,
61+
});
62+
}}
63+
>
64+
{
65+
imageUrl ? (
66+
<img src={imageUrl} alt="award-badge" styleName="image" />
67+
) : (
68+
<FallBackAwardIcon styleName="image" />
69+
)
70+
}
71+
<div styleName="title">
72+
<span>
73+
<div dangerouslySetInnerHTML={{ __html: title }} />
74+
</span>
75+
</div>
76+
</div>
77+
);
78+
})
79+
}
80+
</div>
81+
</div>
82+
{
83+
showModal && (
84+
<Modal onCancel={() => setShowModal(false)} theme={style}>
85+
<div styleName="award-modal">
86+
<div styleName="header">
87+
<h2 styleName="title">Community Awards & Honors</h2>
88+
<div styleName="icon" role="presentation" onClick={() => setShowModal(false)}>
89+
<IconClose />
90+
</div>
91+
</div>
92+
<hr />
93+
94+
<AwardModal
95+
modalData={modalData}
96+
/>
97+
</div>
98+
</Modal>
99+
)
100+
}
101+
</div>
102+
);
103+
};
104+
105+
ProfileBadges.defaultProps = {
106+
badges: {},
107+
};
108+
109+
ProfileBadges.propTypes = {
110+
badges: PT.shape(),
111+
handleParam: PT.string.isRequired,
112+
};
113+
114+
export default ProfileBadges;
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/* stylelint-disable no-descending-specificity */
2+
@import "~styles/mixins";
3+
4+
.outer-container {
5+
width: 100%;
6+
max-width: $screen-max;
7+
margin: 0 auto;
8+
display: flex;
9+
flex-direction: column;
10+
11+
@include xs-to-md {
12+
margin: 0 32px;
13+
}
14+
15+
.memberPageBackLink {
16+
text-transform: uppercase;
17+
color: $listing-checkbox-green;
18+
font-weight: 700;
19+
font-family: Roboto, sans-serif;
20+
margin: 32px 0;
21+
display: flex;
22+
align-items: center;
23+
24+
svg {
25+
margin-right: 6px;
26+
}
27+
}
28+
29+
.badgesWrap {
30+
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
31+
border-radius: 8px;
32+
display: flex;
33+
flex-direction: column;
34+
padding: 32px;
35+
margin-bottom: 32px;
36+
37+
.seactionTitle {
38+
@include barlow-medium;
39+
40+
font-weight: 600;
41+
color: #2a2a2a;
42+
font-size: 22px;
43+
line-height: 26px;
44+
text-transform: uppercase;
45+
padding-bottom: 24px;
46+
border-bottom: 2px solid #e9e9e9;
47+
}
48+
49+
.badgesGrid {
50+
display: grid;
51+
grid-template-columns: repeat(6, 1fr);
52+
53+
@include xs-to-sm {
54+
grid-template-columns: repeat(2, 1fr);
55+
}
56+
57+
@include md {
58+
grid-template-columns: repeat(4, 1fr);
59+
}
60+
61+
.awardBadge {
62+
display: flex;
63+
flex-direction: column;
64+
align-items: center;
65+
justify-content: center;
66+
cursor: pointer;
67+
padding-top: 32px;
68+
69+
.image {
70+
width: 100px;
71+
height: 100px;
72+
}
73+
74+
.title {
75+
@include roboto-bold;
76+
$color: $tco-black;
77+
78+
font-size: 12px;
79+
font-weight: 700;
80+
line-height: 16px;
81+
display: flex;
82+
flex-direction: column;
83+
justify-content: center;
84+
text-align: center;
85+
align-items: center;
86+
max-width: 130px;
87+
margin-top: 17px;
88+
text-transform: uppercase;
89+
90+
@include xs-to-sm {
91+
max-width: unset;
92+
}
93+
}
94+
}
95+
}
96+
}
97+
}
98+
99+
.award-modal {
100+
padding-bottom: 10px;
101+
border-radius: 8px;
102+
margin: 25px 32px 32px;
103+
104+
.header {
105+
display: flex;
106+
justify-content: space-between;
107+
margin-bottom: 25px;
108+
109+
.title {
110+
@include barlow-medium;
111+
112+
font-weight: 600;
113+
color: #2a2a2a;
114+
font-size: 22px;
115+
line-height: 26px;
116+
text-transform: uppercase;
117+
}
118+
119+
.icon {
120+
cursor: pointer;
121+
margin-top: 5px;
122+
}
123+
}
124+
}
125+
126+
hr {
127+
opacity: 0.5;
128+
}
129+
130+
.container {
131+
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
132+
border-radius: 8px;
133+
min-width: 600px;
134+
135+
@include xs-to-sm {
136+
width: 90%;
137+
min-width: unset;
138+
}
139+
}
140+
141+
.overlay {
142+
background-color: #0c0c0c;
143+
opacity: 0.85;
144+
}

src/shared/components/ProfilePage/Awards/AwardBadge/styles.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
border-radius: 8px;
77
display: flex;
88
cursor: pointer;
9+
min-width: 316px;
910

1011
.image {
1112
width: 48px;

src/shared/components/ProfilePage/Awards/AwardModal/styles.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
justify-content: center;
2828
flex-direction: column;
2929

30+
@include xs-to-md {
31+
align-items: center;
32+
}
33+
3034
.title {
3135
@include roboto-bold;
3236

src/shared/components/ProfilePage/Awards/index.jsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import { Modal } from 'topcoder-react-ui-kit';
44
import IconClose from 'assets/images/tc-edu/icon-close-big.svg';
55
import _ from 'lodash';
66
import md from 'utils/markdown';
7+
import { Link } from 'react-router-dom';
78

89
import style from './styles.scss';
910
import AwardBadge from './AwardBadge';
1011
import AwatarModal from './AwardModal';
1112

12-
const Awards = ({ badges }) => {
13+
14+
const Awards = ({ badges, info }) => {
1315
const [showModal, setShowModal] = useState(false);
1416
const [modalData, setModalData] = useState({});
1517

@@ -18,6 +20,12 @@ const Awards = ({ badges }) => {
1820
<div styleName="awards">
1921
<div styleName="header">
2022
<span>Community Awards & Honors</span>
23+
<Link
24+
to={`/members/${info.handle}/badges`}
25+
styleName="badgesPageLink"
26+
>
27+
View All Badges
28+
</Link>
2129
</div>
2230

2331
<div styleName="badgesContainer">
@@ -77,6 +85,7 @@ Awards.defaultProps = {
7785

7886
Awards.propTypes = {
7987
badges: PT.arrayOf(PT.shape()),
88+
info: PT.shape().isRequired,
8089
};
8190

8291
export default Awards;

src/shared/components/ProfilePage/Awards/styles.scss

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@
1919
cursor: pointer;
2020
margin-top: 5px;
2121
}
22+
23+
.badgesPageLink {
24+
text-transform: uppercase;
25+
color: $listing-checkbox-green;
26+
font-weight: 700;
27+
font-family: Roboto, sans-serif;
28+
}
2229
}
2330

2431
.awards {
@@ -28,7 +35,7 @@
2835
padding-bottom: 32px;
2936

3037
.header {
31-
padding: 32px 0 20px 32px;
38+
padding: 32px 32px 20px 32px;
3239

3340
@include xs-to-sm {
3441
padding: 16px 0 16px 16px;

src/shared/components/ProfilePage/index.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ class ProfilePage extends React.Component {
229229
</div>
230230
{
231231
(config.GAMIFICATION.ENABLE_BADGE_UI && badges && (badges.rows || [])).length ? (
232-
<Awards badges={badges.rows} />
232+
<Awards badges={badges.rows} info={info} />
233233
) : null
234234
}
235235
{tcAcademyCertifications.length > 0 && (

0 commit comments

Comments
 (0)