Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/components/group/GroupCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const Card = styled.div<{ cardType: 'main' | 'search' | 'modal'; isFirstCard?: b
gap: 12px;
padding: 12px;
min-width: 232px;
cursor: pointer;
`;

const CoverWrapper = styled.div`
Expand Down
1 change: 1 addition & 0 deletions src/components/group/MyGroupModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ const ErrorMessage = styled.div`
`;

const EmptyState = styled.div`
grid-column: 1 / -1; /* 그리드 2열일 때도 전체 너비 차지 */
flex: 1;
min-height: 78vh;
display: flex;
Expand Down
9 changes: 8 additions & 1 deletion src/components/search/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import styled from '@emotion/styled';
import searchIcon from '../../assets/searchBar/search.svg';
import deleteIcon from '../../assets/searchBar/delete.svg';
import { IconButton } from '../common/IconButton';
import { useState } from 'react';
import type React from 'react';

interface SearchBarProps {
placeholder?: string;
Expand All @@ -20,14 +22,19 @@ const SearchBar = ({
onSearch,
isSearched,
}: SearchBarProps) => {
const [isComposing, setIsComposing] = useState(false);
return (
<SearchBarWrapper onClick={onClick}>
<Input
placeholder={placeholder}
value={value}
onChange={e => onChange?.(e.target.value)}
onKeyDown={e => {
onCompositionStart={() => setIsComposing(true)}
onCompositionEnd={() => setIsComposing(false)}
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
const composing = e.nativeEvent.isComposing || isComposing;
if (composing) return;
onSearch?.();
}
}}
Expand Down
9 changes: 9 additions & 0 deletions src/pages/groupDetail/GroupDetail.styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,17 @@ export const RecommendText = styled.h2`
export const GroupCardBox = styled.div`
display: flex;
overflow-x: auto;
overflow-y: hidden;
padding: 0 20px;
gap: 20px;
scrollbar-width: none;
-ms-overflow-style: none;
&::-webkit-scrollbar {
display: none;
width: 0;
height: 0;
background: transparent;
}
`;

export const BottomButton = styled.button`
Expand Down
19 changes: 7 additions & 12 deletions src/pages/search/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,13 @@ const Search = () => {
const [isLoading, setIsLoading] = useState(false);
const [isInitialized, setIsInitialized] = useState(false);
const [totalElements, setTotalElements] = useState(0);
// 무한스크롤 관련 상태
const [hasMore, setHasMore] = useState(true);
const [page, setPage] = useState(1); // 1부터 시작
const [page, setPage] = useState(1);
const [isLoadingMore, setIsLoadingMore] = useState(false);

const [recentSearches, setRecentSearches] = useState<RecentSearchData[]>([]);
const [searchTimeoutId, setSearchTimeoutId] = useState<NodeJS.Timeout | null>(null);

// Intersection Observer를 위한 ref
const observerRef = useRef<IntersectionObserver | null>(null);
const lastBookElementRef = useRef<HTMLDivElement | null>(null);

Expand All @@ -59,7 +57,6 @@ const Search = () => {
}
};

// 추가 데이터 로드 함수
const loadMore = useCallback(async () => {
if (!searchTerm.trim() || isLoadingMore || !hasMore) return;

Expand All @@ -75,7 +72,6 @@ const Search = () => {
if (newResults.length > 0) {
setSearchResults(prev => [...prev, ...newResults]);
setPage(nextPage);
// API 응답의 last 필드를 사용하여 hasMore 설정
setHasMore(!response.data.last);
} else {
setHasMore(false);
Expand All @@ -92,7 +88,6 @@ const Search = () => {
}
}, [searchTerm, isLoadingMore, hasMore, page, isFinalized]);

// 무한스크롤을 위한 Intersection Observer 설정
const lastBookElementCallback = useCallback(
(node: HTMLDivElement | null) => {
if (isLoadingMore || !hasMore) return;
Expand All @@ -118,8 +113,8 @@ const Search = () => {
setSearchTerm(value);
setIsFinalized(false);
setIsSearching(value.trim() !== '');
setHasMore(true); // 새로운 검색 시 hasMore 초기화
setPage(1); // 페이지를 1로 초기화
setHasMore(true);
setPage(1);

if (value.trim()) {
setSearchParams({ q: value.trim() }, { replace: true });
Expand Down Expand Up @@ -158,16 +153,15 @@ const Search = () => {
}

setIsLoading(true);
setPage(1); // 검색 시 페이지를 1로 초기화
setHasMore(true); // 검색 시 hasMore 초기화
setPage(1);
setHasMore(true);

try {
const response = await getSearchBooks(term, 1, isManualSearch); // 첫 페이지는 1
const response = await getSearchBooks(term, 1, isManualSearch);

if (response.isSuccess) {
const convertedResults = convertToSearchedBooks(response.data.searchResult);
setSearchResults(convertedResults);
// API 응답의 last 필드를 사용하여 hasMore 설정
setHasMore(!response.data.last);
setTotalElements(response.data.totalElements);
} else {
Expand Down Expand Up @@ -249,6 +243,7 @@ const Search = () => {
setHasMore(true);
setPage(1);
setSearchParams({}, { replace: true });
fetchRecentSearches();
};

useEffect(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/searchBook/SearchBook.styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const Header = styled.div`
var(--color-view-viewfield_background_black, #121212) 100%
);
backdrop-filter: blur(0px);
z-index: 10;
z-index: 100;
`;

export const BannerSection = styled.section`
Expand Down