feat: improve building selection controls and add week schedule

Signed-off-by: doprz <52579214+doprz@users.noreply.github.com>
This commit is contained in:
doprz
2024-10-23 14:57:02 -05:00
parent 8bf8a7fff0
commit 5500746138
3 changed files with 159 additions and 5 deletions

View File

@@ -60,7 +60,7 @@ export default function CampusMap() {
</svg> </svg>
{/* Building Selection Controls */} {/* Building Selection Controls */}
<div className='absolute right-8 top-8 rounded-md bg-white/90 p-3 shadow-sm space-y-4'> <div className='absolute right-8 top-8 h-full h-full rounded-md bg-white/90 p-3 shadow-sm space-y-4'>
<div className='text-sm space-y-2'> <div className='text-sm space-y-2'>
<div className='flex items-center gap-2'> <div className='flex items-center gap-2'>
<div className='h-3 w-3 rounded-full bg-[#BF5700]' /> <div className='h-3 w-3 rounded-full bg-[#BF5700]' />
@@ -76,7 +76,7 @@ export default function CampusMap() {
</div> </div>
</div> </div>
<div className='space-y-2'> <div className='overflow-y-scroll space-y-2'>
<p className='text-sm font-medium'>Building Paths:</p> <p className='text-sm font-medium'>Building Paths:</p>
{generateAllBuildingPaths().map(path => ( {generateAllBuildingPaths().map(path => (
<button <button

View File

@@ -1,9 +1,12 @@
import type { Course, StatusType } from '@shared/types/Course';
import type { CourseMeeting } from '@shared/types/CourseMeeting';
import { Button } from '@views/components/common/Button'; import { Button } from '@views/components/common/Button';
import Divider from '@views/components/common/Divider'; import Divider from '@views/components/common/Divider';
import { LargeLogo } from '@views/components/common/LogoIcon'; import { LargeLogo } from '@views/components/common/LogoIcon';
import Text from '@views/components/common/Text/Text'; import Text from '@views/components/common/Text/Text';
import useChangelog from '@views/hooks/useChangelog'; import useChangelog from '@views/hooks/useChangelog';
import React from 'react'; import useSchedules from '@views/hooks/useSchedules';
import React, { useCallback, useEffect } from 'react';
import IconoirGitFork from '~icons/iconoir/git-fork'; import IconoirGitFork from '~icons/iconoir/git-fork';
@@ -15,13 +18,145 @@ import CampusMap from './CampusMap';
const manifest = chrome.runtime.getManifest(); const manifest = chrome.runtime.getManifest();
const LDIconURL = new URL('/src/assets/LD-icon.png', import.meta.url).href; const LDIconURL = new URL('/src/assets/LD-icon.png', import.meta.url).href;
const UTMapURL = new URL('/src/assets/UT-Map.png', import.meta.url).href;
const DAYS = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] as const;
type Day = (typeof DAYS)[number];
/** /**
* Renders the map component for the UTRP (UT Registration Plus) extension. * Renders the map component for the UTRP (UT Registration Plus) extension.
*/ */
export default function Map(): JSX.Element { export default function Map(): JSX.Element {
const handleChangelogOnClick = useChangelog(); const handleChangelogOnClick = useChangelog();
const [activeSchedule] = useSchedules();
/**
* Function to extract and format basic course information
*/
function extractCourseInfo(course: Course) {
const {
status,
schedule: { meetings },
} = course;
let courseDeptAndInstr = `${course.department} ${course.number}`;
const mainInstructor = course.instructors[0];
if (mainInstructor) {
courseDeptAndInstr += ` ${mainInstructor.toString({ format: 'first_last', case: 'capitalize' })}`;
}
return { status, courseDeptAndInstr, meetings, course };
}
// /**
// * Function to process each in-person class into its distinct meeting objects for calendar grid
// */
// function processAsyncCourses({
// courseDeptAndInstr,
// status,
// course,
// }: {
// courseDeptAndInstr: string;
// status: StatusType;
// course: Course;
// }): CalendarGridCourse[] {
// return [
// {
// calendarGridPoint: {
// dayIndex: -1,
// startIndex: -1,
// endIndex: -1,
// },
// componentProps: {
// courseDeptAndInstr,
// status,
// colors: course.colors,
// },
// course,
// async: true,
// },
// ];
// }
/**
* Function to process each in-person class into its distinct meeting objects for calendar grid
*/
function processInPersonMeetings(
meeting: CourseMeeting,
courseDeptAndInstr: string,
status: StatusType,
course: Course
) {
const { days, location } = meeting;
const time = meeting.getTimeString({ separator: '-', capitalize: true });
const timeAndLocation = `${time}${location ? ` - ${location.building}` : ''}`;
return days.map(day => ({
day,
fullName: `${courseDeptAndInstr} - ${timeAndLocation}`,
time,
location,
status,
colors: course.colors,
course,
}));
}
const processedCourses = activeSchedule.courses.flatMap(course => {
const { status, courseDeptAndInstr, meetings } = extractCourseInfo(course);
// if (meetings.length === 0) {
// return processAsyncCourses({ courseDeptAndInstr, status, course });
// }
return meetings.flatMap(meeting =>
// if (meeting.days.includes(DAY_MAP.S) || meeting.startTime < 480) {
// return processAsyncCourses({ courseDeptAndInstr, status, course });
// }
processInPersonMeetings(meeting, courseDeptAndInstr, status, course)
);
});
const generateWeekSchedule = useCallback((): Record<Day, string[]> => {
const weekSchedule: Record<string, string[]> = {};
processedCourses.forEach(course => {
const { day } = course;
// Add the course to the day's schedule
if (!weekSchedule[day]) weekSchedule[day] = [];
weekSchedule[day].push(course.fullName);
});
// TODO: Not the best way to do this
// currently weekSchedule is an object with keys as days and values as an array of courses
// we want to display the days in order, so we create a new object with the days in order
const orderedWeekSchedule: Record<Day, string[]> = {
Monday: [],
Tuesday: [],
Wednesday: [],
Thursday: [],
Friday: [],
Saturday: [],
Sunday: [],
};
DAYS.forEach(day => {
if (weekSchedule[day]) {
orderedWeekSchedule[day] = weekSchedule[day];
}
});
return orderedWeekSchedule;
}, [processedCourses]);
useEffect(() => {
console.log(activeSchedule);
console.log(generateWeekSchedule());
console.log(processedCourses);
}, [activeSchedule, processedCourses, generateWeekSchedule]);
return ( return (
<div> <div>
@@ -55,6 +190,23 @@ export default function Map(): JSX.Element {
<div className='flex p-12'> <div className='flex p-12'>
<CampusMap /> <CampusMap />
</div> </div>
{/* Show week schedule */}
<div className='flex flex-col py-12'>
<p className='text-lg font-medium'>Week Schedule:</p>
{Object.entries(generateWeekSchedule()).map(([day, courses]) => (
<div key={day} className='flex flex-col pb-4'>
<p className='text-sm font-medium'>{day}</p>
<ul>
{courses.map(course => (
<li key={course} className='text-xs'>
{course}
</li>
))}
</ul>
</div>
))}
</div>
</div> </div>
</div> </div>
); );

View File

@@ -86,6 +86,8 @@ export const PathSegment = ({
if (!startNode || !endNode) return null; if (!startNode || !endNode) return null;
if (!isHighlighted) return null;
return ( return (
<line <line
x1={startNode.x} x1={startNode.x}
@@ -97,7 +99,7 @@ export const PathSegment = ({
// strokeWidth={isHighlighted ? '4' : '2'} // strokeWidth={isHighlighted ? '4' : '2'}
strokeWidth={isHighlighted ? '10' : '2'} strokeWidth={isHighlighted ? '10' : '2'}
strokeLinecap='round' strokeLinecap='round'
className={`opacity-60 ${isHighlighted ? 'z-1000' : ''}`} className={`opacity-60 ${isHighlighted ? 'z-10000' : ''}`}
/> />
); );
}; };