diff --git a/frontend/src/pages/mobile/public/Schedule.jsx b/frontend/src/pages/mobile/public/Schedule.jsx index 8411938..c5b26b3 100644 --- a/frontend/src/pages/mobile/public/Schedule.jsx +++ b/frontend/src/pages/mobile/public/Schedule.jsx @@ -27,6 +27,13 @@ function MobileSchedule() { const [calendarViewDate, setCalendarViewDate] = useState(() => new Date(selectedDate)); // 달력 뷰 날짜 const [calendarShowYearMonth, setCalendarShowYearMonth] = useState(false); // 달력 년월 선택 모드 const contentRef = useRef(null); // 스크롤 초기화용 + const searchContainerRef = useRef(null); // 검색 컨테이너 (외부 클릭 감지용) + const searchInputRef = useRef(null); // 검색 입력 필드 (키패드 닫기용) + + // 검색 추천 관련 상태 + const [showSuggestions, setShowSuggestions] = useState(false); + const [selectedSuggestionIndex, setSelectedSuggestionIndex] = useState(-1); + const [originalSearchQuery, setOriginalSearchQuery] = useState(''); // 필터링용 원본 쿼리 // 검색 모드 진입 함수 (history 상태 추가) const enterSearchMode = () => { @@ -38,7 +45,10 @@ function MobileSchedule() { const exitSearchMode = () => { setIsSearchMode(false); setSearchInput(''); + setOriginalSearchQuery(''); setSearchTerm(''); + setShowSuggestions(false); + setSelectedSuggestionIndex(-1); }; // 뒤로가기 버튼 처리 @@ -175,6 +185,26 @@ function MobileSchedule() { }; }, [showCalendar]); + // 검색 추천 드롭다운 외부 클릭 감지 + useEffect(() => { + const handleClickOutside = (event) => { + if (searchContainerRef.current && !searchContainerRef.current.contains(event.target)) { + setShowSuggestions(false); + setSelectedSuggestionIndex(-1); + } + }; + + if (showSuggestions) { + document.addEventListener('mousedown', handleClickOutside); + document.addEventListener('touchstart', handleClickOutside); + } + + return () => { + document.removeEventListener('mousedown', handleClickOutside); + document.removeEventListener('touchstart', handleClickOutside); + }; + }, [showSuggestions]); + // 카테고리 색상 const getCategoryColor = (categoryId) => { const category = categories.find(c => c.id === categoryId); @@ -257,27 +287,75 @@ function MobileSchedule() { {/* 툴바 (헤더 + 날짜 선택기) */}
{isSearchMode ? ( -
+
setSearchInput(e.target.value)} + onChange={(e) => { + setSearchInput(e.target.value); + setOriginalSearchQuery(e.target.value); + setShowSuggestions(true); + setSelectedSuggestionIndex(-1); + }} + onFocus={() => setShowSuggestions(true)} onKeyDown={(e) => { - if (e.key === 'Enter') { + // 필터링은 원본 쿼리 기준으로 유지 + const dummySuggestions = ['성수기', '성수기 이채영', '이채영 먹방', 'NOW TOMORROW', '하얀 그리움', '콘서트', '월드투어'].filter(s => + s.toLowerCase().includes(originalSearchQuery.toLowerCase()) + ).slice(0, 7); + + if (e.key === 'ArrowDown') { e.preventDefault(); - setSearchTerm(searchInput); + 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') { + e.preventDefault(); + if (selectedSuggestionIndex >= 0 && dummySuggestions[selectedSuggestionIndex]) { + setSearchInput(dummySuggestions[selectedSuggestionIndex]); + setSearchTerm(dummySuggestions[selectedSuggestionIndex]); + } else if (searchInput.trim()) { + setSearchTerm(searchInput); + } + setShowSuggestions(false); + setSelectedSuggestionIndex(-1); + // 키패드 닫기 + searchInputRef.current?.blur(); } }} className="flex-1 bg-transparent outline-none text-sm min-w-0 [&::-webkit-search-cancel-button]:hidden" - autoFocus + autoFocus={!searchTerm} /> {searchInput && ( - )} @@ -494,13 +572,48 @@ function MobileSchedule() { {/* 컨텐츠 영역 */}
-
+
{isSearchMode ? ( // 검색 모드 !searchTerm ? ( - // 검색어 입력 전 - 빈 상태 -
- 검색어를 입력하세요 + // 검색어 입력 전 - 추천 검색어 리스트 표시 (유튜브 스타일) +
+ {(() => { + const dummySuggestions = ['성수기', '성수기 이채영', '이채영 먹방', 'NOW TOMORROW', '하얀 그리움', '콘서트', '월드투어']; + + // 입력값이 있으면 필터링 + const filtered = originalSearchQuery.length > 0 + ? dummySuggestions.filter(s => s.toLowerCase().includes(originalSearchQuery.toLowerCase())) + : dummySuggestions; + + if (filtered.length === 0) { + return ( +
+ 추천 검색어가 없습니다 +
+ ); + } + + return filtered.map((suggestion, index) => ( + + )); + })()}
) : searchLoading ? (