From 291a8c88e83155bef6d9b2d35988a289462e6812 Mon Sep 17 00:00:00 2001 From: jsun969 Date: Sun, 22 Sep 2024 01:03:32 +0930 Subject: [PATCH] feat: course colors and card --- src/components/Calendar.tsx | 46 ++++++++++++++++++-- src/components/EnrolledCourses.tsx | 12 +++--- src/constants/course-colors.ts | 69 ++++++++++++++++++++++++++++++ src/data/enrolled-courses.ts | 9 ++++ src/helpers/calendar.ts | 2 + tailwind.config.js | 3 ++ 6 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 src/constants/course-colors.ts diff --git a/src/components/Calendar.tsx b/src/components/Calendar.tsx index 9fbe673..2f85574 100644 --- a/src/components/Calendar.tsx +++ b/src/components/Calendar.tsx @@ -1,13 +1,41 @@ import { Button } from '@nextui-org/react'; -import { useEffect } from 'react'; +import clsx from 'clsx'; +import { useCourseColor } from '../data/enrolled-courses'; import { useCalendar } from '../helpers/calendar'; +import type { WeekCourse } from '../types/course'; + +const CourseCard = ({ + course, + className, +}: { + course: WeekCourse; + className?: string; +}) => { + const color = useCourseColor(course.id); + + return ( +
+
{course.time.start}
+
+ [{course.classType}] {course.name.subject} {course.name.code} -{' '} + {course.name.title} +
+
{course.location}
+
+ ); +}; export const Calendar = () => { const { courses, currentWeek, nextWeek, prevWeek } = useCalendar(); - useEffect(() => { - console.log(courses); - }); return (
@@ -28,6 +56,16 @@ export const Calendar = () => { > ➡️ + {Object.entries(courses).map(([day, dayCourses]) => ( +
+

{day}

+
+ {dayCourses.map((c) => ( + + ))} +
+
+ ))}
); }; diff --git a/src/components/EnrolledCourses.tsx b/src/components/EnrolledCourses.tsx index f4576b0..08eb793 100644 --- a/src/components/EnrolledCourses.tsx +++ b/src/components/EnrolledCourses.tsx @@ -4,16 +4,16 @@ import clsx from 'clsx'; import { useState } from 'react'; import { getCourse } from '../apis'; -import { useEnrolledCourses } from '../data/enrolled-courses'; +import { useCourseColor, useEnrolledCourses } from '../data/enrolled-courses'; import { CourseModal } from './CourseModal'; type CourseChipProps = { name: string; id: string; onOpenModal: (id: string) => void; - className?: string; }; -const CourseChip = ({ name, id, onOpenModal, className }: CourseChipProps) => { +const CourseChip = ({ name, id, onOpenModal }: CourseChipProps) => { + const color = useCourseColor(id); const removeCourse = useEnrolledCourses((s) => s.removeCourse); const { isFetching, isError } = useQuery({ @@ -23,8 +23,7 @@ const CourseChip = ({ name, id, onOpenModal, className }: CourseChipProps) => { return ( { removeCourse(id); }} @@ -34,9 +33,10 @@ const CourseChip = ({ name, id, onOpenModal, className }: CourseChipProps) => { }} classNames={{ base: clsx( + 'border-primary text-primary', isFetching ? 'cursor-wait' : 'cursor-pointer hover:brightness-125', - className, ), + dot: color.dot, }} > {isFetching && '⏳ '} diff --git a/src/constants/course-colors.ts b/src/constants/course-colors.ts new file mode 100644 index 0000000..9e1aed0 --- /dev/null +++ b/src/constants/course-colors.ts @@ -0,0 +1,69 @@ +// Thanks to @Char2sGu for the help with types +type CourseColor = { + border: `border-[#${Primary}]`; + bg: `bg-[#${string}]`; + text: `text-[#${string}]`; + dot: `bg-[#${NoInfer}]`; +}; + +/** + * Enforces dot color to be the same as border color + * @param color + * @returns + */ +const color = (color: CourseColor) => { + return color; +}; + +const BLUE = color({ + border: 'border-[#1D9BF6]', + bg: 'bg-[#C9E6FE]', + text: 'text-[#1D6AA1]', + dot: 'bg-[#1D9BF6]', +}); +const PURPLE = color({ + border: 'border-[#AF38D1]', + bg: 'bg-[#EACDF4]', + text: 'text-[#762C8B]', + dot: 'bg-[#AF38D1]', +}); +const GREEN = color({ + border: 'border-[#4AD321]', + bg: 'bg-[#D4F6C9]', + text: 'text-[#3E8522]', + dot: 'bg-[#4AD321]', +}); +const ORANGE = color({ + border: 'border-[#FA6D0D]', + bg: 'bg-[#FEDBC4]', + text: 'text-[#A75117]', + dot: 'bg-[#FA6D0D]', +}); +const YELLOW = color({ + border: 'border-[#FCB80F]', + bg: 'bg-[#FDEEC3]', + text: 'text-[#936E10]', + dot: 'bg-[#FCB80F]', +}); +const BROWN = color({ + border: 'border-[#7D5E3B]', + bg: 'bg-[#DFD8CF]', + text: 'text-[#5E4D39]', + dot: 'bg-[#7D5E3B]', +}); +const RED = color({ + border: 'border-[#F50445]', + bg: 'bg-[#FEBFD1]', + text: 'text-[#BB1644]', + dot: 'bg-[#F50445]', +}); +const BLACK = color({ + border: 'border-[#000000]', + bg: 'bg-[#D3D3D3]', + text: 'text-[#000000]', + dot: 'bg-[#000000]', +}); + +export const COURSE_COLORS = [BLUE, PURPLE, GREEN, ORANGE, YELLOW, BROWN, RED]; + +export const NOT_FOUND_COLOR = BLACK; diff --git a/src/data/enrolled-courses.ts b/src/data/enrolled-courses.ts index d335299..2fce9b0 100644 --- a/src/data/enrolled-courses.ts +++ b/src/data/enrolled-courses.ts @@ -4,6 +4,7 @@ import { mutative } from 'zustand-mutative'; import { persist } from 'zustand/middleware'; import { getCourse } from '../apis'; +import { COURSE_COLORS, NOT_FOUND_COLOR } from '../constants/course-colors'; import { LocalStorageKey } from '../constants/local-storage-keys'; import { queryClient } from '../lib/query'; import type { DetailedEnrolledCourse } from '../types/course'; @@ -112,3 +113,11 @@ export const useDetailedEnrolledCourses = (): Array => { return detailedCourses.filter((c) => c !== null); }; + +export const useCourseColor = (id: string) => { + const courseIndex = useEnrolledCourses((s) => + s.courses.findIndex((c) => c.id === id), + ); + if (courseIndex === -1) return NOT_FOUND_COLOR; + return COURSE_COLORS[courseIndex]; +}; diff --git a/src/helpers/calendar.ts b/src/helpers/calendar.ts index 059278d..2b1537b 100644 --- a/src/helpers/calendar.ts +++ b/src/helpers/calendar.ts @@ -109,7 +109,9 @@ export const useCalendar = () => { setCurrentWeek((c) => c.subtract(1, 'week')); }; + console.log('currentWeek', enrolledCourses); const courses = getWeekCourses(currentWeek, enrolledCourses); + console.log('courses', courses); return { currentWeek, nextWeek, prevWeek, courses }; }; diff --git a/tailwind.config.js b/tailwind.config.js index fe39e62..5f87080 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -12,6 +12,9 @@ export default { screens: { mobile: { max: '767px' }, }, + fontSize: { + '2xs': ['0.625rem', { lineHeight: '0.75rem' }], + }, }, }, darkMode: 'class',