feat: Calendar Schedule component finished, fix: list didn't allow updates when adding a new schedule (#115)
* Temporarily uninstalling husky cause github desktop has issues with it * Cleaned up some code. Removed unnecessary state value on injected popup * Should've fixed popup alignment issue. Still need to integrate course schedule with calendar. Still debugging. * Updated CalendarGridStories * Fix: change to ExampleCourse from exampleCourse * setCourse and calendar header need work * Update as part of merge * Fix: fixed build errors * Fix: Added Todo * Chore: Cleaned up useFlattenedCourseSchedule hook * fix: List now keeps track of state when existing items are switched, while adding new items to the end * Added back husky * Update src/views/components/calendar/Calendar/Calendar.tsx Co-authored-by: doprz <52579214+doprz@users.noreply.github.com> * refactor: added type-safety, destructuring, etc. ready for re-review * refactor: got rid of ts-ignore in openNewTabFromContentScript * Update src/views/components/calendar/CalendarHeader/CalenderHeader.tsx Co-authored-by: doprz <52579214+doprz@users.noreply.github.com> * refactor: using path aliasing Co-authored-by: doprz <52579214+doprz@users.noreply.github.com> * refactor: using path aliasing Co-authored-by: doprz <52579214+doprz@users.noreply.github.com> * refactor: using satisfies instead of as Co-authored-by: doprz <52579214+doprz@users.noreply.github.com> * refactor: using satisfies instead of as Co-authored-by: doprz <52579214+doprz@users.noreply.github.com> * style: reformatted spacing * style: eslint import order * refactor: added new constructor for UserSchedule to avoid passing down null values to child props --------- Co-authored-by: doprz <52579214+doprz@users.noreply.github.com>
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import CalendarCourseCell from '@views/components/calendar/CalendarCourseCell/CalendarCourseCell';
|
||||
import type { Course } from '@shared/types/Course';
|
||||
/* import calIcon from 'src/assets/icons/cal.svg';
|
||||
import pngIcon from 'src/assets/icons/png.svg';
|
||||
*/
|
||||
import { getCourseColors } from '@shared/util/colors';
|
||||
import CalendarCourseCell from '@views/components/calendar/CalendarCourseCell/CalendarCourseCell';
|
||||
import CalendarCell from '@views/components/calendar/CalendarGridCell/CalendarGridCell';
|
||||
import type { CalendarGridCourse } from '@views/hooks/useFlattenedCourseSchedule';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
@@ -10,34 +12,19 @@ import { DAY_MAP } from 'src/shared/types/CourseMeeting';
|
||||
|
||||
import styles from './CalendarGrid.module.scss';
|
||||
|
||||
/* const daysOfWeek = Object.keys(DAY_MAP).filter(key => !['S', 'SU'].includes(key));
|
||||
const hoursOfDay = Array.from({ length: 14 }, (_, index) => index + 8);
|
||||
const grid = [];
|
||||
for (let i = 0; i < 13; i++) {
|
||||
const row = [];
|
||||
let hour = hoursOfDay[i];
|
||||
row.push(
|
||||
<div key={hour} className={styles.timeBlock}>
|
||||
<div className={styles.timeLabelContainer}>
|
||||
<p>{(hour % 12 === 0 ? 12 : hour % 12) + (hour < 12 ? ' AM' : ' PM')}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
row.push(Array.from({ length: 5 }, (_, j) => <CalendarCell key={j} />));
|
||||
grid.push(row);
|
||||
} */
|
||||
|
||||
interface Props {
|
||||
courseCells?: CalendarGridCourse[];
|
||||
saturdayClass?: boolean;
|
||||
setCourse: React.Dispatch<React.SetStateAction<Course | null>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grid of CalendarGridCell components forming the user's course schedule calendar view
|
||||
* @param props
|
||||
*/
|
||||
function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Props>): JSX.Element {
|
||||
const [grid, setGrid] = useState([]);
|
||||
function CalendarGrid({ courseCells, saturdayClass, setCourse }: React.PropsWithChildren<Props>): JSX.Element {
|
||||
// const [grid, setGrid] = useState([]);
|
||||
const calendarRef = useRef(null); // Create a ref for the calendar grid
|
||||
|
||||
const daysOfWeek = Object.keys(DAY_MAP).filter(key => !['S', 'SU'].includes(key));
|
||||
@@ -76,39 +63,32 @@ function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Pr
|
||||
});
|
||||
}; */
|
||||
|
||||
useEffect(() => {
|
||||
const newGrid = [];
|
||||
for (let i = 0; i < 13; i++) {
|
||||
const row = [];
|
||||
let hour = hoursOfDay[i];
|
||||
let styleProp = {
|
||||
gridColumn: '1',
|
||||
gridRow: `${2 * i + 2}`,
|
||||
};
|
||||
row.push(
|
||||
<div key={hour} className={styles.timeBlock} style={styleProp}>
|
||||
<div className={styles.timeLabelContainer}>
|
||||
<p>{(hour % 12 === 0 ? 12 : hour % 12) + (hour < 12 ? ' AM' : ' PM')}</p>
|
||||
</div>
|
||||
// TODO: Change to useMemo hook once we start calculating grid size based on if there's a Saturday class or not
|
||||
const grid = [];
|
||||
for (let i = 0; i < 13; i++) {
|
||||
const row = [];
|
||||
let hour = hoursOfDay[i];
|
||||
let styleProp = {
|
||||
gridColumn: '1',
|
||||
gridRow: `${2 * i + 2}`,
|
||||
};
|
||||
row.push(
|
||||
<div key={hour} className={styles.timeBlock} style={styleProp}>
|
||||
<div className={styles.timeLabelContainer}>
|
||||
<p>{(hour % 12 === 0 ? 12 : hour % 12) + (hour < 12 ? ' AM' : ' PM')}</p>
|
||||
</div>
|
||||
);
|
||||
for (let k = 0; k < 5; k++) {
|
||||
// let shouldRender = false;
|
||||
styleProp = {
|
||||
gridColumn: `${k + 2}`,
|
||||
gridRow: `${2 * i + 2} / ${2 * i + 4}`,
|
||||
};
|
||||
/* let shouldRenderChild = courseCells[iterator]?.calendarGridPoint &&
|
||||
k === courseCells[iterator].calendarGridPoint.dayIndex && i === courseCells[iterator].calendarGridPoint.startIndex;
|
||||
let childElement = <div className={styles.dot}/>; */
|
||||
/* let completeGridCell = shouldRenderChild ? <CalendarCell key={k} children={childElement}/>
|
||||
: <CalendarCell key={k} />; */
|
||||
row.push(<CalendarCell key={k} styleProp={styleProp} />);
|
||||
}
|
||||
newGrid.push(row);
|
||||
</div>
|
||||
);
|
||||
for (let k = 0; k < 5; k++) {
|
||||
styleProp = {
|
||||
gridColumn: `${k + 2}`,
|
||||
gridRow: `${2 * i + 2} / ${2 * i + 4}`,
|
||||
};
|
||||
row.push(<CalendarCell key={k} styleProp={styleProp} />);
|
||||
}
|
||||
setGrid(newGrid);
|
||||
}, [hoursOfDay]);
|
||||
grid.push(row);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className={styles.calendarGrid}>
|
||||
@@ -120,23 +100,7 @@ function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Pr
|
||||
</div>
|
||||
))}
|
||||
{grid.map((row, rowIndex) => row)}
|
||||
{courseCells ? <AccountForCourseConflicts courseCells={courseCells} /> : null}
|
||||
{/* courseCells.map((block: CalendarGridCourse) => (
|
||||
<div
|
||||
key={`${block}`}
|
||||
style={{
|
||||
gridColumn: `${block.calendarGridPoint.dayIndex + 1}`,
|
||||
gridRow: `${block.calendarGridPoint.startIndex + 1} / ${block.calendarGridPoint.endIndex + 1}`,
|
||||
}}
|
||||
>
|
||||
<CalendarCourseCell
|
||||
courseDeptAndInstr={block.componentProps.courseDeptAndInstr}
|
||||
timeAndLocation={block.componentProps.timeAndLocation}
|
||||
status={block.componentProps.status}
|
||||
colors={block.componentProps.colors}
|
||||
/>
|
||||
</div>
|
||||
)) */}
|
||||
{courseCells ? <AccountForCourseConflicts courseCells={courseCells} setCourse={setCourse}/> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -145,9 +109,10 @@ export default CalendarGrid;
|
||||
|
||||
interface AccountForCourseConflictsProps {
|
||||
courseCells: CalendarGridCourse[];
|
||||
setCourse: React.Dispatch<React.SetStateAction<Course | null>>;
|
||||
}
|
||||
|
||||
function AccountForCourseConflicts({ courseCells }: AccountForCourseConflictsProps): JSX.Element[] {
|
||||
function AccountForCourseConflicts({ courseCells, setCourse }: AccountForCourseConflictsProps): JSX.Element[] {
|
||||
// Groups by dayIndex to identify overlaps
|
||||
const days = courseCells.reduce((acc, cell: CalendarGridCourse) => {
|
||||
const { dayIndex } = cell.calendarGridPoint;
|
||||
@@ -173,11 +138,9 @@ function AccountForCourseConflicts({ courseCells }: AccountForCourseConflictsPro
|
||||
otherCell.calendarGridPoint.startIndex < cell.calendarGridPoint.endIndex &&
|
||||
otherCell.calendarGridPoint.endIndex > cell.calendarGridPoint.startIndex;
|
||||
if (isOverlapping) {
|
||||
console.log('Found overlapping element');
|
||||
// Adjust columnIndex to not overlap with the otherCell
|
||||
if (otherCell.gridColumnStart && otherCell.gridColumnStart >= columnIndex) {
|
||||
columnIndex = otherCell.gridColumnStart + 1;
|
||||
console.log(columnIndex);
|
||||
}
|
||||
cell.totalColumns += 1;
|
||||
}
|
||||
@@ -188,12 +151,15 @@ function AccountForCourseConflicts({ courseCells }: AccountForCourseConflictsPro
|
||||
});
|
||||
});
|
||||
|
||||
// Part of TODO: block.course is definitely a course object
|
||||
console.log(courseCells);
|
||||
|
||||
return courseCells.map(block => (
|
||||
<div
|
||||
key={`${block}`}
|
||||
style={{
|
||||
gridColumn: `${block.calendarGridPoint.dayIndex + 1}`,
|
||||
gridRow: `${block.calendarGridPoint.startIndex + 1} / ${block.calendarGridPoint.endIndex + 1}`,
|
||||
gridColumn: `${block.calendarGridPoint.dayIndex + 2}`,
|
||||
gridRow: `${block.calendarGridPoint.startIndex} / ${block.calendarGridPoint.endIndex}`,
|
||||
width: `calc(100% / ${block.totalColumns})`,
|
||||
marginLeft: `calc(100% * ${(block.gridColumnStart - 1) / block.totalColumns})`,
|
||||
padding: '0px 10px 4px 0px',
|
||||
@@ -203,7 +169,9 @@ function AccountForCourseConflicts({ courseCells }: AccountForCourseConflictsPro
|
||||
courseDeptAndInstr={block.componentProps.courseDeptAndInstr}
|
||||
timeAndLocation={block.componentProps.timeAndLocation}
|
||||
status={block.componentProps.status}
|
||||
colors={block.componentProps.colors}
|
||||
// TODO: Change to block.componentProps.colors when colors are integrated to the rest of the project
|
||||
colors={getCourseColors('emerald', 500) /* block.componentProps.colors */}
|
||||
onClick={() => setCourse(block.course)}
|
||||
/>
|
||||
</div>
|
||||
));
|
||||
|
||||
Reference in New Issue
Block a user