import { Course } from '@shared/types/Course'; import clsx from 'clsx'; import React, { useEffect, useState } from 'react'; import Spinner from '@views/components/common/Spinner/Spinner'; import Text from '@views/components/common/Text/Text'; import { CourseCatalogScraper } from '@views/lib/CourseCatalogScraper'; import { SiteSupport } from '@views/lib/getSiteSupport'; import Card from '../../../common/Card/Card'; import styles from './CourseDescription.module.scss'; type Props = { course: Course; }; enum LoadStatus { LOADING = 'LOADING', DONE = 'DONE', ERROR = 'ERROR', } /** * */ export default function CourseDescription({ course }: Props) { const [description, setDescription] = useState([]); const [status, setStatus] = useState(LoadStatus.LOADING); useEffect(() => { fetchDescription(course) .then(description => { setStatus(LoadStatus.DONE); setDescription(description); }) .catch(() => { setStatus(LoadStatus.ERROR); }); }, [course]); return ( {status === LoadStatus.ERROR && ( Please refresh the page and log back in using your UT EID and password )} {status === LoadStatus.LOADING && } {status === LoadStatus.DONE && (
    {description.map(paragraph => (
  • ))}
)}
); } interface LineProps { line: string; } function DescriptionLine({ line }: LineProps) { const lowerCaseLine = line.toLowerCase(); const className = clsx({ [styles.prerequisite]: lowerCaseLine.includes('prerequisite'), [styles.onlyOne]: lowerCaseLine.includes('may be') || lowerCaseLine.includes('only one') || lowerCaseLine.includes('may not'), [styles.restriction]: lowerCaseLine.includes('restrict'), }); return ( {line} ); } async function fetchDescription(course: Course): Promise { if (!course.description?.length) { const response = await fetch(course.url); const text = await response.text(); const doc = new DOMParser().parseFromString(text, 'text/html'); const scraper = new CourseCatalogScraper(SiteSupport.COURSE_CATALOG_DETAILS); course.description = scraper.getDescription(doc); } return course.description; }