issue #60
All checks were successful
Test CI / build (push) Successful in 17s

- 캘린더 ui 구현 중
This commit is contained in:
geonhee-min
2025-12-04 17:00:02 +09:00
parent daab622638
commit 7df60fe004
4 changed files with 133 additions and 19 deletions

View File

@@ -10,6 +10,7 @@ import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
import { Button, buttonVariants } from "@/components/ui/button" import { Button, buttonVariants } from "@/components/ui/button"
import { format } from "date-fns"
function Calendar({ function Calendar({
className, className,
@@ -36,8 +37,28 @@ function Calendar({
)} )}
captionLayout={captionLayout} captionLayout={captionLayout}
formatters={{ formatters={{
formatCaption: (month) => format(month, "yyyy년 MM월"),
formatWeekdayName: (weekday) => {
switch(weekday.getDay()) {
case 0:
return '일';
case 1:
return '월';
case 2:
return '화';
case 3:
return '수';
case 4:
return '목';
case 5:
return '금';
case 6:
return '토';
}
return '';
},
formatMonthDropdown: (date) => formatMonthDropdown: (date) =>
date.toLocaleString("default", { month: "short" }), date.toLocaleString("", { month: "short" }),
...formatters, ...formatters,
}} }}
classNames={{ classNames={{

View File

@@ -134,6 +134,10 @@ input[type="number"]::-webkit-outer-spin-button {
margin: 0; margin: 0;
} }
.rdp-day {
aspect-ratio: unset;
}
/* Firefox */ /* Firefox */
input[type="number"] { input[type="number"] {
-moz-appearance: textfield; -moz-appearance: textfield;

View File

@@ -0,0 +1,101 @@
import { cn } from "@/lib/utils";
import { Calendar } from "@/components/ui/calendar";
import { useLayoutEffect, useRef, useState } from "react";
import { dateMatchModifiers, getDefaultClassNames } from "react-day-picker";
interface CustomCalendarProps {
data?: any;
}
export const CustomCalendar = ({ data }: CustomCalendarProps) => {
const [weekCount, setWeekCount] = useState(5);
const defaultClassNames = getDefaultClassNames();
const containerRef = useRef<HTMLDivElement>(null);
const updateWeekCount = () => {
if (containerRef === null) return;
if (!containerRef.current) return;
const weeks = containerRef.current.querySelectorAll('.rdp-week');
if (weeks?.length) setWeekCount(weeks.length);
}
useLayoutEffect(() => {
updateWeekCount();
}, []);
return (
<div
className="w-full h-full"
ref={containerRef}
>
<Calendar
mode="single"
className="h-full w-full border rounded-lg"
onMonthChange={() => {
// month 바뀐 직후 DOM 변화가 생기므로 다음 프레임에서 계산
requestAnimationFrame(() => {
updateWeekCount();
});
}}
labels={{
labelDayButton: (date, modifiers) => {
console.log(modifiers);
return `${date.getDate()}`
}
}}
classNames={{
months: cn(
defaultClassNames.months,
"w-full h-full relative"
),
nav: cn(
defaultClassNames.nav,
"flex w-full item-center gap-1 justify-around absolute top-0 inset-x-0"
),
month: cn(
defaultClassNames.month,
"h-full w-full flex flex-col"
),
month_grid: cn(
defaultClassNames.month_grid,
"w-full h-full flex-1"
),
weeks: cn(
defaultClassNames.weeks,
"w-full h-full"
),
weekdays: cn(
defaultClassNames.weekdays,
"w-full"
),
week: cn(
defaultClassNames.week,
`w-full`
),
day: cn(
defaultClassNames.day,
`w-[calc(100%/7)]`
),
day_button: cn(
defaultClassNames.day_button,
"h-full w-full flex p-2 justify-start items-start"
),
selected: cn(
defaultClassNames.selected,
"h-full"
),
today: cn(
defaultClassNames.today,
"h-full"
)
}}
styles={{
day: {
height: `calc(100%/${weekCount})`
}
}}
/>
</div>
)
}

View File

@@ -1,23 +1,11 @@
import { Calendar } from "@/components/ui/calendar"; import { CustomCalendar } from "@/ui/component/calendar/CustomCalendar";
import { cn } from "@/lib/utils";
import { getDefaultClassNames } from "react-day-picker";
export function ScheduleMainPage() { export function ScheduleMainPage() {
const defaultClassNames = getDefaultClassNames();
return ( return (
<div className="w-full h-full p-2"> <div
<Calendar className="w-full h-full p-2"
mode="single" >
className="border w-full rounded-lg" <CustomCalendar />
classNames={{
month_grid: cn(
defaultClassNames.month_grid,
"w-full"
),
}}
/>
</div> </div>
) )
} }