From 09706e42e35611385e44cbd16cf7edf425299783 Mon Sep 17 00:00:00 2001 From: caadiq Date: Sun, 11 Jan 2026 16:08:22 +0900 Subject: [PATCH] =?UTF-8?q?feat(AdminSchedule):=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=EC=96=B4=20=EC=B6=94=EC=B2=9C=20=EB=93=9C=EB=A1=AD=EB=8B=A4?= =?UTF-8?q?=EC=9A=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 검색 버튼을 초록색 돋보기 아이콘으로 변경 - 애니메이션 scale+opacity로 개선 - 검색 모드에서 빈 일정 메시지 숨김 - 추천 검색어 드롭다운 (유튜브 스타일) - 방향키 선택, 외부 클릭 닫기 지원 - 검색 모드 진입 시 기존 카테고리 유지 --- frontend/src/pages/pc/admin/AdminSchedule.jsx | 189 ++++++++++++++---- 1 file changed, 150 insertions(+), 39 deletions(-) diff --git a/frontend/src/pages/pc/admin/AdminSchedule.jsx b/frontend/src/pages/pc/admin/AdminSchedule.jsx index c7f2c7d..4e1d555 100644 --- a/frontend/src/pages/pc/admin/AdminSchedule.jsx +++ b/frontend/src/pages/pc/admin/AdminSchedule.jsx @@ -152,6 +152,13 @@ function AdminSchedule() { const [user, setUser] = useState(null); const { toast, setToast } = useToast(); const scrollContainerRef = useRef(null); + const searchContainerRef = useRef(null); // 검색 컨테이너 (외부 클릭 감지용) + + // 검색 추천 관련 상태 + const [showSuggestions, setShowSuggestions] = useState(false); + const [selectedSuggestionIndex, setSelectedSuggestionIndex] = useState(-1); + const [originalSearchQuery, setOriginalSearchQuery] = useState(''); // 필터링용 원본 쿼리 + const SEARCH_LIMIT = 20; // 페이지당 20개 const ESTIMATED_ITEM_HEIGHT = 100; // 아이템 추정 높이 (동적 측정) @@ -402,6 +409,11 @@ function AdminSchedule() { if (categoryTooltipRef.current && !categoryTooltipRef.current.contains(event.target)) { setShowCategoryTooltip(false); } + // 검색 추천 드롭다운 외부 클릭 시 닫기 + if (searchContainerRef.current && !searchContainerRef.current.contains(event.target)) { + setShowSuggestions(false); + setSelectedSuggestionIndex(-1); + } }; if (showYearMonthPicker || showCategoryTooltip) { @@ -951,58 +963,149 @@ function AdminSchedule() { /* 검색 모드 */ - setSearchInput(e.target.value)} - onKeyDown={(e) => { - if (e.key === 'Enter') { - setSearchTerm(searchInput); - } else if (e.key === 'Escape') { - setIsSearchMode(false); - setSearchInput(''); - setSearchTerm(''); - setSearchResults([]); - } - }} - className="flex-1 bg-transparent focus:outline-none text-gray-700 placeholder-gray-400" - /> - + + {/* 검색 입력 컨테이너 (드롭다운 포함) */} +
+
+ { + setSearchInput(e.target.value); + setOriginalSearchQuery(e.target.value); + setShowSuggestions(true); + setSelectedSuggestionIndex(-1); + }} + onFocus={() => setShowSuggestions(true)} + onKeyDown={(e) => { + // 필터링은 원본 쿼리 기준으로 유지 + const dummySuggestions = ['성수기', '성수기 이채영', '이채영 먹방', 'NOW TOMORROW', '하얀 그리움', '콘서트', '월드투어'].filter(s => + s.toLowerCase().includes(originalSearchQuery.toLowerCase()) + ).slice(0, 7); + + if (e.key === 'ArrowDown') { + e.preventDefault(); + const newIndex = selectedSuggestionIndex < dummySuggestions.length - 1 + ? selectedSuggestionIndex + 1 + : 0; + setSelectedSuggestionIndex(newIndex); + if (dummySuggestions[newIndex]) { + setSearchInput(dummySuggestions[newIndex]); + } + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + const newIndex = selectedSuggestionIndex > 0 + ? selectedSuggestionIndex - 1 + : dummySuggestions.length - 1; + setSelectedSuggestionIndex(newIndex); + if (dummySuggestions[newIndex]) { + setSearchInput(dummySuggestions[newIndex]); + } + } else if (e.key === 'Enter') { + if (selectedSuggestionIndex >= 0 && dummySuggestions[selectedSuggestionIndex]) { + setSearchInput(dummySuggestions[selectedSuggestionIndex]); + setSearchTerm(dummySuggestions[selectedSuggestionIndex]); + } else if (searchInput.trim()) { + setSearchTerm(searchInput); + } + setShowSuggestions(false); + setSelectedSuggestionIndex(-1); + } else if (e.key === 'Escape') { + setIsSearchMode(false); + setSearchInput(''); + setOriginalSearchQuery(''); + setSearchTerm(''); + setShowSuggestions(false); + setSelectedSuggestionIndex(-1); + setSearchResults([]); + } + }} + className="flex-1 bg-transparent focus:outline-none text-gray-700 placeholder-gray-400" + /> + +
+ + {/* 검색어 추천 드롭다운 */} + {showSuggestions && originalSearchQuery.length > 0 && ( +
+ {(() => { + const dummySuggestions = ['성수기', '성수기 이채영', '이채영 먹방', 'NOW TOMORROW', '하얀 그리움', '콘서트', '월드투어'].filter(s => + s.toLowerCase().includes(originalSearchQuery.toLowerCase()) + ).slice(0, 7); + + if (dummySuggestions.length === 0) { + return ( +
+ 추천 검색어가 없습니다 +
+ ); + } + + return dummySuggestions.map((suggestion, index) => ( + + )); + })()} +
+ )} +
) : ( /* 일반 모드 */