@@ -13,14 +13,7 @@ import {
13
13
} from "@/lib/want-todo" ;
14
14
import {
15
15
addMonths ,
16
- eachDayOfInterval ,
17
- endOfMonth ,
18
- endOfWeek ,
19
16
format ,
20
- isSameDay ,
21
- isSameMonth ,
22
- startOfMonth ,
23
- startOfWeek ,
24
17
subMonths ,
25
18
} from "date-fns" ;
26
19
import { ja } from "date-fns/locale" ;
@@ -35,11 +28,11 @@ import { useRouter } from "next/navigation";
35
28
import { useEffect , useMemo , useRef , useState } from "react" ;
36
29
import { generateStickyNoteServer } from "./actions" ;
37
30
import { Event , Todo , StickyNote } from "@/components/types" ;
38
- import { priorityColors } from "@/components/priority-colors" ;
39
31
import { Navigation } from "@/components/navigation" ;
40
32
import { EditWantodoDialog } from "@/components/edit-wantodo-dialog" ;
41
33
import { CreateEventDialog } from "@/components/create-event-dialog" ;
42
34
import { StickyNoteItem } from "@/components/sticky-note-item" ;
35
+ import { CalendarRenderer } from "@/components/calendar-renderer" ;
43
36
44
37
export default function Home ( ) {
45
38
const [ todos ] = useState < Todo [ ] > ( [ ] ) ;
@@ -199,138 +192,6 @@ export default function Home() {
199
192
}
200
193
} ;
201
194
202
- const getDaysInMonth = ( date : Date ) => {
203
- const start = startOfWeek ( startOfMonth ( date ) , { weekStartsOn : 0 } ) ;
204
- const end = endOfWeek ( endOfMonth ( date ) , { weekStartsOn : 0 } ) ;
205
- return eachDayOfInterval ( { start, end } ) ;
206
- } ;
207
-
208
- const getTodoCountForDay = ( day : Date ) => {
209
- return todos . filter ( ( todo ) => isSameDay ( todo . date , day ) ) . length ;
210
- } ;
211
-
212
- const getEventCountForDay = ( day : Date ) => {
213
- return events . filter ( ( event ) => event . start && isSameDay ( event . start , day ) )
214
- . length ;
215
- } ;
216
-
217
- const getTaskIndicatorStyle = ( todoCount : number , eventCount : number ) => {
218
- const count = todoCount + eventCount ;
219
- if ( count === 0 ) return "" ;
220
- const baseColor = isDarkMode ? "bg-red-" : "bg-red-" ;
221
- const intensity = Math . min ( count * 100 , 900 ) ;
222
- const colorClass = `${ baseColor } ${ intensity } ` ;
223
- return `${ colorClass } ${ count >= 3 ? "animate-pulse" : "" } ` ;
224
- } ;
225
-
226
- const renderCalendar = ( ) => {
227
- const days = getDaysInMonth ( currentMonth ) ;
228
- const weeks = Math . ceil ( days . length / 7 ) ;
229
-
230
- return (
231
- < div className = "bg-white dark:bg-gray-800 rounded-lg shadow-md p-4" >
232
- < div className = "grid grid-cols-7 gap-1" >
233
- { [ "日" , "月" , "火" , "水" , "木" , "金" , "土" ] . map ( ( day ) => (
234
- < div
235
- key = { day }
236
- className = "text-center font-semibold text-gray-600 dark:text-gray-300 p-2"
237
- >
238
- { day }
239
- </ div >
240
- ) ) }
241
- </ div >
242
- { Array . from ( { length : weeks } ) . map ( ( _ , weekIndex ) => {
243
- const weekDays = days . slice ( weekIndex * 7 , ( weekIndex + 1 ) * 7 ) ;
244
- const maxEventsInWeek = Math . max (
245
- ...weekDays . map (
246
- ( day ) => getTodoCountForDay ( day ) + getEventCountForDay ( day ) ,
247
- ) ,
248
- ) ;
249
- const weekHeight =
250
- maxEventsInWeek > 2 ? Math . min ( maxEventsInWeek * 20 , 100 ) : "auto" ;
251
-
252
- return (
253
- < div
254
- key = { weekIndex }
255
- className = "grid grid-cols-7 gap-1"
256
- style = { { minHeight : "100px" , height : weekHeight } }
257
- >
258
- { weekDays . map ( ( day ) => {
259
- const todoCount = getTodoCountForDay ( day ) ;
260
- const eventCount = getEventCountForDay ( day ) ;
261
- const isSelected = isSameDay ( day , selectedDate ) ;
262
- const isCurrentMonth = isSameMonth ( day , currentMonth ) ;
263
- const dayItems = [
264
- ...todos . filter ( ( todo ) => isSameDay ( todo . date , day ) ) ,
265
- ...events . filter (
266
- ( event ) => event . start && isSameDay ( event . start , day ) ,
267
- ) ,
268
- ] ;
269
-
270
- return (
271
- < motion . div
272
- key = { day . toISOString ( ) }
273
- className = { `p-1 border rounded-md cursor-pointer transition-all duration-300 overflow-hidden ${ isSelected ? "border-blue-300 dark:border-blue-600" : "" } ${ ! isCurrentMonth
274
- ? "text-gray-400 dark:text-gray-600 bg-gray-100 dark:bg-gray-700"
275
- : ""
276
- } ${ getTaskIndicatorStyle ( todoCount , eventCount ) } hover:bg-gray-100 dark:hover:bg-gray-700`}
277
- onClick = { ( ) => handleDateSelect ( day ) }
278
- whileHover = { { scale : 1.05 } }
279
- whileTap = { { scale : 0.95 } }
280
- onDragOver = { ( e ) => {
281
- e . preventDefault ( ) ;
282
- e . currentTarget . classList . add (
283
- "bg-blue-100" ,
284
- "dark:bg-blue-800" ,
285
- ) ;
286
- } }
287
- onDragLeave = { ( e ) => {
288
- e . currentTarget . classList . remove (
289
- "bg-blue-100" ,
290
- "dark:bg-blue-800" ,
291
- ) ;
292
- } }
293
- onDrop = { ( e ) => {
294
- e . preventDefault ( ) ;
295
- e . currentTarget . classList . remove (
296
- "bg-blue-100" ,
297
- "dark:bg-blue-800" ,
298
- ) ;
299
- if ( draggedStickyNote ) {
300
- handleDateSelect ( day ) ;
301
- setIsEventModalOpen ( true ) ;
302
- deleteStickyNote ( draggedStickyNote . id ) ;
303
- }
304
- } }
305
- >
306
- < div className = "text-right text-sm" > { format ( day , "d" ) } </ div >
307
- { ( todoCount > 0 || eventCount > 0 ) && (
308
- < div className = "mt-1 space-y-1" >
309
- { dayItems . slice ( 0 , 2 ) . map ( ( item , index ) => (
310
- < div
311
- key = { index }
312
- className = { `text-xs p-1 rounded ${ "text" in item ? priorityColors [ item . priority ] : priorityColors [ item . priority ] } ` }
313
- >
314
- { "text" in item ? item . text : item . title }
315
- </ div >
316
- ) ) }
317
- { dayItems . length > 2 && (
318
- < div className = "text-xs text-center font-bold" >
319
- +{ dayItems . length - 2 } more
320
- </ div >
321
- ) }
322
- </ div >
323
- ) }
324
- </ motion . div >
325
- ) ;
326
- } ) }
327
- </ div >
328
- ) ;
329
- } ) }
330
- </ div >
331
- ) ;
332
- } ;
333
-
334
195
const handleDateSelect = ( date : Date ) => {
335
196
setSelectedDate ( date ) ;
336
197
setIsEventModalOpen ( true ) ;
@@ -377,7 +238,18 @@ export default function Home() {
377
238
< ChevronRight className = "h-4 w-4" />
378
239
</ Button >
379
240
</ div >
380
- { renderCalendar ( ) }
241
+ < CalendarRenderer
242
+ todos = { todos }
243
+ events = { events }
244
+ stickyNotes = { stickyNotes }
245
+ currentMonth = { currentMonth }
246
+ selectedDate = { selectedDate }
247
+ handleDateSelect = { handleDateSelect }
248
+ isDarkMode = { isDarkMode }
249
+ draggedStickyNote = { draggedStickyNote }
250
+ deleteStickyNote = { deleteStickyNote }
251
+ setIsEventModalOpen = { setIsEventModalOpen }
252
+ />
381
253
</ div >
382
254
383
255
< div className = "w-full lg:w-1/2 pl-2 bg-white dark:bg-gray-800 overflow-auto lg:block hidden" >
0 commit comments