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
39 changes: 39 additions & 0 deletions src/api/books/getSavedBooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { apiClient } from '../index';

// 저장한 책 정보 타입
export interface SavedBook {
bookId: number;
bookTitle: string;
authorName: string;
publisher: string;
bookImageUrl: string;
isbn: string;
}

// API 응답 데이터 타입
export interface SavedBooksData {
bookList: SavedBook[];
}

// API 응답 타입
export interface SavedBooksResponse {
isSuccess: boolean;
code: number;
message: string;
data: SavedBooksData;
}

// 저장한 책 또는 참여 중 모임의 책 조회
export const getSavedBooks = async (type: 'saved' | 'joining'): Promise<SavedBooksResponse> => {
try {
const response = await apiClient.get<SavedBooksResponse>('/books/selectable-list', {
params: {
type: type.toUpperCase(),
},
});
return response.data;
} catch (error) {
console.error('저장한 책 조회 API 오류:', error);
throw error;
}
};
43 changes: 43 additions & 0 deletions src/components/common/BookSearchBottomSheet/BookList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {
BookList as StyledBookList,
BookItem,
BookCover,
BookInfo,
BookTitle,
} from './BookSearchBottomSheet.styled';

export interface Book {
id: number;
title: string;
author: string;
cover: string;
isbn: string;
}

interface BookListProps {
books: Book[];
onBookSelect: (book: Book) => void;
}

const BookList = ({ books, onBookSelect }: BookListProps) => {
const handleImageError = (e: React.SyntheticEvent<HTMLImageElement>) => {
e.currentTarget.style.display = 'none';
};

return (
<StyledBookList>
{books.map(book => (
<BookItem key={book.id} onClick={() => onBookSelect(book)}>
<BookCover>
<img src={book.cover} alt={book.title} onError={handleImageError} />
</BookCover>
<BookInfo>
<BookTitle>{book.title}</BookTitle>
</BookInfo>
</BookItem>
))}
</StyledBookList>
);
};

export default BookList;
Original file line number Diff line number Diff line change
Expand Up @@ -104,63 +104,56 @@ export const IconButton = styled.button`
export const TabContainer = styled.div`
display: flex;
gap: 34px;
margin-bottom: 24px;
margin-bottom: 16px;
flex-shrink: 0;
`;

export const Tab = styled.button<{ active: boolean }>`
background: none;
border: none;
color: ${({ active }) => (active ? semanticColors.text.primary : semanticColors.text.ghost)};
color: ${({ active }) => (active ? colors.white : colors.grey[300])};
font-size: ${typography.fontSize.sm};
font-weight: ${typography.fontWeight.semibold};
padding: 8px 0 8px 0;
cursor: pointer;
position: relative;

${({ active }) =>
active &&
`
&::after {
content: '';
position: absolute;
bottom: -1px;
left: 0;
right: 0;
height: 2px;
background-color: ${semanticColors.text.primary};
}
`}
&:after {
content: '';
position: absolute;
bottom: -8px;
left: 5px;
right: 5px;
height: 2px;
background-color: ${({ active }) => (active ? colors.white : 'transparent')};
transition: background-color 0.2s ease;
}

&:hover {
color: ${colors.white};
}
`;

export const BookListContainer = styled.div`
flex: 1;
overflow-y: auto;
margin-right: -16px;
padding-right: 16px;
min-height: 0;

&::-webkit-scrollbar {
width: 4px;
width: 3px;
}

&::-webkit-scrollbar-track {
background: ${colors.grey[400]};
border-radius: 2px;
margin-right: 14px;
background: transparent;
}

&::-webkit-scrollbar-thumb {
background-color: ${colors.white};
border-radius: 2px;
background: ${colors.white};
border-radius: 3px;
}

&::-webkit-scrollbar-thumb:hover {
background-color: ${colors.grey[200]};
background: ${colors.grey[100]};
}

