From 1fdc791bd86bdad63784154a5719eda64015cec8 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 4 Aug 2025 21:01:48 +0900 Subject: [PATCH 01/31] =?UTF-8?q?chore(Sprint6):=20=ED=99=98=EA=B2=BD=20?= =?UTF-8?q?=EB=B3=80=EC=88=98=20=ED=8C=8C=EC=9D=BC=20git=20=EC=B6=94?= =?UTF-8?q?=EC=A0=81=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite-project/.env.development | 1 - vite-project/.env.production | 1 - vite-project/.gitignore | 2 ++ 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 vite-project/.env.development delete mode 100644 vite-project/.env.production diff --git a/vite-project/.env.development b/vite-project/.env.development deleted file mode 100644 index 887a088a..00000000 --- a/vite-project/.env.development +++ /dev/null @@ -1 +0,0 @@ -VITE_API_BASE_URL=https://panda-market-api.vercel.app \ No newline at end of file diff --git a/vite-project/.env.production b/vite-project/.env.production deleted file mode 100644 index 887a088a..00000000 --- a/vite-project/.env.production +++ /dev/null @@ -1 +0,0 @@ -VITE_API_BASE_URL=https://panda-market-api.vercel.app \ No newline at end of file diff --git a/vite-project/.gitignore b/vite-project/.gitignore index a547bf36..a3ab6e36 100644 --- a/vite-project/.gitignore +++ b/vite-project/.gitignore @@ -22,3 +22,5 @@ dist-ssr *.njsproj *.sln *.sw? + +.env.* \ No newline at end of file From 01597ba0f42e71f83c1337d7ad9c5b85e81906e1 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 4 Aug 2025 21:04:50 +0900 Subject: [PATCH 02/31] =?UTF-8?q?refactor(Sprint6):=20Button=20component?= =?UTF-8?q?=EC=9D=98=20disabled=20style=EC=9D=84=20CSS=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=EB=A7=8C=20=EC=82=AC=EC=9A=A9=ED=95=B4=EC=84=9C=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite-project/src/components/Button.jsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vite-project/src/components/Button.jsx b/vite-project/src/components/Button.jsx index 4019d336..fe78d60f 100644 --- a/vite-project/src/components/Button.jsx +++ b/vite-project/src/components/Button.jsx @@ -1,8 +1,7 @@ import styled from "styled-components"; const StyledButton = styled.button` - background-color: ${({ disabled }) => - disabled ? "var(--color-cool-gray-400)" : "var(--color-primary-100)"}; + background-color: var(--color-primary-100); padding: 8px 23px; color: var(--color-cool-gray-100); font-size: 16px; @@ -10,7 +9,12 @@ const StyledButton = styled.button` line-height: 26px; border-radius: 8px; border: none; - cursor: ${({ disabled }) => (disabled ? "default" : "pointer")}; + cursor: pointer; + + &:disabled { + background-color: var(--color-cool-gray-400); + cursor: default; + } `; function Button({ children, ...props }) { From c92aa1fc86a7be5cb42cca5e8386773d7227e17b Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 4 Aug 2025 22:18:31 +0900 Subject: [PATCH 03/31] =?UTF-8?q?refactor(Sprint6):=20

