Skip to content

Commit 4ddb656

Browse files
Updated team members components
1 parent b880273 commit 4ddb656

4 files changed

Lines changed: 105 additions & 34 deletions

File tree

src/components/HGNHelpSkillsDashboard/CommunityMembersPage.jsx

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState } from 'react';
1+
import React, { useState, useMemo } from 'react';
22
import RankedUserList from './RankedUserList'; // wherever your RankedUserList is
33

44
const availableSkills = ['React', 'Redux', 'HTML', 'CSS', 'MongoDB', 'Database', 'Agile'];
@@ -12,23 +12,32 @@ function CommunityMembersPage() {
1212
);
1313
};
1414

15+
// EFFECTIVE SKILLS = what we pass to RankedUserList
16+
const effectiveSkills = useMemo(() => {
17+
return selectedSkills.length > 0 ? selectedSkills : availableSkills;
18+
}, [selectedSkills]);
19+
1520
return (
1621
<div>
17-
<h2>Select Skills to Filter Community Members</h2>
18-
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '12px' }}>
19-
{availableSkills.map(skill => (
20-
<label key={skill}>
21-
<input
22-
type="checkbox"
23-
checked={selectedSkills.includes(skill)}
24-
onChange={() => handleCheckboxChange(skill)}
25-
/>
26-
{skill}
27-
</label>
28-
))}
22+
<h1>Community Members</h1>
23+
24+
<div style={{ marginBottom: 16 }}>
25+
<strong>Filter by skills:</strong>
26+
<div style={{ display: 'flex', gap: 10, marginTop: 8, flexWrap: 'wrap' }}>
27+
{availableSkills.map(skill => (
28+
<label key={skill} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
29+
<input
30+
type="checkbox"
31+
checked={selectedSkills.includes(skill)}
32+
onChange={() => handleCheckboxChange(skill)}
33+
/>
34+
{skill}
35+
</label>
36+
))}
37+
</div>
2938
</div>
3039

31-
{selectedSkills.length > 0 && <RankedUserList selectedSkills={selectedSkills} />}
40+
<RankedUserList selectedSkills={effectiveSkills} />
3241
</div>
3342
);
3443
}

src/components/HGNHelpSkillsDashboard/RankedUserList.jsx

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,56 @@ import axios from 'axios';
33
import UserCard from './UserCard';
44
import './style/UserCard.module.css';
55

