ERP-node/frontend/components/admin/dashboard/widgets/MonthView.tsx

152 lines
4.4 KiB
TypeScript
Raw Normal View History

2025-10-14 10:48:17 +09:00
"use client";
import { CalendarConfig } from "../types";
import { CalendarDay, getWeekDayNames } from "./calendarUtils";
interface MonthViewProps {
days: CalendarDay[];
config: CalendarConfig;
isCompact?: boolean; // 작은 크기 (2x2, 3x3)
selectedDate?: Date | null; // 선택된 날짜
onDateClick?: (date: Date) => void; // 날짜 클릭 핸들러
2025-10-14 10:48:17 +09:00
}
/**
*
*/
export function MonthView({ days, config, isCompact = false, selectedDate, onDateClick }: MonthViewProps) {
2025-10-14 10:48:17 +09:00
const weekDayNames = getWeekDayNames(config.startWeekOn);
// 테마별 스타일
const getThemeStyles = () => {
if (config.theme === "custom" && config.customColor) {
return {
todayBg: config.customColor,
holidayText: config.customColor,
weekendText: "#dc2626",
};
}
if (config.theme === "dark") {
return {
todayBg: "#3b82f6",
holidayText: "#f87171",
weekendText: "#f87171",
};
}
// light 테마
return {
todayBg: "#3b82f6",
holidayText: "#dc2626",
weekendText: "#dc2626",
};
};
const themeStyles = getThemeStyles();
// 날짜가 선택된 날짜인지 확인
const isSelected = (day: CalendarDay) => {
if (!selectedDate || !day.isCurrentMonth) return false;
return (
selectedDate.getFullYear() === day.date.getFullYear() &&
selectedDate.getMonth() === day.date.getMonth() &&
selectedDate.getDate() === day.date.getDate()
);
};
// 날짜 클릭 핸들러
const handleDayClick = (day: CalendarDay) => {
if (!day.isCurrentMonth || !onDateClick) return;
onDateClick(day.date);
};
2025-10-14 10:48:17 +09:00
// 날짜 셀 스타일 클래스
const getDayCellClass = (day: CalendarDay) => {
const baseClass = "flex aspect-square items-center justify-center rounded-lg transition-colors";
const sizeClass = isCompact ? "text-xs" : "text-sm";
const cursorClass = day.isCurrentMonth ? "cursor-pointer" : "cursor-default";
2025-10-14 10:48:17 +09:00
2025-10-29 17:53:03 +09:00
let colorClass = "text-foreground";
2025-10-14 10:48:17 +09:00
// 현재 월이 아닌 날짜
if (!day.isCurrentMonth) {
2025-10-29 17:53:03 +09:00
colorClass = "text-muted-foreground";
2025-10-14 10:48:17 +09:00
}
// 선택된 날짜
else if (isSelected(day)) {
colorClass = "text-white font-bold";
}
2025-10-14 10:48:17 +09:00
// 오늘
else if (config.highlightToday && day.isToday) {
colorClass = "text-white font-bold";
}
// 공휴일
else if (config.showHolidays && day.isHoliday) {
colorClass = "font-semibold";
}
// 주말
else if (config.highlightWeekends && day.isWeekend) {
2025-10-29 17:53:03 +09:00
colorClass = "text-destructive";
2025-10-14 10:48:17 +09:00
}
let bgClass = "";
if (isSelected(day)) {
bgClass = ""; // 선택된 날짜는 배경색이 style로 적용됨
} else if (config.highlightToday && day.isToday) {
bgClass = "";
} else {
2025-10-29 17:53:03 +09:00
bgClass = "hover:bg-muted";
}
2025-10-14 10:48:17 +09:00
return `${baseClass} ${sizeClass} ${colorClass} ${bgClass} ${cursorClass}`;
2025-10-14 10:48:17 +09:00
};
return (
<div className="flex h-full flex-col p-2">
{/* 요일 헤더 */}
{!isCompact && (
<div className="mb-2 grid grid-cols-7 gap-1">
{weekDayNames.map((name, index) => {
const isWeekend = config.startWeekOn === "sunday" ? index === 0 || index === 6 : index === 5 || index === 6;
return (
<div
key={name}
2025-10-29 17:53:03 +09:00
className={`text-center text-xs font-semibold ${isWeekend && config.highlightWeekends ? "text-destructive" : "text-foreground"}`}
2025-10-14 10:48:17 +09:00
>
{name}
</div>
);
})}
</div>
)}
{/* 날짜 그리드 */}
<div className="grid flex-1 grid-cols-7 gap-1">
{days.map((day, index) => (
<div
key={index}
className={getDayCellClass(day)}
onClick={() => handleDayClick(day)}
2025-10-14 10:48:17 +09:00
style={{
backgroundColor: isSelected(day)
? "hsl(var(--success))" // 선택된 날짜는 성공 색상
: config.highlightToday && day.isToday
? themeStyles.todayBg
: undefined,
2025-10-14 10:48:17 +09:00
color:
config.showHolidays && day.isHoliday && day.isCurrentMonth
? themeStyles.holidayText
: undefined,
}}
title={day.isHoliday ? day.holidayName : undefined}
>
{day.day}
</div>
))}
</div>
</div>
);
}