From b227ede4de80f31f0b6b96f3e503c92c77080871 Mon Sep 17 00:00:00 2001 From: Daisy Kucharski Date: Sun, 4 Feb 2024 14:29:59 -0500 Subject: [PATCH 1/7] logic --- .../components/Sidebar/NUPathSection.tsx | 264 ++++++++++++++++++ .../frontend/components/Sidebar/Sidebar.tsx | 15 +- 2 files changed, 275 insertions(+), 4 deletions(-) create mode 100644 packages/frontend/components/Sidebar/NUPathSection.tsx diff --git a/packages/frontend/components/Sidebar/NUPathSection.tsx b/packages/frontend/components/Sidebar/NUPathSection.tsx new file mode 100644 index 000000000..b7ddaf8dc --- /dev/null +++ b/packages/frontend/components/Sidebar/NUPathSection.tsx @@ -0,0 +1,264 @@ +import { NUPathEnum, ScheduleCourse2 } from "@graduate/common"; +import { SidebarValidationStatus } from "./Sidebar"; +import { useState } from "react"; +import { Box, Flex, Spinner, Text } from "@chakra-ui/react"; +import { + CheckIcon, + ChevronDownIcon, + ChevronUpIcon, + SmallCloseIcon, +} from "@chakra-ui/icons"; + +interface NUPathSectionProps { + coursesTaken: ScheduleCourse2[]; + dndIdPrefix: string; + loading?: boolean; +} + +const nupathDisplayNames: [nupath: string, display: string][] = [ + [NUPathEnum.ND, "Natural and Designed World (ND)"], + [NUPathEnum.EI, "Creative Expression/Innovation (EI)"], + [NUPathEnum.IC, "Interpreting Culture (IC)"], + [NUPathEnum.FQ, "Formal and Quantitative Reasoning (FQ)"], + [NUPathEnum.AD, "Analyzing/Using Data (AD)"], + [NUPathEnum.DD, "Difference and Diversity (DD)"], + [NUPathEnum.ER, "Ethical Reasoning (ER)"], + [NUPathEnum.WF, "First Year Writing (WF)"], + [NUPathEnum.WI, "Writing Intensive (WI)"], + [NUPathEnum.WD, "Advanced Writing in the Disciplines (WD)"], + [NUPathEnum.EX, "Integration Experience (EX)"], + [NUPathEnum.CE, "Capstone Experience (CE)"], +]; +const grey = "neutral.400"; +const green = "states.success.main"; + +const NUPathSection: React.FC = ({ + coursesTaken, + dndIdPrefix, + loading, +}) => { + const [opened, setOpened] = useState(false); + + let validationStatus = SidebarValidationStatus.Error; + + const nupathMap: Record = {}; + + for (const course of coursesTaken) { + if (!course.nupaths) { + continue; + } + + for (const nupath of course.nupaths) { + nupathMap[nupath] = (nupathMap[nupath] || 0) + 1; + } + } + + const wiCount = nupathMap[NUPathEnum.WI]; + + if (loading) { + validationStatus = SidebarValidationStatus.Loading; + } else if (Object.keys(nupathMap).length === 13 && wiCount && wiCount >= 2) { + // Sidebar is complete if all 13 nupaths have been fulfilled (including 2 writing intensives) + validationStatus = SidebarValidationStatus.Complete; + } + + return ( + + { + setOpened(!opened); + }} + direction="row" + justifyContent="space-between" + alignItems="flex-start" + color="dark.main" + fontWeight="bold" + py="md" + px="md" + margin="0" + backgroundColor="neutral.main" + transition="background-color 0.25s ease" + _hover={{ + backgroundColor: "neutral.900", + }} + _active={{ + backgroundColor: "neutral.200", + }} + display="flex" + position="sticky" + top="0px" + zIndex={1} + > + + + {/* + The following three icons appear and disappear based on opacity to allow for transitions (if they're conditionally rendered, then transitions can't occur). + */} + + + + + + NUpath Requirements + + + + {opened ? ( + + ) : ( + + )} + + + + {loading && ( + + + Loading... + + )} + {opened && !loading && ( + + + Complete the following NUpath requirements. + + <> + {nupathDisplayNames.map(([nupath, displayName], idx) => { + const numTaken = nupathMap[nupath] || 0; + return ( + + ); + })} + + + )} + + + ); +}; + +interface NUPathRequirementProps { + nupath: string; + displayName: string; + numTaken: number; +} + +const NUPathRequirement: React.FC = ({ + nupath, + displayName, + numTaken, +}) => { + const isSatisfied = + (nupath === NUPathEnum.WI && numTaken >= 2) || + (nupath !== NUPathEnum.WI && numTaken >= 1); + + return ( + <> + + {displayName} {numTaken} {String(isSatisfied)} + + + + + + + ); +}; + +export default NUPathSection; diff --git a/packages/frontend/components/Sidebar/Sidebar.tsx b/packages/frontend/components/Sidebar/Sidebar.tsx index f6db4d986..f04dcc7bb 100644 --- a/packages/frontend/components/Sidebar/Sidebar.tsx +++ b/packages/frontend/components/Sidebar/Sidebar.tsx @@ -34,6 +34,7 @@ import { } from "../../validation-worker/worker-messages"; import { useFetchCourses, useMajor } from "../../hooks"; import { HelperToolTip } from "../Help"; +import NUPathSection from "./NUPathSection"; export enum SidebarValidationStatus { Loading = "Loading", @@ -92,15 +93,16 @@ const Sidebar: React.FC = memo( MajorValidationResult | undefined >(undefined); + const coursesTaken = [ + ...getAllCoursesFromPlan(selectedPlan), + ...transferCourses, + ]; + const revalidateMajor = () => { setValidationStatus(undefined); if (!selectedPlan || !major || !workerRef.current) return; currentRequestNum += 1; - const coursesTaken = [ - ...getAllCoursesFromPlan(selectedPlan), - ...transferCourses, - ]; const validationInfo: WorkerPostInfo = { major: major, taken: coursesTaken, @@ -227,6 +229,11 @@ const Sidebar: React.FC = memo( > {courseData && ( <> + {major.requirementSections.map((section, index) => { const sectionValidationError: MajorValidationError | undefined = getSectionError(index, validationStatus); From 6f41725e05e1ea9a7cbcd90e931ec62cf498df62 Mon Sep 17 00:00:00 2001 From: AngelaZQ1 Date: Thu, 8 Feb 2024 15:05:28 -0500 Subject: [PATCH 2/7] update nupath names --- packages/common/src/types.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/common/src/types.ts b/packages/common/src/types.ts index 2e3ddfb78..b7ac8216f 100644 --- a/packages/common/src/types.ts +++ b/packages/common/src/types.ts @@ -3,13 +3,13 @@ * breadth requirements. */ export enum NUPathEnum { - ND = "Natural and Designed World", - EI = "Creative Expression/Innovation", + ND = "Natural/Designed World", + EI = "Creative Express/Innov", IC = "Interpreting Culture", - FQ = "Formal and Quantitative Reasoning", - SI = "Societies and Institutions", + FQ = "Formal/Quant Reasoning", + SI = "Societies/Institutions", AD = "Analyzing/Using Data", - DD = "Difference and Diversity", + DD = "Difference/Diversity", ER = "Ethical Reasoning", WF = "1st Yr Writing", WD = "Adv Writ Dscpl", From f5063b0cffc017d7e24572c9766d69308c38ba96 Mon Sep 17 00:00:00 2001 From: AngelaZQ1 Date: Thu, 8 Feb 2024 16:59:47 -0500 Subject: [PATCH 3/7] styling --- .../components/Sidebar/NUPathSection.tsx | 62 ++++++++++--------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/packages/frontend/components/Sidebar/NUPathSection.tsx b/packages/frontend/components/Sidebar/NUPathSection.tsx index b7ddaf8dc..48d37390f 100644 --- a/packages/frontend/components/Sidebar/NUPathSection.tsx +++ b/packages/frontend/components/Sidebar/NUPathSection.tsx @@ -15,19 +15,20 @@ interface NUPathSectionProps { loading?: boolean; } -const nupathDisplayNames: [nupath: string, display: string][] = [ - [NUPathEnum.ND, "Natural and Designed World (ND)"], - [NUPathEnum.EI, "Creative Expression/Innovation (EI)"], - [NUPathEnum.IC, "Interpreting Culture (IC)"], - [NUPathEnum.FQ, "Formal and Quantitative Reasoning (FQ)"], - [NUPathEnum.AD, "Analyzing/Using Data (AD)"], - [NUPathEnum.DD, "Difference and Diversity (DD)"], - [NUPathEnum.ER, "Ethical Reasoning (ER)"], - [NUPathEnum.WF, "First Year Writing (WF)"], - [NUPathEnum.WI, "Writing Intensive (WI)"], - [NUPathEnum.WD, "Advanced Writing in the Disciplines (WD)"], - [NUPathEnum.EX, "Integration Experience (EX)"], - [NUPathEnum.CE, "Capstone Experience (CE)"], +const nupathAbbreviations: [nupath: string, abbreviation: string][] = [ + [NUPathEnum.ND, "ND"], + [NUPathEnum.EI, "EI"], + [NUPathEnum.IC, "IC"], + [NUPathEnum.FQ, "FQ"], + [NUPathEnum.SI, "SI"], + [NUPathEnum.AD, "AD"], + [NUPathEnum.DD, "DD"], + [NUPathEnum.ER, "ER"], + [NUPathEnum.WF, "WF"], + [NUPathEnum.WD, "WD"], + [NUPathEnum.WI, "WI"], + [NUPathEnum.EX, "EX"], + [NUPathEnum.CE, "CE"], ]; const grey = "neutral.400"; const green = "states.success.main"; @@ -65,7 +66,7 @@ const NUPathSection: React.FC = ({ return ( @@ -81,10 +82,10 @@ const NUPathSection: React.FC = ({ py="md" px="md" margin="0" - backgroundColor="neutral.main" + backgroundColor="neutral.50" transition="background-color 0.25s ease" _hover={{ - backgroundColor: "neutral.900", + backgroundColor: "neutral.100", }} _active={{ backgroundColor: "neutral.200", @@ -171,7 +172,9 @@ const NUPathSection: React.FC = ({ @@ -183,17 +186,17 @@ const NUPathSection: React.FC = ({ )} {opened && !loading && ( - + Complete the following NUpath requirements. <> - {nupathDisplayNames.map(([nupath, displayName], idx) => { + {nupathAbbreviations.map(([nupath, abbreviation], idx) => { const numTaken = nupathMap[nupath] || 0; return ( ); @@ -207,14 +210,14 @@ const NUPathSection: React.FC = ({ }; interface NUPathRequirementProps { + abbreviation: string; nupath: string; - displayName: string; numTaken: number; } const NUPathRequirement: React.FC = ({ + abbreviation, nupath, - displayName, numTaken, }) => { const isSatisfied = @@ -222,10 +225,7 @@ const NUPathRequirement: React.FC = ({ (nupath !== NUPathEnum.WI && numTaken >= 1); return ( - <> - - {displayName} {numTaken} {String(isSatisfied)} - + = ({ width="18px" height="18px" display="flex" + position="relative" transition="background 0.25s ease, color 0.25s ease, border 0.25s ease" transitionDelay="0.1s" alignItems="center" @@ -243,6 +244,7 @@ const NUPathRequirement: React.FC = ({ p="xs" > = ({ /> - + + {abbreviation} + + {nupath} + ); }; From a6211ab25a954deb56f24904781ebc26ccb865dd Mon Sep 17 00:00:00 2001 From: AngelaZQ1 Date: Thu, 8 Feb 2024 17:25:30 -0500 Subject: [PATCH 4/7] WI tooltip --- .../components/Sidebar/NUPathSection.tsx | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/frontend/components/Sidebar/NUPathSection.tsx b/packages/frontend/components/Sidebar/NUPathSection.tsx index 48d37390f..06002fe49 100644 --- a/packages/frontend/components/Sidebar/NUPathSection.tsx +++ b/packages/frontend/components/Sidebar/NUPathSection.tsx @@ -2,6 +2,7 @@ import { NUPathEnum, ScheduleCourse2 } from "@graduate/common"; import { SidebarValidationStatus } from "./Sidebar"; import { useState } from "react"; import { Box, Flex, Spinner, Text } from "@chakra-ui/react"; +import { HelperToolTip } from "../Help"; import { CheckIcon, ChevronDownIcon, @@ -220,9 +221,8 @@ const NUPathRequirement: React.FC = ({ nupath, numTaken, }) => { - const isSatisfied = - (nupath === NUPathEnum.WI && numTaken >= 2) || - (nupath !== NUPathEnum.WI && numTaken >= 1); + const isWI = nupath === NUPathEnum.WI; + const isSatisfied = (isWI && numTaken >= 2) || (!isWI && numTaken >= 1); return ( @@ -259,10 +259,15 @@ const NUPathRequirement: React.FC = ({ boxSize="13px" /> - - {abbreviation} - - {nupath} + + + {abbreviation} + + + {nupath} + + {isWI && } + ); }; From adb50214ba7085402d1eeec14947914ebcfecfdb Mon Sep 17 00:00:00 2001 From: AngelaZQ1 Date: Thu, 8 Feb 2024 17:31:51 -0500 Subject: [PATCH 5/7] use nupath display name --- .../components/Sidebar/NUPathSection.tsx | 66 +++++++++++-------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/packages/frontend/components/Sidebar/NUPathSection.tsx b/packages/frontend/components/Sidebar/NUPathSection.tsx index 06002fe49..6b939ad52 100644 --- a/packages/frontend/components/Sidebar/NUPathSection.tsx +++ b/packages/frontend/components/Sidebar/NUPathSection.tsx @@ -15,21 +15,24 @@ interface NUPathSectionProps { dndIdPrefix: string; loading?: boolean; } - -const nupathAbbreviations: [nupath: string, abbreviation: string][] = [ - [NUPathEnum.ND, "ND"], - [NUPathEnum.EI, "EI"], - [NUPathEnum.IC, "IC"], - [NUPathEnum.FQ, "FQ"], - [NUPathEnum.SI, "SI"], - [NUPathEnum.AD, "AD"], - [NUPathEnum.DD, "DD"], - [NUPathEnum.ER, "ER"], - [NUPathEnum.WF, "WF"], - [NUPathEnum.WD, "WD"], - [NUPathEnum.WI, "WI"], - [NUPathEnum.EX, "EX"], - [NUPathEnum.CE, "CE"], +const nuPathDisplayAndAbbr: [ + nupath: string, + displayName: string, + abbreviation: string +][] = [ + [NUPathEnum.ND, "Natural and Designed World", "ND"], + [NUPathEnum.EI, "Creative Expression/Innovation", "EI"], + [NUPathEnum.IC, "Interpreting Culture", "IC"], + [NUPathEnum.FQ, "Formal and Quantitative Reasoning", "FQ"], + [NUPathEnum.SI, "Societies and Institutions", "SI"], + [NUPathEnum.AD, "Analyzing/Using Data", "AD"], + [NUPathEnum.DD, "Difference and Diversity", "DD"], + [NUPathEnum.ER, "Ethical Reasoning", "ER"], + [NUPathEnum.WF, "First Year Writing", "WF"], + [NUPathEnum.WD, "Advanced Writing in the Disciplines", "WD"], + [NUPathEnum.WI, "Writing Intensive", "WI"], + [NUPathEnum.EX, "Integration Experience", "EX"], + [NUPathEnum.CE, "Capstone Experience", "CE"], ]; const grey = "neutral.400"; const green = "states.success.main"; @@ -191,17 +194,20 @@ const NUPathSection: React.FC = ({ Complete the following NUpath requirements. <> - {nupathAbbreviations.map(([nupath, abbreviation], idx) => { - const numTaken = nupathMap[nupath] || 0; - return ( - - ); - })} + {nuPathDisplayAndAbbr.map( + ([nupath, displayName, abbreviation], idx) => { + const numTaken = nupathMap[nupath] || 0; + return ( + + ); + } + )} )} @@ -211,14 +217,16 @@ const NUPathSection: React.FC = ({ }; interface NUPathRequirementProps { - abbreviation: string; nupath: string; + abbreviation: string; + displayName: string; numTaken: number; } const NUPathRequirement: React.FC = ({ - abbreviation, nupath, + abbreviation, + displayName, numTaken, }) => { const isWI = nupath === NUPathEnum.WI; @@ -264,7 +272,7 @@ const NUPathRequirement: React.FC = ({ {abbreviation} - {nupath} + {displayName} {isWI && } From 9d708356ab0aa63e78f3ebb616e498f8a85a76dc Mon Sep 17 00:00:00 2001 From: AngelaZQ1 Date: Thu, 8 Feb 2024 18:06:50 -0500 Subject: [PATCH 6/7] use colon --- packages/frontend/components/Sidebar/NUPathSection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/components/Sidebar/NUPathSection.tsx b/packages/frontend/components/Sidebar/NUPathSection.tsx index 6b939ad52..7ef4e7c3d 100644 --- a/packages/frontend/components/Sidebar/NUPathSection.tsx +++ b/packages/frontend/components/Sidebar/NUPathSection.tsx @@ -191,7 +191,7 @@ const NUPathSection: React.FC = ({ {opened && !loading && ( - Complete the following NUpath requirements. + Complete the following NUpath requirements: <> {nuPathDisplayAndAbbr.map( From 5643f93078323448d7e2132180292bda3f3bd103 Mon Sep 17 00:00:00 2001 From: Daisy Kucharski Date: Thu, 14 Mar 2024 18:46:18 -0400 Subject: [PATCH 7/7] PR fixes --- packages/frontend/components/Sidebar/NUPathSection.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/frontend/components/Sidebar/NUPathSection.tsx b/packages/frontend/components/Sidebar/NUPathSection.tsx index 7ef4e7c3d..019015369 100644 --- a/packages/frontend/components/Sidebar/NUPathSection.tsx +++ b/packages/frontend/components/Sidebar/NUPathSection.tsx @@ -16,7 +16,7 @@ interface NUPathSectionProps { loading?: boolean; } const nuPathDisplayAndAbbr: [ - nupath: string, + nupath: NUPathEnum, displayName: string, abbreviation: string ][] = [ @@ -58,11 +58,11 @@ const NUPathSection: React.FC = ({ } } - const wiCount = nupathMap[NUPathEnum.WI]; + const wiCount = nupathMap[NUPathEnum.WI] || 0; if (loading) { validationStatus = SidebarValidationStatus.Loading; - } else if (Object.keys(nupathMap).length === 13 && wiCount && wiCount >= 2) { + } else if (Object.keys(nupathMap).length === 13 && wiCount >= 2) { // Sidebar is complete if all 13 nupaths have been fulfilled (including 2 writing intensives) validationStatus = SidebarValidationStatus.Complete; } @@ -83,8 +83,7 @@ const NUPathSection: React.FC = ({ alignItems="flex-start" color="dark.main" fontWeight="bold" - py="md" - px="md" + p="md" margin="0" backgroundColor="neutral.50" transition="background-color 0.25s ease"