Skip to content
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
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d607042
init: 초기세팅
yarimu May 9, 2024
9599a78
feat: 로그인 화면 구현
yarimu May 9, 2024
2a3acb0
chore: 마이페이지 이미지
yarimu May 9, 2024
1ac0693
init: 회원가입 페이지 초기세팅
yarimu May 9, 2024
2bbb7be
feat: 메인페이지> 회원가입 페이지 이동 구현
yarimu May 9, 2024
f99fc31
docs: 라우터 파일분리
yarimu May 9, 2024
87d86dc
feat: 로그인페이지>회원가입페이지 이동 구현
yarimu May 9, 2024
7a5990b
init: 라우터 초기세팅
yarimu May 9, 2024
866198e
feat: 마이페이지로 이동 구현
yarimu May 9, 2024
b19b79e
feat: 회원가입>로그인페이지 이동 구현
yarimu May 9, 2024
57ddbee
feat: 로그인>마이페이지 이동 구현
yarimu May 9, 2024
fdb77ea
feat: 회원가입 api 연결
yarimu May 10, 2024
2fe123e
feat: 회원가입 에러메세지 구현
yarimu May 10, 2024
3ec0dc0
docs: join페이지 오타수정
yarimu May 10, 2024
df21b75
feat: 회원정보 받아오기 구현
yarimu May 10, 2024
8149675
docs: 키값게 맞게 오타수정
yarimu May 10, 2024
1a36974
fix: data unkown 오류 해결
yarimu May 10, 2024
211c05f
feat: Location header id값 넘겨주기
yarimu May 10, 2024
affe0ba
feat: 마이페이지 홈버튼 구현
yarimu May 10, 2024
d09ff7d
feat: 메인>마이페이지 회원정보 가지고 이동 구현
yarimu May 10, 2024
4894484
fix: 페이지이동 기능 Link에서 navigate으로 변경하여 구현
yarimu May 10, 2024
4bf28e6
feat: 비밀번호 변경 input비어있는 경우 api 작동x 기능구현
yarimu May 10, 2024
a897f59
docs: 비밀번호 input 비어있을 경우 api 작동x기능 위치 변경
yarimu May 10, 2024
3a93f74
docs: 마이페이지 오타수정
yarimu May 10, 2024
223ce23
gitignore
yarimu May 23, 2024
05c050a
gitignore
yarimu May 23, 2024
3296409
chore: DS_Store 삭제
yarimu May 23, 2024
cc74c77
chore: 스타일 컴포넌트 설치
yarimu May 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions week4/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
25 changes: 25 additions & 0 deletions week4/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# 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?
.env
30 changes: 30 additions & 0 deletions week4/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 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 {
// other rules...
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: ['./tsconfig.json', './tsconfig.node.json'],
tsconfigRootDir: __dirname,
},
}
```

- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
13 changes: 13 additions & 0 deletions week4/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="ko">

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
31 changes: 31 additions & 0 deletions week4/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "week4",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"axios": "^1.6.8",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.23.0",
"styled-components": "^6.1.10"
},
"devDependencies": {
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"@vitejs/plugin-react-swc": "^3.5.0",
"eslint": "^8.57.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"typescript": "^5.2.2",
"vite": "^5.2.0"
}
}
Binary file added week4/public/img/포챠코.png

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public 폴더 안에 img 폴더 가 있는거 같은데, 이 폴더를 assets에 옮기면 좋을 거 같아요!

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week4/public/img/피짱즈.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions week4/public/vite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file added week4/src/App.css

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 파일은 지워도 될 거 같아요..!!

Empty file.
11 changes: 11 additions & 0 deletions week4/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Router from "./Router";

function App() {
return (
<>
<Router />
</>
);
}

export default App;
20 changes: 20 additions & 0 deletions week4/src/Router.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Join from "./pages/Join";
import Login from "./pages/Login";
import Main from "./pages/Main";
import My from "./pages/My";

const Router = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/login" element={<Login />}></Route>
<Route path="/join" element={<Join />}></Route>
<Route path="/main" element={<Main />}></Route>
<Route path="/my/:memberId" element={<My />}></Route>
</Routes>
</BrowserRouter>
Comment on lines +9 to +16
Copy link
Member

@suwonthugger suwonthugger May 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 마이갓... 완벽한 라우팅 최고입니다, 다음에는 path='/'일 때, 그리고 라우팅이 없는 url로 접속했을 때에는 어떤 화면을 보여줄지에 대한것도 생각해보시면 좋을것 같아요!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 이번에는 라우팅이 없는 url은 신경쓰지 않았는데 확실히 신경쓰는게 좋을 것 같아요! 좋은 제안 감사합니다

);
};

export default Router;
1 change: 1 addition & 0 deletions week4/src/assets/react.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions week4/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";

ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
102 changes: 102 additions & 0 deletions week4/src/pages/Join.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { useState } from "react";
import styled from "styled-components";
import axios, { AxiosError } from "axios";
import { useNavigate } from "react-router-dom";

function Join() {
const [userId, setUserId] = useState("");
const [userPw, setUserPw] = useState("");
const [userNickName, setNickName] = useState("");
const [userPhoneNumber, setPhoneNumber] = useState("");
const navigate = useNavigate();

const submitForm = async () => {
try {
const postJoinData = await axios.post(
`${import.meta.env.VITE_APP_BASE_URL}/member/join`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow... env 사용을 자유자재로 하시는군요... api 주소같이 외부로 노출되면 안되는 부분을 .evn를 사용해서 처리하신게 너무 좋네요~ 다음 프로젝트하실 때도 이런 습관을 들이면 좋을것 같아요

{
authenticationId: userId,
password: userPw,
nickname: userNickName,
phone: userPhoneNumber,
}
);
console.log(postJoinData);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

개발중에 확인을 위해서 사용한 console.log() 성능이나 보안적인 측면에서 지워주는게 좋다고 해요! 다음에는 확인후에 지워서 git에 올리는 걸 추천해드립니다!

alert("웰컴!");
navigate("/login");
} catch (error) {
if (error instanceof AxiosError) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 마이 굿니스... 에러가 AxiosError객체의 인스턴스인것을 명시해줌으로서 타입에러를 해결하셨군요.. 최고입니다

alert(error.response?.data.message);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error.response가 있을 때만 메세지를 출력하게 하셨군요 저는 if문에서 따로 확인을 했었는데 이렇게 alet에서 확인하는 것도 좋은 방법같네요 배워갑니당!

}

console.log(error);
}
};

return (
<>
<JoinWrapper>
<JoinContainer>
<span>회원가입 페이지</span>
<p>아이디</p>
<div>
<input
type="text"
value={userId}
onChange={(e) => setUserId(e.target.value)}
/>
</div>
Comment on lines +41 to +48
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 반복되는 부분은 따로 컴포넌트로 분리하여서 사용해도 좋을것 같아요~~
예시를 보여드리자면

Suggested change
<p>아이디</p>
<div>
<input
type="text"
value={userId}
onChange={(e) => setUserId(e.target.value)}
/>
</div>
function YerimInput({title,value,onChange}) {
return (
<>
<p>{title}<p>
<div>
<input
type="text"
value = {value}
onChange={onChange}
/>
</div>
</>
}

<p>비밀번호</p>
<div>
<input
type="text"
value={userPw}
onChange={(e) => setUserPw(e.target.value)}
/>
<p>
비밀번호가 형식(최소 8글자 이상, 숫자, 문자(a-z, A-Z), 특수문자
포함)
</p>
</div>
<p>닉네임</p>
<div>
<input
type="text"
value={userNickName}
onChange={(e) => setNickName(e.target.value)}
/>
</div>
<p>전화번호</p>
<div>
<input
type="string"
value={userPhoneNumber}
onChange={(e) => setPhoneNumber(e.target.value)}
/>
<p>전화번호가 형식(010-****-****)</p>
</div>

<button type="button" onClick={submitForm}>
회원가입
</button>
Comment on lines +79 to +81

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

버튼 부분도 반복되고 있으니 공통 컴포넌트로 분리해서 적용하면 좋을 거 같아요!!


<button onClick={() => navigate(-1)}>뒤로가기</button>
</JoinContainer>
</JoinWrapper>
</>
);
}

export default Join;

const JoinWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
background-color: #f5dad2;
font-size: 2rem;
`;

