From 7a09c54fb87a52268c64e22b9f15ff4039c56281 Mon Sep 17 00:00:00 2001 From: George-Zhang5246 <70183314+George-Zhang5246@users.noreply.github.com> Date: Thu, 7 Nov 2024 21:11:51 -0600 Subject: [PATCH 1/9] Changed all tables with rmp data changed tables with rmp data --- next-env.d.ts | 2 +- .../common/CompareTable/compareTable.tsx | 13 +++++++---- .../SearchResultsTable/searchResultsTable.tsx | 11 +++++---- .../common/SingleProfInfo/singleProfInfo.tsx | 23 +++++++++++++++++++ 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/next-env.d.ts b/next-env.d.ts index a4a7b3f5..4f11a03d 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/src/components/common/CompareTable/compareTable.tsx b/src/components/common/CompareTable/compareTable.tsx index 587c70d1..c10da18e 100644 --- a/src/components/common/CompareTable/compareTable.tsx +++ b/src/components/common/CompareTable/compareTable.tsx @@ -205,11 +205,14 @@ function GradeAndRmpRow({ {loadingFiller} )) || - (rmp.state === 'done' && ( - - {getRmpValue(rmp.data as RMPInterface)} - - )) || + (rmp.state === 'done' && + getRmpValue(rmp.data as RMPInterface) == 0 && ) || + (rmp.state === 'done' && + getRmpValue(rmp.data as RMPInterface) != 0 && ( + + {getRmpValue(rmp.data as RMPInterface)} + + )) || null} ))} diff --git a/src/components/common/SearchResultsTable/searchResultsTable.tsx b/src/components/common/SearchResultsTable/searchResultsTable.tsx index 87408690..c9ce686b 100644 --- a/src/components/common/SearchResultsTable/searchResultsTable.tsx +++ b/src/components/common/SearchResultsTable/searchResultsTable.tsx @@ -203,7 +203,8 @@ function Row({ )) || - (rmp.state === 'done' && ( + (rmp.state === 'done' && rmp.data.numRatings == 0 && <>) || + (rmp.state === 'done' && rmp.data.numRatings != 0 && ( ); } + if (rmp.data.numRatings == 0) { + return ( + + +

+ {rmp.data.numRatings.toLocaleString()} +

+

Ratings given

+
+ + + Visit Rate My Professors + + +
+ ); + } return ( From c855a034c2fe393eb948180a740cf2e5b007403b Mon Sep 17 00:00:00 2001 From: AbhiramTadepalli Date: Sun, 10 Nov 2024 08:23:40 -0600 Subject: [PATCH 2/9] format --- src/components/common/CompareTable/compareTable.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/common/CompareTable/compareTable.tsx b/src/components/common/CompareTable/compareTable.tsx index e785bcce..e546fdb5 100644 --- a/src/components/common/CompareTable/compareTable.tsx +++ b/src/components/common/CompareTable/compareTable.tsx @@ -275,9 +275,11 @@ function GradeAndRmpRow({ )) || (rmp.state === 'done' && - getRmpValue(rmp.data as RMPInterface) == 0 && ) || - (rmp.state === 'done' && - getRmpValue(rmp.data as RMPInterface) != 0 && ( + getRmpValue(rmp.data as RMPInterface) == 0 && ( + + )) || + (rmp.state === 'done' && + getRmpValue(rmp.data as RMPInterface) != 0 && ( {rmpValue} From 10305471b357ca6e3cb007d1fcf802897ccc5b52 Mon Sep 17 00:00:00 2001 From: AbhiramTadepalli Date: Sun, 10 Nov 2024 08:37:04 -0600 Subject: [PATCH 3/9] Revert "format" This reverts commit c855a034c2fe393eb948180a740cf2e5b007403b. --- src/components/common/CompareTable/compareTable.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/components/common/CompareTable/compareTable.tsx b/src/components/common/CompareTable/compareTable.tsx index e546fdb5..e785bcce 100644 --- a/src/components/common/CompareTable/compareTable.tsx +++ b/src/components/common/CompareTable/compareTable.tsx @@ -275,11 +275,9 @@ function GradeAndRmpRow({ )) || (rmp.state === 'done' && - getRmpValue(rmp.data as RMPInterface) == 0 && ( - - )) || - (rmp.state === 'done' && - getRmpValue(rmp.data as RMPInterface) != 0 && ( + getRmpValue(rmp.data as RMPInterface) == 0 && ) || + (rmp.state === 'done' && + getRmpValue(rmp.data as RMPInterface) != 0 && ( {rmpValue} From f241e9ce445fd6121fab166aadb4553369706b8b Mon Sep 17 00:00:00 2001 From: AbhiramTadepalli Date: Sun, 10 Nov 2024 08:37:10 -0600 Subject: [PATCH 4/9] Revert "Merge branch 'develop' into 288-bug-handle-null-rmp-data" This reverts commit a6f273edebb070b8d8a2e6dc00470e290eb6016c, reversing changes made to 7a09c54fb87a52268c64e22b9f15ff4039c56281. --- README.md | 49 ++-- src/components/common/Carousel/carousel.tsx | 4 +- src/components/common/Compare/compare.tsx | 10 +- .../common/CompareTable/compareTable.tsx | 221 ++++++------------ .../common/GitHubButton/gitHubButton.tsx | 39 ++-- src/components/common/SearchBar/searchBar.tsx | 4 - .../SearchResultsTable/searchResultsTable.tsx | 37 +-- .../navigation/tabNavMenu/tabNavMenu.tsx | 14 +- src/pages/_app.tsx | 29 ++- src/pages/dashboard/index.tsx | 76 ++---- src/pages/index.tsx | 15 +- 11 files changed, 192 insertions(+), 306 deletions(-) diff --git a/README.md b/README.md index c9759816..4fcb2262 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# UTD Trends +# UTD-Trends -_Easy access to all the information you need to plan your schedule_ +_UTD-Trends a data visualization tool built to help students view historical course and section data using the Nebula API_ [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) @@ -8,19 +8,31 @@ _Easy access to all the information you need to plan your schedule_ ### Overview -UTD Trends offers students and faculty an accessible and easily digestible means -of viewing the data stored in the Nebula API and on Rate My Professors. Providing -data visualization tools so that students can view agregated data and make more -informed decisions on their coursework. +UTD-Trends offers students and faculty an accessible and easily digestible means +of viewing the data stored in the Nebula API. This front-end for the API offers +data visualization tools so that students can view agregated data and make more informed +decisions on their coursework. + +### Inspiration + +For years the students of UTD have made use of the UTD Grades tool to access +information about their coursework in conjunction with other web applications like +Rate My Professor. + +Now Project Nebula hopes to offer students a comprehensive view of course information +all in a single application through Project UTD-Trends. The hope is to offer students an all +in one experience and streamline the data gathering experience of students while providing +better data gathered through UTD specific sources rather than the crowd sourcing of other sites. + +UTD-Trends hopes to offer more tooling to students than previously available and build upon the +successes of UTD Grades to enhance the student experience. ### Features -- Multiple Sources - - Find grade distributions and Rate My Professors scores for any given class. -- Aggregate - - Powerful query abilities that aggregate grade and Rate My Professors data across several years to give you a more wholistic view. -- Compare - - See data for multiple courses, professors, and categories on a single graph without switching tabs. +- Data Visualizations for the Nebula API +- Easy searchability and result filtering +- Section comparison +- Multi-metric evaluations on course performance ## Contributing @@ -33,11 +45,14 @@ This project uses the MIT License. To get started, see the [contribution guide](./CONTRIBUTING.md). It'll tell you everything you need to know. +Additionally, see the Project Nebula-wide contributors [guide](https://about.utdnebula.com/) +for more info. + Once you're ready to make some changes, see the -[issues](https://github.com/UTDNebula/utd-trends/issues) for the repository. +[issues](https://github.com/UTDNebula/UTD-Trends/issues) for the repository. If you want to brainstorm, share ideas or ask questions, start a discussion in -our [Discord](https://discord.utdnebula.com/) section. +the [Discussions](https://github.com/UTDNebula/UTD-Trends/discussions) section. ### Set-up @@ -46,8 +61,8 @@ installation. To start, clone the repository, and then run `npm run dev` to laun a local development server at [`localhost:3000`](https://localhost:3000) by default. ```bash -git clone https://github.com/UTDNebula/utd-trends.git -cd utd-Trends +git clone https://github.com/UTDNebula/UTD-Trends.git +cd UTD-Trends npm install npm run dev ``` @@ -55,4 +70,4 @@ npm run dev ### Contact This project is maintained by Nebula Labs. If you have -any questions about this project or Nebula Labs, see the [discord server](https://discord.utdnebula.com/) +any questions about this project or Nebula Labs, see the [discord server](https://discord.gg/3p4H44zjTt) diff --git a/src/components/common/Carousel/carousel.tsx b/src/components/common/Carousel/carousel.tsx index 0b1401d6..8c2c9c70 100644 --- a/src/components/common/Carousel/carousel.tsx +++ b/src/components/common/Carousel/carousel.tsx @@ -7,7 +7,6 @@ import { TabNavMenu } from '../../navigation/tabNavMenu/tabNavMenu'; interface CarouselProps { names: string[] | string; children: ReactJSXElement[] | ReactJSXElement; - compareLength: number; } /** @@ -39,7 +38,7 @@ const variants = { * @param props the props passed from the parent component * @returns */ -const Carousel = ({ names, children, compareLength }: CarouselProps) => { +const Carousel = ({ names, children }: CarouselProps) => { // The card currently being displayed const [currentCard, setCurrentCard] = useState(0); // The Direction that the card is moving in @@ -75,7 +74,6 @@ const Carousel = ({ names, children, compareLength }: CarouselProps) => { value={currentCard} options={Array.isArray(names) ? names : [names]} turner={turn} - compareLength={compareLength} />
diff --git a/src/components/common/Compare/compare.tsx b/src/components/common/Compare/compare.tsx index f8b86647..e2701eb1 100644 --- a/src/components/common/Compare/compare.tsx +++ b/src/components/common/Compare/compare.tsx @@ -15,7 +15,6 @@ type CompareProps = { grades: { [key: string]: GenericFetchedData }; rmp: { [key: string]: GenericFetchedData }; removeFromCompare: { (arg0: SearchQuery): void }; - colorMap: { [key: string]: string }; }; function convertNumbersToPercents(distribution: GradesType): number[] { @@ -25,13 +24,7 @@ function convertNumbersToPercents(distribution: GradesType): number[] { ); } -const Compare = ({ - courses, - grades, - rmp, - removeFromCompare, - colorMap, -}: CompareProps) => { +const Compare = ({ courses, grades, rmp, removeFromCompare }: CompareProps) => { if (courses.length === 0) { return

Click a checkbox to add something to compare.

; } @@ -97,7 +90,6 @@ const Compare = ({ grades={grades} rmp={rmp} removeFromCompare={removeFromCompare} - colorMap={colorMap} />
); diff --git a/src/components/common/CompareTable/compareTable.tsx b/src/components/common/CompareTable/compareTable.tsx index e785bcce..c10da18e 100644 --- a/src/components/common/CompareTable/compareTable.tsx +++ b/src/components/common/CompareTable/compareTable.tsx @@ -8,7 +8,6 @@ import { TableContainer, TableHead, TableRow, - Tooltip, Typography, } from '@mui/material'; import React, { useState } from 'react'; @@ -16,6 +15,7 @@ import React, { useState } from 'react'; import SearchQuery, { convertToProfOnly, } from '../../../modules/SearchQuery/SearchQuery'; +import searchQueryColors from '../../../modules/searchQueryColors/searchQueryColors'; import searchQueryLabel from '../../../modules/searchQueryLabel/searchQueryLabel'; import type { RMPInterface } from '../../../pages/api/ratemyprofessorScraper'; import type { @@ -82,12 +82,6 @@ function GradeOrRmpRow({ handleClick, defaultAscSort, }: GradeOrRmpRowProps) { - const tooltipTitles: { [key: string]: string } = { - GPA: 'Sort by GPA', - Rating: 'Sort by Rating', - 'Would Take Again': 'Sort by Would Take Again %', - Difficulty: 'Sort by Difficulty', - }; return ( @@ -103,26 +97,7 @@ function GradeOrRmpRow({ }, }} > - {tooltipTitles[name] ? ( - - {name} - - ) : ( - name - )} + {name} {values.map((value, index) => ( @@ -144,26 +119,21 @@ function GradeOrRmpRow({ )) || (value.state === 'done' && getValue(value.data) !== -1 && ( - - - {/*value.data is all the data past the state of loading, done, or error. + {/*value.data is all the data past the state of loading, done, or error. getValue returns the specific value from the data structure, like gpa. formatValue makes it look pretty like 3.7216373 displaying as 3.72.*/} - {formatValue(getValue(value.data))} - - + {formatValue(getValue(value.data))} + )) || null} @@ -196,101 +166,60 @@ function GradeAndRmpRow({ return ( - - {name} - + {name} {gradeValues - // Combine values + // combine values .map((x, i) => [x, rmpValues[i]]) // so ts can remember the type of rmp (which it can't do for rmpValues[index]) and know's that when its state is done, you can access its data value - .map(([grade, rmp], index) => { - const gradeValue = - typeof grade !== 'undefined' && grade.state === 'done' - ? getGradeValue(grade.data as GradesType) - : null; - const rmpValue = - typeof rmp !== 'undefined' && rmp.state === 'done' - ? getRmpValue(rmp.data as RMPInterface) - : null; - - return ( - - - - {((typeof grade === 'undefined' || - grade.state === 'error') && ) || - (grade.state === 'loading' && ( - - - {loadingFiller} - - - )) || - (grade.state === 'done' && ( - - {gradeValue} - - )) || - null} - {' / '} - {((typeof rmp === 'undefined' || rmp.state === 'error') && ( - - )) || - (rmp.state === 'loading' && ( - - - {loadingFiller} - - - )) || - (rmp.state === 'done' && + .map(([grade, rmp], index) => ( + + {((typeof grade === 'undefined' || grade.state === 'error') && ( + + )) || + (grade.state === 'loading' && ( + + {loadingFiller} + + )) || + (grade.state === 'done' && ( + + {getGradeValue(grade.data as GradesType)} + + )) || + null} + {' / '} + {((typeof rmp === 'undefined' || rmp.state === 'error') && ( + + )) || + (rmp.state === 'loading' && ( + + {loadingFiller} + + )) || + (rmp.state === 'done' && getRmpValue(rmp.data as RMPInterface) == 0 && ) || (rmp.state === 'done' && getRmpValue(rmp.data as RMPInterface) != 0 && ( - - {rmpValue} - - )) || - null} - - - - ); - })} + + {getRmpValue(rmp.data as RMPInterface)} + + )) || + null} + + ))} ); } + type CheckboxRowProps = { name: string; courses: SearchQuery[]; @@ -340,19 +269,17 @@ function CheckboxRow({ backgroundColor: colors[index] + '10', // add transparency }} > - - { - removeFromCompare(course); - }} - sx={{ - '&.Mui-checked': { - color: colors[index], - }, - }} //Colored Checkbox based on graph - /> - + { + removeFromCompare(course); + }} + sx={{ + '&.Mui-checked': { + color: colors[index], + }, + }} //Colored Checkbox based on graph + /> ))} @@ -364,7 +291,6 @@ type CompareTableProps = { grades: { [key: string]: GenericFetchedData }; rmp: { [key: string]: GenericFetchedData }; removeFromCompare: (arg0: SearchQuery) => void; - colorMap: { [key: string]: string }; }; const CompareTable = ({ @@ -372,7 +298,6 @@ const CompareTable = ({ grades, rmp, removeFromCompare, - colorMap, }: CompareTableProps) => { //Table sorting category const [orderBy, setOrderBy] = useState('Color'); @@ -466,7 +391,12 @@ const CompareTable = ({ return 0; }); - // Update mappedColors to use the passed colorMap + // Color map for each course in the compare table based on searchQueryColors + const colorMap: { [key: string]: string } = {}; + includedResults.forEach((result, index) => { + colorMap[searchQueryLabel(result)] = + searchQueryColors[index % searchQueryColors.length]; + }); const mappedColors = sortedResults.map( (result) => colorMap[searchQueryLabel(result)], ); @@ -516,7 +446,6 @@ const CompareTable = ({ order={order} handleClick={handleClick} /> - name="Rating" values={sortedResults.map( diff --git a/src/components/common/GitHubButton/gitHubButton.tsx b/src/components/common/GitHubButton/gitHubButton.tsx index 4ccc1519..6c915071 100644 --- a/src/components/common/GitHubButton/gitHubButton.tsx +++ b/src/components/common/GitHubButton/gitHubButton.tsx @@ -1,8 +1,11 @@ import GitHub from '@mui/icons-material/GitHub'; -import { IconButton, Tooltip } from '@mui/material'; +import { Card, IconButton, Tooltip, useMediaQuery } from '@mui/material'; import React from 'react'; export default function GitHubButton() { + const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)'); + const cardElevation = prefersDarkMode ? 3 : 1; + const showGitInfo = typeof process.env.NEXT_PUBLIC_VERCEL_ENV !== 'undefined' && process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview' && @@ -14,20 +17,24 @@ export default function GitHubButton() { } return ( - - - - - - - + + + + + + + + + ); } diff --git a/src/components/common/SearchBar/searchBar.tsx b/src/components/common/SearchBar/searchBar.tsx index 5f6dc9ba..5499fe80 100644 --- a/src/components/common/SearchBar/searchBar.tsx +++ b/src/components/common/SearchBar/searchBar.tsx @@ -18,7 +18,6 @@ interface SearchProps { onSelect?: (value: SearchQuery[]) => void; className?: string; input_className?: string; - autoFocus?: boolean; } /** @@ -33,7 +32,6 @@ const SearchBar = ({ onSelect, className, input_className, - autoFocus, }: SearchProps) => { //what you can choose from const [options, setOptions] = useState([]); @@ -264,8 +262,6 @@ const SearchBar = ({ variant="outlined" className={input_className} placeholder="ex. GOVT 2306" - //eslint-disable-next-line jsx-a11y/no-autofocus - autoFocus={autoFocus} /> ); }} diff --git a/src/components/common/SearchResultsTable/searchResultsTable.tsx b/src/components/common/SearchResultsTable/searchResultsTable.tsx index a26cbd7f..c9ce686b 100644 --- a/src/components/common/SearchResultsTable/searchResultsTable.tsx +++ b/src/components/common/SearchResultsTable/searchResultsTable.tsx @@ -84,7 +84,6 @@ type RowProps = { inCompare: boolean; addToCompare: (arg0: SearchQuery) => void; removeFromCompare: (arg0: SearchQuery) => void; - color?: string; }; function Row({ @@ -94,7 +93,6 @@ function Row({ inCompare, addToCompare, removeFromCompare, - color, }: RowProps) { const [open, setOpen] = useState(false); @@ -119,7 +117,6 @@ function Row({ setOpen(!open)} // opens/closes the card by clicking anywhere on the row sx={{ '& > *': { borderBottom: 'unset' } }} - className="cursor-pointer" > - + e.stopPropagation() // prevents opening/closing the card when clicking on the compare checkbox + } + > { - e.stopPropagation(); // prevents opening/closing the card when clicking on the compare checkbox + onClick={() => { if (inCompare) { removeFromCompare(course); } else { @@ -155,25 +155,11 @@ function Row({ (typeof grades !== 'undefined' && grades.state === 'loading') || (typeof rmp !== 'undefined' && rmp.state === 'loading') } - sx={ - color - ? { - '&.Mui-checked': { - color: color, - }, - } - : undefined - } // Apply color if defined /> - e.stopPropagation() // prevents opening/closing the card when clicking on the text - } - className="leading-tight text-lg text-gray-600 dark:text-gray-200 cursor-text" - > + {searchQueryLabel(course) + ((typeof course.profFirst === 'undefined' && typeof course.profLast === 'undefined') || @@ -201,7 +187,7 @@ function Row({ placement="top" > {gpaToLetterGrade(grades.data.gpa)} @@ -258,7 +244,6 @@ type SearchResultsTableProps = { compare: SearchQuery[]; addToCompare: (arg0: SearchQuery) => void; removeFromCompare: (arg0: SearchQuery) => void; - colorMap: { [key: string]: string }; }; const SearchResultsTable = ({ @@ -269,7 +254,6 @@ const SearchResultsTable = ({ compare, addToCompare, removeFromCompare, - colorMap, }: SearchResultsTableProps) => { //Table sorting category const [orderBy, setOrderBy] = useState<'name' | 'gpa' | 'rating'>('name'); @@ -455,7 +439,7 @@ const SearchResultsTable = ({ Name - + - + )) : Array(10) diff --git a/src/components/navigation/tabNavMenu/tabNavMenu.tsx b/src/components/navigation/tabNavMenu/tabNavMenu.tsx index f75a10a0..f8e13b98 100644 --- a/src/components/navigation/tabNavMenu/tabNavMenu.tsx +++ b/src/components/navigation/tabNavMenu/tabNavMenu.tsx @@ -1,4 +1,4 @@ -import { Badge, Tab, Tabs } from '@mui/material'; +import { Tab, Tabs } from '@mui/material'; import React from 'react'; /** @@ -10,7 +10,6 @@ type TabNavMenuProps = { // responsible for playing the animation and setting the value to the correct new value turner: (displacement: number) => void; options: string[]; - compareLength: number; }; /** @@ -28,19 +27,10 @@ export const TabNavMenu = (props: TabNavMenuProps) => { > {props.options.map((option, index) => ( - {option} - - - ) : ( - option - ) - } /> ))} diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index d141e6ba..d0ddd218 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,6 +1,7 @@ import '../styles/globals.css'; -import { useMediaQuery } from '@mui/material'; +import GitHub from '@mui/icons-material/GitHub'; +import { Card, IconButton, Tooltip, useMediaQuery } from '@mui/material'; import { createTheme, ThemeProvider } from '@mui/material/styles'; import { GoogleAnalytics } from '@next/third-parties/google'; import { Analytics } from '@vercel/analytics/react'; @@ -98,6 +99,12 @@ function MyApp({ Component, pageProps }: AppProps) { }, }); + const showGitInfo = + typeof process.env.NEXT_PUBLIC_VERCEL_ENV !== 'undefined' && + process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview' && + typeof process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA !== 'undefined' && + process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA !== ''; + const router = useRouter(); return ( @@ -141,6 +148,26 @@ function MyApp({ Component, pageProps }: AppProps) { + {showGitInfo && ( + <> + + + + + + + + + + + )} ); } diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index 1e873e62..46da9a4b 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -21,7 +21,6 @@ import fetchWithCache, { } from '../../modules/fetchWithCache'; import type SearchQuery from '../../modules/SearchQuery/SearchQuery'; import { convertToProfOnly } from '../../modules/SearchQuery/SearchQuery'; -import searchQueryColors from '../../modules/searchQueryColors/searchQueryColors'; import searchQueryEqual from '../../modules/searchQueryEqual/searchQueryEqual'; import searchQueryLabel from '../../modules/searchQueryLabel/searchQueryLabel'; import type { GradesData } from '../../pages/api/grades'; @@ -229,16 +228,6 @@ function fetchRmpData( }); } -// Add this utility function after the existing type definitions -function createColorMap(courses: SearchQuery[]): { [key: string]: string } { - const colorMap: { [key: string]: string } = {}; - courses.forEach((course, index) => { - colorMap[searchQueryLabel(course)] = - searchQueryColors[index % searchQueryColors.length]; - }); - return colorMap; -} - export const Dashboard: NextPage = () => { const router = useRouter(); @@ -292,15 +281,23 @@ export const Dashboard: NextPage = () => { //Get course/prof info if (courseSearchTerms.length === 1) { - if (!(searchQueryLabel(courseSearchTerms[0]) in rhsGrades.course)) { - fetchAndAddRHSGrades(courseSearchTerms[0], controller); + if ( + typeof grades[searchQueryLabel(courseSearchTerms[0])] === 'undefined' + ) { + fetchAndStoreGradesData(courseSearchTerms[0], controller); } } if (professorSearchTerms.length === 1) { if ( - !(searchQueryLabel(professorSearchTerms[0]) in rhsGrades.professor) + typeof grades[searchQueryLabel(professorSearchTerms[0])] === + 'undefined' + ) { + fetchAndStoreGradesData(professorSearchTerms[0], controller); + } + if ( + typeof rmp[searchQueryLabel(professorSearchTerms[0])] === 'undefined' ) { - fetchAndAddRHSGrades(professorSearchTerms[0], controller); + fetchAndStoreRmpData(professorSearchTerms[0], controller); } } @@ -353,7 +350,9 @@ export const Dashboard: NextPage = () => { //Relavent keys for (const result of [ ...(results.state === 'done' ? results.data : []), - ]) { + ] + .concat(courses.length === 1 ? courses[0] : []) + .concat(professors.length === 1 ? professors[0] : [])) { const entry = grades[searchQueryLabel(result)]; if (entry && entry.state === 'done') { entry.data = { @@ -443,38 +442,6 @@ export const Dashboard: NextPage = () => { return newVal; }); } - - // holds data for course and professor overviews - type rhsGradesType = { [key: string]: GenericFetchedData }; - const [rhsGrades, setRHSGrades] = useState<{ - course: rhsGradesType; - professor: rhsGradesType; - }>({ course: {}, professor: {} }); - function fetchAndAddRHSGrades( - query: SearchQuery, - controller: AbortController, - ) { - const rhsKey = searchQueryLabel(query); - // only update course on course query or vice versa - const isCourse = typeof query.prefix !== 'undefined'; - setRHSGrades((old) => ({ - course: isCourse ? { [rhsKey]: { state: 'loading' } } : old.course, - professor: isCourse ? old.professor : { [rhsKey]: { state: 'loading' } }, - })); - fetchGradesData(query, controller) - .then((rhsGrade) => { - const rhsGradeFetched: GenericFetchedData = { - state: rhsGrade.gpa !== -1 ? 'done' : 'error', - data: rhsGrade, - }; - setRHSGrades((old) => ({ - course: isCourse ? { [rhsKey]: rhsGradeFetched } : old.course, - professor: isCourse ? old.professor : { [rhsKey]: rhsGradeFetched }, - })); - }) - .catch((err) => console.error('Grades data for ' + rhsKey, err)); - } - //Store rmp scores by profs const [rmp, setRmp] = useState<{ [key: string]: GenericFetchedData; @@ -712,9 +679,6 @@ export const Dashboard: NextPage = () => { } } - // Add this after the compare state declaration - const colorMap = createColorMap(compare); - //Main content: loading, error, or normal let contentComponent; @@ -732,7 +696,7 @@ export const Dashboard: NextPage = () => { , ); @@ -743,7 +707,7 @@ export const Dashboard: NextPage = () => { , ); } @@ -755,7 +719,6 @@ export const Dashboard: NextPage = () => { grades={compareGrades} rmp={compareRmp} removeFromCompare={removeFromCompare} - colorMap={colorMap} />, ); contentComponent = ( @@ -781,15 +744,12 @@ export const Dashboard: NextPage = () => { compare={compare} addToCompare={addToCompare} removeFromCompare={removeFromCompare} - colorMap={colorMap} />
- - {tabs} - + {tabs}
diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 8b9e3105..750416d1 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -50,12 +50,12 @@ const Home: NextPage = () => { />

- POWERED BY {/*eslint-disable-next-line react/jsx-no-target-blank*/} + POWERED BY{' '} NEBULA LABS @@ -68,22 +68,11 @@ const Home: NextPage = () => { find the perfect class.

- {/*eslint-disable-next-line react/jsx-no-target-blank*/} - - Also check out UTD Grades - ); From 3e4380fb44c37a8d997f91a241085726c204a35b Mon Sep 17 00:00:00 2001 From: AbhiramTadepalli Date: Sun, 10 Nov 2024 09:08:25 -0600 Subject: [PATCH 5/9] Reapply "Merge branch 'develop' into 288-bug-handle-null-rmp-data" This reverts commit f241e9ce445fd6121fab166aadb4553369706b8b. --- README.md | 49 ++-- src/components/common/Carousel/carousel.tsx | 4 +- src/components/common/Compare/compare.tsx | 10 +- .../common/CompareTable/compareTable.tsx | 221 ++++++++++++------ .../common/GitHubButton/gitHubButton.tsx | 39 ++-- src/components/common/SearchBar/searchBar.tsx | 4 + .../SearchResultsTable/searchResultsTable.tsx | 37 ++- .../navigation/tabNavMenu/tabNavMenu.tsx | 14 +- src/pages/_app.tsx | 29 +-- src/pages/dashboard/index.tsx | 76 ++++-- src/pages/index.tsx | 15 +- 11 files changed, 306 insertions(+), 192 deletions(-) diff --git a/README.md b/README.md index 4fcb2262..c9759816 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# UTD-Trends +# UTD Trends -_UTD-Trends a data visualization tool built to help students view historical course and section data using the Nebula API_ +_Easy access to all the information you need to plan your schedule_ [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) @@ -8,31 +8,19 @@ _UTD-Trends a data visualization tool built to help students view historical cou ### Overview -UTD-Trends offers students and faculty an accessible and easily digestible means -of viewing the data stored in the Nebula API. This front-end for the API offers -data visualization tools so that students can view agregated data and make more informed -decisions on their coursework. - -### Inspiration - -For years the students of UTD have made use of the UTD Grades tool to access -information about their coursework in conjunction with other web applications like -Rate My Professor. - -Now Project Nebula hopes to offer students a comprehensive view of course information -all in a single application through Project UTD-Trends. The hope is to offer students an all -in one experience and streamline the data gathering experience of students while providing -better data gathered through UTD specific sources rather than the crowd sourcing of other sites. - -UTD-Trends hopes to offer more tooling to students than previously available and build upon the -successes of UTD Grades to enhance the student experience. +UTD Trends offers students and faculty an accessible and easily digestible means +of viewing the data stored in the Nebula API and on Rate My Professors. Providing +data visualization tools so that students can view agregated data and make more +informed decisions on their coursework. ### Features -- Data Visualizations for the Nebula API -- Easy searchability and result filtering -- Section comparison -- Multi-metric evaluations on course performance +- Multiple Sources + - Find grade distributions and Rate My Professors scores for any given class. +- Aggregate + - Powerful query abilities that aggregate grade and Rate My Professors data across several years to give you a more wholistic view. +- Compare + - See data for multiple courses, professors, and categories on a single graph without switching tabs. ## Contributing @@ -45,14 +33,11 @@ This project uses the MIT License. To get started, see the [contribution guide](./CONTRIBUTING.md). It'll tell you everything you need to know. -Additionally, see the Project Nebula-wide contributors [guide](https://about.utdnebula.com/) -for more info. - Once you're ready to make some changes, see the -[issues](https://github.com/UTDNebula/UTD-Trends/issues) for the repository. +[issues](https://github.com/UTDNebula/utd-trends/issues) for the repository. If you want to brainstorm, share ideas or ask questions, start a discussion in -the [Discussions](https://github.com/UTDNebula/UTD-Trends/discussions) section. +our [Discord](https://discord.utdnebula.com/) section. ### Set-up @@ -61,8 +46,8 @@ installation. To start, clone the repository, and then run `npm run dev` to laun a local development server at [`localhost:3000`](https://localhost:3000) by default. ```bash -git clone https://github.com/UTDNebula/UTD-Trends.git -cd UTD-Trends +git clone https://github.com/UTDNebula/utd-trends.git +cd utd-Trends npm install npm run dev ``` @@ -70,4 +55,4 @@ npm run dev ### Contact This project is maintained by Nebula Labs. If you have -any questions about this project or Nebula Labs, see the [discord server](https://discord.gg/3p4H44zjTt) +any questions about this project or Nebula Labs, see the [discord server](https://discord.utdnebula.com/) diff --git a/src/components/common/Carousel/carousel.tsx b/src/components/common/Carousel/carousel.tsx index 8c2c9c70..0b1401d6 100644 --- a/src/components/common/Carousel/carousel.tsx +++ b/src/components/common/Carousel/carousel.tsx @@ -7,6 +7,7 @@ import { TabNavMenu } from '../../navigation/tabNavMenu/tabNavMenu'; interface CarouselProps { names: string[] | string; children: ReactJSXElement[] | ReactJSXElement; + compareLength: number; } /** @@ -38,7 +39,7 @@ const variants = { * @param props the props passed from the parent component * @returns */ -const Carousel = ({ names, children }: CarouselProps) => { +const Carousel = ({ names, children, compareLength }: CarouselProps) => { // The card currently being displayed const [currentCard, setCurrentCard] = useState(0); // The Direction that the card is moving in @@ -74,6 +75,7 @@ const Carousel = ({ names, children }: CarouselProps) => { value={currentCard} options={Array.isArray(names) ? names : [names]} turner={turn} + compareLength={compareLength} />
diff --git a/src/components/common/Compare/compare.tsx b/src/components/common/Compare/compare.tsx index e2701eb1..f8b86647 100644 --- a/src/components/common/Compare/compare.tsx +++ b/src/components/common/Compare/compare.tsx @@ -15,6 +15,7 @@ type CompareProps = { grades: { [key: string]: GenericFetchedData }; rmp: { [key: string]: GenericFetchedData }; removeFromCompare: { (arg0: SearchQuery): void }; + colorMap: { [key: string]: string }; }; function convertNumbersToPercents(distribution: GradesType): number[] { @@ -24,7 +25,13 @@ function convertNumbersToPercents(distribution: GradesType): number[] { ); } -const Compare = ({ courses, grades, rmp, removeFromCompare }: CompareProps) => { +const Compare = ({ + courses, + grades, + rmp, + removeFromCompare, + colorMap, +}: CompareProps) => { if (courses.length === 0) { return

Click a checkbox to add something to compare.

; } @@ -90,6 +97,7 @@ const Compare = ({ courses, grades, rmp, removeFromCompare }: CompareProps) => { grades={grades} rmp={rmp} removeFromCompare={removeFromCompare} + colorMap={colorMap} />
); diff --git a/src/components/common/CompareTable/compareTable.tsx b/src/components/common/CompareTable/compareTable.tsx index c10da18e..e785bcce 100644 --- a/src/components/common/CompareTable/compareTable.tsx +++ b/src/components/common/CompareTable/compareTable.tsx @@ -8,6 +8,7 @@ import { TableContainer, TableHead, TableRow, + Tooltip, Typography, } from '@mui/material'; import React, { useState } from 'react'; @@ -15,7 +16,6 @@ import React, { useState } from 'react'; import SearchQuery, { convertToProfOnly, } from '../../../modules/SearchQuery/SearchQuery'; -import searchQueryColors from '../../../modules/searchQueryColors/searchQueryColors'; import searchQueryLabel from '../../../modules/searchQueryLabel/searchQueryLabel'; import type { RMPInterface } from '../../../pages/api/ratemyprofessorScraper'; import type { @@ -82,6 +82,12 @@ function GradeOrRmpRow({ handleClick, defaultAscSort, }: GradeOrRmpRowProps) { + const tooltipTitles: { [key: string]: string } = { + GPA: 'Sort by GPA', + Rating: 'Sort by Rating', + 'Would Take Again': 'Sort by Would Take Again %', + Difficulty: 'Sort by Difficulty', + }; return ( @@ -97,7 +103,26 @@ function GradeOrRmpRow({ }, }} > - {name} + {tooltipTitles[name] ? ( + + {name} + + ) : ( + name + )} {values.map((value, index) => ( @@ -119,21 +144,26 @@ function GradeOrRmpRow({ )) || (value.state === 'done' && getValue(value.data) !== -1 && ( - - {/*value.data is all the data past the state of loading, done, or error. + + {/*value.data is all the data past the state of loading, done, or error. getValue returns the specific value from the data structure, like gpa. formatValue makes it look pretty like 3.7216373 displaying as 3.72.*/} - {formatValue(getValue(value.data))} - + {formatValue(getValue(value.data))} + +
)) || null} @@ -166,60 +196,101 @@ function GradeAndRmpRow({ return ( - {name} + + {name} + {gradeValues - // combine values + // Combine values .map((x, i) => [x, rmpValues[i]]) // so ts can remember the type of rmp (which it can't do for rmpValues[index]) and know's that when its state is done, you can access its data value - .map(([grade, rmp], index) => ( - - {((typeof grade === 'undefined' || grade.state === 'error') && ( - - )) || - (grade.state === 'loading' && ( - - {loadingFiller} - - )) || - (grade.state === 'done' && ( - - {getGradeValue(grade.data as GradesType)} - - )) || - null} - {' / '} - {((typeof rmp === 'undefined' || rmp.state === 'error') && ( - - )) || - (rmp.state === 'loading' && ( - - {loadingFiller} - - )) || - (rmp.state === 'done' && + .map(([grade, rmp], index) => { + const gradeValue = + typeof grade !== 'undefined' && grade.state === 'done' + ? getGradeValue(grade.data as GradesType) + : null; + const rmpValue = + typeof rmp !== 'undefined' && rmp.state === 'done' + ? getRmpValue(rmp.data as RMPInterface) + : null; + + return ( + + + + {((typeof grade === 'undefined' || + grade.state === 'error') && ) || + (grade.state === 'loading' && ( + + + {loadingFiller} + + + )) || + (grade.state === 'done' && ( + + {gradeValue} + + )) || + null} + {' / '} + {((typeof rmp === 'undefined' || rmp.state === 'error') && ( + + )) || + (rmp.state === 'loading' && ( + + + {loadingFiller} + + + )) || + (rmp.state === 'done' && getRmpValue(rmp.data as RMPInterface) == 0 && ) || (rmp.state === 'done' && getRmpValue(rmp.data as RMPInterface) != 0 && ( - - {getRmpValue(rmp.data as RMPInterface)} - - )) || - null} - - ))} + + {rmpValue} + + )) || + null} + + + + ); + })} ); } - type CheckboxRowProps = { name: string; courses: SearchQuery[]; @@ -269,17 +340,19 @@ function CheckboxRow({ backgroundColor: colors[index] + '10', // add transparency }} > - { - removeFromCompare(course); - }} - sx={{ - '&.Mui-checked': { - color: colors[index], - }, - }} //Colored Checkbox based on graph - /> + + { + removeFromCompare(course); + }} + sx={{ + '&.Mui-checked': { + color: colors[index], + }, + }} //Colored Checkbox based on graph + /> + ))} @@ -291,6 +364,7 @@ type CompareTableProps = { grades: { [key: string]: GenericFetchedData }; rmp: { [key: string]: GenericFetchedData }; removeFromCompare: (arg0: SearchQuery) => void; + colorMap: { [key: string]: string }; }; const CompareTable = ({ @@ -298,6 +372,7 @@ const CompareTable = ({ grades, rmp, removeFromCompare, + colorMap, }: CompareTableProps) => { //Table sorting category const [orderBy, setOrderBy] = useState('Color'); @@ -391,12 +466,7 @@ const CompareTable = ({ return 0; }); - // Color map for each course in the compare table based on searchQueryColors - const colorMap: { [key: string]: string } = {}; - includedResults.forEach((result, index) => { - colorMap[searchQueryLabel(result)] = - searchQueryColors[index % searchQueryColors.length]; - }); + // Update mappedColors to use the passed colorMap const mappedColors = sortedResults.map( (result) => colorMap[searchQueryLabel(result)], ); @@ -446,6 +516,7 @@ const CompareTable = ({ order={order} handleClick={handleClick} /> + name="Rating" values={sortedResults.map( diff --git a/src/components/common/GitHubButton/gitHubButton.tsx b/src/components/common/GitHubButton/gitHubButton.tsx index 6c915071..4ccc1519 100644 --- a/src/components/common/GitHubButton/gitHubButton.tsx +++ b/src/components/common/GitHubButton/gitHubButton.tsx @@ -1,11 +1,8 @@ import GitHub from '@mui/icons-material/GitHub'; -import { Card, IconButton, Tooltip, useMediaQuery } from '@mui/material'; +import { IconButton, Tooltip } from '@mui/material'; import React from 'react'; export default function GitHubButton() { - const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)'); - const cardElevation = prefersDarkMode ? 3 : 1; - const showGitInfo = typeof process.env.NEXT_PUBLIC_VERCEL_ENV !== 'undefined' && process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview' && @@ -17,24 +14,20 @@ export default function GitHubButton() { } return ( - - - - - - - - - + + + + + + + ); } diff --git a/src/components/common/SearchBar/searchBar.tsx b/src/components/common/SearchBar/searchBar.tsx index 5499fe80..5f6dc9ba 100644 --- a/src/components/common/SearchBar/searchBar.tsx +++ b/src/components/common/SearchBar/searchBar.tsx @@ -18,6 +18,7 @@ interface SearchProps { onSelect?: (value: SearchQuery[]) => void; className?: string; input_className?: string; + autoFocus?: boolean; } /** @@ -32,6 +33,7 @@ const SearchBar = ({ onSelect, className, input_className, + autoFocus, }: SearchProps) => { //what you can choose from const [options, setOptions] = useState([]); @@ -262,6 +264,8 @@ const SearchBar = ({ variant="outlined" className={input_className} placeholder="ex. GOVT 2306" + //eslint-disable-next-line jsx-a11y/no-autofocus + autoFocus={autoFocus} /> ); }} diff --git a/src/components/common/SearchResultsTable/searchResultsTable.tsx b/src/components/common/SearchResultsTable/searchResultsTable.tsx index c9ce686b..a26cbd7f 100644 --- a/src/components/common/SearchResultsTable/searchResultsTable.tsx +++ b/src/components/common/SearchResultsTable/searchResultsTable.tsx @@ -84,6 +84,7 @@ type RowProps = { inCompare: boolean; addToCompare: (arg0: SearchQuery) => void; removeFromCompare: (arg0: SearchQuery) => void; + color?: string; }; function Row({ @@ -93,6 +94,7 @@ function Row({ inCompare, addToCompare, removeFromCompare, + color, }: RowProps) { const [open, setOpen] = useState(false); @@ -117,6 +119,7 @@ function Row({ setOpen(!open)} // opens/closes the card by clicking anywhere on the row sx={{ '& > *': { borderBottom: 'unset' } }} + className="cursor-pointer" > - e.stopPropagation() // prevents opening/closing the card when clicking on the compare checkbox - } - > + { + onClick={(e) => { + e.stopPropagation(); // prevents opening/closing the card when clicking on the compare checkbox if (inCompare) { removeFromCompare(course); } else { @@ -155,11 +155,25 @@ function Row({ (typeof grades !== 'undefined' && grades.state === 'loading') || (typeof rmp !== 'undefined' && rmp.state === 'loading') } + sx={ + color + ? { + '&.Mui-checked': { + color: color, + }, + } + : undefined + } // Apply color if defined /> - + e.stopPropagation() // prevents opening/closing the card when clicking on the text + } + className="leading-tight text-lg text-gray-600 dark:text-gray-200 cursor-text" + > {searchQueryLabel(course) + ((typeof course.profFirst === 'undefined' && typeof course.profLast === 'undefined') || @@ -187,7 +201,7 @@ function Row({ placement="top" > {gpaToLetterGrade(grades.data.gpa)} @@ -244,6 +258,7 @@ type SearchResultsTableProps = { compare: SearchQuery[]; addToCompare: (arg0: SearchQuery) => void; removeFromCompare: (arg0: SearchQuery) => void; + colorMap: { [key: string]: string }; }; const SearchResultsTable = ({ @@ -254,6 +269,7 @@ const SearchResultsTable = ({ compare, addToCompare, removeFromCompare, + colorMap, }: SearchResultsTableProps) => { //Table sorting category const [orderBy, setOrderBy] = useState<'name' | 'gpa' | 'rating'>('name'); @@ -439,7 +455,7 @@ const SearchResultsTable = ({ Name - + - + )) : Array(10) diff --git a/src/components/navigation/tabNavMenu/tabNavMenu.tsx b/src/components/navigation/tabNavMenu/tabNavMenu.tsx index f8e13b98..f75a10a0 100644 --- a/src/components/navigation/tabNavMenu/tabNavMenu.tsx +++ b/src/components/navigation/tabNavMenu/tabNavMenu.tsx @@ -1,4 +1,4 @@ -import { Tab, Tabs } from '@mui/material'; +import { Badge, Tab, Tabs } from '@mui/material'; import React from 'react'; /** @@ -10,6 +10,7 @@ type TabNavMenuProps = { // responsible for playing the animation and setting the value to the correct new value turner: (displacement: number) => void; options: string[]; + compareLength: number; }; /** @@ -27,10 +28,19 @@ export const TabNavMenu = (props: TabNavMenuProps) => { > {props.options.map((option, index) => ( + {option} + + + ) : ( + option + ) + } /> ))} diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index d0ddd218..d141e6ba 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,7 +1,6 @@ import '../styles/globals.css'; -import GitHub from '@mui/icons-material/GitHub'; -import { Card, IconButton, Tooltip, useMediaQuery } from '@mui/material'; +import { useMediaQuery } from '@mui/material'; import { createTheme, ThemeProvider } from '@mui/material/styles'; import { GoogleAnalytics } from '@next/third-parties/google'; import { Analytics } from '@vercel/analytics/react'; @@ -99,12 +98,6 @@ function MyApp({ Component, pageProps }: AppProps) { }, }); - const showGitInfo = - typeof process.env.NEXT_PUBLIC_VERCEL_ENV !== 'undefined' && - process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview' && - typeof process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA !== 'undefined' && - process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA !== ''; - const router = useRouter(); return ( @@ -148,26 +141,6 @@ function MyApp({ Component, pageProps }: AppProps) { - {showGitInfo && ( - <> - - - - - - - - - - - )} ); } diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index 46da9a4b..1e873e62 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -21,6 +21,7 @@ import fetchWithCache, { } from '../../modules/fetchWithCache'; import type SearchQuery from '../../modules/SearchQuery/SearchQuery'; import { convertToProfOnly } from '../../modules/SearchQuery/SearchQuery'; +import searchQueryColors from '../../modules/searchQueryColors/searchQueryColors'; import searchQueryEqual from '../../modules/searchQueryEqual/searchQueryEqual'; import searchQueryLabel from '../../modules/searchQueryLabel/searchQueryLabel'; import type { GradesData } from '../../pages/api/grades'; @@ -228,6 +229,16 @@ function fetchRmpData( }); } +// Add this utility function after the existing type definitions +function createColorMap(courses: SearchQuery[]): { [key: string]: string } { + const colorMap: { [key: string]: string } = {}; + courses.forEach((course, index) => { + colorMap[searchQueryLabel(course)] = + searchQueryColors[index % searchQueryColors.length]; + }); + return colorMap; +} + export const Dashboard: NextPage = () => { const router = useRouter(); @@ -281,23 +292,15 @@ export const Dashboard: NextPage = () => { //Get course/prof info if (courseSearchTerms.length === 1) { - if ( - typeof grades[searchQueryLabel(courseSearchTerms[0])] === 'undefined' - ) { - fetchAndStoreGradesData(courseSearchTerms[0], controller); + if (!(searchQueryLabel(courseSearchTerms[0]) in rhsGrades.course)) { + fetchAndAddRHSGrades(courseSearchTerms[0], controller); } } if (professorSearchTerms.length === 1) { if ( - typeof grades[searchQueryLabel(professorSearchTerms[0])] === - 'undefined' - ) { - fetchAndStoreGradesData(professorSearchTerms[0], controller); - } - if ( - typeof rmp[searchQueryLabel(professorSearchTerms[0])] === 'undefined' + !(searchQueryLabel(professorSearchTerms[0]) in rhsGrades.professor) ) { - fetchAndStoreRmpData(professorSearchTerms[0], controller); + fetchAndAddRHSGrades(professorSearchTerms[0], controller); } } @@ -350,9 +353,7 @@ export const Dashboard: NextPage = () => { //Relavent keys for (const result of [ ...(results.state === 'done' ? results.data : []), - ] - .concat(courses.length === 1 ? courses[0] : []) - .concat(professors.length === 1 ? professors[0] : [])) { + ]) { const entry = grades[searchQueryLabel(result)]; if (entry && entry.state === 'done') { entry.data = { @@ -442,6 +443,38 @@ export const Dashboard: NextPage = () => { return newVal; }); } + + // holds data for course and professor overviews + type rhsGradesType = { [key: string]: GenericFetchedData }; + const [rhsGrades, setRHSGrades] = useState<{ + course: rhsGradesType; + professor: rhsGradesType; + }>({ course: {}, professor: {} }); + function fetchAndAddRHSGrades( + query: SearchQuery, + controller: AbortController, + ) { + const rhsKey = searchQueryLabel(query); + // only update course on course query or vice versa + const isCourse = typeof query.prefix !== 'undefined'; + setRHSGrades((old) => ({ + course: isCourse ? { [rhsKey]: { state: 'loading' } } : old.course, + professor: isCourse ? old.professor : { [rhsKey]: { state: 'loading' } }, + })); + fetchGradesData(query, controller) + .then((rhsGrade) => { + const rhsGradeFetched: GenericFetchedData = { + state: rhsGrade.gpa !== -1 ? 'done' : 'error', + data: rhsGrade, + }; + setRHSGrades((old) => ({ + course: isCourse ? { [rhsKey]: rhsGradeFetched } : old.course, + professor: isCourse ? old.professor : { [rhsKey]: rhsGradeFetched }, + })); + }) + .catch((err) => console.error('Grades data for ' + rhsKey, err)); + } + //Store rmp scores by profs const [rmp, setRmp] = useState<{ [key: string]: GenericFetchedData; @@ -679,6 +712,9 @@ export const Dashboard: NextPage = () => { } } + // Add this after the compare state declaration + const colorMap = createColorMap(compare); + //Main content: loading, error, or normal let contentComponent; @@ -696,7 +732,7 @@ export const Dashboard: NextPage = () => { , ); @@ -707,7 +743,7 @@ export const Dashboard: NextPage = () => { , ); } @@ -719,6 +755,7 @@ export const Dashboard: NextPage = () => { grades={compareGrades} rmp={compareRmp} removeFromCompare={removeFromCompare} + colorMap={colorMap} />, ); contentComponent = ( @@ -744,12 +781,15 @@ export const Dashboard: NextPage = () => { compare={compare} addToCompare={addToCompare} removeFromCompare={removeFromCompare} + colorMap={colorMap} />
- {tabs} + + {tabs} +
diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 750416d1..8b9e3105 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -50,12 +50,12 @@ const Home: NextPage = () => { />

- POWERED BY{' '} + POWERED BY {/*eslint-disable-next-line react/jsx-no-target-blank*/} NEBULA LABS @@ -68,11 +68,22 @@ const Home: NextPage = () => { find the perfect class.

+ {/*eslint-disable-next-line react/jsx-no-target-blank*/} + + Also check out UTD Grades + ); From cbf56cea33467daeba4483433a275ea8e319b36a Mon Sep 17 00:00:00 2001 From: AbhiramTadepalli Date: Sun, 10 Nov 2024 09:08:34 -0600 Subject: [PATCH 6/9] Reapply "format" This reverts commit 10305471b357ca6e3cb007d1fcf802897ccc5b52. --- src/components/common/CompareTable/compareTable.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/common/CompareTable/compareTable.tsx b/src/components/common/CompareTable/compareTable.tsx index e785bcce..e546fdb5 100644 --- a/src/components/common/CompareTable/compareTable.tsx +++ b/src/components/common/CompareTable/compareTable.tsx @@ -275,9 +275,11 @@ function GradeAndRmpRow({ )) || (rmp.state === 'done' && - getRmpValue(rmp.data as RMPInterface) == 0 && ) || - (rmp.state === 'done' && - getRmpValue(rmp.data as RMPInterface) != 0 && ( + getRmpValue(rmp.data as RMPInterface) == 0 && ( + + )) || + (rmp.state === 'done' && + getRmpValue(rmp.data as RMPInterface) != 0 && ( {rmpValue} From 402829698c222cb02d3e7aef244c21900f2445fd Mon Sep 17 00:00:00 2001 From: AbhiramTadepalli Date: Sun, 10 Nov 2024 10:21:45 -0600 Subject: [PATCH 7/9] Compare Table will not display rmp data if there are no reviews --- .../common/CompareTable/compareTable.tsx | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/components/common/CompareTable/compareTable.tsx b/src/components/common/CompareTable/compareTable.tsx index e546fdb5..4f7caa2a 100644 --- a/src/components/common/CompareTable/compareTable.tsx +++ b/src/components/common/CompareTable/compareTable.tsx @@ -143,7 +143,7 @@ function GradeOrRmpRow({ {loadingFiller} )) || - (value.state === 'done' && getValue(value.data) !== -1 && ( + (value.state === 'done' && getValue(value.data) > 0 && ( )) || - (rmp.state === 'done' && - getRmpValue(rmp.data as RMPInterface) == 0 && ( - - )) || - (rmp.state === 'done' && - getRmpValue(rmp.data as RMPInterface) != 0 && ( - - {rmpValue} - - )) || + (rmp.state === 'done' && rmpValue == 0 && ) || + (rmp.state === 'done' && rmpValue != 0 && ( + + {rmpValue} + + )) || null} From 51144fd3af4148edb0f8f68f85deb140b4ca5d86 Mon Sep 17 00:00:00 2001 From: AbhiramTadepalli Date: Sun, 10 Nov 2024 10:30:18 -0600 Subject: [PATCH 8/9] Use numRatings to determine if CompareTable should show RMP data --- .../common/CompareTable/compareTable.tsx | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/components/common/CompareTable/compareTable.tsx b/src/components/common/CompareTable/compareTable.tsx index 4f7caa2a..8b16d967 100644 --- a/src/components/common/CompareTable/compareTable.tsx +++ b/src/components/common/CompareTable/compareTable.tsx @@ -143,28 +143,30 @@ function GradeOrRmpRow({ {loadingFiller} )) || - (value.state === 'done' && getValue(value.data) > 0 && ( - - 0 && ( // do not display RMP data (non-GPA data) if there are no reviews + - {/*value.data is all the data past the state of loading, done, or error. + + {/*value.data is all the data past the state of loading, done, or error. getValue returns the specific value from the data structure, like gpa. formatValue makes it look pretty like 3.7216373 displaying as 3.72.*/} - {formatValue(getValue(value.data))} - - - )) || + {formatValue(getValue(value.data))} + + + )) || null}
))} From 7c725b823b417998f64b6981dba6989c2177ec71 Mon Sep 17 00:00:00 2001 From: AbhiramTadepalli Date: Sun, 10 Nov 2024 10:35:03 -0600 Subject: [PATCH 9/9] fixed the logic for numRatings in compare to only target non-GPA data --- src/components/common/CompareTable/compareTable.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/common/CompareTable/compareTable.tsx b/src/components/common/CompareTable/compareTable.tsx index 8b16d967..4b99c03c 100644 --- a/src/components/common/CompareTable/compareTable.tsx +++ b/src/components/common/CompareTable/compareTable.tsx @@ -144,8 +144,9 @@ function GradeOrRmpRow({ )) || (value.state === 'done' && - name !== 'GPA' && - (value.data as RMPInterface).numRatings > 0 && ( // do not display RMP data (non-GPA data) if there are no reviews + (name !== 'GPA' + ? (value.data as RMPInterface).numRatings > 0 + : true) && ( // do not display RMP data (non-GPA data) if there are no reviews