Skip to content
Open
3 changes: 2 additions & 1 deletion src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
.ReactModal__Body--open,
.ReactModal__Html--open {
overflow: hidden;
}
}

6 changes: 6 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ModalProvider } from "./context/modal";
import { CurrentUserProvider } from "./context/currentUser";
import Welcome from "./pages/welcome";
import AllSearchResults from "./pages/allSearchResults";
import Students from "./pages/students";

const App = () => {
return (
Expand Down Expand Up @@ -48,6 +49,11 @@ const App = () => {
<Profile />
</ProtectedRoute>
} />
<Route path="/students" element={
<ProtectedRoute>
<Students />
</ProtectedRoute>
}/>
</Routes>
</ModalProvider>
</CurrentUserProvider>
Expand Down
34 changes: 34 additions & 0 deletions src/components/cohorts/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { useEffect, useState } from "react"
import { getCohorts } from "../../service/apiClient"
import Card from "../card"
import { CohortProfileCircle } from "../profileCircle"

const Cohorts = () => {
const [cohorts, setCohorts] = useState([])
useEffect(() => {
getCohorts().then(setCohorts)
}, [])

return (
<Card name="cohorts">
{cohorts.length === 0 && (
<p>No cohorts found.</p>
)}
{cohorts.length > 0 && (
<ul className="search-results-list">
{cohorts.map((cohort) => (
<li key={cohort.id} className="found-user-card">
<CohortProfileCircle background='#64DC78'/>
<div className="found-user-details">
<span>{`${cohort.name}`}</span>
<p>{`Cohort ${cohort.id}`}</p>
</div>
</li>
))}
</ul>
)}
</Card>
)
}

export default Cohorts
15 changes: 13 additions & 2 deletions src/components/profileCircle/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ const ProfileCircle = ({ initials, hasCascadingMenu = true }) => {
style={{ cursor: cursor }}
>
{renderCascadingMenu()}

<div className="profile-icon">
<p>{uppercaseInitials}</p>
</div>
Expand All @@ -51,7 +50,19 @@ const ProfileCircle = ({ initials, hasCascadingMenu = true }) => {
)
}

const CascadingMenu = () => {
export const CohortProfileCircle = () => {
return (
<div>
<div className='profile-circle'>
<div className="profile-icon-cohort">
<SquareBracketsIcon />
</div>
</div>
</div>
)
}

const CascadingMenu = () => {
return (
<Menu className="profile-circle-menu">
<MenuItem icon={<ProfileIcon />} text="Profile" />
Expand Down
17 changes: 17 additions & 0 deletions src/components/profileCircle/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,21 @@

.profile-circle-menu {
margin-left: 65px;
}

.profile-icon-cohort {
justify-content: center;
padding-top: 1rem;
background-color: #64DC78;
width: 56px;
height: 56px;
border-radius: 50%;
}

.profile-icon-cohort svg {
margin-left: 7.5px;
}

.profile-icon-cohort path {
fill: white;
}
134 changes: 106 additions & 28 deletions src/components/userLists/index.jsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,127 @@
import "./style.css";
import ProfileCircle from "../profileCircle/index.jsx";
import Card from "../card/index.jsx";
import EllipsisIcon from "../../assets/icons/ellipsisIcon.jsx";
import { NavLink, useNavigate } from "react-router-dom";
import SimpleThreeDotsMenu from "../simpleThreeDotsMenu/index.jsx";
import useUser from "../../hooks/useUser.jsx";
import ThreeDotsMenu from "../threeDotsMenu/index.jsx";
import { useEffect, useRef } from "react";
import Button from "../button/index.jsx";
import ListItem from "./listItem.jsx";

const UserLists = ({ results, name }) => {
const { currentUser } = useUser();
const menuRef = useRef(null);
const navigate = useNavigate();

const getInitials = (firstName, lastName) => {
const getInitials = (firstName, lastName) => {
const firstInitial = firstName ? firstName[0].toUpperCase() : "";
const lastInitial = lastName ? lastName[0].toUpperCase() : "";
return [firstInitial, lastInitial];
};

const onClickStudent = (id) => {
setSelectedProfileId(id);
setIsStudentModalVisible(true);
const handleClickOutside = (event) => {
if (
menuRef.current &&
!menuRef.current.contains(event.target) &&
!event.target.closest(".link-to-profile")
) {
setSelectedProfileId(null);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this setSelectedProfileId function defined? I can't see it in this file

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is used to remove the rendered profile popup after the three dot button is clicked, and the user clicks on another part of the screen. It's used in the onClickMenu to ensure when the profile is clicked it takes the user to that users profile page

}
};

useEffect(() => {
document.addEventListener("click", handleClickOutside);
return () => {
document.removeEventListener("click", handleClickOutside);
};
}, []);

const onClickMenu = (id, event) => {
event.stopPropagation();
setSelectedProfileId((prevId) => (prevId === id ? null : id));
};

const renderTeacherContent = (user) => (
<>

<div className="teacher-links">
<NavLink to="/">
<span>Profile</span>
</NavLink>
<NavLink to="/">
<span>Add Note</span>
</NavLink>
<NavLink to="/">
<span>Move to Cohort</span>
</NavLink>
</div>
<div className="search-three-dots-menu">
<ThreeDotsMenu
onClick={() => onClickMenu(user.id)}
id={user.id}
hasCascadingMenu={true}
/>
</div>
</>
);

const renderStudentContent = (user) => (
<>
{name !== "cohorts" ||
(name !== "students" && (
<div className="found-user-profile-link">
<NavLink to="/">
<p>Profile</p>
</NavLink>
</div>
))}
<div className="search-three-dots-menu">
<SimpleThreeDotsMenu
onClick={() => onClickMenu(user.id)}
id={user.id}
hasCascadingMenu={true}
/>
</div>
</>
);

const onClick = () => {
const students = results;
navigate("/students", { state: { results: students } });
};

return (
<Card name={name}>
{results?.length === 0 && <p>No results found.</p>}
{results?.length > 0 && (
<ul className="search-results-list">
{results.map((user) => (
<li key={user.id} className="found-user-card">
<ProfileCircle
initials={getInitials(user.firstName, user.lastName)}
hasCascadingMenu={false}
{location.pathname !== "/students"
? results.filter((user, index) => index < 10).map((user) => (
<ListItem
user={user}
getInitials={getInitials}
currentUser={currentUser}renderStudentContent={renderStudentContent} renderTeacherContent={renderTeacherContent}
name={name}
/>
))
: results.map((user) => (
<ListItem
user={user}
getInitials={getInitials}
currentUser={currentUser}
renderStudentContent={renderStudentContent} renderTeacherContent={renderTeacherContent}
name={name}
/>

<div className="found-user-details">
<span>{`${user.firstName} ${user.lastName}`}</span>
<p>{`${user.cohort}`}</p>
</div>

<div>
<p>Profile</p>
</div>

<figure
className="link-to-profile"
onClick={() => onClickStudent(cohort.id)}
>
<EllipsisIcon />
</figure>
</li>
))}
{results.length > 10 && location.pathname !== "/students" && (
<div className="button-container">
<Button
text={"All students"}
classes="green width-full"
onClick={onClick}
/>
</div>
)}
</ul>
)}
</Card>
Expand Down
23 changes: 23 additions & 0 deletions src/components/userLists/listItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import ProfileCircle from "../profileCircle";

const ListItem = ({ user, getInitials, currentUser, renderTeacherContent, renderStudentContent, name }) => {
const searchResults = name === 'searchResults'
return (
<li key={user.id} className='students-user-card'>
<ProfileCircle
initials={getInitials(user.firstName, user.lastName)}
hasCascadingMenu={false}
/>

<div className="found-user-details">
<span>{`${user.firstName} ${user.lastName}`}</span>
<p>{`Software Developer, Cohort ${user.cohortId}`}</p>
</div>
{searchResults && currentUser.role === "TEACHER"
? renderTeacherContent(user)
: renderStudentContent(user)}
</li>
);
};

export default ListItem
6 changes: 6 additions & 0 deletions src/components/userLists/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,10 @@
padding-bottom: 12px;
}

.found-user-card {
max-width: 400px;
}

.button-container {
border-top: 1px #e6ebf5 solid;
}
5 changes: 3 additions & 2 deletions src/pages/dashboard/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import ProfileIcon from "../../assets/icons/profileIcon";
import UserProfileIcon from "../../components/UserProfileIcon";
import UserLists from "../../components/userLists";
import useUser from "../../hooks/useUser";
import Cohorts from "../../components/cohorts";

const Dashboard = () => {
const [searchVal, setSearchVal] = useState("");
Expand Down Expand Up @@ -205,11 +206,11 @@ const Dashboard = () => {
<>
<Card name={"user-lists"}>
<h4>Cohorts</h4>
<UserLists name={"cohorts"}/>
<Cohorts />
</Card>
<Card name={"user-lists"}>
<h4>Students</h4>
<UserLists results={cohorts} name={"students"}/>
<UserLists results={students} name={"students"}/>
</Card>
<Card name={"user-lists"}>
<h4>Teachers</h4>
Expand Down
27 changes: 27 additions & 0 deletions src/pages/students/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useLocation } from "react-router-dom"
import UserLists from "../../components/userLists"
import { useState } from "react"
import Header from "../../components/header"
import Navigation from "../../components/navigation"
import './style.css'

const Students = () => {
const location = useLocation()
const { results: studentsState} = location.state || { results: []}
const [students, setStudents] = useState(studentsState)
return (
<div className="students-page-container">
<main className="students-main">
<div className="top">
<h2>Students</h2>
</div>
<div className="students">
<UserLists results={ students }/>
</div>
</main>
</div>

)
}

export default Students
18 changes: 18 additions & 0 deletions src/pages/students/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.students-page-container {
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: auto 1fr;
height: 100vh;
background-color: #f0f5fa;
}

.students-main {
width: 800px;
place-self: center;
}

.students-user-card {
display: grid;
grid-template-columns: 56px 1fr 40px;
width: 100%;
}
10 changes: 9 additions & 1 deletion src/service/apiClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ async function createProfile(
})
}

async function getCohorts() {
const res = await get('cohorts')
if(res.data.error) {
return res
}
return res.data.cohorts
}

async function getUsers() {
const res = await get('users')
return res.data.users
Expand Down Expand Up @@ -83,4 +91,4 @@ async function request(method, endpoint, data, auth = true) {
return response.json()
}

export { login, getUsers, getPosts, register, createProfile, getUser, createPost }
export { login, getUsers, getPosts, register, createProfile, getUser, createPost, getCohorts }