const JoinContainer = styled.div`
width: 20rem;
`;
83 changes: 83 additions & 0 deletions week4/src/pages/Login.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { useState } from "react";
import styled from "styled-components";
import axios from "axios";
import img1 from "../../public/img/포챠코.png";
import { useNavigate } from "react-router-dom";

function Login() {
const [userId, setUserId] = useState("");
const [userPw, setUserPw] = useState("");
const [uniqueId, setUniqueId] = useState("");

const navigate = useNavigate();

const handleClickLogin = async () => {
try {
const postData = await axios.post(
`${import.meta.env.VITE_APP_BASE_URL}/member/login`,
{
authenticationId: userId,
password: userPw,
}
);
const memberId = postData.headers.location;
navigate(`/my/${memberId}`);

setUniqueId(uniqueId);
// console.log(postData);
// console.log(memberId);
} catch (error) {
alert("아이디,비밀번호를 입력하세요");
console.log(error);
}
};
Comment on lines +14 to +33
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

로그인 로직 너무 깔끔하고 좋은데요~~ axios를 잘 사용하시는걸로 봐서 다음에는 axios instance를 활용해보는것도 좋은 경험이 될 것 같아요! 합세 때 해봅시다!!


return (
<>
<LoginWrapper>
<LoginContainer>
<span>로그인</span>
<img src={img1} alt="포챠코이미지" width="150rem" />
<p>아이디</p>
<div>
<input
type="text"
value={userId}
onChange={(e) => setUserId(e.target.value)}
/>
</div>
Comment on lines +41 to +48
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요기도 이전에 언급한 부분이랑 형식이 동일하게 반복되는데 컴포넌트 폴더를 하나 만들어서 분리해두면 좋을것 같아유

<p>비밀번호</p>
<div>
<input
type="text"
value={userPw}
onChange={(e) => setUserPw(e.target.value)}
/>
</div>

<button type="button" onClick={handleClickLogin}>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

버튼도 반복해서 사용한다면 버튼 컴포넌트를 만들어서 이를 사용하는 것도 추천해드립니다!

로그인
</button>

<button type="button" onClick={() => navigate("/join")}>
회원가입
</button>
</LoginContainer>
</LoginWrapper>
</>
);
}

export default Login;

const LoginWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
background-color: #f5dad2;
font-size: 2rem;
`;

const LoginContainer = styled.div`
width: 10rem;
`;
33 changes: 33 additions & 0 deletions week4/src/pages/Main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Link } from "react-router-dom";
import img2 from "../../public/img/피짱즈.png";
import styled from "styled-components";

const Main = () => {
return (
<MainWrapper>
<MainContainer>
<img src={img2} alt="피짱즈이미지" width="300rem" />
<Link to="/my/:memberId">
<button type="button">내정보</button>
</Link>
Comment on lines +10 to +12
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 useNavigate를 사용했는데, Link를 사용하셨군요! 이 부분에서는 클릭했을 때 아무런 조건없이 해당 url로 이동해야하니 적절한 사용이되겠네요 하나 배워갑니다

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 link를 사용할 생각은 못했는데 배워갑니다!

<Link to="/join">
<button type="button">회원가입</button>
</Link>
</MainContainer>
</MainWrapper>
);
};

export default Main;

const MainWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
background-color: #f5dad2;
font-size: 2rem;
`;

const MainContainer = styled.div`
width: 20rem;
`;
Loading