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

139 lines
4.5 KiB
TypeScript

"use client";
import { useState } from "react";
import { DashboardElement, CalendarConfig } from "../types";
import { MonthView } from "./MonthView";
import { CalendarSettings } from "./CalendarSettings";
import { generateCalendarDays, getMonthName, navigateMonth } from "./calendarUtils";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Button } from "@/components/ui/button";
import { Settings, ChevronLeft, ChevronRight, Calendar } from "lucide-react";
import { useDashboard } from "@/contexts/DashboardContext";
interface CalendarWidgetProps {
element: DashboardElement;
onConfigUpdate?: (config: CalendarConfig) => void;
}
/**
* 달력 위젯 메인 컴포넌트
* - 월간/주간/일간 뷰 지원
* - 네비게이션 (이전/다음 월, 오늘)
* - 내장 설정 UI
*/
export function CalendarWidget({ element, onConfigUpdate }: CalendarWidgetProps) {
// Context에서 선택된 날짜 관리
const { selectedDate, setSelectedDate } = useDashboard();
// 현재 표시 중인 년/월
const today = new Date();
const [currentYear, setCurrentYear] = useState(today.getFullYear());
const [currentMonth, setCurrentMonth] = useState(today.getMonth());
const [settingsOpen, setSettingsOpen] = useState(false);
// 날짜 클릭 핸들러
const handleDateClick = (date: Date) => {
setSelectedDate(date);
};
// 기본 설정값
const config = element.calendarConfig || {
view: "month",
startWeekOn: "sunday",
highlightWeekends: true,
highlightToday: true,
showHolidays: true,
theme: "light",
};
// 설정 저장 핸들러
const handleSaveSettings = (newConfig: CalendarConfig) => {
onConfigUpdate?.(newConfig);
setSettingsOpen(false);
};
// 이전 월로 이동
const handlePrevMonth = () => {
const { year, month } = navigateMonth(currentYear, currentMonth, "prev");
setCurrentYear(year);
setCurrentMonth(month);
};
// 다음 월로 이동
const handleNextMonth = () => {
const { year, month } = navigateMonth(currentYear, currentMonth, "next");
setCurrentYear(year);
setCurrentMonth(month);
};
// 오늘로 돌아가기
const handleToday = () => {
setCurrentYear(today.getFullYear());
setCurrentMonth(today.getMonth());
};
// 달력 날짜 생성
const calendarDays = generateCalendarDays(currentYear, currentMonth, config.startWeekOn);
// 크기에 따른 컴팩트 모드 판단
const isCompact = element.size.width < 400 || element.size.height < 400;
return (
<div className="relative flex h-full w-full flex-col">
{/* 헤더 - 네비게이션 */}
<div className="flex items-center justify-between border-b border-gray-200 p-2">
{/* 이전 월 버튼 */}
<Button variant="ghost" size="icon" className="h-7 w-7" onClick={handlePrevMonth}>
<ChevronLeft className="h-4 w-4" />
</Button>
{/* 현재 년월 표시 */}
<div className="flex items-center gap-2">
<span className="text-sm font-semibold">
{currentYear} {getMonthName(currentMonth)}
</span>
{!isCompact && (
<Button variant="outline" size="sm" className="h-6 px-2 text-xs" onClick={handleToday}>
</Button>
)}
</div>
{/* 다음 월 버튼 */}
<Button variant="ghost" size="icon" className="h-7 w-7" onClick={handleNextMonth}>
<ChevronRight className="h-4 w-4" />
</Button>
</div>
{/* 달력 콘텐츠 */}
<div className="flex-1 overflow-hidden">
{config.view === "month" && (
<MonthView
days={calendarDays}
config={config}
isCompact={isCompact}
selectedDate={selectedDate}
onDateClick={handleDateClick}
/>
)}
{/* 추후 WeekView, DayView 추가 가능 */}
</div>
{/* 설정 버튼 - 우측 하단 */}
<div className="absolute bottom-2 right-2">
<Popover open={settingsOpen} onOpenChange={setSettingsOpen}>
<PopoverTrigger asChild>
<Button variant="ghost" size="icon" className="h-8 w-8 bg-white/80 hover:bg-white">
<Settings className="h-4 w-4" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-[450px] p-0" align="end">
<CalendarSettings config={config} onSave={handleSaveSettings} onClose={() => setSettingsOpen(false)} />
</PopoverContent>
</Popover>
</div>
</div>
);
}