Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create hover view #836

Merged
merged 9 commits into from
Jan 24, 2024
12 changes: 9 additions & 3 deletions apps/antalmanac/src/components/Calendar/CalendarRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import CourseCalendarEvent, { CalendarEvent } from './CourseCalendarEvent';
import AppStore from '$stores/AppStore';
import locationIds from '$lib/location_ids';
import { useTimeFormatStore } from '$stores/SettingsStore';
import { useHoveredStore } from '$stores/HoveredStore';

const localizer = momentLocalizer(moment);

Expand Down Expand Up @@ -52,8 +53,8 @@ const AntAlmanacEvent = ({ event }: { event: CalendarEvent }) => {
{event.showLocationInfo
? event.locations.map((location) => `${location.building} ${location.room}`).join(', ')
: event.locations.length > 1
? `${event.locations.length} Locations`
: `${event.locations[0].building} ${event.locations[0].room}`}
? `${event.locations.length} Locations`
: `${event.locations[0].building} ${event.locations[0].room}`}
</Box>
<Box>{event.sectionCode}</Box>
</Box>
Expand All @@ -78,9 +79,14 @@ export default function ScheduleCalendar(props: ScheduleCalendarProps) {
const [scheduleNames, setScheduleNames] = useState(AppStore.getScheduleNames());

const { isMilitaryTime } = useTimeFormatStore();
const { hoveredCourseEvents } = useHoveredStore();

const getEventsForCalendar = () => {
return showFinalsSchedule ? finalsEventsInCalendar : eventsInCalendar;
return showFinalsSchedule
? finalsEventsInCalendar
: hoveredCourseEvents
? [...eventsInCalendar, ...hoveredCourseEvents]
: eventsInCalendar;
};

const handleClosePopover = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import locationIds from '$lib/location_ids';
import { normalizeTime, parseDaysString, formatTimes } from '$stores/calendarizeHelpers';
import useColumnStore, { type SectionTableColumn } from '$stores/ColumnStore';
import { useTimeFormatStore } from '$stores/SettingsStore';
import { useHoveredStore } from '$stores/HoveredStore';

const styles: Styles<Theme, object> = (theme) => ({
sectionCode: {
Expand Down Expand Up @@ -148,20 +149,20 @@ type SectionType = 'Act' | 'Col' | 'Dis' | 'Fld' | 'Lab' | 'Lec' | 'Qiz' | 'Res'
interface SectionDetailCellProps {
classes: ClassNameMap;
sectionType: SectionType;
sectionNum: string;
sectionNumber: string;
units: number;
}

const SectionDetailsCell = withStyles(styles)((props: SectionDetailCellProps) => {
const { classes, sectionType, sectionNum, units } = props;
const { classes, sectionType, sectionNumber, units } = props;
const isMobileScreen = useMediaQuery(`(max-width: ${MOBILE_BREAKPOINT})`);

return (
<NoPaddingTableCell className={classes.cell} style={isMobileScreen ? { textAlign: 'center' } : {}}>
<Box className={classes[sectionType]}>{sectionType}</Box>
<Box>
{!isMobileScreen && <>Sec: </>}
{sectionNum}
{sectionNumber}
</Box>
<Box>
{!isMobileScreen && <>Units: </>}
Expand Down Expand Up @@ -482,9 +483,6 @@ const tableBodyCells: Record<SectionTableColumn, React.ComponentType<any>> = {
status: StatusCell,
};

/**
* TODO: SectionNum name parity -> SectionNumber
*/
const SectionTableBody = withStyles(styles)((props: SectionTableBodyProps) => {
const { classes, section, courseDetails, term, allowHighlight, scheduleNames } = props;

Expand All @@ -505,20 +503,34 @@ const SectionTableBody = withStyles(styles)((props: SectionTableBodyProps) => {
daysOccurring: parseDaysString(section.meetings[0].days),
...normalizeTime(section.meetings[0]),
};
}, [section.meetings[0]]);
}, [section.meetings]);

// Stable references to event listeners will synchronize React state with the store.

const updateHighlight = useCallback(() => {
setAddedCourse(AppStore.getAddedSectionCodes().has(`${section.sectionCode} ${term}`));
}, []);
}, [section.sectionCode, term]);

const updateCalendarEvents = useCallback(() => {
setCalendarEvents(AppStore.getCourseEventsInCalendar());
}, [setCalendarEvents]);

// Attach event listeners to the store.
const [hoveredCourseEvents, setHoveredCourseEvents] = useHoveredStore((store) => [
store.hoveredCourseEvents,
store.setHoveredCourseEvents,
]);

const handleHover = useCallback(() => {
const alreadyHovered =
hoveredCourseEvents &&
hoveredCourseEvents.some((courseEvent) => courseEvent.sectionCode == section.sectionCode);

alreadyHovered || addedCourse
? setHoveredCourseEvents(undefined)
: setHoveredCourseEvents(section, courseDetails, term);
}, [addedCourse, courseDetails, hoveredCourseEvents, section, setHoveredCourseEvents, term]);

// Attach event listeners to the store.
useEffect(() => {
AppStore.on('addedCoursesChange', updateHighlight);
AppStore.on('currentScheduleIndexChange', updateHighlight);
Expand Down Expand Up @@ -592,6 +604,8 @@ const SectionTableBody = withStyles(styles)((props: SectionTableBodyProps) => {
// allowHighlight is ALWAYS false when in Added Course Pane and ALWAYS true when in CourseRenderPane
addedCourse ? { addedCourse: addedCourse && allowHighlight } : { scheduleConflict: scheduleConflict }
)}
onMouseEnter={handleHover}
onMouseLeave={handleHover}
>
{!addedCourse ? (
<ScheduleAddCell
Expand All @@ -604,12 +618,10 @@ const SectionTableBody = withStyles(styles)((props: SectionTableBodyProps) => {
) : (
<ColorAndDelete color={section.color} sectionCode={section.sectionCode} term={term} />
)}

{Object.entries(tableBodyCells)
.filter(([column]) => activeColumns.includes(column as SectionTableColumn))
.map(([column, Component]) => {
return (
// All of this is a little bulky, so if the props can be added specifically to activeTableBodyColumns, LMK!
<Component
key={column}
section={section}
Expand Down
33 changes: 33 additions & 0 deletions apps/antalmanac/src/stores/HoveredStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { create } from 'zustand';
import { AASection } from '@packages/antalmanac-types';
import { calendarizeCourseEvents } from './calendarizeHelpers';
import { CourseEvent } from '$components/Calendar/CourseCalendarEvent';
import { CourseDetails } from '$lib/course_data.types';

export interface HoveredStore {
hoveredCourseEvents: CourseEvent[] | undefined;
setHoveredCourseEvents: (section?: AASection, courseDetails?: CourseDetails, term?: string) => void;
}

export const useHoveredStore = create<HoveredStore>((set) => {
return {
hoveredCourseEvents: undefined,
setHoveredCourseEvents: (section, courseDetails, term) => {
set({
hoveredCourseEvents:
section && courseDetails && term
? calendarizeCourseEvents([
{
...courseDetails,
section: {
...section,
color: '#808080',
},
term,
},
])
: undefined,
});
},
};
});
Loading