From 217746af3e5c150fb5afd13e56024d0b27980166 Mon Sep 17 00:00:00 2001 From: caadiq Date: Tue, 6 Jan 2026 11:42:47 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B4=87=20=EA=B4=80=EB=A6=AC=20UI=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 카드 그리드 레이아웃으로 변경 - 통계 분리: 총 추가 / 마지막 추가 / 업데이트 간격 - DB에 last_added_count 컬럼 추가 - 업데이트 시간을 봇 이름 아래에 표시 - 마지막 추가된 개수 초록색 강조 --- backend/services/youtube-bot.js | 10 +- frontend/src/pages/pc/admin/AdminSchedule.jsx | 8 + .../src/pages/pc/admin/AdminScheduleBots.jsx | 171 +++++++++--------- .../src/pages/pc/admin/AdminScheduleForm.jsx | 9 +- 4 files changed, 110 insertions(+), 88 deletions(-) diff --git a/backend/services/youtube-bot.js b/backend/services/youtube-bot.js index 2b33fed..4615b52 100644 --- a/backend/services/youtube-bot.js +++ b/backend/services/youtube-bot.js @@ -433,14 +433,15 @@ export async function syncNewVideos(botId) { } } - // 봇 상태 업데이트 + // 봇 상태 업데이트 (전체 추가 수 + 마지막 추가 수) await pool.query( `UPDATE bots SET last_check_at = DATE_ADD(NOW(), INTERVAL 9 HOUR), schedules_added = schedules_added + ?, + last_added_count = ?, error_message = NULL WHERE id = ?`, - [addedCount, botId] + [addedCount, addedCount, botId] ); return { addedCount, total: videos.length }; @@ -536,14 +537,15 @@ export async function syncAllVideos(botId) { } } - // 봇 상태 업데이트 + // 봇 상태 업데이트 (전체 추가 수 + 마지막 추가 수) await pool.query( `UPDATE bots SET last_check_at = DATE_ADD(NOW(), INTERVAL 9 HOUR), schedules_added = schedules_added + ?, + last_added_count = ?, error_message = NULL WHERE id = ?`, - [addedCount, botId] + [addedCount, addedCount, botId] ); return { addedCount, total: videos.length }; diff --git a/frontend/src/pages/pc/admin/AdminSchedule.jsx b/frontend/src/pages/pc/admin/AdminSchedule.jsx index ba25425..6cbb564 100644 --- a/frontend/src/pages/pc/admin/AdminSchedule.jsx +++ b/frontend/src/pages/pc/admin/AdminSchedule.jsx @@ -163,7 +163,15 @@ function AdminSchedule() { // 카테고리 로드 fetchCategories(); + + // sessionStorage에서 토스트 메시지 확인 (일정 추가/수정 완료 시) + const savedToast = sessionStorage.getItem('scheduleToast'); + if (savedToast) { + setToast(JSON.parse(savedToast)); + sessionStorage.removeItem('scheduleToast'); + } }, [navigate]); + // 월이 변경될 때마다 일정 로드 useEffect(() => { diff --git a/frontend/src/pages/pc/admin/AdminScheduleBots.jsx b/frontend/src/pages/pc/admin/AdminScheduleBots.jsx index a686d42..45adaad 100644 --- a/frontend/src/pages/pc/admin/AdminScheduleBots.jsx +++ b/frontend/src/pages/pc/admin/AdminScheduleBots.jsx @@ -280,106 +280,113 @@ function AdminScheduleBots() {

위의 버튼을 클릭하여 봇을 추가하세요

) : ( -
+
{bots.map((bot, index) => { const statusInfo = getStatusInfo(bot.status); return ( -
- {/* 아이콘 */} -
- -
- - {/* 정보 */} -
-
+ {/* 상단 헤더 */} +
+
+
+ +
+

{bot.name}

- - - {statusInfo.text} - - - YouTube - +

+ {bot.last_check_at ? `${formatTime(bot.last_check_at)}에 업데이트됨` : '아직 업데이트 없음'} +

-

- 채널: {bot.channel_name || bot.channel_id} | {formatInterval(bot.check_interval)} 간격 -

- - {/* 메타 정보 */} -
- - - 마지막 체크: {formatTime(bot.last_check_at)} - - - - 추가된 일정: {bot.schedules_added}개 - -
- - {/* 오류 메시지 */} - {bot.status === 'error' && bot.error_message && ( -
- ⚠️ {bot.error_message} -
- )}
- - {/* 액션 버튼 */} -
- - + + + {statusInfo.text} + +
+ + {/* 통계 정보 */} +
+
+
{bot.schedules_added}
+
총 추가
+
+
+
0 ? 'text-green-500' : 'text-gray-400'}`}> + +{bot.last_added_count || 0} +
+
마지막
+
+
+
{formatInterval(bot.check_interval)}
+
업데이트 간격
+
+
+ + + + {/* 오류 메시지 */} + {bot.status === 'error' && bot.error_message && ( +
+ ⚠️ {bot.error_message} +
+ )} + + {/* 액션 버튼 */} +
+
+ +
+ ); })}
)} +
diff --git a/frontend/src/pages/pc/admin/AdminScheduleForm.jsx b/frontend/src/pages/pc/admin/AdminScheduleForm.jsx index 73bd67a..64749ac 100644 --- a/frontend/src/pages/pc/admin/AdminScheduleForm.jsx +++ b/frontend/src/pages/pc/admin/AdminScheduleForm.jsx @@ -1031,8 +1031,13 @@ function AdminScheduleForm() { throw new Error(error.error || (isEditMode ? '일정 수정에 실패했습니다.' : '일정 생성에 실패했습니다.')); } - setToast({ type: 'success', message: isEditMode ? '일정이 수정되었습니다.' : '일정이 추가되었습니다.' }); - setTimeout(() => navigate('/admin/schedule'), 1500); + // 성공 메시지를 sessionStorage에 저장하고 목록 페이지로 이동 + sessionStorage.setItem('scheduleToast', JSON.stringify({ + type: 'success', + message: isEditMode ? '일정이 수정되었습니다.' : '일정이 추가되었습니다.' + })); + navigate('/admin/schedule'); + } catch (error) { console.error('일정 저장 오류:', error); setToast({ type: 'error', message: error.message || '일정 저장 중 오류가 발생했습니다.' });