diff --git a/package-lock.json b/package-lock.json
index a730a528..c79f83ed 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,7 +14,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
- "react-router-dom": "^7.9.5",
+ "react-router-dom": "^6.30.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}
@@ -3073,6 +3073,15 @@
}
}
},
+ "node_modules/@remix-run/router": {
+ "version": "1.23.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz",
+ "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -13878,50 +13887,35 @@
}
},
"node_modules/react-router": {
- "version": "7.9.5",
- "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.5.tgz",
- "integrity": "sha512-JmxqrnBZ6E9hWmf02jzNn9Jm3UqyeimyiwzD69NjxGySG6lIz/1LVPsoTCwN7NBX2XjCEa1LIX5EMz1j2b6u6A==",
+ "version": "6.30.1",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.1.tgz",
+ "integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==",
"license": "MIT",
"dependencies": {
- "cookie": "^1.0.1",
- "set-cookie-parser": "^2.6.0"
+ "@remix-run/router": "1.23.0"
},
"engines": {
- "node": ">=20.0.0"
+ "node": ">=14.0.0"
},
"peerDependencies": {
- "react": ">=18",
- "react-dom": ">=18"
- },
- "peerDependenciesMeta": {
- "react-dom": {
- "optional": true
- }
+ "react": ">=16.8"
}
},
"node_modules/react-router-dom": {
- "version": "7.9.5",
- "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.9.5.tgz",
- "integrity": "sha512-mkEmq/K8tKN63Ae2M7Xgz3c9l9YNbY+NHH6NNeUmLA3kDkhKXRsNb/ZpxaEunvGo2/3YXdk5EJU3Hxp3ocaBPw==",
+ "version": "6.30.1",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.1.tgz",
+ "integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==",
"license": "MIT",
"dependencies": {
- "react-router": "7.9.5"
+ "@remix-run/router": "1.23.0",
+ "react-router": "6.30.1"
},
"engines": {
- "node": ">=20.0.0"
+ "node": ">=14.0.0"
},
"peerDependencies": {
- "react": ">=18",
- "react-dom": ">=18"
- }
- },
- "node_modules/react-router/node_modules/cookie": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
- "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
}
},
"node_modules/react-scripts": {
@@ -14818,12 +14812,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/set-cookie-parser": {
- "version": "2.7.2",
- "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
- "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
- "license": "MIT"
- },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
diff --git a/package.json b/package.json
index c799bed6..cb5106ac 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
- "react-router-dom": "^7.9.5",
+ "react-router-dom": "^6.30.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
diff --git a/src/App.js b/src/App.js
index 12193c73..73514c01 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,17 +1,28 @@
-import { BrowserRouter, Routes, Route } from "react-router-dom";
import React from "react";
+import { BrowserRouter, Routes, Route } from "react-router-dom";
import Main from "./pages/Main";
-import Login from "./pages/Login";
-import SignUp from "./pages/SignUp";
-import Market from "./pages/Market"
+import MarketPage from "./pages/MarketPage/MarketPage";
+import Login from "./pages/login/Login";
+import SignUp from "./pages/signup/SignUp";
+import Item from "./pages/item/Item";
+import Privacy from "./pages/privacy/Privacy";
+import Faq from "./pages/faq/Faq";
+import RegistrationPage from "./pages/registration/RegistrationPage";
+import ProductDetailPage from "./pages/product/ProductDetailPage";
+
function App() {
return (
- } />
- } />
- {/* } /> */}
- {/* } /> */}
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
);
diff --git a/src/api/itemApi.js b/src/api/itemApi.js
new file mode 100644
index 00000000..5e4c5af7
--- /dev/null
+++ b/src/api/itemApi.js
@@ -0,0 +1,40 @@
+export async function getProducts(params = {}) {
+ const query = new URLSearchParams(params).toString();
+
+ try {
+ const response = await fetch(
+ ` https://panda-market-api.vercel.app/docs/products?${query}`
+ );
+ if (!response.ok) {
+ throw new Error(`HTTP error: ${response.status}`);
+ }
+ const body = await response.json();
+ return body;
+ } catch (error) {
+ console.error("Failed to fetch products:", error);
+ throw error;
+ }
+}
+
+export async function createProduct(productData) {
+ try {
+ const response = await fetch(
+ `https://panda-market-api.vercel.app/docs/products`,
+ {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(productData),
+ }
+ );
+ if (!response.ok) {
+ throw new Error(`HTTP error: ${response.status}`);
+ }
+ const body = await response.json();
+ return body;
+ } catch (error) {
+ console.error("Failed to create product:", error);
+ throw error;
+ }
+}
diff --git a/src/assets/Matket/defaultImg.svg b/src/assets/Matket/defaultImg.svg
new file mode 100644
index 00000000..1f155779
--- /dev/null
+++ b/src/assets/Matket/defaultImg.svg
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/images/icons/arrow_left.svg b/src/assets/images/icons/arrow_left.svg
new file mode 100644
index 00000000..2a9de23a
--- /dev/null
+++ b/src/assets/images/icons/arrow_left.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/assets/images/icons/arrow_right.svg b/src/assets/images/icons/arrow_right.svg
new file mode 100644
index 00000000..daa483c3
--- /dev/null
+++ b/src/assets/images/icons/arrow_right.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/assets/images/icons/ic_arrow_down.svg b/src/assets/images/icons/ic_arrow_down.svg
new file mode 100644
index 00000000..8308690f
--- /dev/null
+++ b/src/assets/images/icons/ic_arrow_down.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/assets/images/icons/ic_heart.svg b/src/assets/images/icons/ic_heart.svg
new file mode 100644
index 00000000..cad016c1
--- /dev/null
+++ b/src/assets/images/icons/ic_heart.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/assets/images/icons/ic_search.svg b/src/assets/images/icons/ic_search.svg
new file mode 100644
index 00000000..52241e6d
--- /dev/null
+++ b/src/assets/images/icons/ic_search.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/assets/images/icons/ic_sort_mobile.svg b/src/assets/images/icons/ic_sort_mobile.svg
new file mode 100644
index 00000000..657b44f9
--- /dev/null
+++ b/src/assets/images/icons/ic_sort_mobile.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/assets/images/logo/logo.svg b/src/assets/images/logo/logo.svg
new file mode 100644
index 00000000..d497acbf
--- /dev/null
+++ b/src/assets/images/logo/logo.svg
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Constants.js b/src/components/Constants.js
index c0b6f608..f8b31cf4 100644
--- a/src/components/Constants.js
+++ b/src/components/Constants.js
@@ -6,3 +6,5 @@ const USER_DATA = [
{ email: "codeit5@codeit.com", password: "codeit505!" },
{ email: "codeit6@codeit.com", password: "codeit606!" },
];
+
+export default USER_DATA;
diff --git a/src/components/Errormodals.js b/src/components/Errormodals.js
deleted file mode 100644
index 8e29acb6..00000000
--- a/src/components/Errormodals.js
+++ /dev/null
@@ -1,25 +0,0 @@
-document.addEventListener("DOMContentLoaded", () => {
- const errorModal = document.getElementById("error-modal");
- const modalMessage = document.getElementById("modal-message");
- const confirmButton = document.getElementById("confirm-button");
-
-
- function showModal(message, url = null) {
- console.log(url);
- modalMessage.textContent = message;
- errorModal.style.display = "block";
- redirectUrl = url;
- }
-
- function closeModal() {
- errorModal.style.display = "none";
- if (redirectUrl) {
- window.location.href = redirectUrl;
- }
- }
-
- confirmButton.addEventListener("click", closeModal);
-
- window.showModal = showModal;
- console.log(USER_DATA);
-});
diff --git a/src/components/Layout/Header.css b/src/components/Layout/Header.css
new file mode 100644
index 00000000..1d0c90d7
--- /dev/null
+++ b/src/components/Layout/Header.css
@@ -0,0 +1,49 @@
+.headerLeft {
+ display: flex;
+ align-items: center;
+}
+
+.headerLogo {
+ margin-right: 16px;
+}
+
+.globalHeader nav ul {
+ display: flex;
+ list-style: none;
+ gap: 8px;
+ font-weight: bold;
+ font-size: 16px;
+ color: #4b5563;
+}
+
+.globalHeader nav ul li:hover {
+ color: var(--blue);
+}
+
+.globalHeader nav ul li.active a {
+ color: #3692ff;
+}
+
+.loginLink {
+ font-size: 16px;
+ font-weight: 600;
+ border-radius: 8px;
+ padding: 11.5px 23px;
+}
+
+@media (min-width: 744px) {
+ .globalHeader nav ul {
+ gap: 36px;
+ font-size: 18px;
+ }
+
+ .headerLogo {
+ margin-right: 35px;
+ }
+}
+
+@media (min-width: 1280px) {
+ .headerLogo {
+ margin-right: 47px;
+ }
+}
diff --git a/src/components/Layout/Header.jsx b/src/components/Layout/Header.jsx
new file mode 100644
index 00000000..7c105fdf
--- /dev/null
+++ b/src/components/Layout/Header.jsx
@@ -0,0 +1,43 @@
+import React from "react";
+import Logo from "../../assets/images/logo/logo.svg";
+import "./Header.css";
+import { Link, useLocation } from "react-router-dom";
+
+function Header() {
+ const location = useLocation();
+ const isItemsPage = location.pathname === "/items";
+
+ return (
+
+
+
+
+
+
+
+
+ 자유게시판
+
+
+
+ 중고마켓
+
+
+
+
+
+
+
+ 로그인
+
+
+
+ );
+}
+
+export default Header;
diff --git a/src/components/UI/DropdownList.css b/src/components/UI/DropdownList.css
new file mode 100644
index 00000000..4d25cf91
--- /dev/null
+++ b/src/components/UI/DropdownList.css
@@ -0,0 +1,29 @@
+.dropdownList {
+ position: absolute;
+ top: 110%;
+ right: 0;
+ background: #fff;
+ border-radius: 8px;
+ border: 1px solid #e5e7eb;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ z-index: 99;
+}
+
+.dropdownItem {
+ width: 100%;
+ padding: 12px 44px;
+ border-bottom: 1px solid #e5e7eb;
+ font-size: 16px;
+ color: #1f2937;
+ cursor: pointer;
+ background-color: transparent;
+ text-align: left;
+}
+
+.dropdownItem:last-child {
+ border-bottom: none;
+}
+
+.dropdownItem:hover {
+ background-color: #f3f4f6;
+}
diff --git a/src/components/UI/DropdownList.jsx b/src/components/UI/DropdownList.jsx
new file mode 100644
index 00000000..b2985613
--- /dev/null
+++ b/src/components/UI/DropdownList.jsx
@@ -0,0 +1,25 @@
+import React from "react";
+import "./DropdownList.css";
+
+function DropdownList({ onSortSelection }) {
+ return (
+
+ onSortSelection("recent")}
+ >
+ 최신순
+
+ onSortSelection("favorite")}
+ >
+ 인기순
+
+
+ );
+}
+
+export default DropdownList;
diff --git a/src/components/UI/PaginationBar.css b/src/components/UI/PaginationBar.css
new file mode 100644
index 00000000..8c5975cb
--- /dev/null
+++ b/src/components/UI/PaginationBar.css
@@ -0,0 +1,30 @@
+.paginationBar {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 4px;
+}
+
+.paginationButton {
+ border: 1px solid #e5e7eb;
+ border-radius: 50%;
+ width: 40px;
+ height: 40px;
+ color: #6b7280;
+ font-weight: 600;
+ font-size: 16px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: #fff;
+}
+
+.paginationButton:disabled {
+ cursor: default;
+ opacity: 0.5;
+}
+
+.paginationButton.active {
+ background-color: var(--blue);
+ color: #fff;
+}
diff --git a/src/components/UI/PaginationBar.jsx b/src/components/UI/PaginationBar.jsx
new file mode 100644
index 00000000..3bcffdaf
--- /dev/null
+++ b/src/components/UI/PaginationBar.jsx
@@ -0,0 +1,59 @@
+import React from "react";
+import "./PaginationBar.css";
+import { ReactComponent as LeftArrow } from "../../assets/images/icons/arrow_left.svg";
+import { ReactComponent as RightArrow } from "../../assets/images/icons/arrow_right.svg";
+
+function PaginationBar({ totalPageNum = 1, activePageNum = 1, onPageChange }) {
+ const maxVisiblePages = 5;
+ let startPage;
+
+ if (totalPageNum <= maxVisiblePages) {
+ startPage = 1;
+ } else {
+ startPage = Math.max(activePageNum - Math.floor(maxVisiblePages / 2), 1);
+ startPage = Math.min(startPage, totalPageNum - maxVisiblePages + 1);
+ }
+
+ const pages = Array.from(
+ { length: Math.min(maxVisiblePages, totalPageNum - startPage + 1) },
+ (_, index) => startPage + index
+ );
+
+ return (
+
+ onPageChange(activePageNum - 1)}
+ aria-label="이전 페이지"
+ >
+
+
+ {pages.map((page) => (
+ onPageChange(page)}
+ aria-current={activePageNum === page ? "page" : undefined}
+ >
+ {page}
+
+ ))}
+ onPageChange(activePageNum + 1)}
+ aria-label="다음 페이지"
+ >
+
+
+
+ );
+}
+
+export default PaginationBar;
diff --git a/src/styles/modal.css b/src/components/modal/modal.css
similarity index 100%
rename from src/styles/modal.css
rename to src/components/modal/modal.css
diff --git a/src/index.js b/src/index.js
index 895d8184..b391783d 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,12 +1,11 @@
-import React from 'react';
-import ReactDOM from 'react-dom/client';
-import App from './App';
-import "./styles/global.css"
+import React from "react";
+import ReactDOM from "react-dom/client";
+import App from "./App";
+import "./styles/global.css";
-const root = ReactDOM.createRoot(document.getElementById('root'));
+const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
);
-
diff --git a/src/pages/Item.js b/src/pages/Item.js
deleted file mode 100644
index a6a6beec..00000000
--- a/src/pages/Item.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import { useEffect, useMemo, useState } from "react";
-import '../styles/item.css'
-
-export default function Item() {
- const
-}
\ No newline at end of file
diff --git a/src/pages/Login.js b/src/pages/Login.js
deleted file mode 100644
index 75e4f501..00000000
--- a/src/pages/Login.js
+++ /dev/null
@@ -1,236 +0,0 @@
-import React, { useEffect, useMemo, useState } from "react";
-import "../styles/auth.css"
-import "../styles/modal.css"
-import USER_DATA from "../components/Constants"
-//로고
-import logo from "../assets/logo/logo.svg";
-import googleLogo from "../assets/social/google-logo.png";
-import kakaoLogo from "../assets/social/kakao-logo.png";
-import eyeInvisible from "../assets/icons/eye-invisible.svg";
-import eyeVisible from "../assets/icons/eye-visible.svg";
-import { Link } from "react-router-dom";
-
-const errors = {
- passwordMismatch: "이메일 또는 비밀번호가 일치하지 않습니다.",
- emailExists: "이미 가입된 이메일입니다."
-};
-
-export default function Login() {
- const [email, setEamil] = useState("");
- const [password, setPassword] = useState("");
-
- const [isEmailValid, setIsEmailValid] = useState(false);
- const [isPasswordValid, setIsPasswordInvalid] = useState(false);
-
- const [showEmailEmpty, setShowEmailEmpty] = useState(false);
- const [showEmailInvalid, setShowEmailInvalid] = useState(false);
- const [showPasswordEmpty, setShowPasswordEmpty] = useState(false);
- const [showPasswordShort, setShowPasswordShort] = useState(false);
-
- const [showPassword, setShowPassword] = useState(false);
-
- const [modalOpen, setModalOpen] = useState(false);
- const [modalMessage, setModalMessage] = useState("");
- const [modalConfirmHref, setModalConfirmHref] = useState("");
-
- const isFormValid = useMemo(
- () => isEmailValid && isPasswordValid,
- [isEmailValid, isPasswordValid]
- );
-
- const validateEmailString = (value) => {
- const emailRegex = /^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/;
- return emailRegex.test(value);
- };
-
- const checkEmailValidity = () => {
- const v = email.trim();
- setIsEmailValid(false);
- setShowEmailEmpty(false);
- setShowEmailInvalid(false);
-
- if (!v) {
- setShowEmailEmpty(true);
- } else if (!validateEmailString(v)) {
- setShowEmailInvalid(true);
- } else {
- setIsEmailValid(true);
- }
- };
-
- const checkPasswordValidity = () => {
- const v = password.trim();
- setIsPasswordInvalid(false);
- setShowPasswordEmpty(false);
- setShowPasswordShort(false);
-
- if (!v) {
- setShowPasswordEmpty(true);
- } else if (v.length < 8) {
- setShowPasswordShort(true);
- } else {
- setIsPasswordInvalid(true);
- }
- };
-
- useEffect(() => {
- checkEmailValidity();
- checkPasswordValidity();
- }, []);
-
- const showModal = (message, confirmHref = "") => {
- setModalMessage(message);
- setModalConfirmHref(confirmHref);
- setModalOpen(true);
- };
-
- const closeModal = () => {
- setModalOpen(false);
- setModalMessage("");
- setModalConfirmHref("");
- };
-
- const handleModalConfirm = () => {
- if (modalConfirmHref) {
- window.location.href = modalConfirmHref;
- } else {
- closeModal();
- }
- }
-
- const onSubmit = (e) => {
- e.preventDefault();
- checkEmailValidity();
- checkPasswordValidity();
- if (!isFormValid) return;
-
- const user = USER_DATA.find((u) => u.email === email.trim());
- if (!user || user.password !== password.trim()) {
- showModal(errors.passwordMismatch, "/src/pages/SignUp.js");
- } else {
- window.location.href = "./Items.js";
- }
- };
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
- {modalOpen && (
-
-
-
{modalMessage}
-
- 확인
-
-
-
- )}
- >
- );
-}
\ No newline at end of file
diff --git a/src/pages/Main.js b/src/pages/Main.js
index 13e8e100..7ecfbbe9 100644
--- a/src/pages/Main.js
+++ b/src/pages/Main.js
@@ -1,7 +1,7 @@
import React from "react";
-import "../styles/home.css"
-// 이미지
-import logo from "../assets/logo/logo.svg"
+import "../styles/home.css";
+import { Link } from "react-router-dom";
+import logo from "../assets/logo/logo.svg";
import feature1 from "../assets/home/feature1-image.png";
import feature2 from "../assets/home/feature2-image.png";
import feature3 from "../assets/home/feature3-image.png";
@@ -9,96 +9,96 @@ import facebookIcon from "../assets/social/facebook-logo.svg";
import twitterIcon from "../assets/social/twitter-logo.svg";
import youtubeIcon from "../assets/social/youtube-logo.svg";
import instagramIcon from "../assets/social/instagram-logo.svg";
-import { Link } from "react-router-dom";
-import Login from "./Login";
-export default function Main () {
+export default function Main() {
return (
<>
-
-
-
-
+
+
+
+
+
+ 로그인
+
+
-
-
-
-
-
Hot item
+
+
+
- 인기 상품을
- 확인해보세요
-
-
- 가장 HOT한 중고거래 물품을
+ 일상의 모든 물건을
- 판다마켓에서 확인해 보세요
-
+ 거래해 보세요
+
+
+ 구경하러가기
+
-
+
-
-
-
-
Search
-
- 구매를 원하는
- 상품을 검색하세요
-
-
- 구매하고 싶은 물품은 검색해서
-
- 쉽게 찾아보세요
-
+
+
+
+
+
Hot item
+
+ 인기 상품을
+ 확인해보세요
+
+
+ 가장 HOT한 중고거래 물품을
+
+ 판다마켓에서 확인해 보세요
+
+
-
-
-
-
-
Register
+
+
+
+
Search
+
+ 구매를 원하는
+ 상품을 검색하세요
+
+
+ 구매하고 싶은 물품은 검색해서
+
+ 쉽게 찾아보세요
+
+
+
+
+
+
+
+
Register
+
+ 판매를 원하는
+ 상품을 등록하세요
+
+
+ 어떤 물건이든 판매하고 싶은 상품을
+
+ 쉽게 등록하세요
+
+
+
+
+
+
+
- 판매를 원하는
- 상품을 등록하세요
-
-
- 어떤 물건이든 판매하고 싶은 상품을
+ 믿을 수 있는
- 쉽게 등록하세요
-
+ 판다마켓 중고거래
+
-
-
+
+
-
-
-
- 믿을 수 있는
-
- 판다마켓 중고거래
-
-
-
-
-
-