6-
function RankedUserList({ selectedSkills }) {
6+
function RankedUserList({ selectedSkills = [] }) {
77
const [rankedUsers, setRankedUsers] = useState([]);
88
const [loading, setLoading] = useState(true);
9+
const [error, setError] = useState(null);
910

1011
useEffect(() => {
11-
if (!selectedSkills || selectedSkills.length === 0) return;
12+
let canceled = false;
1213

1314
const fetchRankedUsers = async () => {
1415
setLoading(true);
16+
setError(null);
17+
1518
try {
16-
const response = await axios.get('http://localhost:4500/api/hgnform/ranked', {
17-
params: { skills: selectedSkills.join(',') },
18-
});
19-
setRankedUsers(response.data);
19+
const params = {};
20+
if (Array.isArray(selectedSkills) && selectedSkills.length > 0) {
21+
params.skills = selectedSkills.join(',');
22+
}
23+
24+
const response = await axios.get('http://localhost:4500/api/hgnform/ranked', { params });
25+
26+
if (!canceled) {
27+
const data = response?.data || [];
28+
setRankedUsers(Array.isArray(data) ? data : []);
29+
}
2030
} catch (err) {
21-
// console.error('Error fetching ranked users:', err);
31+
console.error('Failed to fetch ranked users', err);
32+
if (!canceled) {
33+
setError(err);
34+
setRankedUsers([]);
35+
}
2236
} finally {
23-
setLoading(false);
37+
if (!canceled) setLoading(false);
2438
}
2539
};
2640

2741
fetchRankedUsers();
42+
43+
return () => {
44+
canceled = true;
45+
};
2846
}, [selectedSkills]);
2947

3048
if (loading) return <p>Loading ranked users...</p>;
49+
if (error) return <p>Failed to load users.</p>;
50+
if (!rankedUsers.length) return <p>No members found.</p>;
3151

3252
return (
3353
<div className="user-card-container">
3454
{rankedUsers.map(user => (
35-
<UserCard key={user._id} user={user} />
55+
<UserCard key={user._id || user.id || user.uuid} user={user} />
3656
))}
3757
</div>
3858
);

src/components/HGNHelpSkillsDashboard/UserCard.jsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
import React from 'react';
12
import styles from './style/UserCard.module.css';
23
import avatar from './style/avatar.png';
34
import emailIcon from './style/email_icon.png';
45
import slackIcon from './style/slack_icon.png';
56

7+
import { useSelector } from 'react-redux';
8+
69
function UserCard({ user }) {
10+
const darkMode = useSelector(state => state.theme?.darkMode);
711
const { name, email, slack, score, topSkills } = user;
812

913
const getScoreColor = userScore => {
@@ -12,10 +16,12 @@ function UserCard({ user }) {
1216
};
1317

1418
return (
15-
<div className={`${styles.userCard}`}>
19+
<div className={`${styles.userCard} ${darkMode ? styles.darkMode : ''}`}>
1620
<img src={avatar} alt="Avatar" className={`${styles.avatar}`} />
1721
<div className={`${styles.info}`}>
18-
<div className={`${styles.userName}`}>{name}</div>
22+
<div className={`${styles.userName}`} title={name}>
23+
{name}
24+
</div>
1925
{email && (
2026
<div className={`${styles.contactLine}`}>
2127
<img src={emailIcon} alt="Email" className={`${styles.contactIcon}`} />
@@ -41,7 +47,9 @@ function UserCard({ user }) {
4147

4248
<div className={`${styles.skillsSection}`}>
4349
<div className={`${styles.skillsLabel}`}>Top Skills:</div>
44-
<div className={`${styles.skillsText}`}>{topSkills.join(', ')}</div>
50+
<div className={`${styles.skillsText}`}>
51+
{Array.isArray(topSkills) ? topSkills.join(', ') : topSkills || ''}
52+
</div>
4553
</div>
4654
</div>
4755
</div>

src/components/HGNHelpSkillsDashboard/style/UserCard.module.css

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.userCard {
2-
width: 360px;
3-
height: auto;
2+
max-width: 360px;
3+
width: 100%;
4+
box-sizing: border-box;
45
padding: 30px 24px;
56
background: #ffffff;
67
border: 2px solid #eeeeee;
@@ -16,20 +17,24 @@
1617
.avatar {
1718
width: 140px;
1819
height: 140px;
20+
max-width: 40%;
21+
max-height: 140px;
1922
border-radius: 50%;
2023
margin-bottom: 8px;
24+
object-fit: cover;
2125
}
2226

2327
.info {
2428
display: flex;
2529
flex-direction: column;
26-
align-items: flex-start; /* keeps name/email/slack left-aligned */
27-
text-align: left;
30+
align-items: center;
31+
text-align: center;
2832
margin-top: 16px;
2933
padding: 0;
30-
width: fit-content;
31-
margin-left: auto;
32-
margin-right: auto;
34+
width: 100%;
35+
box-sizing: border-box;
36+
padding-left: 8px;
37+
padding-right: 8px;
3338
}
3439

3540
.userName {
@@ -38,7 +43,9 @@
3843
color: black;
3944
margin-bottom: 8px;
4045
white-space: nowrap;
41-
/*font-size: Large;*/
46+
overflow: hidden;
47+
text-overflow: ellipsis;
48+
max-width: 100%;
4249
}
4350

4451
.contactLine {
@@ -48,6 +55,7 @@
4855
font-size: 16px;
4956
color: #616161;
5057
margin-bottom: 6px;
58+
justify-content: center;
5159
}
5260

5361
.contactIcon {
@@ -103,4 +111,30 @@
103111
color: #616161;
104112
line-height: 22px;
105113
word-wrap: break-word;
114+
overflow-wrap: break-word;
115+
}
116+
117+
.userCard.darkMode {
118+
background: #2f4157;
119+
border-color: #444;
120+
box-shadow: none;
121+
}
122+
123+
.userCard.darkMode .contactLine {
124+
color: #ccc;
125+
}
126+
127+
.darkMode .skillsText {
128+
color: #ffffff !important;
129+
}
130+
131+
.darkMode .userName {
132+
color: #ffffff !important;
133+
}
134+
135+
.darkMode .scoreLine,
136+
.darkMode .scoreLabel,
137+
.darkMode .scoreValue,
138+
.darkMode .scoreMax {
139+
color: #ffffff !important;
106140
}

0 commit comments

Comments
 (0)