diff --git a/.eslintrc b/.eslintrc index 9c185f84..57918af5 100644 --- a/.eslintrc +++ b/.eslintrc @@ -73,6 +73,7 @@ "ignoreReadBeforeAssign": false } ], + "no-plusplus": "off", "no-inner-declarations": "off", "sort-imports": "off", "no-case-declarations": "off", diff --git a/.vscode/settings.json b/.vscode/settings.json index e5de7edc..a89cbd32 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,8 @@ { "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, "editor.defaultFormatter": "esbenp.prettier-vscode", "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" @@ -34,4 +37,4 @@ "editor.defaultFormatter": "esbenp.prettier-vscode" }, "typescript.tsdk": "node_modules/typescript/lib", -} \ No newline at end of file +} diff --git a/src/shared/util/colors.ts b/src/shared/util/colors.ts index 807a2c16..d6f7fdd6 100644 --- a/src/shared/util/colors.ts +++ b/src/shared/util/colors.ts @@ -42,9 +42,9 @@ export function pickFontColor(bgColor: string): 'text-white' | 'text-black' { * Get primary and secondary colors from a tailwind colorway * @param colorway the tailwind colorway ex. "emerald" */ -export function getCourseColors(colorway: keyof typeof theme.colors): CourseColors { +export function getCourseColors(colorway: keyof typeof theme.colors, index = 600, offset = 200): CourseColors { return { - primaryColor: theme.colors[colorway][600] as string, - secondaryColor: theme.colors[colorway][800] as string, + primaryColor: theme.colors[colorway][index] as string, + secondaryColor: theme.colors[colorway][index + offset] as string, }; } diff --git a/src/stories/components/CalendarCourseCell.stories.tsx b/src/stories/components/CalendarCourseCell.stories.tsx index 647a766d..19c1908e 100644 --- a/src/stories/components/CalendarCourseCell.stories.tsx +++ b/src/stories/components/CalendarCourseCell.stories.tsx @@ -1,10 +1,9 @@ +import { Course, Status } from '@shared/types/Course'; +import { getCourseColors } from '@shared/util/colors'; import { Meta, StoryObj } from '@storybook/react'; +import CalendarCourseCell from '@views/components/common/CalendarCourseCell/CalendarCourseCell'; import React from 'react'; -import { Course, Status } from 'src/shared/types/Course'; -import { CourseMeeting, DAY_MAP } from 'src/shared/types/CourseMeeting'; -import { CourseSchedule } from 'src/shared/types/CourseSchedule'; -import Instructor from 'src/shared/types/Instructor'; -import CalendarCourseCell from 'src/views/components/common/CalendarCourseCell/CalendarCourseCell'; +import { exampleCourse } from './PopupCourseBlock.stories'; const meta = { title: 'Components/Common/CalendarCourseCell', @@ -16,52 +15,48 @@ const meta = { argTypes: { course: { control: 'object' }, meetingIdx: { control: 'number' }, - color: { control: 'color' }, + colors: { control: 'object' }, }, render: (args: any) => ( -
+
), + args: { + course: exampleCourse, + meetingIdx: 0, + colors: getCourseColors('emerald', 500), + }, } satisfies Meta; export default meta; type Story = StoryObj; -export const Default: Story = { - args: { - course: new Course({ - uniqueId: 123, - number: '311C', - fullName: "311C - Bevo's Default Course", - courseName: "Bevo's Default Course", - department: 'BVO', - creditHours: 3, - status: Status.WAITLISTED, - instructors: [new Instructor({ firstName: '', lastName: 'Bevo', fullName: 'Bevo' })], - isReserved: false, - url: '', - flags: [], - schedule: new CourseSchedule({ - meetings: [ - new CourseMeeting({ - days: [DAY_MAP.M, DAY_MAP.W, DAY_MAP.F], - startTime: 480, - endTime: 570, - location: { - building: 'UTC', - room: '123', - }, - }), - ], - }), - instructionMode: 'In Person', - semester: { - year: 2024, - season: 'Spring', - }, - }), - meetingIdx: 0, - color: 'red', - }, +export const Default: Story = {}; + +export const Variants: Story = { + render: props => ( +
+ + + + +
+ ), }; diff --git a/src/stories/components/ImportantLinks.stories.tsx b/src/stories/components/ImportantLinks.stories.tsx new file mode 100644 index 00000000..9f8a606d --- /dev/null +++ b/src/stories/components/ImportantLinks.stories.tsx @@ -0,0 +1,19 @@ +import { Meta, StoryObj } from '@storybook/react'; +import ImportantLinks from 'src/views/components/ImportantLinks'; + +const meta = { + title: 'Components/Common/ImportantLinks', + component: ImportantLinks, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], + argTypes: {}, +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: {}, +}; diff --git a/src/stories/components/PopupCourseBlock.stories.tsx b/src/stories/components/PopupCourseBlock.stories.tsx index adda6062..0e60f9fe 100644 --- a/src/stories/components/PopupCourseBlock.stories.tsx +++ b/src/stories/components/PopupCourseBlock.stories.tsx @@ -1,13 +1,13 @@ import type { Meta, StoryObj } from '@storybook/react'; +import PopupCourseBlock from '@views/components/common/PopupCourseBlock/PopupCourseBlock'; import React from 'react'; import { Course, Status } from 'src/shared/types/Course'; import { CourseMeeting } from 'src/shared/types/CourseMeeting'; import Instructor from 'src/shared/types/Instructor'; -import PopupCourseBlock from '@views/components/common/PopupCourseBlock/PopupCourseBlock'; import { getCourseColors } from 'src/shared/util/colors'; import { theme } from 'unocss/preset-mini'; -const exampleCourse: Course = new Course({ +export const exampleCourse: Course = new Course({ courseName: 'ELEMS OF COMPTRS/PROGRAMMNG-WB', creditHours: 3, department: 'C S', @@ -103,7 +103,7 @@ export const test_colors = Object.keys(theme.colors) export const AllColors: Story = { render: props => ( -
+
{test_colors.map((color, i) => ( ))} diff --git a/src/views/components/ImportantLinks.tsx b/src/views/components/ImportantLinks.tsx new file mode 100644 index 00000000..5e7c52d1 --- /dev/null +++ b/src/views/components/ImportantLinks.tsx @@ -0,0 +1,65 @@ +import React from 'react'; +import clsx from 'clsx'; +import Text from './common/Text/Text'; +import OutwardArrowIcon from '~icons/material-symbols/arrow-outward'; + +type Props = { + className?: string; +}; + +/** + * The "Important Links" section of the calendar website + * @returns + */ +export default function ImportantLinks({ className }: Props) { + return ( + + ); +} diff --git a/src/views/components/common/CalendarCourseCell/CalendarCourseCell.tsx b/src/views/components/common/CalendarCourseCell/CalendarCourseCell.tsx index cd0969a7..1991126b 100644 --- a/src/views/components/common/CalendarCourseCell/CalendarCourseCell.tsx +++ b/src/views/components/common/CalendarCourseCell/CalendarCourseCell.tsx @@ -1,6 +1,7 @@ +import { Course, Status } from '@shared/types/Course'; +import { CourseMeeting } from '@shared/types/CourseMeeting'; import React from 'react'; -import { Course, Status } from 'src/shared/types/Course'; -import { CourseMeeting } from 'src/shared/types/CourseMeeting'; +import { CourseColors, pickFontColor } from 'src/shared/util/colors'; import ClosedIcon from '~icons/material-symbols/lock'; import WaitlistIcon from '~icons/material-symbols/timelapse'; import CancelledIcon from '~icons/material-symbols/warning'; @@ -11,11 +12,14 @@ export interface CalendarCourseCellProps { course: Course; /* index into course meeting array to display */ meetingIdx?: number; - /** The background color for the course. */ - color: string; + colors: CourseColors; } -const CalendarCourseCell: React.FC = ({ course, meetingIdx }: CalendarCourseCellProps) => { +const CalendarCourseBlock: React.FC = ({ + course, + meetingIdx, + colors, +}: CalendarCourseBlockProps) => { let meeting: CourseMeeting | null = meetingIdx !== undefined ? course.schedule.meetings[meetingIdx] : null; let rightIcon: React.ReactNode | null = null; if (course.status === Status.WAITLISTED) { @@ -26,20 +30,34 @@ const CalendarCourseCell: React.FC = ({ course, meeting rightIcon = ; } + // whiteText based on secondaryColor + const fontColor = pickFontColor(colors.primaryColor); + return ( -
+
{course.department} {course.number} - {course.instructors[0].lastName} - {`${meeting.getTimeString({ separator: '–', capitalize: true })}${ - meeting.location ? ` – ${meeting.location.building}` : '' - }`} + {meeting && + `${meeting.getTimeString({ separator: '–', capitalize: true })}${ + meeting.location ? ` – ${meeting.location.building}` : '' + }`}
{rightIcon && ( -
+
{rightIcon}
)} diff --git a/src/views/components/common/List/List.tsx b/src/views/components/common/List/List.tsx index 8f2f24b5..c61314d4 100644 --- a/src/views/components/common/List/List.tsx +++ b/src/views/components/common/List/List.tsx @@ -135,8 +135,7 @@ const List: React.FC = ({ draggableElements, itemHeight, listHeight,
{items.map((item, index) => ( @@ -150,7 +149,9 @@ const List: React.FC = ({ draggableElements, itemHeight, listHeight, marginBottom: `${gap}px`, }} > - {React.cloneElement(item.content, { dragHandleProps: draggableProvided.dragHandleProps })} + {React.cloneElement(item.content, { + dragHandleProps: draggableProvided.dragHandleProps, + })}
)}