diff --git a/site/src/component/GradeDist/Chart.tsx b/site/src/component/GradeDist/Chart.tsx index be3fa5a4..79f89d4a 100644 --- a/site/src/component/GradeDist/Chart.tsx +++ b/site/src/component/GradeDist/Chart.tsx @@ -4,8 +4,8 @@ import { ResponsiveBar, BarTooltipProps, BarDatum } from '@nivo/bar'; import ThemeContext from '../../style/theme-context'; import { type Theme } from '@nivo/core'; import { GradesRaw } from '@peterportal/types'; - -const colors = ['#60A3D1', '#81C284', '#F5D77F', '#ECAD6D', '#E8966D', '#EBEBEB', '#EBEBEB']; +import { GradeColors } from './gradeColors.ts'; +import { tooltipStyle } from './tooltipStyle.ts'; interface ChartProps { gradeData: GradesRaw; @@ -70,61 +70,47 @@ export default class Chart extends React.Component { id: 'A', label: 'A', A: gradeACount, - color: '#2484C6', + color: GradeColors.A, }, { id: 'B', label: 'B', B: gradeBCount, - color: '#54B058', + color: GradeColors.B, }, { id: 'C', label: 'C', C: gradeCCount, - color: '#F9CE50', + color: GradeColors.C, }, { id: 'D', label: 'D', D: gradeDCount, - color: '#ED9237', + color: GradeColors.D, }, { id: 'F', label: 'F', F: gradeFCount, - color: '#E67237', + color: GradeColors.F, }, { id: 'P', label: 'P', P: gradePCount, - color: '#4AB486', + color: GradeColors.P, }, { id: 'NP', label: 'NP', NP: gradeNPCount, - color: '#E36436', + color: GradeColors.NP, }, ]; }; - tooltipStyle: Theme = { - tooltip: { - container: { - background: 'rgba(0,0,0,.87)', - color: '#ffffff', - fontSize: '1.2rem', - outline: 'none', - margin: 0, - padding: '0.25em 0.5em', - borderRadius: '2px', - }, - }, - }; - /* * Indicate how the tooltip should look like when users hover over the bar * Code is slightly modified from: https://codesandbox.io/s/nivo-scatterplot- @@ -134,7 +120,7 @@ export default class Chart extends React.Component { */ styleTooltip = (props: BarTooltipProps) => { return ( -
+
{props.label}: {props.data[props.label]} @@ -184,7 +170,7 @@ export default class Chart extends React.Component { legendOffset: 36, }} enableLabel={false} - colors={colors} + colors={Object.values(GradeColors)} theme={this.getTheme(darkMode)} tooltipLabel={(datum) => String(datum.id)} tooltip={this.styleTooltip} diff --git a/site/src/component/GradeDist/Colors.tsx b/site/src/component/GradeDist/Colors.tsx new file mode 100644 index 00000000..5f2aa2a6 --- /dev/null +++ b/site/src/component/GradeDist/Colors.tsx @@ -0,0 +1 @@ +export const Colors = ['#60A3D1', '#81C284', '#F5D77F', '#ECAD6D', '#E8966D', '#EBEBEB', '#EBEBEB']; diff --git a/site/src/component/GradeDist/Pie.tsx b/site/src/component/GradeDist/Pie.tsx index 2d41bfb3..108fff67 100644 --- a/site/src/component/GradeDist/Pie.tsx +++ b/site/src/component/GradeDist/Pie.tsx @@ -2,6 +2,8 @@ import React from 'react'; import { ResponsivePie, PieTooltipProps } from '@nivo/pie'; import { GradesRaw } from '@peterportal/types'; +import { GradeColors } from './gradeColors.ts'; +import { tooltipStyle } from './tooltipStyle.ts'; const gradeScale = ['A', 'A-', 'B+', 'B', 'B-', 'C+', 'C', 'C-', 'D+', 'D', 'D-']; const gpaScale = [4.0, 3.7, 3.3, 3.0, 2.7, 2.3, 2.0, 1.7, 1.3, 1.0, 0, 7]; @@ -27,7 +29,7 @@ export default class Pie extends React.Component { averageGrade = ''; averagePNP = ''; - getClassData = () => { + getClassData = (): Slice[] => { let gradeACount = 0, gradeBCount = 0, gradeCCount = 0, @@ -85,13 +87,13 @@ export default class Pie extends React.Component { id: 'P', label: 'P', value: gradePCount, - color: '#4AB486', + color: GradeColors.P, }, { id: 'NP', label: 'NP', value: gradeNPCount, - color: '#E36436', + color: GradeColors.NP, }, ]; return data; @@ -102,43 +104,43 @@ export default class Pie extends React.Component { id: 'A', label: 'A', value: gradeACount, - color: '#60A3D1', + color: GradeColors.A, }, { id: 'B', label: 'B', value: gradeBCount, - color: '#81C284', + color: GradeColors.B, }, { id: 'C', label: 'C', value: gradeCCount, - color: '#F5D77F', + color: GradeColors.C, }, { id: 'D', label: 'D', value: gradeDCount, - color: '#ECAD6D', + color: GradeColors.D, }, { id: 'F', label: 'F', value: gradeFCount, - color: '#E8966D', + color: GradeColors.F, }, { id: 'P', label: 'P', value: gradePCount, - color: '#4AB486', + color: GradeColors.P, }, { id: 'NP', label: 'NP', value: gradeNPCount, - color: '#E36436', + color: GradeColors.NP, }, ]; return data; @@ -150,6 +152,16 @@ export default class Pie extends React.Component { this.averageGrade = gradeScale[i]; } + styleTooltip = (props: PieTooltipProps) => { + return ( +
+ + {props.datum.id}: {((props.datum.value / this.total) * 100).toFixed(2)}% + +
+ ); + }; + render() { return (
@@ -165,24 +177,11 @@ export default class Pie extends React.Component { enableArcLinkLabels={false} innerRadius={0.8} padAngle={2} - colors={['#60A3D1', '#81C284', '#F5D77F', '#ECAD6D', '#E8966D', '#4AB486', '#E36436']} + colors={Object.values(GradeColors)} cornerRadius={3} borderWidth={1} borderColor={{ from: 'color', modifiers: [['darker', 0.2]] }} - tooltip={(props: PieTooltipProps) => ( -
- - {props.datum.id}: {((props.datum.value / this.total) * 100).toFixed(2)}% - -
- )} + tooltip={this.styleTooltip} />
{ // Math.max() ensures that we're not finding the log of a non-positive number const marginX = 30 + 5 * Math.floor(Math.log10(Math.max(100, greatestCount) / 100)); + //tickSize calculates the proper scale of the graph based on its upper bound as calculated in GreatestCount + const tickSize = Math.floor(greatestCount / 6); + return ( <> @@ -153,7 +156,7 @@ export default class Chart extends React.Component { legendOffset: 36, }} axisLeft={{ - tickValues: Array.from({ length: greatestCount }, (_, i) => i + 1), // integers from 1 to max + tickValues: Array.from({ length: greatestCount / tickSize }, (_, i) => i * tickSize + tickSize), }} enableLabel={false} colors={colors} diff --git a/site/src/component/SearchHitContainer/SearchHitContainer.tsx b/site/src/component/SearchHitContainer/SearchHitContainer.tsx index 4e705722..31c51a48 100644 --- a/site/src/component/SearchHitContainer/SearchHitContainer.tsx +++ b/site/src/component/SearchHitContainer/SearchHitContainer.tsx @@ -29,10 +29,16 @@ const SearchResults = ({ quarter.courses.map((course) => course.department + ' ' + course.courseNumber), ), ); + const transfers = roadmap?.transfers.map((transfer) => transfer.name); if (index === 'courses') { return (results as CourseGQLData[]).map((course, i) => { const requiredCourses = Array.from( - validateCourse(new Set(allExistingCourses), course.prerequisiteTree, new Set(), course.corequisites), + validateCourse( + new Set([...allExistingCourses, ...transfers]), + course.prerequisiteTree, + new Set(), + course.corequisites, + ), ); return ( 0 && { requiredCourses })} /> diff --git a/site/src/pages/RoadmapPage/Transfer.scss b/site/src/pages/RoadmapPage/Transfer.scss index c16ce832..a49796ae 100644 --- a/site/src/pages/RoadmapPage/Transfer.scss +++ b/site/src/pages/RoadmapPage/Transfer.scss @@ -6,7 +6,8 @@ border-top-color: var(--overlay3); } } -.transfer { + +.transfer-body { max-height: 75vh; overflow-y: auto; } @@ -16,7 +17,7 @@ overflow-x: scroll; } -.transfer .list-group .list-group-item { +.transfer-body .list-group .list-group-item { min-width: max-content; background-color: var(--overlay3); } @@ -24,3 +25,37 @@ .entry { margin-top: 1%; } + +.add-entry { + background-color: transparent; + color: var(--peterportal-primary-color-1); + font-size: 16px; + font-weight: bold; + width: fit-content; + margin-inline: auto; + display: flex; + align-items: center; + gap: 4px; +} + +.add-entry:hover { + background-color: transparent; + color: var(--peterportal-primary-color-1); +} + +[data-theme='dark'] { + .add-entry, + .add-entry:hover { + color: var(--peterportal-primary-color-2); + } +} + +.transfer-modal { + .modal-dialog { + max-width: 500px; + max-height: 80%; + } + p { + font-size: 16px; + } +} diff --git a/site/src/pages/RoadmapPage/Transfer.tsx b/site/src/pages/RoadmapPage/Transfer.tsx index 4e145770..9d87ca26 100644 --- a/site/src/pages/RoadmapPage/Transfer.tsx +++ b/site/src/pages/RoadmapPage/Transfer.tsx @@ -8,6 +8,7 @@ import Container from 'react-bootstrap/Container'; import Row from 'react-bootstrap/Row'; import Col from 'react-bootstrap/Col'; import CloseButton from 'react-bootstrap/CloseButton'; +import { PlusLg } from 'react-bootstrap-icons'; import { setShowTransfer, deleteTransfer, setTransfer, addTransfer } from '../../store/slices/roadmapSlice'; import { useAppSelector, useAppDispatch } from '../../store/hooks'; @@ -45,13 +46,13 @@ const TransferEntry: FC = (props) => { return ( - + dispatch(deleteTransfer(props.index))} /> - + setName(e.target.value)} /> - + = ({ missingPrereqNames }) => { }; return ( - - - Transfer Credits + + +

Transfer Credits

- +

Record your AP Credits or Community College Credits here. Doing so will clear the prerequisites on the roadmap. @@ -100,19 +101,20 @@ const Transfer: FC = ({ missingPrereqNames }) => { )} -

+ {transfers.map((transfer, i) => ( ))}
- - -