-
Notifications
You must be signed in to change notification settings - Fork 0
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주차 기본/심화/공유 과제] 회원가입 & 로그인 #5
Open
m2na7
wants to merge
29
commits into
main
Choose a base branch
from
assignment4
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
f1c3615
chore: 4주차 과제 초기세팅
m2na7 b1d4626
chore: paths alias 설정
m2na7 70f4c83
chore: 파일구조 및 라우터 설정
m2na7 a606f53
feat: Theme 설정
m2na7 f2d64a7
style: 로그인 페이지 퍼블리싱
m2na7 0b0f2eb
style: 회원가입 페이지 퍼블리싱
m2na7 69aea39
style: 헤더 퍼블리싱
m2na7 8b7f80f
feat: url 경로에 따른 헤더 레이아웃 설정
m2na7 93638ba
feat: `Button` 컴포넌트 추가
m2na7 f68808a
feat: `Input` 컴포넌트 추가
m2na7 9b850d0
refactor: 공통 컴포넌트 불러오도록 수정
m2na7 ed8cbf2
style: 취미 페이지 퍼블리싱
m2na7 8c3a8db
style: 내 정보 페이지 퍼블리싱
m2na7 8119c70
feat: api 기본 설정
m2na7 c1687e5
feat: 회원가입 기능 구현
m2na7 0ccbdc1
feat: 로그인 및 로그아웃 기능 구현
m2na7 06af2c0
feat: Protected Route 기능 구현
m2na7 8acce09
feat: 나의 취미 조회 기능 구현
m2na7 be09712
feat: 취미 검색 기능 구현
m2na7 75363fb
feat: 정보 수정 기능 구현
m2na7 efdd288
feat: 에러 핸들링
m2na7 49ea26f
feat: `Button` disabled 기능 추가
m2na7 22f8ce3
feat: 폼제출 관련 에러 핸들링
m2na7 4ad67db
refactor: 불필요한 타입 제거 및 import 변경
m2na7 0aad4f6
feat: 비밀번호 표시 기능 추가
m2na7 572ad58
refactor: 라우터 구조 변경
m2na7 39ce6fc
refactor: `SignupForm` 내부 컴포넌트 분리
m2na7 e3ee82d
refactor: Layout 구조 간소화
m2na7 c59c19e
refactor: placeholder 타입 제거
m2na7 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# 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? | ||
|
||
.yarn | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# React + TypeScript + 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 | ||
|
||
## Expanding the ESLint configuration | ||
|
||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: | ||
|
||
- Configure the top-level `parserOptions` property like this: | ||
|
||
```js | ||
export default tseslint.config({ | ||
languageOptions: { | ||
// other options... | ||
parserOptions: { | ||
project: ['./tsconfig.node.json', './tsconfig.app.json'], | ||
tsconfigRootDir: import.meta.dirname, | ||
}, | ||
}, | ||
}) | ||
``` | ||
|
||
- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked` | ||
- Optionally add `...tseslint.configs.stylisticTypeChecked` | ||
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config: | ||
|
||
```js | ||
// eslint.config.js | ||
import react from 'eslint-plugin-react' | ||
|
||
export default tseslint.config({ | ||
// Set the react version | ||
settings: { react: { version: '18.3' } }, | ||
plugins: { | ||
// Add the react plugin | ||
react, | ||
}, | ||
rules: { | ||
// other rules... | ||
// Enable its recommended rules | ||
...react.configs.recommended.rules, | ||
...react.configs['jsx-runtime'].rules, | ||
}, | ||
}) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import js from '@eslint/js' | ||
import globals from 'globals' | ||
import reactHooks from 'eslint-plugin-react-hooks' | ||
import reactRefresh from 'eslint-plugin-react-refresh' | ||
import tseslint from 'typescript-eslint' | ||
|
||
export default tseslint.config( | ||
{ ignores: ['dist'] }, | ||
{ | ||
extends: [js.configs.recommended, ...tseslint.configs.recommended], | ||
files: ['**/*.{ts,tsx}'], | ||
languageOptions: { | ||
ecmaVersion: 2020, | ||
globals: globals.browser, | ||
}, | ||
plugins: { | ||
'react-hooks': reactHooks, | ||
'react-refresh': reactRefresh, | ||
}, | ||
rules: { | ||
...reactHooks.configs.recommended.rules, | ||
'react-refresh/only-export-components': [ | ||
'warn', | ||
{ allowConstantExport: true }, | ||
], | ||
}, | ||
}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!DOCTYPE html> | ||
<html lang="ko"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>4주차 과제</title> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script type="module" src="/src/main.tsx"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"name": "week4", | ||
"private": true, | ||
"version": "0.0.0", | ||
"type": "module", | ||
"scripts": { | ||
"dev": "vite", | ||
"build": "tsc -b && vite build", | ||
"lint": "eslint .", | ||
"preview": "vite preview" | ||
}, | ||
"dependencies": { | ||
"@vanilla-extract/css": "^1.16.0", | ||
"@vanilla-extract/vite-plugin": "^4.0.17", | ||
"axios": "^1.7.7", | ||
"react": "^18.3.1", | ||
"react-dom": "^18.3.1", | ||
"react-router-dom": "^6.27.0", | ||
"vite-tsconfig-paths": "^5.1.0" | ||
}, | ||
"devDependencies": { | ||
"@eslint/js": "^9.13.0", | ||
"@types/react": "^18.3.12", | ||
"@types/react-dom": "^18.3.1", | ||
"@vitejs/plugin-react-swc": "^3.5.0", | ||
"eslint": "^9.13.0", | ||
"eslint-plugin-react-hooks": "^5.0.0", | ||
"eslint-plugin-react-refresh": "^0.4.14", | ||
"globals": "^15.11.0", | ||
"typescript": "~5.6.2", | ||
"typescript-eslint": "^8.11.0", | ||
"vite": "^5.4.10" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import Router from '@router/Router'; | ||
import '@styles/global.css'; | ||
|
||
function App() { | ||
return <Router />; | ||
} | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import axios from 'axios'; | ||
import { BASE_URL } from '@constants/api'; | ||
import { onErrorResponse } from './error'; | ||
|
||
export const client = axios.create({ | ||
baseURL: BASE_URL, | ||
}); | ||
|
||
client.interceptors.response.use((response) => response, onErrorResponse); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { ERROR_MESSAGE } from '@constants/messages'; | ||
import axios, { AxiosError, AxiosResponse } from 'axios'; | ||
|
||
export const onErrorResponse = (error: AxiosError) => { | ||
if (axios.isAxiosError(error)) { | ||
const response = error.response as AxiosResponse; | ||
const code = response.data.code; | ||
let errorMessage; | ||
|
||
// http 상태 코드에 따른 에러 메시지 처리 | ||
switch (response.status) { | ||
case 400: | ||
errorMessage = ERROR_MESSAGE.INVALID_REQUEST; | ||
break; | ||
case 401: | ||
errorMessage = ERROR_MESSAGE.NO_TOKEN; | ||
break; | ||
case 403: | ||
errorMessage = | ||
code === '00' | ||
? ERROR_MESSAGE.INVALID_TOKEN | ||
: ERROR_MESSAGE.INVALID_PASSWORD; | ||
break; | ||
case 404: | ||
errorMessage = | ||
code === '00' ? ERROR_MESSAGE.INVALID_PATH : ERROR_MESSAGE.INVALID_NO; | ||
break; | ||
case 409: | ||
errorMessage = ERROR_MESSAGE.DUPLICATED_USERNAME; | ||
break; | ||
default: | ||
errorMessage = ERROR_MESSAGE.DEFAULT; | ||
} | ||
|
||
return Promise.reject(new Error(errorMessage)); | ||
} | ||
|
||
return Promise.reject(new Error(ERROR_MESSAGE.DEFAULT)); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { ACCESS_TOKEN_KEY } from '@constants/config'; | ||
import { client } from './client'; | ||
import { END_POINT } from '@constants/api'; | ||
|
||
export const getMyHobby = async () => { | ||
try { | ||
const token = sessionStorage.getItem(ACCESS_TOKEN_KEY); | ||
const response = await client.get(END_POINT.MY_HOBBY, { | ||
headers: { | ||
token: token, | ||
}, | ||
}); | ||
return response.data.result.hobby; | ||
} catch (error) { | ||
if (error instanceof Error) { | ||
throw new Error(error.message); | ||
} | ||
} | ||
}; | ||
|
||
export const getUserHobby = async (userId: number) => { | ||
try { | ||
const token = sessionStorage.getItem(ACCESS_TOKEN_KEY); | ||
const response = await client.get(END_POINT.USER_HOBBY(userId), { | ||
headers: { | ||
token: token, | ||
}, | ||
}); | ||
return response.data.result.hobby; | ||
} catch (error) { | ||
if (error instanceof Error) { | ||
throw new Error(error.message); | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { client } from './client'; | ||
import { END_POINT } from '@constants/api'; | ||
import { ACCESS_TOKEN_KEY } from '@constants/config'; | ||
import { LoginData, User, UserInfoData } from '@type/user'; | ||
|
||
export const postLogin = async (data: LoginData) => { | ||
try { | ||
const response = await client.post(END_POINT.LOGIN, data); | ||
|
||
return response.data.result.token; | ||
} catch (error) { | ||
if (error instanceof Error) { | ||
throw new Error(error.message); | ||
} | ||
} | ||
}; | ||
|
||
export const postSignUp = async (data: User) => { | ||
try { | ||
const response = await client.post(END_POINT.USER, data); | ||
return response.data.result; | ||
} catch (error) { | ||
if (error instanceof Error) { | ||
throw new Error(error.message); | ||
} | ||
} | ||
}; | ||
|
||
export const putUserInfo = async (data: UserInfoData) => { | ||
try { | ||
const token = sessionStorage.getItem(ACCESS_TOKEN_KEY); | ||
const response = await client.put(END_POINT.USER, data, { | ||
headers: { | ||
token: token, | ||
}, | ||
}); | ||
|
||
return response.data; | ||
} catch (error) { | ||
if (error instanceof Error) { | ||
throw new Error(error.message); | ||
} | ||
} | ||
}; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { vars } from '@styles/theme.css'; | ||
import { style } from '@vanilla-extract/css'; | ||
|
||
export const button = style({ | ||
marginBottom: 14, | ||
padding: 12, | ||
borderRadius: 8, | ||
backgroundColor: vars.color.primary, | ||
color: vars.color.white, | ||
textAlign: 'center', | ||
fontSize: vars.fontSize.md, | ||
|
||
':hover': { | ||
backgroundColor: vars.color.blue600, | ||
transition: 'background-color 0.3s', | ||
}, | ||
|
||
':disabled': { | ||
backgroundColor: vars.color.gray300, | ||
color: vars.color.gray100, | ||
cursor: 'not-allowed', | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import * as styles from './Button.css'; | ||
|
||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> { | ||
children: React.ReactNode; | ||
} | ||
|
||
const Button = ({ children, ...props }: ButtonProps) => { | ||
return ( | ||
<button className={styles.button} {...props}> | ||
{children} | ||
</button> | ||
); | ||
}; | ||
|
||
export default Button; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { style } from '@vanilla-extract/css'; | ||
import { vars } from '@styles/theme.css'; | ||
|
||
export const header = style({ | ||
display: 'flex', | ||
justifyContent: 'space-between', | ||
alignItems: 'center', | ||
padding: '20px', | ||
minHeight: vars.spacing.headerHeight, | ||
gap: 20, | ||
|
||
backgroundColor: vars.color.primary, | ||
color: vars.color.white, | ||
}); | ||
|
||
export const leftSection = style({ | ||
display: 'flex', | ||
alignItems: 'center', | ||
gap: 60, | ||
}); | ||
|
||
export const title = style({ | ||
fontSize: vars.fontSize['2xl'], | ||
fontWeight: 'bold', | ||
}); | ||
|
||
export const nav = style({ | ||
display: 'flex', | ||
gap: 40, | ||
}); | ||
|
||
export const link = style({ | ||
fontSize: vars.fontSize.lg, | ||
|
||
':hover': { | ||
color: vars.color.secondary, | ||
}, | ||
}); | ||
|
||
export const logoutButton = style({ | ||
fontSize: vars.fontSize.lg, | ||
|
||
':hover': { | ||
color: vars.color.secondary, | ||
}, | ||
}); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
이렇게 단위를 설정하지않으면 기본적으로 px단위로 지정되지 않나요?
font등에서는 rem단위를 사용하고 여백 등 레이아웃에서는 px단위를 사용하시는 것으로 보이는데,
폰트는 접근성을 고려하고 레이아웃은 깨지지 않게 하려고 하신걸까요?
단위를 섞어쓰면 유지보수나 일관성 측면에서 단점이 좀 생기지 않나 해서 여쭤봅니다~
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.
4주차 과제진행할 때 vanilla extract에 익숙치 않았어서 단위를 많이 생략(ve에서는 생략시 px로 변환)했었네요 ... 빠르게 진행하다보니 ㅎㅎ.
border를 제외하고는 rem으로 바꾸는게 적절하다고 저도 생각합니다 ~