Skip to content

Commit

Permalink
Implemented quartercard, catalog, and degree plan. Refactored existin…
Browse files Browse the repository at this point in the history
…g code.
  • Loading branch information
xiaolongbytes committed Nov 3, 2024
1 parent cb2c4d1 commit 89c6d29
Show file tree
Hide file tree
Showing 18 changed files with 341 additions and 70 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# Problem
TODO:

# Figma
TODO:

# Lessons Learned:
- BEM naming convention for class names
- block__element--modifier
- The Typescript + React FunctionComponent pattern for defining component function signature

# Getting Started with Create React App

This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
Expand Down
38 changes: 38 additions & 0 deletions src/App.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
h1, h2, h3, h4, h5, h6, p, span, a {
font-family: sans-serif
}

.App {
padding: 1em;
max-width: 1600px;
margin: 0 auto;
display: grid;
gap: 0 1em;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto;
grid-template-areas:
"header header header"
"coursecatalog form quartercatalog";
}

@media screen and (max-width: 1000px) {
.App {
grid-template-columns: repeat(2, 1fr);
grid-template-areas:
"header header"
"form form"
"coursecatalog quartercatalog";
}
}
.App__header {
grid-area: header;
}

.App__coursecatalog {
grid-area: coursecatalog;
}

.App__form {
grid-area: form;
}

.App__quartercatalog {
grid-area: quartercatalog;
}
8 changes: 0 additions & 8 deletions src/App.test.js

This file was deleted.

117 changes: 66 additions & 51 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,71 +1,86 @@
import React from 'react';
import { SeasonBadge } from './components/SeasonBadge/SeasonBadge';
import { v4 } from 'uuid';
import { ALL_OFFERED_COURSES, Season, COURSE_IDS, UUID, Quarter, Course } from './common/constants';
import { PrerequisiteBadge } from './components/PrerequisiteBadge/PrerequisiteBadge';
import { NoPrerequisiteBadge } from './components/PrerequisiteBadge/NoPrerequisitesBadge';
import { PrerequisitesList } from './components/PrerequisitesList/PrerequisitesList';
import { CourseCard } from './components/CourseCard/CourseCard';
import { ALL_OFFERED_COURSES, Season, COURSE_IDS, UUID, Quarter } from './common/constants';
import './common/reset.css';
import './common/variables.css';
import './App.css';
import { CourseCatalog } from './components/CourseCatalog/CourseCatalog';
import { DegreePlan } from './components/DegreePlan/DegreePlan';

