[Frontend] Convert semestersPresent to use CSS based SVGs and MUI components

This commit is contained in:
Santeri Rajamäki
2025-07-02 13:04:02 +03:00
parent 4c553124bf
commit be1be25d00
5 changed files with 90 additions and 55 deletions
+19
View File
@@ -0,0 +1,19 @@
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 80 80"
>
<path
d="M70 30L60 56H20L10 30L27 40L40 15L52 40L70 30Z"
fill="#fff238"
stroke="#696969"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M40 52l9 -11l-9 -13l-9 13l9 11"
fill="#61DAFF"
stroke="#E8740E"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>

After

Width:  |  Height:  |  Size: 379 B

+12
View File
@@ -0,0 +1,12 @@
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 80 80"
>
<path
d="M70 30L60 56H20L10 30L27 40L40 15L52 40L70 30Z"
fill="#fff238"
stroke="#696969"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>

After

Width:  |  Height:  |  Size: 234 B

@@ -0,0 +1,22 @@
/* These should inherit the width and height from .enrollment-label-no-margin */
/* Instead we inflate the size and offset the svg... */
.graduated::after,
.graduated-higher::after {
content: '';
position: relative;
top: -15px;
left: -4px;
display: inline-block;
width: 23px;
height: 23px;
background-image: url('/crown.svg');
background-size: contain;
background-repeat: no-repeat;
overflow: visible;
}
.graduated-higher::after {
background-image: url('/crown-big.svg');
}
@@ -1,9 +1,11 @@
import Tooltip from '@mui/material/Tooltip'
import dayjs from 'dayjs'
import isBetween from 'dayjs/plugin/isBetween'
import { Popup } from 'semantic-ui-react'
import { getCurrentSemester, isFall, isMastersProgramme } from '@/common'
import './semestersPresent.css'
dayjs.extend(isBetween)
export const getSemestersPresentFunctions = ({
@@ -54,8 +56,8 @@ export const getSemestersPresentFunctions = ({
const graduatedOnSemester = (student, semester, programmeCode) => {
if (!programmeCode) return 0
const firstGraduation = studentToStudyrightEndMap[student.studentNumber]
const secondGraduation = studentToSecondStudyrightEndMap[student.studentNumber]
const firstGraduation = studentToStudyrightEndMap.get(student.studentNumber)
const secondGraduation = studentToSecondStudyrightEndMap.get(student.studentNumber)
if (
firstGraduation &&
dayjs(firstGraduation).isBetween(allSemestersMap[semester].startdate, allSemestersMap[semester].enddate)
@@ -79,57 +81,35 @@ export const getSemestersPresentFunctions = ({
const semesterIcons = []
const getSemesterJSX = (semester, enrollmenttype, statutoryAbsence, graduated, key) => {
let type = 'none'
if (enrollmenttype === 1) type = 'present'
if (enrollmenttype === 2) type = 'absent'
if (enrollmenttype === 2 && statutoryAbsence) type = 'absent-statutory'
if (enrollmenttype === 3) type = 'passive'
const onHoverString = () => {
const graduationText = graduated !== 0 ? `(graduated as ${graduated === 1 ? 'Bachelor' : 'Master'})` : ''
return `${enrollmentTypeText(enrollmenttype, statutoryAbsence)} in ${getTextIn(
allSemestersMap[semester]?.name
)} ${graduationText}`
let type
switch (enrollmenttype) {
case 1:
type = 'present'
break
case 2:
type = statutoryAbsence ? 'absent-statutory' : 'absent'
break
case 3:
type = 'passive'
break
default:
type = 'none'
break
}
const graduationCrown = (
<svg
fill="none"
height="23"
style={{ overflow: 'visible' }}
viewBox="17 54 70 70"
width="23"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M69.8203 29.1952L61.0704 56.1246H18.7499L10 29.1952L27.2632 38.9284L39.9102 15L52.5571 38.9284L69.8203 29.1952Z"
fill="#fff238"
stroke="#696969"
strokeLinecap="round"
strokeLinejoin="round"
/>
{graduated === 2 && (
<path d="M 40 52.5 l 9 -12 l -9 -12 l -9 12 l 9 12" fill="rgb(97, 218, 255)" stroke="rgb(232, 116, 14)" />
)}
</svg>
)
const graduationCrownClassName = graduated ? (graduated === 2 ? 'graduated-higher' : 'graduated') : ''
const graduationText = graduated ? `(graduated as ${graduated === 1 ? 'Bachelor' : 'Master'})` : ''
const onHoverString = `
${enrollmentTypeText(enrollmenttype, statutoryAbsence)} in ${getTextIn(allSemestersMap[semester]?.name)} ${graduationText}
`
return (
<Popup
content={onHoverString()}
key={key}
on="hover"
position="bottom center"
size="tiny"
trigger={
<div
className={`enrollment-label-no-margin label-${type} ${isFall(semester) ? '' : 'margin-right'}`}
key={key}
>
{graduated > 0 && graduationCrown}
</div>
}
/>
<Tooltip key={key} placement="top" title={onHoverString}>
<span
className={`enrollment-label-no-margin label-${type} ${isFall(semester) ? '' : 'margin-right'} ${graduationCrownClassName}`}
/>
</Tooltip>
)
}
@@ -1,3 +1,4 @@
import { useMemo } from 'react'
import { getStudentTotalCredits, getHighestGradeOfCourseBetweenRange } from '@/common'
import { creditDateFilter } from '@/components/FilterView/filters'
import { useFilters } from '@/components/FilterView/useFilters'
@@ -105,7 +106,7 @@ export const GeneralTabContainer = ({
const shouldShowBachelorAndMaster = showBachelorAndMaster === 'true'
const getStudyRight = student => {
const code = programmeCode ?? studentToPrimaryProgrammeMap[student.studentNumber]?.code
const code = programmeCode ?? studentToPrimaryProgrammeMap.get(student.studentNumber)?.code
return student.studyRights.find(studyRight => studyRight.studyRightElements.some(element => element.code === code))
}
@@ -166,7 +167,7 @@ export const GeneralTabContainer = ({
}
const getMostRecentAttainment = student => {
const code = programmeCode ?? studentToPrimaryProgrammeMap[student.studentNumber]?.code
const code = programmeCode ?? studentToPrimaryProgrammeMap.get(student.studentNumber)?.code
const studyPlan = student.studyplans?.find(plan => plan.programme_code === code) ?? null
if (!studyPlan) return ''
@@ -191,7 +192,7 @@ export const GeneralTabContainer = ({
return studyRightEnd ? formatDate(studyRightEnd, DateFormat.ISO_DATE) : ''
}
const getCreditsFromHops = student => {
const code = programmeCode ?? studentToPrimaryProgrammeMap[student.studentNumber]?.code
const code = programmeCode ?? studentToPrimaryProgrammeMap.get(student.studentNumber)?.code
return student.hopsCredits ?? student.studyplans?.find(plan => plan.programme_code === code)?.completed_credits ?? 0
}
@@ -427,8 +428,9 @@ export const GeneralTabContainer = ({
return result
}
const formattedData: FormattedStudentData[] = selectedStudentNumbers.map(studentNumber =>
formatStudent(students[studentNumber])
const formattedData: FormattedStudentData[] = useMemo(
() => selectedStudentNumbers.map(studentNumber => formatStudent(students[studentNumber])),
[filteredStudents]
)
const containsAdmissionTypes = formattedData.some(student => student.admissionType !== 'Ei valintatapaa')