@@ -3,23 +3,120 @@ import {
3
3
CalendarActions ,
4
4
CalendarBody ,
5
5
CalendarContainer ,
6
+ CalendarDay ,
6
7
CalendarHeader ,
7
8
CalendarTitle ,
8
9
} from './styles'
10
+
9
11
import { getWeekDays } from '@/utils/get-week-days'
12
+ import { useMemo , useState } from 'react'
13
+ import dayjs from 'dayjs'
14
+
15
+ interface CalendarWeek {
16
+ week : number
17
+ days : Array < {
18
+ date : dayjs . Dayjs
19
+ disabled : boolean
20
+ } >
21
+ }
22
+
23
+ type CalendarWeeks = CalendarWeek [ ]
24
+
25
+ interface CalendarProps {
26
+ selectedDate : Date | null
27
+ onDateSelected : ( date : Date ) => void
28
+ }
29
+
30
+ export function Calendar ( { selectedDate, onDateSelected } : CalendarProps ) {
31
+ const [ currentDate , setCurrentDate ] = useState ( ( ) => {
32
+ return dayjs ( ) . set ( 'date' , 1 )
33
+ } )
34
+
35
+ function handlePreviousMonth ( ) {
36
+ const previousMonthDate = currentDate . subtract ( 1 , 'month' )
37
+ setCurrentDate ( previousMonthDate )
38
+ }
39
+
40
+ function handleNextMonth ( ) {
41
+ const nextMonthDate = currentDate . add ( 1 , 'month' )
42
+ setCurrentDate ( nextMonthDate )
43
+ }
10
44
11
- export function Calendar ( ) {
12
45
const shortWeekDays = getWeekDays ( { short : true } )
13
46
47
+ const currentMonth = currentDate . format ( 'MMMM' )
48
+ const currentYeah = currentDate . format ( 'YYYY' )
49
+
50
+ const calendarWeeks = useMemo ( ( ) => {
51
+ const daysInMonthArray = Array . from ( {
52
+ length : currentDate . daysInMonth ( ) ,
53
+ } ) . map ( ( _ , i ) => {
54
+ return currentDate . set ( 'date' , i + 1 )
55
+ } )
56
+
57
+ const firstWeekDay = currentDate . get ( 'day' )
58
+
59
+ const previousMonthFillArray = Array . from ( {
60
+ length : firstWeekDay ,
61
+ } )
62
+ . map ( ( _ , i ) => {
63
+ return currentDate . subtract ( i + 1 , 'day' )
64
+ } )
65
+ . reverse ( )
66
+
67
+ const lastDayInCurrentMonth = currentDate . set (
68
+ 'date' ,
69
+ currentDate . daysInMonth ( ) ,
70
+ )
71
+
72
+ const lastWeekDay = lastDayInCurrentMonth . get ( 'day' )
73
+
74
+ const nextMonthFillArray = Array . from ( {
75
+ length : 7 - ( lastWeekDay + 1 ) ,
76
+ } ) . map ( ( _ , i ) => {
77
+ return lastDayInCurrentMonth . add ( i + 1 , 'day' )
78
+ } )
79
+
80
+ const calendarDays = [
81
+ ...previousMonthFillArray . map ( ( date ) => {
82
+ return { date, disabled : true }
83
+ } ) ,
84
+ ...daysInMonthArray . map ( ( date ) => {
85
+ return { date, disabled : date . endOf ( 'day' ) . isBefore ( new Date ( ) ) }
86
+ } ) ,
87
+ ...nextMonthFillArray . map ( ( date ) => {
88
+ return { date, disabled : true }
89
+ } ) ,
90
+ ]
91
+
92
+ const calendarWeeks = calendarDays . reduce < CalendarWeeks > (
93
+ ( weeks , _ , i , original ) => {
94
+ const isNewWeek = i % 7 === 0
95
+ if ( isNewWeek ) {
96
+ weeks . push ( {
97
+ week : i / 7 + 1 ,
98
+ days : original . slice ( i , i + 7 ) ,
99
+ } )
100
+ }
101
+ return weeks
102
+ } ,
103
+ [ ] ,
104
+ )
105
+
106
+ return calendarWeeks
107
+ } , [ currentDate ] )
108
+
14
109
return (
15
110
< CalendarContainer >
16
111
< CalendarHeader >
17
- < CalendarTitle > Maio 2023</ CalendarTitle >
112
+ < CalendarTitle >
113
+ { currentMonth } < span > { currentYeah } </ span >
114
+ </ CalendarTitle >
18
115
< CalendarActions >
19
- < button >
116
+ < button onClick = { handlePreviousMonth } title = "Previous month" >
20
117
< CaretLeft />
21
118
</ button >
22
- < button >
119
+ < button onClick = { handleNextMonth } title = "Next month" >
23
120
< CaretRight />
24
121
</ button >
25
122
</ CalendarActions >
@@ -32,7 +129,26 @@ export function Calendar() {
32
129
) ) }
33
130
</ tr >
34
131
</ thead >
35
- < tbody > </ tbody >
132
+ < tbody >
133
+ { calendarWeeks . map ( ( { week, days } ) => {
134
+ return (
135
+ < tr key = { week } >
136
+ { days . map ( ( { date, disabled } ) => {
137
+ return (
138
+ < td key = { date . toString ( ) } >
139
+ < CalendarDay
140
+ onClick = { ( ) => onDateSelected ( date . toDate ( ) ) }
141
+ disabled = { disabled }
142
+ >
143
+ { date . get ( 'date' ) }
144
+ </ CalendarDay >
145
+ </ td >
146
+ )
147
+ } ) }
148
+ </ tr >
149
+ )
150
+ } ) }
151
+ </ tbody >
36
152
</ CalendarBody >
37
153
</ CalendarContainer >
38
154
)
0 commit comments