Made CourseCells and CalendarGridCells more responsive. CourseCells now rendering onto grid. Still, need to make course cells more responsive, and add edge cases

This commit is contained in:
knownotunknown
2024-02-18 14:10:13 -06:00
parent a1a0f00514
commit b0a95a6153
6 changed files with 125 additions and 82 deletions

View File

@@ -1,8 +1,8 @@
import { Meta, StoryObj } from '@storybook/react'; import { Meta, StoryObj } from '@storybook/react';
import CalendarGrid from 'src/views/components/common/CalendarGrid/CalendarGrid'; import CalendarGrid from '@views/components/common/CalendarGrid/CalendarGrid';
import { getCourseColors } from 'src/shared/util/colors'; import { getCourseColors } from '@shared/util/colors';
import { CalendarGridCourse } from 'src/views/hooks/useFlattenedCourseSchedule'; import { CalendarGridCourse } from '@views/hooks/useFlattenedCourseSchedule';
import { Status } from 'src/shared/types/Course'; import { Status } from '@shared/types/Course';
const meta = { const meta = {
title: 'Components/Common/CalendarGrid', title: 'Components/Common/CalendarGrid',
@@ -20,9 +20,9 @@ export default meta;
const testData: CalendarGridCourse[] = [ const testData: CalendarGridCourse[] = [
{ {
calendarGridPoint: { calendarGridPoint: {
dayIndex: 0, dayIndex: 4,
startIndex: 4, startIndex: 10,
endIndex: 6, endIndex: 11,
}, },
componentProps: { componentProps: {
courseDeptAndInstr: 'Course 1', courseDeptAndInstr: 'Course 1',
@@ -33,9 +33,9 @@ const testData: CalendarGridCourse[] = [
}, },
{ {
calendarGridPoint: { calendarGridPoint: {
dayIndex: 4, dayIndex: 1,
startIndex: 10, startIndex: 10,
endIndex: 20, endIndex: 12,
}, },
componentProps: { componentProps: {
courseDeptAndInstr: 'Course 2', courseDeptAndInstr: 'Course 2',

View File

@@ -36,7 +36,7 @@ const CalendarCourseCell: React.FC<CalendarCourseCellProps> = ({
return ( return (
<div <div
className={clsx('w-full flex justify-center rounded p-2', fontColor, className)} className={clsx('h-full w-full flex justify-center rounded p-2', fontColor, className)}
style={{ style={{
backgroundColor: colors.primaryColor, backgroundColor: colors.primaryColor,
}} }}

View File

@@ -14,8 +14,9 @@
.calendarGrid { .calendarGrid {
display: grid; display: grid;
grid-template-columns: repeat(6, 1fr); grid-template-columns: repeat(6, 1fr);
grid-template-rows: repeat(13, 1fr); grid-template-rows: repeat(26, 1fr);
position:absolute; width: 100%;
height: 100%;
} }
.calendarRow { .calendarRow {
@@ -27,7 +28,7 @@
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
position: relative; // Ensuring that child elements can be positioned in relation to this. position: relative; // Ensuring that child elements can be positioned in relation to this.
min-width: 500px; min-width: 800px;
min-height: 500px; min-height: 500px;
} }
@@ -56,7 +57,7 @@
justify-content: space-between; justify-content: space-between;
align-items: flex-start; align-items: flex-start;
flex: 1 0 0; flex: 1 0 0;
border-radius: var(--border-radius-none, 0px); border-radius: 0px;
} }
.timeBlock { .timeBlock {
@@ -128,3 +129,12 @@
width: 1px; width: 1px;
background-color: grey; background-color: grey;
} }
.dot {
height: 75%; /* 75% of the container's height */
width: 75%; /* 75% of the container's width */
background-color: #000000; /* Color of the dot */
border-radius: 50%; /* Rounds the corners into a circle */
top: 12.5%; /* Centers the dot vertically */
left: 12.5%; /* Centers the dot horizontally */
}

View File

@@ -1,16 +1,16 @@
import React, { useState, useRef } from 'react'; import React, { useState, useRef, useEffect } from 'react';
import html2canvas from 'html2canvas'; // import html2canvas from 'html2canvas';
import { DAY_MAP } from 'src/shared/types/CourseMeeting'; import { DAY_MAP } from 'src/shared/types/CourseMeeting';
import { CalendarGridCourse } from 'src/views/hooks/useFlattenedCourseSchedule'; import { CalendarGridCourse } from 'src/views/hooks/useFlattenedCourseSchedule';
import calIcon from 'src/assets/icons/cal.svg'; /* import calIcon from 'src/assets/icons/cal.svg';
import pngIcon from 'src/assets/icons/png.svg'; import pngIcon from 'src/assets/icons/png.svg';
*/
import CalendarCell from '../CalendarGridCell/CalendarGridCell'; import CalendarCell from '../CalendarGridCell/CalendarGridCell';
import CalendarCourseCell from '../CalendarCourseCell/CalendarCourseCell'; import CalendarCourseCell from '../CalendarCourseCell/CalendarCourseCell';
import styles from './CalendarGrid.module.scss'; import styles from './CalendarGrid.module.scss';
import calIcon from 'src/assets/icons/cal.svg';
import pngIcon from 'src/assets/icons/png.svg';
const daysOfWeek = Object.keys(DAY_MAP).filter(key => !['S', 'SU'].includes(key));
/* const daysOfWeek = Object.keys(DAY_MAP).filter(key => !['S', 'SU'].includes(key));
const hoursOfDay = Array.from({ length: 14 }, (_, index) => index + 8); const hoursOfDay = Array.from({ length: 14 }, (_, index) => index + 8);
const grid = []; const grid = [];
for (let i = 0; i < 13; i++) { for (let i = 0; i < 13; i++) {
@@ -25,7 +25,7 @@ for (let i = 0; i < 13; i++) {
); );
row.push(Array.from({ length: 5 }, (_, j) => <CalendarCell key={j} />)); row.push(Array.from({ length: 5 }, (_, j) => <CalendarCell key={j} />));
grid.push(row); grid.push(row);
} } */
interface Props { interface Props {
courseCells: CalendarGridCourse[]; courseCells: CalendarGridCourse[];
@@ -38,8 +38,12 @@ interface Props {
*/ */
function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Props>): JSX.Element { function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Props>): JSX.Element {
const [iterator, setIterator] = useState<number>(0); const [iterator, setIterator] = useState<number>(0);
const [grid, setGrid] = useState([]);
const calendarRef = useRef(null); // Create a ref for the calendar grid 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 = () => {
if (calendarRef.current) { if (calendarRef.current) {
html2canvas(calendarRef.current).then(canvas => { html2canvas(calendarRef.current).then(canvas => {
@@ -52,65 +56,88 @@ 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>
</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);
}
setGrid(newGrid);
}, []);
return ( return (
<div className={styles.calendar}> <div className={styles.calendar}>
<div className={styles.dayLabelContainer} /> <div className={styles.dayLabelContainer}/>
{/* Displaying the rest of the calendar */} {/* Displaying the rest of the calendar */}
<div ref={calendarRef} className={styles.timeAndGrid}> <div className={styles.timeAndGrid}>
{/* <div className={styles.timeColumn}> <div className={styles.calendarGrid}>
<div className={styles.timeBlock}></div>
{hoursOfDay.map((hour) => (
<div key={hour} className={styles.timeBlock}>
<div className={styles.timeLabelContainer}>
<p>{hour % 12 === 0 ? 12 : hour % 12} {hour < 12 ? 'AM' : 'PM'}</p>
</div>
</div>
))}
</div> */}
<div className={styles.calendarGrid} id='grid1'>
{/* Displaying day labels */} {/* Displaying day labels */}
<div className={styles.timeBlock} /> <div className={styles.timeBlock}/>
{daysOfWeek.map((day, x) => ( {daysOfWeek.map(day => (
<div key={`${day}`} className={styles.day}> <div key={day} className={styles.day}>
{day} {day}
</div> </div>
))} ))}
{grid.map((row, y) => ( {grid.map((row, rowIndex) => (row))}
<div key={`${row}`}> {courseCells.map((block: CalendarGridCourse) => (
{row.map((cell, x) => { <div
const shouldRenderChild = courseCells[iterator].calendarGridPoint && x === courseCells[iterator].calendarGridPoint.dayIndex && y === courseCells[iterator].calendarGridPoint.startIndex; key={`${block}`}
if (shouldRenderChild) { style={{
setIterator((iterator) => iterator + 1); gridColumn: `${block.calendarGridPoint.dayIndex + 1}`,
} gridRow: `${block.calendarGridPoint.startIndex + 1} / ${block.calendarGridPoint.endIndex + 1}`,
return ( }}
<div key={`${cell}`}> >
{cell} <CalendarCourseCell
{shouldRenderChild && <CalendarCourseCell courseDeptAndInstr={block.componentProps.courseDeptAndInstr}
courseDeptAndInstr={courseCells[iterator].componentProps.courseDeptAndInstr} timeAndLocation={block.componentProps.timeAndLocation}
status={courseCells[iterator].componentProps.status} status={block.componentProps.status}
colors={courseCells[iterator].componentProps.colors} />} colors={block.componentProps.colors}
</div> />
);
})}
</div> </div>
))} ))}
</div> </div>
</div> </div>
<div className={styles.buttonContainer}>
<div className={styles.divider} /> {/* First divider */}
<button className={styles.calendarButton}>
<img src={calIcon} className={styles.buttonIcon} alt='CAL' />
Save as .CAL
</button>
<div className={styles.divider} /> {/* Second divider */}
<button onClick={saveAsPNG} className={styles.calendarButton}>
<img src={pngIcon} className={styles.buttonIcon} alt='PNG' />
Save as .PNG
</button>
</div>
</div> </div>
); );
} }
export default CalendarGrid; export default CalendarGrid;
/* <div className={styles.buttonContainer}>
<div className={styles.divider} />
<button className={styles.calendarButton}>
<img src={calIcon} className={styles.buttonIcon} alt='CAL' />
Save as .CAL
</button>
<div className={styles.divider} />
<button onClick={saveAsPNG} className={styles.calendarButton}>
<img src={pngIcon} className={styles.buttonIcon} alt='PNG' />
Save as .PNG
</button>
</div> */

View File

@@ -1,7 +1,7 @@
.calendarCell { .calendarCell {
display: flex; display: flex;
width: 213.8px; width: 100%;
height: 44.769px; height: 100%;
min-width: 45px; min-width: 45px;
min-height: 40px; min-height: 40px;
flex-direction: column; flex-direction: column;
@@ -11,8 +11,8 @@
} }
.hourLine { .hourLine {
width: 213.8px; width: 100%;
height: 1px; height: 1px;
border-radius: var(--border-radius-none, 0px); border-radius: 0px;
background: rgba(218, 220, 224, 0.25); background: rgba(218, 220, 224, 0.25);
} }

View File

@@ -1,14 +1,20 @@
import React from 'react'; import React from 'react';
import styles from './CalendarGridCell.module.scss'; import styles from './CalendarGridCell.module.scss';
interface Props {
styleProp: any;
}
/** /**
* Component representing each 1 hour time block of a calendar * Component representing each 1 hour time block of a calendar
* @param props * @param props
*/ */
const CalendarCell: React.FC = props => ( function CalendarCell({ styleProp }: Props): JSX.Element {
<div className={styles.calendarCell}> return (
<div className={styles.calendarCell} style={styleProp}>
<div className={styles.hourLine} /> <div className={styles.hourLine} />
</div> </div>
); );
}
export default CalendarCell; export default CalendarCell;