Skip to content

Commit 5e52f5d

Browse files
committed
feat: 캘린더 YYYY.MM 상단 날짜 표기 추가
1 parent 8ad5dbc commit 5e52f5d

File tree

3 files changed

+121
-121
lines changed

3 files changed

+121
-121
lines changed

src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ function App() {
2727
</label>
2828
</div>
2929
<div className="flex-1">
30-
<h1 className="text-sm min-w-40 p-2 text-center bg-base-200 rounded flex-end">개인 일정 캘린더</h1>
30+
<h1 className="flex-end min-w-40 rounded bg-base-200 p-2 text-center text-sm">개인 일정 캘린더</h1>
3131
</div>
3232
</div>
3333
</div>

src/components/common/Calendar.tsx

Lines changed: 116 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -4,134 +4,134 @@ import interactionPlugin from '@fullcalendar/interaction';
44
import { useRef, useState, useEffect } from 'react';
55

66
const events = [
7-
{ title: 'Meeting', start: new Date() },
8-
{ title: 'Meeting', start: '2024-05-08' },
9-
{ title: 'Meeting', start: '2024-05-08' },
10-
{ title: 'Meeting', start: '2024-05-08' },
7+
{ title: 'Meeting', start: new Date() },
8+
{ title: 'Meeting', start: '2024-05-08' },
9+
{ title: 'Meeting', start: '2024-05-08' },
10+
{ title: 'Meeting', start: '2024-05-08' },
1111
];
1212

1313
export function Calendar() {
14-
const [calendarHeight, setCalendarHeight] = useState<string | number>('auto');
15-
const calendarRef = useRef<FullCalendar | null>(null);
16-
const handlePrev = () => {
17-
const calendarApi = calendarRef?.current?.getApi();
18-
if (calendarApi) {
19-
calendarApi.prev();
20-
} else {
21-
console.error('Calendar API is not available.');
22-
}
23-
};
14+
const [calendarHeight, setCalendarHeight] = useState<string | number>('auto');
15+
const calendarRef = useRef<FullCalendar | null>(null);
16+
const handlePrev = () => {
17+
const calendarApi = calendarRef?.current?.getApi();
18+
if (calendarApi) {
19+
calendarApi.prev();
20+
} else {
21+
console.error('Calendar API is not available.');
22+
}
23+
};
2424

25-
const handleNext = () => {
26-
const calendarApi = calendarRef?.current?.getApi();
27-
if (calendarApi) {
28-
calendarApi.next();
29-
} else {
30-
console.error('Calendar API is not available.');
31-
}
32-
};
25+
const handleNext = () => {
26+
const calendarApi = calendarRef?.current?.getApi();
27+
if (calendarApi) {
28+
calendarApi.next();
29+
} else {
30+
console.error('Calendar API is not available.');
31+
}
32+
};
3333

34-
// eslint-disable-next-line react-hooks/exhaustive-deps
35-
const updateSize = () => {
36-
const isMobile = window.innerWidth < 768;
37-
setCalendarHeight(isMobile ? 500 : 'auto');
38-
updateTitle();
39-
};
34+
// eslint-disable-next-line react-hooks/exhaustive-deps
35+
const updateSize = () => {
36+
const isMobile = window.innerWidth < 768;
37+
setCalendarHeight(isMobile ? 500 : 'auto');
38+
updateTitle();
39+
};
40+
41+
const updateTitle = () => {
42+
const calendarApi = calendarRef?.current?.getApi();
43+
if (calendarApi) {
44+
const calendarView = calendarApi.view;
45+
46+
const date = new Date(calendarView.currentStart);
47+
const year = date.getFullYear();
48+
const month = (date.getMonth() + 1).toString().padStart(2, '0');
49+
const newTitle = `${year}.${month}`;
50+
51+
const titleElement = document.querySelector('.fc-toolbar-title');
52+
if (titleElement) {
53+
titleElement.textContent = newTitle;
54+
}
55+
}
56+
};
4057

41-
const updateTitle = () => {
42-
const calendarApi = calendarRef?.current?.getApi();
43-
if (calendarApi) {
44-
const calendarView = calendarApi.view;
45-
46-
const date = new Date(calendarView.currentStart);
47-
const year = date.getFullYear();
48-
const month = (date.getMonth() + 1).toString().padStart(2, '0');
49-
const newTitle = `${year}.${month}`;
50-
51-
const titleElement = document.querySelector(".fc-toolbar-title");
52-
if (titleElement) {
53-
titleElement.textContent = newTitle;
54-
}
55-
}
58+
useEffect(() => {
59+
const calendarApi = calendarRef?.current?.getApi();
60+
61+
if (calendarApi) {
62+
calendarApi.on('datesSet', updateTitle);
63+
}
64+
65+
updateTitle(); // 컴포넌트 마운트 시 제목 업데이트
66+
67+
/* 캘린더 - 반응형 사이즈 */
68+
window.addEventListener('resize', updateSize);
69+
updateSize(); // 컴포넌트 마운트 시 화면 크기에 따른 업데이트
70+
71+
return () => {
72+
window.removeEventListener('resize', updateSize);
73+
if (calendarApi) {
74+
calendarApi.off('datesSet', updateTitle);
75+
}
5676
};
57-
58-
useEffect(() => {
59-
const calendarApi = calendarRef?.current?.getApi();
60-
61-
if (calendarApi) {
62-
calendarApi.on('datesSet', updateTitle);
63-
}
64-
65-
updateTitle(); // 컴포넌트 마운트 시 제목 업데이트
66-
67-
/* 캘린더 - 반응형 사이즈 */
68-
window.addEventListener('resize', updateSize);
69-
updateSize(); // 컴포넌트 마운트 시 화면 크기에 따른 업데이트
70-
71-
return () => {
72-
window.removeEventListener('resize', updateSize);
73-
if (calendarApi) {
74-
calendarApi.off('datesSet', updateTitle);
75-
}
76-
}
77-
}, [updateSize]);
77+
}, [updateSize]);
7878

79-
return (
80-
<div>
81-
<FullCalendar
82-
ref={calendarRef}
83-
plugins={[dayGridPlugin, interactionPlugin]}
84-
initialView="dayGridMonth"
85-
events={events}
86-
dayMaxEvents={2} //Max개수까지보이고 나머지는 more
87-
navLinks={true} // 날짜/주 이름을 클릭하여 뷰를 변경할 수 있습니다.
88-
editable={true} // 이벤트를 수정할 수 있습니다.
89-
eventContent={renderEventContent}
90-
contentHeight={calendarHeight}
91-
titleFormat={{
92-
year: 'numeric',
93-
month: '2-digit',
94-
}}
95-
eventTimeFormat={{
96-
hour: '2-digit',
97-
minute: '2-digit',
98-
meridiem: false,
99-
}}
100-
dayHeaderFormat={{
101-
weekday: 'short',
102-
}}
103-
headerToolbar={{
104-
left: 'prevButton',
105-
center: 'title',
106-
right: 'nextButton',
107-
}}
108-
customButtons={{
109-
prevButton: {
110-
click: handlePrev,
111-
},
112-
nextButton: {
113-
click: handleNext,
114-
},
115-
}}
116-
/>
117-
</div>
118-
);
79+
return (
80+
<div>
81+
<FullCalendar
82+
ref={calendarRef}
83+
plugins={[dayGridPlugin, interactionPlugin]}
84+
initialView="dayGridMonth"
85+
events={events}
86+
dayMaxEvents={2} //Max개수까지보이고 나머지는 more
87+
navLinks={true} // 날짜/주 이름을 클릭하여 뷰를 변경할 수 있습니다.
88+
editable={true} // 이벤트를 수정할 수 있습니다.
89+
eventContent={renderEventContent}
90+
contentHeight={calendarHeight}
91+
titleFormat={{
92+
year: 'numeric',
93+
month: '2-digit',
94+
}}
95+
eventTimeFormat={{
96+
hour: '2-digit',
97+
minute: '2-digit',
98+
meridiem: false,
99+
}}
100+
dayHeaderFormat={{
101+
weekday: 'short',
102+
}}
103+
headerToolbar={{
104+
left: 'prevButton',
105+
center: 'title',
106+
right: 'nextButton',
107+
}}
108+
customButtons={{
109+
prevButton: {
110+
click: handlePrev,
111+
},
112+
nextButton: {
113+
click: handleNext,
114+
},
115+
}}
116+
/>
117+
</div>
118+
);
119119
}
120120

121121
interface EventInfo {
122-
timeText: string;
123-
event: {
124-
title: string;
125-
};
122+
timeText: string;
123+
event: {
124+
title: string;
125+
};
126126
}
127127

128128
function renderEventContent(eventInfo: EventInfo) {
129-
return (
130-
<>
131-
<div className="bg-secondary border-0 p-0.5 w-full text-white">
132-
<b className='border-0'>{eventInfo.timeText}</b>
133-
<i> {eventInfo.event.title}</i>
134-
</div>
135-
</>
136-
);
129+
return (
130+
<>
131+
<div className="w-full border-0 bg-secondary p-0.5 text-white">
132+
<b className="border-0">{eventInfo.timeText}</b>
133+
<i> {eventInfo.event.title}</i>
134+
</div>
135+
</>
136+
);
137137
}

tailwind.config.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ export default {
77
theme: {
88
extend: {},
99
fontFamily: {
10-
'sans': ['Pretendard-Regular', 'sans-serif'],
11-
'serif': ['Pretendard-Regular', 'sans-serif'],
12-
'mono': ['Pretendard-Regular', 'sans-serif']
13-
}
10+
sans: ['Pretendard-Regular', 'sans-serif'],
11+
serif: ['Pretendard-Regular', 'sans-serif'],
12+
mono: ['Pretendard-Regular', 'sans-serif'],
13+
},
1414
},
1515

1616
daisyui: {

0 commit comments

Comments
 (0)