=20->=20=20?= =?UTF-8?q?tag=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite-project/src/components/item/item.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vite-project/src/components/item/item.jsx b/vite-project/src/components/item/item.jsx index cb0fed39..a4f383cf 100644 --- a/vite-project/src/components/item/item.jsx +++ b/vite-project/src/components/item/item.jsx @@ -58,7 +58,7 @@ function Item({ imageUrl, title, price, likeCount }) {

{title}

-

{formatPrice(price, "원")}

+ {formatPrice(price, "원")} 좋아요 갯수 {likeCount} From 1735fa35d4c52570472673907b08b36d50d42ceb Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 5 Aug 2025 08:26:26 +0900 Subject: [PATCH 04/31] =?UTF-8?q?feat(Sprint7)=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=ED=81=B4=EB=A6=AD=20=EC=8B=9C=20=EC=83=81=EC=84=B8=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/item/items-grid.jsx | 18 ++++++++++++------ vite-project/src/main.jsx | 2 ++ .../src/pages/items/item-detail-page.jsx | 10 ++++++++++ 3 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 vite-project/src/pages/items/item-detail-page.jsx diff --git a/vite-project/src/components/item/items-grid.jsx b/vite-project/src/components/item/items-grid.jsx index ceab0b45..50b48c21 100644 --- a/vite-project/src/components/item/items-grid.jsx +++ b/vite-project/src/components/item/items-grid.jsx @@ -1,3 +1,4 @@ +import { Link } from "react-router-dom"; import styled from "styled-components"; import Item from "./item"; @@ -15,13 +16,18 @@ function ItemsGrid({ items, numberOfColumns }) { return ( {items.map((product) => ( - + style={{ textDecoration: "none" }} + > + + ))} ); diff --git a/vite-project/src/main.jsx b/vite-project/src/main.jsx index e88db0e8..e07e1629 100644 --- a/vite-project/src/main.jsx +++ b/vite-project/src/main.jsx @@ -1,6 +1,7 @@ import { BrowserRouter, Route, Routes } from "react-router-dom"; import App from "./components/App"; import AddItemPage from "./pages/add-item/add-item-page"; +import ItemDetailPage from "./pages/items/item-detail-page"; import ItemsPage from "./pages/items/items-page"; function Main() { @@ -9,6 +10,7 @@ function Main() { } /> + } /> } /> NOT IMPLEMENTED} /> diff --git a/vite-project/src/pages/items/item-detail-page.jsx b/vite-project/src/pages/items/item-detail-page.jsx new file mode 100644 index 00000000..fb9835dc --- /dev/null +++ b/vite-project/src/pages/items/item-detail-page.jsx @@ -0,0 +1,10 @@ +function ItemDetailPage() { + return ( +
+

Item Detail Page

+ {/* Add your item detail content here */} +
+ ); +} + +export default ItemDetailPage; \ No newline at end of file From 4716e30d7eff15c2071a6388d53996aa12358653 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 5 Aug 2025 13:31:18 +0900 Subject: [PATCH 05/31] =?UTF-8?q?fix(Sprint6):=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=B6=94=EA=B0=80=ED=95=A0=20?= =?UTF-8?q?=EB=95=8C=20image=20input=EA=B3=BC=20image=20preview=20?= =?UTF-8?q?=ED=81=AC=EA=B8=B0=EA=B0=80=20=EB=A7=9E=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite-project/src/components/add-item/adding-item-image.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vite-project/src/components/add-item/adding-item-image.jsx b/vite-project/src/components/add-item/adding-item-image.jsx index 8c4f3b8c..20729d78 100644 --- a/vite-project/src/components/add-item/adding-item-image.jsx +++ b/vite-project/src/components/add-item/adding-item-image.jsx @@ -3,11 +3,12 @@ import removeImg from "../../assets/ic-xmark-fill.svg"; const StyledAddingItemImage = styled.div` width: 282px; + height: 282px; position: relative; & > img { width: 100%; - aspect-ratio: 1; + height: 100%; object-fit: cover; border-radius: 12px; } @@ -25,10 +26,12 @@ const StyledAddingItemImage = styled.div` @media (max-width: 1199px) { width: 168px; + height: 168px; } @media (max-width: 767px) { width: 50%; + height: auto; } `; From 9fe818fb168546f27f327abdc60d55adb907838e Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 5 Aug 2025 13:57:00 +0900 Subject: [PATCH 06/31] =?UTF-8?q?feat(Sprint7):=20Product=20detail=20page?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=8F=99=ED=96=88=EC=9D=84=20=EB=95=8C=20?= =?UTF-8?q?=EC=84=9C=EB=B2=84=EC=97=90=EC=84=9C=20product=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A0=95=EB=B3=B4=20=EA=B0=80=EC=A0=B8=EC=98=A4?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite-project/src/api/products.js | 48 ++++++++++++++++--- .../src/pages/items/item-detail-page.jsx | 12 ++++- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/vite-project/src/api/products.js b/vite-project/src/api/products.js index fe32ac72..11283375 100644 --- a/vite-project/src/api/products.js +++ b/vite-project/src/api/products.js @@ -1,19 +1,44 @@ +function trimPath(str) { + let trimmed = str.trim(); + while (trimmed.startsWith("/")) { + trimmed = trimmed.slice(1); + } + return trimmed; +} + +function createUrl(path, params) { + const trimmed = trimPath(path); + const url = new URL(`${import.meta.env.VITE_API_BASE_URL}/${trimmed}`); + + if (!params) { + return url; + } + + Object.keys(params).forEach((key) => + url.searchParams.append(key, params[key]) + ); + + return url; +} + export async function fetchProducts({ keyword = "", page = 1, pageSize = 10, orderBy = "recent", } = {}) { - const url = new URL(`${import.meta.env.VITE_API_BASE_URL}/products`); - url.searchParams.append("page", page); - url.searchParams.append("pageSize", pageSize); - url.searchParams.append("orderBy", orderBy); + const params = { + page, + pageSize, + orderBy, + }; + if (keyword) { - url.searchParams.append("keyword", keyword); + params.keyword = keyword; } + const url = createUrl("products", params); const response = await fetch(url); - if (!response.ok) { throw new Error("Failed to fetch products"); } @@ -24,3 +49,14 @@ export async function fetchProducts({ numberOfPages: Math.ceil(json.totalCount / pageSize), }; } + +export async function fetchProduct(id) { + const url = createUrl(`products/${id}`); + const response = await fetch(url); + if (!response.ok) { + throw new Error("Failed to fetch product"); + } + + const json = await response.json(); + return json; +} diff --git a/vite-project/src/pages/items/item-detail-page.jsx b/vite-project/src/pages/items/item-detail-page.jsx index fb9835dc..5bd0688c 100644 --- a/vite-project/src/pages/items/item-detail-page.jsx +++ b/vite-project/src/pages/items/item-detail-page.jsx @@ -1,4 +1,14 @@ +import { useEffect } from "react"; +import { useParams } from "react-router-dom"; +import { fetchProduct } from "../../api/products"; + function ItemDetailPage() { + const { id } = useParams(); + + useEffect(() => { + fetchProduct(id).then((product) => console.log(product)); + }, [id]); + return (

Item Detail Page

@@ -7,4 +17,4 @@ function ItemDetailPage() { ); } -export default ItemDetailPage; \ No newline at end of file +export default ItemDetailPage; From 94f5653d66516d98d8e56ae23f8d9cef2a6ec764 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 5 Aug 2025 15:52:18 +0900 Subject: [PATCH 07/31] =?UTF-8?q?feat(Sprint7):=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20-=20image,=20title,=20price=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/assets/ic-dots-3-vertical.svg | 5 ++ .../item-detail/item-detail-title.jsx | 79 +++++++++++++++++++ .../components/item-detail/item-detail.jsx | 70 ++++++++++++++++ .../src/pages/items/item-detail-page.jsx | 13 +-- 4 files changed, 156 insertions(+), 11 deletions(-) create mode 100644 vite-project/src/assets/ic-dots-3-vertical.svg create mode 100644 vite-project/src/components/item-detail/item-detail-title.jsx create mode 100644 vite-project/src/components/item-detail/item-detail.jsx diff --git a/vite-project/src/assets/ic-dots-3-vertical.svg b/vite-project/src/assets/ic-dots-3-vertical.svg new file mode 100644 index 00000000..dd7ed7f5 --- /dev/null +++ b/vite-project/src/assets/ic-dots-3-vertical.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/vite-project/src/components/item-detail/item-detail-title.jsx b/vite-project/src/components/item-detail/item-detail-title.jsx new file mode 100644 index 00000000..2014f8a0 --- /dev/null +++ b/vite-project/src/components/item-detail/item-detail-title.jsx @@ -0,0 +1,79 @@ +import styled from "styled-components"; +import moreImg from "../../assets/ic-dots-3-vertical.svg"; +import { formatPrice } from "../../utils/formatter"; + +const StyledItemDetailTitle = styled.div``; + +const StyledItemTitleHeader = styled.div` + display: flex; + justify-content: space-between; + align-items: center; +`; + +const StyledItemName = styled.h2` + margin: 0; + font-size: 24px; + font-weight: 600; + line-height: 32px; + color: var(--color-secondary-800); + + @media (max-width: 1199px) { + font-size: 20px; + } + + @media (max-width: 767px) { + font-size: 16px; + line-height: 26px; + } +`; + +const StyledItemMoreButton = styled.button` + background: none; + border: none; + padding: 0; + width: 24px; + height: 24px; + cursor: pointer; +`; + +const StyledItemPrice = styled.span` + display: block; + font-size: 40px; + font-weight: 600; + line-height: 100%; + color: var(--color-secondary-800); + margin-top: 16px; + margin-bottom: 16px; + + @media (max-width: 1199px) { + font-size: 32px; + line-height: 42px; + margin-top: 8px; + } + + @media (max-width: 767px) { + font-size: 24px; + line-height: 32px; + } +`; + +const StyledSeparator = styled.div` + border-bottom: 1px solid var(--color-cool-gray-200); +`; + +function ItemDetailTitle({ title, price }) { + return ( + + + {title} + + + + + {formatPrice(price, "원")} + + + ); +} + +export default ItemDetailTitle; diff --git a/vite-project/src/components/item-detail/item-detail.jsx b/vite-project/src/components/item-detail/item-detail.jsx new file mode 100644 index 00000000..c2e2bac2 --- /dev/null +++ b/vite-project/src/components/item-detail/item-detail.jsx @@ -0,0 +1,70 @@ +import { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; +import styled from "styled-components"; +import { fetchProduct } from "../../api/products"; +import ItemDetailTitle from "./item-detail-title"; + +const StyledItemDetail = styled.div` + display: flex; + gap: 24px; + + @media (max-width: 1199px) { + gap: 16px; + } + + @media (max-width: 767px) { + flex-direction: column; + } +`; + +const StyledItemDetailImage = styled.div` + width: 486px; + height: 486px; + aspect-ratio: 1 / 1; + + img { + width: 100%; + height: 100%; + border-radius: 16px; + object-fit: cover; + } + + @media (max-width: 1199px) { + width: 340px; + height: 340px; + } + + @media (max-width: 767px) { + width: 100%; + height: 100%; + } +`; + +const StyledItemDetailInfo = styled.div` + width: 100%; +`; + +function ItemDetail() { + const [product, setProduct] = useState(null); + const { id } = useParams(); + + useEffect(() => { + fetchProduct(id).then(setProduct); + }, [id]); + + return product ? ( + + + {product.images[0] && } + + + + + + ) : ( + // TODO: Product loading 중 보여줄 UI +

Loading...

+ ); +} + +export default ItemDetail; diff --git a/vite-project/src/pages/items/item-detail-page.jsx b/vite-project/src/pages/items/item-detail-page.jsx index 5bd0688c..a26c98d0 100644 --- a/vite-project/src/pages/items/item-detail-page.jsx +++ b/vite-project/src/pages/items/item-detail-page.jsx @@ -1,18 +1,9 @@ -import { useEffect } from "react"; -import { useParams } from "react-router-dom"; -import { fetchProduct } from "../../api/products"; +import ItemDetail from "../../components/item-detail/item-detail"; function ItemDetailPage() { - const { id } = useParams(); - - useEffect(() => { - fetchProduct(id).then((product) => console.log(product)); - }, [id]); - return (
-

Item Detail Page

- {/* Add your item detail content here */} +
); } From 5696e741401cad7c46910a1a6ed65e2e57738bc7 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 5 Aug 2025 15:54:51 +0900 Subject: [PATCH 08/31] =?UTF-8?q?refactor(Sprint7):=20TagList=20component?= =?UTF-8?q?=EC=97=90=EC=84=9C=20margin=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite-project/src/components/tag/tag-list.jsx | 1 - vite-project/src/pages/add-item/add-item-page.jsx | 10 ++++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/vite-project/src/components/tag/tag-list.jsx b/vite-project/src/components/tag/tag-list.jsx index a6e64e3e..046c91cf 100644 --- a/vite-project/src/components/tag/tag-list.jsx +++ b/vite-project/src/components/tag/tag-list.jsx @@ -4,7 +4,6 @@ import Tag from "./tag"; const StyledTagList = styled.div` display: flex; gap: 12px; - margin-top: 14px; flex-wrap: wrap; `; diff --git a/vite-project/src/pages/add-item/add-item-page.jsx b/vite-project/src/pages/add-item/add-item-page.jsx index 10493852..a524193a 100644 --- a/vite-project/src/pages/add-item/add-item-page.jsx +++ b/vite-project/src/pages/add-item/add-item-page.jsx @@ -20,6 +20,12 @@ const StyledAddItemForm = styled.form` padding-bottom: 69px; `; +const StyledTagSectionContent = styled.div` + display: flex; + flex-direction: column; + gap: 14px; +`; + function AddItemPage() { const [inputValues, setInputValues] = useState(INITIAL_INPUT_VALUES); const [tags, setTags] = useState([]); @@ -114,7 +120,7 @@ function AddItemPage() {
-
+ 0 && ( )} -
+
From 5cb1e3ab6d44f84018a5aa7e8951539661116b06 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 5 Aug 2025 16:00:36 +0900 Subject: [PATCH 09/31] =?UTF-8?q?feat(Sprint7):=20Tag=20=EB=B0=8F=20TagLis?= =?UTF-8?q?t=20component=EC=97=90=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20on/off=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite-project/src/components/tag/tag-list.jsx | 2 +- vite-project/src/components/tag/tag.jsx | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/vite-project/src/components/tag/tag-list.jsx b/vite-project/src/components/tag/tag-list.jsx index 046c91cf..dfac0325 100644 --- a/vite-project/src/components/tag/tag-list.jsx +++ b/vite-project/src/components/tag/tag-list.jsx @@ -11,7 +11,7 @@ function TagList({ tags, onRemove }) { return ( {tags.map((tag) => ( - onRemove(tag)}> + onRemove(tag) : undefined}> {"#" + tag} ))} diff --git a/vite-project/src/components/tag/tag.jsx b/vite-project/src/components/tag/tag.jsx index bcf7813e..b9e29a15 100644 --- a/vite-project/src/components/tag/tag.jsx +++ b/vite-project/src/components/tag/tag.jsx @@ -5,11 +5,10 @@ const StyledTag = styled.div` background-color: var(--color-cool-gray-100); color: var(--color-secondary-800); font-size: 16px; - fontweight: 400; line-height: 26px; padding: 5px 0; padding-left: 16px; - padding-right: 12px; + padding-right: ${({ onRemove }) => (onRemove ? 12 : 16)}px; border-radius: 26px; display: flex; gap: 8px; @@ -29,9 +28,11 @@ function Tag({ children, onRemove }) { return ( {children} - + {onRemove && ( + + )} ); } From 3bcc6390cd04db31cadfb050b5ea0a39c93e3db5 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 5 Aug 2025 16:00:53 +0900 Subject: [PATCH 10/31] =?UTF-8?q?feat(Sprint7):=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20-=20description,=20tags=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../item-detail/item-detail-section.jsx | 43 +++++++++++++++++++ .../components/item-detail/item-detail.jsx | 22 ++++++++++ 2 files changed, 65 insertions(+) create mode 100644 vite-project/src/components/item-detail/item-detail-section.jsx diff --git a/vite-project/src/components/item-detail/item-detail-section.jsx b/vite-project/src/components/item-detail/item-detail-section.jsx new file mode 100644 index 00000000..e0b4ed80 --- /dev/null +++ b/vite-project/src/components/item-detail/item-detail-section.jsx @@ -0,0 +1,43 @@ +import styled from "styled-components"; + +const StyledItemDetailSection = styled.section` + display: flex; + flex-direction: column; + gap: 16px; + + h3 { + font-size: 16px; + font-weight: 600; + line-height: 26px; + color: var(--color-secondary-800); + margin: 0; + } + + p { + font-size: 16px; + line-height: 26px; + color: var(--color-secondary-600); + margin: 0; + } + + @media (max-width: 1199px) { + gap: 8px; + + h3 { + font-size: 14px; + line-height: 24px; + } + } +`; + +function ItemDetailSection({ title, description, children }) { + return ( + +

{title}

+ {description &&

{description}

} + {children} +
+ ); +} + +export default ItemDetailSection; diff --git a/vite-project/src/components/item-detail/item-detail.jsx b/vite-project/src/components/item-detail/item-detail.jsx index c2e2bac2..8e96e5ac 100644 --- a/vite-project/src/components/item-detail/item-detail.jsx +++ b/vite-project/src/components/item-detail/item-detail.jsx @@ -2,6 +2,8 @@ import { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; import styled from "styled-components"; import { fetchProduct } from "../../api/products"; +import TagList from "../tag/tag-list"; +import ItemDetailSection from "./item-detail-section"; import ItemDetailTitle from "./item-detail-title"; const StyledItemDetail = styled.div` @@ -44,6 +46,17 @@ const StyledItemDetailInfo = styled.div` width: 100%; `; +const StyledItemDetailSections = styled.div` + display: flex; + flex-direction: column; + gap: 24px; + margin-top: 24px; + + @media (max-width: 1199px) { + margin-top: 16px; + } +`; + function ItemDetail() { const [product, setProduct] = useState(null); const { id } = useParams(); @@ -59,6 +72,15 @@ function ItemDetail() { + + + + + + ) : ( From 9cc803407b2251a7d934b7c38a42720635189781 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 5 Aug 2025 16:07:50 +0900 Subject: [PATCH 11/31] =?UTF-8?q?feat(Sprint7):=20User=20profile=20?= =?UTF-8?q?=EC=82=AC=EC=A7=84=EC=9D=84=20Avatar=20component=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite-project/src/components/Nav.jsx | 7 ++----- vite-project/src/components/avatar.jsx | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 vite-project/src/components/avatar.jsx diff --git a/vite-project/src/components/Nav.jsx b/vite-project/src/components/Nav.jsx index ed76fa9c..a95cbe47 100644 --- a/vite-project/src/components/Nav.jsx +++ b/vite-project/src/components/Nav.jsx @@ -1,9 +1,8 @@ import { NavLink, useLocation } from "react-router-dom"; import largeLogo from "../assets/logo-large.svg"; import smallLogo from "../assets/logo-small.svg"; -import profileImg from "../assets/profile-default.svg"; - import "./Nav.css"; +import Avatar from "./avatar"; function NavigationLink({ to, activePaths = [], children }) { const location = useLocation(); @@ -40,9 +39,7 @@ function Nav() { 중고마켓 -
- -
+
); diff --git a/vite-project/src/components/avatar.jsx b/vite-project/src/components/avatar.jsx new file mode 100644 index 00000000..87f7c1ac --- /dev/null +++ b/vite-project/src/components/avatar.jsx @@ -0,0 +1,26 @@ +import styled from "styled-components"; +import defaultImg from "../assets/profile-default.svg"; + +const StyledAvatar = styled.div` + width: ${({ $size }) => $size}px; + height: ${({ $size }) => $size}px; + + img { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: 20; + } +`; + +const DEFAULT_SIZE = 40; + +function Avatar({ imageUrl, size = DEFAULT_SIZE }) { + return ( + + 프로필 사진 + + ); +} + +export default Avatar; From e9c28ada49aba13a51e249864d6743438df71d8d Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 5 Aug 2025 16:53:52 +0900 Subject: [PATCH 12/31] =?UTF-8?q?feat(Sprint7):=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20-=20profile,=20favorite=20button=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/favorite-button.jsx | 42 +++++++++++++++++ .../item-detail/item-detail-profile.jsx | 46 +++++++++++++++++++ .../components/item-detail/item-detail.jsx | 31 +++++++++++++ vite-project/src/palette.css | 1 + vite-project/src/utils/formatter.js | 7 +++ 5 files changed, 127 insertions(+) create mode 100644 vite-project/src/components/favorite-button.jsx create mode 100644 vite-project/src/components/item-detail/item-detail-profile.jsx diff --git a/vite-project/src/components/favorite-button.jsx b/vite-project/src/components/favorite-button.jsx new file mode 100644 index 00000000..7c1f2290 --- /dev/null +++ b/vite-project/src/components/favorite-button.jsx @@ -0,0 +1,42 @@ +import styled from "styled-components"; +import favoriteImg from "../assets/ic-heart.svg"; + +const StyledFavoriteButton = styled.div` + display: flex; + gap: 4px; + align-items: center; + border: 1px solid var(--color-secondary-200); + border-radius: 40px; + background: none; + padding: 4px 12px; + + img { + width: 32px; + height: 32px; + } + + span { + font-size: 16px; + font-weight: 500; + line-height: 26px; + color: var(--color-cool-gray-500); + } + + @media (max-width: 1199px) { + div { + width: 24px; + height: 24px; + } + } +`; + +function FavoriteButton({ count, isFavorite }) { + return ( + + 좋아요 + {count} + + ); +} + +export default FavoriteButton; diff --git a/vite-project/src/components/item-detail/item-detail-profile.jsx b/vite-project/src/components/item-detail/item-detail-profile.jsx new file mode 100644 index 00000000..e2feb19e --- /dev/null +++ b/vite-project/src/components/item-detail/item-detail-profile.jsx @@ -0,0 +1,46 @@ +import styled from "styled-components"; +import { formatDateYYYYMMDD } from "../../utils/formatter"; +import Avatar from "../avatar"; + +const ProfileInfo = styled.div` + display: flex; + flex-direction: column; + gap: 2px; + + span:first-child { + font-size: 14px; + font-weight: 500; + line-height: 24px; + color: var(--color-secondary-600); + } + + span:last-child { + font-size: 14px; + line-height: 24px; + color: var(--color-cool-gray-400); + } +`; + +const StyledItemDetailProfile = styled.div` + display: flex; + align-items: center; + gap: 16px; + + ${ProfileInfo} { + flex-grow: 1; + } +`; + +function ItemDetailProfile({ imageUrl, name, createdAt }) { + return ( + + + + {name} + {formatDateYYYYMMDD(createdAt)} + + + ); +} + +export default ItemDetailProfile; diff --git a/vite-project/src/components/item-detail/item-detail.jsx b/vite-project/src/components/item-detail/item-detail.jsx index 8e96e5ac..780d60c6 100644 --- a/vite-project/src/components/item-detail/item-detail.jsx +++ b/vite-project/src/components/item-detail/item-detail.jsx @@ -2,7 +2,9 @@ import { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; import styled from "styled-components"; import { fetchProduct } from "../../api/products"; +import FavoriteButton from "../favorite-button"; import TagList from "../tag/tag-list"; +import ItemDetailProfile from "./item-detail-profile"; import ItemDetailSection from "./item-detail-section"; import ItemDetailTitle from "./item-detail-title"; @@ -57,6 +59,23 @@ const StyledItemDetailSections = styled.div` } `; +const StyledItemDetailProfileContainer = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + gap: 24px; + margin-top: 62px; + + @media (max-width: 1199px) { + margin-top: 40px; + } +`; + +const StyledItemDetailFavoriteContainer = styled.div` + border-left: 1px solid var(--color-cool-gray-200); + padding-left: 24px; +`; + function ItemDetail() { const [product, setProduct] = useState(null); const { id } = useParams(); @@ -81,6 +100,18 @@ function ItemDetail() { + + + + + + ) : ( diff --git a/vite-project/src/palette.css b/vite-project/src/palette.css index bbbc00c5..78260bfa 100644 --- a/vite-project/src/palette.css +++ b/vite-project/src/palette.css @@ -4,6 +4,7 @@ /* Secondary */ --color-secondary-100: #f3f4f6; + --color-secondary-200: #e5e7eb; --color-secondary-400: #9ca3af; --color-secondary-600: #4b5563; --color-secondary-800: #1f2937; diff --git a/vite-project/src/utils/formatter.js b/vite-project/src/utils/formatter.js index a1ba1305..60ae0464 100644 --- a/vite-project/src/utils/formatter.js +++ b/vite-project/src/utils/formatter.js @@ -1,3 +1,10 @@ export function formatPrice(price, suffix = "") { return Intl.NumberFormat().format(price) + suffix; } + +export function formatDateYYYYMMDD(dateString) { + const date = new Date(dateString); + const isoString = date.toISOString(); + const index = isoString.indexOf("T"); + return isoString.slice(0, index); +} From 104fe67036bd793198594fd7208a7197cedc6260 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 5 Aug 2025 16:56:03 +0900 Subject: [PATCH 13/31] =?UTF-8?q?refactor(Sprint7):=20Component=20?= =?UTF-8?q?=EC=99=B8=EB=B6=80=EC=99=80=20=EC=A0=91=EC=A0=90=EC=9D=B4=20?= =?UTF-8?q?=EC=97=86=EB=8A=94=20styled-components=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=EC=9D=84=20=EB=8B=A8=EC=88=9C=ED=95=98=EA=B2=8C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 외부와 간접적으로 접점이 없는 styled-components로 만든 component들은 `Styled~` 이름 규칙을 따르지 않습니다. --- .../components/item-detail/item-detail.jsx | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/vite-project/src/components/item-detail/item-detail.jsx b/vite-project/src/components/item-detail/item-detail.jsx index 780d60c6..86a1f7e5 100644 --- a/vite-project/src/components/item-detail/item-detail.jsx +++ b/vite-project/src/components/item-detail/item-detail.jsx @@ -21,7 +21,7 @@ const StyledItemDetail = styled.div` } `; -const StyledItemDetailImage = styled.div` +const ItemImage = styled.div` width: 486px; height: 486px; aspect-ratio: 1 / 1; @@ -44,11 +44,11 @@ const StyledItemDetailImage = styled.div` } `; -const StyledItemDetailInfo = styled.div` +const ItemInfo = styled.div` width: 100%; `; -const StyledItemDetailSections = styled.div` +const InfoSectionContainer = styled.div` display: flex; flex-direction: column; gap: 24px; @@ -59,7 +59,7 @@ const StyledItemDetailSections = styled.div` } `; -const StyledItemDetailProfileContainer = styled.div` +const ProfileContainer = styled.div` display: flex; justify-content: space-between; align-items: center; @@ -71,7 +71,7 @@ const StyledItemDetailProfileContainer = styled.div` } `; -const StyledItemDetailFavoriteContainer = styled.div` +const FavoriteContainer = styled.div` border-left: 1px solid var(--color-cool-gray-200); padding-left: 24px; `; @@ -86,12 +86,12 @@ function ItemDetail() { return product ? ( - + {product.images[0] && } - - + + - + - - + + - + - - - + + + ) : ( // TODO: Product loading 중 보여줄 UI From 9c59b120184ab3a53840d3ba406632cf43002e8a Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 5 Aug 2025 17:20:55 +0900 Subject: [PATCH 14/31] =?UTF-8?q?feat(Sprint7):=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20-=20=EC=83=81=ED=92=88=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EC=99=80=20comment=EB=A5=BC=20=EA=B5=AC=EB=B6=84?= =?UTF-8?q?=ED=95=98=EB=8A=94=20Separator=20component=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/item-comment/item-comment.jsx | 5 +++++ .../src/pages/items/item-detail-page.jsx | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 vite-project/src/components/item-comment/item-comment.jsx diff --git a/vite-project/src/components/item-comment/item-comment.jsx b/vite-project/src/components/item-comment/item-comment.jsx new file mode 100644 index 00000000..ca1b9e67 --- /dev/null +++ b/vite-project/src/components/item-comment/item-comment.jsx @@ -0,0 +1,5 @@ +function ItemComment() { + return

Comments

; +} + +export default ItemComment; diff --git a/vite-project/src/pages/items/item-detail-page.jsx b/vite-project/src/pages/items/item-detail-page.jsx index a26c98d0..2f9f1f1c 100644 --- a/vite-project/src/pages/items/item-detail-page.jsx +++ b/vite-project/src/pages/items/item-detail-page.jsx @@ -1,9 +1,27 @@ +import styled from "styled-components"; +import ItemComment from "../../components/item-comment/item-comment"; import ItemDetail from "../../components/item-detail/item-detail"; +const Separator = styled.div` + width: 100%; + border-bottom: 1px solid var(--color-cool-gray-200); + margin: 40px 0; + + @media (max-width: 1199px) { + margin-top: 32px; + } + + @media (max-width: 767px) { + margin: 24px 0; + } +`; + function ItemDetailPage() { return (
+ +
); } From cb8a160ce21935b92bc6a03e80fb5db627d24c9f Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 5 Aug 2025 17:34:13 +0900 Subject: [PATCH 15/31] =?UTF-8?q?feat(Sprint7):=20TextInput=20component?= =?UTF-8?q?=EC=9D=98=20multiline=20height=20=EC=84=A4=EC=A0=95=EC=9D=84=20?= =?UTF-8?q?`rows`=20=EA=B8=B0=EB=B0=98=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite-project/src/components/text-input.jsx | 3 +-- vite-project/src/pages/add-item/add-item-page.jsx | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vite-project/src/components/text-input.jsx b/vite-project/src/components/text-input.jsx index 986e0316..8a3c79c2 100644 --- a/vite-project/src/components/text-input.jsx +++ b/vite-project/src/components/text-input.jsx @@ -24,7 +24,6 @@ const StyledTextInput = styled.div` background-color: var(--color-secondary-100); padding: 16px 24px; border-radius: 12px; - ${({ $multiline }) => ($multiline ? "height: 282px;" : "")} input { ${inputStyle} @@ -51,7 +50,7 @@ const StyledTextInput = styled.div` function TextInput({ multiline = false, ...props }) { return ( - + {multiline ?