Skip to content

Commit

Permalink
fix description, start no distribution state
Browse files Browse the repository at this point in the history
  • Loading branch information
abhinavchadaga committed Feb 23, 2024
1 parent a49be44 commit 65277f1
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 38 deletions.
2 changes: 1 addition & 1 deletion src/stories/injected/CourseCatalogInjectedPopup.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const exampleCourse: Course = new Course({
}),
],
}),
url: 'https://utdirect.utexas.edu/apps/registrar/course_schedule/20242/12345/',
url: 'https://utdirect.utexas.edu/apps/registrar/course_schedule/20242/50825/',
flags: ['Writing', 'Independent Inquiry'],
instructionMode: 'In Person',
semester: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const CourseCatalogInjectedPopup: React.FC<CourseCatalogInjectedPopupProps> = ({
<Popup overlay className='max-w-[780px] px-6' onClose={onClose}>
<div className='flex flex-col'>
<HeadingAndActions course={course} onClose={onClose} activeSchedule={activeSchedule} />
<Description lines={course.description} />
<Description course={course} />
<GradeDistribution course={course} />
</div>
</Popup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,78 @@
import clsx from 'clsx';
import React from 'react';
import { Course } from 'src/shared/types/Course';
import { CourseCatalogScraper } from 'src/views/lib/CourseCatalogScraper';
import { SiteSupport } from 'src/views/lib/getSiteSupport';
import Spinner from '../../common/Spinner/Spinner';
import Text from '../../common/Text/Text';

interface DescriptionProps {
lines: string[];
course: Course;
}

const Description: React.FC<DescriptionProps> = ({ lines }: DescriptionProps) => {
// TODO: This needs to fetch the url and grab the description from the course catalog
// IT WILL NOT ALREADY BE IN THE COURSE OBJECT (lookat CourseDescription.tsx for an example of how to do this)
enum LoadStatus {
LOADING = 'LOADING',
DONE = 'DONE',
ERROR = 'ERROR',
}

async function fetchDescription(course: Course): Promise<string[]> {
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;
}

const Description: React.FC<DescriptionProps> = ({ course }: DescriptionProps) => {
const [description, setDescription] = React.useState<string[]>([]);
const [status, setStatus] = React.useState<LoadStatus>(LoadStatus.LOADING);

React.useEffect(() => {
fetchDescription(course)
.then(description => {
setStatus(LoadStatus.DONE);
setDescription(description);
})
.catch(() => {
setStatus(LoadStatus.ERROR);
});
}, [course]);

const keywords = ['prerequisite', 'restricted'];
return (
<ul className='my-[5px] space-y-1.5 children:marker:text-ut-burntorange'>
{lines.map(line => {
const isKeywordPresent = keywords.some(keyword => line.toLowerCase().includes(keyword));
return (
<div className='flex gap-2'>
<span className='text-ut-burntorange'></span>
<li key={line}>
<Text variant='p' className={clsx({ 'font-bold text-ut-burntorange': isKeywordPresent })}>
{line}
</Text>
</li>
</div>
);
})}
</ul>
<>
{status === LoadStatus.ERROR && (
<Text color='speedway_brick'>
Please refresh the page and log back in using your UT EID and password
</Text>
)}
{status === LoadStatus.LOADING && <Spinner />}
{status === LoadStatus.DONE && (
<ul className='my-[5px] space-y-1.5 children:marker:text-ut-burntorange'>
{description.map(line => {
const isKeywordPresent = keywords.some(keyword => line.toLowerCase().includes(keyword));
return (
<div key={line} className='flex gap-2'>
<span className='text-ut-burntorange'></span>
<li key={line}>
<Text
variant='p'
className={clsx({ 'font-bold text-ut-burntorange': isKeywordPresent })}
>
{line}
</Text>
</li>
</div>
);
})}
</ul>
)}
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,17 @@ const GradeDistribution: React.FC<GradeDistributionProps> = ({ course }) => {
return (
<div className='pb-[25px] pt-[12px]'>
{status === DataStatus.LOADING && <Spinner />}
{status === DataStatus.NOT_FOUND && <Text variant='p'>No grade distribution data found</Text>}
{status === DataStatus.NOT_FOUND && (
<HighchartsReact
ref={ref}
highcharts={Highcharts}
options={{
...chartOptions,
title: { text: 'No grade distribution data available' },
tooltip: { enabled: false },
}}
/>
)}
{status === DataStatus.ERROR && <Text variant='p'>Error fetching grade distribution data</Text>}
{status === DataStatus.FOUND && (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Divider from '@views/components/common/Divider/Divider';
import Text from '@views/components/common/Text/Text';
import React, { useState } from 'react';
import { background } from 'src/shared/messages';
import { Course } from 'src/shared/types/Course';
import { Course, Status } from 'src/shared/types/Course';
import Instructor from 'src/shared/types/Instructor';
import { UserSchedule } from 'src/shared/types/UserSchedule';
import Add from '~icons/material-symbols/add';
Expand Down Expand Up @@ -115,25 +115,22 @@ const HeadingAndActions: React.FC<HeadingAndActionProps> = ({ course, onClose, a
)}
<div className='flex-content-centr flex gap-1'>
{flags.map(flag => (
<Chip label={flagMap[flag]} />
<Chip key={flagMap[flag]} label={flagMap[flag]} />
))}
</div>
</div>
<div className='flex flex-col'>
{schedule.meetings.map(meeting => (
<Text variant='h4'>
{meeting.getDaysString({ format: 'long', separator: 'long' })}{' '}
{meeting.getTimeString({ separator: ' to ', capitalize: false })}
{meeting.location && (
<>
{` in `}
<Text variant='h4' className='text-ut-burntorange underline'>
{meeting.location.building}
</Text>
</>
)}
</Text>
))}
{schedule.meetings.map(meeting => {
const daysString = meeting.getDaysString({ format: 'long', separator: 'long' });
const timeString = meeting.getTimeString({ separator: ' to ', capitalize: false });
const locationString = meeting.location ? ` in ${meeting.location.building}` : '';
return (
<Text key={daysString + timeString + locationString} variant='h4'>
{daysString} {timeString}
{locationString}
</Text>
);
})}
</div>
</div>
<div className='my-3 flex flex-wrap items-center gap-[15px]'>
Expand All @@ -150,6 +147,7 @@ const HeadingAndActions: React.FC<HeadingAndActionProps> = ({ course, onClose, a
</Button>
<Button
variant='filled'
disabled={course.status !== Status.OPEN}
color={!courseAdded ? 'ut-green' : 'ut-red'}
icon={!courseAdded ? Add : Remove}
onClick={handleAddOrRemoveCourse}
Expand Down

0 comments on commit 65277f1

Please sign in to comment.