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
4 changes: 2 additions & 2 deletions src/app/components/Bookmark.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ export default function Bookmark({
buttonClassName={`${btnPosition} group absolute top-4 z-10 cursor-pointer`}
onClick={(e) => handleClickBookmark(e, book.isbn)}
src={bookmarkIcon}
width={30}
height={30}
width={25}
height={25}
alt="북마크 추가"
imgClassName='transition-transform duration-100 ease-in group-hover:scale-110"'
/>
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default function Dropdown({
return (
<form
action=""
className={`${dropdownPosition} absolute flex flex-col items-center gap-3 rounded border bg-white p-5 shadow-lg`}
className={`${dropdownPosition} absolute top-11 flex w-1/2 flex-col items-center gap-3 rounded border bg-white p-5 shadow-lg md:w-1/3`}
onClick={(e) => e.stopPropagation()}
>
<label className="mr-2 text-sm font-semibold">
Expand Down
48 changes: 26 additions & 22 deletions src/app/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,29 +38,33 @@ export default function Navbar() {
};

return (
<div className="flex w-full items-center justify-between border-b-2 border-borderColor bg-navbar p-4">
<Image
className="cursor-pointer"
src={Logo}
alt="Logo"
width={75}
height={75}
priority={true}
style={{ width: 75, height: 75 }}
onClick={handleHomeClick}
/>
<div className="flex w-full items-center justify-between border-b-2 border-borderColor bg-navbar px-2 py-3 md:p-4">
<picture className="relative h-14 w-14 md:h-16 md:w-16">
<Image
className="cursor-pointer"
src={Logo}
alt="Logo"
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw"
priority={true}
onClick={handleHomeClick}
/>
</picture>

<SearchBar />
<Image
className="cursor-pointer"
src={BookIcon}
width={45}
height={45}
alt="books"
onClick={() => {
resetSearchState();
router.push("/bookshelf");
}}
/>
<picture className="relative h-8 w-8 md:h-11 md:w-11">
<Image
className="cursor-pointer"
src={BookIcon}
fill
alt="books"
onClick={() => {
resetSearchState();
router.push("/bookshelf");
}}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw"
/>
</picture>
</div>
);
}
6 changes: 3 additions & 3 deletions src/app/components/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default function SearchBar() {
role="search"
aria-label="도서 검색"
onSubmit={handleSubmit}
className="flex w-2/5 min-w-72 rounded-lg bg-white p-4 shadow-md"
className="relative flex w-1/3 min-w-60 gap-2 rounded-lg bg-white p-3 shadow-md md:p-4"
>
<label htmlFor="searchInput" className="sr-only">
검색
Expand All @@ -32,9 +32,9 @@ export default function SearchBar() {
placeholder="Search..."
aria-describedby="search-hint"
onChange={(e) => setQuery(e.target.value)}
className="grow text-lg text-font-textPrimary outline-none"
className="w-full grow text-lg text-font-textPrimary outline-none"
/>
<button type="submit" aria-label="검색 버튼" className="search">
<button type="submit" aria-label="검색 버튼" className="">
<Image src={searchBtn} width={32} height={32} alt="검색 아이콘" />
</button>
<p id="search-hint" className="sr-only">
Expand Down
10 changes: 7 additions & 3 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,14 @@ input[type="search"]::-webkit-search-cancel-button {
@apply flex items-center justify-center;
}

.searchDetail {
@apply w-3/12 text-font-textSecondary;
.searchBookKey {
@apply mr-2 flex justify-between;
}

.searchList {
@apply w-[900px] max-w-5xl rounded-lg border-2 border-neutral-200 bg-white;
@apply w-full border-b-2 border-neutral-200 bg-white md:rounded-lg md:border-2;
}

.searchDetail {
@apply flex justify-between text-font-textSecondary md:w-1/6;
}
6 changes: 3 additions & 3 deletions src/app/search/_components/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default function Pagination({ meta, currentPageNum }: PaginationProps) {
const hasNextBlock = endPage < totalPages;

return (
<nav className="flexCenter mt-4">
<nav className="flexCenter mx-2 mt-4">
{/* 첫 페이지 */}
<IconButton
src={doubleArrow}
Expand Down Expand Up @@ -81,8 +81,8 @@ export default function Pagination({ meta, currentPageNum }: PaginationProps) {
onClick={() => handlePageChange(page)}
className={
page === currentPage
? "mx-1 rounded bg-blue-500 px-2 py-1 text-white"
: "mx-1 rounded bg-white px-2 py-1"
? "mx-1 rounded bg-blue-500 px-1 py-1 text-white md:px-2"
: "mx-1 rounded bg-white px-1 py-1 md:px-2"
}
>
{page}
Expand Down
2 changes: 1 addition & 1 deletion src/app/search/_components/SortSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default function SortSearch({ query, page, sort }: SortProps) {
};

return (
<div className="my-1 flex">
<div className="mx-1 my-1 flex self-start text-sm md:text-base">
{sortOption.map((option, index) => (
<div key={option.value} className="flex items-center">
<button
Expand Down
82 changes: 82 additions & 0 deletions src/app/search/_components/presentation/BookItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React from "react";
import Image from "next/image";
import noImage from "/public/NoBookImage.jpeg";
import Bookmark from "@/app/components/Bookmark";
import { Book } from "@/types/common";

interface BookItemProps {
book: Book;
}

function extractISBN(isbn: string) {
const [isbn10, isbn13] = isbn.split(" ");
return { isbn10, isbn13 };
}

function formatDate(dateTime?: string) {
if (!dateTime) return "표시할 날짜가 없습니다.";
return dateTime.split("T")[0];
}

function BookItem({ book }: BookItemProps) {
const { isbn10, isbn13 } = extractISBN(book.isbn);
const publishedDate = formatDate(book.datetime);

const hasTranslators = book.translators && book.translators.length > 0;

const detailList = [
{ label: "작가", value: book.authors },
hasTranslators ? { label: "번역", value: book.translators } : null,
{ label: "출판사", value: book.publisher },
{ label: "출판 날짜", value: publishedDate },
{ label: "ISBN-10", value: isbn10 },
{ label: "ISBN-13", value: isbn13 },
].filter(Boolean);

return (
<li className="searchList">
<article className="relative flex justify-center">
<picture className="flexCenter relative mx-4 my-3 h-40 w-28 self-center shadow-md md:mx-8 md:h-60 md:w-36">
<Image
src={book.thumbnail || noImage}
fill
priority={true}
alt={`${book.title} 표지`}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw"
/>
</picture>

<div className="md:border md:border-borderColor" />

<div className="my-2 ml-4 mr-12 flex w-8/12 flex-col justify-between gap-2 md:my-4 md:ml-8 md:mr-14">
<div className="flex flex-col gap-2">
<h2 className="text-sm font-black text-font-textPrimary md:text-2xl">
{book.title}
</h2>

<p className="line-clamp-2 text-xs font-medium text-font-textSecondary md:line-clamp-4 md:text-sm">
{book.contents}
</p>
</div>

<dl className="grid gap-1 text-xs leading-5 text-font-textPrimary md:gap-2 md:text-sm">
{detailList.map((detail) => (
<div className="searchBookKey" key={detail?.label}>
<dt className="searchDetail">{detail?.label}</dt>
<dd className="font-semibold">{detail?.value}</dd>
</div>
))}
</dl>
</div>

<Bookmark
book={book}
btnPosition={"right-5"}
dropdownPosition={"right-5 w-1/4"}
/>
</article>
</li>
);
}

export default React.memo(BookItem);
86 changes: 4 additions & 82 deletions src/app/search/_components/presentation/SearchResult.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import Image from "next/image";
import noImage from "/public/NoBookImage.jpeg";

import BookItem from "./BookItem";
import SortSearch from "../SortSelect";
import Pagination from "../Pagination";
import Bookmark from "@/app/components/Bookmark";

import { Book, BookResponse } from "@/types/common";

Expand All @@ -26,86 +23,11 @@ export default function SearchResult({
currentPageNum,
}: SearchResultProps) {
return (
<section>
<section className="mx-auto flex max-w-5xl flex-col items-center md:w-4/5">
<SortSearch query={query} page={page} sort={sort} />
<ul className="flex flex-col items-center gap-5">
<ul className="flex w-full flex-col md:gap-5">
{allDocs.map((book) => {
return (
<li key={book.isbn} className="searchList">
<article className="relative flex justify-center">
<picture className="flexCenter relative mx-8 my-3 h-60 w-36 self-center shadow-md">
<Image
src={book.thumbnail || noImage}
fill
alt={`${book.title} 표지`}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw"
/>
</picture>

<div className="border border-borderColor" />

<div className="my-4 ml-8 mr-14 flex w-8/12 flex-col justify-between gap-2">
<div className="flex flex-col gap-2">
<h2 className="text-2xl font-black text-font-textPrimary">
{book.title}
</h2>

<p className="line-clamp-4 text-sm font-medium text-font-textSecondary">
{book.contents}
</p>
</div>

<dl className="grid gap-2 text-sm leading-5 text-font-textPrimary">
<div className="flex">
<dt className="searchDetail">작가</dt>
<dd className="font-semibold">{book.authors}</dd>
</div>

{book.translators && book.translators.length > 0 ? (
<div className="flex">
<dt className="searchDetail">번역</dt>
<dd className="font-semibold">{book.translators}</dd>
</div>
) : null}

<div className="flex">
<dt className="searchDetail">출판사</dt>
<dd className="font-semibold">{book.publisher}</dd>
</div>

<div className="flex">
<dt className="searchDetail">출판 날짜</dt>
<dd className="font-semibold">
{book.datetime ? book.datetime.split("T")[0] : "x"}
</dd>
</div>

{book.isbn.split(" ")[0] && (
<div className="flex">
<dt className="searchDetail">ISBN-10</dt>
<dd className="font-semibold">
{book.isbn.split(" ")[0]}
</dd>
</div>
)}

<div className="flex">
<dt className="searchDetail">ISBN-13</dt>
<dd className="font-semibold">
{book.isbn.split(" ")[1]}
</dd>
</div>
</dl>
</div>

<Bookmark
book={book}
btnPosition={"right-5"}
dropdownPosition={"right-5 w-1/4"}
/>
</article>
</li>
);
return <BookItem key={book.isbn} book={book} />;
})}
</ul>
<Pagination meta={meta} currentPageNum={currentPageNum} />
Expand Down
2 changes: 1 addition & 1 deletion src/app/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default async function Search({ searchParams }: SearchProps) {
}

return (
<section className="flexCenter relative mb-10 mt-10 flex-col font-main">
<section className="relative my-10 flex-col font-main">
{errorMessage ? (
<div className="text-center font-styled text-2xl font-bold text-font-textPrimary">
<p className="mb-2">책 데이터를 불러오는 중 문제가 발생했습니다..</p>
Expand Down