Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: bottom bar for the calendar page #91

Merged
merged 3 commits into from
Feb 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions src/stories/components/CalendarBottomBar.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import React from 'react';
import { Meta, StoryObj } from '@storybook/react';
import { Course, Status } from '@shared/types/Course';
import Instructor from '@shared/types/Instructor';
import { CalendarBottomBar } from '@views/components/common/CalendarBottomBar/CalendarBottomBar';
import { getCourseColors } from '../../shared/util/colors';

const exampleGovCourse: Course = new Course({
courseName: 'Nope',
creditHours: 3,
department: 'GOV',
description: ['nah', 'aint typing this', 'corndog'],
flags: ['no flag for you >:)'],
fullName: 'GOV 312L Something something',
instructionMode: 'Online',
instructors: [
new Instructor({
firstName: 'Bevo',
lastName: 'Barrymore',
fullName: 'Bevo Barrymore',
}),
],
isReserved: false,
number: '312L',
schedule: {
meetings: [],
},
semester: {
code: '12345',
season: 'Spring',
year: 2024,
},
status: Status.OPEN,
uniqueId: 12345,
url: 'https://utdirect.utexas.edu/apps/registrar/course_schedule/20242/12345/',
});

const examplePsyCourse: Course = new Course({
courseName: 'Nope Again',
creditHours: 3,
department: 'PSY',
description: ['nah', 'aint typing this', 'corndog'],
flags: ['no flag for you >:)'],
fullName: 'PSY 317L Yada yada',
instructionMode: 'Online',
instructors: [
new Instructor({
firstName: 'Bevo',
lastName: 'Etz',
fullName: 'Bevo Etz',
}),
],
isReserved: false,
number: '317L',
schedule: {
meetings: [],
},
semester: {
code: '12346',
season: 'Spring',
year: 2024,
},
status: Status.CLOSED,
uniqueId: 12346,
url: 'https://utdirect.utexas.edu/apps/registrar/course_schedule/20242/12345/',
});

const meta = {
title: 'Components/Common/CalendarBottomBar',
component: CalendarBottomBar,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {},
} satisfies Meta<typeof CalendarBottomBar>;
export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
courses: [
{
colors: getCourseColors('pink', 200),
courseDeptAndInstr: `${exampleGovCourse.department} ${exampleGovCourse.number} – ${exampleGovCourse.instructors[0].lastName}`,
status: exampleGovCourse.status,
},
{
colors: getCourseColors('slate', 500),
courseDeptAndInstr: `${examplePsyCourse.department} ${examplePsyCourse.number} – ${examplePsyCourse.instructors[0].lastName}`,
status: examplePsyCourse.status,
},
],
},
render: props => (
<div className='outline-red outline w-292.5!'>
<CalendarBottomBar {...props} />
</div>
),
};
Original file line number Diff line number Diff line change
@@ -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>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ export interface CalendarCourseCellProps {
timeAndLocation?: string;
status: Status;
colors: CourseColors;
className?: string;
}

const CalendarCourseCell: React.FC<CalendarCourseCellProps> = ({
courseDeptAndInstr,
timeAndLocation,
status,
colors,
className,
}: CalendarCourseCellProps) => {
let rightIcon: React.ReactNode | null = null;
if (status === Status.WAITLISTED) {
Expand All @@ -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,
}}
Expand Down
27 changes: 15 additions & 12 deletions src/views/components/common/CalendarGrid/CalendarGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, {useRef} from 'react';
import React, { useRef } from 'react';
import html2canvas from 'html2canvas';
import { DAY_MAP } from 'src/shared/types/CourseMeeting';
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 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 hoursOfDay = Array.from({ length: 14 }, (_, index) => index + 8);
Expand Down Expand Up @@ -34,12 +34,12 @@ 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) => {
html2canvas(calendarRef.current).then(canvas => {
// Create an a element to trigger download
const a = document.createElement('a');
a.href = canvas.toDataURL('image/png');
Expand Down Expand Up @@ -85,19 +85,22 @@ function CalendarGrid({ courseCells, saturdayClass }: React.PropsWithChildren<Pr
gridRow: `${block.calendarGridPoint.startIndex} / ${block.calendarGridPoint.endIndex}`,
}}
>
<CalendarCourseCell courseDeptAndInstr={block.componentProps.courseDeptAndInstr}
status={block.componentProps.status} colors={block.componentProps.colors}/>
<CalendarCourseCell
courseDeptAndInstr={block.componentProps.courseDeptAndInstr}
status={block.componentProps.status}
colors={block.componentProps.colors}
/>
</div>
))}
))}
<div className={styles.buttonContainer}>
<div className={styles.divider}></div> {/* First divider */}
<div className={styles.divider} /> {/* First divider */}
<button className={styles.calendarButton}>
<img src={calIcon} className={styles.buttonIcon} alt="CAL" />
<img src={calIcon} className={styles.buttonIcon} alt='CAL' />
Save as .CAL
</button>
<div className={styles.divider}></div> {/* Second divider */}
<div className={styles.divider} /> {/* Second divider */}
<button onClick={saveAsPNG} className={styles.calendarButton}>
<img src={pngIcon} className={styles.buttonIcon} alt="PNG" />
<img src={pngIcon} className={styles.buttonIcon} alt='PNG' />
Save as .PNG
</button>
</div>
Expand Down
Loading