diff --git a/package-lock.json b/package-lock.json
index fa8c604a..1a44ef75 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-hook-form": "^7.62.0",
"react-router-dom": "^6.30.0",
"react-scripts": "5.0.1",
"sass": "^1.89.0",
@@ -15308,6 +15309,21 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
},
+ "node_modules/react-hook-form": {
+ "version": "7.62.0",
+ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.62.0.tgz",
+ "integrity": "sha512-7KWFejc98xqG/F4bAxpL41NB3o1nnvQO1RWZT3TqRZYL8RryQETGfEdVnJN2fy1crCiBLLjkRBVK05j24FxJGA==",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-hook-form"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17 || ^18 || ^19"
+ }
+ },
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
diff --git a/package.json b/package.json
index 2265d62e..f39c45b9 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-hook-form": "^7.62.0",
"react-router-dom": "^6.30.0",
"react-scripts": "5.0.1",
"sass": "^1.89.0",
diff --git a/src/App.tsx b/src/App.tsx
index fca54db3..d24328d9 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -2,8 +2,9 @@ import { createBrowserRouter, RouterProvider } from "react-router-dom";
import routes from "./routes";
import "./styles/style.scss";
import ToastContainer from "./components/Toast/ToastContainer";
-import { Global } from "@emotion/react";
+import { Global, ThemeProvider } from "@emotion/react";
import { globalStyle } from "./styles/globalStyle";
+import { theme } from "@styles/theme";
function App() {
const router = createBrowserRouter(routes, {
@@ -13,9 +14,11 @@ function App() {
});
return (
<>
-
-
-
+
+
+
+
+
>
);
}
diff --git a/src/components/AuthFormInput/AuthFormInput.js b/src/components/AuthFormInput/AuthFormInput.js
deleted file mode 100644
index 29cc97dd..00000000
--- a/src/components/AuthFormInput/AuthFormInput.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import React from "react";
-import { getAuthValidClassName } from "../../utils/authUtils";
-import PasswordInput from "../PasswordInput/PasswordInput";
-import Input from "../Input/Input";
-
-const AuthFormInput = ({
- label,
- type,
- name,
- value,
- onChange,
- placeholder,
- validInfo,
-}) => {
- const hasError = validInfo.isValid === false;
-
- return (
-
-
- {type === "password" ? (
-
- ) : (
-
- )}
- {hasError &&
{validInfo.msg}
}
-
- );
-};
-
-export default AuthFormInput;
diff --git a/src/components/AuthFormInput/AuthFormInput.tsx b/src/components/AuthFormInput/AuthFormInput.tsx
new file mode 100644
index 00000000..9ce5bf75
--- /dev/null
+++ b/src/components/AuthFormInput/AuthFormInput.tsx
@@ -0,0 +1,31 @@
+import PasswordInput from "../PasswordInput/PasswordInput";
+import Input from "../Input/Input";
+import { forwardRef, InputHTMLAttributes } from "react";
+import {
+ AuthFormItem,
+ AuthFormLabel,
+ AuthFormErrorMsg,
+} from "@styles/formStyles";
+
+interface Props extends InputHTMLAttributes {
+ label: string;
+ errorMsg?: string;
+}
+
+const AuthFormInput = forwardRef(
+ ({ label, errorMsg, ...props }, ref) => {
+ return (
+
+ {label}
+ {props.type === "password" ? (
+
+ ) : (
+
+ )}
+ {errorMsg && {errorMsg}}
+
+ );
+ }
+);
+
+export default AuthFormInput;
diff --git a/src/components/AuthGuide/AuthGuide.js b/src/components/AuthGuide/AuthGuide.js
deleted file mode 100644
index f14ed6f3..00000000
--- a/src/components/AuthGuide/AuthGuide.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import { Link } from "react-router-dom";
-
-const AuthGuide = ({ guideTxt, linkTxt, linkUrl }) => {
- return (
-
-
{guideTxt}
-
- {linkTxt}
-
-
- );
-};
-
-export default AuthGuide;
diff --git a/src/components/AuthGuide/AuthGuide.tsx b/src/components/AuthGuide/AuthGuide.tsx
new file mode 100644
index 00000000..52d9a0d0
--- /dev/null
+++ b/src/components/AuthGuide/AuthGuide.tsx
@@ -0,0 +1,39 @@
+import styled from "@emotion/styled/macro";
+import { theme } from "@styles/theme";
+import { Link } from "react-router-dom";
+
+interface Props {
+ guideTxt: string;
+ linkTxt: string;
+ linkUrl: string;
+}
+
+const AuthGuide = ({ guideTxt, linkTxt, linkUrl }: Props) => {
+ return (
+
+ {guideTxt}
+
+ {linkTxt}
+
+
+ );
+};
+
+const AuthGuideBox = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-top: 24px;
+ font-size: 14px;
+ font-weight: 500;
+ gap: 5px;
+`;
+
+const AuthGuideLink = styled(Link)`
+ text-decoration: underline;
+ text-underline-offset: 3px;
+ text-decoration-thickness: 2px;
+ color: ${theme.colors.primaryColor};
+`;
+
+export default AuthGuide;
diff --git a/src/components/AuthSns/AuthSns.js b/src/components/AuthSns/AuthSns.tsx
similarity index 58%
rename from src/components/AuthSns/AuthSns.js
rename to src/components/AuthSns/AuthSns.tsx
index 983bbeb7..b3be70d1 100644
--- a/src/components/AuthSns/AuthSns.js
+++ b/src/components/AuthSns/AuthSns.tsx
@@ -1,12 +1,13 @@
import { Link } from "react-router-dom";
import snsGoogle from "../../assets/images/icons/ic_sns_google.svg";
import snsKakao from "../../assets/images/icons/ic_sns_kakao.svg";
+import styled from "@emotion/styled/macro";
const AuthSns = () => {
return (
-
-
간편 로그인하기
-
+
+ 간편 로그인하기
+
-
{
-
-
+
+
);
};
+const AuthSnsBox = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-top: 24px;
+ padding: 16px 23px;
+ background-color: #e6f2ff;
+ border-radius: 8px;
+`;
+
+const AuthSnsLabel = styled.h2`
+ display: block;
+ font-size: 16px;
+ font-weight: 500;
+`;
+
+const AuthSnsList = styled.ul`
+ display: flex;
+ align-items: center;
+ gap: 16px;
+`;
+
export default AuthSns;
diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx
index 5744a2b2..bd2469b2 100644
--- a/src/components/Button/Button.tsx
+++ b/src/components/Button/Button.tsx
@@ -1,15 +1,12 @@
import { ButtonHTMLAttributes, ReactNode } from "react";
import { ButtonStyle, ButtonStyleProps } from "./ButtonStyle";
-interface BaseButtonProps {
- onClick?: () => void;
+interface ButtonProps
+ extends ButtonHTMLAttributes,
+ ButtonStyleProps {
children: ReactNode;
}
-type ButtonProps = ButtonHTMLAttributes &
- BaseButtonProps &
- ButtonStyleProps;
-
const Button = ({ onClick, children, ...props }: ButtonProps) => {
return (
diff --git a/src/components/Button/ButtonStyle.ts b/src/components/Button/ButtonStyle.ts
index 177d11fb..377003f0 100644
--- a/src/components/Button/ButtonStyle.ts
+++ b/src/components/Button/ButtonStyle.ts
@@ -2,34 +2,35 @@ import { css } from "@emotion/react";
import styled from "@emotion/styled/macro";
import { mq } from "../../styles/mixins";
import { Link } from "react-router-dom";
+import { theme } from "@styles/theme";
export interface ButtonStyleProps {
- color?: keyof typeof ButtonColors;
+ variant?: keyof typeof ButtonStyles;
size?: keyof typeof ButtonSize;
round?: boolean;
}
-export const ButtonColors = {
+export const ButtonStyles = {
primary: css`
color: #fff;
- background-color: var(--btn-primary);
+ background-color: ${theme.btn.primary};
&:hover {
- background-color: var(--btn-primary-hover);
+ background-color: ${theme.btn.hover};
}
&:active {
- background-color: var(--btn-primary-click);
+ background-color: ${theme.btn.click};
}
&:disabled {
- background-color: var(--btn-disabled);
+ background-color: ${theme.btn.disabled};
}
`,
white: css`
- border: 1px solid var(--primary-color);
- color: var(--primary-color);
- background-color: var(--white);
+ border: 1px solid ${theme.colors.primaryColor};
+ color: ${theme.colors.primaryColor};
+ background-color: ${theme.colors.white};
`,
custom: css``,
};
@@ -69,7 +70,7 @@ export const ButtonBaseStyle = (props: ButtonStyleProps) => css`
cursor: pointer;
${props.size ? ButtonSize[props.size] : ButtonSize["sm"]};
- ${props.color ? ButtonColors[props.color] : ButtonColors["primary"]};
+ ${props.variant ? ButtonStyles[props.variant] : ButtonStyles["primary"]};
border-radius: ${props.round ? "40px" : "8px"};
`;
diff --git a/src/components/Input/Input.js b/src/components/Input/Input.js
deleted file mode 100644
index 3d85e01a..00000000
--- a/src/components/Input/Input.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import styles from "./Input.module.scss";
-
-const Input = ({
- type,
- name,
- value,
- onChange,
- placeholder,
- className,
- ...params
-}) => {
- const handleChangeValue = (e) => {
- onChange(e.target.value);
- };
-
- return (
-
- );
-};
-
-export default Input;
diff --git a/src/components/Input/Input.module.scss b/src/components/Input/Input.module.scss
deleted file mode 100644
index 77990b05..00000000
--- a/src/components/Input/Input.module.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-@use "../../styles/mixin" as mixin;
-
-.input {
- @include mixin.defaultInput;
-}
diff --git a/src/components/Input/Input.tsx b/src/components/Input/Input.tsx
new file mode 100644
index 00000000..cce44fec
--- /dev/null
+++ b/src/components/Input/Input.tsx
@@ -0,0 +1,10 @@
+import { forwardRef, InputHTMLAttributes } from "react";
+import { InputStyle } from "@styles/formStyles";
+
+interface Props extends InputHTMLAttributes {}
+
+const Input = forwardRef(({ ...props }, ref) => {
+ return ;
+});
+
+export default Input;
diff --git a/src/components/PasswordInput/PasswordInput.js b/src/components/PasswordInput/PasswordInput.js
deleted file mode 100644
index 16bd3c5c..00000000
--- a/src/components/PasswordInput/PasswordInput.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import usePasswordToggle from "../../hooks/usePasswordToggle";
-import styles from "./PasswordInput.module.scss";
-
-const PasswordInput = ({
- name,
- value,
- onChange,
- placeholder,
- className,
- isToggle = true,
-}) => {
- const { toggle, handleClickToggle, toggleImg } = usePasswordToggle();
-
- const handleChangeValue = (e) => {
- onChange(e.target.value);
- };
-
- return (
-
-
- {isToggle && (
-
- )}
-
- );
-};
-
-export default PasswordInput;
diff --git a/src/components/PasswordInput/PasswordInput.module.scss b/src/components/PasswordInput/PasswordInput.module.scss
deleted file mode 100644
index f4449672..00000000
--- a/src/components/PasswordInput/PasswordInput.module.scss
+++ /dev/null
@@ -1,20 +0,0 @@
-@use "../../styles/mixin" as mixin;
-
-.password {
- &-box {
- position: relative;
- }
-
- &-input {
- @include mixin.defaultInput;
- padding-right: 60px;
- }
-
- &__toggle-btn {
- position: absolute;
- top: 0;
- right: 12px;
- height: 100%;
- padding: 0 12px;
- }
-}
diff --git a/src/components/PasswordInput/PasswordInput.tsx b/src/components/PasswordInput/PasswordInput.tsx
new file mode 100644
index 00000000..bb23af8e
--- /dev/null
+++ b/src/components/PasswordInput/PasswordInput.tsx
@@ -0,0 +1,52 @@
+/** @jsxImportSource @emotion/react */
+import { forwardRef, InputHTMLAttributes } from "react";
+import usePasswordToggle from "../../hooks/usePasswordToggle";
+import { InputStyle } from "@styles/formStyles";
+import styled from "@emotion/styled/macro";
+
+interface Props extends InputHTMLAttributes {
+ placeholder?: string;
+ className?: string;
+ isToggle?: boolean;
+}
+
+const PasswordInput = forwardRef(
+ ({ type, isToggle = true, ...props }, ref) => {
+ const { toggle, handleClickToggle, toggleImg } = usePasswordToggle();
+
+ return (
+
+
+ {isToggle && (
+
+
+
+ )}
+
+ );
+ }
+);
+
+const PasswordBox = styled.div`
+ position: relative;
+`;
+
+const PasswordToggleBtn = styled.button`
+ position: absolute;
+ top: 0;
+ right: 12px;
+ height: 100%;
+ padding: 0 12px;
+`;
+
+export default PasswordInput;
diff --git a/src/components/TagItem/TagItem.tsx b/src/components/TagItem/TagItem.tsx
index 847949b2..4584b247 100644
--- a/src/components/TagItem/TagItem.tsx
+++ b/src/components/TagItem/TagItem.tsx
@@ -4,19 +4,15 @@ import {
} from "@components/TagItem/TagItemStyle";
import { ButtonHTMLAttributes, HTMLAttributes, ReactNode } from "react";
-interface TagItemBase {
+interface TextProps extends HTMLAttributes {
+ type: "text";
+ children: ReactNode;
+}
+interface ButtonProps extends ButtonHTMLAttributes {
+ type: "button";
+ onClick: () => void;
children: ReactNode;
}
-
-type TextProps = HTMLAttributes &
- TagItemBase & {
- type: "text";
- };
-type ButtonProps = ButtonHTMLAttributes &
- TagItemBase & {
- type: "button";
- onClick: () => void;
- };
type TagItemProps = TextProps | ButtonProps;
diff --git a/src/components/TagItem/TagItemStyle.ts b/src/components/TagItem/TagItemStyle.ts
index cf9057ae..81be4480 100644
--- a/src/components/TagItem/TagItemStyle.ts
+++ b/src/components/TagItem/TagItemStyle.ts
@@ -1,6 +1,7 @@
import { css } from "@emotion/react";
import styled from "@emotion/styled/macro";
import DeleteIcon from "@assets/images/icons/ic_delete.svg";
+import { theme } from "@styles/theme";
const TagItemBaseStyle = css`
display: inline-flex;
@@ -8,8 +9,8 @@ const TagItemBaseStyle = css`
height: 36px;
padding: 5px 16px;
font-size: 16px;
- color: var(--gray800);
- background: var(--gray100);
+ color: ${theme.colors.gray800};
+ background: ${theme.colors.gray100};
border-radius: 26px;
&::before {
diff --git a/src/data/api.ts b/src/data/api.ts
index 8ce76626..b15c898d 100644
--- a/src/data/api.ts
+++ b/src/data/api.ts
@@ -1,12 +1,22 @@
-import { InquiryItemType, ProductItemType } from "types/productType";
+import {
+ InquiryListType,
+ ProductItemDetailType,
+ ProductListType,
+} from "types/productType";
const BASE_URL = process.env.REACT_APP_API_BASE_URL;
+interface ProductQueryProps {
+ page: number;
+ pageSize: number;
+ orderBy: "recent" | "favorite";
+}
+
export const getData = async ({
page = 1,
pageSize = 10,
orderBy = "recent",
-}) => {
+}: ProductQueryProps): Promise => {
const query = `page=${page}&pageSize=${pageSize}&orderBy=${orderBy}`;
const res = await fetch(`${BASE_URL}/products?${query}`);
@@ -20,7 +30,7 @@ export const getData = async ({
export const getProductInfo = async (
productId: number
-): Promise => {
+): Promise => {
const res = await fetch(`${BASE_URL}/products/${productId}`);
if (!res.ok) {
@@ -33,7 +43,7 @@ export const getProductInfo = async (
export const getProductInquiries = async (
productId: number
-): Promise<{ nextCursor: number; list: InquiryItemType[] }> => {
+): Promise => {
const res = await fetch(
`${BASE_URL}/products/${productId}/comments?limit=10`
);
diff --git a/src/index.js b/src/index.tsx
similarity index 66%
rename from src/index.js
rename to src/index.tsx
index 8db5acb8..153cce06 100644
--- a/src/index.js
+++ b/src/index.tsx
@@ -2,7 +2,9 @@ import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
-const root = ReactDOM.createRoot(document.getElementById("root"));
+const root = ReactDOM.createRoot(
+ document.getElementById("root") as HTMLElement
+);
root.render(
diff --git a/src/layouts/Footer.js b/src/layouts/Footer.tsx
similarity index 100%
rename from src/layouts/Footer.js
rename to src/layouts/Footer.tsx
diff --git a/src/layouts/Header.js b/src/layouts/Header.tsx
similarity index 100%
rename from src/layouts/Header.js
rename to src/layouts/Header.tsx
diff --git a/src/layouts/Layout.js b/src/layouts/Layout.tsx
similarity index 100%
rename from src/layouts/Layout.js
rename to src/layouts/Layout.tsx
diff --git a/src/pages/AddItemPage/AddItemPage.js b/src/pages/AddItemPage/AddItemPage.js
index f72ba23a..7ac6c26c 100644
--- a/src/pages/AddItemPage/AddItemPage.js
+++ b/src/pages/AddItemPage/AddItemPage.js
@@ -1,5 +1,5 @@
/** @jsxImportSource @emotion/react */
-import { useMemo, useState } from "react";
+import React, { useMemo, useState } from "react";
import Input from "../../components/Input/Input";
import styles from "./AddItemPage.module.scss";
import TextArea from "../../components/TextArea/TextArea";
@@ -94,7 +94,7 @@ const AddItemPage = () => {
type={"text"}
name={"title"}
value={prdName}
- onChange={setPrdName}
+ onChange={(e) => setPrdName(e.target.value)}
placeholder={"상품명을 입력해주세요"}
/>
@@ -121,7 +121,7 @@ const AddItemPage = () => {
type={"tel"}
name={"price"}
value={prdPrice}
- onChange={handleChangePrice}
+ onChange={(e) => handleChangePrice(e.target.value)}
placeholder={"판매 가격을 입력해주세요"}
/>
@@ -134,7 +134,7 @@ const AddItemPage = () => {
type={"text"}
name={"tag"}
value={tagInput}
- onChange={setTagInput}
+ onChange={(e) => setTagInput(e.target.value)}
placeholder={"태그를 입력해주세요"}
onKeyDown={handleAddTag}
/>
@@ -142,7 +142,8 @@ const AddItemPage = () => {
{tagList.map((tag, id) => (
{
handleDeleteTag(id);
}}
diff --git a/src/pages/LoginPage/LoginPage.js b/src/pages/LoginPage/LoginPage.js
deleted file mode 100644
index 5ff5978e..00000000
--- a/src/pages/LoginPage/LoginPage.js
+++ /dev/null
@@ -1,121 +0,0 @@
-import { useEffect, useState } from "react";
-import { Link, useNavigate } from "react-router-dom";
-import { checkValidEmail, checkValidPassword } from "../../utils/authUtils";
-import getLogo from "../../utils/getLogo";
-import AuthSns from "../../components/AuthSns/AuthSns";
-import AuthGuide from "../../components/AuthGuide/AuthGuide";
-import "../../styles/auth.scss";
-import styles from "./LoginPage.module.scss";
-import AuthFormInput from "../../components/AuthFormInput/AuthFormInput";
-import { getIsAllValid } from "../../utils/getIsAllValid";
-
-const INIT_VALID = {
- isValid: null,
- msg: "",
-};
-
-const LoginPage = () => {
- const nav = useNavigate();
- const [userEmail, setUserEmail] = useState("");
- const [userPassword, setUserPassword] = useState("");
- const [validUserEmail, setValidUserEmail] = useState(INIT_VALID);
- const [validUserPassword, setValidUserPassword] = useState(INIT_VALID);
- const [isAllValid, setIsAllValid] = useState(false);
-
- const getUserValidation = (name, value) => {
- let validEmail = validUserEmail;
- let validPassword = validUserPassword;
-
- switch (name) {
- case "email": {
- validEmail = checkValidEmail(value);
- break;
- }
- case "password": {
- validPassword = checkValidPassword(value);
- break;
- }
- // no default
- }
-
- return {
- validEmail,
- validPassword,
- };
- };
-
- const handleFocusOut = (e) => {
- const { name, value } = e.target;
-
- // 인풋 검증
- const { validEmail, validPassword } = getUserValidation(name, value);
- setValidUserEmail(() => validEmail);
- setValidUserPassword(() => validPassword);
- };
-
- const handleClickSubmit = (e) => {
- e.preventDefault();
- nav("/");
- };
-
- useEffect(() => {
- // 버튼 활성화 여부
- setIsAllValid(getIsAllValid([validUserEmail, validUserPassword]));
- }, [validUserEmail, validUserPassword]);
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default LoginPage;
diff --git a/src/pages/LoginPage/LoginPage.module.scss b/src/pages/LoginPage/LoginPage.module.scss
deleted file mode 100644
index 62fdafba..00000000
--- a/src/pages/LoginPage/LoginPage.module.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-@use "../../styles/mixin" as mixin;
-
-.loginPage {
- padding: 231px 0;
-
- @include mixin.tablet {
- padding: 190px 0;
- }
-
- @include mixin.mobile {
- padding: 80px 0;
- }
-}
diff --git a/src/pages/LoginPage/LoginPage.tsx b/src/pages/LoginPage/LoginPage.tsx
new file mode 100644
index 00000000..6a3d0ee5
--- /dev/null
+++ b/src/pages/LoginPage/LoginPage.tsx
@@ -0,0 +1,122 @@
+/** @jsxImportSource @emotion/react */
+import { Link } from "react-router-dom";
+import { getAuthValidStateClassName } from "../../utils/authUtils";
+import getLogo from "../../utils/getLogo";
+import AuthSns from "../../components/AuthSns/AuthSns";
+import AuthGuide from "../../components/AuthGuide/AuthGuide";
+import AuthFormInput from "../../components/AuthFormInput/AuthFormInput";
+import { SubmitHandler, useForm } from "react-hook-form";
+import { css } from "@emotion/react";
+import { AuthContainer, AuthForm, AuthLogoImage } from "@styles/formStyles";
+import Button from "@components/Button/Button";
+import styled from "@emotion/styled/macro";
+import { mq } from "@styles/mixins";
+
+interface FormDataType {
+ email: string;
+ password: string;
+}
+
+const LoginPage = () => {
+ const {
+ register,
+ handleSubmit,
+ formState: { errors, isValid, touchedFields },
+ } = useForm({ mode: "onBlur" });
+
+ const handleSubmitFormData: SubmitHandler = (data) => {
+ console.log(data);
+ };
+
+ return (
+
+
+
+
+
+
+
+
+ {/* 이메일 */}
+
+
+ {/* 비밀번호 */}
+
+
+
+
+
+
+
+
+ );
+};
+
+const LoginPageStyle = styled.div`
+ padding: 231px 0;
+
+ ${mq["tablet"]} {
+ padding: 190px 0;
+ }
+
+ ${mq["mobile"]} {
+ padding: 80px 0;
+ }
+`;
+
+export default LoginPage;
diff --git a/src/pages/MainPage/MainPage.js b/src/pages/MainPage/MainPage.tsx
similarity index 100%
rename from src/pages/MainPage/MainPage.js
rename to src/pages/MainPage/MainPage.tsx
diff --git a/src/pages/ProductDetailPage/components/DetailDropdown/DetailDropdownStyle.ts b/src/pages/ProductDetailPage/components/DetailDropdown/DetailDropdownStyle.ts
index 58d273a6..b64cfff4 100644
--- a/src/pages/ProductDetailPage/components/DetailDropdown/DetailDropdownStyle.ts
+++ b/src/pages/ProductDetailPage/components/DetailDropdown/DetailDropdownStyle.ts
@@ -1,9 +1,10 @@
import { css } from "@emotion/react";
import { mq } from "@styles/mixins";
+import { theme } from "@styles/theme";
export const DropdownListStyle = css`
width: 139px;
- border: 1px solid var(--gray300);
+ border: 1px solid ${theme.colors.gray300};
background: #fff;
border-radius: 8px;
z-index: 1;
@@ -17,11 +18,11 @@ export const DropdownListStyle = css`
export const DropdownItemStyle = css`
width: 100%;
padding: 12px 0 8px;
- color: var(--gray500);
+ color: ${theme.colors.gray500};
transition: background-color 0.3s ease;
&:hover {
- background-color: var(--gray100);
+ background-color: ${theme.colors.gray100};
}
${mq["mobile"]} {
diff --git a/src/pages/ProductDetailPage/components/ProductInfo/FavoriteButton.tsx b/src/pages/ProductDetailPage/components/ProductInfo/FavoriteButton.tsx
index b1018425..7b808e59 100644
--- a/src/pages/ProductDetailPage/components/ProductInfo/FavoriteButton.tsx
+++ b/src/pages/ProductDetailPage/components/ProductInfo/FavoriteButton.tsx
@@ -1,12 +1,13 @@
import { css } from "@emotion/react";
import { ReactComponent as HearIcon } from "@assets/images/icons/ic_heart.svg";
-import { ProductItemType } from "types/productType";
+import { ProductItemDetailType } from "types/productType";
import styled from "@emotion/styled/macro";
import { mq } from "@styles/mixins";
import { ButtonHTMLAttributes } from "react";
+import { theme } from "@styles/theme";
type Props = ButtonHTMLAttributes &
- Pick;
+ Pick;
const FavoriteButton = ({ favoriteCount, isFavorite, ...props }: Props) => {
return (
@@ -22,18 +23,18 @@ const activeHeartStyle = css`
`;
const inactiveHeartStyle = css`
- stroke: var(--gray500);
+ stroke: ${theme.colors.gray500};
fill: transparent;
`;
const HeartButton = styled.button<{ isFavorite?: boolean }>`
display: flex;
align-items: center;
- border: 1px solid var(--gray200);
+ border: 1px solid ${theme.colors.gray200};
padding: 4px 12px;
gap: 4px;
font-weight: 500;
- color: var(--gray500);
+ color: ${theme.colors.gray500};
border-radius: 35px;
path {
diff --git a/src/pages/ProductDetailPage/components/ProductInfo/ProductInfoContent.tsx b/src/pages/ProductDetailPage/components/ProductInfo/ProductInfoContent.tsx
index 2d374896..90e70e8d 100644
--- a/src/pages/ProductDetailPage/components/ProductInfo/ProductInfoContent.tsx
+++ b/src/pages/ProductDetailPage/components/ProductInfo/ProductInfoContent.tsx
@@ -3,15 +3,16 @@ import DetailDropdown from "@pages/ProductDetailPage/components/DetailDropdown/D
import ProductInfoItem from "@pages/ProductDetailPage/components/ProductInfo/ProductInfoItem";
import UserProfile from "@pages/ProductDetailPage/components/UserProfile/UserProfile";
import { formatDate, formatPrice } from "@utils/formatters";
-import { ProductItemType } from "types/productType";
+import { ProductItemDetailType } from "types/productType";
import TagList from "@pages/ProductDetailPage/components/ProductInfo/TagList";
import FavoriteButton from "@pages/ProductDetailPage/components/ProductInfo/FavoriteButton";
import styled from "@emotion/styled/macro";
import { mq } from "@styles/mixins";
import { css } from "@emotion/react";
+import { theme } from "@styles/theme";
interface Props {
- productInfo: ProductItemType;
+ productInfo: ProductItemDetailType;
}
const ProductInfoContent = ({ productInfo }: Props) => {
@@ -62,7 +63,7 @@ const InfoHeader = styled.div`
position: relative;
margin-bottom: 24px;
- border-bottom: 1px solid var(--gray200);
+ border-bottom: 1px solid ${theme.colors.gray200};
padding-bottom: 16px;
${mq["tablet"]} {
@@ -73,7 +74,7 @@ const InfoHeader = styled.div`
margin-bottom: 16px;
font-size: 24px;
font-weight: 600;
- color: var(--gray800);
+ color: ${theme.colors.gray800};
line-height: 1.3;
${mq["tablet"]} {
@@ -90,7 +91,7 @@ const InfoHeader = styled.div`
display: block;
font-size: 40px;
font-weight: 600;
- color: var(--gray800);
+ color: ${theme.colors.gray800};
line-height: 1.2;
${mq["tablet"]} {
@@ -125,7 +126,7 @@ const PostInfo = styled.div`
width: 1px;
height: 34px;
transform: translateY(-50%);
- background: var(--gray200);
+ background: ${theme.colors.gray200};
content: "";
}
}
diff --git a/src/pages/ProductDetailPage/components/ProductInfo/ProductInfoItem.tsx b/src/pages/ProductDetailPage/components/ProductInfo/ProductInfoItem.tsx
index ff133250..678db9d9 100644
--- a/src/pages/ProductDetailPage/components/ProductInfo/ProductInfoItem.tsx
+++ b/src/pages/ProductDetailPage/components/ProductInfo/ProductInfoItem.tsx
@@ -1,5 +1,6 @@
import styled from "@emotion/styled/macro";
import { mq } from "@styles/mixins";
+import { theme } from "@styles/theme";
import { ReactNode } from "react";
interface Props {
@@ -22,7 +23,7 @@ const InfoItem = styled.div`
.subject {
margin-bottom: 16px;
font-weight: 600;
- color: var(--gray600);
+ color: ${theme.colors.gray600};
${mq["tablet"]} {
margin-bottom: 8px;
@@ -31,7 +32,7 @@ const InfoItem = styled.div`
}
.desc {
- color: var(--gray600);
+ color: ${theme.colors.gray600};
white-space: pre-line;
}
`;
diff --git a/src/pages/ProductDetailPage/components/ProductInfo/index.tsx b/src/pages/ProductDetailPage/components/ProductInfo/index.tsx
index ba6e37db..edf1a098 100644
--- a/src/pages/ProductDetailPage/components/ProductInfo/index.tsx
+++ b/src/pages/ProductDetailPage/components/ProductInfo/index.tsx
@@ -6,13 +6,15 @@ import {
} from "@pages/ProductDetailPage/components/ProductInfo/indexStyle";
import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";
-import { ProductItemType } from "types/productType";
+import { ProductItemDetailType } from "types/productType";
import ProductInfoContent from "@pages/ProductDetailPage/components/ProductInfo/ProductInfoContent";
import { getProductInfo } from "@data/api";
const ProductInfo = () => {
const { productId } = useParams();
- const [productInfo, setProductInfo] = useState(null);
+ const [productInfo, setProductInfo] = useState(
+ null
+ );
useEffect(() => {
const getProduct = async () => {
diff --git a/src/pages/ProductDetailPage/components/ProductInfo/indexStyle.ts b/src/pages/ProductDetailPage/components/ProductInfo/indexStyle.ts
index 90030af7..4ea3b2ac 100644
--- a/src/pages/ProductDetailPage/components/ProductInfo/indexStyle.ts
+++ b/src/pages/ProductDetailPage/components/ProductInfo/indexStyle.ts
@@ -1,12 +1,13 @@
import styled from "@emotion/styled/macro";
-import { mq } from "../../../../styles/mixins";
+import { mq } from "@styles/mixins";
+import { theme } from "@styles/theme";
export const DetailInfoBox = styled.div`
display: flex;
align-items: flex-start;
gap: 24px;
margin-bottom: 40px;
- border-bottom: 1px solid var(--gray200);
+ border-bottom: 1px solid ${theme.colors.gray200};
padding-bottom: 40px;
${mq["tablet"]} {
diff --git a/src/pages/ProductDetailPage/components/ProductInquiry/ProductInquiryEditor.tsx b/src/pages/ProductDetailPage/components/ProductInquiry/ProductInquiryEditor.tsx
index 446b581f..180aff39 100644
--- a/src/pages/ProductDetailPage/components/ProductInquiry/ProductInquiryEditor.tsx
+++ b/src/pages/ProductDetailPage/components/ProductInquiry/ProductInquiryEditor.tsx
@@ -3,6 +3,7 @@ import Button from "@components/Button/Button";
import TextArea from "@components/TextArea/TextArea";
import { css } from "@emotion/react";
import InquiryUserProfile from "@pages/ProductDetailPage/components/ProductInquiry/InquiryUserProfile";
+import { theme } from "@styles/theme";
import { ChangeEvent, useState } from "react";
import { InquiryItemType } from "types/productType";
@@ -42,7 +43,7 @@ const InquiryEditor = ({