From 6aedbc8e1f5c1494fbb106aa797e6fcf70612569 Mon Sep 17 00:00:00 2001 From: Hakjoon Sim Date: Wed, 28 Feb 2024 16:01:31 +0900 Subject: [PATCH] BP Calendar component added --- src/app/bp/history/page.tsx | 9 +- src/components/bp/calendar.tsx | 160 +++++++++++++++++++++++++++++++++ src/components/button.tsx | 4 +- 3 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 src/components/bp/calendar.tsx diff --git a/src/app/bp/history/page.tsx b/src/app/bp/history/page.tsx index b0228de..7b1a31d 100644 --- a/src/app/bp/history/page.tsx +++ b/src/app/bp/history/page.tsx @@ -1,3 +1,10 @@ +import Calendar from '@/components/bp/calendar'; + export default function History() { - return
BP history
; + return ( +
+
BP history
+ +
+ ); } diff --git a/src/components/bp/calendar.tsx b/src/components/bp/calendar.tsx new file mode 100644 index 0000000..ae80356 --- /dev/null +++ b/src/components/bp/calendar.tsx @@ -0,0 +1,160 @@ +'use client'; + +import { + addDays, + addMonths, + endOfMonth, + getDate, + getDay, + getMonth, + getYear, + isBefore, + isSameMonth, + startOfMonth, + subMonths, +} from 'date-fns'; +import { memo, useEffect, useMemo, useState } from 'react'; +import Button from '../button'; + +export default function Calendar() { + const today = new Date(); + + const [start, setStart] = useState(() => startOfMonth(today)); + const [end, setEnd] = useState(() => endOfMonth(today)); + const [daysArr, setDaysArr] = useState([]); + + useEffect(() => { + setEnd(endOfMonth(start)); + }, [start]); + + useEffect(() => { + if (isBefore(end, start)) { + return; + } + + setDaysArr(() => { + const arr: Date[][] = []; + let currentDate = new Date(start); + + while (isSameMonth(currentDate, end)) { + arr.push([]); + + for (let i = 0; i < 7; i += 1) { + if (getDay(currentDate) === i) { + arr[arr.length - 1][i] = new Date(currentDate); + currentDate = addDays(currentDate, 1); + } + + if (!isSameMonth(currentDate, end)) { + break; + } + } + } + + return arr; + }); + }, [end, start]); + + const getMonthString = useMemo( + () => (date: Date) => { + switch (getMonth(date)) { + case 0: + return 'Jan.'; + case 1: + return 'Feb.'; + case 2: + return 'Mar.'; + case 3: + return 'Apr.'; + case 4: + return 'May'; + case 5: + return 'Jun.'; + case 6: + return 'Jul.'; + case 7: + return 'Aug.'; + case 8: + return 'Sep.'; + case 9: + return 'Oct.'; + case 10: + return 'Nov.'; + case 11: + return 'Dec.'; + } + }, + [], + ); + + return ( + <> +
+
+ +
+
+ +
+
+ {getMonthString(start)} {getYear(start)} +
+
+
+ {daysArr.map((week, i) => ( +
+ {[0, 1, 2, 3, 4, 5, 6].map((i) => ( + + ))} +
+ ))} +
+ + ); +} + +const Cell = memo(({ date }: { date: Date }) => { + const getDayString = useMemo( + () => (date: Date) => { + switch (getDay(date)) { + case 0: + return 'SUN'; + case 1: + return 'MON'; + case 2: + return 'TUE'; + case 3: + return 'WED'; + case 4: + return 'THU'; + case 5: + return 'FRI'; + case 6: + return 'SAT'; + default: + return ''; + } + }, + [], + ); + + return ( +
+ {date ? ( +
+
+
{getDayString(date)}
+
{getDate(date)}
+
+
+ ) : ( +
+ )} +
+ ); +}); +Cell.displayName = 'Cell'; diff --git a/src/components/button.tsx b/src/components/button.tsx index 1b750dc..b5a0a00 100644 --- a/src/components/button.tsx +++ b/src/components/button.tsx @@ -5,12 +5,14 @@ const Button = ({ color = 'zinc', size = 'base', disabled = false, + throttle = 1000, onClick, }: { children: ReactNode; color?: 'zinc' | 'indigo'; size?: 'xs' | 'sm' | 'base' | 'lg'; disabled?: boolean; + throttle?: number; onClick: () => void; }) => { const throttleRef = useRef(null); @@ -22,7 +24,7 @@ const Button = ({ throttleRef.current = setTimeout(() => { throttleRef.current = null; - }, 1000); + }, throttle); onClick(); };