/* Firefox 스크롤바 */
scrollbar-width: thin;
scrollbar-color: ${colors.white} ${colors.grey[400]};
`;

export const BookList = styled.div`
Expand All @@ -172,18 +165,24 @@ export const BookList = styled.div`
export const BookItem = styled.div`
display: flex;
align-items: center;
gap: 8px;
padding: 12px 0;
border-bottom: 1px solid ${colors.grey[400]};
padding: 12px 2px;
background-color: none;
cursor: pointer;
transition: background-color 0.2s ease;
border-bottom: 1px solid ${colors.grey[400]};

&:last-child {
border-bottom: none;
}
`;

export const BookCover = styled.div`
width: 45px;
height: 60px;
overflow: hidden;
flex-shrink: 0;
background-color: ${semanticColors.background.card};
margin-right: 8px;
border: 1px solid ${colors.grey[300]};

img {
width: 100%;
Expand All @@ -194,14 +193,82 @@ export const BookCover = styled.div`

export const BookInfo = styled.div`
flex: 1;
min-width: 0;
`;

export const BookTitle = styled.h3`
font-size: ${typography.fontSize.sm};
font-weight: ${typography.fontWeight.regular};
color: ${colors.white};
margin: 0;
line-height: 1.4;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
`;

// 로딩 상태 스타일
export const LoadingContainer = styled.div`
display: flex;
justify-content: center;
align-items: center;
height: 200px;
`;

export const LoadingText = styled.p`
color: ${colors.grey[300]};
font-size: ${typography.fontSize.base};
margin: 0;
`;

// 에러 상태 스타일
export const ErrorContainer = styled.div`
display: flex;
justify-content: center;
align-items: center;
height: 200px;
`;

export const ErrorText = styled.p`
color: ${colors.red};
font-size: ${typography.fontSize.base};
margin: 0;
text-align: center;
`;

// 빈 상태 스타일
export const EmptyContainer = styled.div`
display: flex;
flex-direction: column;
gap: 4px;
justify-content: center;
align-items: center;
height: 200px;
gap: 8px;
`;

export const BookTitle = styled.div`
color: ${semanticColors.text.primary};
export const EmptyText = styled.p`
color: #e0e0e0;};
font-size: ${typography.fontSize.sm};
font-weight: ${typography.fontWeight.regular};
line-height: 1.4;
margin: 0;
text-align: center;
`;
Comment on lines +251 to +257
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

문법 오류: 여분의 중괄호로 인해 스타일 파싱 실패

EmptyText의 color 속성에 불필요한 };가 포함되어 있습니다. 이대로면 CSS-in-JS 파싱 오류가 발생할 수 있습니다. 즉시 수정이 필요합니다.

-export const EmptyText = styled.p`
-  color: #e0e0e0;};
+export const EmptyText = styled.p`
+  color: #e0e0e0;
   font-size: ${typography.fontSize.sm};
   font-weight: ${typography.fontWeight.regular};
   margin: 0;
   text-align: center;
 `;

선택: 색 값을 토큰으로 통일하고 싶다면 ${colors.grey[200]} 사용도 고려해 주세요.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const EmptyText = styled.p`
color: #e0e0e0;};
font-size: ${typography.fontSize.sm};
font-weight: ${typography.fontWeight.regular};
line-height: 1.4;
margin: 0;
text-align: center;
`;
export const EmptyText = styled.p`
color: #e0e0e0;
font-size: ${typography.fontSize.sm};
font-weight: ${typography.fontWeight.regular};
margin: 0;
text-align: center;
`;
🤖 Prompt for AI Agents
In src/components/common/BookSearchBottomSheet/BookSearchBottomSheet.styled.ts
around lines 251 to 257, remove the stray characters after the color property
(the extra "};") so the CSS-in-JS block parses correctly; change the color line
to a valid property assignment and, if you want consistent tokens, replace the
hex with the design token `${colors.grey[200]}` (ensure colors is imported) and
keep the rest of the styled.p block intact.


export const ApplyButton = styled.button`
background-color: ${colors.purple.main};
color: ${colors.white};
padding: 10px 12px;
font-size: ${typography.fontSize.base};
font-weight: ${typography.fontWeight.semibold};
line-height: 24px;
border: none;
border-radius: 12px;
cursor: pointer;
margin-top: 16px;

&:hover {
background-color: ${colors.purple.dark};
}
`;
Loading