diff --git a/.gitignore b/.gitignore
index 4d29575d..26d11f4a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
-# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+node_modules
# dependencies
/node_modules
@@ -21,3 +22,4 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
+
diff --git a/src/App.js b/src/App.js
index d9fe58ce..b7283cd0 100644
--- a/src/App.js
+++ b/src/App.js
@@ -3,6 +3,7 @@ import Header from "./components/Header";
import HomePage from "./pages/Homepage/HomePage";
import CommunityPage from "./pages/CommunityPage/CommunityPage";
import ProductsPage from "./pages/ProductsPage/ProductsPage";
+import AddItemPage from "./pages/AddItemPage/AddItemPage";
import LoginPage from "./pages/LoginPage/LoginPage";
function App() {
@@ -14,6 +15,7 @@ function App() {
} />
} />
} />
+ } />
} />
diff --git a/src/api.js b/src/api.js
index 1d81755a..784c169d 100644
--- a/src/api.js
+++ b/src/api.js
@@ -10,3 +10,16 @@ export async function getProducts(params = {}) {
const body = await response.json();
return body;
}
+
+
+export async function postProducts(data) {
+ const response = await fetch(`${BASE_URL}/products`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(data),
+ });
+
+ if (!response.ok) throw new Error("상품 등록 실패");
+
+ return await response.json();
+}
diff --git a/src/assets/X.png b/src/assets/X.png
new file mode 100644
index 00000000..009ff15c
Binary files /dev/null and b/src/assets/X.png differ
diff --git a/src/assets/plus.png b/src/assets/plus.png
new file mode 100644
index 00000000..df2fb448
Binary files /dev/null and b/src/assets/plus.png differ
diff --git a/src/components/Header.css b/src/components/Header.css
index 33a07c69..ff554b75 100644
--- a/src/components/Header.css
+++ b/src/components/Header.css
@@ -8,6 +8,11 @@
align-items: center;
}
+
+.logo img {
+ display: none;
+}
+
.logo {
display: flex;
justify-content: center;
@@ -42,6 +47,11 @@
}
@media (min-width: 768px) {
+
+ .logo img {
+ display: block;
+ }
+
.logo a {
font-size: 25.63px;
}
diff --git a/src/pages/AddItemPage/AddItemPage.jsx b/src/pages/AddItemPage/AddItemPage.jsx
new file mode 100644
index 00000000..fcee6a04
--- /dev/null
+++ b/src/pages/AddItemPage/AddItemPage.jsx
@@ -0,0 +1,202 @@
+import { useRef, useState } from "react";
+import "./additem.css";
+import { postProducts } from "../../api";
+import plus from "../../assets/plus.png";
+import xbtn from "../../assets/X.png";
+
+function AddItemPage() {
+ const [newItem, setNewItem] = useState({
+ images: null,
+ tagInput: "",
+ tags: [],
+ price: "",
+ description: "",
+ name: "",
+ });
+
+ const [imageAlert, setImageAlert] = useState("");
+ const fileInputRef = useRef(null);
+
+ const handleInputChange = (field, value) => {
+ setNewItem((prev) => ({ ...prev, [field]: value }));
+ };
+
+ const handleTagKeyDown = (e) => {
+ if (e.key === "Enter" && newItem.tagInput.trim() !== "") {
+ e.preventDefault();
+ const newTag = newItem.tagInput.trim();
+ if (!newItem.tags.includes(newTag)) {
+ setNewItem((prev) => ({
+ ...prev,
+ tags: [...prev.tags, newTag],
+ tagInput: "",
+ }));
+ }
+ }
+ };
+
+ const handleRemoveTag = (tagToRemove) => {
+ setNewItem((prev) => ({
+ ...prev,
+ tags: prev.tags.filter((tag) => tag !== tagToRemove),
+ }));
+ };
+
+ const handleImageClick = () => {
+ if (newItem.images) {
+ setImageAlert(`*이미지 등록은 최대 1개까지 가능합니다.`);
+ return;
+ }
+ fileInputRef.current.click();
+ };
+
+ const handleCreateItem = async () => {
+ const itemData = {
+ images: newItem.images,
+ tags: newItem.tags,
+ price: newItem.price,
+ description: newItem.description,
+ name: newItem.name,
+ };
+
+ const result = await postProducts(itemData);
+
+ if (result) {
+ setNewItem({
+ images: null,
+ tags: [],
+ price: "",
+ description: "",
+ name: "",
+ });
+ }
+ };
+
+ const isFormValid =
+ newItem.name.trim() !== "" &&
+ newItem.description.trim() !== "" &&
+ newItem.price !== "" &&
+ newItem.tags.length > 0;
+
+ return (
+ <>
+
+
+
상품 등록하기
+
+
+
+
+
상품 이미지
+
+
+ {newItem.images && (
+
+
})
+
+
+ )}
+
+ {imageAlert &&
{imageAlert}
}
+
+
+
상품명
+ handleInputChange("name", e.target.value)}
+ className="item__input"
+ placeholder="상품명을 입력해주세요"
+ />
+
+
+
상품 소개
+
+
+
판매 가격
+ handleInputChange("price", e.target.value)}
+ className="item__input"
+ placeholder="판매 가격을 입력해주세요"
+ />
+
+
+
태그
+
+
handleInputChange("tagInput", e.target.value)}
+ onKeyDown={handleTagKeyDown}
+ className="item__input"
+ placeholder="태그를 입력해주세요"
+ />
+
+ {newItem.tags.map((tag) => (
+
+
#{tag}
+
+
+ ))}
+
+
+
+
+
+ >
+ );
+}
+
+export default AddItemPage;
diff --git a/src/pages/AddItemPage/additem.css b/src/pages/AddItemPage/additem.css
new file mode 100644
index 00000000..74c766df
--- /dev/null
+++ b/src/pages/AddItemPage/additem.css
@@ -0,0 +1,205 @@
+h2 {
+ font-size: var(--text-lg);
+}
+
+.item__container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: space-between;
+ gap: 24px;
+ padding: 15px;
+}
+
+.item__register {
+ width: 345px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.item__info {
+ width: 345px;
+ display: flex;
+ flex-direction: column;
+ gap: 24px;
+}
+
+.item__image {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+}
+
+.item__register--button {
+ width: 74px;
+ height: 42px;
+ background-color: #9ca3af;
+ color: #ffffff;
+ font-size: var(--text-base);
+ border-radius: 8px;
+ border: none;
+ padding: 12px 23px;
+}
+
+.item__register--button.active {
+ background-color: #3692ff;
+ cursor: pointer;
+}
+
+.item__image-wrapper {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.item__image-upload {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ width: 168px;
+ height: 168px;
+ background-color: #f3f4f6;
+ border-radius: 12px;
+ border: none;
+ padding: 42px 47px;
+ font-size: var(--text-base);
+ color: #9ca3af;
+ cursor: pointer;
+}
+
+.item__image-plus {
+ width: 48px;
+ height: 48px;
+}
+
+.item__image-preview {
+ position: relative;
+ width: 168px;
+ height: 168px;
+ border-radius: 12px;
+ border: none;
+ overflow: hidden;
+}
+
+.item__image-preview img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.item__delete {
+ position: absolute;
+ top: 6px;
+ right: 6px;
+ width: 22px;
+ height: 22px;
+ cursor: pointer;
+ background-color: rgba(0, 0, 0, 0);
+ border-radius: 50%;
+ border: none;
+}
+
+.item__alert {
+ color: #f74747;
+ font-size: var(--text-base);
+}
+
+.item__name,
+.item__description,
+.item__price,
+.item__tags {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+}
+
+.item__input {
+ width: 100%;
+ height: 56px;
+ background-color: #f3f4f6;
+ border-radius: 12px;
+ border: none;
+ padding: 16px 24px;
+ font-size: var(--text-base);
+}
+
+input[type="number"]::-webkit-outer-spin-button,
+input[type="number"]::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+
+.item__textarea {
+ width: 100%;
+ height: 282px;
+ background-color: #f3f4f6;
+ border-radius: 12px;
+ border: none;
+ padding: 16px 24px;
+ font-size: var(--text-base);
+}
+
+.item__tag {
+ display: flex;
+ flex-direction: column;
+ gap: 14px;
+}
+
+.item__tag-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+}
+
+.item__tag-hash {
+ height: 36px;
+ display: flex;
+ align-items: center;
+ background-color: #f3f4f6;
+ border-radius: 26px;
+ border: none;
+ padding: 6px 12px;
+ gap: 10px;
+ font-size: var(--text-base);
+}
+.item__tag-hash .item__delete {
+ position: static;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+@media (min-width: 768px) {
+ .item__container {
+ padding: 15px 24px;
+ }
+ .item__register {
+ width: 696px;
+ }
+ .item__info {
+ width: 696px;
+ }
+}
+@media (min-width: 1280px) {
+ .item__container {
+ padding: 24px 360px;
+ }
+ .item__register {
+ width: 1200px;
+ }
+ .item__info {
+ width: 1200px;
+ }
+ .item__image-wrapper {
+ gap: 24px;
+ }
+ .item__image-upload {
+ width: 282px;
+ height: 282px;
+ }
+ .item__image-preview {
+ width: 282px;
+ height: 282px;
+ }
+}