fix: Calendar View/Scaling Issues (#144)
* fix: calendar looks normal now; scaling * fix: array indexing * chore: eslint * chore: lint * feat: team Links and scrolling
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
.scrollableSchedules {
|
||||||
|
overflow-y: auto; /* Enables vertical scrolling */
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollableLimit {
|
||||||
|
overflow-y: auto; /* Enables vertical scrolling */
|
||||||
|
max-height: 35vh; /* Adjusts based on your needs and testing */
|
||||||
|
}
|
||||||
@@ -4,46 +4,82 @@ import CalendarGrid from '@views/components/calendar/CalendarGrid/CalendarGrid';
|
|||||||
import CalendarHeader from '@views/components/calendar/CalendarHeader/CalenderHeader';
|
import CalendarHeader from '@views/components/calendar/CalendarHeader/CalenderHeader';
|
||||||
import { CalendarSchedules } from '@views/components/calendar/CalendarSchedules/CalendarSchedules';
|
import { CalendarSchedules } from '@views/components/calendar/CalendarSchedules/CalendarSchedules';
|
||||||
import ImportantLinks from '@views/components/calendar/ImportantLinks';
|
import ImportantLinks from '@views/components/calendar/ImportantLinks';
|
||||||
|
import TeamLinks from '@views/components/calendar/TeamLinks';
|
||||||
|
import Divider from '@views/components/common/Divider/Divider';
|
||||||
import CourseCatalogInjectedPopup from '@views/components/injected/CourseCatalogInjectedPopup/CourseCatalogInjectedPopup';
|
import CourseCatalogInjectedPopup from '@views/components/injected/CourseCatalogInjectedPopup/CourseCatalogInjectedPopup';
|
||||||
import { useFlattenedCourseSchedule } from '@views/hooks/useFlattenedCourseSchedule';
|
import { useFlattenedCourseSchedule } from '@views/hooks/useFlattenedCourseSchedule';
|
||||||
import React, { useRef } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { ExampleCourse } from 'src/stories/components/PopupCourseBlock.stories';
|
|
||||||
|
|
||||||
|
import styles from './Calendar.module.scss';
|
||||||
/**
|
/**
|
||||||
* A reusable chip component that follows the design system of the extension.
|
* A reusable chip component that follows the design system of the extension.
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export default function Calendar(): JSX.Element {
|
export default function Calendar(): JSX.Element {
|
||||||
const calendarRef = useRef(null);
|
const calendarRef = useRef<HTMLDivElement>(null);
|
||||||
const { courseCells, activeSchedule } = useFlattenedCourseSchedule();
|
const { courseCells, activeSchedule } = useFlattenedCourseSchedule();
|
||||||
const [course, setCourse] = React.useState<Course | null>(null);
|
const [course, setCourse] = useState<Course | null>(null);
|
||||||
|
const [sidebarWidth, setSidebarWidth] = useState('20%');
|
||||||
|
const [scale, setScale] = useState(1);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const adjustLayout = () => {
|
||||||
|
const windowHeight = window.innerHeight;
|
||||||
|
const windowWidth = window.innerWidth;
|
||||||
|
|
||||||
|
const desiredCalendarHeight = 760;
|
||||||
|
const minSidebarWidthPixels = 230;
|
||||||
|
|
||||||
|
const scale = Math.min(1, windowHeight / desiredCalendarHeight);
|
||||||
|
|
||||||
|
const sidebarWidthPixels = Math.max(
|
||||||
|
windowWidth * scale - windowWidth + minSidebarWidthPixels,
|
||||||
|
minSidebarWidthPixels
|
||||||
|
);
|
||||||
|
const newSidebarWidth = `${(sidebarWidthPixels / windowWidth) * 100}%`;
|
||||||
|
|
||||||
|
setScale(scale);
|
||||||
|
setSidebarWidth(newSidebarWidth);
|
||||||
|
};
|
||||||
|
|
||||||
|
adjustLayout();
|
||||||
|
|
||||||
|
window.addEventListener('resize', adjustLayout);
|
||||||
|
return () => window.removeEventListener('resize', adjustLayout);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const calendarContainerStyle = {
|
||||||
|
transform: `scale(${scale})`,
|
||||||
|
transformOrigin: 'top left',
|
||||||
|
marginTop: '-20px',
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col'>
|
<div className='h-screen flex flex-col' style={{ width: 'calc(100% - 1rem)' }}>
|
||||||
<CalendarHeader
|
<div className='pl-5'>
|
||||||
// TODO: implement props
|
<CalendarHeader />
|
||||||
// totalHours={activeSchedule.hours}
|
</div>
|
||||||
// scheduleName={activeSchedule.name}
|
<div className={`flex flex-grow flex-row overflow-hidden pl-4 ${styles.scrollableSchedules}`}>
|
||||||
// totalCourses={activeSchedule?.courses.length}
|
<div className='sidebar-style' style={{ width: sidebarWidth, padding: '10px 15px 5px 5px' }}>
|
||||||
/>
|
<div className={`mb-4 ${styles.scrollableLimit}`}>
|
||||||
<div className='h-screen w-full flex flex-col md:flex-row'>
|
|
||||||
<div className='min-h-[30%] flex flex-col items-start gap-2.5 p-5 pl-7'>
|
|
||||||
<div className='min-h-[30%]'>
|
|
||||||
<CalendarSchedules />
|
<CalendarSchedules />
|
||||||
</div>
|
</div>
|
||||||
|
<Divider orientation='horizontal' size='100%' />
|
||||||
|
<div className='mt-4'>
|
||||||
<ImportantLinks />
|
<ImportantLinks />
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-grow flex-col gap-4 overflow-hidden pr-12'>
|
<Divider orientation='horizontal' size='100%' />
|
||||||
<div ref={calendarRef} className='flex-grow overflow-auto'>
|
<div className='mt-4'>
|
||||||
|
<TeamLinks />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-grow flex-col' style={calendarContainerStyle} ref={calendarRef}>
|
||||||
|
<div className='flex-grow overflow-auto'>
|
||||||
<CalendarGrid courseCells={courseCells} setCourse={setCourse} />
|
<CalendarGrid courseCells={courseCells} setCourse={setCourse} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<CalendarBottomBar calendarRef={calendarRef} />
|
<CalendarBottomBar calendarRef={calendarRef} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{/* TODO: Doesn't work when exampleCourse is replaced with an actual course through setCourse.
|
|
||||||
Check CalendarGrid.tsx and AccountForCourseConflicts for an example */}
|
|
||||||
{course ? (
|
{course ? (
|
||||||
<CourseCatalogInjectedPopup
|
<CourseCatalogInjectedPopup
|
||||||
course={course}
|
course={course}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { getCourseColors } from '@shared/util/colors';
|
|||||||
import CalendarCourseCell from '@views/components/calendar/CalendarCourseCell/CalendarCourseCell';
|
import CalendarCourseCell from '@views/components/calendar/CalendarCourseCell/CalendarCourseCell';
|
||||||
import CalendarCell from '@views/components/calendar/CalendarGridCell/CalendarGridCell';
|
import CalendarCell from '@views/components/calendar/CalendarGridCell/CalendarGridCell';
|
||||||
import type { CalendarGridCourse } from '@views/hooks/useFlattenedCourseSchedule';
|
import type { CalendarGridCourse } from '@views/hooks/useFlattenedCourseSchedule';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import styles from './CalendarGrid.module.scss';
|
import styles from './CalendarGrid.module.scss';
|
||||||
|
|
||||||
@@ -26,12 +26,10 @@ export default function CalendarGrid({
|
|||||||
saturdayClass,
|
saturdayClass,
|
||||||
setCourse,
|
setCourse,
|
||||||
}: React.PropsWithChildren<Props>): JSX.Element {
|
}: React.PropsWithChildren<Props>): JSX.Element {
|
||||||
// const [grid, setGrid] = useState([]);
|
const [grid, setGrid] = useState([]);
|
||||||
// const calendarRef = useRef(null); // Create a ref for the calendar grid
|
|
||||||
const grid = [];
|
|
||||||
|
|
||||||
// Run once to create the grid on initial render
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const newGrid = [];
|
||||||
for (let i = 0; i < 13; i++) {
|
for (let i = 0; i < 13; i++) {
|
||||||
const row = [];
|
const row = [];
|
||||||
let hour = hoursOfDay[i];
|
let hour = hoursOfDay[i];
|
||||||
@@ -53,9 +51,10 @@ export default function CalendarGrid({
|
|||||||
};
|
};
|
||||||
row.push(<CalendarCell key={k} styleProp={styleProp} />);
|
row.push(<CalendarCell key={k} styleProp={styleProp} />);
|
||||||
}
|
}
|
||||||
grid.push(row);
|
newGrid.push(row);
|
||||||
}
|
}
|
||||||
});
|
setGrid(newGrid);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.calendarGrid}>
|
<div className={styles.calendarGrid}>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const handleOpenOptions = async (): Promise<void> => {
|
|||||||
*/
|
*/
|
||||||
export default function CalendarHeader(): JSX.Element {
|
export default function CalendarHeader(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className='min-h-79px min-w-672px w-full flex px-0 py-15'>
|
<div className='min-h-79px min-w-672px w-full flex px-0 py-5'>
|
||||||
<div className='flex flex-row gap-20'>
|
<div className='flex flex-row gap-20'>
|
||||||
<div className='flex gap-10'>
|
<div className='flex gap-10'>
|
||||||
<div className='flex gap-1'>
|
<div className='flex gap-1'>
|
||||||
|
|||||||
50
src/views/components/calendar/TeamLinks.tsx
Normal file
50
src/views/components/calendar/TeamLinks.tsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import Text from '@views/components/common/Text/Text';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import OutwardArrowIcon from '~icons/material-symbols/arrow-outward';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "From The Team" section of the calendar website
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export default function TeamLinks({ className }: Props): JSX.Element {
|
||||||
|
return (
|
||||||
|
<article className={clsx(className, 'flex flex-col gap-2')}>
|
||||||
|
<Text variant='h3'>From The Team</Text>
|
||||||
|
<a
|
||||||
|
href='options.html'
|
||||||
|
className='flex items-center gap-0.5 text-ut-burntorange'
|
||||||
|
target='_blank'
|
||||||
|
rel='noreferrer'
|
||||||
|
>
|
||||||
|
<Text variant='p'>Credits – Meet the team!</Text>
|
||||||
|
<OutwardArrowIcon className='h-3 w-3' />
|
||||||
|
</a>
|
||||||
|
{/* TODO: ADD THE LINK HERE */}
|
||||||
|
<a
|
||||||
|
href='application-link'
|
||||||
|
className='flex items-center gap-0.5 text-ut-burntorange'
|
||||||
|
target='_blank'
|
||||||
|
rel='noreferrer'
|
||||||
|
>
|
||||||
|
<Text variant='p'>Apply to Longhorn Developers</Text>
|
||||||
|
<OutwardArrowIcon className='h-3 w-3' />
|
||||||
|
</a>
|
||||||
|
{/* TODO: ADD THE LINK HERE */}
|
||||||
|
<a
|
||||||
|
href='beta_tester-link'
|
||||||
|
className='flex items-center gap-0.5 text-ut-burntorange'
|
||||||
|
target='_blank'
|
||||||
|
rel='noreferrer'
|
||||||
|
>
|
||||||
|
<Text variant='p'>Become a Beta Tester</Text>
|
||||||
|
<OutwardArrowIcon className='h-3 w-3' />
|
||||||
|
</a>
|
||||||
|
</article>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user