feat: refactor all components in injected
This commit is contained in:
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -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(() => {
|
||||||
|
|||||||
@@ -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(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user