From bc464cd264ae0973e003ff788d390edd0dafbff1 Mon Sep 17 00:00:00 2001 From: Sriram Hariharan Date: Sat, 4 Mar 2023 22:42:51 -0600 Subject: [PATCH] lots of UI changes, and keyboard command support --- src/shared/types/CourseSchedule.ts | 4 +-- src/views/components/CourseCatalogMain.tsx | 8 +++-- .../components/common/Panel/Panel.module.scss | 24 +++++++++++++ src/views/components/common/Panel/Panel.tsx | 31 ++++++++++++++++ .../CoursePanel/CoursePanel.module.scss | 35 +++++++++++++++++++ .../injected/CoursePanel/CoursePanel.tsx | 26 ++++++++++++++ .../CoursePopup/CoursePopup.module.scss | 0 .../injected/CoursePopup/CoursePopup.tsx | 19 ---------- src/views/hooks/useKeyPress.ts | 20 +++++++++++ 9 files changed, 143 insertions(+), 24 deletions(-) create mode 100644 src/views/components/common/Panel/Panel.module.scss create mode 100644 src/views/components/common/Panel/Panel.tsx create mode 100644 src/views/components/injected/CoursePanel/CoursePanel.module.scss create mode 100644 src/views/components/injected/CoursePanel/CoursePanel.tsx delete mode 100644 src/views/components/injected/CoursePopup/CoursePopup.module.scss delete mode 100644 src/views/components/injected/CoursePopup/CoursePopup.tsx create mode 100644 src/views/hooks/useKeyPress.ts diff --git a/src/shared/types/CourseSchedule.ts b/src/shared/types/CourseSchedule.ts index 6ab6192e..18cf3b0d 100644 --- a/src/shared/types/CourseSchedule.ts +++ b/src/shared/types/CourseSchedule.ts @@ -14,10 +14,10 @@ const DAY_MAP = { } as const; /** A day of the week that a class is taught */ -type Day = typeof DAY_MAP[keyof typeof DAY_MAP]; +export type Day = typeof DAY_MAP[keyof typeof DAY_MAP]; /** A physical room that a class is taught in */ -type Room = { +export type Room = { /** The UT building code for where the class is taught */ building: string; /** The room number for where the class is taught */ diff --git a/src/views/components/CourseCatalogMain.tsx b/src/views/components/CourseCatalogMain.tsx index 443fed55..a6701328 100644 --- a/src/views/components/CourseCatalogMain.tsx +++ b/src/views/components/CourseCatalogMain.tsx @@ -1,12 +1,12 @@ import React, { useEffect, useState } from 'react'; -import ReactDOM from 'react-dom'; import { Course, CourseRow } from 'src/shared/types/Course'; import useInfiniteScroll from '../hooks/useInfiniteScroll'; +import { useKeyPress } from '../hooks/useKeyPress'; import { CourseScraper } from '../lib/courseCatalog/CourseScraper'; import { populateSearchInputs } from '../lib/courseCatalog/populateSearchInputs'; import { SiteSupport } from '../lib/getSiteSupport'; import ExtensionRoot from './common/ExtensionRoot/ExtensionRoot'; -import CoursePopup from './injected/CoursePopup/CoursePopup'; +import CoursePanel from './injected/CoursePanel/CoursePanel'; import TableHead from './injected/TableHead'; import TableRow from './injected/TableRow'; @@ -45,6 +45,8 @@ export default function CourseCatalogMain({ support }: Props) { setSelectedCourse(null); }; + useKeyPress('Escape', handleClearSelectedCourse); + return ( Plus @@ -56,7 +58,7 @@ export default function CourseCatalogMain({ support }: Props) { onClick={handleRowButtonClick(row.course)} /> ))} - {selectedCourse && } + {selectedCourse && } {isScrolling &&
Scrolling...
}
); diff --git a/src/views/components/common/Panel/Panel.module.scss b/src/views/components/common/Panel/Panel.module.scss new file mode 100644 index 00000000..2b481499 --- /dev/null +++ b/src/views/components/common/Panel/Panel.module.scss @@ -0,0 +1,24 @@ +@import 'src/views/styles/base.module.scss'; + +.container { + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + position: fixed; + top: 0; + + &.overlay { + background-color: rgba(0, 0, 0, 0.5); + z-index: 2147483647; + } +} + +.body { + overflow-y: auto; + z-index: 2147483647; + background-color: rgb(52, 53, 65); + box-shadow: 0px 12px 30px 0px #323e5f29; + transition: box-shadow 0.15s; +} diff --git a/src/views/components/common/Panel/Panel.tsx b/src/views/components/common/Panel/Panel.tsx new file mode 100644 index 00000000..819743c4 --- /dev/null +++ b/src/views/components/common/Panel/Panel.tsx @@ -0,0 +1,31 @@ +import classNames from 'classnames'; +import React, { PropsWithChildren } from 'react'; +import styles from './Panel.module.scss'; + +interface Props { + testId?: string; + style?: React.CSSProperties; + className?: string; + overlay?: boolean; +} + +/** + * + */ +export default function Panel(props: PropsWithChildren) { + return ( +
+
{props.children}
+
+ ); +} diff --git a/src/views/components/injected/CoursePanel/CoursePanel.module.scss b/src/views/components/injected/CoursePanel/CoursePanel.module.scss new file mode 100644 index 00000000..3aeca90a --- /dev/null +++ b/src/views/components/injected/CoursePanel/CoursePanel.module.scss @@ -0,0 +1,35 @@ +.panelBody { + height: auto; + color: white; + padding: 10px; + display: flex; + align-items: center; + justify-content: center; +} + +.coursePanelBase { + position: fixed; + transform: translateY(-50%); + top: 15px; + right: 15px; + z-index: 2147483647; +} + +.coursePanelHeader { + display: flex; + height: 50; + background-color: #29465b; + width: 100%; + + .closePanelButton { + display: flex; + align-items: center; + justify-content: center; + width: 20px; + height: 20px; + margin: 5px; + margin-left: auto; + cursor: pointer; + color: white; + } +} diff --git a/src/views/components/injected/CoursePanel/CoursePanel.tsx b/src/views/components/injected/CoursePanel/CoursePanel.tsx new file mode 100644 index 00000000..873f74ae --- /dev/null +++ b/src/views/components/injected/CoursePanel/CoursePanel.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Course } from 'src/shared/types/Course'; +import Panel from '../../common/Panel/Panel'; +import styles from './CoursePanel.module.scss'; + +interface Props { + course: Course; + onClose: () => void; +} + +export default function CoursePanel({ course, onClose }: Props) { + return ( + +
+
+ ✕ +
+
+ +
+
{course.courseName}
+
{course.uniqueId}
+
+
+ ); +} diff --git a/src/views/components/injected/CoursePopup/CoursePopup.module.scss b/src/views/components/injected/CoursePopup/CoursePopup.module.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/src/views/components/injected/CoursePopup/CoursePopup.tsx b/src/views/components/injected/CoursePopup/CoursePopup.tsx deleted file mode 100644 index fa9cc868..00000000 --- a/src/views/components/injected/CoursePopup/CoursePopup.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import { Course } from 'src/shared/types/Course'; -import { Button } from '../../common/Button/Button'; -import styles from './CoursePopup.module.scss'; - -interface Props { - course: Course; - onClose: () => void; -} - -export default function CoursePopup({ course, onClose }: Props) { - return ( -
-

{course.fullName}

-

{course.description}

- -
- ); -} diff --git a/src/views/hooks/useKeyPress.ts b/src/views/hooks/useKeyPress.ts new file mode 100644 index 00000000..24edf9f8 --- /dev/null +++ b/src/views/hooks/useKeyPress.ts @@ -0,0 +1,20 @@ +import { useEffect } from 'react'; + +/** + * Hook that calls a callback when a key is pressed + * @param key the key to listen for + * @param callback the callback to call when the key is pressed + */ +export function useKeyPress(key: string, callback: (...args: any[]) => void): void { + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === key) { + callback(); + } + }; + document.addEventListener('keydown', handleKeyDown); + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [key, callback]); +}