1
1
import FullCalendar from '@fullcalendar/react' ;
2
+ import { EventClickArg } from '@fullcalendar/core' ;
2
3
import dayGridPlugin from '@fullcalendar/daygrid' ;
3
4
import interactionPlugin from '@fullcalendar/interaction' ;
4
5
import { useRef , useState , useEffect } from 'react' ;
5
6
import { useEventState } from '@/stores/myEventsStore' ;
6
7
import { getPersonalSchedule } from '@/apis/personalScheduleApi' ;
7
8
8
- const Calendar : React . FC = ( ) => {
9
+
10
+ type Event = {
11
+ title : string ;
12
+ start : Date | string ;
13
+ } ;
14
+ interface EventCardsProps {
15
+ events : Event [ ] ;
16
+ date : Date | string | null ;
17
+ }
18
+
19
+ const events = [
20
+ { title : 'Meeting' , start : new Date ( ) } ,
21
+ { title : 'Meeting' , start : '2024-05-08' } ,
22
+ { title : 'Meeting' , start : '2024-05-08' } ,
23
+ { title : 'Meeting' , start : '2024-05-08' } ,
24
+ ] ;
25
+
26
+ export function Calendar ( ) {
27
+
9
28
const [ calendarHeight , setCalendarHeight ] = useState < string | number > ( 'auto' ) ;
10
29
const calendarRef = useRef < FullCalendar | null > ( null ) ;
30
+ const [ selectedEvents , setSelectedEvents ] = useState < Event [ ] > ( [ ] ) ;
31
+ const [ selectedDate , setSelectedDate ] = useState < Date | null > ( null ) ;
32
+
33
+ const handleDateClick = ( clickInfo : EventClickArg ) => {
34
+ if ( clickInfo . event . start ) {
35
+ const clickStartDate = new Date ( clickInfo . event . start ) ;
36
+ setSelectedDate ( clickStartDate ) ;
37
+
38
+ const clickedStartDate = new Date ( clickInfo . event . start ) . toDateString ( ) ;
39
+ setSelectedEvents ( events . filter ( ( event ) => new Date ( event . start ) . toDateString ( ) === clickedStartDate ) ) ;
40
+ } else {
41
+ console . log ( 'not available' ) ;
42
+ }
43
+ } ;
44
+
11
45
const handlePrev = ( ) => {
12
46
const calendarApi = calendarRef ?. current ?. getApi ( ) ;
13
47
if ( calendarApi ) {
14
48
calendarApi . prev ( ) ;
49
+ setSelectedDate ( null ) ;
15
50
} else {
16
51
console . error ( 'Calendar API is not available.' ) ;
17
52
}
@@ -21,6 +56,7 @@ const Calendar: React.FC = () => {
21
56
const calendarApi = calendarRef ?. current ?. getApi ( ) ;
22
57
if ( calendarApi ) {
23
58
calendarApi . next ( ) ;
59
+ setSelectedDate ( null ) ;
24
60
} else {
25
61
console . error ( 'Calendar API is not available.' ) ;
26
62
}
@@ -80,42 +116,42 @@ const Calendar: React.FC = () => {
80
116
81
117
return (
82
118
< div >
83
- < FullCalendar
84
- ref = { calendarRef }
85
- plugins = { [ dayGridPlugin , interactionPlugin ] }
86
- initialView = "dayGridMonth"
87
- events = { events }
88
- dayMaxEvents = { 2 } //Max๊ฐ์๊น์ง๋ณด์ด๊ณ ๋๋จธ์ง๋ more
89
- navLinks = { true } // ๋ ์ง/์ฃผ ์ด๋ฆ์ ํด๋ฆญํ์ฌ ๋ทฐ๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
90
- editable = { true } // ์ด๋ฒคํธ๋ฅผ ์์ ํ ์ ์์ต๋๋ค.
91
- eventContent = { renderEventContent }
92
- contentHeight = { calendarHeight }
93
- titleFormat = { {
94
- year : 'numeric' ,
95
- month : '2-digit' ,
96
- } }
97
- eventTimeFormat = { {
98
- hour : '2-digit' ,
99
- minute : '2-digit' ,
100
- meridiem : false ,
101
- } }
102
- dayHeaderFormat = { {
103
- weekday : 'short' ,
104
- } }
105
- headerToolbar = { {
106
- left : 'prevButton' ,
107
- center : 'title' ,
108
- right : 'nextButton ' ,
109
- } }
110
- customButtons = { {
111
- prevButton : {
112
- click : handlePrev ,
113
- } ,
114
- nextButton : {
115
- click : handleNext ,
116
- } ,
117
- } }
118
- / >
119
+ < div className = "rounded bg-white p-6 px-4 sm:px-0" >
120
+ < FullCalendar
121
+ ref = { calendarRef }
122
+ plugins = { [ dayGridPlugin , interactionPlugin ] }
123
+ initialView = "dayGridMonth"
124
+ events = { events }
125
+ eventClick = { handleDateClick }
126
+ dayMaxEvents = { 2 } //Max๊ฐ์๊น์ง๋ณด์ด๊ณ ๋๋จธ์ง๋ more
127
+ //navLinks={true} // ๋ ์ง/์ฃผ ์ด๋ฆ์ ํด๋ฆญํ์ฌ ๋ทฐ๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
128
+ editable = { true } // ์ด๋ฒคํธ๋ฅผ ์์ ํ ์ ์์ต๋๋ค.
129
+ eventContent = { renderEventContent }
130
+ contentHeight = { calendarHeight }
131
+ titleFormat = { {
132
+ year : 'numeric' ,
133
+ month : '2-digit' ,
134
+ } }
135
+ eventTimeFormat = { {
136
+ hour : '2-digit' ,
137
+ minute : '2-digit' ,
138
+ meridiem : false ,
139
+ } }
140
+ dayHeaderFormat = { {
141
+ weekday : 'short' ,
142
+ } }
143
+ headerToolbar = { {
144
+ left : 'prevButton ' ,
145
+ center : 'title' ,
146
+ right : 'nextButton' ,
147
+ } }
148
+ customButtons = { {
149
+ prevButton : { click : handlePrev } ,
150
+ nextButton : { click : handleNext } ,
151
+ } }
152
+ />
153
+ </ div >
154
+ < div className = "mt-10" > { selectedDate && < EventCards events = { selectedEvents } date = { selectedDate } /> } </ div >
119
155
</ div >
120
156
) ;
121
157
} ;
@@ -138,4 +174,52 @@ function renderEventContent(eventInfo: EventInfo) {
138
174
) ;
139
175
}
140
176
141
- export default Calendar ;
177
+
178
+ function EventCards ( { events, date } : EventCardsProps ) {
179
+ const [ menuOpen , setMenuOpen ] = useState ( - 1 ) ;
180
+
181
+ if ( ! date ) {
182
+ return < div > No date provided</ div > ; // date๊ฐ null์ธ ๊ฒฝ์ฐ ์ฒ๋ฆฌ
183
+ }
184
+
185
+ const formattedDate = new Date ( date )
186
+ . toLocaleDateString ( 'ko-KR' , {
187
+ year : 'numeric' ,
188
+ month : '2-digit' ,
189
+ day : '2-digit' ,
190
+ } )
191
+ . replace ( / \. / g, '.' )
192
+ . slice ( 0 , - 1 ) ;
193
+
194
+ return (
195
+ < div >
196
+ < h2 className = "ml-2" > { formattedDate } </ h2 >
197
+ < div className = "flex gap-5 overflow-x-auto" >
198
+ { events . map ( ( event , index ) => (
199
+ < div key = { index } className = "relative min-h-[150px] min-w-[240px] bg-white p-4 text-black" >
200
+ < h3 > { event . title } </ h3 >
201
+ < p className = "mt-1 text-xs" > { new Date ( event . start ) . toLocaleTimeString ( ) } </ p >
202
+ { /* ๋ฉ๋ด ๋ฒํผ */ }
203
+ < div
204
+ className = "absolute right-2 top-2 flex cursor-pointer flex-col items-center justify-center"
205
+ onClick = { ( ) => setMenuOpen ( menuOpen === index ? - 1 : index ) }
206
+ >
207
+ < div className = "mb-1 h-1 w-1 rounded-full bg-[#429400]" > </ div >
208
+ < div className = "mb-1 h-1 w-1 rounded-full bg-[#429400]" > </ div >
209
+ < div className = "h-1 w-1 rounded-full bg-[#429400]" > </ div >
210
+ </ div >
211
+ { menuOpen === index && (
212
+ < div className = "absolute right-0 top-10 z-10 rounded-lg bg-white shadow-md" >
213
+ < ul >
214
+ < li className = "cursor-pointer p-2 hover:bg-gray-100" > ํธ์ง</ li >
215
+ < li className = "cursor-pointer p-2 hover:bg-gray-100" > ์ญ์ </ li >
216
+ </ ul >
217
+ </ div >
218
+ ) }
219
+ </ div >
220
+ ) ) }
221
+ </ div >
222
+ </ div >
223
+ ) ;
224
+ }
225
+
0 commit comments