diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 3e212e1..f72df80 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -6,16 +6,41 @@ module.exports = {
'plugin:react/recommended',
'plugin:react/jsx-runtime',
'plugin:react-hooks/recommended',
+ 'plugin: prettier/recommended',
+ 'react-app',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
settings: { react: { version: '18.2' } },
plugins: ['react-refresh'],
rules: {
+ 'no-var': 'warn', // var 금지
+ 'no-multiple-empty-lines': 'warn', // 여러 줄 공백 금지
+ 'no-console': ['warn', { allow: ['warn', 'error'] }], // console.log() 금지
+ eqeqeq: 'warn', // 일치 연산자 사용 필수
+ 'dot-notation': 'warn', // 가능하다면 dot notation 사용
+ 'no-unused-vars': 'warn', // 사용하지 않는 변수 금지
+ 'react/destructuring-assignment': 'warn', // state, prop 등에 구조분해 할당 적용
+ 'react/jsx-pascal-case': 'warn', // 컴포넌트 이름은 PascalCase로
+ 'react/no-direct-mutation-state': 'warn', // state 직접 수정 금지
+ 'react/jsx-no-useless-fragment': 'warn', // 불필요한 fragment 금지
+ 'react/no-unused-state': 'warn', // 사용되지 않는 state
+ 'react/jsx-key': 'warn', // 반복문으로 생성하는 요소에 key 강제
+ 'react/self-closing-comp': 'warn', // 셀프 클로징 태그 가능하면 적용
+ 'react/jsx-curly-brace-presence': 'warn', // jsx 내 불필요한 중괄호 금지
+ 'prettier/prettier': [
+ 'error',
+ {
+ endOfLine: 'auto',
+ },
+ ],
+ env: {
+ browser: true, // document, window 등의 브라우저 내장 객체들 조회시 ESLint 오류 없이 작업
+ },
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
-}
+};
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..5a01fba
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,6 @@
+{
+ "tabWidth": 2,
+ "endOfLine": "lf",
+ "arrowParens": "avoid",
+ "singleQuote": true
+}
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..ff1b97a
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,3 @@
+{
+ "recommendations": ["streetsidesoftware.code-spell-checker"]
+}
diff --git a/package-lock.json b/package-lock.json
index 65af28b..bda5dc9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,10 +25,13 @@
"@types/react-dom": "^18.2.22",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.57.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"json-server": "^0.17.4",
+ "prettier": "^3.2.5",
"vite": "^5.2.0"
}
},
@@ -955,6 +958,18 @@
"node": ">= 8"
}
},
+ "node_modules/@pkgr/core": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
+ "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
"node_modules/@remix-run/router": {
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz",
@@ -2414,6 +2429,48 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/eslint-config-prettier": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
+ "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz",
+ "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.8.6"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-plugin-prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "eslint-config-prettier": "*",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
"node_modules/eslint-plugin-react": {
"version": "7.34.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz",
@@ -2780,6 +2837,12 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true
+ },
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -4529,6 +4592,33 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/prettier": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
+ "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -5385,6 +5475,28 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/synckit": {
+ "version": "0.8.8",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz",
+ "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==",
+ "dev": true,
+ "dependencies": {
+ "@pkgr/core": "^0.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "node_modules/synckit/node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "dev": true
+ },
"node_modules/text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
diff --git a/package.json b/package.json
index 0c19490..2e20cf1 100644
--- a/package.json
+++ b/package.json
@@ -28,10 +28,13 @@
"@types/react-dom": "^18.2.22",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.57.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"json-server": "^0.17.4",
+ "prettier": "^3.2.5",
"vite": "^5.2.0"
}
}
diff --git a/src/api/WastesApi.jsx b/src/api/WastesApi.jsx
index 176029d..707ebe1 100644
--- a/src/api/WastesApi.jsx
+++ b/src/api/WastesApi.jsx
@@ -28,3 +28,8 @@ export const deletePost = async (wasteId) => {
throw error; // 오류를 다시 throw하여 컴포넌트에서 처리할 수 있도록 함
}
};
+
+export const updatePost = async (wasteId, updatedPost) => {
+ const response = await axios.put(`${API_URL}/wastes/${wasteId}`, updatedPost);
+ return response.data;
+};
diff --git a/src/components/ProductCard.jsx b/src/components/ProductCard.jsx
new file mode 100644
index 0000000..c9bc366
--- /dev/null
+++ b/src/components/ProductCard.jsx
@@ -0,0 +1,71 @@
+import React, { useState } from 'react';
+import * as S from '../styles/ProductCardStyle';
+import { GoHeart } from 'react-icons/go';
+import { GoHeartFill } from 'react-icons/go';
+import { useRecoilState } from 'recoil';
+import { postsState } from '../recoil/RecoilWastes';
+import { useEffect } from 'react';
+import { fetchPosts } from '../api/WastesApi';
+import { updatePost } from '../api/WastesApi';
+const ProductCard = ({ post, onDelete }) => {
+ const handleDeleteClick = () => {
+ onDelete(post.id);
+ };
+
+ const [posts, setPosts] = useRecoilState(postsState);
+
+ const handleLikeToggle = async () => {
+ const updatedPost = { ...post };
+ if (updatedPost.hearted) {
+ updatedPost.likeCount -= 1; // 채워진 하트에서 빈 하트로 변경되면 likeCount 감소
+ } else {
+ updatedPost.likeCount += 1; // 빈 하트에서 채워진 하트로 변경되면 likeCount 증가
+ }
+ updatedPost.hearted = !updatedPost.hearted; // 하트 상태 업데이트
+ await updatePost(post.id, updatedPost); // 서버에 업데이트 요청
+ const updatedPosts = posts.map(p => (p.id === post.id ? updatedPost : p));
+ setPosts(updatedPosts); // Recoil 상태 업데이트
+ };
+ return (
+
+
+
+
+
+
+
{post.title}
+
+
+
{post.address.state}
+
{post.address.city}
+
+
+ {/*
*/}
+ {/*
{wastes.created_at}
*/}
+
+
+
{post.wastePrice}원
+
+
+
+
{post.sellStatus}
+
+
+
{post.likeCount}
+
+
+ {/*
*/}
+ {/*
*/}
+
+
+
+ );
+};
+
+export default ProductCard;
diff --git a/src/fakeServer/db.json b/src/fakeServer/db.json
index cc07d9f..7f3adf4 100644
--- a/src/fakeServer/db.json
+++ b/src/fakeServer/db.json
@@ -2,24 +2,304 @@
"wastes": [
{
"fileName": {},
- "title": "예시",
+ "title": "옷팝니다.",
"wasteCategory": "의류",
+ "wasteStatus": "중",
+ "sellStatus": "거래중",
+ "wastePrice": "2,000",
+ "content": "ㅇㅇㅇㅇㅇㅇㅇㅇㅇ",
+ "address": {
+ "address": "경기 안성시 고삼면 안성대로 1980",
+ "zipcode": "17505",
+ "state": "경기",
+ "city": "안성시",
+ "district": "가유리",
+ "detail": ""
+ },
+ "likeCount": 50,
+ "viewCount": 55,
+ "created_at": "2024. 4. 11.",
+ "id": 1
+ },
+ {
+ "fileName": {},
+ "title": "화장품 팝니다.",
+ "wasteCategory": "뷰티",
+ "wasteStatus": "하",
+ "sellStatus": "거래중",
+ "wastePrice": "2,500",
+ "content": "팔아요",
+ "address": {
+ "address": "인천 강화군 강화읍 갑룡길 35",
+ "zipcode": "23024",
+ "state": "인천",
+ "city": "강화군",
+ "district": "갑곳리",
+ "detail": "그랑드빌 아파트"
+ },
+ "likeCount": 40,
+ "viewCount": 45,
+ "created_at": "2024. 4. 11.",
+ "id": 2
+ },
+ {
+ "fileName": {},
+ "title": "핸드폰 팔아요",
+ "wasteCategory": "전자기기",
+ "wasteStatus": "최상",
+ "sellStatus": "거래중",
+ "wastePrice": "10,000",
+ "content": "팝니다.",
+ "address": {
+ "address": "서울 성동구 서울숲길 17",
+ "zipcode": "04766",
+ "state": "서울",
+ "city": "성동구",
+ "district": "성수동1가",
+ "detail": "성수파크빌"
+ },
+ "likeCount": 60,
+ "viewCount": 72,
+ "created_at": "2024. 4. 11.",
+ "id": 3
+ },
+ {
+ "fileName": {},
+ "title": "안녕하세요",
+ "wasteCategory": "뷰티",
+ "wasteStatus": "최하",
+ "sellStatus": "거래중",
+ "wastePrice": "0",
+ "content": "나눔합니다.",
+ "address": {
+ "address": "서울 종로구 북촌로 31-4",
+ "zipcode": "03055",
+ "state": "서울",
+ "city": "종로구",
+ "district": "가회동",
+ "detail": "오픈아이즈센터"
+ },
+ "likeCount": 60,
+ "viewCount": 72,
+ "created_at": "2024. 4. 11.",
+ "id": 4,
+ "hearted": false
+ },
+ {
+ "fileName": {},
+ "title": "가구나눔",
+ "wasteCategory": "가구/인텔어",
+ "wasteStatus": "최상",
+ "sellStatus": "거래중",
+ "wastePrice": "0",
+ "content": "ddfweg",
+ "address": {
+ "address": "인천 부평구 갈산로 2",
+ "zipcode": "21316",
+ "state": "인천",
+ "city": "부평구",
+ "district": "갈산동",
+ "detail": ""
+ },
+ "likeCount": 88,
+ "viewCount": 100,
+ "created_at": "2024. 4. 11.",
+ "id": 6,
+ "hearted": false
+ },
+ {
+ "fileName": {},
+ "title": "씨앗 팔아요",
+ "wasteCategory": "식물",
+ "wasteStatus": "최상",
+ "sellStatus": "거래중",
+ "wastePrice": "500",
+ "content": "ㅇㅇㅇㄴㄹㄷ",
+ "address": {
+ "address": "서울 강남구 가로수길 5",
+ "zipcode": "06035",
+ "state": "서울",
+ "city": "강남구",
+ "district": "신사동",
+ "detail": ""
+ },
+ "likeCount": 100,
+ "viewCount": 25,
+ "created_at": "2024. 4. 11.",
+ "id": 7,
+ "hearted": false
+ },
+ {
+ "fileName": {},
+ "title": "건강식품",
+ "wasteCategory": "건강",
+ "wasteStatus": "중",
+ "sellStatus": "거래중",
+ "wastePrice": "4,000",
+ "content": "건강식품",
+ "address": {
+ "address": "서울 용산구 두텁바위로 5",
+ "zipcode": "04335",
+ "state": "서울",
+ "city": "용산구",
+ "district": "갈월동",
+ "detail": ""
+ },
+ "likeCount": 70,
+ "viewCount": 55,
+ "created_at": "2024. 4. 12.",
+ "id": 8
+ },
+ {
+ "fileName": {},
+ "title": "ㄹㄹㄹㄹㄹㄹㄹ",
+ "wasteCategory": "뷰티",
+ "wasteStatus": "최하",
+ "sellStatus": "거래중",
+ "wastePrice": "5,000",
+ "content": "뷰티",
+ "address": {
+ "address": "인천 미추홀구 남주길 5",
+ "zipcode": "22156",
+ "state": "인천",
+ "city": "미추홀구",
+ "district": "주안동",
+ "detail": ""
+ },
+ "likeCount": 70,
+ "viewCount": 55,
+ "created_at": "2024. 4. 12.",
+ "id": 9
+ },
+ {
+ "fileName": {},
+ "title": "ㅇㅇㅇㅇㅇㅇ",
+ "wasteCategory": "뷰티",
+ "wasteStatus": "하",
+ "sellStatus": "거래중",
+ "wastePrice": "0",
+ "content": "dddddddd",
+ "address": {
+ "address": "서울 송파구 성남대로 1541-40",
+ "zipcode": "05843",
+ "state": "서울",
+ "city": "송파구",
+ "district": "장지동",
+ "detail": ""
+ },
+ "likeCount": 70,
+ "viewCount": 55,
+ "created_at": "2024. 4. 12.",
+ "id": 10
+ },
+ {
+ "fileName": {},
+ "title": "뷰티",
+ "wasteCategory": "뷰티",
+ "wasteStatus": "최하",
+ "sellStatus": "거래중",
+ "wastePrice": "500",
+ "content": "뷰티템",
+ "address": {
+ "address": "서울 은평구 갈현로 181-2",
+ "zipcode": "03325",
+ "state": "서울",
+ "city": "은평구",
+ "district": "갈현동",
+ "detail": ""
+ },
+ "likeCount": 70,
+ "viewCount": 55,
+ "created_at": "2024. 4. 12.",
+ "id": 11,
+ "hearted": false
+ },
+ {
+ "fileName": {},
+ "title": "뷰티템5개",
+ "wasteCategory": "뷰티",
"wasteStatus": "상",
"sellStatus": "거래중",
+ "wastePrice": "8,000",
+ "content": "5개팔아요",
+ "address": {
+ "address": "인천 남동구 간석로 1",
+ "zipcode": "21510",
+ "state": "인천",
+ "city": "남동구",
+ "district": "간석동",
+ "detail": ""
+ },
+ "likeCount": 70,
+ "viewCount": 55,
+ "created_at": "2024. 4. 12.",
+ "id": 12,
+ "hearted": false
+ },
+ {
+ "fileName": {},
+ "title": "xx립스틱",
+ "wasteCategory": "뷰티",
+ "wasteStatus": "중",
+ "sellStatus": "거래중",
+ "wastePrice": "50,000",
+ "content": "새거 팝니다.",
+ "address": {
+ "address": "서울 용산구 남산공원길 101",
+ "zipcode": "04340",
+ "state": "서울",
+ "city": "용산구",
+ "district": "후암동",
+ "detail": ""
+ },
+ "likeCount": 70,
+ "viewCount": 55,
+ "created_at": "2024. 4. 12.",
+ "id": 13,
+ "hearted": false
+ },
+ {
+ "fileName": {},
+ "title": "사세요~",
+ "wasteCategory": "뷰티",
+ "wasteStatus": "최상",
+ "sellStatus": "거래중",
+ "wastePrice": "50,000",
+ "content": "가져가세요~",
+ "address": {
+ "address": "경기 부천시 소사구 부천로 1",
+ "zipcode": "14637",
+ "state": "경기",
+ "city": "부천시 소사구",
+ "district": "심곡본동",
+ "detail": "부천역사 쇼핑몰"
+ },
+ "likeCount": 70,
+ "viewCount": 55,
+ "created_at": "2024. 4. 12.",
+ "id": 14,
+ "hearted": false
+ },
+ {
+ "fileName": {},
+ "title": "ddfdd",
+ "wasteCategory": "의류",
+ "wasteStatus": "중",
+ "sellStatus": "",
"wastePrice": "3,000",
- "content": "예시입니다.",
+ "content": "ddddd",
"address": {
- "address": "서울 서초구 안골길 4",
- "zipcode": "06794",
+ "address": "서울 마포구 굴레방로 1",
+ "zipcode": "04117",
"state": "서울",
- "city": "서초구",
- "district": "내곡동",
+ "city": "마포구",
+ "district": "아현동",
"detail": ""
},
- "likeCount": "",
- "viewCount": "",
- "created_at": "2024. 4. 11.",
- "id": 1
+ "likeCount": 70,
+ "viewCount": 55,
+ "created_at": "2024. 4. 13.",
+ "id": 15
}
]
}
\ No newline at end of file
diff --git a/src/index.css b/src/index.css
index cd7c391..5410a08 100644
--- a/src/index.css
+++ b/src/index.css
@@ -32,6 +32,7 @@
--grey-dgrey: #34495e;
--grey-dark: #353e4a;
--grey-box: #d9d9d9;
+ --grey-light: #f0f0f0;
--white-ivory: #fbf8ef;
}
@@ -123,3 +124,6 @@ video {
font: inherit;
vertical-align: baseline;
}
+ul {
+ list-style: none;
+}
diff --git a/src/pages/ProductAdd.jsx b/src/pages/ProductAdd.jsx
index 2ad9eda..c40ab4c 100644
--- a/src/pages/ProductAdd.jsx
+++ b/src/pages/ProductAdd.jsx
@@ -1,37 +1,37 @@
-import React, { useState } from "react";
-import { useRecoilState } from "recoil";
-import Nav from "../components/Nav";
-import { FaWonSign } from "react-icons/fa6";
-import { IoIosArrowForward } from "react-icons/io";
-import * as S from "../styles/ProductAddStyle";
-import { Link, Navigate, useNavigate } from "react-router-dom";
-import { postsState } from "../recoil/RecoilWastes";
-import { createPost } from "../api/WastesApi";
-import { IoIosCamera } from "react-icons/io";
-import axios from "axios";
+import React, { useState } from 'react';
+import { useRecoilState } from 'recoil';
+import Nav from '../components/Nav';
+import { FaWonSign } from 'react-icons/fa6';
+import { IoIosArrowForward } from 'react-icons/io';
+import * as S from '../styles/ProductAddStyle';
+import { Link, Navigate, useNavigate } from 'react-router-dom';
+import { postsState } from '../recoil/RecoilWastes';
+import { createPost } from '../api/WastesApi';
+import { IoIosCamera } from 'react-icons/io';
+import axios from 'axios';
const ProductAdd = () => {
const [posts, setPosts] = useRecoilState(postsState);
- const [wasteCategory, setWasteCategory] = useState("");
- const [title, setTitle] = useState("");
- const [wasteStatus, setWasteStatus] = useState("");
- const [content, setContent] = useState("");
- const [sellStatus, setSellStatus] = useState("");
- const [wastePrice, setWastePrice] = useState("");
+ const [wasteCategory, setWasteCategory] = useState('');
+ const [title, setTitle] = useState('');
+ const [wasteStatus, setWasteStatus] = useState('');
+ const [content, setContent] = useState('');
+ const [sellStatus, setSellStatus] = useState('');
+ const [wastePrice, setWastePrice] = useState('');
const [address, setAddress] = useState({
- zipcode: "",
- state: "",
- city: "",
- district: "",
- detail: "",
+ zipcode: '',
+ state: '',
+ city: '',
+ district: '',
+ detail: '',
});
const [fileName, setFileName] = useState(null);
- const [likeCount, setLikeCount] = useState("");
- const [viewCount, setViewCount] = useState("");
+ const [likeCount, setLikeCount] = useState(70);
+ const [viewCount, setViewCount] = useState(55);
const navigate = useNavigate();
//찾은 주소 inptu 반영
- const handleComplete = (data) => {
+ const handleComplete = data => {
setAddress({
address: data.address,
zipcode: data.zonecode,
@@ -48,14 +48,14 @@ const ProductAdd = () => {
}).open();
};
//이미지 형식 제한
- const validImageTypes = ["image/jpeg", "image/jpg", "image/png"];
- const handleImageChange = (e) => {
+ const validImageTypes = ['image/jpeg', 'image/jpg', 'image/png'];
+ const handleImageChange = e => {
const file = e.target.files[0];
if (file) {
if (validImageTypes.includes(file.type)) {
setFileName(file);
} else {
- alert("올바른 이미지 형식을 선택하세요. (JPEG, JPG, PNG)");
+ alert('올바른 이미지 형식을 선택하세요. (JPEG, JPG, PNG)');
// 선택한 파일 초기화
e.target.value = null;
}
@@ -63,47 +63,47 @@ const ProductAdd = () => {
};
//데이터 제출
- const handlePriceChange = (str) => {
- const comma = (str) => {
+ const handlePriceChange = str => {
+ const comma = str => {
str = String(str);
- return str.replace(/(\d)(?=(?:\d{3})+(?!\d))/g, "$1,");
+ return str.replace(/(\d)(?=(?:\d{3})+(?!\d))/g, '$1,');
};
- const uncomma = (str) => {
+ const uncomma = str => {
str = String(str);
- return str.replace(/[^\d]+/g, "");
+ return str.replace(/[^\d]+/g, '');
};
return comma(uncomma(str));
};
//제목 글자수 제한
- const handleTitleChange = (e) => {
+ const handleTitleChange = e => {
const inputValue = e.target.value;
if (inputValue.length <= 255) {
setTitle(inputValue);
}
};
//내용 글자수 제한
- const handleContentChange = (e) => {
+ const handleContentChange = e => {
const inputValue = e.target.value;
if (inputValue.length <= 65535) {
setContent(inputValue);
}
};
- const handleSubmit = async (e) => {
+ const handleSubmit = async e => {
e.preventDefault();
const formData = new FormData();
- formData.append("fileName", fileName);
- formData.append("category", wasteCategory);
- formData.append("title", title);
- formData.append("waste_status", wasteStatus);
- formData.append("sell_status", sellStatus);
- formData.append("waste_price", wastePrice);
- formData.append("content", content);
- formData.append("address", address);
- formData.append("likeCount", likeCount);
- formData.append("viewCount", viewCount);
+ formData.append('fileName', fileName);
+ formData.append('category', wasteCategory);
+ formData.append('title', title);
+ formData.append('waste_status', wasteStatus);
+ formData.append('sell_status', sellStatus);
+ formData.append('waste_price', wastePrice);
+ formData.append('content', content);
+ formData.append('address', address);
+ formData.append('likeCount', likeCount);
+ formData.append('viewCount', viewCount);
try {
const newPost = {
@@ -122,18 +122,18 @@ const ProductAdd = () => {
const createdPost = await createPost(newPost);
setPosts([...posts, createdPost]);
- setWasteCategory("");
- setTitle("");
- setWasteStatus("");
- setContent("");
- setSellStatus("");
- setWastePrice("");
- setAddress("");
+ setWasteCategory('');
+ setTitle('');
+ setWasteStatus('');
+ setContent('');
+ setSellStatus('');
+ setWastePrice('');
+ setAddress('');
setFileName(null);
- navigate("/ProductsList");
+ navigate('/ProductsList');
} catch (error) {
- console.error("Error uploading image:", error);
+ console.error('Error uploading image:', error);
}
};
return (
@@ -173,7 +173,7 @@ const ProductAdd = () => {