Grid works cleanly with up to two course conflicts. Prob needs refactoring

This commit is contained in:
knownotunknown
2024-02-18 16:28:29 -06:00
parent 313a9648c9
commit 297601e715
4 changed files with 174 additions and 46 deletions

View File

@@ -31,6 +31,19 @@ const testData: CalendarGridCourse[] = [
colors: getCourseColors('emerald', 500),
},
},
{
calendarGridPoint: {
dayIndex: 2,
startIndex: 5,
endIndex: 6,
},
componentProps: {
courseDeptAndInstr: 'Course 1',
timeAndLocation: '9:00 AM - 10:00 AM, Room 101',
status: Status.OPEN,
colors: getCourseColors('emerald', 500),
},
},
{
calendarGridPoint: {
dayIndex: 1,
@@ -44,7 +57,58 @@ const testData: CalendarGridCourse[] = [
colors: getCourseColors('emerald', 500),
},
},
// add more data as needed
{
calendarGridPoint: {
dayIndex: 4,
startIndex: 10,
endIndex: 11,
},
componentProps: {
courseDeptAndInstr: 'Course 1',
timeAndLocation: '9:00 AM - 10:00 AM, Room 101',
status: Status.OPEN,
colors: getCourseColors('emerald', 500),
},
},
{
calendarGridPoint: {
dayIndex: 1,
startIndex: 10,
endIndex: 12,
},
componentProps: {
courseDeptAndInstr: 'Course 2',
timeAndLocation: '10:00 AM - 11:00 AM, Room 102',
status: Status.CLOSED,
colors: getCourseColors('emerald', 500),
},
},
{
calendarGridPoint: {
dayIndex: 1,
startIndex: 10,
endIndex: 12,
},
componentProps: {
courseDeptAndInstr: 'Course 3',
timeAndLocation: '10:00 AM - 11:00 AM, Room 102',
status: Status.CLOSED,
colors: getCourseColors('emerald', 500),
},
},
{
calendarGridPoint: {
dayIndex: 1,
startIndex: 10,
endIndex: 12,
},
componentProps: {
courseDeptAndInstr: 'Course 4',
timeAndLocation: '10:00 AM - 11:00 AM, Room 102',
status: Status.CLOSED,
colors: getCourseColors('emerald', 500),
},
},
];
type Story = StoryObj<typeof meta>;

View File

