+
+
+ {COLOR_OPTIONS.map((color) => (
+
+
+ {/* 버튼 */}
+
+
+ 취소
+
+
+ {editingCategory ? '수정' : '추가'}
+
+
+
+
+ )}
+
+ );
+});
+
+export default CategoryFormModal;
diff --git a/frontend-temp/src/components/pc/admin/schedule/index.js b/frontend-temp/src/components/pc/admin/schedule/index.js
index 3151963..c9f2176 100644
--- a/frontend-temp/src/components/pc/admin/schedule/index.js
+++ b/frontend-temp/src/components/pc/admin/schedule/index.js
@@ -5,3 +5,4 @@ export { default as LocationSearchDialog } from './LocationSearchDialog';
export { default as MemberSelector } from './MemberSelector';
export { default as ImageUploader } from './ImageUploader';
export { default as WordItem, POS_TAGS } from './WordItem';
+export { default as CategoryFormModal } from './CategoryFormModal';
diff --git a/frontend-temp/src/pages/pc/admin/schedules/ScheduleBots.jsx b/frontend-temp/src/pages/pc/admin/schedules/ScheduleBots.jsx
index 74670c3..9271797 100644
--- a/frontend-temp/src/pages/pc/admin/schedules/ScheduleBots.jsx
+++ b/frontend-temp/src/pages/pc/admin/schedules/ScheduleBots.jsx
@@ -2,20 +2,9 @@ import { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { motion, AnimatePresence } from 'framer-motion';
-import {
- Home,
- ChevronRight,
- Bot,
- Play,
- Square,
- Youtube,
- CheckCircle,
- XCircle,
- RefreshCw,
- Download,
-} from 'lucide-react';
-import { Toast, Tooltip } from '@/components/common';
-import { AdminLayout } from '@/components/pc/admin';
+import { Home, ChevronRight, Bot, CheckCircle, XCircle, RefreshCw } from 'lucide-react';
+import { Toast, Tooltip, AnimatedNumber } from '@/components/common';
+import { AdminLayout, BotCard } from '@/components/pc/admin';
import { useAdminAuth } from '@/hooks/pc/admin';
import { useToast } from '@/hooks/common';
import * as botsApi from '@/api/admin/bots';
@@ -38,95 +27,6 @@ const itemVariants = {
},
};
-// 슬롯머신 스타일 롤링 숫자 컴포넌트
-function AnimatedNumber({ value, className = '' }) {
- const chars = String(value).split('');
-
- return (
-
- {chars.map((char, i) => (
-
-
- {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map((n) => (
-
- {n}
-
- ))}
-
-
- ))}
-
- );
-}
-
-// X 아이콘 컴포넌트
-const XIcon = ({ size = 20, fill = 'currentColor' }) => (
-
-);
-
-// Meilisearch 아이콘 컴포넌트
-const MeilisearchIcon = ({ size = 20 }) => (
-
-);
-
function ScheduleBots() {
const queryClient = useQueryClient();
const { user, isAuthenticated } = useAdminAuth();
@@ -411,154 +311,23 @@ function ScheduleBots() {
) : (
- {bots.map((bot, index) => {
- const statusInfo = getStatusInfo(bot.status);
-
- return (
-
- isInitialLoad && index === bots.length - 1 && setIsInitialLoad(false)
- }
- className="relative bg-gradient-to-br from-gray-50 to-white rounded-xl border border-gray-200 overflow-hidden hover:shadow-md transition-all"
- >
- {/* 상단 헤더 */}
-
-
-
- {bot.type === 'x' ? (
-
- ) : bot.type === 'meilisearch' ? (
-
- ) : (
-
- )}
-
-
-
{bot.name}
-
- {bot.last_check_at
- ? `${formatTime(bot.last_check_at)}에 업데이트됨`
- : '아직 업데이트 없음'}
-
-
-
-
-
- {statusInfo.text}
-
-
-
- {/* 통계 정보 */}
-
- {bot.type === 'meilisearch' ? (
- <>
-
-
- {bot.schedules_added || 0}
-
-
동기화 수
-
-
-
- {bot.last_added_count
- ? `${(bot.last_added_count / 1000 || 0).toFixed(1)}초`
- : '-'}
-
-
소요 시간
-
- >
- ) : (
- <>
-
-
{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}
-
- )}
-
- {/* 액션 버튼 */}
-
-
-
handleSyncAllVideos(bot.id)}
- disabled={syncing === bot.id}
- className="flex-1 flex items-center justify-center gap-2 px-4 py-2.5 bg-blue-500 text-white rounded-lg font-medium transition-colors hover:bg-blue-600 disabled:opacity-50"
- >
- {syncing === bot.id ? (
- <>
-
- 동기화 중...
- >
- ) : (
- <>
-
- 전체 동기화
- >
- )}
-
-
toggleBot(bot.id, bot.status, bot.name)}
- className={`flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg font-medium transition-colors ${
- bot.status === 'running'
- ? 'bg-gray-100 text-gray-600 hover:bg-gray-200'
- : 'bg-green-500 text-white hover:bg-green-600'
- }`}
- >
- {bot.status === 'running' ? (
- <>
-
- 정지
- >
- ) : (
- <>
-
- 시작
- >
- )}
-
-
-
-
- );
- })}
+ {bots.map((bot, index) => (
+
+ isInitialLoad && index === bots.length - 1 && setIsInitialLoad(false)
+ }
+ formatTime={formatTime}
+ formatInterval={formatInterval}
+ />
+ ))}
)}