diff --git a/components/SubscriptionsPage/ClassCard.tsx b/components/SubscriptionsPage/ClassCard.tsx index d3ea45ec..df44480b 100644 --- a/components/SubscriptionsPage/ClassCard.tsx +++ b/components/SubscriptionsPage/ClassCard.tsx @@ -4,6 +4,7 @@ import { LastUpdated } from '../common/LastUpdated'; import { DesktopSectionPanel } from '../ResultsPage/Results/SectionPanel'; import { getFormattedSections } from '../ResultsPage/ResultsLoader'; import DropdownArrow from '../icons/DropdownArrow.svg'; +import IconCollapseExpand from '../icons/IconCollapseExpand'; import CourseCheckBox from '../panels/CourseCheckBox'; import { CRNBadge } from './CRNBadge'; import axios from 'axios'; @@ -24,8 +25,10 @@ export const ClassCardWrapper = ({ }: ClassCardWrapperType): ReactElement => { return (
-
{headerLeft}
- {headerRight} +
+
{headerLeft}
+ {headerRight} +
{body} {afterBody} @@ -72,24 +75,45 @@ export function ClassCard({ return ( {course.subject} {course.classId}: {course.name} - - {course.sections.map((section) => ( - - ))} + /> */} +
+ {course.sections.map((section) => ( + + ))} +
} - headerRight={} + headerRight={ +
setAreSectionsHidden(!areSectionsHidden)} + style={{ + cursor: 'pointer', + display: 'inline-flex', + alignItems: 'center', + }} + > + +
+ } body={ <>
@@ -143,27 +167,26 @@ export function ClassCard({ } afterBody={ - <> -
setAreSectionsHidden(!areSectionsHidden)} - > - {areSectionsHidden ? 'Show sections' : 'Hide sections'} - +
-
- + role="button" + tabIndex={0} + > + +
+ + ) } /> ); diff --git a/package.json b/package.json index 4a2c3839..5715997b 100644 --- a/package.json +++ b/package.json @@ -115,5 +115,6 @@ }, "engines": { "node": ">=18" - } + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/pages/subscriptions.tsx b/pages/subscriptions.tsx index ac4d1e28..7a47edfd 100644 --- a/pages/subscriptions.tsx +++ b/pages/subscriptions.tsx @@ -7,6 +7,11 @@ import { SubscriptionCourse } from '../components/types'; import { gqlClient } from '../utils/courseAPIClient'; import useUserInfo from '../utils/useUserInfo'; import { EmptyCard } from '../components/SubscriptionsPage/EmptyCard'; +import getTermInfosWithError from '../utils/TermInfoProvider'; +import { getTermName, getLatestTerm } from '../components/terms'; +import { Campus } from '../components/types'; +import Keys from '../components/Keys'; +import axios from 'axios'; async function fetchCourseNotifs(classMapping, courseIds) { for (const courseId of courseIds) { @@ -116,6 +121,10 @@ export default function SubscriptionsPage(): ReactElement { // is the user subscribed to at least one class const [isSubscribed, setIsSubscribed] = useState(false); + const termInfos = getTermInfosWithError().termInfos; + const termId = getLatestTerm(termInfos, Campus.NEU); + const termName = getTermName(termInfos, termId).replace('Semester', ''); + useEffect(() => { if (isUserInfoLoading) { return; @@ -145,6 +154,22 @@ export default function SubscriptionsPage(): ReactElement { fetchSubscriptions(); }, [userInfo?.phoneNumber, isUserInfoLoading]); + const unsubscribeAll = () => { + const allSections = Array.from(classes.values()).flatMap( + (course) => course.sections + ); + + axios + .delete(`${process.env.NEXT_PUBLIC_NOTIFS_ENDPOINT}/user/subscriptions`, { + data: { + token: userInfo.token, + sectionIds: allSections.map((s) => Keys.getSectionHash(s)), + // courseIds: [Keys.getClassHash(course)], + }, + }) + .then(() => fetchUserInfo()); + }; + if (isFetching) { return ( <> @@ -171,7 +196,6 @@ export default function SubscriptionsPage(): ReactElement {
+ {isSubscribed ? ( - <> -
-
-
-

Subscriptions

- {Array.from(classes) - .sort((a, b) => (a > b ? 1 : -1)) // Sort to ensure the sub order doesn't change - .map(([courseCode, course]) => { - return ( - - ); - })} +
+
+
+
+

+ {termName} Notifications +

+
+ {Array.from(classes) + .sort((a, b) => (a > b ? 1 : -1)) + .map(([courseCode, course]) => ( + + ))}
- +
) : ( )} diff --git a/public/unsubscribe.svg b/public/unsubscribe.svg new file mode 100644 index 00000000..e814122b --- /dev/null +++ b/public/unsubscribe.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/styles/pages/_Results.scss b/styles/pages/_Results.scss index 15c67690..aac5b4f6 100644 --- a/styles/pages/_Results.scss +++ b/styles/pages/_Results.scss @@ -175,6 +175,47 @@ $SIDEBAR_WIDTH: 268px; padding-left: 10px; } + .Subscriptions_Header_Container { + display: flex; + justify-content: space-between; + align-items: end; + flex-direction: row; + + .Subscriptions_Title { + font-family: Lato; + font-size: 24px; + font-style: normal; + font-weight: 700; + line-height: 28.8px; + } + + .Unsubscribe_All_Button { + display: flex; + gap: 8px; + align-items: center; + + padding: 9px 18px; + + cursor: pointer; + + border: 0.5px solid #1d3557; + background-color: white; + border-radius: 8px; + + color: #212121; + font-family: Lato; + font-size: 14px; + font-style: normal; + font-weight: 700; + line-height: 16px; + + .Unsuscribe_Icon { + width: 8px; + height: 8px; + } + } + } + .Results_Main__EmptyCard { display: flex; flex-direction: column; diff --git a/styles/results/_SearchResult.scss b/styles/results/_SearchResult.scss index 7c76499e..82473637 100644 --- a/styles/results/_SearchResult.scss +++ b/styles/results/_SearchResult.scss @@ -29,6 +29,7 @@ font-size: 18px; line-height: 2px; border-radius: 5px 5px 0 0; + color: Colors.$NEU9; } &--employeeName { @@ -175,6 +176,7 @@ &__sectionTable > thead > tr > th { text-align: left; padding-left: 16px; + padding-top: 20px; } &__sectionTable > thead > tr > th:nth-child(6) { @@ -236,15 +238,28 @@ } &--subscriptionExpanded { - transform: rotate(-180deg); + transform: rotate(-90deg); margin-top: 2px; } &--subscriptionCollapsed { - transform: rotate(0deg); + transform: rotate(90deg); margin-top: 3px; } + &--unsubscribeButton { + margin-left: auto; + width: fit-content; + display: flex; + width: auto; + padding: 8px 16px; + align-items: center; + border-radius: 8px; + border: 1px solid #d1d3d7; + font-weight: 700; + background: #fff; + } + & > span { margin-right: 8px; }