@@ -36,12 +36,12 @@ const CalendarCourseCell: React.FC<CalendarCourseCellProps> = ({
return (
<div
className={clsx('h-full w-full flex justify-center rounded p-2', fontColor, className)}
className={clsx('h-full w-full flex justify-center rounded p-2 overflow-x-hidden', fontColor, className)}
style={{
backgroundColor: colors.primaryColor,
}}
>
<div className='flex flex-1 flex-col gap-1 overflow-x-hidden'>
<div className='flex flex-1 flex-col gap-1'>
<Text
variant='h1-course'
className={clsx('-my-0.8 leading-tight', {

View File

@@ -9,7 +9,6 @@ import CalendarCell from '../CalendarGridCell/CalendarGridCell';
import CalendarCourseCell from '../CalendarCourseCell/CalendarCourseCell';
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 = [];
@@ -37,14 +36,13 @@ interface Props {
* @param props
*/
function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Props>): JSX.Element {
const [iterator, setIterator] = useState<number>(0);
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));
const hoursOfDay = Array.from({ length: 14 }, (_, index) => index + 8);
const saveAsPNG = () => {
/* const saveAsPNG = () => {
htmlToImage
.toPng(calendarRef.current, {
backgroundColor: 'white',
@@ -75,7 +73,7 @@ function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Pr
.catch(error => {
console.error('oops, something went wrong!', error);
});
};
}; */
useEffect(() => {
const newGrid = [];
@@ -84,7 +82,7 @@ function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Pr
let hour = hoursOfDay[i];
let styleProp = {
gridColumn: '1',
gridRow: `${(2 * i) + 2}`,
gridRow: `${2 * i + 2}`,
};
row.push(
<div key={hour} className={styles.timeBlock} style={styleProp}>
@@ -104,27 +102,29 @@ function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Pr
let childElement = <div className={styles.dot}/>; */
/* let completeGridCell = shouldRenderChild ? <CalendarCell key={k} children={childElement}/>
: <CalendarCell key={k} />; */
row.push(<CalendarCell key={k} styleProp={styleProp}/>);
row.push(<CalendarCell key={k} styleProp={styleProp} />);
}
newGrid.push(row);
}
};
setGrid(newGrid);
}, []);
return (
<div className={styles.calendar}>
<div className={styles.dayLabelContainer}/>
<div className={styles.dayLabelContainer} />
{/* Displaying the rest of the calendar */}
<div className={styles.timeAndGrid}>
<div className={styles.calendarGrid}>
{/* Displaying day labels */}
<div className={styles.timeBlock}/>
<div className={styles.timeBlock} />
{daysOfWeek.map(day => (
<div key={day} className={styles.day}>
{day}
</div>
))}
{grid.map((row, rowIndex) => (row))}
{courseCells.map((block: CalendarGridCourse) => (
{grid.map((row, rowIndex) => row)}
{accountForCourseConflicts(courseCells)}
{/* courseCells.map((block: CalendarGridCourse) => (
<div
key={`${block}`}
style={{
@@ -139,7 +139,7 @@ function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Pr
colors={block.componentProps.colors}
/>
</div>
))}
)) */}
</div>
</div>
</div>
@@ -148,6 +148,67 @@ function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Pr
export default CalendarGrid;
function accountForCourseConflicts(courseCells: CalendarGridCourse[]): JSX.Element[] {
// Groups by dayIndex to identify overlaps
const days = courseCells.reduce((acc, cell: CalendarGridCourse) => {
const { dayIndex } = cell.calendarGridPoint;
if (!acc[dayIndex]) {
acc[dayIndex] = [];
}
acc[dayIndex].push(cell);
return acc;
}, {});
// Check for overlaps within each day and adjust gridColumnIndex and totalColumns
Object.values(days).forEach((dayCells: CalendarGridCourse[]) => {
// Sort by start time to ensure proper columnIndex assignment
dayCells.sort((a, b) => a.calendarGridPoint.startIndex - b.calendarGridPoint.startIndex);
dayCells.forEach((cell, _, arr) => {
let columnIndex = 1;
cell.totalColumns = 1;
// Check for overlaps and adjust columnIndex as needed
for (let otherCell of arr) {
if (otherCell !== cell) {
const isOverlapping =
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;
}
}
}
cell.gridColumnStart = columnIndex;
cell.gridColumnEnd = columnIndex + 1;
});
});
return courseCells.map(block => (
<div
key={`${block}`}
style={{
gridColumn: `${block.calendarGridPoint.dayIndex + 1}`,
gridRow: `${block.calendarGridPoint.startIndex + 1} / ${block.calendarGridPoint.endIndex + 1}`,
width: `calc(100% / ${block.totalColumns})`,
marginLeft: `calc(100% * ${(block.gridColumnStart - 1) / block.totalColumns})`,
padding: '0px 10px 4px 0px',
}}
>
<CalendarCourseCell
courseDeptAndInstr={block.componentProps.courseDeptAndInstr}
timeAndLocation={block.componentProps.timeAndLocation}
status={block.componentProps.status}
colors={block.componentProps.colors}
/>
</div>
));
}
/* <div className={styles.buttonContainer}>
<div className={styles.divider} />

View File

@@ -21,6 +21,9 @@ interface CalendarGridPoint {
export interface CalendarGridCourse {
calendarGridPoint: CalendarGridPoint;
componentProps: CalendarCourseCellProps;
gridColumnStart?: number;
gridColumnEnd?: number;
totalColumns?: number;
}
const convertMinutesToIndex = (minutes: number): number => Math.floor(minutes - 420 / 30);