This commit is contained in:
Casey Charleston
2024-02-17 18:00:06 -06:00
18 changed files with 3433 additions and 473 deletions

View File

@@ -17,7 +17,7 @@ export default function ImportantLinks({ className }: Props) {
<Text variant='h3'>Important Links</Text>
<a
href='https://utdirect.utexas.edu/apps/registrar/course_schedule/20242/'
className='text-ut-burntorange flex items-center gap-0.5'
className='flex items-center gap-0.5 text-ut-burntorange'
target='_blank'
rel='noreferrer'
>
@@ -26,7 +26,7 @@ export default function ImportantLinks({ className }: Props) {
</a>
<a
href='https://utdirect.utexas.edu/apps/registrar/course_schedule/20236/'
className='text-ut-burntorange flex items-center gap-0.5'
className='flex items-center gap-0.5 text-ut-burntorange'
target='_blank'
rel='noreferrer'
>
@@ -35,7 +35,7 @@ export default function ImportantLinks({ className }: Props) {
</a>
<a
href='https://utdirect.utexas.edu/registrar/ris.WBX'
className='text-ut-burntorange flex items-center gap-0.5'
className='flex items-center gap-0.5 text-ut-burntorange'
target='_blank'
rel='noreferrer'
>
@@ -44,7 +44,7 @@ export default function ImportantLinks({ className }: Props) {
</a>
<a
href='https://utdirect.utexas.edu/registration/chooseSemester.WBX'
className='text-ut-burntorange flex items-center gap-0.5'
className='flex items-center gap-0.5 text-ut-burntorange'
target='_blank'
rel='noreferrer'
>
@@ -53,7 +53,7 @@ export default function ImportantLinks({ className }: Props) {
</a>
<a
href='https://utdirect.utexas.edu/apps/degree/audits/'
className='text-ut-burntorange flex items-center gap-0.5'
className='flex items-center gap-0.5 text-ut-burntorange'
target='_blank'
rel='noreferrer'
>

View File

@@ -0,0 +1,44 @@
import React from 'react';
import clsx from 'clsx';
import Text from '../Text/Text';
import CalendarCourseBlock, { CalendarCourseCellProps } from '../CalendarCourseCell/CalendarCourseCell';
import { Button } from '../Button/Button';
import ImageIcon from '~icons/material-symbols/image';
import CalendarMonthIcon from '~icons/material-symbols/calendar-month';
type CalendarBottomBarProps = {
courses: CalendarCourseCellProps[];
};
/**
*
*/
export const CalendarBottomBar = ({ courses }: CalendarBottomBarProps): JSX.Element => {
if (courses.length === -1) console.log('foo'); // dumb line to make eslint happy
return (
<div className='w-full flex py-1.25'>
<div className='flex flex-grow items-center gap-3.75 pl-7.5 pr-2.5'>
<Text variant='h4'>Async. and Other:</Text>
<div className='h-14 inline-flex gap-2.5'>
{courses.map(course => (
<CalendarCourseBlock
courseDeptAndInstr={course.courseDeptAndInstr}
status={course.status}
colors={course.colors}
key={course.courseDeptAndInstr}
className={clsx(course.className, 'w-35!')}
/>
))}
</div>
</div>
<div className='flex items-center pl-2.5 pr-7.5'>
<Button variant='single' color='ut-black' icon={CalendarMonthIcon}>
Save as .CAL
</Button>
<Button variant='single' color='ut-black' icon={ImageIcon}>
Save as .PNG
</Button>
</div>
</div>
);
};

View File

@@ -12,6 +12,7 @@ export interface CalendarCourseCellProps {
timeAndLocation?: string;
status: Status;
colors: CourseColors;
className?: string;
}
const CalendarCourseCell: React.FC<CalendarCourseCellProps> = ({
@@ -19,6 +20,7 @@ const CalendarCourseCell: React.FC<CalendarCourseCellProps> = ({
timeAndLocation,
status,
colors,
className,
}: CalendarCourseCellProps) => {
let rightIcon: React.ReactNode | null = null;
if (status === Status.WAITLISTED) {
@@ -34,7 +36,7 @@ const CalendarCourseCell: React.FC<CalendarCourseCellProps> = ({
return (
<div
className={`w-full flex justify-center rounded p-2 ${fontColor}`}
className={clsx('w-full flex justify-center rounded p-2', fontColor, className)}
style={{
backgroundColor: colors.primaryColor,
}}

View File

@@ -22,9 +22,10 @@
}
.calendar {
// display: grid;
// grid-template-columns: auto repeat(5, 1fr);
display: flex;
flex-direction: column;
gap: 10px;
position: relative; // Ensuring that child elements can be positioned in relation to this.
}
.day {
@@ -89,3 +90,38 @@
line-height: normal;
}
}
.buttonContainer {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 10px;
padding: 10px;
margin-top: auto;
}
.calendarButton {
display: flex;
align-items: center;
gap: 5px;
padding: 6px 6px;
border: none;
background-color: transparent;
color: #333;
cursor: pointer;
&:hover {
background-color: rgba(0, 0, 0, 0.1);
}
}
.buttonIcon {
height: 24px;
fill: currentColor;
}
.divider {
height: 30px;
width: 1px;
background-color: grey;
}

View File

@@ -1,9 +1,12 @@
import React from 'react';
import React, { useRef } from 'react';
import html2canvas from 'html2canvas';
import { DAY_MAP } from 'src/shared/types/CourseMeeting';
import styles from './CalendarGrid.module.scss';
import { CalendarGridCourse } from 'src/views/hooks/useFlattenedCourseSchedule';
import calIcon from 'src/assets/icons/cal.svg';
import pngIcon from 'src/assets/icons/png.svg';
import CalendarCell from '../CalendarGridCell/CalendarGridCell';
import CalendarCourseCell from '../CalendarCourseCell/CalendarCourseCell';
import { Chip } from '../Chip/Chip';
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);
@@ -23,7 +26,7 @@ for (let i = 0; i < 13; i++) {
}
interface Props {
courseCells: any[];
courseCells: CalendarGridCourse[];
saturdayClass: boolean;
}
@@ -31,12 +34,26 @@ interface Props {
* Grid of CalendarGridCell components forming the user's course schedule calendar view
* @param props
*/
function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Props> ): JSX.Element {
function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Props>): JSX.Element {
const calendarRef = useRef(null); // Create a ref for the calendar grid
const saveAsPNG = () => {
if (calendarRef.current) {
html2canvas(calendarRef.current).then(canvas => {
// Create an a element to trigger download
const a = document.createElement('a');
a.href = canvas.toDataURL('image/png');
a.download = 'calendar.png';
a.click();
});
}
};
return (
<div className={styles.calendar}>
<div className={styles.dayLabelContainer} />
{/* Displaying the rest of the calendar */}
<div className={styles.timeAndGrid}>
<div ref={calendarRef} className={styles.timeAndGrid}>
{/* <div className={styles.timeColumn}>
<div className={styles.timeBlock}></div>
{hoursOfDay.map((hour) => (
@@ -55,20 +72,38 @@ function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Pr
{day}
</div>
))}
{grid.map(row => row)}
{grid.map((row, index) => (
<React.Fragment key={index}>{row}</React.Fragment>
))}
</div>
</div>
{/* courseCells.map((Block: typeof CalendarCourseCell) => (
{courseCells.map((block: CalendarGridCourse) => (
<div
key={`${Block}`}
key={`${block}`}
style={{
gridColumn: `1`,
gridRow: `1`,
gridColumn: `${block.calendarGridPoint.dayIndex}`,
gridRow: `${block.calendarGridPoint.startIndex} / ${block.calendarGridPoint.endIndex}`,
}}
>
<Chip label='test' />
<CalendarCourseCell
courseDeptAndInstr={block.componentProps.courseDeptAndInstr}
status={block.componentProps.status}
colors={block.componentProps.colors}
/>
</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>
);
}

View File

@@ -12,40 +12,41 @@ import ScheduleTotalHoursAndCourses from '../ScheduleTotalHoursAndCourses/Schedu
import CourseStatus from '../CourseStatus/CourseStatus';
const CalendarHeader = () => (
<div
style={{
display: 'flex',
minWidth: '672px',
minHeight: '79px',
padding: '15px 0px',
justifyContent: 'space-between',
alignItems: 'center',
alignContent: 'center',
rowGap: '10px',
alignSelf: 'stretch',
flexWrap: 'wrap',
}}
>
<Button variant='single' icon={MenuIcon} color='ut-gray' />
<div style={{ display: 'flex', alignItems: 'center' }}>
<LogoIcon style={{ marginRight: '5px' }} />
<Text>Your Logo Text</Text>
<div className='min-h-79px min-w-672px flex px-0 py-15'>
<div className='flex flex-row gap-20'>
<div className='flex gap-10'>
<div className='flex gap-1'>
<Button variant='single' icon={MenuIcon} color='ut-gray' />
<div className='flex items-center'>
<LogoIcon style={{ marginRight: '5px' }} />
<div className='flex flex-col gap-1 whitespace-nowrap'>
<Text className='leading-trim text-cap font-roboto text-base text-ut-burntorange font-medium'>
UT Registration
</Text>
<Text className='leading-trim text-cap font-roboto text-base text-ut-orange font-medium'>
Plus
</Text>
</div>
</div>
</div>
<div className='flex flex-col'>
<ScheduleTotalHoursAndCourses scheduleName='SCHEDULE' totalHours={22} totalCourses={8} />
DATA UPDATED ON: 12:00 AM 02/01/2024
</div>
</div>
<div className='flex flex-row items-center space-x-8'>
<div className='flex flex-row space-x-4'>
<CourseStatus size='small' status={Status.WAITLISTED} />
<CourseStatus size='small' status={Status.CLOSED} />
<CourseStatus size='small' status={Status.CANCELLED} />
</div>
<div className='flex flex-row'>
<Button variant='single' icon={UndoIcon} color='ut-black' />
<Button variant='single' icon={RedoIcon} color='ut-black' />
<Button variant='single' icon={SettingsIcon} color='ut-black' />
</div>
</div>
</div>
<ScheduleTotalHoursAndCourses scheduleName='SCHEDULE' totalHours={22} totalCourses={8} />
<CourseStatus size='small' status={Status.WAITLISTED} />
<CourseStatus size='small' status={Status.CLOSED} />
<CourseStatus size='small' status={Status.CANCELLED} />
<div style={{ display: 'flex' }}>
<Button variant='outline' icon={UndoIcon} color='ut-black' />
<Button variant='outline' icon={RedoIcon} color='ut-black' />
</div>
<Button variant='outline' icon={SettingsIcon} color='ut-black' />
<Divider type='solid' />
</div>
);

View File

@@ -21,7 +21,7 @@ export default function ScheduleTotalHoursAndCourses({
totalCourses,
}: ScheduleTotalHoursAndCoursesProps): JSX.Element {
return (
<div className='min-w-64 flex flex-wrap content-center items-baseline gap-2 uppercase'>
<div className='min-w-64 flex whitespace-nowrap content-center items-baseline gap-2 uppercase'>
<Text className='text-[#BF5700]' variant='h1' as='span'>
{`${scheduleName}: `}
</Text>