-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[4주차 기본/공유 과제] 🔗 로그인, 회원가입 구현해보기 #6
base: main
Are you sure you want to change the base?
Changes from all commits
a8ff1a0
26b3fd5
b64624a
ad755ba
faf7426
ceffe47
ca97cf6
1571030
d66025d
813614e
ec2b2f3
57abc88
9b68c9d
27899be
79691c4
19fc7a1
e8ca510
6a398f0
a101c42
4dee0f9
b8792a4
65a56c5
1235172
4e55974
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
VITE_APP_BASE_URL = http://34.64.233.12:8080 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
module.exports = { | ||
root: true, | ||
env: { browser: true, es2020: true }, | ||
extends: [ | ||
'eslint:recommended', | ||
'plugin:react/recommended', | ||
'plugin:react/jsx-runtime', | ||
'plugin:react-hooks/recommended', | ||
], | ||
ignorePatterns: ['dist', '.eslintrc.cjs'], | ||
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, | ||
settings: { react: { version: '18.2' } }, | ||
plugins: ['react-refresh'], | ||
rules: { | ||
'react/jsx-no-target-blank': 'off', | ||
'react-refresh/only-export-components': [ | ||
'warn', | ||
{ allowConstantExport: true }, | ||
], | ||
}, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
pnpm-debug.log* | ||
lerna-debug.log* | ||
|
||
node_modules | ||
dist | ||
dist-ssr | ||
*.local | ||
|
||
# Editor directories and files | ||
.vscode/* | ||
!.vscode/extensions.json | ||
.idea | ||
.DS_Store | ||
*.suo | ||
*.ntvs* | ||
*.njsproj | ||
*.sln | ||
*.sw? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# React + Vite | ||
|
||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. | ||
|
||
Currently, two official plugins are available: | ||
|
||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh | ||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<!DOCTYPE html> | ||
<html lang="ko"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>👩🏻💻 로그인/회원가입 👩🏻💻</title> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script type="module" src="/src/main.jsx"></script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"name": "loginsignup", | ||
"private": true, | ||
"version": "0.0.0", | ||
"type": "module", | ||
"scripts": { | ||
"dev": "vite", | ||
"build": "vite build", | ||
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", | ||
"preview": "vite preview" | ||
}, | ||
"dependencies": { | ||
"@fortawesome/fontawesome-svg-core": "^6.5.2", | ||
"@fortawesome/free-solid-svg-icons": "^6.5.2", | ||
"@fortawesome/react-fontawesome": "^0.2.0", | ||
"axios": "^1.6.8", | ||
"react": "^18.2.0", | ||
"react-dom": "^18.2.0", | ||
"react-router-dom": "^6.23.0", | ||
"styled-components": "^6.1.10", | ||
"styled-reset": "^4.5.2" | ||
}, | ||
"devDependencies": { | ||
"@types/react": "^18.2.66", | ||
"@types/react-dom": "^18.2.22", | ||
"@vitejs/plugin-react": "^4.2.1", | ||
"eslint": "^8.57.0", | ||
"eslint-plugin-react": "^7.34.1", | ||
"eslint-plugin-react-hooks": "^4.6.0", | ||
"eslint-plugin-react-refresh": "^0.4.6", | ||
"vite": "^5.2.0" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import styled from 'styled-components'; | ||
import Router from './Router'; | ||
|
||
function App() { | ||
return ( | ||
<DesktopWrapper> | ||
<Router /> | ||
</DesktopWrapper> | ||
); | ||
} | ||
|
||
export default App; | ||
|
||
const DesktopWrapper = styled.div` | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
|
||
width: 100vw; | ||
height: 100vh; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* eslint-disable react/prop-types */ | ||
import { BrowserRouter, Route, Routes } from 'react-router-dom'; | ||
|
||
import Main from './pages/main/Main'; | ||
import Signup from './pages/signup/Signup'; | ||
import Login from './pages/login/Login'; | ||
import MyPage from './pages/myPage/MyPage'; | ||
|
||
const Router = () => { | ||
return ( | ||
<BrowserRouter> | ||
<Routes> | ||
<Route path="/" element={<Main />} /> | ||
<Route path="/signup" element={<Signup />} /> | ||
<Route path="/login" element={<Login />} /> | ||
<Route path="/mypage/:userId" element={<MyPage />} /> | ||
</Routes> | ||
</BrowserRouter> | ||
); | ||
}; | ||
|
||
export default Router; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import axios from 'axios'; | ||
|
||
export const client = axios.create({ | ||
baseURL: import.meta.env.VITE_APP_BASE_URL, | ||
headers: { 'Content-Type': 'application/json' }, | ||
}); | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { client } from './client'; | ||
|
||
export const getUserInfo = (userId) => { | ||
return client.get(`/member/info`, { | ||
headers: { | ||
memberId: userId, | ||
}, | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { client } from './client'; | ||
|
||
export const patchChangePw = (body, userId) => { | ||
return client.patch(`/member/password`, body, { | ||
headers: { | ||
...client.defaults.headers, | ||
memberId: userId, | ||
}, | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { client } from './client'; | ||
|
||
export const postLogin = (body) => { | ||
return client.post(`/member/login`, body); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { client } from './client'; | ||
|
||
export const postSignup = (body) => { | ||
return client.post(`/member/join`, body); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
const SIGNUP_LABEL = [ | ||
{ label: 'ID', detailExist: false }, | ||
{ | ||
label: 'PW', | ||
detailExist: true, | ||
detail: '비밀번호 형식은 8자이상, 숫자, 특수문자, 영어 알파벳이 포함되어야 합니다.', | ||
}, | ||
{ label: '닉네임', detailExist: false }, | ||
{ label: '전화번호', detailExist: true, detail: '전화번호 형식은 010-****-**** 입니다.' }, | ||
]; | ||
|
||
const LOGIN_LABEL = [{ label: 'ID' }, { label: 'PW' }]; | ||
|
||
const MYPAGE_LABEL = [ | ||
{ | ||
label: 'ID', | ||
content: 'authenticationId', | ||
}, | ||
{ | ||
label: '닉네임', | ||
content: 'nickname', | ||
}, | ||
{ | ||
label: '전화번호', | ||
content: 'phone', | ||
}, | ||
]; | ||
|
||
const CHANGE_PW_LABEL = [ | ||
{ label: '기존 비밀번호', id: 'previousPassword' }, | ||
{ label: '새로운 비밀번호', id: 'newPassword' }, | ||
{ label: '비밀번호 확인', id: 'newPasswordVerification' }, | ||
]; | ||
|
||
export { SIGNUP_LABEL, LOGIN_LABEL, MYPAGE_LABEL, CHANGE_PW_LABEL }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* eslint-disable react/prop-types */ | ||
import styled, { css } from 'styled-components'; | ||
|
||
const Button = (props) => { | ||
const { content, onClick } = props; | ||
return ( | ||
<ButtonWrapper {...props} onClick={onClick}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 스프레드 연산자로 prop의 모든 값을 한번에 넘겨줄 수도 있군요! 서진님 덕분에 새롭게 배워가요!!! |
||
{content} | ||
</ButtonWrapper> | ||
); | ||
}; | ||
|
||
export default Button; | ||
|
||
const ButtonWrapper = styled.button` | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
|
||
width = auto; | ||
height = auto; | ||
|
||
padding: 0.5rem 0.8rem; | ||
|
||
border: 1px solid ${({ theme }) => theme.colors.white}; | ||
border-radius: 0.3rem; | ||
|
||
font-size: 1.2rem; | ||
cursor: pointer; | ||
|
||
${({ | ||
theme, | ||
$marginTop = '', | ||
$buttonColor = 'skyblue', | ||
$fontColor = 'white', | ||
$hoverFontColor = 'white', | ||
$hoverColor = 'blue', | ||
}) => css` | ||
margin-top: ${$marginTop}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. p5) 혹시 여기서만 css 로 css 설정을 해주신 이유가 있을까요?? |
||
|
||
background-color: ${theme.colors[$buttonColor]}; | ||
color: ${theme.colors[$fontColor]}; | ||
|
||
&:hover { | ||
border: 1px solid ${({ theme }) => theme.colors.blue}; | ||
|
||
color: ${theme.colors[$hoverFontColor]}; | ||
background-color: ${theme.colors[$hoverColor]}; | ||
} | ||
`} | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* eslint-disable react/prop-types */ | ||
import styled from 'styled-components'; | ||
|
||
const ButtonWrapper = (props) => { | ||
const { children } = props; | ||
return <BtnWrapper>{children}</BtnWrapper>; | ||
}; | ||
|
||
export default ButtonWrapper; | ||
|
||
const BtnWrapper = styled.div` | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
gap: 2rem; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* eslint-disable react/prop-types */ | ||
import styled from 'styled-components'; | ||
|
||
const Input = (props) => { | ||
const { label, children, onChangeHandler } = props; | ||
|
||
return ( | ||
<InputWrapper> | ||
<InputContainer> | ||
<InputLabel>{label}</InputLabel> | ||
<StyledInput id={label} onChange={onChangeHandler} /> | ||
</InputContainer> | ||
{children} | ||
</InputWrapper> | ||
); | ||
}; | ||
|
||
export default Input; | ||
|
||
const InputWrapper = styled.div` | ||
position: relative; | ||
`; | ||
|
||
const InputContainer = styled.div` | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
gap: 2rem; | ||
|
||
width: 28rem; | ||
`; | ||
|
||
const InputLabel = styled.label` | ||
color: ${({ theme }) => theme.colors.white}; | ||
|
||
font-size: 1.2rem; | ||
font-weight: bolder; | ||
`; | ||
|
||
const StyledInput = styled.input` | ||
width: 17rem; | ||
|
||
padding: 0.5rem 0.7rem; | ||
|
||
border: none; | ||
border-radius: 0.5rem; | ||
|
||
background-color: ${({ theme }) => theme.colors.white}; | ||
|
||
font-size: 1.1rem; | ||
font-family: ${({ theme }) => theme.font.fontFamily}; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* eslint-disable react/prop-types */ | ||
import styled from 'styled-components'; | ||
|
||
const LoginSignupWrapper = (props) => { | ||
const { title, children } = props; | ||
return ( | ||
<LoginSignupWrp> | ||
<Title>{title}</Title> | ||
{children} | ||
</LoginSignupWrp> | ||
); | ||
}; | ||
|
||
export default LoginSignupWrapper; | ||
|
||
const LoginSignupWrp = styled.section` | ||
display: flex; | ||
flex-direction: column; | ||
justify-content: flex-start; | ||
align-items: center; | ||
gap: 2.7rem; | ||
|
||
width: 35rem; | ||
|
||
padding: 2.5rem 1rem 4rem 1rem; | ||
|
||
border: 1px solid ${({ theme }) => theme.colors.white}; | ||
border-radius: 0.5rem; | ||
|
||
color: ${({ theme }) => theme.colors.black}; | ||
background-color: ${({ theme }) => theme.colors.lightSkyblue}; | ||
`; | ||
|
||
const Title = styled.h1` | ||
color: ${({ theme }) => theme.colors.white}; | ||
|
||
font-size: 1.7rem; | ||
font-weight: bolder; | ||
`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p5) axios.create로 axios 인스턴스를 만들고 불러와서 사용할수 있네요!! 배워갑니다..