11import dayjs from "dayjs" ;
22import { useMemo } from "react" ;
3+ import { DAYS_IN_WEEK , MIN_COUNT , WEEKEND_DAYS } from "./constants" ;
34import type { CalendarDayCell , CalendarMatrixResult } from "./types" ;
45
5- interface UseCalendarMatrixParams {
6+ export interface UseCalendarMatrixParams {
67 month : string ;
78 data : Record < string , number > ;
89 weekDays : string [ ] ;
@@ -11,6 +12,39 @@ interface UseCalendarMatrixParams {
1112 selectedDate : string ;
1213}
1314
15+ const createCalendarDayCell = (
16+ current : dayjs . Dayjs ,
17+ monthKey : string ,
18+ data : Record < string , number > ,
19+ today : string ,
20+ selectedDate : string ,
21+ ) : CalendarDayCell => {
22+ const isoDate = current . format ( "YYYY-MM-DD" ) ;
23+ const isCurrentMonth = current . format ( "YYYY-MM" ) === monthKey ;
24+ const count = data [ isoDate ] ?? 0 ;
25+
26+ return {
27+ date : isoDate ,
28+ label : current . date ( ) ,
29+ count,
30+ isCurrentMonth,
31+ isToday : isoDate === today ,
32+ isSelected : isoDate === selectedDate ,
33+ isWeekend : WEEKEND_DAYS . includes ( current . day ( ) ) ,
34+ } ;
35+ } ;
36+
37+ const calculateCalendarBoundaries = ( monthStart : dayjs . Dayjs , weekStartDayOffset : number ) => {
38+ const monthEnd = monthStart . endOf ( "month" ) ;
39+ const startOffset = ( monthStart . day ( ) - weekStartDayOffset + DAYS_IN_WEEK ) % DAYS_IN_WEEK ;
40+ const endOffset = ( weekStartDayOffset + ( DAYS_IN_WEEK - 1 ) - monthEnd . day ( ) + DAYS_IN_WEEK ) % DAYS_IN_WEEK ;
41+ const calendarStart = monthStart . subtract ( startOffset , "day" ) ;
42+ const calendarEnd = monthEnd . add ( endOffset , "day" ) ;
43+ const dayCount = calendarEnd . diff ( calendarStart , "day" ) + 1 ;
44+
45+ return { calendarStart, dayCount } ;
46+ } ;
47+
1448export const useCalendarMatrix = ( {
1549 month,
1650 data,
@@ -21,51 +55,32 @@ export const useCalendarMatrix = ({
2155} : UseCalendarMatrixParams ) : CalendarMatrixResult => {
2256 return useMemo ( ( ) => {
2357 const monthStart = dayjs ( month ) . startOf ( "month" ) ;
24- const monthEnd = monthStart . endOf ( "month" ) ;
2558 const monthKey = monthStart . format ( "YYYY-MM" ) ;
2659
27- const orderedWeekDays = weekDays . slice ( weekStartDayOffset ) . concat ( weekDays . slice ( 0 , weekStartDayOffset ) ) ;
28-
29- const startOffset = ( monthStart . day ( ) - weekStartDayOffset + 7 ) % 7 ;
30- const endOffset = ( weekStartDayOffset + 6 - monthEnd . day ( ) + 7 ) % 7 ;
60+ const rotatedWeekDays = weekDays . slice ( weekStartDayOffset ) . concat ( weekDays . slice ( 0 , weekStartDayOffset ) ) ;
3161
32- const calendarStart = monthStart . subtract ( startOffset , "day" ) ;
33- const calendarEnd = monthEnd . add ( endOffset , "day" ) ;
34- const dayCount = calendarEnd . diff ( calendarStart , "day" ) + 1 ;
62+ const { calendarStart, dayCount } = calculateCalendarBoundaries ( monthStart , weekStartDayOffset ) ;
3563
3664 const weeks : CalendarMatrixResult [ "weeks" ] = [ ] ;
3765 let maxCount = 0 ;
3866
3967 for ( let index = 0 ; index < dayCount ; index += 1 ) {
4068 const current = calendarStart . add ( index , "day" ) ;
41- const isoDate = current . format ( "YYYY-MM-DD" ) ;
42- const weekIndex = Math . floor ( index / 7 ) ;
69+ const weekIndex = Math . floor ( index / DAYS_IN_WEEK ) ;
4370
4471 if ( ! weeks [ weekIndex ] ) {
4572 weeks [ weekIndex ] = { days : [ ] } ;
4673 }
4774
48- const isCurrentMonth = current . format ( "YYYY-MM" ) === monthKey ;
49- const count = data [ isoDate ] ?? 0 ;
50-
51- const dayCell : CalendarDayCell = {
52- date : isoDate ,
53- label : current . date ( ) ,
54- count,
55- isCurrentMonth,
56- isToday : isoDate === today ,
57- isSelected : isoDate === selectedDate ,
58- isWeekend : [ 0 , 6 ] . includes ( current . day ( ) ) ,
59- } ;
60-
75+ const dayCell = createCalendarDayCell ( current , monthKey , data , today , selectedDate ) ;
6176 weeks [ weekIndex ] . days . push ( dayCell ) ;
62- maxCount = Math . max ( maxCount , count ) ;
77+ maxCount = Math . max ( maxCount , dayCell . count ) ;
6378 }
6479
6580 return {
6681 weeks,
67- weekDays : orderedWeekDays ,
68- maxCount : Math . max ( maxCount , 1 ) ,
82+ weekDays : rotatedWeekDays ,
83+ maxCount : Math . max ( maxCount , MIN_COUNT ) ,
6984 } ;
7085 } , [ month , data , weekDays , weekStartDayOffset , today , selectedDate ] ) ;
7186} ;
0 commit comments