From 2af3af9345b54767f8de45c661fb1c3dfcfe9ef4 Mon Sep 17 00:00:00 2001 From: caadiq Date: Sat, 6 Jun 2026 22:58:13 +0900 Subject: [PATCH] =?UTF-8?q?feat(festival-bot):=20=EB=8B=A4=EC=9D=B4?= =?UTF-8?q?=EC=96=BC=EB=A1=9C=EA=B7=B8=EC=97=90=20=ED=99=9C=EC=84=B1=20?= =?UTF-8?q?=EC=9B=94=20=EC=84=A0=ED=83=9D=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 축제 봇 추가/수정 다이얼로그에 1~12월 토글 그리드 + 전체 선택/해제 추가. 신규 봇은 전체 월(항상 실행) 기본. 전체 선택은 active_months null로 저장. Co-Authored-By: Claude Opus 4.7 --- .../pc/admin/bot/FestivalBotDialog.jsx | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/pc/admin/bot/FestivalBotDialog.jsx b/frontend/src/components/pc/admin/bot/FestivalBotDialog.jsx index b524d11..b8fa526 100644 --- a/frontend/src/components/pc/admin/bot/FestivalBotDialog.jsx +++ b/frontend/src/components/pc/admin/bot/FestivalBotDialog.jsx @@ -17,6 +17,8 @@ const INTERVAL_OPTIONS = [ { value: 1440, label: '24시간' }, ]; +const ALL_MONTHS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + /** * 커스텀 드롭다운 (Portal 사용) */ @@ -118,8 +120,17 @@ function FestivalBotDialog({ isOpen, onClose, botId = null, onSuccess }) { const [name, setName] = useState(''); const [searchUrl, setSearchUrl] = useState(''); const [interval, setInterval] = useState(360); + const [activeMonths, setActiveMonths] = useState(ALL_MONTHS); const [submitting, setSubmitting] = useState(false); + const allMonthsSelected = activeMonths.length === ALL_MONTHS.length; + const toggleMonth = (m) => + setActiveMonths((prev) => + prev.includes(m) ? prev.filter((x) => x !== m) : [...prev, m].sort((a, b) => a - b) + ); + const toggleAllMonths = () => + setActiveMonths(allMonthsSelected ? [] : [...ALL_MONTHS]); + // 축제 봇 상세 조회 (수정 모드) const { data: bot, isLoading: botLoading } = useQuery({ queryKey: ['admin', 'festival-bot', botId], @@ -137,11 +148,18 @@ function FestivalBotDialog({ isOpen, onClose, botId = null, onSuccess }) { setName(bot.name || ''); setSearchUrl(bot.search_url || ''); setInterval(bot.cron_interval || 360); + // active_months: null(전체) → 전체 선택, 배열이면 그대로 + setActiveMonths( + Array.isArray(bot.active_months) && bot.active_months.length > 0 + ? bot.active_months + : [...ALL_MONTHS] + ); } else if (!botId) { - // 추가 모드 + // 추가 모드 (기본: 전체 월 = 항상 실행) setName(''); setSearchUrl(''); setInterval(360); + setActiveMonths([...ALL_MONTHS]); } }, [isOpen, bot, botId]); @@ -156,6 +174,8 @@ function FestivalBotDialog({ isOpen, onClose, botId = null, onSuccess }) { name: name.trim(), search_url: searchUrl.trim(), cron_interval: interval, + // 전체 선택(또는 미선택)은 제한 없음(null)으로 저장 + active_months: allMonthsSelected ? null : activeMonths, }; if (isEdit) { @@ -261,6 +281,42 @@ function FestivalBotDialog({ isOpen, onClose, botId = null, onSuccess }) { placeholder="간격 선택" /> + + {/* 활성 월 */} +
+
+ + +
+
+ {ALL_MONTHS.map((m) => { + const on = activeMonths.includes(m); + return ( + + ); + })} +
+

+ 선택한 월에만 봇이 실행됩니다. 전체 선택 시 항상 실행됩니다. +

+
)}