Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework catalog section design #576

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 4 additions & 9 deletions frontend/src/Berkeleytime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const Berkeleytime = () => {
});

useEffect(() => {
observe(document.getElementById('root'));
// Fetch enrollment context early on for catalog and enrollment page.
dispatch(fetchEnrollContext());

Expand All @@ -41,15 +42,9 @@ const Berkeleytime = () => {
if (localStorage.getItem(key) === null) {
localStorage.setItem(key, key);
}
}, [dispatch]);

return (
<div ref={observe} className="app">
<IconoirProvider iconProps={{ strokeWidth: 2 }}>
<Routes />
</IconoirProvider>
</div>
);
}, [dispatch, observe]);

return <Routes />;
};

export default memo(Berkeleytime);
8 changes: 6 additions & 2 deletions frontend/src/app/Catalog/CatalogList/CatalogList.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,13 @@
}
}

.grade {
.gradeWrapper {
display: flex;
justify-content: center;
flex-direction: column;

span {
line-height: 20px;
}
}

.A {
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/app/Catalog/CatalogList/CatalogListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const CatalogListItem = ({ style, data }: CatalogListItemProps) => {
<h6>{`${course.abbreviation} ${course.courseNumber}`}</h6>
<p>{course.title}</p>
</div>
<div>
<div className={styles.gradeWrapper}>
{user && (
<div
className={styles.saveIcon}
Expand All @@ -67,14 +67,14 @@ const CatalogListItem = ({ style, data }: CatalogListItemProps) => {
{isSaved ? <BookmarkSaved /> : <BookmarkUnsaved />}
</div>
)}
<span className={`${styles.grade} ${styles[course.letterAverage[0]]}`}>
<span className={`${styles[course.letterAverage[0]]}`}>
{course.letterAverage !== '' ? course.letterAverage : ''}
</span>
</div>
</div>
<div className={styles.itemStats}>
<span className={colorEnrollment(course.enrolledPercentage)}>
{formatEnrollment(course.enrolledPercentage)}
{formatEnrollment(course.enrolledPercentage)} enrolled
</span>
<span> • {course.units ? formatUnits(course.units) : 'N/A'}</span>
</div>
Expand Down
62 changes: 44 additions & 18 deletions frontend/src/app/Catalog/CatalogView/CatalogView.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
flex-direction: column;
padding: 30px;
gap: 15px;
overflow-y: auto;
overflow-y: overlay;
overflow-x: hidden;
-webkit-animation: fadeIn 0.1s;
animation: fadeIn 0.1s;
Expand All @@ -37,10 +37,6 @@
color: $bt-base-text;
font-weight: 700;
font-size: 18px;

span {
color: $bt-blue;
}
}

h6 {
Expand Down Expand Up @@ -210,29 +206,59 @@
.sectionItem {
display: flex;
flex-direction: row;
// background: #F8F8F8;
padding: 12px 24px;
border-radius: 12px !important;
padding: 12px;
border-radius: 16px;
border: 1.5px solid #eaeaea;
gap: 20px;
h5 {
gap: 30px;

h6 {
font-size: 16px;
min-height: 21px;
margin: 0;
font-weight: bold;
color: $bt-base-text;
}
}

.sectionInfo {
display: flex;
flex-direction: column;
flex: 1;

h6 {
font-size: 14px;
span {
text-transform: capitalize;
}
display: flex;
align-items: center;
min-height: 24px;
}
}

.sectionInfo {
.instructor {
display: flex;
gap: 5px;
align-items: center;
font-size: 14px;
color: $bt-light-grey;
text-transform: capitalize;
gap: 4px;
min-height: 24px;
color: $bt-light-text;
}

.sectionContent {
display: flex;
flex-direction: column;
flex: 1;
justify-content: flex-start;
font-size: 14px;

span {
display: inline-flex;
justify-content: flex-end;
align-items: center;
line-height: 20px;
gap: 4px;
color: $bt-light-text;
text-align: right;
}
}

.sectionStats {
Expand All @@ -241,14 +267,14 @@
flex-wrap: wrap;
gap: 5px;
color: $bt-light-text;
margin-top: 5px;
margin-top: 12px;
font-size: 14px;
text-transform: none !important;
}

.enrolled {
display: flex;
justify-content: center;
justify-content: flex-end;
align-items: center;
font-size: 14px;
font-weight: 600;
Expand Down
41 changes: 19 additions & 22 deletions frontend/src/app/Catalog/CatalogView/CatalogView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const CatalogView = (props: CatalogViewProps) => {
)?.id ?? null
);

const [getCourse, { data, loading }] = useGetCourseForNameLazyQuery({
const [getCourse, { data }] = useGetCourseForNameLazyQuery({
onCompleted: (data) => {
const course = data.allCourses.edges[0].node;
if (course) {
Expand Down Expand Up @@ -89,17 +89,23 @@ const CatalogView = (props: CatalogViewProps) => {
const [playlists, sections] = useMemo(() => {
let playlists = null;
let sections = null;
// let semesters = null;

if (course?.playlistSet) {
const { edges } = course.playlistSet;
playlists = catalogService.sortPills(edges.map((e) => e.node as PlaylistType));

// semesters = catalogService.sortSemestersByLatest(
// edges.map((e) => e.node).filter((n) => n.category === 'semester')
// );
}

if (course?.sectionSet) {
const { edges } = course.sectionSet;
sections = sortSections(edges.map((e) => e.node));
}

// return [playlists ?? skeleton, sections ?? [], semesters];
return [playlists ?? skeleton, sections ?? null];
}, [course]);

Expand Down Expand Up @@ -132,19 +138,19 @@ const CatalogView = (props: CatalogViewProps) => {

return (
<div className={`${styles.root}`} data-modal={isOpen}>
<button
className={styles.modalButton}
onClick={() => {
setCurrentCourse(null);
setCourse(null);
navigate(`/catalog/${semester}`, { replace: true });
}}
>
<BackArrow />
Back to Courses
</button>
{course && (
<>
<button
className={styles.modalButton}
onClick={() => {
setCurrentCourse(null);
setCourse(null);
navigate(`/catalog/${semester}`);
}}
>
<BackArrow />
Back to Courses
</button>
<h3>
{course.abbreviation} {course.courseNumber}
</h3>
Expand Down Expand Up @@ -211,16 +217,7 @@ const CatalogView = (props: CatalogViewProps) => {
</>
</ReadMore>
<h5>Class Times - {semester ?? ''}</h5>
{sections && sections.length > 0 ? (
<SectionTable sections={sections} />
) : !loading ? (
<span>There are no class times for the selected course.</span>
) : null}

{/*
Redesigned catalog sections
<CatalogViewSections sections={sections} />
*/}
<SectionTable sections={sections} />

{/* Good feature whenever we want...
<h5>Past Offerings</h5>
Expand Down
108 changes: 64 additions & 44 deletions frontend/src/app/Catalog/CatalogView/SectionTable.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { SectionFragment } from 'graphql';
import { CSSProperties } from 'react';
import { Table } from 'react-bootstrap';
import { formatSectionTime } from 'utils/sections/section';
import catalogService from '../service';
import Skeleton from 'react-loading-skeleton';

import denero from 'assets/img/eggs/denero.png';
import hug from 'assets/img/eggs/hug.png';
Expand All @@ -9,9 +11,13 @@ import sahai from 'assets/img/eggs/sahai.png';
import scott from 'assets/img/eggs/scott.png';
import kubi from 'assets/img/eggs/kubi.png';
import garcia from 'assets/img/eggs/garcia.png';
import { formatSectionTime } from 'utils/sections/section';
import { Clock, Group, PinAlt, User } from 'iconoir-react';

import styles from './CatalogView.module.scss';

const easterEggImages = new Map<string, string>([
const { colorEnrollment } = catalogService;

const easterEggImages = new Map([
['DENERO J', denero],
['HUG J', hug],
['SAHAI A', sahai],
Expand All @@ -35,52 +41,66 @@ function findInstructor(instr: string | null): CSSProperties {
return {};
}

type Props = {
interface Props {
sections: SectionFragment[] | null;
};
}

const SectionTable = ({ sections }: Props) => {
if (!sections) {
return (
<Skeleton
className={styles.sectionItem}
count={3}
height={65}
style={{ marginBottom: '10px' }}
/>
);
}

return (
<section className="table-container description-section">
<div>
<Table className="table">
<thead>
<tr>
<th style={{ width: '75px' }}>Type</th>
<th style={{ width: '50px' }}>CCN</th>
<th style={{ width: '100px' }}>Instructor</th>
<th style={{ width: '130px' }}>Time</th>
<th style={{ width: '85px' }}>Location</th>
<th style={{ width: '75px' }}>Enrolled</th>
<th style={{ width: '75px' }}>Waitlist</th>
</tr>
</thead>
<tbody>
{sections?.map((section) => {
return (
<tr key={section.ccn} style={findInstructor(section.instructor)}>
<td>{section.kind}</td>
<td>{section.ccn}</td>
<td>{section.instructor}</td>
{section.startTime && section.endTime ? (
<td>
{section.wordDays} {formatSectionTime(section)}
</td>
) : (
<td></td>
)}
<td>{section.locationName}</td>
<td>
<div className={styles.sectionRoot}>
{sections.length > 0 ? (
sections.map((section) => {
const color = colorEnrollment(section.enrolled / section.enrolledMax);

return (
<div
className={styles.sectionItem}
style={findInstructor(section.instructor)}
key={section.ccn}
>
<div className={styles.sectionInfo}>
<h6>{section.kind}</h6>
<span className={styles.instructor}>
<User width={14} />
{section.instructor?.toLowerCase() || 'unknown'}
</span>
<div className={styles.sectionStats}>
<div className={`${color} ${styles.enrolled}`}>
<Group width={16} height={24} />
{section.enrolled}/{section.enrolledMax}
</td>
<td>{section.waitlisted}</td>
</tr>
);
})}
</tbody>
</Table>
</div>
</section>
</div>
<div className={styles.enrolled}>• {section.waitlisted} Waitlisted</div>
{/* <span>• CCN {section.ccn}</span> */}
</div>
</div>
<div className={styles.sectionContent}>
<span>
<PinAlt width={16} height={24} />
{section.locationName || 'Unknown'}
</span>
<span>
<Clock width={16} height={24} />
{section.wordDays} {formatSectionTime(section)}
</span>
</div>
</div>
);
})
) : (
<div>There are no class sections for this course.</div>
)}
</div>
);
};

Expand Down
Loading