diff --git a/task_yell/src/app/home/page.tsx b/task_yell/src/app/home/page.tsx index e73d52e..cb01df8 100644 --- a/task_yell/src/app/home/page.tsx +++ b/task_yell/src/app/home/page.tsx @@ -13,14 +13,7 @@ import { } from "@/lib/want-todo"; import { addMonths, - eachDayOfInterval, - endOfMonth, - endOfWeek, format, - isSameDay, - isSameMonth, - startOfMonth, - startOfWeek, subMonths, } from "date-fns"; import { ja } from "date-fns/locale"; @@ -35,11 +28,11 @@ import { useRouter } from "next/navigation"; import { useEffect, useMemo, useRef, useState } from "react"; import { generateStickyNoteServer } from "./actions"; import { Event, Todo, StickyNote } from "@/components/types"; -import { priorityColors } from "@/components/priority-colors"; import { Navigation } from "@/components/navigation"; import { EditWantodoDialog } from "@/components/edit-wantodo-dialog"; import { CreateEventDialog } from "@/components/create-event-dialog"; import { StickyNoteItem } from "@/components/sticky-note-item"; +import { CalendarRenderer } from "@/components/calendar-renderer"; export default function Home() { const [todos] = useState([]); @@ -199,138 +192,6 @@ export default function Home() { } }; - const getDaysInMonth = (date: Date) => { - const start = startOfWeek(startOfMonth(date), { weekStartsOn: 0 }); - const end = endOfWeek(endOfMonth(date), { weekStartsOn: 0 }); - return eachDayOfInterval({ start, end }); - }; - - const getTodoCountForDay = (day: Date) => { - return todos.filter((todo) => isSameDay(todo.date, day)).length; - }; - - const getEventCountForDay = (day: Date) => { - return events.filter((event) => event.start && isSameDay(event.start, day)) - .length; - }; - - const getTaskIndicatorStyle = (todoCount: number, eventCount: number) => { - const count = todoCount + eventCount; - if (count === 0) return ""; - const baseColor = isDarkMode ? "bg-red-" : "bg-red-"; - const intensity = Math.min(count * 100, 900); - const colorClass = `${baseColor}${intensity}`; - return `${colorClass} ${count >= 3 ? "animate-pulse" : ""}`; - }; - - const renderCalendar = () => { - const days = getDaysInMonth(currentMonth); - const weeks = Math.ceil(days.length / 7); - - return ( -
-
- {["日", "月", "火", "水", "木", "金", "土"].map((day) => ( -
- {day} -
- ))} -
- {Array.from({ length: weeks }).map((_, weekIndex) => { - const weekDays = days.slice(weekIndex * 7, (weekIndex + 1) * 7); - const maxEventsInWeek = Math.max( - ...weekDays.map( - (day) => getTodoCountForDay(day) + getEventCountForDay(day), - ), - ); - const weekHeight = - maxEventsInWeek > 2 ? Math.min(maxEventsInWeek * 20, 100) : "auto"; - - return ( -
- {weekDays.map((day) => { - const todoCount = getTodoCountForDay(day); - const eventCount = getEventCountForDay(day); - const isSelected = isSameDay(day, selectedDate); - const isCurrentMonth = isSameMonth(day, currentMonth); - const dayItems = [ - ...todos.filter((todo) => isSameDay(todo.date, day)), - ...events.filter( - (event) => event.start && isSameDay(event.start, day), - ), - ]; - - return ( - handleDateSelect(day)} - whileHover={{ scale: 1.05 }} - whileTap={{ scale: 0.95 }} - onDragOver={(e) => { - e.preventDefault(); - e.currentTarget.classList.add( - "bg-blue-100", - "dark:bg-blue-800", - ); - }} - onDragLeave={(e) => { - e.currentTarget.classList.remove( - "bg-blue-100", - "dark:bg-blue-800", - ); - }} - onDrop={(e) => { - e.preventDefault(); - e.currentTarget.classList.remove( - "bg-blue-100", - "dark:bg-blue-800", - ); - if (draggedStickyNote) { - handleDateSelect(day); - setIsEventModalOpen(true); - deleteStickyNote(draggedStickyNote.id); - } - }} - > -
{format(day, "d")}
- {(todoCount > 0 || eventCount > 0) && ( -
- {dayItems.slice(0, 2).map((item, index) => ( -
- {"text" in item ? item.text : item.title} -
- ))} - {dayItems.length > 2 && ( -
- +{dayItems.length - 2} more -
- )} -
- )} -
- ); - })} -
- ); - })} -
- ); - }; - const handleDateSelect = (date: Date) => { setSelectedDate(date); setIsEventModalOpen(true); @@ -377,7 +238,18 @@ export default function Home() { - {renderCalendar()} +
diff --git a/task_yell/src/components/calendar-renderer.tsx b/task_yell/src/components/calendar-renderer.tsx new file mode 100644 index 0000000..e1da054 --- /dev/null +++ b/task_yell/src/components/calendar-renderer.tsx @@ -0,0 +1,167 @@ +"use client"; + +import { + eachDayOfInterval, + endOfMonth, + endOfWeek, + format, + isSameDay, + isSameMonth, + startOfMonth, + startOfWeek, +} from "date-fns"; +import { motion } from "framer-motion"; +import { Event, Todo, StickyNote } from "@/components/types"; +import { priorityColors } from "@/components/priority-colors"; + +type Props = { + todos: Todo[]; + events: Event[]; + stickyNotes: StickyNote[]; + currentMonth: Date; + selectedDate: Date; + handleDateSelect: (date: Date) => void; + isDarkMode: boolean; + draggedStickyNote: StickyNote | null; + deleteStickyNote: (id: string) => void; + setIsEventModalOpen: (isOpen: boolean) => void; +} + +function getDaysInMonth(date: Date) { + const start = startOfWeek(startOfMonth(date), { weekStartsOn: 0 }); + const end = endOfWeek(endOfMonth(date), { weekStartsOn: 0 }); + return eachDayOfInterval({ start, end }); +} + +function getTodoCountForDay(todos: Todo[], day: Date) { + return todos.filter((todo) => isSameDay(todo.date, day)).length; +} + +function getEventCountForDay(events: Event[], day: Date) { + return events.filter((event) => event.start && isSameDay(event.start, day)) + .length; +} + +function getTaskIndicatorStyle(isDarkMode: boolean, todoCount: number, eventCount: number) { + const count = todoCount + eventCount; + if (count === 0) return ""; + const baseColor = isDarkMode ? "bg-red-" : "bg-red-"; + const intensity = Math.min(count * 100, 900); + const colorClass = `${baseColor}${intensity}`; + return `${colorClass} ${count >= 3 ? "animate-pulse" : ""}`; +} + +export function CalendarRenderer({ + todos, events, + currentMonth, selectedDate, handleDateSelect, + isDarkMode, + draggedStickyNote, deleteStickyNote, + setIsEventModalOpen +}: Props +) { + const days = getDaysInMonth(currentMonth); + const weeks = Math.ceil(days.length / 7); + + return ( +
+
+ {["日", "月", "火", "水", "木", "金", "土"].map((day) => ( +
+ {day} +
+ ))} +
+ {Array.from({ length: weeks }).map((_, weekIndex) => { + const weekDays = days.slice(weekIndex * 7, (weekIndex + 1) * 7); + const maxEventsInWeek = Math.max( + ...weekDays.map( + (day) => getTodoCountForDay(todos, day) + getEventCountForDay(events, day), + ), + ); + const weekHeight = + maxEventsInWeek > 2 ? Math.min(maxEventsInWeek * 20, 100) : "auto"; + + return ( +
+ {weekDays.map((day) => { + const todoCount = getTodoCountForDay(todos, day); + const eventCount = getEventCountForDay(events, day); + const isSelected = isSameDay(day, selectedDate); + const isCurrentMonth = isSameMonth(day, currentMonth); + const dayItems = [ + ...todos.filter((todo) => isSameDay(todo.date, day)), + ...events.filter( + (event) => event.start && isSameDay(event.start, day), + ), + ]; + + return ( + handleDateSelect(day)} + whileHover={{ scale: 1.05 }} + whileTap={{ scale: 0.95 }} + onDragOver={(e) => { + e.preventDefault(); + e.currentTarget.classList.add( + "bg-blue-100", + "dark:bg-blue-800", + ); + }} + onDragLeave={(e) => { + e.currentTarget.classList.remove( + "bg-blue-100", + "dark:bg-blue-800", + ); + }} + onDrop={(e) => { + e.preventDefault(); + e.currentTarget.classList.remove( + "bg-blue-100", + "dark:bg-blue-800", + ); + if (draggedStickyNote) { + handleDateSelect(day); + setIsEventModalOpen(true); + deleteStickyNote(draggedStickyNote.id); + } + }} + > +
{format(day, "d")}
+ {(todoCount > 0 || eventCount > 0) && ( +
+ {dayItems.slice(0, 2).map((item, index) => ( +
+ {"text" in item ? item.text : item.title} +
+ ))} + {dayItems.length > 2 && ( +
+ +{dayItems.length - 2} more +
+ )} +
+ )} +
+ ); + })} +
+ ); + })} +
+ ); +}; \ No newline at end of file