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}
-
- >
- )}
-
- );
- })}
-
+