Skip to content

Commit c15fc2b

Browse files
authored
Merge pull request #195 from prgrms-aibe-devcourse/dev
dev to main
2 parents e5b6801 + 2b11a6d commit c15fc2b

8 files changed

Lines changed: 280 additions & 42 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
| 구분 | 기술 |
5050
| :--- | :--- |
5151
| **Core** | ![React](https://img.shields.io/badge/React-18-61DAFB?style=for-the-badge&logo=react&logoColor=black) ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white) ![Vite](https://img.shields.io/badge/Vite-646CFF?style=for-the-badge&logo=vite&logoColor=white) |
52-
| **State & Data** | ![Zustand](https://img.shields.io/badge/Zustand-7E5340?style=for-the-badge&logo=zustand&logoColor=white) ![Axios](https://img.shields.io/badge/Axios-5A29E4?style=for-the-badge&logo=axios&logoColor=white) ![React Hook Form](https://img.shields.io/badge/React%20Hook%20Form-EC5990?style=for-the-badge&logo=reacthookform&logoColor=white) |
52+
| **State & Data** | ![Zustand](https://img.shields.io/badge/Zustand-7E5340?style=for-the-badge&logo=zustand&logoColor=white) ![Axios](https://img.shields.io/badge/Axios-5A29E4?style=for-the-badge&logo=axios&logoColor=white) |
5353
| **UI & Routing** | ![Tailwind CSS](https://img.shields.io/badge/Tailwind%20CSS-06B6D4?style=for-the-badge&logo=tailwindcss&logoColor=white) ![Framer Motion](https://img.shields.io/badge/Framer%20Motion-0055FF?style=for-the-badge&logo=framer&logoColor=white) ![React Router](https://img.shields.io/badge/React%20Router-CA4245?style=for-the-badge&logo=reactrouter&logoColor=white) |
5454
| **배포** | ![Vercel](https://img.shields.io/badge/Vercel-000000?style=for-the-badge&logo=vercel&logoColor=white) |
5555

check-backend.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// 백엔드 서버 상태 체크 스크립트
2+
const https = require('https');
3+
const http = require('http');
4+
5+
const checkEndpoint = (url) => {
6+
return new Promise((resolve, reject) => {
7+
const protocol = url.startsWith('https:') ? https : http;
8+
const req = protocol.get(url, (res) => {
9+
console.log(`${url}: ${res.statusCode}`);
10+
resolve(res.statusCode);
11+
});
12+
13+
req.on('error', (err) => {
14+
console.error(`${url}: ERROR - ${err.message}`);
15+
reject(err);
16+
});
17+
18+
req.setTimeout(5000, () => {
19+
req.destroy();
20+
reject(new Error('Timeout'));
21+
});
22+
});
23+
};
24+
25+
async function checkBackend() {
26+
const endpoints = [
27+
'http://localhost:8080',
28+
'http://localhost:8080/oauth2/authorization/google',
29+
'https://api.woori-zip.lastdance.store',
30+
'https://api.woori-zip.lastdance.store/oauth2/authorization/google'
31+
];
32+
33+
for (const endpoint of endpoints) {
34+
try {
35+
await checkEndpoint(endpoint);
36+
} catch (error) {
37+
console.error(`Failed to check ${endpoint}`);
38+
}
39+
}
40+
}
41+
42+
checkBackend();

src/components/calendar/EventModal.tsx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ const EventModal: React.FC<EventModalProps> = ({
119119
return;
120120
}
121121

122+
// 반복일정 선택 시 종료일 필수 검증
123+
if (formData.repeat && formData.repeat !== 'none' && !formData.repeatEndDate) {
124+
toast.error('반복일정을 선택했을 때는 반복 종료 날짜를 꼭 선택해야 합니다.');
125+
return;
126+
}
127+
122128
// 반복 종료 날짜가 시작 날짜보다 이전인지 검증
123129
if (formData.repeatEndDate && formData.date && formData.repeatEndDate < formData.date) {
124130
toast.error('반복 종료 날짜는 시작 날짜보다 이후여야 합니다.');
@@ -407,7 +413,22 @@ const EventModal: React.FC<EventModalProps> = ({
407413
</label>
408414
<select
409415
value={formData.repeat}
410-
onChange={(e) => setFormData(prev => ({ ...prev, repeat: e.target.value as Event['repeat'] }))}
416+
onChange={(e) => {
417+
const repeatValue = e.target.value as Event['repeat'];
418+
setFormData(prev => ({
419+
...prev,
420+
repeat: repeatValue,
421+
// 반복을 'none'으로 변경하면 종료일 초기화
422+
repeatEndDate: repeatValue === 'none' ? undefined : prev.repeatEndDate
423+
}));
424+
425+
// 반복일정을 선택한 경우 안내 메시지
426+
if (repeatValue !== 'none') {
427+
setTimeout(() => {
428+
toast.success('반복일정을 선택했습니다. 반복 종료 날짜를 꼭 설정해주세요.');
429+
}, 100);
430+
}
431+
}}
411432
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:outline-none focus:ring-accent-500 focus:border-transparent"
412433
disabled={isSubmitting}
413434
>
@@ -423,7 +444,7 @@ const EventModal: React.FC<EventModalProps> = ({
423444
{formData.repeat && formData.repeat !== 'none' && (
424445
<div>
425446
<label className="block text-sm font-medium text-gray-700 mb-2">
426-
반복 종료 날짜 (선택사항)
447+
반복 종료 날짜 * <span className="text-xs text-red-500">(필수)</span>
427448
</label>
428449
<input
429450
type="date"
@@ -432,9 +453,13 @@ const EventModal: React.FC<EventModalProps> = ({
432453
...prev,
433454
repeatEndDate: e.target.value ? new Date(e.target.value) : undefined
434455
}))}
435-
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:outline-none focus:ring-accent-500 focus:border-transparent"
456+
className="w-full px-3 py-2 border-2 border-red-300 rounded-lg focus:ring-2 focus:outline-none focus:ring-red-500 focus:border-red-500 bg-red-50"
436457
disabled={isSubmitting}
458+
required
437459
/>
460+
<p className="text-xs text-gray-500 mt-1">
461+
반복일정을 선택했을 때는 반드시 종료 날짜를 설정해야 합니다.
462+
</p>
438463
</div>
439464
)}
440465

src/components/expenses/ExpenseModal.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ const ExpenseModal: React.FC<ExpenseModalProps> = ({expense, onClose}) => {
184184

185185
onClose();
186186
toast.success(expense ? '지출이 수정되었습니다' : '지출이 추가되었습니다');
187+
window.dispatchEvent(new CustomEvent('refreshMonthlyTrend'));
187188
} catch (error) {
188189
console.error('지출 처리 실패: ', error);
189190
} finally {

src/components/expenses/ExpensesPage.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,19 @@ const ExpensesPage: React.FC = () => {
432432
}
433433
}, [categoryFilter, searchTerm]); // 의존성에 필터와 검색어 추가
434434

435+
// 월별 추이 그래프 새로고침 이벤트 리스너
436+
useEffect(() => {
437+
const handleRefresh = () => {
438+
loadMonthlyTrendData();
439+
};
440+
441+
window.addEventListener('refreshMonthlyTrend', handleRefresh);
442+
443+
return () => {
444+
window.removeEventListener('refreshMonthlyTrend', handleRefresh);
445+
};
446+
}, [loadMonthlyTrendData]);
447+
435448
const categoryData = [
436449
{ category: "FOOD", label: "식비", color: "#FF6B6B" },
437450
{ category: "UTILITIES", label: "공과금", color: "#4ECDC4" },

0 commit comments

Comments
 (0)