# πŸ“… 달λ ₯ μœ„μ ― κ΅¬ν˜„ κ³„νš ## κ°œμš” λŒ€μ‹œλ³΄λ“œμ— μΆ”κ°€ν•  수 μžˆλŠ” 달λ ₯ μœ„μ ―μ„ κ΅¬ν˜„ν•©λ‹ˆλ‹€. μ‚¬μš©μžκ°€ λ‚ μ§œλ₯Ό ν™•μΈν•˜κ³  일정을 관리할 수 μžˆλŠ” μΈν„°λž™ν‹°λΈŒν•œ 달λ ₯ κΈ°λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€. ## μ£Όμš” κΈ°λŠ₯ ### 1. 달λ ₯ λ·° νƒ€μž… - **μ›”κ°„ λ·°**: ν•œ 달 전체λ₯Ό λ³΄μ—¬μ£ΌλŠ” κΈ°λ³Έ λ·° - **μ£Όκ°„ λ·°**: 일주일을 μ„Έλ‘œλ‘œ λ³΄μ—¬μ£ΌλŠ” λ·° - **일간 λ·°**: ν•˜λ£¨μ˜ μ‹œκ°„λŒ€λ³„ 일정 λ·° ### 2. 달λ ₯ μ„€μ • - **μ‹œμž‘ μš”μΌ**: μ›”μš”μΌ μ‹œμž‘ / μΌμš”μΌ μ‹œμž‘ 선택 - **주말 κ°•μ‘°**: 주말 색상 λ‹€λ₯΄κ²Œ ν‘œμ‹œ - **였늘 λ‚ μ§œ κ°•μ‘°**: 였늘 λ‚ μ§œ ν•˜μ΄λΌμ΄νŠΈ - **곡휴일 ν‘œμ‹œ**: ν•œκ΅­ 곡휴일 ν‘œμ‹œ (선택 사항) ### 3. ν…Œλ§ˆ 및 μŠ€νƒ€μΌ - **Light ν…Œλ§ˆ**: 밝은 λ°°κ²½ - **Dark ν…Œλ§ˆ**: μ–΄λ‘μš΄ λ°°κ²½ - **μ‚¬μš©μž μ§€μ •**: μ»€μŠ€ν…€ 색상 선택 ### 4. 일정 κΈ°λŠ₯ (ν–₯ν›„ ν™•μž₯) - κ°„λ‹¨ν•œ λ©”λͺ¨ μΆ”κ°€ - 일정 ν‘œμ‹œ (μ™ΈλΆ€ 연동) ## κ΅¬ν˜„ 단계 ### βœ… Step 1: νƒ€μž… μ •μ˜ - [x] `CalendarConfig` μΈν„°νŽ˜μ΄μŠ€ μ •μ˜ - [x] `types.ts`에 달λ ₯ μ„€μ • νƒ€μž… μΆ”κ°€ - [x] μš”μ†Œ νƒ€μž…μ— 'calendar' subtype μΆ”κ°€ ### βœ… Step 2: κΈ°λ³Έ 달λ ₯ μ»΄ν¬λ„ŒνŠΈ - [x] `CalendarWidget.tsx` - 메인 μœ„μ ― μ»΄ν¬λ„ŒνŠΈ - [x] `MonthView.tsx` - μ›”κ°„ 달λ ₯ λ·° - [x] λ‚ μ§œ 계산 μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜ (`calendarUtils.ts`) - [ ] `WeekView.tsx` - μ£Όκ°„ 달λ ₯ λ·° (ν–₯ν›„ μΆ”κ°€) ### βœ… Step 3: 달λ ₯ λ„€λΉ„κ²Œμ΄μ…˜ - [x] 이전/λ‹€μŒ μ›” 이동 λ²„νŠΌ - [x] 였늘둜 λŒμ•„κ°€κΈ° λ²„νŠΌ - [ ] μ›”/연도 선택 λ“œλ‘­λ‹€μš΄ (ν–₯ν›„ μΆ”κ°€) ### βœ… Step 4: μ„€μ • UI - [x] `CalendarSettings.tsx` - Popover λ‚΄μž₯ μ„€μ • μ»΄ν¬λ„ŒνŠΈ - [x] λ·° νƒ€μž… 선택 (μ›”κ°„ - ν˜„μž¬ κ΅¬ν˜„) - [x] μ‹œμž‘ μš”μΌ μ„€μ • - [x] ν…Œλ§ˆ 선택 (light/dark/custom) - [x] ν‘œμ‹œ μ˜΅μ…˜ (주말 κ°•μ‘°, 곡휴일, 였늘 κ°•μ‘°) ### βœ… Step 5: μŠ€νƒ€μΌλ§ - [x] 달λ ₯ κ·Έλ¦¬λ“œ λ ˆμ΄μ•„μ›ƒ - [x] λ‚ μ§œ μ…€ λ””μžμΈ - [x] 였늘 λ‚ μ§œ ν•˜μ΄λΌμ΄νŠΈ - [x] 주말/평일 ꡬ뢄 - [x] λ°˜μ‘ν˜• λ””μžμΈ (크기별 μ΅œμ ν™”) ### βœ… Step 6: 톡합 - [x] `DashboardSidebar`에 달λ ₯ μœ„μ ― μΆ”κ°€ - [x] `CanvasElement`μ—μ„œ 달λ ₯ μœ„μ ― λ Œλ”λ§ - [x] `DashboardDesigner`에 κΈ°λ³Έκ°’ μ„€μ • ### βœ… Step 7: 곡휴일 데이터 - [x] ν•œκ΅­ 곡휴일 데이터 μ •μ˜ - [x] 곡휴일 ν‘œμ‹œ κΈ°λŠ₯ - [x] 곡휴일 이름 툴팁 ### βœ… Step 8: ν…ŒμŠ€νŠΈ 및 μ΅œμ ν™” - [ ] λ‹€μ–‘ν•œ ν¬κΈ°μ—μ„œ ν…ŒμŠ€νŠΈ (μ‚¬μš©μž ν…ŒμŠ€νŠΈ ν•„μš”) - [x] λ‚ μ§œ 계산 둜직 검증 - [ ] μ„±λŠ₯ μ΅œμ ν™” (ν•„μš”μ‹œ) - [ ] μ ‘κ·Όμ„± κ°œμ„  (ν•„μš”μ‹œ) ## 기술 μŠ€νƒ ### UI μ»΄ν¬λ„ŒνŠΈ - **shadcn/ui**: Button, Select, Switch, Popover, Card - **lucide-react**: Settings, ChevronLeft, ChevronRight, Calendar ### λ‚ μ§œ 처리 - **JavaScript Date API**: κΈ°λ³Έ λ‚ μ§œ 계산 - **Intl.DateTimeFormat**: λ‚ μ§œ ν˜•μ‹ν™” - μ™ΈλΆ€ 라이브러리 없이 순수 κ΅¬ν˜„ ### μŠ€νƒ€μΌλ§ - **Tailwind CSS**: λ°˜μ‘ν˜• κ·Έλ¦¬λ“œ λ ˆμ΄μ•„μ›ƒ - **CSS Grid**: 달λ ₯ λ ˆμ΄μ•„μ›ƒ ## μ»΄ν¬λ„ŒνŠΈ ꡬ쑰 ``` widgets/ β”œβ”€β”€ CalendarWidget.tsx # 메인 μœ„μ ― (μ„€μ • λ²„νŠΌ 포함) β”œβ”€β”€ CalendarSettings.tsx # μ„€μ • UI (Popover λ‚΄λΆ€) β”œβ”€β”€ MonthView.tsx # μ›”κ°„ λ·° β”œβ”€β”€ WeekView.tsx # μ£Όκ°„ λ·° (선택) β”œβ”€β”€ DayView.tsx # 일간 λ·° (선택) └── calendarUtils.ts # λ‚ μ§œ 계산 μœ ν‹Έλ¦¬ν‹° ``` ## 데이터 ꡬ쑰 ```typescript interface CalendarConfig { view: "month" | "week" | "day"; // λ·° νƒ€μž… startWeekOn: "monday" | "sunday"; // μ£Ό μ‹œμž‘ μš”μΌ highlightWeekends: boolean; // 주말 κ°•μ‘° highlightToday: boolean; // 였늘 κ°•μ‘° showHolidays: boolean; // 곡휴일 ν‘œμ‹œ theme: "light" | "dark" | "custom"; // ν…Œλ§ˆ customColor?: string; // μ‚¬μš©μž μ§€μ • 색상 showWeekNumbers?: boolean; // μ£Όμ°¨ ν‘œμ‹œ (선택) } ``` ## UI/UX 고렀사항 ### λ°˜μ‘ν˜• λ””μžμΈ - **2x2**: λ―Έλ‹ˆ 달λ ₯ (μ›”κ°„ 뷰만, λ‚ μ§œλ§Œ ν‘œμ‹œ) - **3x3**: κΈ°λ³Έ 달λ ₯ (μ›”κ°„ λ·°, μš”μΌ 헀더 포함) - **4x4 이상**: ν’€ 달λ ₯ (λͺ¨λ“  κΈ°λŠ₯, 일정 ν‘œμ‹œ κ°€λŠ₯) ### μΈν„°λž™μ…˜ - λ‚ μ§œ 클릭 μ‹œ ν•΄λ‹Ή λ‚ μ§œ 정보 ν‘œμ‹œ (선택) - λ“œλž˜κ·Έλ‘œ μ›” λ³€κ²½ (선택) - ν‚€λ³΄λ“œ λ„€λΉ„κ²Œμ΄μ…˜ 지원 ### μ ‘κ·Όμ„± - λ‚ μ§œ 셀에 μ μ ˆν•œ aria-label - ν‚€λ³΄λ“œ λ„€λΉ„κ²Œμ΄μ…˜ 지원 - 슀크린 리더 ν˜Έν™˜ ## 곡휴일 데이터 ꡬ쑰 ```typescript interface Holiday { date: string; // 'MM-DD' ν˜•μ‹ name: string; // 곡휴일 이름 isRecurring: boolean; // λ§€λ…„ 반볡 μ—¬λΆ€ } // 2025λ…„ ν•œκ΅­ 곡휴일 μ˜ˆμ‹œ const KOREAN_HOLIDAYS: Holiday[] = [ { date: "01-01", name: "μ‹ μ •", isRecurring: true }, { date: "01-28", name: "μ„€λ‚  μ—°νœ΄", isRecurring: false }, { date: "01-29", name: "μ„€λ‚ ", isRecurring: false }, { date: "01-30", name: "μ„€λ‚  μ—°νœ΄", isRecurring: false }, { date: "03-01", name: "μ‚ΌμΌμ ˆ", isRecurring: true }, { date: "05-05", name: "어린이날", isRecurring: true }, { date: "06-06", name: "ν˜„μΆ©μΌ", isRecurring: true }, { date: "08-15", name: "κ΄‘λ³΅μ ˆ", isRecurring: true }, { date: "10-03", name: "개천절", isRecurring: true }, { date: "10-09", name: "ν•œκΈ€λ‚ ", isRecurring: true }, { date: "12-25", name: "크리슀마슀", isRecurring: true }, ]; ``` ## ν–₯ν›„ ν™•μž₯ κΈ°λŠ₯ ### Phase 2 (선택) - [ ] 일정 μΆ”κ°€/μˆ˜μ •/μ‚­μ œ - [ ] 반볡 일정 μ„€μ • - [ ] μΉ΄ν…Œκ³ λ¦¬λ³„ 색상 ꡬ뢄 - [ ] λ‹€λ₯Έ 달λ ₯ μ„œλΉ„μŠ€ 연동 (Google Calendar, Outlook λ“±) - [ ] 일정 μ•Œλ¦Ό κΈ°λŠ₯ - [ ] λ“œλž˜κ·Έ μ•€ λ“œλ‘­μœΌλ‘œ 일정 이동 ### Phase 3 (선택) - [ ] μ—¬λŸ¬ 달λ ₯ λ ˆμ΄μ–΄ 지원 - [ ] 일정 검색 κΈ°λŠ₯ - [ ] 월별 톡계 (일정 개수 λ“±) - [ ] CSV/iCal 내보내기 ## 참고사항 ### μž₯점 - 순수 JavaScript둜 κ΅¬ν˜„ (μ™ΈλΆ€ μ˜μ‘΄μ„± μ΅œμ†Œν™”) - shadcn/ui μ»΄ν¬λ„ŒνŠΈ ν™œμš©μœΌλ‘œ μΌκ΄€λœ λ””μžμΈ - μ‹œκ³„ μœ„μ ―κ³Ό λ™μΌν•œ νŒ¨ν„΄ (λ‚΄μž₯ μ„€μ • UI) ### μ£Όμ˜μ‚¬ν•­ - λ‚ μ§œ 계산 둜직 μ •ν™•μ„± 검증 ν•„μš” - μœ€λ…„ 처리 - νƒ€μž„μ‘΄ κ³ λ € (ν•„μš”μ‹œ) - λ‹€μ–‘ν•œ ν¬κΈ°μ—μ„œμ˜ 가독성 ## μ™„λ£Œ κΈ°μ€€ - [x] μ›”κ°„ λ·° 달λ ₯이 μ •ν™•ν•˜κ²Œ ν‘œμ‹œλ¨ - [x] 이전/λ‹€μŒ μ›” λ„€λΉ„κ²Œμ΄μ…˜μ΄ μž‘λ™ν•¨ - [x] 였늘 λ‚ μ§œκ°€ ν•˜μ΄λΌμ΄νŠΈλ¨ - [x] 주말이 λ‹€λ₯Έ μƒ‰μƒμœΌλ‘œ ν‘œμ‹œλ¨ - [x] 곡휴일이 ν‘œμ‹œλ˜κ³  이름이 λ³΄μž„ - [x] μ„€μ • UIμ—μ„œ λͺ¨λ“  μ˜΅μ…˜μ„ λ³€κ²½ν•  수 있음 - [x] ν…Œλ§ˆ 변경이 μ¦‰μ‹œ 반영됨 - [x] 2x2 ν¬κΈ°μ—μ„œλ„ κΉ”λ”ν•˜κ²Œ ν‘œμ‹œλ¨ - [x] 4x4 ν¬κΈ°μ—μ„œ λͺ¨λ“  κΈ°λŠ₯이 정상 μž‘λ™ν•¨ --- ## κ΅¬ν˜„ μ‹œμž‘ 이제 λ‹¨κ³„λ³„λ‘œ κ΅¬ν˜„μ„ μ‹œμž‘ν•©λ‹ˆλ‹€!