feat: refactor all components in injected

This commit is contained in:
doprz
2024-03-04 14:51:14 -06:00
parent f93a98e46a
commit 0c44849e15
10 changed files with 27 additions and 30 deletions

View File

@@ -10,7 +10,7 @@ import { useKeyPress } from '@views/hooks/useKeyPress';
import useSchedules from '@views/hooks/useSchedules'; import useSchedules from '@views/hooks/useSchedules';
import { CourseCatalogScraper } from '@views/lib/CourseCatalogScraper'; import { CourseCatalogScraper } from '@views/lib/CourseCatalogScraper';
import getCourseTableRows from '@views/lib/getCourseTableRows'; import getCourseTableRows from '@views/lib/getCourseTableRows';
import type { SiteSupport, SiteSupportType } from '@views/lib/getSiteSupport'; import type { SiteSupportType } from '@views/lib/getSiteSupport';
import { populateSearchInputs } from '@views/lib/populateSearchInputs'; import { populateSearchInputs } from '@views/lib/populateSearchInputs';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
@@ -21,7 +21,7 @@ interface Props {
/** /**
* This is the top level react component orchestrating the course catalog page. * This is the top level react component orchestrating the course catalog page.
*/ */
export default function CourseCatalogMain({ support }: Props) { export default function CourseCatalogMain({ support }: Props): JSX.Element {
const [rows, setRows] = React.useState<ScrapedRow[]>([]); const [rows, setRows] = React.useState<ScrapedRow[]>([]);
const [selectedCourse, setSelectedCourse] = useState<Course | null>(null); const [selectedCourse, setSelectedCourse] = useState<Course | null>(null);

View File

@@ -21,7 +21,7 @@ import SettingsIcon from '~icons/material-symbols/settings';
* Renders the main popup component. * Renders the main popup component.
* This component displays the main schedule, courses, and options buttons. * This component displays the main schedule, courses, and options buttons.
*/ */
export default function PopupMain() { export default function PopupMain(): JSX.Element {
const [activeSchedule, schedules] = useSchedules(); const [activeSchedule, schedules] = useSchedules();
const [isPopupVisible, setIsPopupVisible] = useState(false); const [isPopupVisible, setIsPopupVisible] = useState(false);
const popupRef = useRef(null); const popupRef = useRef(null);

View File

@@ -9,6 +9,7 @@ type Props = {
* @param props className * @param props className
* @returns The content for the settings page * @returns The content for the settings page
*/ */
export default function Settings({ className }: Props) { export default function Settings({ className }: Props): JSX.Element {
// TODO: Implement the settings page
return <div className={className}>this will be finished laterrrrrrr</div>; return <div className={className}>this will be finished laterrrrrrr</div>;
} }

View File

@@ -21,7 +21,7 @@ type Props = {
* This component is responsible for loading the next page of courses when the user scrolls to the bottom of the page. * This component is responsible for loading the next page of courses when the user scrolls to the bottom of the page.
* @returns * @returns
*/ */
export default function AutoLoad({ addRows }: Props) { export default function AutoLoad({ addRows }: Props): JSX.Element {
const [container, setContainer] = useState<HTMLDivElement | null>(null); const [container, setContainer] = useState<HTMLDivElement | null>(null);
const [status, setStatus] = useState<AutoLoadStatusType>(AutoLoadStatus.IDLE); const [status, setStatus] = useState<AutoLoadStatusType>(AutoLoadStatus.IDLE);

View File

@@ -14,10 +14,10 @@ const LoadStatus = {
LOADING: 'LOADING', LOADING: 'LOADING',
DONE: 'DONE', DONE: 'DONE',
ERROR: 'ERROR', ERROR: 'ERROR',
} as const; } as const satisfies Record<string, string>;
type LoadStatusType = (typeof LoadStatus)[keyof typeof LoadStatus]; type LoadStatusType = (typeof LoadStatus)[keyof typeof LoadStatus];
async function fetchDescription(course: Course): Promise<string[]> { const fetchDescription = async (course: Course): Promise<string[]> => {
if (!course.description?.length) { if (!course.description?.length) {
const response = await fetch(course.url); const response = await fetch(course.url);
const text = await response.text(); const text = await response.text();
@@ -27,7 +27,7 @@ async function fetchDescription(course: Course): Promise<string[]> {
course.description = scraper.getDescription(doc); course.description = scraper.getDescription(doc);
} }
return course.description; return course.description;
} };
/** /**
* Renders the description component. * Renders the description component.
@@ -37,7 +37,7 @@ async function fetchDescription(course: Course): Promise<string[]> {
* @param {Course} props.course - The course for which to display the description. * @param {Course} props.course - The course for which to display the description.
* @returns {JSX.Element} The rendered description component. * @returns {JSX.Element} The rendered description component.
*/ */
const Description: React.FC<DescriptionProps> = ({ course }: DescriptionProps) => { export default function Description({ course }: DescriptionProps): JSX.Element {
const [description, setDescription] = React.useState<string[]>([]); const [description, setDescription] = React.useState<string[]>([]);
const [status, setStatus] = React.useState<LoadStatusType>(LoadStatus.LOADING); const [status, setStatus] = React.useState<LoadStatusType>(LoadStatus.LOADING);
@@ -82,6 +82,4 @@ const Description: React.FC<DescriptionProps> = ({ course }: DescriptionProps) =
)} )}
</> </>
); );
}; }
export default Description;

View File

@@ -21,7 +21,7 @@ const DataStatus = {
FOUND: 'FOUND', FOUND: 'FOUND',
NOT_FOUND: 'NOT_FOUND', NOT_FOUND: 'NOT_FOUND',
ERROR: 'ERROR', ERROR: 'ERROR',
} as const; } as const satisfies Record<string, string>;
type DataStatusType = (typeof DataStatus)[keyof typeof DataStatus]; type DataStatusType = (typeof DataStatus)[keyof typeof DataStatus];
const GRADE_COLORS = { const GRADE_COLORS = {
@@ -47,7 +47,7 @@ const GRADE_COLORS = {
* @param {Course} props.course - The course for which to display the grade distribution. * @param {Course} props.course - The course for which to display the grade distribution.
* @returns {JSX.Element} The grade distribution chart component. * @returns {JSX.Element} The grade distribution chart component.
*/ */
const GradeDistribution: React.FC<GradeDistributionProps> = ({ course }) => { export default function GradeDistribution({ course }: GradeDistributionProps): JSX.Element {
const [semester, setSemester] = React.useState('Aggregate'); const [semester, setSemester] = React.useState('Aggregate');
const [distributions, setDistributions] = React.useState<Record<string, Distribution>>({}); const [distributions, setDistributions] = React.useState<Record<string, Distribution>>({});
const [status, setStatus] = React.useState<DataStatusType>(DataStatus.LOADING); const [status, setStatus] = React.useState<DataStatusType>(DataStatus.LOADING);
@@ -187,6 +187,4 @@ const GradeDistribution: React.FC<GradeDistributionProps> = ({ course }) => {
)} )}
</div> </div>
); );
}; }
export default GradeDistribution;

