diff --git a/src/views/components/injected/CourseCatalogInjectedPopup/DisplayMeetingInfo.tsx b/src/views/components/injected/CourseCatalogInjectedPopup/DisplayMeetingInfo.tsx new file mode 100644 index 00000000..81a3b4e3 --- /dev/null +++ b/src/views/components/injected/CourseCatalogInjectedPopup/DisplayMeetingInfo.tsx @@ -0,0 +1,96 @@ +import type { Course } from '@shared/types/Course'; +import type { CourseMeeting } from '@shared/types/CourseMeeting'; +import Link from '@views/components/common/Link'; +import Text from '@views/components/common/Text/Text'; +import React from 'react'; + +/** + * Props for the DisplayMeetingInfo component. + */ +export interface DisplayMeetingInfoProps { + course: Course; +} + +interface MeetingInfoTextProps { + meeting: CourseMeeting; + instructionMode: string; +} + +/** + * Renders a single meeting's time and location info. + * + * @param meeting - The meeting to display the info for. + * @param instructionMode - The instruction mode of the course. + * @returns The JSX element for the meeting info. + */ +function MeetingInfoText({ meeting, instructionMode }: MeetingInfoTextProps): JSX.Element { + const daysString = meeting.getDaysString({ format: 'long', separator: 'long' }); + const timeString = meeting.getTimeString({ separator: ' to ' }); + + const getBuildingUrl = (building: string) => + `https://utdirect.utexas.edu/apps/campus/buildings/nlogon/maps/UTM/${building}`; + + let locationInfo: JSX.Element | string | undefined; + + if (meeting.location) { + locationInfo = ( +
+ {'in '} + + {meeting.location.building} {meeting.location.room} + +
+ ); + } else if (instructionMode !== 'Online') { + locationInfo = ( + + (No location has been provided) + + ); + } else if (instructionMode === 'Online') { + locationInfo = ', Online (Internet)'; + } + + return ( +
+ + {daysString} {timeString} + + + {locationInfo} + +
+ ); +} + +/** + * Render the time and location for the current class. + * + * @param course - The course to display the meeting info for. + * @returns The JSX element for the meeting info. + */ +export default function DisplayMeetingInfo({ course }: DisplayMeetingInfoProps): JSX.Element { + const { schedule, instructionMode } = course; + + const noMeetings = !Array.isArray(schedule.meetings) || schedule.meetings.length === 0; + + return ( +
+ {noMeetings ? ( + + {instructionMode !== 'Online' + ? '(No time and location has been provided)' + : '(No time has been provided), Online (Internet)'} + + ) : ( + schedule.meetings.map(meeting => ( + + )) + )} +
+ ); +} diff --git a/src/views/components/injected/CourseCatalogInjectedPopup/HeadingAndActions.tsx b/src/views/components/injected/CourseCatalogInjectedPopup/HeadingAndActions.tsx index e9ede71b..68e8a9b1 100644 --- a/src/views/components/injected/CourseCatalogInjectedPopup/HeadingAndActions.tsx +++ b/src/views/components/injected/CourseCatalogInjectedPopup/HeadingAndActions.tsx @@ -20,6 +20,8 @@ import OpenNewIcon from '~icons/material-symbols/open-in-new'; import Remove from '~icons/material-symbols/remove'; import Reviews from '~icons/material-symbols/reviews'; +import DisplayMeetingInfo from './DisplayMeetingInfo'; + const { openNewTab, addCourse, removeCourse, openCESPage } = background; /** @@ -56,9 +58,6 @@ export default function HeadingAndActions({ course, activeSchedule, onClose }: H const getInstructorFullName = (instructor: Instructor) => instructor.toString({ format: 'first_last', case: 'capitalize' }); - const getBuildingUrl = (building: string) => - `https://utdirect.utexas.edu/apps/campus/buildings/nlogon/maps/UTM/${building}`; - const handleCopy = () => { navigator.clipboard.writeText(formattedUniqueId); }; @@ -164,38 +163,7 @@ export default function HeadingAndActions({ course, activeSchedule, onClose }: H ))} -
- {schedule.meetings.map(meeting => { - const daysString = meeting.getDaysString({ format: 'long', separator: 'long' }); - const timeString = meeting.getTimeString({ separator: ' to ' }); - return ( - - {daysString} {timeString} - {meeting.location && ( - <> - {' in '} - - {meeting.location.building} {meeting.location.room} - - - )} - - ); - })} -
+