From a6078af74c3eebb1676a34f7b9a4dbdcdce27b00 Mon Sep 17 00:00:00 2001 From: heejin Date: Mon, 24 Feb 2025 03:46:34 +0900 Subject: [PATCH 01/20] Refactor : add useEffect dependency array --- src/components/Detail/Detail.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Detail/Detail.jsx b/src/components/Detail/Detail.jsx index 35efb572..b8825c2a 100644 --- a/src/components/Detail/Detail.jsx +++ b/src/components/Detail/Detail.jsx @@ -29,7 +29,7 @@ export default function Detail() { getProductInfo(productId) .then((result) => setProduct(result)) .catch((error) => console.error(error)); - }, []); + }, [productId]); const handleHeartChange = () => { setIsFull((prev) => !prev); From bc52a216291fad9a6d9d64f6cec1f88a31bb9ad2 Mon Sep 17 00:00:00 2001 From: heejin Date: Mon, 24 Feb 2025 03:51:20 +0900 Subject: [PATCH 02/20] Refactor : axios instance --- src/api/comment.js | 10 ++++------ src/api/index.js | 12 ++++++++++++ src/api/products.js | 8 +++----- 3 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 src/api/index.js diff --git a/src/api/comment.js b/src/api/comment.js index 609d6110..adfdaab1 100644 --- a/src/api/comment.js +++ b/src/api/comment.js @@ -1,10 +1,8 @@ -import axios from "axios"; +import api from "./index"; -const BASE_URL = process.env.REACT_APP_BASE_URL; - -export async function getComments(productId) { - const response = await axios.get( - `${BASE_URL}/products/${productId}/comments?limit=3` +export async function getComments(productId, limit = 3) { + const response = await api.get( + `/products/${productId}/comments?limit=${limit}` ); return response.data.list; diff --git a/src/api/index.js b/src/api/index.js new file mode 100644 index 00000000..e9ddd6b1 --- /dev/null +++ b/src/api/index.js @@ -0,0 +1,12 @@ +import axios from "axios"; + +const BASE_URL = process.env.REACT_APP_BASE_URL; + +const api = axios.create({ + baseURL: BASE_URL, + headers: { + "Content-Type": "application/json", + }, +}); + +export default api; diff --git a/src/api/products.js b/src/api/products.js index 4f9bb5c2..294559de 100644 --- a/src/api/products.js +++ b/src/api/products.js @@ -1,10 +1,8 @@ -import axios from "axios"; - -const BASE_URL = process.env.REACT_APP_BASE_URL; +import api from "./index"; export async function getProducts(params) { const { page, pageSize, orderBy, keyword } = params; - const response = await axios.get(`${BASE_URL}/products`, { + const response = await api.get(`/products`, { params: { page, pageSize, orderBy, keyword }, }); @@ -12,7 +10,7 @@ export async function getProducts(params) { } export async function getProductInfo(productId) { - const response = await axios.get(`${BASE_URL}/products/${productId}`); + const response = await api.get(`/products/${productId}`); return response.data; } From 1bfc74548c193fce5141935e02faa18aaf140ffd Mon Sep 17 00:00:00 2001 From: heejin Date: Tue, 25 Feb 2025 04:25:46 +0900 Subject: [PATCH 03/20] Feat : add item page type --- package-lock.json | 82 ++++++++++++------- package.json | 5 ++ ...Page.styles.jsx => AddItemPage.styles.tsx} | 0 .../{AddItemPage.jsx => AddItemPage.tsx} | 29 ++++--- tsconfig.json | 19 +++++ 5 files changed, 96 insertions(+), 39 deletions(-) rename src/components/pages/AddItemPage/{AddItemPage.styles.jsx => AddItemPage.styles.tsx} (100%) rename src/components/pages/AddItemPage/{AddItemPage.jsx => AddItemPage.tsx} (83%) create mode 100644 tsconfig.json diff --git a/package-lock.json b/package-lock.json index 6c48b1fa..99b29892 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,10 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "@types/jest": "^29.5.14", + "@types/node": "^22.13.5", + "@types/react": "^19.0.10", + "@types/react-dom": "^19.0.4", "axios": "^1.7.9", "lodash.debounce": "^4.0.8", "react": "^18.2.0", @@ -19,6 +23,7 @@ "react-router-dom": "^6.28.1", "react-scripts": "5.0.1", "styled-components": "^6.1.14", + "typescript": "^5.7.3", "web-vitals": "^2.1.4" } }, @@ -3805,6 +3810,24 @@ "node": ">=12" } }, + "node_modules/@testing-library/react/node_modules/@types/react": { + "version": "18.3.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", + "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@testing-library/react/node_modules/@types/react-dom": { + "version": "18.3.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz", + "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, "node_modules/@testing-library/react/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -4077,9 +4100,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.4", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.4.tgz", - "integrity": "sha512-PhglGmhWeD46FYOVLt3X7TiWjzwuVGW9wG/4qocPevXMjCmrIc5b6db9WjeGE4QYVpUAWMDv3v0IiBwObY289A==", + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" @@ -4328,9 +4351,12 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, "node_modules/@types/node": { - "version": "20.5.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", - "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==" + "version": "22.13.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.5.tgz", + "integrity": "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==", + "dependencies": { + "undici-types": "~6.20.0" + } }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -4343,9 +4369,10 @@ "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==" }, "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "peer": true }, "node_modules/@types/q": { "version": "1.5.6", @@ -4363,21 +4390,19 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, "node_modules/@types/react": { - "version": "18.2.21", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.21.tgz", - "integrity": "sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==", + "version": "19.0.10", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.10.tgz", + "integrity": "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==", "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.2.7", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz", - "integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==", - "dependencies": { - "@types/react": "*" + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.4.tgz", + "integrity": "sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==", + "peerDependencies": { + "@types/react": "^19.0.0" } }, "node_modules/@types/resolve": { @@ -4393,11 +4418,6 @@ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, - "node_modules/@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" - }, "node_modules/@types/semver": { "version": "7.5.1", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.1.tgz", @@ -16866,16 +16886,15 @@ } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "peer": true, + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/unbox-primitive": { @@ -16897,6 +16916,11 @@ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", diff --git a/package.json b/package.json index 7c5a459a..2cf1d248 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,10 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "@types/jest": "^29.5.14", + "@types/node": "^22.13.5", + "@types/react": "^19.0.10", + "@types/react-dom": "^19.0.4", "axios": "^1.7.9", "lodash.debounce": "^4.0.8", "react": "^18.2.0", @@ -14,6 +18,7 @@ "react-router-dom": "^6.28.1", "react-scripts": "5.0.1", "styled-components": "^6.1.14", + "typescript": "^5.7.3", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/src/components/pages/AddItemPage/AddItemPage.styles.jsx b/src/components/pages/AddItemPage/AddItemPage.styles.tsx similarity index 100% rename from src/components/pages/AddItemPage/AddItemPage.styles.jsx rename to src/components/pages/AddItemPage/AddItemPage.styles.tsx diff --git a/src/components/pages/AddItemPage/AddItemPage.jsx b/src/components/pages/AddItemPage/AddItemPage.tsx similarity index 83% rename from src/components/pages/AddItemPage/AddItemPage.jsx rename to src/components/pages/AddItemPage/AddItemPage.tsx index f1ddc6a5..176449b1 100644 --- a/src/components/pages/AddItemPage/AddItemPage.jsx +++ b/src/components/pages/AddItemPage/AddItemPage.tsx @@ -6,6 +6,14 @@ import { useState } from "react"; import { useNavigate } from "react-router-dom"; import { isValidAddItem } from "../../../utils/addValidate"; +interface AddItem { + images: string | null; + name: string; + description: string; + price: number; + tags: string[]; +} + const INITIAL_VALUE = { images: null, name: "", @@ -16,10 +24,10 @@ const INITIAL_VALUE = { export default function AddItemPage() { const navigate = useNavigate(); - const [values, setValues] = useState(INITIAL_VALUE); - const [tag, setTag] = useState(""); + const [values, setValues] = useState(INITIAL_VALUE); + const [tag, setTag] = useState(""); - const handleInputChange = (e) => { + const handleInputChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setValues((prevState) => ({ @@ -28,7 +36,7 @@ export default function AddItemPage() { })); }; - const handleTagChange = (e) => { + const handleTagChange = (e: React.KeyboardEvent) => { // IME composition if (e.nativeEvent.isComposing) return; @@ -49,14 +57,14 @@ export default function AddItemPage() { } }; - const handleTagDelete = (deleteTag) => { + const handleTagDelete = (deleteTag: string) => { setValues((prevState) => ({ ...prevState, tags: prevState.tags.filter((tag) => tag !== deleteTag), })); }; - const handleSubmit = (e) => { + const handleSubmit = (e: React.FormEvent) => { if (isValidAddItem(values)) { e.preventDefault(); // const formData = new FormData(); @@ -69,7 +77,7 @@ export default function AddItemPage() { } }; - const handleKeyDown = (e) => { + const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Enter") { e.preventDefault(); } @@ -108,7 +116,8 @@ export default function AddItemPage() { type: "text", placeholder: "태그를 입력해주세요", value: tag, - onChange: (e) => setTag(e.target.value), + onChange: (e: React.ChangeEvent) => + setTag(e.target.value), onKeyDown: handleTagChange, }, ]; @@ -130,9 +139,9 @@ export default function AddItemPage() { setValues={setValues} /> - {INPUT.map((i, idx) => ( + {INPUT.map((i) => ( Date: Tue, 25 Feb 2025 04:26:14 +0900 Subject: [PATCH 04/20] Feat : input common component type --- .../Input/{Input.styles.jsx => Input.styles.tsx} | 6 +++++- .../common/Input/{Input.jsx => Input.tsx} | 14 +++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) rename src/components/common/Input/{Input.styles.jsx => Input.styles.tsx} (89%) rename src/components/common/Input/{Input.jsx => Input.tsx} (59%) diff --git a/src/components/common/Input/Input.styles.jsx b/src/components/common/Input/Input.styles.tsx similarity index 89% rename from src/components/common/Input/Input.styles.jsx rename to src/components/common/Input/Input.styles.tsx index e5de2cf1..035be032 100644 --- a/src/components/common/Input/Input.styles.jsx +++ b/src/components/common/Input/Input.styles.tsx @@ -1,6 +1,10 @@ import styled from "styled-components"; import theme from "../../../styles/theme"; +interface LargeHeight { + $largeHeight?: string; +} + export const InputContainer = styled.div` width: 100%; height: 100%; @@ -16,7 +20,7 @@ export const Label = styled.label` color: ${theme.color.gray800}; `; -export const StyledInput = styled.input` +export const StyledInput = styled.input` width: 100%; height: ${({ height }) => height || "100%"}; background-color: ${theme.color.gray100}; diff --git a/src/components/common/Input/Input.jsx b/src/components/common/Input/Input.tsx similarity index 59% rename from src/components/common/Input/Input.jsx rename to src/components/common/Input/Input.tsx index a519e71e..d9f2add6 100644 --- a/src/components/common/Input/Input.jsx +++ b/src/components/common/Input/Input.tsx @@ -1,21 +1,29 @@ import * as S from "./Input.styles"; +import { CSSProperties, InputHTMLAttributes } from "react"; + +interface InputProps extends InputHTMLAttributes { + label: string; + style?: CSSProperties; + isTextarea?: boolean; + height?: string; + largeHeight?: string; + $largeHeight?: string; +} export default function Input({ label, style, isTextarea, - onChange, height, largeHeight, ...rest -}) { +}: InputProps) { return ( {label} Date: Tue, 25 Feb 2025 04:30:35 +0900 Subject: [PATCH 05/20] Feat : tag component type & svg.d.ts --- src/components/Tag/Tag.jsx | 13 ------------- .../Tag/{Tag.styles.jsx => Tag.styles.tsx} | 8 ++++++-- src/components/Tag/Tag.tsx | 19 +++++++++++++++++++ src/types/svg.d.ts | 4 ++++ 4 files changed, 29 insertions(+), 15 deletions(-) delete mode 100644 src/components/Tag/Tag.jsx rename src/components/Tag/{Tag.styles.jsx => Tag.styles.tsx} (75%) create mode 100644 src/components/Tag/Tag.tsx create mode 100644 src/types/svg.d.ts diff --git a/src/components/Tag/Tag.jsx b/src/components/Tag/Tag.jsx deleted file mode 100644 index 13902048..00000000 --- a/src/components/Tag/Tag.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as S from "./Tag.styles"; -import x from "../../assets/icons/delete.svg"; - -export default function Tag({ tag, onClick, readOnly }) { - return ( - - - #{tag} - - - - ); -} diff --git a/src/components/Tag/Tag.styles.jsx b/src/components/Tag/Tag.styles.tsx similarity index 75% rename from src/components/Tag/Tag.styles.jsx rename to src/components/Tag/Tag.styles.tsx index 4c3e15c4..51c06a07 100644 --- a/src/components/Tag/Tag.styles.jsx +++ b/src/components/Tag/Tag.styles.tsx @@ -1,6 +1,10 @@ import { styled } from "styled-components"; import theme from "../../styles/theme"; +interface Readonly { + readonly?: boolean; +} + export const TagContainer = styled.li` height: 36px; background-color: ${theme.color.gray100}; @@ -19,10 +23,10 @@ export const TagName = styled.div` color: ${theme.color.gray800}; `; -export const DeleteTag = styled.img` +export const DeleteTag = styled.img` width: 22px; height: 24px; cursor: pointer; - display: ${({ readOnly }) => (readOnly ? "none" : "block")}; + display: ${({ readonly }) => (readonly ? "none" : "block")}; `; diff --git a/src/components/Tag/Tag.tsx b/src/components/Tag/Tag.tsx new file mode 100644 index 00000000..628a0de2 --- /dev/null +++ b/src/components/Tag/Tag.tsx @@ -0,0 +1,19 @@ +import * as S from "./Tag.styles"; +import x from "../../assets/icons/delete.svg"; + +interface TagProps { + tag: string; + onClick: () => void; + readonly?: boolean; +} + +export default function Tag({ tag, onClick, readonly }: TagProps) { + return ( + + + #{tag} + + + + ); +} diff --git a/src/types/svg.d.ts b/src/types/svg.d.ts new file mode 100644 index 00000000..5e52f805 --- /dev/null +++ b/src/types/svg.d.ts @@ -0,0 +1,4 @@ +declare module "*.svg" { + const content: string; + export default content; +} From e91dbc4e19efe229294aea05254eb4e6ae2de342 Mon Sep 17 00:00:00 2001 From: heejin Date: Tue, 25 Feb 2025 18:40:15 +0900 Subject: [PATCH 06/20] Feat : dropdown type --- .../{Dropdown.styles.jsx => Dropdown.styles.tsx} | 6 +++++- .../common/Dropdown/{Dropdown.jsx => Dropdown.tsx} | 14 ++++++++++++-- src/components/common/Input/Input.tsx | 1 - 3 files changed, 17 insertions(+), 4 deletions(-) rename src/components/common/Dropdown/{Dropdown.styles.jsx => Dropdown.styles.tsx} (95%) rename src/components/common/Dropdown/{Dropdown.jsx => Dropdown.tsx} (73%) diff --git a/src/components/common/Dropdown/Dropdown.styles.jsx b/src/components/common/Dropdown/Dropdown.styles.tsx similarity index 95% rename from src/components/common/Dropdown/Dropdown.styles.jsx rename to src/components/common/Dropdown/Dropdown.styles.tsx index 4b182382..5ea84a4c 100644 --- a/src/components/common/Dropdown/Dropdown.styles.jsx +++ b/src/components/common/Dropdown/Dropdown.styles.tsx @@ -4,6 +4,10 @@ import up from "../../../assets/icons/arrowUp.svg"; import dropdown from "../../../assets/icons/dropdown.svg"; import theme from "../../../styles/theme"; +interface IsOpen { + $isOpen: boolean; +} + export const DropdownContainer = styled.div` display: flex; flex-direction: column; @@ -45,7 +49,7 @@ export const PresentValue = styled.div` } `; -export const Arrow = styled.img` +export const Arrow = styled.img` width: 24px; height: 24px; user-select: none; diff --git a/src/components/common/Dropdown/Dropdown.jsx b/src/components/common/Dropdown/Dropdown.tsx similarity index 73% rename from src/components/common/Dropdown/Dropdown.jsx rename to src/components/common/Dropdown/Dropdown.tsx index e64aba65..1eab1001 100644 --- a/src/components/common/Dropdown/Dropdown.jsx +++ b/src/components/common/Dropdown/Dropdown.tsx @@ -1,8 +1,18 @@ import * as S from "./Dropdown.styles"; import { useState } from "react"; -export default function Dropdown({ sortOption = "최신순", onChange, list = [] }) { - const [isOpen, setIsOpen] = useState(false); +interface DropDownProps { + sortOption: string; + onChange: (option: string) => void; + list: string[]; +} + +export default function Dropdown({ + sortOption, + onChange, + list = [], +}: DropDownProps) { + const [isOpen, setIsOpen] = useState(false); const handleOpenClick = () => { setIsOpen(!isOpen); diff --git a/src/components/common/Input/Input.tsx b/src/components/common/Input/Input.tsx index d9f2add6..9d00fd2e 100644 --- a/src/components/common/Input/Input.tsx +++ b/src/components/common/Input/Input.tsx @@ -7,7 +7,6 @@ interface InputProps extends InputHTMLAttributes { isTextarea?: boolean; height?: string; largeHeight?: string; - $largeHeight?: string; } export default function Input({ From ed3d1696f1fa45af4aee04c67ae71c064b35102f Mon Sep 17 00:00:00 2001 From: heejin Date: Tue, 25 Feb 2025 18:40:45 +0900 Subject: [PATCH 07/20] Feat : all items component type --- ...llItems.styles.jsx => AllItems.styles.tsx} | 0 .../AllItems/{AllItems.jsx => AllItems.tsx} | 23 +++++++++++-------- ...oneItem.styles.jsx => NoneItem.styles.tsx} | 0 .../NoneItem/{NoneItem.jsx => NoneItem.tsx} | 2 +- 4 files changed, 15 insertions(+), 10 deletions(-) rename src/components/Items/AllItems/{AllItems.styles.jsx => AllItems.styles.tsx} (100%) rename src/components/Items/AllItems/{AllItems.jsx => AllItems.tsx} (78%) rename src/components/NoneItem/{NoneItem.styles.jsx => NoneItem.styles.tsx} (100%) rename src/components/NoneItem/{NoneItem.jsx => NoneItem.tsx} (78%) diff --git a/src/components/Items/AllItems/AllItems.styles.jsx b/src/components/Items/AllItems/AllItems.styles.tsx similarity index 100% rename from src/components/Items/AllItems/AllItems.styles.jsx rename to src/components/Items/AllItems/AllItems.styles.tsx diff --git a/src/components/Items/AllItems/AllItems.jsx b/src/components/Items/AllItems/AllItems.tsx similarity index 78% rename from src/components/Items/AllItems/AllItems.jsx rename to src/components/Items/AllItems/AllItems.tsx index 8d684a21..7d1775c2 100644 --- a/src/components/Items/AllItems/AllItems.jsx +++ b/src/components/Items/AllItems/AllItems.tsx @@ -5,18 +5,23 @@ import ItemCard from "../ItemCard/ItemCard"; import Dropdown from "../../common/Dropdown/Dropdown"; import Search from "../../Search/Search"; import NoneItem from "../../NoneItem/NoneItem"; -import { getProducts } from "../../../api/products"; +import { getProducts, Items } from "../../../api/products"; import Paging from "../../Paging/Paging"; import useResize from "../../../hooks/useResize"; const LIST = ["최신순", "좋아요순"]; +export interface AddItem { + list: Items[]; + totalCount: number; +} + export default function AllItems() { - const [items, setItems] = useState([]); - const [currentPage, setCurrentPage] = useState(1); - const [sortOption, setSortOption] = useState("최신순"); - const [keyword, setKeyword] = useState(""); - const [totalItems, setTotalItems] = useState(0); + const [items, setItems] = useState([]); + const [currentPage, setCurrentPage] = useState(1); + const [sortOption, setSortOption] = useState("최신순"); + const [keyword, setKeyword] = useState(""); + const [totalItems, setTotalItems] = useState(0); const { showItems } = useResize(4, 6, 10); const orderByValue = sortOption === "최신순" ? "recent" : "favorite"; @@ -27,14 +32,14 @@ export default function AllItems() { pageSize: showItems, orderBy: orderByValue, keyword: keyword, - }).then((result) => { + }).then((result: AddItem) => { if (!result) return; setItems(result.list); setTotalItems(result.totalCount); }); }, [currentPage, showItems, orderByValue, keyword]); - const handleChangeClick = (sortOption) => { + const handleChangeClick = (sortOption: string) => { setSortOption(sortOption); setCurrentPage(1); }; @@ -57,7 +62,7 @@ export default function AllItems() { handleChangeClick(option)} /> diff --git a/src/components/NoneItem/NoneItem.styles.jsx b/src/components/NoneItem/NoneItem.styles.tsx similarity index 100% rename from src/components/NoneItem/NoneItem.styles.jsx rename to src/components/NoneItem/NoneItem.styles.tsx diff --git a/src/components/NoneItem/NoneItem.jsx b/src/components/NoneItem/NoneItem.tsx similarity index 78% rename from src/components/NoneItem/NoneItem.jsx rename to src/components/NoneItem/NoneItem.tsx index de86223d..c7fd09d0 100644 --- a/src/components/NoneItem/NoneItem.jsx +++ b/src/components/NoneItem/NoneItem.tsx @@ -1,6 +1,6 @@ import * as S from "./NoneItem.styles"; -export default function NoneItem({ list }) { +export default function NoneItem() { return ( 검색한 상품이 없습니다 From a2378ccbdc93aa49ac00e9e4ded87dbbd64e62a0 Mon Sep 17 00:00:00 2001 From: heejin Date: Tue, 25 Feb 2025 18:41:17 +0900 Subject: [PATCH 08/20] Feat : best item component type --- .../{BestItems.styles.jsx => BestItems.styles.tsx} | 0 .../Items/BestItems/{BestItems.jsx => BestItems.tsx} | 10 +++++++--- .../{ItemPage.styles.jsx => ItemPage.styles.tsx} | 0 .../pages/ItemPage/{ItemPage.jsx => ItemPage.tsx} | 0 4 files changed, 7 insertions(+), 3 deletions(-) rename src/components/Items/BestItems/{BestItems.styles.jsx => BestItems.styles.tsx} (100%) rename src/components/Items/BestItems/{BestItems.jsx => BestItems.tsx} (80%) rename src/components/pages/ItemPage/{ItemPage.styles.jsx => ItemPage.styles.tsx} (100%) rename src/components/pages/ItemPage/{ItemPage.jsx => ItemPage.tsx} (100%) diff --git a/src/components/Items/BestItems/BestItems.styles.jsx b/src/components/Items/BestItems/BestItems.styles.tsx similarity index 100% rename from src/components/Items/BestItems/BestItems.styles.jsx rename to src/components/Items/BestItems/BestItems.styles.tsx diff --git a/src/components/Items/BestItems/BestItems.jsx b/src/components/Items/BestItems/BestItems.tsx similarity index 80% rename from src/components/Items/BestItems/BestItems.jsx rename to src/components/Items/BestItems/BestItems.tsx index 07977174..fe413ad2 100644 --- a/src/components/Items/BestItems/BestItems.jsx +++ b/src/components/Items/BestItems/BestItems.tsx @@ -1,11 +1,15 @@ import * as S from "./BestItems.styles"; import { useState, useEffect } from "react"; import ItemCard from "../ItemCard/ItemCard"; -import { getProducts } from "../../../api/products"; +import { getProducts, Items } from "../../../api/products"; import useResize from "../../../hooks/useResize"; +export interface BestItem { + list: Items[]; +} + export default function BestItems() { - const [bestItems, setBestItems] = useState([]); + const [bestItems, setBestItems] = useState([]); const { showItems } = useResize(1, 2, 4); useEffect(() => { @@ -14,7 +18,7 @@ export default function BestItems() { pageSize: 4, orderBy: "favorite", keyword: "", - }).then((result) => { + }).then((result: BestItem) => { if (!result) return; const sortedBestItems = [...result.list].slice(0, 4); setBestItems(sortedBestItems); diff --git a/src/components/pages/ItemPage/ItemPage.styles.jsx b/src/components/pages/ItemPage/ItemPage.styles.tsx similarity index 100% rename from src/components/pages/ItemPage/ItemPage.styles.jsx rename to src/components/pages/ItemPage/ItemPage.styles.tsx diff --git a/src/components/pages/ItemPage/ItemPage.jsx b/src/components/pages/ItemPage/ItemPage.tsx similarity index 100% rename from src/components/pages/ItemPage/ItemPage.jsx rename to src/components/pages/ItemPage/ItemPage.tsx From f509000fd11cc7eb09cf5fa5f3aaa82c5deb996a Mon Sep 17 00:00:00 2001 From: heejin Date: Tue, 25 Feb 2025 18:44:12 +0900 Subject: [PATCH 09/20] Feat : header type --- .../common/Header/{Header.styles.jsx => Header.styles.tsx} | 2 +- src/components/common/Header/{Header.jsx => Header.tsx} | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/components/common/Header/{Header.styles.jsx => Header.styles.tsx} (97%) rename src/components/common/Header/{Header.jsx => Header.tsx} (91%) diff --git a/src/components/common/Header/Header.styles.jsx b/src/components/common/Header/Header.styles.tsx similarity index 97% rename from src/components/common/Header/Header.styles.jsx rename to src/components/common/Header/Header.styles.tsx index 8b32092b..163a4ddb 100644 --- a/src/components/common/Header/Header.styles.jsx +++ b/src/components/common/Header/Header.styles.tsx @@ -62,7 +62,7 @@ export const NavItems = styled.div` line-height: 26px; text-align: center; padding: 15px 21px; - color: ${theme.color.gray00}; + color: ${theme.color.gray100}; cursor: pointer; @media (max-width: 768px) { padding: 15px 0; diff --git a/src/components/common/Header/Header.jsx b/src/components/common/Header/Header.tsx similarity index 91% rename from src/components/common/Header/Header.jsx rename to src/components/common/Header/Header.tsx index 55e46589..31122e53 100644 --- a/src/components/common/Header/Header.jsx +++ b/src/components/common/Header/Header.tsx @@ -7,7 +7,7 @@ import theme from "../../../styles/theme"; export default function Header() { const location = useLocation().pathname; - const activeLink = ({ isActive }) => { + const activeLink = ({ isActive }: { isActive: boolean }) => { const isItemsOrAddItem = isActive || location.startsWith("/addItem"); return { @@ -20,7 +20,7 @@ export default function Header() { const navLink = [ { to: "/freeBoard", - style: ({ isActive }) => ({ + style: ({ isActive }: { isActive: boolean }) => ({ color: isActive ? `${theme.color.blue}` : `${theme.color.gray600}`, }), name: "자유게시판", From f6bf6a40cf4671b89b343330b81384d44ccfb597 Mon Sep 17 00:00:00 2001 From: heejin Date: Tue, 25 Feb 2025 18:54:10 +0900 Subject: [PATCH 10/20] Feat : apply type --- package-lock.json | 28 +++++++++++++++---- package.json | 5 +++- src/{App.jsx => App.tsx} | 0 src/components/{Router.jsx => Router.tsx} | 0 src/hooks/{useResize.js => useResize.tsx} | 10 +++++-- src/{index.js => index.tsx} | 2 +- .../{GlobalStyle.jsx => GlobalStyle.tsx} | 0 src/styles/{Layout.jsx => Layout.tsx} | 0 src/styles/{theme.jsx => theme.tsx} | 0 9 files changed, 35 insertions(+), 10 deletions(-) rename src/{App.jsx => App.tsx} (100%) rename src/components/{Router.jsx => Router.tsx} (100%) rename src/hooks/{useResize.js => useResize.tsx} (80%) rename src/{index.js => index.tsx} (71%) rename src/styles/{GlobalStyle.jsx => GlobalStyle.tsx} (100%) rename src/styles/{Layout.jsx => Layout.tsx} (100%) rename src/styles/{theme.jsx => theme.tsx} (100%) diff --git a/package-lock.json b/package-lock.json index 99b29892..46e192e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,8 +23,11 @@ "react-router-dom": "^6.28.1", "react-scripts": "5.0.1", "styled-components": "^6.1.14", - "typescript": "^5.7.3", "web-vitals": "^2.1.4" + }, + "devDependencies": { + "@types/lodash.debounce": "^4.0.9", + "typescript": "^4.9.5" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -4345,6 +4348,21 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, + "node_modules/@types/lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==", + "dev": true + }, + "node_modules/@types/lodash.debounce": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/lodash.debounce/-/lodash.debounce-4.0.9.tgz", + "integrity": "sha512-Ma5JcgTREwpLRwMM+XwBR7DaWe96nC38uCBDFKZWbNKD+osjVzdpnUSwBcqCptrp16sSOLBAUb50Car5I0TCsQ==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -16886,15 +16904,15 @@ } }, "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=14.17" + "node": ">=4.2.0" } }, "node_modules/unbox-primitive": { diff --git a/package.json b/package.json index 2cf1d248..2fec4dd9 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,6 @@ "react-router-dom": "^6.28.1", "react-scripts": "5.0.1", "styled-components": "^6.1.14", - "typescript": "^5.7.3", "web-vitals": "^2.1.4" }, "scripts": { @@ -44,5 +43,9 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "@types/lodash.debounce": "^4.0.9", + "typescript": "^4.9.5" } } diff --git a/src/App.jsx b/src/App.tsx similarity index 100% rename from src/App.jsx rename to src/App.tsx diff --git a/src/components/Router.jsx b/src/components/Router.tsx similarity index 100% rename from src/components/Router.jsx rename to src/components/Router.tsx diff --git a/src/hooks/useResize.js b/src/hooks/useResize.tsx similarity index 80% rename from src/hooks/useResize.js rename to src/hooks/useResize.tsx index 4bb0f51b..aa9a2059 100644 --- a/src/hooks/useResize.js +++ b/src/hooks/useResize.tsx @@ -1,7 +1,11 @@ import { useState, useEffect, useMemo } from "react"; -import throttle from "lodash.throttle"; +import debounce from "lodash.debounce"; -export default function useResize(mobile, tablet, desktop) { +export default function useResize( + mobile: number, + tablet: number, + desktop: number +) { const [showItems, setShowItems] = useState(desktop); const updateItemsCount = () => { @@ -15,7 +19,7 @@ export default function useResize(mobile, tablet, desktop) { }; const handleThrottleUpdate = useMemo( - () => throttle(updateItemsCount, 500), + () => debounce(updateItemsCount, 500), [] ); diff --git a/src/index.js b/src/index.tsx similarity index 71% rename from src/index.js rename to src/index.tsx index d4c777aa..b64fe63e 100644 --- a/src/index.js +++ b/src/index.tsx @@ -3,7 +3,7 @@ import ReactDOM from "react-dom/client"; import App from "./App"; import GlobalStyle from "./styles/GlobalStyle"; -ReactDOM.createRoot(document.getElementById("root")).render( +ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( <> diff --git a/src/styles/GlobalStyle.jsx b/src/styles/GlobalStyle.tsx similarity index 100% rename from src/styles/GlobalStyle.jsx rename to src/styles/GlobalStyle.tsx diff --git a/src/styles/Layout.jsx b/src/styles/Layout.tsx similarity index 100% rename from src/styles/Layout.jsx rename to src/styles/Layout.tsx diff --git a/src/styles/theme.jsx b/src/styles/theme.tsx similarity index 100% rename from src/styles/theme.jsx rename to src/styles/theme.tsx From 1461f32578e68db79b18da364559ae6bd4de7606 Mon Sep 17 00:00:00 2001 From: heejin Date: Tue, 25 Feb 2025 19:53:34 +0900 Subject: [PATCH 11/20] Feat : item card component type --- src/components/Items/AllItems/AllItems.tsx | 4 +-- ...temCard.styles.jsx => ItemCard.styles.tsx} | 26 ++++++++++++------- .../ItemCard/{ItemCard.jsx => ItemCard.tsx} | 11 +++++++- ...eImage.styles.jsx => NoneImage.styles.tsx} | 8 +++--- .../{NoneImage.jsx => NoneImage.tsx} | 4 +-- .../pages/AddItemPage/AddItemPage.tsx | 6 ++--- 6 files changed, 37 insertions(+), 22 deletions(-) rename src/components/Items/ItemCard/{ItemCard.styles.jsx => ItemCard.styles.tsx} (78%) rename src/components/Items/ItemCard/{ItemCard.jsx => ItemCard.tsx} (89%) rename src/components/NoneImage/{NoneImage.styles.jsx => NoneImage.styles.tsx} (72%) rename src/components/NoneImage/{NoneImage.jsx => NoneImage.tsx} (61%) diff --git a/src/components/Items/AllItems/AllItems.tsx b/src/components/Items/AllItems/AllItems.tsx index 7d1775c2..2008b1d6 100644 --- a/src/components/Items/AllItems/AllItems.tsx +++ b/src/components/Items/AllItems/AllItems.tsx @@ -11,7 +11,7 @@ import useResize from "../../../hooks/useResize"; const LIST = ["최신순", "좋아요순"]; -export interface AddItem { +export interface AllItem { list: Items[]; totalCount: number; } @@ -32,7 +32,7 @@ export default function AllItems() { pageSize: showItems, orderBy: orderByValue, keyword: keyword, - }).then((result: AddItem) => { + }).then((result: AllItem) => { if (!result) return; setItems(result.list); setTotalItems(result.totalCount); diff --git a/src/components/Items/ItemCard/ItemCard.styles.jsx b/src/components/Items/ItemCard/ItemCard.styles.tsx similarity index 78% rename from src/components/Items/ItemCard/ItemCard.styles.jsx rename to src/components/Items/ItemCard/ItemCard.styles.tsx index 9727553c..bd094831 100644 --- a/src/components/Items/ItemCard/ItemCard.styles.jsx +++ b/src/components/Items/ItemCard/ItemCard.styles.tsx @@ -1,32 +1,38 @@ import styled from "styled-components"; import theme from "../../../styles/theme"; +export interface List { + list: string; +} + +type ScreenSize = keyof typeof BEST_IMG; + export const BEST_IMG = { PC: "282px", Tablet: "343px", - Moblie: "343px", -}; + Mobile: "343px", +} as const; export const ALL_IMG = { PC: "221px", Tablet: "221px", - Moblie: "168px", -}; + Mobile: "168px", +} as const; -export const getImgSize = (list, screen) => { +export const getImgSize = (list: string, screen: ScreenSize) => { const item = list === "best" ? BEST_IMG : ALL_IMG; return item[screen]; }; -export const ItemImg = styled.img` +export const ItemImg = styled.img` width: ${({ list }) => getImgSize(list, "PC")}; height: ${({ list }) => getImgSize(list, "PC")}; border-radius: 16px; object-fit: cover; @media (max-width: 767px) { - width: ${({ list }) => getImgSize(list, "Moblie")}; - height: ${({ list }) => getImgSize(list, "Moblie")}; + width: ${({ list }) => getImgSize(list, "Mobile")}; + height: ${({ list }) => getImgSize(list, "Mobile")}; } @media (min-width: 768px) and (max-width: 1199px) { @@ -40,14 +46,14 @@ export const ItemImg = styled.img` } `; -export const ItemContainer = styled.div` +export const ItemContainer = styled.div` width: ${({ list }) => getImgSize(list, "PC")}; display: flex; flex-direction: column; gap: 16px; @media (max-width: 767px) { - width: ${({ list }) => getImgSize(list, "Moblie")}; + width: ${({ list }) => getImgSize(list, "Mobile")}; } @media (min-width: 768px) and (max-width: 1199px) { diff --git a/src/components/Items/ItemCard/ItemCard.jsx b/src/components/Items/ItemCard/ItemCard.tsx similarity index 89% rename from src/components/Items/ItemCard/ItemCard.jsx rename to src/components/Items/ItemCard/ItemCard.tsx index 33b01380..8089d838 100644 --- a/src/components/Items/ItemCard/ItemCard.jsx +++ b/src/components/Items/ItemCard/ItemCard.tsx @@ -4,6 +4,15 @@ import NoneImage from "../../NoneImage/NoneImage"; import { useState } from "react"; import { useNavigate } from "react-router-dom"; +interface Card { + list: string; + id: string; + images: string; + name: string; + price: number; + favoriteCount: number; +} + export default function ItemCard({ list = "best", id, @@ -11,7 +20,7 @@ export default function ItemCard({ name, price, favoriteCount, -}) { +}: Card) { const [isImgError, setIsImgError] = useState(false); const navigate = useNavigate(); diff --git a/src/components/NoneImage/NoneImage.styles.jsx b/src/components/NoneImage/NoneImage.styles.tsx similarity index 72% rename from src/components/NoneImage/NoneImage.styles.jsx rename to src/components/NoneImage/NoneImage.styles.tsx index 1ade409d..c8459201 100644 --- a/src/components/NoneImage/NoneImage.styles.jsx +++ b/src/components/NoneImage/NoneImage.styles.tsx @@ -1,8 +1,8 @@ import styled from "styled-components"; -import { getImgSize } from "../Items/ItemCard/ItemCard.styles"; +import { getImgSize, List } from "../Items/ItemCard/ItemCard.styles"; import theme from "../../styles/theme"; -export const NoneImgContainer = styled.div` +export const NoneImgContainer = styled.div` width: ${({ list }) => getImgSize(list, "PC")}; height: ${({ list }) => getImgSize(list, "PC")}; border-radius: 16px; @@ -13,8 +13,8 @@ export const NoneImgContainer = styled.div` flex-shrink: 0; @media (max-width: 767px) { - width: ${({ list }) => getImgSize(list, "Moblie")}; - height: ${({ list }) => getImgSize(list, "Moblie")}; + width: ${({ list }) => getImgSize(list, "Mobile")}; + height: ${({ list }) => getImgSize(list, "Mobile")}; } @media (min-width: 768px) and (max-width: 1199px) { diff --git a/src/components/NoneImage/NoneImage.jsx b/src/components/NoneImage/NoneImage.tsx similarity index 61% rename from src/components/NoneImage/NoneImage.jsx rename to src/components/NoneImage/NoneImage.tsx index 031e7130..5b3b6528 100644 --- a/src/components/NoneImage/NoneImage.jsx +++ b/src/components/NoneImage/NoneImage.tsx @@ -1,9 +1,9 @@ import * as S from "./NoneImage.styles"; import noneImg from "../../assets/icons/image.svg"; -export default function NoneImage({ list, detail }) { +export default function NoneImage({ list }: { list: string }) { return ( - + ); diff --git a/src/components/pages/AddItemPage/AddItemPage.tsx b/src/components/pages/AddItemPage/AddItemPage.tsx index 176449b1..3a75db96 100644 --- a/src/components/pages/AddItemPage/AddItemPage.tsx +++ b/src/components/pages/AddItemPage/AddItemPage.tsx @@ -6,7 +6,7 @@ import { useState } from "react"; import { useNavigate } from "react-router-dom"; import { isValidAddItem } from "../../../utils/addValidate"; -interface AddItem { +export interface AddItem { images: string | null; name: string; description: string; @@ -40,10 +40,10 @@ export default function AddItemPage() { // IME composition if (e.nativeEvent.isComposing) return; - const eqaulTag = values.tags.some((existing) => existing === tag); + const equalTag = values.tags.some((existing) => existing === tag); const enterEvent = e.key === "Enter"; - if (!eqaulTag) { + if (!equalTag) { if (enterEvent && tag.trim() !== "") { setValues((prevState) => ({ ...prevState, From 7c820a5bcc86d956201725afa82b6911ad2ff7ed Mon Sep 17 00:00:00 2001 From: heejin Date: Tue, 25 Feb 2025 20:16:24 +0900 Subject: [PATCH 12/20] Feat : detail component type --- .../{Detail.styles.jsx => Detail.styles.tsx} | 4 --- .../Detail/{Detail.jsx => Detail.tsx} | 31 +++++++++++++------ src/components/Tag/Tag.styles.tsx | 4 +-- src/components/Tag/Tag.tsx | 4 +-- .../User/{User.styles.jsx => User.styles.tsx} | 12 ++++--- src/components/User/{User.jsx => User.tsx} | 8 ++++- ...Page.styles.jsx => ProductPage.styles.tsx} | 0 .../{ProductPage.jsx => ProductPage.tsx} | 0 8 files changed, 41 insertions(+), 22 deletions(-) rename src/components/Detail/{Detail.styles.jsx => Detail.styles.tsx} (98%) rename src/components/Detail/{Detail.jsx => Detail.tsx} (76%) rename src/components/User/{User.styles.jsx => User.styles.tsx} (77%) rename src/components/User/{User.jsx => User.tsx} (78%) rename src/components/pages/ProductPage/{ProductPage.styles.jsx => ProductPage.styles.tsx} (100%) rename src/components/pages/ProductPage/{ProductPage.jsx => ProductPage.tsx} (100%) diff --git a/src/components/Detail/Detail.styles.jsx b/src/components/Detail/Detail.styles.tsx similarity index 98% rename from src/components/Detail/Detail.styles.jsx rename to src/components/Detail/Detail.styles.tsx index 6137f2e5..ac1ba506 100644 --- a/src/components/Detail/Detail.styles.jsx +++ b/src/components/Detail/Detail.styles.tsx @@ -48,10 +48,6 @@ export const NoneImageContainer = styled.div` display: flex; justify-content: center; align-items: center; - - /* @media (max-width: 767px) { - min-width: 343px; - } */ `; export const NoneImage = styled.img` diff --git a/src/components/Detail/Detail.jsx b/src/components/Detail/Detail.tsx similarity index 76% rename from src/components/Detail/Detail.jsx rename to src/components/Detail/Detail.tsx index b8825c2a..405942f1 100644 --- a/src/components/Detail/Detail.jsx +++ b/src/components/Detail/Detail.tsx @@ -2,6 +2,7 @@ import * as S from "./Detail.styles"; import { useState, useEffect } from "react"; import { useParams } from "react-router-dom"; import { getProductInfo } from "../../api/products"; +import { AddItem } from "../pages/AddItemPage/AddItemPage"; import Tag from "../Tag/Tag"; import User from "../User/User"; import emptyHeart from "../../assets/icons/emptyHeart.svg"; @@ -9,8 +10,19 @@ import fullHeart from "../../assets/icons/fullHeart.svg"; import dots from "../../assets/icons/dots.svg"; import noneImg from "../../assets/icons/image.svg"; +interface DetailItem extends AddItem { + favoriteCount: number; + createdAt: string; + updatedAt: string; + ownerNickname: string; +} + +interface ProductParams extends Record { + productId: string; +} + export default function Detail() { - const [product, setProduct] = useState({ + const [product, setProduct] = useState({ name: "", description: "", price: 0, @@ -21,14 +33,16 @@ export default function Detail() { updatedAt: "", ownerNickname: "", }); - const [isFull, setIsFull] = useState(false); - const [isImgError, setIsImgError] = useState(false); - const { productId } = useParams(); + const [isFull, setIsFull] = useState(false); + const [isImgError, setIsImgError] = useState(false); + const { productId } = useParams(); useEffect(() => { - getProductInfo(productId) - .then((result) => setProduct(result)) - .catch((error) => console.error(error)); + if (productId) { + getProductInfo(productId) + .then((result) => setProduct(result)) + .catch((error) => console.error(error)); + } }, [productId]); const handleHeartChange = () => { @@ -48,7 +62,6 @@ export default function Detail() { )} -
@@ -67,7 +80,7 @@ export default function Detail() { 상품 태그 {product.tags.map((tag) => ( - + ))}
diff --git a/src/components/Tag/Tag.styles.tsx b/src/components/Tag/Tag.styles.tsx index 51c06a07..f6ae6c92 100644 --- a/src/components/Tag/Tag.styles.tsx +++ b/src/components/Tag/Tag.styles.tsx @@ -2,7 +2,7 @@ import { styled } from "styled-components"; import theme from "../../styles/theme"; interface Readonly { - readonly?: boolean; + $readonly?: boolean; } export const TagContainer = styled.li` @@ -28,5 +28,5 @@ export const DeleteTag = styled.img` height: 24px; cursor: pointer; - display: ${({ readonly }) => (readonly ? "none" : "block")}; + display: ${({ $readonly }) => ($readonly ? "none" : "block")}; `; diff --git a/src/components/Tag/Tag.tsx b/src/components/Tag/Tag.tsx index 628a0de2..47634048 100644 --- a/src/components/Tag/Tag.tsx +++ b/src/components/Tag/Tag.tsx @@ -3,7 +3,7 @@ import x from "../../assets/icons/delete.svg"; interface TagProps { tag: string; - onClick: () => void; + onClick?: () => void; readonly?: boolean; } @@ -12,7 +12,7 @@ export default function Tag({ tag, onClick, readonly }: TagProps) { #{tag} - + ); diff --git a/src/components/User/User.styles.jsx b/src/components/User/User.styles.tsx similarity index 77% rename from src/components/User/User.styles.jsx rename to src/components/User/User.styles.tsx index 6c4b2edd..d1ca5cc7 100644 --- a/src/components/User/User.styles.jsx +++ b/src/components/User/User.styles.tsx @@ -1,14 +1,18 @@ import styled from "styled-components"; import theme from "../../styles/theme"; -export const User = styled.div` +interface Detail { + $detail: boolean; +} + +export const User = styled.div` display: flex; justify-content: flex-start; align-items: center; gap: ${({ $detail }) => ($detail ? "16px" : "8px")}; `; -export const Profile = styled.img` +export const Profile = styled.img` width: ${({ $detail }) => ($detail ? "40px" : "32px")}; height: ${({ $detail }) => ($detail ? "40px" : "32px")}; border-radius: 100px; @@ -20,13 +24,13 @@ export const UserInfo = styled.div` gap: 4px; `; -export const Name = styled.div` +export const Name = styled.div` font: ${({ $detail }) => $detail ? `${theme.font.H7Regular}` : `${theme.font.H8}`}; color: ${theme.color.gray600}; `; -export const CreatedAt = styled.div` +export const CreatedAt = styled.div` font: ${({ $detail }) => $detail ? `${theme.font.H7Regular}` : `${theme.font.H8}`}; color: ${theme.color.gray400}; diff --git a/src/components/User/User.jsx b/src/components/User/User.tsx similarity index 78% rename from src/components/User/User.jsx rename to src/components/User/User.tsx index 36822b3a..dcc230da 100644 --- a/src/components/User/User.jsx +++ b/src/components/User/User.tsx @@ -1,7 +1,13 @@ import * as S from "./User.styles"; import user from "../../assets/icons/user.svg"; -export default function User({ owner, createdAt, detail }) { +interface UserProps { + owner: string; + createdAt: string; + detail: boolean; +} + +export default function User({ owner, createdAt, detail }: UserProps) { const date = new Date(createdAt); const formattedDate = `${date.getFullYear()}.${String( date.getMonth() + 1 diff --git a/src/components/pages/ProductPage/ProductPage.styles.jsx b/src/components/pages/ProductPage/ProductPage.styles.tsx similarity index 100% rename from src/components/pages/ProductPage/ProductPage.styles.jsx rename to src/components/pages/ProductPage/ProductPage.styles.tsx diff --git a/src/components/pages/ProductPage/ProductPage.jsx b/src/components/pages/ProductPage/ProductPage.tsx similarity index 100% rename from src/components/pages/ProductPage/ProductPage.jsx rename to src/components/pages/ProductPage/ProductPage.tsx From c42c8dad0a752b3be0292bfbe702596d5c673c34 Mon Sep 17 00:00:00 2001 From: heejin Date: Tue, 25 Feb 2025 21:29:10 +0900 Subject: [PATCH 13/20] Feat : comment component type --- ...{Comment.styles.jsx => Comment.styles.tsx} | 0 .../Comment/{Comment.jsx => Comment.tsx} | 0 ...put.styles.jsx => CommentInput.styles.tsx} | 0 .../{CommentInput.jsx => CommentInput.tsx} | 6 ++-- ...List.styles.jsx => CommentList.styles.tsx} | 0 .../{CommentList.jsx => CommentList.tsx} | 31 ++++++++++--------- src/components/Detail/Detail.tsx | 2 +- ...ment.styles.jsx => NoneComment.styles.tsx} | 0 .../{NoneComment.jsx => NoneComment.tsx} | 0 src/components/common/Input/Input.tsx | 2 +- 10 files changed, 23 insertions(+), 18 deletions(-) rename src/components/Comment/{Comment.styles.jsx => Comment.styles.tsx} (100%) rename src/components/Comment/{Comment.jsx => Comment.tsx} (100%) rename src/components/Comment/{CommentInput.styles.jsx => CommentInput.styles.tsx} (100%) rename src/components/Comment/{CommentInput.jsx => CommentInput.tsx} (82%) rename src/components/Comment/{CommentList.styles.jsx => CommentList.styles.tsx} (100%) rename src/components/Comment/{CommentList.jsx => CommentList.tsx} (75%) rename src/components/NoneComment/{NoneComment.styles.jsx => NoneComment.styles.tsx} (100%) rename src/components/NoneComment/{NoneComment.jsx => NoneComment.tsx} (100%) diff --git a/src/components/Comment/Comment.styles.jsx b/src/components/Comment/Comment.styles.tsx similarity index 100% rename from src/components/Comment/Comment.styles.jsx rename to src/components/Comment/Comment.styles.tsx diff --git a/src/components/Comment/Comment.jsx b/src/components/Comment/Comment.tsx similarity index 100% rename from src/components/Comment/Comment.jsx rename to src/components/Comment/Comment.tsx diff --git a/src/components/Comment/CommentInput.styles.jsx b/src/components/Comment/CommentInput.styles.tsx similarity index 100% rename from src/components/Comment/CommentInput.styles.jsx rename to src/components/Comment/CommentInput.styles.tsx diff --git a/src/components/Comment/CommentInput.jsx b/src/components/Comment/CommentInput.tsx similarity index 82% rename from src/components/Comment/CommentInput.jsx rename to src/components/Comment/CommentInput.tsx index 1b6129ee..e06f07b8 100644 --- a/src/components/Comment/CommentInput.jsx +++ b/src/components/Comment/CommentInput.tsx @@ -3,7 +3,7 @@ import * as S from "./CommentInput.styles"; import { useState } from "react"; export default function CommentInput() { - const [comment, setComment] = useState(""); + const [comment, setComment] = useState(""); return ( @@ -14,7 +14,9 @@ export default function CommentInput() { largeHeight="140px" isTextarea value={comment} - onChange={(e) => setComment(e.target.value)} + onChange={(e: React.ChangeEvent) => + setComment(e.target.value) + } />