diff --git a/sprint-mission5/src/Main.js b/sprint-mission5/src/Main.js
deleted file mode 100644
index 579cfb498..000000000
--- a/sprint-mission5/src/Main.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import { BrowserRouter, Routes, Route } from "react-router-dom";
-import App from "./components/App";
-import ItemsPage from "./pages/ItemsPage";
-import AddProductPage from "./pages/AddProductPage";
-
-function Main() {
- return (
-
-
-
- } />
- } />
-
-
-
- );
-}
-
-export default Main;
diff --git a/sprint-mission5/src/api/api.js b/sprint-mission5/src/api/api.js
deleted file mode 100644
index 3d2672954..000000000
--- a/sprint-mission5/src/api/api.js
+++ /dev/null
@@ -1,34 +0,0 @@
-const BASE_URL = `https://panda-market-api.vercel.app`;
-
-export async function getProducts({
- page = "1",
- pageSize = "10",
- orderBy = "recent",
- keyword = "",
-}) {
- const query = `page=${page}&pageSize=${pageSize}&orderBy=${orderBy}&keyword=${keyword}`;
-
- try {
- const response = await fetch(`/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(formData) {
- const response = await fetch(`${BASE_URL}/products`, {
- method: "POST",
- body: formData,
- });
- if (!response.ok) {
- throw new Error("Failed to post products");
- }
- const body = await response.json();
- return body;
-}
diff --git a/sprint-mission5/src/components/ItemCard.jsx b/sprint-mission5/src/components/ItemCard.jsx
deleted file mode 100644
index 7437f0ce3..000000000
--- a/sprint-mission5/src/components/ItemCard.jsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import React from "react";
-import favoriteIcon from "../assets/Icon.png";
-
-function ItemCard({ item }) {
- return (
-
-
-
-
{item.name}
-
{item.price.toLocaleString()}원
-
-
- {item.favoriteCount}
-
-
-
- );
-}
-
-export default ItemCard;
diff --git a/sprint-mission5/.gitignore b/sprint-mission7/.gitignore
similarity index 100%
rename from sprint-mission5/.gitignore
rename to sprint-mission7/.gitignore
diff --git a/sprint-mission5/README.md b/sprint-mission7/README.md
similarity index 100%
rename from sprint-mission5/README.md
rename to sprint-mission7/README.md
diff --git a/sprint-mission7/eslint.config.mjs b/sprint-mission7/eslint.config.mjs
new file mode 100644
index 000000000..8b22a462d
--- /dev/null
+++ b/sprint-mission7/eslint.config.mjs
@@ -0,0 +1,20 @@
+import globals from "globals";
+import pluginJs from "@eslint/js";
+import pluginReact from "eslint-plugin-react";
+import airbnbHooks from "eslint-config-airbnb/hooks";
+
+/** @type {import('eslint').Linter.Config[]} */
+export default [
+ { files: ["**/*.{js,mjs,cjs,jsx}"] },
+ {
+ languageOptions: {
+ ecmaVersion: "latest",
+ sourceType: "module",
+ globals: globals.browser,
+ },
+ },
+ { rules: {} },
+ pluginJs.configs.recommended,
+ pluginReact.configs.flat.recommended,
+ airbnbHooks,
+];
diff --git a/sprint-mission5/package-lock.json b/sprint-mission7/package-lock.json
similarity index 96%
rename from sprint-mission5/package-lock.json
rename to sprint-mission7/package-lock.json
index d28976b9e..ac64a1d41 100644
--- a/sprint-mission5/package-lock.json
+++ b/sprint-mission7/package-lock.json
@@ -11,11 +11,22 @@
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
+ "@types/styled-components": "^5.1.34",
+ "eslint-config-airbnb": "^19.0.4",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.28.0",
- "react-scripts": "5.0.1",
+ "react-scripts": "^5.0.1",
+ "styled-components": "^6.1.13",
"web-vitals": "^2.1.4"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.16.0",
+ "eslint": "^8.57.1",
+ "eslint-plugin-react": "^7.37.2",
+ "globals": "^15.13.0",
+ "typescript": "^4.9.5",
+ "typescript-eslint": "^8.17.0"
}
},
"node_modules/@adobe/css-tools": {
@@ -175,19 +186,6 @@
"node": ">=6.9.0"
}
},
- "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz",
- "integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/helper-compilation-targets": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz",
@@ -244,13 +242,13 @@
}
},
"node_modules/@babel/helper-create-regexp-features-plugin": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz",
- "integrity": "sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==",
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz",
+ "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==",
"license": "MIT",
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.25.9",
- "regexpu-core": "^6.1.1",
+ "regexpu-core": "^6.2.0",
"semver": "^6.3.1"
},
"engines": {
@@ -383,19 +381,6 @@
"@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/helper-simple-access": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz",
- "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/helper-skip-transparent-expression-wrappers": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz",
@@ -1086,6 +1071,15 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-transform-classes/node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/@babel/plugin-transform-computed-properties": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz",
@@ -1180,12 +1174,11 @@
}
},
"node_modules/@babel/plugin-transform-exponentiation-operator": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz",
- "integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==",
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz",
+ "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9",
"@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
@@ -1336,14 +1329,13 @@
}
},
"node_modules/@babel/plugin-transform-modules-commonjs": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz",
- "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==",
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz",
+ "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-module-transforms": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-simple-access": "^7.25.9"
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -1807,9 +1799,9 @@
}
},
"node_modules/@babel/plugin-transform-typescript": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.9.tgz",
- "integrity": "sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==",
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.3.tgz",
+ "integrity": "sha512-6+5hpdr6mETwSKjmJUdYw0EIkATiQhnELWlE3kJFBwSg/BGIVwVaVbX+gOXBCdc7Ln1RXZxyWGecIXhUfnl7oA==",
"license": "MIT",
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.25.9",
@@ -1995,9 +1987,9 @@
}
},
"node_modules/@babel/preset-react": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.25.9.tgz",
- "integrity": "sha512-D3to0uSPiWE7rBrdIICCd0tJSIGpLaaGptna2+w7Pft5xMqLpA1sz99DK5TZ1TjGbdQ/VI1eCSZ06dv3lT4JOw==",
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.26.3.tgz",
+ "integrity": "sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw==",
"license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.25.9",
@@ -2077,6 +2069,15 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/traverse/node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/@babel/types": {
"version": "7.26.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz",
@@ -2382,6 +2383,27 @@
"postcss-selector-parser": "^6.0.10"
}
},
+ "node_modules/@emotion/is-prop-valid": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz",
+ "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==",
+ "license": "MIT",
+ "dependencies": {
+ "@emotion/memoize": "^0.8.1"
+ }
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
+ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==",
+ "license": "MIT"
+ },
+ "node_modules/@emotion/unitless": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
+ "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==",
+ "license": "MIT"
+ },
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
@@ -2478,12 +2500,13 @@
}
},
"node_modules/@eslint/js": {
- "version": "8.57.1",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
- "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
+ "version": "9.16.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz",
+ "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@humanwhocodes/config-array": {
@@ -3765,9 +3788,9 @@
}
},
"node_modules/@types/express-serve-static-core": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz",
- "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==",
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.2.tgz",
+ "integrity": "sha512-vluaspfvWEtE4vcSDlKRNer52DvOGrB2xv6diXy6UKyKW0lqZiWHGNApSyxOv+8DE5Z27IzVvE7hNkxg7EXIcg==",
"license": "MIT",
"dependencies": {
"@types/node": "*",
@@ -3797,6 +3820,16 @@
"@types/node": "*"
}
},
+ "node_modules/@types/hoist-non-react-statics": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz",
+ "integrity": "sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
"node_modules/@types/html-minifier-terser": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
@@ -4186,6 +4219,23 @@
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
"license": "MIT"
},
+ "node_modules/@types/styled-components": {
+ "version": "5.1.34",
+ "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.34.tgz",
+ "integrity": "sha512-mmiVvwpYklFIv9E8qfxuPyIt/OuyIrn6gMOAMOFUO3WJfSrSE+sGUoa4PiZj77Ut7bKZpaa6o1fBKS/4TOEvnA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hoist-non-react-statics": "*",
+ "@types/react": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/stylis": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz",
+ "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==",
+ "license": "MIT"
+ },
"node_modules/@types/testing-library__jest-dom": {
"version": "5.14.9",
"resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz",
@@ -5703,6 +5753,15 @@
"node": ">= 6"
}
},
+ "node_modules/camelize": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
+ "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/caniuse-api": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
@@ -6246,6 +6305,15 @@
"postcss": "^8.4"
}
},
+ "node_modules/css-color-keywords": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
+ "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/css-declaration-sorter": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz",
@@ -6395,6 +6463,17 @@
"integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==",
"license": "MIT"
},
+ "node_modules/css-to-react-native": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
+ "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==",
+ "license": "MIT",
+ "dependencies": {
+ "camelize": "^1.0.0",
+ "css-color-keywords": "^1.0.0",
+ "postcss-value-parser": "^4.0.2"
+ }
+ },
"node_modules/css-tree": {
"version": "1.0.0-alpha.37",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz",
@@ -7490,6 +7569,55 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/eslint-config-airbnb": {
+ "version": "19.0.4",
+ "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz",
+ "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==",
+ "license": "MIT",
+ "dependencies": {
+ "eslint-config-airbnb-base": "^15.0.0",
+ "object.assign": "^4.1.2",
+ "object.entries": "^1.1.5"
+ },
+ "engines": {
+ "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^7.32.0 || ^8.2.0",
+ "eslint-plugin-import": "^2.25.3",
+ "eslint-plugin-jsx-a11y": "^6.5.1",
+ "eslint-plugin-react": "^7.28.0",
+ "eslint-plugin-react-hooks": "^4.3.0"
+ }
+ },
+ "node_modules/eslint-config-airbnb-base": {
+ "version": "15.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz",
+ "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==",
+ "license": "MIT",
+ "dependencies": {
+ "confusing-browser-globals": "^1.0.10",
+ "object.assign": "^4.1.2",
+ "object.entries": "^1.1.5",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^7.32.0 || ^8.2.0",
+ "eslint-plugin-import": "^2.25.2"
+ }
+ },
+ "node_modules/eslint-config-airbnb-base/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
"node_modules/eslint-config-react-app": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz",
@@ -7877,6 +8005,15 @@
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
+ "node_modules/eslint/node_modules/@eslint/js": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
+ "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
"node_modules/eslint/node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -8132,9 +8269,9 @@
}
},
"node_modules/express": {
- "version": "4.21.1",
- "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
- "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
+ "version": "4.21.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
+ "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
@@ -8156,7 +8293,7 @@
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
- "path-to-regexp": "0.1.10",
+ "path-to-regexp": "0.1.12",
"proxy-addr": "~2.0.7",
"qs": "6.13.0",
"range-parser": "~1.2.1",
@@ -8171,6 +8308,10 @@
},
"engines": {
"node": ">= 0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
"node_modules/express/node_modules/debug": {
@@ -8888,12 +9029,16 @@
}
},
"node_modules/globals": {
- "version": "11.12.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
- "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "version": "15.13.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.13.0.tgz",
+ "integrity": "sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">=4"
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/globalthis": {
@@ -9073,6 +9218,21 @@
"he": "bin/he"
}
},
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "node_modules/hoist-non-react-statics/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "license": "MIT"
+ },
"node_modules/hoopy": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
@@ -10638,6 +10798,15 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
+ "node_modules/jest-runtime/node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/jest-serializer": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz",
@@ -11854,9 +12023,9 @@
}
},
"node_modules/nwsapi": {
- "version": "2.2.13",
- "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz",
- "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==",
+ "version": "2.2.16",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz",
+ "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==",
"license": "MIT"
},
"node_modules/object-assign": {
@@ -12277,9 +12446,9 @@
"license": "ISC"
},
"node_modules/path-to-regexp": {
- "version": "0.1.10",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
- "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
+ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
"license": "MIT"
},
"node_modules/path-type": {
@@ -12934,9 +13103,9 @@
}
},
"node_modules/postcss-load-config/node_modules/lilconfig": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
- "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
+ "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
"license": "MIT",
"engines": {
"node": ">=14"
@@ -13846,12 +14015,15 @@
}
},
"node_modules/psl": {
- "version": "1.13.0",
- "resolved": "https://registry.npmjs.org/psl/-/psl-1.13.0.tgz",
- "integrity": "sha512-BFwmFXiJoFqlUpZ5Qssolv15DMyc84gTBds1BjsV1BfXEo1UyyD7GsmN67n7J77uRhoSNW1AXtXKPLcBFQn9Aw==",
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
+ "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==",
"license": "MIT",
"dependencies": {
"punycode": "^2.3.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/lupomontero"
}
},
"node_modules/punycode": {
@@ -15096,6 +15268,12 @@
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"license": "ISC"
},
+ "node_modules/shallowequal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
+ "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==",
+ "license": "MIT"
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -15118,10 +15296,13 @@
}
},
"node_modules/shell-quote": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
- "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz",
+ "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==",
"license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -15646,12 +15827,12 @@
}
},
"node_modules/strip-bom": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
- "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
"license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">=4"
}
},
"node_modules/strip-comments": {
@@ -15712,6 +15893,68 @@
"webpack": "^5.0.0"
}
},
+ "node_modules/styled-components": {
+ "version": "6.1.13",
+ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.13.tgz",
+ "integrity": "sha512-M0+N2xSnAtwcVAQeFEsGWFFxXDftHUD7XrKla06QbpUMmbmtFBMMTcKWvFXtWxuD5qQkB8iU5gk6QASlx2ZRMw==",
+ "license": "MIT",
+ "dependencies": {
+ "@emotion/is-prop-valid": "1.2.2",
+ "@emotion/unitless": "0.8.1",
+ "@types/stylis": "4.2.5",
+ "css-to-react-native": "3.2.0",
+ "csstype": "3.1.3",
+ "postcss": "8.4.38",
+ "shallowequal": "1.1.0",
+ "stylis": "4.3.2",
+ "tslib": "2.6.2"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/styled-components"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0",
+ "react-dom": ">= 16.8.0"
+ }
+ },
+ "node_modules/styled-components/node_modules/postcss": {
+ "version": "8.4.38",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
+ "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/styled-components/node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "license": "0BSD"
+ },
"node_modules/stylehacks": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz",
@@ -15728,6 +15971,12 @@
"postcss": "^8.2.15"
}
},
+ "node_modules/stylis": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz",
+ "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==",
+ "license": "MIT"
+ },
"node_modules/sucrase": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
@@ -16011,9 +16260,9 @@
"license": "MIT"
},
"node_modules/tailwindcss": {
- "version": "3.4.15",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz",
- "integrity": "sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==",
+ "version": "3.4.16",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.16.tgz",
+ "integrity": "sha512-TI4Cyx7gDiZ6r44ewaJmt0o6BrMCT5aK5e0rmJ/G9Xq3w7CX/5VXl/zIPEJZFUK5VEqwByyhqNPycPlvcK4ZNw==",
"license": "MIT",
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
@@ -16025,7 +16274,7 @@
"glob-parent": "^6.0.2",
"is-glob": "^4.0.3",
"jiti": "^1.21.6",
- "lilconfig": "^2.1.0",
+ "lilconfig": "^3.1.3",
"micromatch": "^4.0.8",
"normalize-path": "^3.0.0",
"object-hash": "^3.0.0",
@@ -16047,6 +16296,18 @@
"node": ">=14.0.0"
}
},
+ "node_modules/tailwindcss/node_modules/lilconfig": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
+ "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antonk52"
+ }
+ },
"node_modules/tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
@@ -16112,9 +16373,9 @@
}
},
"node_modules/terser": {
- "version": "5.36.0",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz",
- "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==",
+ "version": "5.37.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz",
+ "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==",
"license": "BSD-2-Clause",
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
@@ -16309,6 +16570,19 @@
"integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==",
"license": "MIT"
},
+ "node_modules/ts-api-utils": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
+ "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
"node_modules/ts-interface-checker": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
@@ -16339,15 +16613,6 @@
"json5": "lib/cli.js"
}
},
- "node_modules/tsconfig-paths/node_modules/strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@@ -16509,7 +16774,6 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"license": "Apache-2.0",
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -16518,6 +16782,270 @@
"node": ">=4.2.0"
}
},
+ "node_modules/typescript-eslint": {
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.17.0.tgz",
+ "integrity": "sha512-409VXvFd/f1br1DCbuKNFqQpXICoTB+V51afcwG1pn1a3Cp92MqAUges3YjwEdQ0cMUoCIodjVDAYzyD8h3SYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.17.0",
+ "@typescript-eslint/parser": "8.17.0",
+ "@typescript-eslint/utils": "8.17.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.17.0.tgz",
+ "integrity": "sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "8.17.0",
+ "@typescript-eslint/type-utils": "8.17.0",
+ "@typescript-eslint/utils": "8.17.0",
+ "@typescript-eslint/visitor-keys": "8.17.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.3.1",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
+ "eslint": "^8.57.0 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": {
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.17.0.tgz",
+ "integrity": "sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.17.0",
+ "@typescript-eslint/types": "8.17.0",
+ "@typescript-eslint/typescript-estree": "8.17.0",
+ "@typescript-eslint/visitor-keys": "8.17.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.17.0.tgz",
+ "integrity": "sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.17.0",
+ "@typescript-eslint/visitor-keys": "8.17.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/type-utils": {
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.17.0.tgz",
+ "integrity": "sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "8.17.0",
+ "@typescript-eslint/utils": "8.17.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": {
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.17.0.tgz",
+ "integrity": "sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.17.0.tgz",
+ "integrity": "sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/types": "8.17.0",
+ "@typescript-eslint/visitor-keys": "8.17.0",
+ "debug": "^4.3.4",
+ "fast-glob": "^3.3.2",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": {
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.17.0.tgz",
+ "integrity": "sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@typescript-eslint/scope-manager": "8.17.0",
+ "@typescript-eslint/types": "8.17.0",
+ "@typescript-eslint/typescript-estree": "8.17.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.17.0.tgz",
+ "integrity": "sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.17.0",
+ "eslint-visitor-keys": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/eslint-visitor-keys": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
+ "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/unbox-primitive": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
@@ -16823,16 +17351,16 @@
}
},
"node_modules/webpack": {
- "version": "5.96.1",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz",
- "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==",
+ "version": "5.97.1",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz",
+ "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==",
"license": "MIT",
"dependencies": {
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.6",
- "@webassemblyjs/ast": "^1.12.1",
- "@webassemblyjs/wasm-edit": "^1.12.1",
- "@webassemblyjs/wasm-parser": "^1.12.1",
+ "@webassemblyjs/ast": "^1.14.1",
+ "@webassemblyjs/wasm-edit": "^1.14.1",
+ "@webassemblyjs/wasm-parser": "^1.14.1",
"acorn": "^8.14.0",
"browserslist": "^4.24.0",
"chrome-trace-event": "^1.0.2",
diff --git a/sprint-mission5/package.json b/sprint-mission7/package.json
similarity index 67%
rename from sprint-mission5/package.json
rename to sprint-mission7/package.json
index e24158432..99dca0897 100644
--- a/sprint-mission5/package.json
+++ b/sprint-mission7/package.json
@@ -6,13 +6,17 @@
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
+ "@types/styled-components": "^5.1.34",
+ "eslint-config-airbnb": "^19.0.4",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.28.0",
- "react-scripts": "5.0.1",
+ "react-scripts": "^5.0.1",
+ "styled-components": "^6.1.13",
"web-vitals": "^2.1.4"
},
"scripts": {
+ "lint": "eslint src/**/*.js",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
@@ -35,5 +39,13 @@
"last 1 firefox version",
"last 1 safari version"
]
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.16.0",
+ "eslint": "^8.57.1",
+ "eslint-plugin-react": "^7.37.2",
+ "globals": "^15.13.0",
+ "typescript": "^4.9.5",
+ "typescript-eslint": "^8.17.0"
}
}
diff --git a/sprint-mission5/public/index.html b/sprint-mission7/public/index.html
similarity index 100%
rename from sprint-mission5/public/index.html
rename to sprint-mission7/public/index.html
diff --git a/sprint-mission7/src/Main.js b/sprint-mission7/src/Main.js
new file mode 100644
index 000000000..bb66b8e9a
--- /dev/null
+++ b/sprint-mission7/src/Main.js
@@ -0,0 +1,25 @@
+import { BrowserRouter, Routes, Route } from "react-router-dom";
+import App from "./components/App";
+import ItemsPage from "./pages/ItemsPage";
+import HomePage from "./pages/HomePage";
+import ItemPage from "./pages/ItemPage";
+import AddProductPage from "./pages/AddProductPage";
+
+function Main() {
+ return (
+
+
+ }>
+ } />
+
+ } />
+ } />
+
+ } />
+
+
+
+ );
+}
+
+export default Main;
diff --git a/sprint-mission7/src/api/api.js b/sprint-mission7/src/api/api.js
new file mode 100644
index 000000000..f307b1dff
--- /dev/null
+++ b/sprint-mission7/src/api/api.js
@@ -0,0 +1,64 @@
+const BASE_URL = `https://panda-market-api.vercel.app`;
+
+export async function getProducts({
+ page = 1,
+ pageSize = 10,
+ orderBy = "recent",
+ keyword = "",
+}) {
+ const query = `page=${page}&pageSize=${pageSize}&orderBy=${orderBy}&keyword=${keyword}`;
+
+ try {
+ const response = await fetch(`${BASE_URL}/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(formData) {
+ const response = await fetch(`${BASE_URL}/products`, {
+ method: "POST",
+ body: formData,
+ });
+ if (!response.ok) {
+ throw new Error("Failed to post products");
+ }
+ const body = await response.json();
+ return body;
+}
+
+export async function getProductsById(itemId) {
+ try {
+ const response = await fetch(`${BASE_URL}/products/${itemId}`);
+ 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 getProductComment(itemId) {
+ try {
+ const response = await fetch(
+ `${BASE_URL}/products/${itemId}/comments?limit=3`
+ );
+ 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;
+ }
+}
diff --git a/sprint-mission5/src/assets/Component 2.png b/sprint-mission7/src/assets/Component 2.png
similarity index 100%
rename from sprint-mission5/src/assets/Component 2.png
rename to sprint-mission7/src/assets/Component 2.png
diff --git a/sprint-mission5/src/assets/Component 3.png b/sprint-mission7/src/assets/Component 3.png
similarity index 100%
rename from sprint-mission5/src/assets/Component 3.png
rename to sprint-mission7/src/assets/Component 3.png
diff --git a/sprint-mission5/src/assets/Group 19.png b/sprint-mission7/src/assets/Group 19.png
similarity index 100%
rename from sprint-mission5/src/assets/Group 19.png
rename to sprint-mission7/src/assets/Group 19.png
diff --git a/sprint-mission5/src/assets/Icon.png b/sprint-mission7/src/assets/Icon.png
similarity index 100%
rename from sprint-mission5/src/assets/Icon.png
rename to sprint-mission7/src/assets/Icon.png
diff --git a/sprint-mission5/src/assets/Img_home_01.png b/sprint-mission7/src/assets/Img_home_01.png
similarity index 100%
rename from sprint-mission5/src/assets/Img_home_01.png
rename to sprint-mission7/src/assets/Img_home_01.png
diff --git a/sprint-mission5/src/assets/Img_home_02.png b/sprint-mission7/src/assets/Img_home_02.png
similarity index 100%
rename from sprint-mission5/src/assets/Img_home_02.png
rename to sprint-mission7/src/assets/Img_home_02.png
diff --git a/sprint-mission5/src/assets/Img_home_03.png b/sprint-mission7/src/assets/Img_home_03.png
similarity index 100%
rename from sprint-mission5/src/assets/Img_home_03.png
rename to sprint-mission7/src/assets/Img_home_03.png
diff --git a/sprint-mission5/src/assets/Img_home_bottom.png b/sprint-mission7/src/assets/Img_home_bottom.png
similarity index 100%
rename from sprint-mission5/src/assets/Img_home_bottom.png
rename to sprint-mission7/src/assets/Img_home_bottom.png
diff --git a/sprint-mission5/src/assets/Img_home_top.png b/sprint-mission7/src/assets/Img_home_top.png
similarity index 100%
rename from sprint-mission5/src/assets/Img_home_top.png
rename to sprint-mission7/src/assets/Img_home_top.png
diff --git a/sprint-mission5/src/assets/Vector(1).png b/sprint-mission7/src/assets/Vector(1).png
similarity index 100%
rename from sprint-mission5/src/assets/Vector(1).png
rename to sprint-mission7/src/assets/Vector(1).png
diff --git a/sprint-mission5/src/assets/Vector(2).png b/sprint-mission7/src/assets/Vector(2).png
similarity index 100%
rename from sprint-mission5/src/assets/Vector(2).png
rename to sprint-mission7/src/assets/Vector(2).png
diff --git a/sprint-mission5/src/assets/Vector(3).png b/sprint-mission7/src/assets/Vector(3).png
similarity index 100%
rename from sprint-mission5/src/assets/Vector(3).png
rename to sprint-mission7/src/assets/Vector(3).png
diff --git a/sprint-mission5/src/assets/Vector.png b/sprint-mission7/src/assets/Vector.png
similarity index 100%
rename from sprint-mission5/src/assets/Vector.png
rename to sprint-mission7/src/assets/Vector.png
diff --git a/sprint-mission7/src/assets/arrow_left.svg b/sprint-mission7/src/assets/arrow_left.svg
new file mode 100644
index 000000000..2a9de23a6
--- /dev/null
+++ b/sprint-mission7/src/assets/arrow_left.svg
@@ -0,0 +1,3 @@
+
diff --git a/sprint-mission7/src/assets/arrow_right.svg b/sprint-mission7/src/assets/arrow_right.svg
new file mode 100644
index 000000000..daa483c3e
--- /dev/null
+++ b/sprint-mission7/src/assets/arrow_right.svg
@@ -0,0 +1,3 @@
+
diff --git a/sprint-mission5/src/assets/cancellIcon.png b/sprint-mission7/src/assets/cancellIcon.png
similarity index 100%
rename from sprint-mission5/src/assets/cancellIcon.png
rename to sprint-mission7/src/assets/cancellIcon.png
diff --git a/sprint-mission5/src/assets/ic_plus.png b/sprint-mission7/src/assets/ic_plus.png
similarity index 100%
rename from sprint-mission5/src/assets/ic_plus.png
rename to sprint-mission7/src/assets/ic_plus.png
diff --git a/sprint-mission5/src/assets/logo.png b/sprint-mission7/src/assets/logo.png
similarity index 100%
rename from sprint-mission5/src/assets/logo.png
rename to sprint-mission7/src/assets/logo.png
diff --git a/sprint-mission5/src/assets/panda_face.png b/sprint-mission7/src/assets/panda_face.png
similarity index 100%
rename from sprint-mission5/src/assets/panda_face.png
rename to sprint-mission7/src/assets/panda_face.png
diff --git a/sprint-mission5/src/assets/password.png b/sprint-mission7/src/assets/password.png
similarity index 100%
rename from sprint-mission5/src/assets/password.png
rename to sprint-mission7/src/assets/password.png
diff --git a/sprint-mission5/src/assets/userLogo.png b/sprint-mission7/src/assets/userLogo.png
similarity index 100%
rename from sprint-mission5/src/assets/userLogo.png
rename to sprint-mission7/src/assets/userLogo.png
diff --git a/sprint-mission5/src/components/AddProductForm.css b/sprint-mission7/src/components/AddProductForm.css
similarity index 100%
rename from sprint-mission5/src/components/AddProductForm.css
rename to sprint-mission7/src/components/AddProductForm.css
diff --git a/sprint-mission5/src/components/AddProductForm.jsx b/sprint-mission7/src/components/AddProductForm.jsx
similarity index 100%
rename from sprint-mission5/src/components/AddProductForm.jsx
rename to sprint-mission7/src/components/AddProductForm.jsx
diff --git a/sprint-mission5/src/components/Allproducts.jsx b/sprint-mission7/src/components/Allproducts.jsx
similarity index 63%
rename from sprint-mission5/src/components/Allproducts.jsx
rename to sprint-mission7/src/components/Allproducts.jsx
index ba87a1f58..e10bd8968 100644
--- a/sprint-mission5/src/components/Allproducts.jsx
+++ b/sprint-mission7/src/components/Allproducts.jsx
@@ -1,12 +1,25 @@
import React, { useEffect, useState } from "react";
+import { Link } from "react-router-dom";
import ItemCard from "./ItemCard";
import { getProducts } from "../api/api";
+import PaginationBar from "./PaginationBar";
import "./allItems.css";
+const getPageSize = () => {
+ const width = window.innerWidth;
+ if (width < 768) {
+ return 4;
+ } else if (width < 1280) {
+ return 6;
+ } else {
+ return 10;
+ }
+};
+
function AllProducts() {
- const [page, setPage] = useState("1");
+ const [page, setPage] = useState(1);
const [orderBy, setOrderBy] = useState("recent");
- const [pageSize, setPageSize] = useState("10");
+ const [pageSize, setPageSize] = useState(10);
const [itemList, setItemList] = useState([]);
const [keyword, setKeyword] = useState("");
const [totalPageNum, setTotalPageNum] = useState();
@@ -26,25 +39,27 @@ function AllProducts() {
setKeyword(e.target["search"].value);
};
- const getPageSize = () => {
- const width = window.innerWidth;
- if (width < 768) {
- return 4;
- } else if (width < 1280) {
- return 6;
- } else {
- return 10;
- }
+ const onPageChange = (pageNumber) => {
+ setPage(pageNumber);
};
useEffect(() => {
+ const handleResize = () => {
+ setPageSize(getPageSize());
+ };
+
+ window.addEventListener("resize", handleResize);
handleLoad({
orderBy,
- keyword,
page,
+ keyword,
+ pageSize,
});
- setPageSize(getPageSize());
- }, [orderBy, keyword, page, pageSize]);
+
+ return () => {
+ window.removeEventListener("resize", handleResize);
+ };
+ }, [orderBy, page, pageSize, keyword]);
return (
@@ -55,7 +70,7 @@ function AllProducts() {
-
상품 등록하기
+
상품 등록하기
@@ -65,6 +80,13 @@ function AllProducts() {
))}
+
);
}
diff --git a/sprint-mission5/src/components/App.jsx b/sprint-mission7/src/components/App.jsx
similarity index 53%
rename from sprint-mission5/src/components/App.jsx
rename to sprint-mission7/src/components/App.jsx
index d50f68037..d559a1192 100644
--- a/sprint-mission5/src/components/App.jsx
+++ b/sprint-mission7/src/components/App.jsx
@@ -1,11 +1,14 @@
+import { Outlet } from "react-router-dom";
import Nav from "../components/Nav";
import styles from "./App.module.css";
-function App({ children }) {
+function App() {
return (
<>
- {children}
+
+
+
>
);
}
diff --git a/sprint-mission5/src/components/App.module.css b/sprint-mission7/src/components/App.module.css
similarity index 66%
rename from sprint-mission5/src/components/App.module.css
rename to sprint-mission7/src/components/App.module.css
index 30245cb5d..6a5246307 100644
--- a/sprint-mission5/src/components/App.module.css
+++ b/sprint-mission7/src/components/App.module.css
@@ -4,6 +4,5 @@
}
body {
- margin: 0;
- padding-top: 70px;
+ margin-top: 70px;
}
diff --git a/sprint-mission5/src/components/BestItemsSection.jsx b/sprint-mission7/src/components/BestItemsSection.jsx
similarity index 65%
rename from sprint-mission5/src/components/BestItemsSection.jsx
rename to sprint-mission7/src/components/BestItemsSection.jsx
index ecd963771..9e90b39b9 100644
--- a/sprint-mission5/src/components/BestItemsSection.jsx
+++ b/sprint-mission7/src/components/BestItemsSection.jsx
@@ -3,20 +3,20 @@ import ItemCard from "./ItemCard";
import { getProducts } from "../api/api";
import "./bestItems.css";
+const getPageSize = () => {
+ const width = window.innerWidth;
+ if (width < 768) {
+ return 1;
+ } else if (width < 1280) {
+ return 2;
+ } else {
+ return 4;
+ }
+};
+
function BestProductsSection() {
const [itemList, setItemList] = useState([]);
- const [pageSize, setPageSize] = useState("4");
-
- const getPageSize = () => {
- const width = window.innerWidth;
- if (width < 768) {
- return 1;
- } else if (width < 1280) {
- return 2;
- } else {
- return 4;
- }
- };
+ const [pageSize, setPageSize] = useState(4);
const fetchSortedData = async ({ orderBy, pageSize }) => {
const products = await getProducts({ orderBy, pageSize });
@@ -24,8 +24,16 @@ function BestProductsSection() {
};
useEffect(() => {
+ const handleResize = () => {
+ setPageSize(getPageSize());
+ };
+
+ window.addEventListener("resize", handleResize);
fetchSortedData({ orderBy: "favorite", pageSize });
- setPageSize(getPageSize());
+
+ return () => {
+ window.removeEventListener("resize", handleResize);
+ };
}, [pageSize]);
return (
diff --git a/sprint-mission7/src/components/CommentCard.jsx b/sprint-mission7/src/components/CommentCard.jsx
new file mode 100644
index 000000000..de98850d2
--- /dev/null
+++ b/sprint-mission7/src/components/CommentCard.jsx
@@ -0,0 +1,11 @@
+import React from "react";
+
+function CommentCard({ comment }) {
+ return (
+
+ );
+}
+
+export default CommentCard;
diff --git a/sprint-mission7/src/components/DetailPage.jsx b/sprint-mission7/src/components/DetailPage.jsx
new file mode 100644
index 000000000..0f86f2848
--- /dev/null
+++ b/sprint-mission7/src/components/DetailPage.jsx
@@ -0,0 +1,82 @@
+import { useParams, Link } from "react-router-dom";
+import { getProductsById, getProductComment } from "../api/api";
+import React, { useEffect, useState } from "react";
+import favoriteIcon from "../assets/Icon.png";
+import styles from "./detailPage.module.css";
+import TagDisplay from "./TagDisplay";
+import CommentCard from "./CommentCard";
+
+function DetailPage() {
+ const { itemSlug } = useParams();
+ const [item, setItem] = useState(null);
+ const [commentList, setCommentList] = useState([]);
+
+ const fetchItemData = async () => {
+ const data = await getProductsById(itemSlug);
+ setItem(data);
+ };
+
+ const fetchCommentData = async () => {
+ const data = await getProductComment(itemSlug);
+ setCommentList(data.list);
+ };
+
+ useEffect(() => {
+ fetchItemData();
+ fetchCommentData();
+ }, [itemSlug]);
+
+ if (!item) {
+ return Loading...
;
+ }
+
+ if (!commentList) {
+ return Loading...
;
+ }
+
+ return (
+ <>
+
+
+
+
+
+
{item.name}
+
{item.price.toLocaleString()}원
+
상품 소개
+
{item.description}
+
상품 태그
+
+
+
+
+
+
{item.ownerNickname}
+
{item.createdAt}
+
+
+
+
+
{item.favoriteCount}
+
+
+
+
+
+
+
+ {commentList?.map((comment) => (
+
+ ))}
+
+
목록으로 돌아가기
+
+ >
+ );
+}
+
+export default DetailPage;
diff --git a/sprint-mission5/src/components/FileInput.css b/sprint-mission7/src/components/FileInput.css
similarity index 100%
rename from sprint-mission5/src/components/FileInput.css
rename to sprint-mission7/src/components/FileInput.css
diff --git a/sprint-mission5/src/components/FileInput.jsx b/sprint-mission7/src/components/FileInput.jsx
similarity index 100%
rename from sprint-mission5/src/components/FileInput.jsx
rename to sprint-mission7/src/components/FileInput.jsx
diff --git a/sprint-mission7/src/components/ItemCard.jsx b/sprint-mission7/src/components/ItemCard.jsx
new file mode 100644
index 000000000..cc79119fd
--- /dev/null
+++ b/sprint-mission7/src/components/ItemCard.jsx
@@ -0,0 +1,23 @@
+import React from "react";
+import favoriteIcon from "../assets/Icon.png";
+import { Link } from "react-router-dom";
+
+function ItemCard({ item }) {
+ return (
+
+
+
+
+
{item.name}
+
{item.price.toLocaleString()}원
+
+
+ {item.favoriteCount}
+
+
+
+
+ );
+}
+
+export default ItemCard;
diff --git a/sprint-mission5/src/components/Nav.jsx b/sprint-mission7/src/components/Nav.jsx
similarity index 100%
rename from sprint-mission5/src/components/Nav.jsx
rename to sprint-mission7/src/components/Nav.jsx
diff --git a/sprint-mission7/src/components/PaginationBar.jsx b/sprint-mission7/src/components/PaginationBar.jsx
new file mode 100644
index 000000000..75a309745
--- /dev/null
+++ b/sprint-mission7/src/components/PaginationBar.jsx
@@ -0,0 +1,52 @@
+import React from "react";
+import { ReactComponent as LeftArrow } from "../assets/arrow_left.svg";
+import { ReactComponent as RightArrow } from "../assets/arrow_right.svg";
+
+const PaginationBar = ({ totalPageNum, activePageNum, 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) },
+ (_, i) => startPage + i
+ );
+
+ return (
+
+
+ {pages.map((page) => (
+
+ ))}
+
+
+ );
+};
+
+export default PaginationBar;
diff --git a/sprint-mission7/src/components/TagDisplay.jsx b/sprint-mission7/src/components/TagDisplay.jsx
new file mode 100644
index 000000000..876120fe4
--- /dev/null
+++ b/sprint-mission7/src/components/TagDisplay.jsx
@@ -0,0 +1,18 @@
+import React from "react";
+import styles from "./tagDisplay.module.css";
+
+function TagDisplay({ tags }) {
+ if (!tags || tags.length === 0) return null;
+
+ return (
+
+ {tags.map((tag, index) => (
+
+ #{tag}
+
+ ))}
+
+ );
+}
+
+export default TagDisplay;
diff --git a/sprint-mission5/src/components/allItems.css b/sprint-mission7/src/components/allItems.css
similarity index 100%
rename from sprint-mission5/src/components/allItems.css
rename to sprint-mission7/src/components/allItems.css
diff --git a/sprint-mission5/src/components/bestItems.css b/sprint-mission7/src/components/bestItems.css
similarity index 100%
rename from sprint-mission5/src/components/bestItems.css
rename to sprint-mission7/src/components/bestItems.css
diff --git a/sprint-mission7/src/components/detailPage.module.css b/sprint-mission7/src/components/detailPage.module.css
new file mode 100644
index 000000000..5df24143a
--- /dev/null
+++ b/sprint-mission7/src/components/detailPage.module.css
@@ -0,0 +1,30 @@
+.img {
+ width: 486px;
+ height: 486px;
+ border-radius: 28px;
+}
+
+.name {
+ font-family: Pretendard;
+ font-size: 24px;
+ font-weight: 600;
+ line-height: 32px;
+}
+
+.itemDetailSection {
+ display: flex;
+ flex-direction: row;
+}
+
+.itemDetailPageContainer {
+ margin: auto;
+ width: 1200px;
+ top: 24px;
+}
+
+.price {
+ font-family: Pretendard;
+ font-size: 40px;
+ font-weight: 600;
+ line-height: 47px;
+}
diff --git a/sprint-mission5/src/components/header.css b/sprint-mission7/src/components/header.css
similarity index 100%
rename from sprint-mission5/src/components/header.css
rename to sprint-mission7/src/components/header.css
diff --git a/sprint-mission7/src/components/tagDisplay.module.css b/sprint-mission7/src/components/tagDisplay.module.css
new file mode 100644
index 000000000..ebb7c262a
--- /dev/null
+++ b/sprint-mission7/src/components/tagDisplay.module.css
@@ -0,0 +1,16 @@
+.tagsDisplaySection {
+ display: flex;
+ gap: 8px;
+ flex-wrap: wrap;
+}
+
+.tag {
+ background-color: #f3f4f6;
+ color: #1f2937;
+ font-family: Pretendard;
+ padding: 6px 16px;
+ border-radius: 999px;
+ font-size: 16px;
+ font-weight: 400;
+ line-height: 26px;
+}
diff --git a/sprint-mission5/src/index.js b/sprint-mission7/src/index.js
similarity index 100%
rename from sprint-mission5/src/index.js
rename to sprint-mission7/src/index.js
diff --git a/sprint-mission5/src/pages/AddProductPage.js b/sprint-mission7/src/pages/AddProductPage.js
similarity index 100%
rename from sprint-mission5/src/pages/AddProductPage.js
rename to sprint-mission7/src/pages/AddProductPage.js
diff --git a/sprint-mission7/src/pages/HomePage.js b/sprint-mission7/src/pages/HomePage.js
new file mode 100644
index 000000000..b31700247
--- /dev/null
+++ b/sprint-mission7/src/pages/HomePage.js
@@ -0,0 +1,13 @@
+import BestProductsSection from "../components/BestItemsSection";
+import AllProducts from "../components/Allproducts";
+
+function HomePage() {
+ return (
+
+ );
+}
+
+export default HomePage;
diff --git a/sprint-mission7/src/pages/ItemPage.js b/sprint-mission7/src/pages/ItemPage.js
new file mode 100644
index 000000000..fa5a92652
--- /dev/null
+++ b/sprint-mission7/src/pages/ItemPage.js
@@ -0,0 +1,11 @@
+import DetailPage from "../components/DetailPage";
+
+function ItemPage() {
+ return (
+ <>
+
+ >
+ );
+}
+
+export default ItemPage;
diff --git a/sprint-mission5/src/pages/ItemsPage.js b/sprint-mission7/src/pages/ItemsPage.js
similarity index 100%
rename from sprint-mission5/src/pages/ItemsPage.js
rename to sprint-mission7/src/pages/ItemsPage.js