Skip to content
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import React from "react"
import { renderWithProviders, screen, setMockResponse } from "@/test-utils"
import {
renderWithProviders,
screen,
setMockResponse,
user,
} from "@/test-utils"
import { EnrollmentDisplay } from "./EnrollmentDisplay"
import * as mitxonline from "api/mitxonline-test-utils"
import moment from "moment"
Expand All @@ -9,7 +14,13 @@ const courseEnrollment = mitxonline.factories.enrollment.courseEnrollment
const grade = mitxonline.factories.enrollment.grade
describe("EnrollmentDisplay", () => {
const setupApis = () => {
const ended = [
const completed = [
courseEnrollment({
run: { title: "C Course Ended" },
grades: [grade({ passed: true })],
}),
]
const expired = [
courseEnrollment({
run: {
title: "A Course Ended",
Expand All @@ -22,10 +33,6 @@ describe("EnrollmentDisplay", () => {
end_date: faker.date.past().toISOString(),
},
}),
courseEnrollment({
run: { title: "C Course Ended" },
grades: [grade({ passed: true })],
}),
]
const started = [
courseEnrollment({
Expand Down Expand Up @@ -54,7 +61,8 @@ describe("EnrollmentDisplay", () => {
}),
]
const mitxonlineCourseEnrollments = faker.helpers.shuffle([
...ended,
...expired,
...completed,
...started,
...notStarted,
])
Expand All @@ -66,7 +74,7 @@ describe("EnrollmentDisplay", () => {

return {
mitxonlineCourseEnrollments,
mitxonlineCourses: { started, ended, notStarted },
mitxonlineCourses: { completed, expired, started, notStarted },
}
}

Expand All @@ -80,7 +88,28 @@ describe("EnrollmentDisplay", () => {
const expectedTitles = [
...mitxonlineCourses.started,
...mitxonlineCourses.notStarted,
...mitxonlineCourses.ended,
...mitxonlineCourses.completed,
].map((e) => e.run.title)

expectedTitles.forEach((title, i) => {
expect(cards[i]).toHaveTextContent(title)
})
})

test("Clicking show all reveals ended courses", async () => {
const { mitxonlineCourses } = setupApis()
renderWithProviders(<EnrollmentDisplay />)

await user.click(screen.getByText("Show all"))

screen.getByRole("heading", { name: "My Learning" })

const cards = await screen.findAllByTestId("enrollment-card-desktop")
const expectedTitles = [
...mitxonlineCourses.started,
...mitxonlineCourses.notStarted,
...mitxonlineCourses.completed,
...mitxonlineCourses.expired,
].map((e) => e.run.title)

expectedTitles.forEach((title, i) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import React from "react"
import { enrollmentQueries } from "api/mitxonline-hooks/enrollment"
import {
Collapse,
Link,
PlainList,
PlainListProps,
Typography,
TypographyProps,
styled,
theme,
} from "ol-components"
import { useQuery } from "@tanstack/react-query"
import { mitxonlineEnrollments } from "./transform"
Expand Down Expand Up @@ -42,7 +45,7 @@ const Title = styled(Typography)<Pick<TypographyProps, "component">>(
}),
)

const EnrollmentList = styled(PlainList)<Pick<PlainListProps, "itemSpacing">>(
const EnrollmentsList = styled(PlainList)<Pick<PlainListProps, "itemSpacing">>(
({ theme }) => ({
[theme.breakpoints.down("md")]: {
borderTop: `1px solid ${theme.custom.colors.lightGray2}`,
Expand All @@ -53,6 +56,23 @@ const EnrollmentList = styled(PlainList)<Pick<PlainListProps, "itemSpacing">>(
}),
)

const HiddenEnrollmentsList = styled(EnrollmentsList)({
marginTop: "16px",
[theme.breakpoints.down("md")]: {
borderTop: "none",
marginTop: "0",
},
})

const ShowAllContainer = styled.div(({ theme }) => ({
display: "flex",
justifyContent: "center",
marginTop: "24px",
[theme.breakpoints.down("md")]: {
marginBottom: "24px",
},
}))

const alphabeticalSort = (a: DashboardCourse, b: DashboardCourse) =>
a.title.localeCompare(b.title)

Expand All @@ -65,15 +85,18 @@ const startsSooner = (a: DashboardCourse, b: DashboardCourse) => {
return x.getTime() - y.getTime()
}
const sortEnrollments = (resources: DashboardCourse[]) => {
const ended: DashboardCourse[] = []
const expired: DashboardCourse[] = []
const completed: DashboardCourse[] = []
const started: DashboardCourse[] = []
const notStarted: DashboardCourse[] = []
resources.forEach((resource) => {
if (
resource.enrollment?.status === EnrollmentStatus.Completed ||
(resource.run.endDate && new Date(resource.run.endDate) < new Date())
if (resource.enrollment?.status === EnrollmentStatus.Completed) {
completed.push(resource)
} else if (
resource.run.endDate &&
new Date(resource.run.endDate) < new Date()
) {
ended.push(resource)
expired.push(resource)
} else if (
resource.run.startDate &&
new Date(resource.run.startDate) < new Date()
Expand All @@ -85,12 +108,62 @@ const sortEnrollments = (resources: DashboardCourse[]) => {
})

return {
ended: ended.sort(alphabeticalSort),
completed: completed.sort(alphabeticalSort),
expired: expired.sort(alphabeticalSort),
started: started.sort(alphabeticalSort),
notStarted: notStarted.sort(startsSooner),
}
}

interface EnrollmentExpandCollapseProps {
shownEnrollments: DashboardCourse[]
hiddenEnrollments: DashboardCourse[]
}

const EnrollmentExpandCollapse: React.FC<EnrollmentExpandCollapseProps> = ({
shownEnrollments,
hiddenEnrollments,
}) => {
const [shown, setShown] = React.useState(false)

const handleToggle = (event: React.MouseEvent) => {
event.preventDefault()
setShown(!shown)
}

return (
<>
<EnrollmentsList itemSpacing={"16px"}>
{shownEnrollments.map((course) => (
<DashboardCardStyled
key={course.id}
Component="li"
dashboardResource={course}
showNotComplete={false}
/>
))}
</EnrollmentsList>
<Collapse orientation="vertical" in={shown}>
<HiddenEnrollmentsList itemSpacing={"16px"}>
{hiddenEnrollments.map((course) => (
<DashboardCardStyled
key={course.id}
Component="li"
dashboardResource={course}
showNotComplete={false}
/>
))}
</HiddenEnrollmentsList>
</Collapse>
<ShowAllContainer>
<Link color="red" size="medium" onClick={handleToggle}>
{shown ? "Show less" : "Show all"}
</Link>
</ShowAllContainer>
</>
)
}

const EnrollmentDisplay = () => {
const { data: enrolledCourses } = useQuery({
...enrollmentQueries.coursesList(),
Expand All @@ -106,24 +179,20 @@ const EnrollmentDisplay = () => {
* The constants below are separate for impending "Show All" functionality.
* The above TODO could be handled then.
*/
const { ended, started, notStarted } = sortEnrollments(enrolledCourses || [])
const sorted = [...started, ...notStarted, ...ended]
const { completed, expired, started, notStarted } = sortEnrollments(
enrolledCourses || [],
)
const shownEnrollments = [...started, ...notStarted, ...completed]

return (
<Wrapper>
<Title variant="h5" component="h2">
My Learning
</Title>
<EnrollmentList itemSpacing={"16px"}>
{sorted?.map((course) => (
<DashboardCardStyled
key={course.id}
Component="li"
showNotComplete={false}
dashboardResource={course}
/>
))}
</EnrollmentList>
<EnrollmentExpandCollapse
shownEnrollments={shownEnrollments}
hiddenEnrollments={expired}
/>
</Wrapper>
)
}
Expand Down
Loading