Skip to content

Commit

Permalink
Sort and color course cards based on study modules (#1096)
Browse files Browse the repository at this point in the history
* Sort and color course cards based on study modules

* Simplify study module parsing for colouring course card headings

* Fix the usage of a possibly undefined prop

* Add typing to colorSchemes in new course card
  • Loading branch information
Redande authored Jan 27, 2023
1 parent 2042631 commit 7bc23b2
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 58 deletions.
51 changes: 26 additions & 25 deletions frontend/components/NewLayout/Courses/CourseCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ import { CardTitle } from "../Common/Card"
import OutboundLink from "/components/OutboundLink"
import moocLogoUrl from "/static/images/moocfi_white.svg"
import SponsorLogo from "/static/images/new/components/courses/f-secure_logo.png"
import CommonTranslations from "/translations/common"
import { formatDateTime } from "/util/dataFormatFunctions"
import { useTranslator } from "/util/useTranslator"

import { CourseFieldsFragment } from "/graphql/generated"

const colorSchemes = {
csb: "#215887",
programming: "#1F6964",
cloud: "#822630",
ai: "#6245A9",
const colorSchemes: Record<string, string> = {
"Cyber Security Base": "#215887",
Ohjelmointi: "#1F6964",
"Pilvipohjaiset websovellukset": "#822630",
"Tekoäly ja data": "#6245A9",
other: "#313947",
}

Expand All @@ -33,21 +35,11 @@ const ContainerBase = css`
`

const Container = styled("li", {
shouldForwardProp: (prop) => prop !== "backgroundImage",
})<{ backgroundImage?: string }>`
shouldForwardProp: (prop) => prop !== "module",
})<{ module?: string }>`
${ContainerBase};
&:nth-of-type(n) {
background: ${colorSchemes["cloud"]};
}
&:nth-of-type(2n) {
background: ${colorSchemes["programming"]};
}
&:nth-of-type(3n) {
background: ${colorSchemes["csb"]};
}
&:nth-of-type(4n) {
background: ${colorSchemes["ai"]};
}
background-color: ${(props) =>
props.module ? colorSchemes[props.module] : "#313947"};
`

const SkeletonContainer = styled("li")`
Expand Down Expand Up @@ -153,8 +145,16 @@ interface CourseCardProps {
}

function CourseCard({ course, tags }: CourseCardProps) {
const t = useTranslator(CommonTranslations)

return (
<Container>
<Container
module={
course.study_modules.length == 0
? "other"
: course.study_modules[0].name
}
>
<TitleContainer>
<Title variant="h4" component="h2">
{course?.name}
Expand All @@ -177,25 +177,26 @@ function CourseCard({ course, tags }: CourseCardProps) {
<Schedule>
{course.status == "Upcoming" ? (
<p>
Tulossa {course.start_date && prettifyDate(course.start_date)}
{t("Upcoming")}{" "}
{course.start_date && prettifyDate(course.start_date)}
</p>
) : course?.status == "Ended" ? (
<p>
Päättynyt{" "}
{t("Ended")}{" "}
{course.end_date &&
Date.parse(course.end_date) < Date.now() &&
formatDateTime(course.end_date)}
</p>
) : (
<p>
Käynnissä{" "}
{t("Active")}{" "}
{course.end_date ? (
<>
{formatDateTime(course.start_date)} -{" "}
{formatDateTime(course.end_date)}
</>
) : (
<>Aikatauluton</>
<>{t("unscheduled")}</>
)}
</p>
)}
Expand All @@ -221,7 +222,7 @@ function CourseCard({ course, tags }: CourseCardProps) {
))}
</Tags>
<Link eventLabel="to_course_material" to="https://www.mooc.fi">
Näytä kurssi
{t("showCourse")}
</Link>
</ContentContainer>
</Container>
Expand Down
90 changes: 58 additions & 32 deletions frontend/components/NewLayout/Courses/CourseGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ import CommonTranslations from "/translations/common"
import { mapNextLanguageToLocaleCode } from "/util/moduleFunctions"
import { useTranslator } from "/util/useTranslator"

import { CoursesDocument, CourseStatus } from "/graphql/generated"
import {
CourseFieldsFragment,
CoursesDocument,
CourseStatus,
} from "/graphql/generated"

/* Coming in a later PR for better mobile view
const Container = styled.div`
Expand Down Expand Up @@ -187,6 +191,7 @@ function CourseGrid() {
CourseStatus.Active,
CourseStatus.Upcoming,
])
const [courses, setCourses] = useState<CourseFieldsFragment[]>([])

// TODO: set tags on what tags are found from courses in db? or just do a hard-coded list of tags?

Expand Down Expand Up @@ -223,7 +228,12 @@ function CourseGrid() {
: "undefined",
)
setHardcodedTags(hardcoded)
}, [difficultyTags, moduleTags, languageTags])

if (data?.courses) {
const filteredCourses = data.courses.slice().sort(compareCourses)
setCourses(filteredCourses)
}
}, [data])

const handleClick = (tag: string) => {
if (activeTags.includes(tag)) {
Expand Down Expand Up @@ -287,6 +297,23 @@ function CourseGrid() {
}
}

const compareCourses = (
course1: CourseFieldsFragment,
course2: CourseFieldsFragment,
) => {
if (course1.study_modules.length == 0) {
return 1
} else if (course2.study_modules.length == 0) {
return -1
} else if (course1.study_modules[0].name < course2.study_modules[0].name) {
return -1
} else if (course1.study_modules[0].name >= course2.study_modules[0].name) {
return 1
} else {
return 0
}
}

return (
<Container>
<FiltersContainer>
Expand Down Expand Up @@ -413,36 +440,35 @@ function CourseGrid() {
</CardContainer>
) : (
<CardContainer>
{data?.courses &&
data.courses
.filter(
(course) =>
!course.hidden &&
course.course_translations.length > 0 &&
(course?.name
.toLowerCase()
.includes(searchString.toLowerCase()) ||
course?.description
?.toLowerCase()
.includes(searchString.toLowerCase())) &&
(activeTags.length > 0
? activeTags.every((tag) =>
hardcodedTags[course?.slug].includes(tag),
)
: true) &&
(filteredStatuses.length > 0 && course.status
? filteredStatuses.includes(CourseStatus[course.status])
: true),
)
.map((course) => (
<CourseCard
key={course.id}
course={course}
tags={
course?.slug ? hardcodedTags[course?.slug] : ["undefined"]
}
/>
))}
{courses
.filter(
(course) =>
!course.hidden &&
course.course_translations.length > 0 &&
(course?.name
.toLowerCase()
.includes(searchString.toLowerCase()) ||
course?.description
?.toLowerCase()
.includes(searchString.toLowerCase())) &&
(activeTags.length > 0
? activeTags.every((tag) =>
hardcodedTags[course?.slug].includes(tag),
)
: true) &&
(filteredStatuses.length > 0 && course.status
? filteredStatuses.includes(CourseStatus[course.status])
: true),
)
.map((course) => (
<CourseCard
key={course.id}
course={course}
tags={
course?.slug ? hardcodedTags[course?.slug] : ["undefined"]
}
/>
))}
</CardContainer>
)}
</Container>
Expand Down
2 changes: 2 additions & 0 deletions frontend/translations/common/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,7 @@
"fi": "Suomeksi",
"en": "In English",
"selectAll": "Select all",
"unscheduled": "Indefinitely open",
"showCourse": "Show course",
"noResults": "No results"
}
4 changes: 3 additions & 1 deletion frontend/translations/common/fi.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"showHidden": "Näytä piilotetut",
"Active": "Käynnissä",
"Upcoming": "Tulossa",
"Ended": "Loppunut",
"Ended": "Päättynyt",
"handledBy": "Handled by",
"search": "Etsi...",
"filter": "Suodata",
Expand All @@ -67,6 +67,8 @@
"fi": "Suomeksi",
"en": "In English",
"selectAll": "Valitse kaikki",
"unscheduled": "Aikatauluton",
"showCourse": "Näytä kurssi",
"noResults": "Ei tuloksia"
}

2 changes: 2 additions & 0 deletions frontend/translations/common/se.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
"ukraineHyLinkText": "University of Helsinki Ukraine appeal",
"noResults": "No results",
"selectAll": "Select all",
"unscheduled": "Indefinitely open",
"showCourse": "Show course",
"fi": "Suomeksi",
"en": "In English"
}

0 comments on commit 7bc23b2

Please sign in to comment.