feat: improve building selection controls and add week schedule
Signed-off-by: doprz <52579214+doprz@users.noreply.github.com>
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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' : ''}`}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user