@@ -47,13 +75,41 @@ const DetailsRow = ({course, onlyShowSections, onShowEverything, onShareCourse}:
-
- Description:
- {course.course.description}
-
+
+
+ Description:
+ {course.course.description}
+
+
+ {
+ course.course.offered.length > 0 && (
+
+ Semesters offered:
+ {toTitleCase(course.course.offered.join(', '))}
+
+ )
+ }
+
- } aria-label="Share course" variant="ghost" colorScheme="brand" title="Share course" onClick={onShareCourse}/>
+
+
+ }
+ aria-label="Share course"
+ variant="ghost"
+ colorScheme="brand"
+ title="Share course"
+ onClick={onShareCourse}/>
+
+ : }
+ aria-label="Add course to basket"
+ title="Add course to basket"
+ size="xs"
+ colorScheme={isCourseInBasket ? 'red' : undefined}
+ onClick={handleBasketAction}/>
+
{
@@ -70,17 +126,21 @@ const DetailsRow = ({course, onlyShowSections, onShowEverything, onShareCourse}:
-
- {!onlyShowSections && (
- Sections
- )}
+ {
+ courseSections.length > 0 && (
+
+ {!onlyShowSections && (
+ Sections
+ )}
-
-
+
+
+ )
+ }
|
);
};
-export default DetailsRow;
+export default observer(DetailsRow);
diff --git a/src/components/courses-table/row.tsx b/src/components/courses-table/row.tsx
index 013db29..8a67b7a 100644
--- a/src/components/courses-table/row.tsx
+++ b/src/components/courses-table/row.tsx
@@ -1,4 +1,4 @@
-import React, {useCallback, useLayoutEffect, useMemo, useState} from 'react';
+import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {Tr, Td, IconButton, useDisclosure, usePrevious} from '@chakra-ui/react';
import {InfoIcon, InfoOutlineIcon} from '@chakra-ui/icons';
import {observer} from 'mobx-react-lite';
@@ -16,6 +16,11 @@ const TableRow = observer(({course, onShareCourse}: {course: ICourseWithFiltered
const creditsString: string = useMemo(() => {
if (sections.length === 0) {
+ const {credits} = course.course;
+ if (credits !== null) {
+ return getCreditsStr(credits, credits);
+ }
+
return '';
}
@@ -34,8 +39,7 @@ const TableRow = observer(({course, onShareCourse}: {course: ICourseWithFiltered
return getCreditsStr(min, max);
}, [sections]);
- // TODO: can this use useEffect instead?
- useLayoutEffect(() => {
+ useEffect(() => {
if (course.sections.wasFiltered !== wasPreviouslyFiltered) {
if (course.sections.wasFiltered) {
setOnlyShowSections(true);
diff --git a/src/components/navbar.tsx b/src/components/navbar.tsx
index fe8513a..c831a2a 100644
--- a/src/components/navbar.tsx
+++ b/src/components/navbar.tsx
@@ -6,6 +6,8 @@ import {observer} from 'mobx-react-lite';
import useStore from 'src/lib/state/context';
import Logo from 'public/images/logo.svg';
import {SEMESTER_DISPLAY_MAPPING} from 'src/lib/constants';
+import {ISemesterFilter} from 'src/lib/state/api';
+import toTitleCase from 'src/lib/to-title-case';
import ColorModeToggle from './color-mode-toggle';
import Link from './link';
@@ -24,6 +26,16 @@ const PAGES = [
},
];
+const getSemesterDisplayName = (semester: ISemesterFilter) => {
+ if (semester.isFuture) {
+ return toTitleCase(`Future ${semester.semester.toLowerCase()} Semester`);
+ }
+
+ return `${SEMESTER_DISPLAY_MAPPING[semester.semester]} ${semester.year}`;
+};
+
+const PATHS_THAT_REQUIRE_SEMESTER_SELECTOR = new Set(['/', '/help/registration-script']);
+
const Navbar = () => {
const router = useRouter();
const store = useStore();
@@ -34,9 +46,10 @@ const Navbar = () => {
const handleSemesterSelect = useCallback(async (event: React.ChangeEvent