Skip to content

Commit

Permalink
feat: Polymorphic components, prepare for dashboard, play around with…
Browse files Browse the repository at this point in the history
… new reusable drawers
  • Loading branch information
mathhulk committed Jul 10, 2024
1 parent ef62209 commit 48b05ae
Show file tree
Hide file tree
Showing 43 changed files with 1,677 additions and 918 deletions.
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint --ext .tsx,.ts src/ --report-unused-disable-directives",
"lint": "eslint --ext .tsx,.ts src/ --report-unused-disable-directives",
"start": "serve -s dist -p 3000"
},
"dependencies": {
Expand All @@ -14,6 +14,7 @@
"@mapbox/mapbox-gl-directions": "^4.3.1",
"@radix-ui/react-checkbox": "^1.1.0",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-hover-card": "^1.1.1",
"@radix-ui/react-radio-group": "^1.2.0",
"@radix-ui/react-scroll-area": "^1.1.0",
Expand Down
127 changes: 79 additions & 48 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,74 +1,105 @@
import { lazy } from "react";

import * as Tooltip from "@radix-ui/react-tooltip";
import { IconoirProvider } from "iconoir-react";
import { RouterProvider, createBrowserRouter } from "react-router-dom";

import About from "@/app/About";
import Catalog from "@/app/Catalog";
import Discover from "@/app/Discover";
import Landing from "@/app/Landing";
import Map from "@/app/Map";
import Plan from "@/app/Plan";
import Schedule from "@/app/Schedule";
import Compare from "@/app/Schedule/Compare";
import Manage from "@/app/Schedule/Manage";
import Schedules from "@/app/Schedules";
import BaseLayout from "@/components/BaseLayout";
import Layout from "@/components/Layout";

const About = lazy(() => import("@/app/About"));
const Enrollment = lazy(() => import("@/app/Catalog/Class/Enrollment"));
const Grades = lazy(() => import("@/app/Catalog/Class/Grades"));
const Overview = lazy(() => import("@/app/Catalog/Class/Overview"));
const Sections = lazy(() => import("@/app/Catalog/Class/Sections"));
const Discover = lazy(() => import("@/app/Discover"));
const Plan = lazy(() => import("@/app/Plan"));
const Schedule = lazy(() => import("@/app/Schedule"));
const Compare = lazy(() => import("@/app/Schedule/Compare"));
const Manage = lazy(() => import("@/app/Schedule/Manage"));
const Schedules = lazy(() => import("@/app/Schedules"));
const Map = lazy(() => import("@/app/Map"));

const router = createBrowserRouter([
{
element: <Layout header={false} footer={false} />,
element: <Layout />,
children: [
{
element: <Landing />,
index: true,
},
{
element: <Discover />,
path: "explore",
},
{
element: <Schedule />,
path: "schedules/:scheduleId",
element: <BaseLayout header={false} footer={false} />,
children: [
{
element: <Manage />,
element: <Landing />,
index: true,
},
{
element: <Compare />,
path: "compare/:comparedScheduleId?",
element: <Discover />,
path: "explore",
},
{
element: <Schedule />,
path: "schedules/:scheduleId",
children: [
{
element: <Manage />,
index: true,
},
{
element: <Compare />,
path: "compare/:comparedScheduleId?",
},
],
},
{
element: <Map />,
path: "map",
},
],
},
],
},
{
element: <Layout />,
children: [
{
element: <About />,
path: "about",
},
],
},
{
element: <Layout footer={false} />,
children: [
{
element: <Catalog />,
path: "catalog/:year?/:semester?/:subject?/:courseNumber?/:classNumber?",
},
{
element: <Schedules />,
path: "schedules",
},
{
element: <Plan />,
path: "plan",
element: <BaseLayout />,
children: [
{
element: <About />,
path: "about",
},
],
},
{
element: <Map />,
path: "map",
element: <BaseLayout footer={false} />,
children: [
{
element: <Catalog />,
path: "catalog/:year?/:semester?/:subject?/:courseNumber?/:classNumber?",
children: [
{
element: <Overview />,
index: true,
},
{
element: <Sections />,
path: "sections",
},
{
element: <Enrollment />,
path: "enrollment",
},
{
element: <Grades />,
path: "grades",
},
],
},
{
element: <Schedules />,
path: "schedules",
},
{
element: <Plan />,
path: "plan",
},
],
},
],
},
Expand Down
31 changes: 30 additions & 1 deletion frontend/src/app/Catalog/Class/Class.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,35 @@
height: 128px;
}

.dropdown {
display: flex;
flex-direction: column;
padding: 4px;
background-color: var(--foreground-color);
border: 1px solid var(--border-color);
border-radius: 4px;
box-shadow: 0 4px 8px rgb(0 0 0 / 5%);
z-index: 999;

.item {
display: flex;
align-items: center;
gap: 12px;
padding: 0 12px 0 8px;
height: 32px;
border-radius: 4px;
color: var(--paragraph-color);
cursor: pointer;
font-size: 14px;
font-weight: 500;
line-height: 1;

&:hover {
background-color: var(--button-hover-color);
}
}
}

.root {
flex-grow: 1;
display: flex;
Expand All @@ -24,7 +53,7 @@
.row {
display: flex;
justify-content: space-between;
margin-bottom: 24px;
margin-bottom: 32px;
}

.group {
Expand Down
45 changes: 31 additions & 14 deletions frontend/src/app/Catalog/Class/Enrollment/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { useMemo } from "react";

import { useQuery } from "@apollo/client";
import {
CartesianGrid,
Line,
Expand All @@ -9,12 +12,13 @@ import {
YAxis,
} from "recharts";

import { IClass } from "@/lib/api";
import useCatalog from "@/hooks/useCatalog";
import { GET_CLASS, IClass } from "@/lib/api";

import styles from "./Enrollment.module.scss";
import Reservations from "./Reservations";

const data = [
const series = [
{
name: "Page A",
uv: 0,
Expand Down Expand Up @@ -59,11 +63,26 @@ const data = [
},
];

interface EnrollmentProps {
currentClass?: IClass;
}
export default function Enrollment() {
const { subject, courseNumber, classNumber, semester, year } = useCatalog();

// TODO: Handle loading state
const { data } = useQuery<{ class: IClass }>(GET_CLASS, {
variables: {
term: {
semester,
year,
},
subject,
courseNumber,
classNumber,
},
});

// Because Sections will only be rendered when data loaded, we do
// not need to worry about loading or error states for right now
const _class = useMemo(() => data?.class as IClass, [data]);

export default function Enrollment({ currentClass }: EnrollmentProps) {
return (
<div className={styles.root}>
<div className={styles.legend}>
Expand All @@ -81,7 +100,7 @@ export default function Enrollment({ currentClass }: EnrollmentProps) {
<LineChart
width={500}
height={300}
data={data}
data={series}
margin={{ top: 8, right: 8, bottom: 8, left: 8 }}
>
<CartesianGrid
Expand Down Expand Up @@ -128,13 +147,11 @@ export default function Enrollment({ currentClass }: EnrollmentProps) {
</LineChart>
</ResponsiveContainer>
</div>
{currentClass && (
<Reservations
enrollCount={currentClass.primarySection.enrollCount}
enrollMax={currentClass.primarySection.enrollMax}
reservations={currentClass.primarySection.reservations}
/>
)}
<Reservations
enrollCount={_class.primarySection.enrollCount}
enrollMax={_class.primarySection.enrollMax}
reservations={_class.primarySection.reservations}
/>
</div>
);
}
28 changes: 20 additions & 8 deletions frontend/src/app/Catalog/Class/Grades/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ import {
Bar,
BarChart,
CartesianGrid,
LabelList,
Legend,
ResponsiveContainer,
Tooltip,
XAxis,
YAxis,
} from "recharts";

import styles from "./Grades.module.scss";
Expand Down Expand Up @@ -54,13 +53,26 @@ export default function Grades() {
<div className={styles.root}>
<ResponsiveContainer width="100%" height="100%">
<BarChart width={730} height={250} data={data}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="grade" />
<YAxis />
<Tooltip />
<CartesianGrid strokeDasharray="3 3" vertical={false} />
<XAxis dataKey="grade" fill="var(--label-color)" tickMargin={8} />
<Legend />
<Bar dataKey="percentage" fill="#8884d8" />
<Bar dataKey="average" fill="#82ca9d" />
<Bar dataKey="percentage" fill="var(--blue-500)">
<LabelList
dataKey="percentage"
position="insideTop"
offset={16}
fontSize={12}
fill="var(--label-color)"
/>
</Bar>
<Bar dataKey="average" fill="var(--label-color)">
<LabelList
dataKey="average"
position="top"
fontSize={12}
fill="var(--label-color)"
/>
</Bar>
</BarChart>
</ResponsiveContainer>
</div>
Expand Down
Loading

0 comments on commit 48b05ae

Please sign in to comment.