Skip to content

Commit

Permalink
Showing 14 changed files with 225 additions and 223 deletions.
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@
border-radius: 8px;
background-color: var(--foreground-color);
flex-shrink: 0;

.error {
color: var(--paragraph-color);
text-align: center;
144 changes: 63 additions & 81 deletions apps/frontend/src/app/Catalog/Dashboard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Dispatch, SetStateAction } from "react";
import { Dispatch, SetStateAction, useMemo } from "react";

import {
ArrowSeparateVertical,
@@ -14,38 +14,40 @@ import { Button, Container, IconButton, Tooltip } from "@repo/theme";
import { DropdownMenu } from "@repo/theme";

import Carousel from "@/components/Carousel";
import CarouselClass from "@/components/CarouselClass";
import { useReadUser } from "@/hooks/api";
import { ITerm } from "@/lib/api";
import { getRecents } from "@/lib/recents";
import { getRecentClasses } from "@/lib/recent-classes";

import styles from "./Dashboard.module.scss";

interface DashboardProps {
term: ITerm | null | undefined;
termList: ITerm[] | undefined;
term: ITerm;
terms: ITerm[];
expanded: boolean;
setExpanded: Dispatch<SetStateAction<boolean>>;
setOpen: Dispatch<SetStateAction<boolean>>;
}

export default function Dashboard({
term,
termList,
terms,
expanded,
setExpanded,
setOpen,
}: DashboardProps) {
const navigate = useNavigate();
const { data: user, loading: userLoading } = useReadUser();

if (!term) return <></>;

const recents = getRecents().filter(
(v) => v.semester == term.semester && v.year == term.year
const recentClasses = useMemo(
() =>
getRecentClasses().filter(
(recentClass) =>
recentClass.semester === term.semester &&
recentClass.year === term.year
),
[term]
);

const navigate = useNavigate();

return (
<div className={styles.root}>
<Container size="sm">
@@ -58,32 +60,21 @@ export default function Dashboard({
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content sideOffset={5}>
{termList ? (
termList
.filter(
({ year, semester }, index) =>
index ===
termList.findIndex(
(term) =>
term.semester === semester && term.year === year
)
)
.map((t) => {
return (
<DropdownMenu.Item
key={`${t.semester} ${t.year}`}
onClick={() =>
navigate(`/catalog/${t.year}/${t.semester}`)
}
>
{t.semester} {t.year}
</DropdownMenu.Item>
);
})
) : (
<></>
)}
<DropdownMenu.Arrow style={{ fill: "var(--foreground-color)" }} />
{terms
.filter(
({ year, semester }) =>
year !== term.year || semester !== term.semester
)
.map(({ year, semester }) => {
return (
<DropdownMenu.Item
key={`${semester} ${year}`}
onClick={() => navigate(`/catalog/${year}/${semester}`)}
>
{semester} {year}
</DropdownMenu.Item>
);
})}
</DropdownMenu.Content>
</DropdownMenu.Root>
<div className={styles.toggle}>
@@ -101,20 +92,17 @@ export default function Dashboard({
<p className={styles.heading}>
{term.semester} {term.year}
</p>
{term.startDate && term.endDate ? (
{term.startDate && term.endDate && (
<p className={styles.paragraph}>
{moment(term.startDate).format("MMMM Do")} through{" "}
{moment(term.endDate).format("MMMM Do")}
</p>
) : (
<></>
)}
{/* <Carousel title="Upcoming events" Icon={<Calendar />} to="/semesters">
<div className={styles.card}></div>
<div className={styles.card}></div>
<div className={styles.card}></div>
</Carousel> */}
<Carousel title="Bookmarked" Icon={<BookmarkSolid />} to="/account">
<Carousel.Root
title="Bookmarked"
Icon={<BookmarkSolid />}
to="/account"
>
{userLoading || !user ? (
<div className={styles.card}>
<div className={styles.error}>Sign in to bookmark classes</div>
@@ -126,47 +114,41 @@ export default function Dashboard({
) : (
user?.bookmarkedClasses
.filter(
(c) =>
!term || (c.year == term.year && c.semester == term.semester)
(bookmarkedClass) =>
bookmarkedClass.year === term.year &&
bookmarkedClass.semester === term.semester
)
.map((c, i) => {
.map((bookmarkedClass, i) => {
return (
<div key={i} className={styles.card}>
<CarouselClass
subject={c.subject}
year={c.year}
semester={c.semester}
courseNumber={c.courseNumber}
number={c.number}
/>
</div>
<Carousel.Class
key={i}
subject={bookmarkedClass.subject}
year={bookmarkedClass.year}
semester={bookmarkedClass.semester}
courseNumber={bookmarkedClass.courseNumber}
number={bookmarkedClass.number}
/>
);
})
)}
</Carousel>
{recents.length !== 0 && (
<Carousel title="Recently viewed" Icon={<Search />}>
{" "}
{recents
.filter(
(c) =>
!term || (c.year == term.year && c.semester == term.semester)
)
.reverse()
.map((c, i) => {
</Carousel.Root>
{recentClasses.length !== 0 && (
<Carousel.Root title="Recently viewed" Icon={<Search />}>
{recentClasses.map(
({ subject, year, semester, courseNumber, number }, i) => {
return (
<div key={i} className={styles.card}>
<CarouselClass
subject={c.subject}
year={c.year}
semester={c.semester}
courseNumber={c.courseNumber}
number={c.number}
/>
</div>
<Carousel.Class
key={i}
subject={subject}
year={year}
semester={semester}
courseNumber={courseNumber}
number={number}
/>
);
})}
</Carousel>
}
)}
</Carousel.Root>
)}
</Container>
</div>
4 changes: 2 additions & 2 deletions apps/frontend/src/app/Catalog/index.tsx
Original file line number Diff line number Diff line change
@@ -102,7 +102,7 @@ export default function Catalog() {
}

// TODO: Error state
if (!term) {
if (!terms || !term) {
return <></>;
}

@@ -145,7 +145,7 @@ export default function Catalog() {
) : (
<Dashboard
term={term}
termList={terms}
terms={terms}
expanded={expanded}
setExpanded={setExpanded}
setOpen={setOpen}
2 changes: 1 addition & 1 deletion apps/frontend/src/components/Carousel/Carousel.module.scss
Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@
overflow: auto;
padding: 0 24px;
display: flex;
gap: 24px;
gap: 16px;
scrollbar-width: none;
scroll-behavior: smooth;
}
Original file line number Diff line number Diff line change
@@ -3,11 +3,10 @@
border-radius: 8px;
flex-shrink: 0;
background-color: var(--foreground-color);
position: relative;
padding: 16px;
display: flex;
width: 320px;
gap: 16px;
align-items: flex-start;
cursor: pointer;

&:hover .column .icon {
@@ -29,7 +28,8 @@
.text {
flex-grow: 1;
font-size: 14px;
width: 80%;
display: flex;
flex-direction: column;

.heading {
color: var(--heading-color);
@@ -47,18 +47,14 @@
.description {
color: var(--paragraph-color);
line-height: 1.5;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
flex-grow: 1;
}

.row {
display: flex;
gap: 12px;
margin-top: 12px;
align-items: center;
float: bottom;
}
}
}
76 changes: 76 additions & 0 deletions apps/frontend/src/components/Carousel/Class/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { useMemo } from "react";

import { ArrowRight } from "iconoir-react";

import AverageGrade from "@/components/AverageGrade";
import Capacity from "@/components/Capacity";
import Units from "@/components/Units";
import { useReadClass } from "@/hooks/api";
import { Semester } from "@/lib/api";

import ClassDrawer from "../../ClassDrawer";
import styles from "./Class.module.scss";

interface ClassProps {
year: number;
semester: Semester;
subject: string;
courseNumber: string;
number: string;
}

export default function Class({
year,
semester,
subject,
courseNumber,
number,
}: ClassProps) {
const { data, loading } = useReadClass(
year as number,
semester as Semester,
subject as string,
courseNumber as string,
number as string
);

const _class = useMemo(() => data, [data]);

return loading || !_class ? (
<></>
) : (
<ClassDrawer
year={year}
semester={semester}
subject={subject}
courseNumber={courseNumber}
number={number}
>
<div className={styles.root}>
<div className={styles.text}>
<p className={styles.heading}>
{_class.subject} {_class.courseNumber} #{_class.number}
</p>
<p className={styles.description}>
{_class.title ?? _class.course.title}
</p>
<div className={styles.row}>
<AverageGrade gradeDistribution={_class.gradeDistribution} />
<Capacity
enrollCount={_class.primarySection.enrollCount}
enrollMax={_class.primarySection.enrollMax}
waitlistCount={_class.primarySection.waitlistCount}
waitlistMax={_class.primarySection.waitlistMax}
/>
<Units unitsMin={_class.unitsMin} unitsMax={_class.unitsMax} />
</div>
</div>
<div className={styles.column}>
<div className={styles.icon}>
<ArrowRight />
</div>
</div>
</div>
</ClassDrawer>
);
}
12 changes: 10 additions & 2 deletions apps/frontend/src/components/Carousel/index.tsx
Original file line number Diff line number Diff line change
@@ -7,15 +7,16 @@ import { Link, To } from "react-router-dom";
import { IconButton } from "@repo/theme";

import styles from "./Carousel.module.scss";
import Class from "./Class";

interface CarouselProps {
interface RootProps {
title: string;
Icon: ReactNode;
children: ReactNode;
to?: To;
}

export default function Carousel({ title, Icon, children, to }: CarouselProps) {
function Root({ title, Icon, children, to }: RootProps) {
const [start, setStart] = useState(false);
const [end, setEnd] = useState(false);

@@ -97,3 +98,10 @@ export default function Carousel({ title, Icon, children, to }: CarouselProps) {
</div>
);
}

const Carousel = {
Root,
Class,
};

export default Carousel;
71 changes: 0 additions & 71 deletions apps/frontend/src/components/CarouselClass/index.tsx

This file was deleted.

10 changes: 4 additions & 6 deletions apps/frontend/src/components/Class/index.tsx
Original file line number Diff line number Diff line change
@@ -44,7 +44,7 @@ import { useReadCourse, useReadUser, useUpdateUser } from "@/hooks/api";
import { useReadClass } from "@/hooks/api/classes/useReadClass";
import usePins from "@/hooks/usePins";
import { IClass, Semester } from "@/lib/api";
import { addToRecent } from "@/lib/recents";
import { addRecentClass } from "@/lib/recent-classes";
import { getExternalLink } from "@/lib/section";

import styles from "./Class.module.scss";
@@ -236,9 +236,7 @@ export default function Class({
useEffect(() => {
if (!_class) return;

console.log(_class);

addToRecent({
addRecentClass({
subject: _class.subject,
year: _class.year,
semester: _class.semester,
@@ -277,7 +275,7 @@ export default function Class({
[styles.active]: bookmarked,
})}
onClick={() => bookmark()}
disabled={userLoading} // setting disabled to false still appears on my version
disabled={userLoading}
>
{bookmarked ? <BookmarkSolid /> : <Bookmark />}
</IconButton>
@@ -361,7 +359,7 @@ export default function Class({
as={Link}
to={{
...location,
pathname: `/catalog/${year}/${semester}`,
pathname: `/catalog/${_class.year}/${_class.semester}`,
}}
onClick={() => onClose()}
>
58 changes: 58 additions & 0 deletions apps/frontend/src/lib/recent-classes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Semester } from "./api";

interface RecentClassData {
subject: string;
year: number;
semester: Semester;
courseNumber: string;
number: string;
}

const RECENT_CLASSES_KEY = "recent-classes";

const RECENT_CLASSES_MAX_LENGTH = 10;

export function addRecentClass({
subject,
year,
semester,
courseNumber,
number,
}: RecentClassData) {
let recentClasses = getRecentClasses();

recentClasses = recentClasses.filter(
(recentClass) =>
!(
subject == recentClass.subject &&
year == recentClass.year &&
semester == recentClass.semester &&
courseNumber == recentClass.courseNumber &&
number == recentClass.number
)
);

recentClasses.unshift({
subject: subject,
year: year,
semester: semester,
courseNumber: courseNumber,
number: number,
});

recentClasses = recentClasses.slice(0, RECENT_CLASSES_MAX_LENGTH);

const item = JSON.stringify(recentClasses);
localStorage.setItem(RECENT_CLASSES_KEY, item);
}

export function getRecentClasses() {
try {
const item = localStorage.getItem(RECENT_CLASSES_KEY);
if (!item) return [];

return JSON.parse(item) as RecentClassData[];
} catch {
return [];
}
}
47 changes: 0 additions & 47 deletions apps/frontend/src/lib/recents.ts

This file was deleted.

4 changes: 2 additions & 2 deletions packages/theme/src/components/Button/index.tsx
Original file line number Diff line number Diff line change
@@ -29,8 +29,8 @@ export const Button = forwardRef(
{...props}
ref={ref}
data-variant={variant}
disabled={disabled}
data-disabled={disabled}
disabled={disabled || undefined}
data-disabled={disabled || undefined}
className={classNames(styles.root, className)}
>
{children}
4 changes: 2 additions & 2 deletions packages/theme/src/components/IconButton/index.tsx
Original file line number Diff line number Diff line change
@@ -26,8 +26,8 @@ export const IconButton = forwardRef(
) => {
return (
<Component
data-disabled={disabled}
disabled={disabled}
disabled={disabled || undefined}
data-disabled={disabled || undefined}
data-variant={variant}
className={classNames(styles.root, className)}
ref={ref}
3 changes: 2 additions & 1 deletion packages/theme/src/components/MenuItem/index.tsx
Original file line number Diff line number Diff line change
@@ -27,7 +27,8 @@ export const MenuItem = forwardRef(
return (
<Component
ref={ref}
data-disabled={disabled}
data-disabled={disabled ?? undefined}
disabled={disabled ?? undefined}
className={classNames(
styles.root,
{

0 comments on commit 43e9d0b

Please sign in to comment.