Skip to content

Commit

Permalink
Merge pull request #151 from jihwooon/issue-79
Browse files Browse the repository at this point in the history
도서 목록 보기 기능 추가 및 쿼리스트링 설정
  • Loading branch information
jihwooon authored Mar 3, 2024
2 parents 226c8c6 + a071a7a commit 28d5cd6
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 13 deletions.
10 changes: 7 additions & 3 deletions client/src/components/books/BookItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import { styled } from "styled-components";
import { Book } from "../../models/book.model";
import { formatNumber } from "../../utils/format";
import { getImgSrc } from "../../utils/image";
import { ViewMode } from "./BooksViewSwitcher";

interface Props {
book: Book;
view?: ViewMode;
}

const BookItem = ({ book }: Props) => {
const BookItem = ({ book, view }: Props) => {
return (
<BookItemStyled>
<BookItemStyled view={view}>
<div className="img">
<img src={getImgSrc(book.imgId)} alt={book.title} />
</div>
Expand All @@ -28,14 +30,15 @@ const BookItem = ({ book }: Props) => {
);
};

const BookItemStyled = styled.div`
const BookItemStyled = styled.div<Pick<Props, 'view'>>`
display: flex;
flex-direction: column;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
.img {
border-radius: ${({ theme }) => theme.borderRadius.default};
overflow: hidden;
width: ${({ view }) => (view === "grid" ? "auto" : "160px")};
img {
max-width: 100%;
}
Expand All @@ -44,6 +47,7 @@ const BookItemStyled = styled.div`
.content {
padding: 16px;
position: relative;
flex: ${({ view }) => (view === "grid" ? 0 : 1)};
.title {
font-size: 1.25rem;
Expand Down
26 changes: 22 additions & 4 deletions client/src/components/books/BooksList.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,44 @@
import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import { styled } from "styled-components";
import { Book } from "../../models/book.model";
import { QUERYSTRING } from "../constants/querystring";
import BookItem from "./BookItem";
import { ViewMode } from "./BooksViewSwitcher";

interface Props {
books: Book[]
}

const BooksList = ({ books}: Props) => {
const [view, setView] = useState<ViewMode>('grid');
const location = useLocation();

useEffect(() => {
const params = new URLSearchParams(location.search)
if (params.get(QUERYSTRING.VIEW)) {
setView(params.get(QUERYSTRING.VIEW) as ViewMode)
}
}, [location.search])

return (
<BooksListStyle>
<BooksListStyle view={view}>
{
books?.map((item) => (
<BookItem key={item.id} book={item} />
<BookItem key={item.id} book={item} view={view}/>
))
}
</BooksListStyle>
);
};

const BooksListStyle = styled.div`
interface BooksListStyleProps {
view: ViewMode;
}

const BooksListStyle = styled.div<BooksListStyleProps>`
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-columns: ${({ view }) => (view === 'grid' ? "repeat(4, 1fr)" : "repeat(1, 1fr)")};
gap: 24px;
`;

Expand Down
58 changes: 54 additions & 4 deletions client/src/components/books/BooksViewSwitcher.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,63 @@
import { useEffect } from "react";
import { FaList, FaTh } from "react-icons/fa";
import { useSearchParams } from "react-router-dom";
import { styled } from "styled-components";
import Button from "../common/Button";
import { QUERYSTRING } from "../constants/querystring";

const viewOptions = [
{
value: 'list',
icon: <FaList/>
},
{
value: 'grid',
icon: <FaTh/>
}
]

export type ViewMode = 'grid' | 'list'

const BooksViewSwitcher = () => {
const [searchParams, setSearchParams] = useSearchParams()

const handleSwitch = (value: ViewMode) => {
const newSearchParams = new URLSearchParams(searchParams);

newSearchParams.set(QUERYSTRING.VIEW, value)
setSearchParams(newSearchParams);
}

useEffect(() => {
if (!searchParams.get(QUERYSTRING.VIEW)) {
handleSwitch('grid');
}
}, [])

return (
<div>
<h1>BooksViewSwitcher</h1>
</div>
<BooksViewSwitcherStyle>
{
viewOptions.map((option) => (
<Button
key={option.value}
size="medium"
scheme={searchParams.get(QUERYSTRING.VIEW) === option.value ? "primary" : "normal"}
onClick={() => handleSwitch(option.value as ViewMode)}
>
{option.icon}
</Button>
))
}
</BooksViewSwitcherStyle>
);
};

const BooksViewSwitcherStyled = styled.div``;
const BooksViewSwitcherStyle = styled.div`
display: flex;
gap: 8px;
svg {
fill: #fff;
}
`;

export default BooksViewSwitcher;
3 changes: 2 additions & 1 deletion client/src/components/constants/querystring.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export const QUERYSTRING = {
CATEGORY_ID: 'category_id',
NEWS: 'news',
PAGE: 'page'
PAGE: 'page',
VIEW: 'view'
}
2 changes: 1 addition & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"test": "jest --runInBand --detectOpenHandles --forceExit",
"test:only-changed": "jest --runInBand --onlyChanged",
"test:watch": "jest --watch --runInBand --detectOpenHandles --forceExit",
"start": "tsx --watch src/index.ts"
"start": "tsx watch src/index.ts"
},
"keywords": [],
"author": "",
Expand Down

0 comments on commit 28d5cd6

Please sign in to comment.