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 ( + <> + +

회원가입

+ + +