From 17657c1f90aeb714d2cf59a40ace7ff97dd61a03 Mon Sep 17 00:00:00 2001 From: jihwooon Date: Wed, 6 Mar 2024 17:37:20 +0900 Subject: [PATCH] =?UTF-8?q?=EB=8F=84=EC=84=9C=20=EC=83=81=EC=84=B8=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=ED=99=95=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 주요 변경 내용 - 도서 상세 페이지에서 보여지는 정보를 확장했습니다. - 도서 카테고리, 출간일, 가격 등의 정보를 추가했습니다. - dayjs 라이브러리를 추가하여 날짜 포맷팅 기능을 구현했습니다. - 서버 도메인 모델에서 Book 클래스에 categoryName 속성을 추가했습니다. - findWithCategory 함수를 수정하여 카테고리 이름 정보를 함께 조회하도록 했습니다. 관련 변경 사항 - client/package.json 파일 수정 - client/package-lock.json 파일 수정 - client/src/api/http.ts 파일 수정 - client/src/pages/BookDetail.tsx 파일 수정 - client/src/utils/format.ts 파일 수정 - server/src/books/domain/book.ts 파일 수정 - server/src/books/domain/books.repository.ts 파일 수정 --- client/package-lock.json | 6 ++ client/package.json | 1 + client/src/api/http.ts | 2 +- client/src/pages/BookDetail.tsx | 111 +++++++++++++++++++- client/src/utils/format.ts | 8 +- server/src/books/domain/book.ts | 9 ++ server/src/books/domain/books.repository.ts | 3 +- 7 files changed, 134 insertions(+), 6 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index e5655c7..ca9787f 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -17,6 +17,7 @@ "@types/react-dom": "^18.2.19", "@types/react-router-dom": "^5.3.3", "axios": "^1.6.7", + "dayjs": "^1.11.10", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.50.1", @@ -6688,6 +6689,11 @@ "node": ">=10" } }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", diff --git a/client/package.json b/client/package.json index aa5ff95..46e1cd5 100644 --- a/client/package.json +++ b/client/package.json @@ -12,6 +12,7 @@ "@types/react-dom": "^18.2.19", "@types/react-router-dom": "^5.3.3", "axios": "^1.6.7", + "dayjs": "^1.11.10", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.50.1", diff --git a/client/src/api/http.ts b/client/src/api/http.ts index a38a037..4b10cbb 100644 --- a/client/src/api/http.ts +++ b/client/src/api/http.ts @@ -1,4 +1,4 @@ -import axios, { AxiosRequestConfig } from 'axios' +import axios, { AxiosRequestConfig } from 'axios'; import { getToken, removeToken } from '../store/authStore'; const BASE_URL = "http://localhost:8080"; diff --git a/client/src/pages/BookDetail.tsx b/client/src/pages/BookDetail.tsx index 398ab0d..1bce565 100644 --- a/client/src/pages/BookDetail.tsx +++ b/client/src/pages/BookDetail.tsx @@ -1,6 +1,48 @@ -import { useParams } from "react-router-dom"; +import { Link, useParams } from "react-router-dom"; import styled from "styled-components"; +import Title from "../components/common/Title"; import { useBook } from "../hooks/useBook"; +import { BookDetail as IBookDetail } from "../models/book.model"; +import { formatDate, formatNumber } from "../utils/format"; +import { getImgSrc } from "../utils/image"; + +const bookInfoList = [ + { + label: "카테고리", + key: "categoryName", + filter: (book: IBookDetail) => ( + + {book.categoryName} + + ) + }, + { + label: "포맷", + key: "form" + }, + { + label: "페이지", + key: "pages" + }, + { + label: "ISBN", + key: "isbn" + }, + { + label: "출간일", + key: "pubDate", + filter: (book: IBookDetail) => { + return formatDate(book.pubDate) + } + }, + { + label: "가격", + key: "price", + filter: (book: IBookDetail) => { + return `${formatNumber(book.price)} 원` + } + } +] const BookDetail = () => { const { bookId } = useParams(); @@ -9,10 +51,73 @@ const BookDetail = () => { if (!book) return null; return ( -

