feat(festival-bot): 다이얼로그에 활성 월 선택 UI
축제 봇 추가/수정 다이얼로그에 1~12월 토글 그리드 + 전체 선택/해제 추가. 신규 봇은 전체 월(항상 실행) 기본. 전체 선택은 active_months null로 저장. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
8b36e9b5f7
commit
2af3af9345
1 changed files with 57 additions and 1 deletions
|
|
@ -17,6 +17,8 @@ const INTERVAL_OPTIONS = [
|
||||||
{ value: 1440, label: '24시간' },
|
{ value: 1440, label: '24시간' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const ALL_MONTHS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 커스텀 드롭다운 (Portal 사용)
|
* 커스텀 드롭다운 (Portal 사용)
|
||||||
*/
|
*/
|
||||||
|
|
@ -118,8 +120,17 @@ function FestivalBotDialog({ isOpen, onClose, botId = null, onSuccess }) {
|
||||||
const [name, setName] = useState('');
|
const [name, setName] = useState('');
|
||||||
const [searchUrl, setSearchUrl] = useState('');
|
const [searchUrl, setSearchUrl] = useState('');
|
||||||
const [interval, setInterval] = useState(360);
|
const [interval, setInterval] = useState(360);
|
||||||
|
const [activeMonths, setActiveMonths] = useState(ALL_MONTHS);
|
||||||
const [submitting, setSubmitting] = useState(false);
|
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({
|
const { data: bot, isLoading: botLoading } = useQuery({
|
||||||
queryKey: ['admin', 'festival-bot', botId],
|
queryKey: ['admin', 'festival-bot', botId],
|
||||||
|
|
@ -137,11 +148,18 @@ function FestivalBotDialog({ isOpen, onClose, botId = null, onSuccess }) {
|
||||||
setName(bot.name || '');
|
setName(bot.name || '');
|
||||||
setSearchUrl(bot.search_url || '');
|
setSearchUrl(bot.search_url || '');
|
||||||
setInterval(bot.cron_interval || 360);
|
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) {
|
} else if (!botId) {
|
||||||
// 추가 모드
|
// 추가 모드 (기본: 전체 월 = 항상 실행)
|
||||||
setName('');
|
setName('');
|
||||||
setSearchUrl('');
|
setSearchUrl('');
|
||||||
setInterval(360);
|
setInterval(360);
|
||||||
|
setActiveMonths([...ALL_MONTHS]);
|
||||||
}
|
}
|
||||||
}, [isOpen, bot, botId]);
|
}, [isOpen, bot, botId]);
|
||||||
|
|
||||||
|
|
@ -156,6 +174,8 @@ function FestivalBotDialog({ isOpen, onClose, botId = null, onSuccess }) {
|
||||||
name: name.trim(),
|
name: name.trim(),
|
||||||
search_url: searchUrl.trim(),
|
search_url: searchUrl.trim(),
|
||||||
cron_interval: interval,
|
cron_interval: interval,
|
||||||
|
// 전체 선택(또는 미선택)은 제한 없음(null)으로 저장
|
||||||
|
active_months: allMonthsSelected ? null : activeMonths,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isEdit) {
|
if (isEdit) {
|
||||||
|
|
@ -261,6 +281,42 @@ function FestivalBotDialog({ isOpen, onClose, botId = null, onSuccess }) {
|
||||||
placeholder="간격 선택"
|
placeholder="간격 선택"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* 활성 월 */}
|
||||||
|
<div>
|
||||||
|
<div className="flex items-center justify-between mb-1.5">
|
||||||
|
<label className="text-sm font-medium text-gray-700">활성 월</label>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={toggleAllMonths}
|
||||||
|
className="text-xs font-medium text-emerald-600 hover:text-emerald-700"
|
||||||
|
>
|
||||||
|
{allMonthsSelected ? '전체 해제' : '전체 선택'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-6 gap-1.5">
|
||||||
|
{ALL_MONTHS.map((m) => {
|
||||||
|
const on = activeMonths.includes(m);
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={m}
|
||||||
|
type="button"
|
||||||
|
onClick={() => toggleMonth(m)}
|
||||||
|
className={`py-2 rounded-lg text-sm font-medium transition-colors ${
|
||||||
|
on
|
||||||
|
? 'bg-emerald-500 text-white'
|
||||||
|
: 'bg-gray-100 text-gray-400 hover:bg-gray-200'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{m}월
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-gray-400 mt-1.5">
|
||||||
|
선택한 월에만 봇이 실행됩니다. 전체 선택 시 항상 실행됩니다.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue