diff --git a/src/App.tsx b/src/App.tsx
index 7e1d97e..74e8365 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -2,6 +2,8 @@ import { BrowserRouter, Route, Routes } from "react-router-dom";
import HomePage from "./components/pages/Homepage.tsx";
import NavBar from "./components/nav/NavBar.tsx";
import GlobalStyle from "./components/style/GlobalStyle.tsx";
+import LoginPage from "./components/pages/LoginPage.tsx";
+import JoinPage from "./components/pages/JoinPage.tsx";
function App() {
return (
@@ -10,8 +12,9 @@ function App() {
- } />
-
+ } />
+ } />
+ } />
diff --git a/src/components/join/Button.tsx b/src/components/join/Button.tsx
new file mode 100644
index 0000000..55f70f8
--- /dev/null
+++ b/src/components/join/Button.tsx
@@ -0,0 +1,33 @@
+import styled from "@emotion/styled";
+
+const ButtonWrapStyle = styled.div`
+ cursor: pointer;
+ width: 100%;
+ background-color: rgb(0, 0, 128);
+ border-radius: 10px;
+ height: 50px;
+
+ border: 3px solid skyblue;
+
+ display: flex;
+ justify-content: center;
+ margin-top: 30px;
+`;
+
+const ButtonStyle = styled.button`
+ cursor: pointer;
+ color: white;
+ background-color: rgb(0, 0, 128);
+ font-weight: bold;
+ font-size: large;
+ border: none;
+`;
+
+const Button = () => {
+ return (
+
+ 회원가입
+
+ );
+};
+export default Button;
diff --git a/src/components/join/GotoLogin.tsx b/src/components/join/GotoLogin.tsx
new file mode 100644
index 0000000..0875bb6
--- /dev/null
+++ b/src/components/join/GotoLogin.tsx
@@ -0,0 +1,9 @@
+const GotoLogin = () => {
+ return (
+
+ 이미 계정이 있으신가요? 로그인
+
+ );
+};
+
+export default GotoLogin;
diff --git a/src/components/join/Input.tsx b/src/components/join/Input.tsx
new file mode 100644
index 0000000..d2b0c21
--- /dev/null
+++ b/src/components/join/Input.tsx
@@ -0,0 +1,21 @@
+import InputItem from "./InputItem";
+import styled from "@emotion/styled";
+
+const InputWrapStyle = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+`;
+
+const Input = () => {
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default Input;
diff --git a/src/components/join/InputItem.tsx b/src/components/join/InputItem.tsx
new file mode 100644
index 0000000..2a08451
--- /dev/null
+++ b/src/components/join/InputItem.tsx
@@ -0,0 +1,22 @@
+import styled from "@emotion/styled";
+
+interface InputItemProps {
+ content: string;
+}
+
+const InputItemStyle = styled.input`
+ border-radius: 5px;
+ width: 100%;
+ height: 45px;
+ background-color: #e3e3e3;
+ border: none;
+`;
+
+const InputItem = ({ content }: InputItemProps) => {
+ return (
+
+
+
+ );
+};
+export default InputItem;
diff --git a/src/components/login/Button.tsx b/src/components/login/Button.tsx
new file mode 100644
index 0000000..7862b3e
--- /dev/null
+++ b/src/components/login/Button.tsx
@@ -0,0 +1,26 @@
+/** @jsxImportSource @emotion/react */
+import styled from "@emotion/styled";
+import { useNavigate } from "react-router-dom"; // navigate 훅 사용
+
+const ButtonStyle = styled.button`
+ cursor: pointer;
+ color: white;
+ background-color: rgb(0, 0, 128);
+ font-weight: bold;
+ font-size: large;
+ border: none;
+ border-radius: 10px;
+ height: 50px;
+ width: 100%;
+ margin-top: 30px;
+`;
+
+const Button = () => {
+ const navigate = useNavigate();
+ const handleContinueLogin = () => {
+ navigate("/home"); // 로그인 후 이동할 경로
+ };
+ return 로그인;
+};
+
+export default Button;
diff --git a/src/components/login/Input.tsx b/src/components/login/Input.tsx
new file mode 100644
index 0000000..5ced8da
--- /dev/null
+++ b/src/components/login/Input.tsx
@@ -0,0 +1,74 @@
+// src/components/login/Input.tsx
+/** @jsxImportSource @emotion/react */
+import styled from "@emotion/styled";
+import InputItem from "./InputItem";
+import { useState } from "react";
+
+interface InputProps {
+ id: string;
+ setId: React.Dispatch>;
+ pw: string;
+ setPw: React.Dispatch>;
+ handlePw?: (e: React.ChangeEvent) => void;
+}
+
+const InputStyle = styled.div`
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+`;
+
+const InputWrapStyle = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+`;
+
+const ErrorMessageStyle = styled.div`
+ color: #ef0000;
+ font-size: 12px;
+`;
+
+const Input = ({ id, setId, pw, setPw }: InputProps) => {
+ const [pwValid, setPwValid] = useState(false);
+
+ const handlePw = (e: React.ChangeEvent) => {
+ setPw(e.target.value);
+ const regex =
+ /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,}$/;
+ if (regex.test(pw)) {
+ setPwValid(true);
+ } else {
+ setPwValid(false);
+ }
+ };
+
+ return (
+
+
+ {
+ setId(e.target.value);
+ }}
+ />
+
+
+
+
+ {!pwValid && pw.length > 0 && (
+ 영문, 숫자, 특수문자 포함 8자 이상 입력해주세요.
+ )}
+
+
+ );
+};
+
+export default Input;
diff --git a/src/components/login/InputItem.tsx b/src/components/login/InputItem.tsx
new file mode 100644
index 0000000..db1df74
--- /dev/null
+++ b/src/components/login/InputItem.tsx
@@ -0,0 +1,43 @@
+// src/components/login/InputItem.tsx
+/** @jsxImportSource @emotion/react */
+import styled from "@emotion/styled";
+
+interface InputItemProps {
+ content: string;
+ type: string;
+ value: string;
+ onChange: (e: React.ChangeEvent) => void;
+}
+
+const InputStyle = styled.input`
+ border-radius: 5px;
+ width: 100%;
+ height: 40px;
+ background-color: #e3e3e3;
+ border: none;
+ outline: none;
+ font-size: 15px;
+ font-weight: 400;
+`;
+
+const InputItemStyle = styled.div`
+ display: flex;
+ border-radius: 8px;
+ background-color: #e3e3e3;
+ padding: 5px;
+`;
+
+const InputItem = ({ content, type, value, onChange }: InputItemProps) => {
+ return (
+
+
+
+ );
+};
+
+export default InputItem;
diff --git a/src/components/pages/JoinPage.tsx b/src/components/pages/JoinPage.tsx
new file mode 100644
index 0000000..bedeb3d
--- /dev/null
+++ b/src/components/pages/JoinPage.tsx
@@ -0,0 +1,48 @@
+import Input from "../join/Input";
+import Button from "../join/Button";
+import styled from "@emotion/styled";
+import GotoLogin from "../join/GotoLogin";
+
+const JoinContainerStyle = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+ width: 25%;
+ height: 60%;
+ justify-content: center;
+ align-items: center;
+
+ /* 페이지 전체 화면에서 중앙 정렬 */
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ h1 {
+ font-size: 40px;
+ }
+`;
+
+const JoinWperStyle = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ justify-content: center;
+ width: 100%;
+`;
+
+const JoinPage = () => {
+ return (
+ <>
+
+ 회원가입
+
+
+
+
+
+
+ >
+ );
+};
+
+export default JoinPage;
diff --git a/src/components/pages/LoginPage.tsx b/src/components/pages/LoginPage.tsx
new file mode 100644
index 0000000..3254b53
--- /dev/null
+++ b/src/components/pages/LoginPage.tsx
@@ -0,0 +1,69 @@
+// src/components/login/Main.tsx
+/** @jsxImportSource @emotion/react */
+import styled from "@emotion/styled";
+import { useState } from "react";
+import Input from "../login/Input";
+import Button from "../login/Button";
+
+const WrapperStyle = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+`;
+const MainContainerStyle = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+ width: 25%;
+ height: 60%;
+ justify-content: center;
+ align-items: center;
+
+ /* 페이지 전체 화면에서 중앙 정렬 */
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ h1 {
+ font-size: 40px;
+ }
+
+ p {
+ cursor: pointer;
+ justify-content: center;
+ width: auto;
+ }
+`;
+const LoginPage = () => {
+ const [id, setId] = useState("");
+ const [pw, setPw] = useState("");
+ // const handlePw = (e: React.ChangeEvent) => {
+ // setPw(e.target.value);
+ // };
+ console.log("로그인 페이지 렌더링");
+ return (
+ <>
+
+ 로그인
+
+
+
+
+
+
+ >
+ );
+};
+
+export default LoginPage;