{book.title}

+ +
+
+ {book.title}/ +
+
+ + {book.title} + + { + bookInfoList.map((item) => ( +
+
{item.label}
+
{item.filter ? item.filter(book) : book + [item.key as keyof IBookDetail]}
+
+ )) + } +

{book.summary}

+ +
+ Like +
+ +
+ Cart +
+
+
+
) } -const BookDetailStyle = styled.div`` +const BookDetailStyle = styled.div` + .header { + display: flex; + align-items: start; + gap: 24px; + padding: 0 0 24px 0; + + .img { + flex: 1; + img { + width: 100%; + height: auto; + } + } + + .info { + flex: 1; + display: flex; + flex-direction: column; + gap: 12px; + + dl { + display: flex; + margin: 0; + dt { + width: 80px; + color: ${({ theme }) => theme.color.secondary} + } + a { + color: ${({ theme }) => theme.color.primary} + } + } + } + } +` export default BookDetail; diff --git a/client/src/utils/format.ts b/client/src/utils/format.ts index 2748d47..0af1f2f 100644 --- a/client/src/utils/format.ts +++ b/client/src/utils/format.ts @@ -1,3 +1,9 @@ +import dayjs from 'dayjs'; + export const formatNumber = (number: number) => { return number.toLocaleString(); -} \ No newline at end of file +} + +export const formatDate = (date: string, format?: string) => { + return dayjs(date).format(format ? format : "YYYY년 MM월 DD일") +} diff --git a/server/src/books/domain/book.ts b/server/src/books/domain/book.ts index bf79857..f67dd44 100644 --- a/server/src/books/domain/book.ts +++ b/server/src/books/domain/book.ts @@ -7,6 +7,8 @@ export default class Book { private categoryId: number; + private categoryName: string; + private form: string; private isbn: string; @@ -32,6 +34,7 @@ export default class Book { title = '', imgId = 0, categoryId = 0, + categoryName = '', form = '', isbn = '', summary = '', @@ -47,6 +50,7 @@ export default class Book { title?: string; imgId?: number; categoryId?: number; + categoryName?: string; form?: string; isbn?: string; summary?: string; @@ -62,6 +66,7 @@ export default class Book { this.title = title; this.imgId = imgId; this.categoryId = categoryId; + this.categoryName = categoryName; this.form = form; this.isbn = isbn; this.summary = summary; @@ -90,6 +95,10 @@ export default class Book { return this.categoryId; } + getCategoryName() { + return this.categoryName; + } + getForm() { return this.form; } diff --git a/server/src/books/domain/books.repository.ts b/server/src/books/domain/books.repository.ts index 1d53aa9..7e18ab4 100644 --- a/server/src/books/domain/books.repository.ts +++ b/server/src/books/domain/books.repository.ts @@ -56,7 +56,7 @@ export const findAll = async ( export const findWithCategory = async (userId: number, bookId: number): Promise => { const [rows] = await doQuery((connection) => connection.execute( - `SELECT b.id, b.title, b.category_id, b.form, b.isbn, b.summary, b.detail, b.author, b.pages, b.contents, b.price, b.pub_date, + `SELECT b.id, b.title, b.category_id, c.name as category_name, b.form, b.isbn, b.summary, b.detail, b.author, b.pages, b.contents, b.price, b.pub_date, (SELECT count(*) FROM likes WHERE b.id = liked_book_id) as Likes, (SELECT EXISTS(SELECT * FROM likes WHERE user_id = ? AND liked_book_id)) as liked FROM books b @@ -79,6 +79,7 @@ export const findWithCategory = async (userId: number, bookId: number): Promise< form: row.form, isbn: row.isbn, categoryId: row.category_id, + categoryName: row.category_name, summary: row.summary, detail: row.detail, author: row.author,