const exampleQuarter: Quarter = {
const fall2024: Quarter = {
id: v4(),
season: Season.FALL,
year: 2024,
};
const winter2024: Quarter = {
id: v4(),
season: Season.WINTER,
year: 2024,
};
const spring2025: Quarter = {
id: v4(),
season: Season.SPRING,
year: 2025,
};
const summer2025: Quarter = {
id: v4(),
season: Season.SPRING,
year: 2025,
};

const exampleQuarters = [fall2024, winter2024, spring2025, summer2025];

const exampleQuartersToCourses: Record<UUID, UUID[]> = {
[exampleQuarter.id]: [COURSE_IDS.CS161],
[fall2024.id]: [COURSE_IDS.CS161],
[winter2024.id]: [COURSE_IDS.CS162],
[spring2025.id]: [COURSE_IDS.CS225],
[summer2025.id]: [COURSE_IDS.CS261],
};

const exampleCourse: Course = {
id: COURSE_IDS.CS325,
isRequired: true,
fullName: 'Analysis of Algorithms',
courseCode: 'CS325',
prerequisiteCourseIDs: [COURSE_IDS.CS225, COURSE_IDS.CS261],
offeredIn: [Season.FALL, Season.WINTER, Season.SPRING, Season.SUMMER],
};
// const exampleCourse: Course = {
// id: COURSE_IDS.CS325,
// isRequired: true,
// fullName: 'Analysis of Algorithms',
// courseCode: 'CS325',
// prerequisiteCourseIDs: [COURSE_IDS.CS225, COURSE_IDS.CS261],
// offeredIn: [Season.FALL, Season.WINTER, Season.SPRING, Season.SUMMER],
// };

function App() {
const App = () => {
return (
<div className="App">
<SeasonBadge season={Season.FALL} />
<SeasonBadge season={Season.WINTER} />
<SeasonBadge season={Season.SPRING} />
<SeasonBadge season={Season.SUMMER} />
<br />
<PrerequisiteBadge courseName="CS161" isFulfilled={true} />
<PrerequisiteBadge courseName="CS161" isFulfilled={false} />
<NoPrerequisiteBadge />
<br />
<PrerequisitesList
allOfferedCourses={ALL_OFFERED_COURSES}
prerequisiteCourseIDs={[]}
quartersToCourses={exampleQuartersToCourses}
/>
<PrerequisitesList
allOfferedCourses={ALL_OFFERED_COURSES}
prerequisiteCourseIDs={[COURSE_IDS.CS162]}
quartersToCourses={exampleQuartersToCourses}
/>
<CourseCard
isSelected={false}
course={exampleCourse}
allOfferedCourses={ALL_OFFERED_COURSES}
onCourseSelect={_ => {}}
quartersToCourses={exampleQuartersToCourses}
/>
<CourseCard
isSelected
course={exampleCourse}
allOfferedCourses={ALL_OFFERED_COURSES}
onCourseSelect={_ => {}}
quartersToCourses={exampleQuartersToCourses}
/>
<div className="App__header">{/* TODO */}</div>
<div className="App__coursecatalog">
<CourseCatalog
allOfferedCourses={ALL_OFFERED_COURSES}
selectedCourse={null}
courses={ALL_OFFERED_COURSES}
onCourseSelect={_ => {}}
quartersToCourses={exampleQuartersToCourses}
/>
</div>
<div className="App__form">
<div style={{ height: '500px', width: '100%', backgroundColor: '#eee' }} />
{/* TODO */}
</div>
<div className="App__quartercatalog">
{/* <QuarterCard
quarter={fall2024}
quartersToCourses={exampleQuartersToCourses}
allOfferedCourses={ALL_OFFERED_COURSES}
onCourseSelect={_ => {}}
selectedCourse={null}
/> */}
<DegreePlan
quarters={exampleQuarters}
allOfferedCourses={ALL_OFFERED_COURSES}
quartersToCourses={exampleQuartersToCourses}
selectedCourse={null}
onCourseSelect={_ => {}}
/>
</div>
</div>
);
}
};

export default App;
1 change: 1 addition & 0 deletions src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export const ALL_OFFERED_COURSES: Course[] = [
prerequisiteCourseIDs: [],
offeredIn: [Season.FALL, Season.WINTER, Season.SPRING, Season.SUMMER],
},
// TODO: CHECK PREREQS FOR CS261, THIS DOESN'T SEEM RIGHT
{
id: COURSE_IDS.CS261,
isRequired: true,
Expand Down
4 changes: 4 additions & 0 deletions src/common/reset.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,7 @@ table {
border-collapse: collapse;
border-spacing: 0;
}

* {
box-sizing: border-box;
}
5 changes: 5 additions & 0 deletions src/common/variables.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
:root {
--white: #FFF;
--border-radius: 5px;
--border-color: #eee;
}
3 changes: 2 additions & 1 deletion src/components/CourseCard/CourseCard.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
.coursecard {
display: flex;
flex-direction: column;
max-width: 400px;
padding: 1em;
border-radius: 8px;
border: 1px lightgray solid;
background-color: white;
cursor: pointer;
}

.coursecard--selected {
Expand Down
8 changes: 7 additions & 1 deletion src/components/CourseCard/CourseCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ type CourseCardProps = {
isSelected: boolean;
course: Course;
allOfferedCourses: Course[];
/**
* Callback for when a course is selected
*/
onCourseSelect: (course: Course) => void;
quartersToCourses: Record<UUID, UUID[]>;
};
Expand All @@ -17,9 +20,12 @@ export const CourseCard: FunctionComponent<CourseCardProps> = ({
course,
allOfferedCourses,
quartersToCourses,
onCourseSelect,
}) => {
return (
<div className={`coursecard ${isSelected ? 'coursecard--selected' : ''}`}>
<div
onClick={() => onCourseSelect(course)}
className={`coursecard ${isSelected ? 'coursecard--selected' : ''}`}>
<div className="coursecard__header">
<p>
{course.courseCode} - {course.fullName}
Expand Down
26 changes: 26 additions & 0 deletions src/components/CourseCatalog/CourseCatalog.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.coursecatalog__header {
font-size: larger;
font-weight: bold;
padding: 0.5em 0em;
}

.coursecatalog {
/* max-width: 500px; */
}

.coursecatalog__body {
display: flex;
flex-direction: column;
gap: 0.5em;
align-items: center;
max-height: 80vh;
overflow-y: auto;
padding: 0.5em 1em;
border: 1px solid #eee;
border-radius: 8px;
background-color: #f2f2f2;
}

.coursecatalog__body .coursecard {
align-self: stretch;
}
38 changes: 38 additions & 0 deletions src/components/CourseCatalog/CourseCatalog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, { FunctionComponent } from 'react';
import { Course, UUID } from '../../common/constants';
import { CourseCard } from '../CourseCard/CourseCard';
import './CourseCatalog.css';

type CourseCatalogProps = {
allOfferedCourses: Course[];
selectedCourse: Course | null;
courses: Course[];
onCourseSelect: (course: Course) => void;
quartersToCourses: Record<UUID, UUID[]>;
};

export const CourseCatalog: FunctionComponent<CourseCatalogProps> = ({
allOfferedCourses,
selectedCourse,
courses,
onCourseSelect,
quartersToCourses,
}) => {
return (
<div className="coursecatalog">
<p className="coursecatalog__header">Course Catalog</p>
<div className="coursecatalog__body">
{courses.map(course => (
<CourseCard
isSelected={selectedCourse?.id === course.id}
course={course}
allOfferedCourses={allOfferedCourses}
onCourseSelect={onCourseSelect}
quartersToCourses={quartersToCourses}
key={course.id}
/>
))}
</div>
</div>
);
};
20 changes: 20 additions & 0 deletions src/components/DegreePlan/DegreePlan.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.degreeplan {
/* max-width: 500px; */
}

.degreeplan__header {
font-size: larger;
font-weight: bold;
padding: 0.5em 0em;
}

.degreeplan__body {
display: flex;
flex-direction: column;
/* gap: 0.5em; */
max-height: 80vh;
overflow-y: auto;
border: 1px solid #eee;
border-radius: 8px;
background-color: #f2f2f2;
}
38 changes: 38 additions & 0 deletions src/components/DegreePlan/DegreePlan.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, { FunctionComponent } from 'react';
import { Course, Quarter, UUID } from '../../common/constants';
import './DegreePlan.css';
import { QuarterCard } from '../QuarterCard/QuarterCard';

type DegreePlanProps = {
quarters: Quarter[];
allOfferedCourses: Course[];
quartersToCourses: Record<UUID, UUID[]>;
selectedCourse: Course | null;
onCourseSelect: (course: Course) => void;
};

export const DegreePlan: FunctionComponent<DegreePlanProps> = ({
quarters,
allOfferedCourses,
quartersToCourses,
selectedCourse,
onCourseSelect,
}) => {
return (
<div className="degreeplan">
<p className="degreeplan__header">Degree Plan</p>
<div className="degreeplan__body">
{quarters.map(quarter => (
<QuarterCard
selectedCourse={selectedCourse}
quarter={quarter}
quartersToCourses={quartersToCourses}
allOfferedCourses={allOfferedCourses}
onCourseSelect={onCourseSelect}
key={quarter.id}
/>
))}
</div>
</div>
);
};
Loading

0 comments on commit 89c6d29

Please sign in to comment.