View File

@@ -38,6 +38,12 @@ export const handleOpenCalendar = async (): Promise<void> => {
openNewTab({ url }); openNewTab({ url });
}; };
/**
* Capitalizes the first letter of a string and converts the rest of the letters to lowercase.
*
* @param str - The string to be capitalized.
* @returns The capitalized string.
*/
const capitalizeString = (str: string) => str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); const capitalizeString = (str: string) => str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
/** /**
@@ -49,11 +55,7 @@ const capitalizeString = (str: string) => str.charAt(0).toUpperCase() + str.slic
* @param {Function} props.onClose - The function to close the popup. * @param {Function} props.onClose - The function to close the popup.
* @returns {JSX.Element} The rendered component. * @returns {JSX.Element} The rendered component.
*/ */
const HeadingAndActions: React.FC<HeadingAndActionProps> = ({ export default function HeadingAndActions({ course, activeSchedule, onClose }: HeadingAndActionProps): JSX.Element {
course,
activeSchedule,
onClose,
}: HeadingAndActionProps): JSX.Element => {
const { courseName, department, number: courseNumber, uniqueId, instructors, flags, schedule } = course; const { courseName, department, number: courseNumber, uniqueId, instructors, flags, schedule } = course;
const courseAdded = activeSchedule.courses.some(ourCourse => ourCourse.uniqueId === uniqueId); const courseAdded = activeSchedule.courses.some(ourCourse => ourCourse.uniqueId === uniqueId);
@@ -173,6 +175,4 @@ const HeadingAndActions: React.FC<HeadingAndActionProps> = ({
<Divider orientation='horizontal' size='100%' /> <Divider orientation='horizontal' size='100%' />
</div> </div>
); );
}; }
export default HeadingAndActions;

View File

@@ -14,7 +14,7 @@ const RECRUIT_FROM_DEPARTMENTS = ['C S', 'ECE', 'MIS', 'CSE', 'EE', 'ITD'];
* This adds a new column to the course catalog table header. * This adds a new column to the course catalog table header.
* @returns a react portal to the new column or null if the column has not been created yet. * @returns a react portal to the new column or null if the column has not been created yet.
*/ */
export default function RecruitmentBanner() { export default function RecruitmentBanner(): JSX.Element {
const [container, setContainer] = useState<HTMLDivElement | null>(null); const [container, setContainer] = useState<HTMLDivElement | null>(null);
useEffect(() => { useEffect(() => {
@@ -55,7 +55,7 @@ export default function RecruitmentBanner() {
* Determines if recruitment can be done from the current department. * Determines if recruitment can be done from the current department.
* @returns {boolean} True if recruitment can be done from the current department, false otherwise. * @returns {boolean} True if recruitment can be done from the current department, false otherwise.
*/ */
export function canRecruitFrom(): boolean { export const canRecruitFrom = (): boolean => {
const params = ['fos_fl', 'fos_cn']; const params = ['fos_fl', 'fos_cn'];
let department = ''; let department = '';
params.forEach(p => { params.forEach(p => {
@@ -68,4 +68,4 @@ export function canRecruitFrom(): boolean {
return false; return false;
} }
return RECRUIT_FROM_DEPARTMENTS.includes(department); return RECRUIT_FROM_DEPARTMENTS.includes(department);
} };

View File

@@ -6,7 +6,7 @@ import ReactDOM from 'react-dom';
* This adds a new column to the course catalog table header. * This adds a new column to the course catalog table header.
* @returns a react portal to the new column or null if the column has not been created yet. * @returns a react portal to the new column or null if the column has not been created yet.
*/ */
export default function TableHead({ children }: PropsWithChildren) { export default function TableHead({ children }: PropsWithChildren): JSX.Element | null {
const [container, setContainer] = useState<HTMLTableCellElement | null>(null); const [container, setContainer] = useState<HTMLTableCellElement | null>(null);
useEffect(() => { useEffect(() => {

View File

@@ -11,7 +11,7 @@ interface Props {
* This component is injected into each row of the course catalog table. * This component is injected into each row of the course catalog table.
* @returns a react portal to the new td in the column or null if the column has not been created yet. * @returns a react portal to the new td in the column or null if the column has not been created yet.
*/ */
export default function TableSubheading({ row }: Props) { export default function TableSubheading({ row }: Props): JSX.Element | null {
const { element } = row; const { element } = row;
useEffect(() => { useEffect(() => {