- 
                Notifications
    You must be signed in to change notification settings 
- Fork 7
[3주차] 김남일 미션 제출합니다. #9
base: master
Are you sure you want to change the base?
Changes from all commits
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,15 @@ | ||
| { | ||
| // Use IntelliSense to learn about possible attributes. | ||
| // Hover to view descriptions of existing attributes. | ||
| // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
| "version": "0.2.0", | ||
| "configurations": [ | ||
| { | ||
| "name": "Python: Current File", | ||
| "type": "python", | ||
| "request": "launch", | ||
| "program": "${file}", | ||
| "console": "integratedTerminal" | ||
| } | ||
| ] | ||
| } | 
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,13 +1,19 @@ | ||||||
| import React from "react"; | ||||||
| import styled from "styled-components"; | ||||||
| import React, { useState } from "react"; | ||||||
|  | ||||||
| import LoginForm from "../src/components/login-form"; | ||||||
| import VoteForm from "../src/components/vote-form"; | ||||||
|  | ||||||
| import styled from "styled-components"; | ||||||
| import Axios from "axios"; | ||||||
|  | ||||||
| export default function Home() { | ||||||
| const [login, setLogin] = useState(false); | ||||||
| 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. 
        Suggested change
       
 boolean값을 표현하는 변수라 이름에 is를 붙여주면 더 좋을 것 같아요! | ||||||
|  | ||||||
| return ( | ||||||
| <Wrapper> | ||||||
| 리액트 투-표 | ||||||
| <LoginForm /> | ||||||
| <Header>리액트 투-표</Header> | ||||||
| {!login && <LoginForm loginAccess={setLogin} />} | ||||||
| {login && <VoteForm />} | ||||||
| </Wrapper> | ||||||
| ); | ||||||
| } | ||||||
|  | @@ -17,3 +23,7 @@ const Wrapper = styled.div` | |||||
| padding: 10rem 40rem; | ||||||
| background-color: Azure; | ||||||
| `; | ||||||
|  | ||||||
| const Header = styled.h1` | ||||||
| font-size: 4rem; | ||||||
| `; | ||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,64 @@ | ||||||||||
| import React, { useEffect, useState } from "react"; | ||||||||||
|  | ||||||||||
| import styled from "styled-components"; | ||||||||||
| import axios from "axios"; | ||||||||||
|  | ||||||||||
| export default function CandidateForm(props) { | ||||||||||
| 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. 
        Suggested change
       
 Form은 input으로 입력받은 정보를 제출하는 section을 의미합니다. | ||||||||||
| const { name, voteCount, rank, id } = props; | ||||||||||
|  | ||||||||||
| const voteCandidate = () => { | ||||||||||
| axios | ||||||||||
| .put(process.env.API_HOST + "/candidates/" + id + "/vote/") | ||||||||||
| 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. 템플릿 리터럴을 사용해볼까요? 참고링크 | ||||||||||
| .then(function (response) { | ||||||||||
| 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. 화살표함수로 바꿔주세요! | ||||||||||
| console.log(response); | ||||||||||
| alert(name + "님에게 투표완료."); | ||||||||||
| }) | ||||||||||
| 
      Comment on lines
    
      +14
     to 
      +15
    
   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. 투표 완료시 candidateList를 다시 가져오는 로직이 빠져있네요! | ||||||||||
| .catch(function (error) { | ||||||||||
| console.log(error); | ||||||||||
| alert("다시 시도해주세요."); | ||||||||||
| }); | ||||||||||
| }; | ||||||||||
|  | ||||||||||
| return ( | ||||||||||
| <Wrapper> | ||||||||||
| <Rank>{rank}위:</Rank> | ||||||||||
| <Info> | ||||||||||
| {name}[{voteCount}표] | ||||||||||
| </Info> | ||||||||||
| <VoteButton | ||||||||||
| onClick={() => { | ||||||||||
| voteCandidate(); | ||||||||||
| }} | ||||||||||
| 
      Comment on lines
    
      +29
     to 
      +31
    
   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. 
        Suggested change
       
 함수명을 그대로 써주셔도 같습니다 ㅎㅎ | ||||||||||
| > | ||||||||||
| 투표 | ||||||||||
| </VoteButton> | ||||||||||
| </Wrapper> | ||||||||||
| ); | ||||||||||
| } | ||||||||||
|  | ||||||||||
| const Wrapper = styled.div` | ||||||||||
| display: flex; | ||||||||||
| justify-content: space-between; | ||||||||||
| align-items: center; | ||||||||||
| flex-direction: row; | ||||||||||
| `; | ||||||||||
|  | ||||||||||
| const Rank = styled.p` | ||||||||||
| font-weight: bolder; | ||||||||||
| font-size: 2.5rem; | ||||||||||
| border: none; | ||||||||||
| `; | ||||||||||
| const Info = styled.p` | ||||||||||
| font-size: 2.5rem; | ||||||||||
| width: 40%; | ||||||||||
| border: none; | ||||||||||
| `; | ||||||||||
| const VoteButton = styled.button` | ||||||||||
| background: blue; | ||||||||||
| color: white; | ||||||||||
| border: none; | ||||||||||
| border-radius: 0.7rem; | ||||||||||
| font-size: 2rem; | ||||||||||
| height: 3.5rem; | ||||||||||
| width: 5.5rem; | ||||||||||
| `; | ||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,8 +1,86 @@ | ||||||||||||||||
| import React from "react"; | ||||||||||||||||
| import React, { useState } from "react"; | ||||||||||||||||
|  | ||||||||||||||||
| import axios from "axios"; | ||||||||||||||||
|  | ||||||||||||||||
| import styled from "styled-components"; | ||||||||||||||||
|  | ||||||||||||||||
| export default function LoginForm() { | ||||||||||||||||
| return <Wrapper>안녕 나는 로그인 폼!</Wrapper>; | ||||||||||||||||
| export default function LoginForm(props) { | ||||||||||||||||
| const { loginAccess } = props; | ||||||||||||||||
|  | ||||||||||||||||
| const [userData, setUserData] = useState({ | ||||||||||||||||
| email: "", | ||||||||||||||||
| password: "", | ||||||||||||||||
| }); | ||||||||||||||||
|  | ||||||||||||||||
| const { email, password } = userData; | ||||||||||||||||
|  | ||||||||||||||||
| const handleFormChange = (e) => { | ||||||||||||||||
| const { name, value } = e.target; | ||||||||||||||||
| setUserData({ ...userData, [name]: value }); | ||||||||||||||||
| }; | ||||||||||||||||
|  | ||||||||||||||||
| const checkData = () => { | ||||||||||||||||
| if (email === "" || password === "") { | ||||||||||||||||
| alert("모든 칸을 채워주세요."); | ||||||||||||||||
| return false; | ||||||||||||||||
| } else { | ||||||||||||||||
| return true; | ||||||||||||||||
| } | ||||||||||||||||
| 
      Comment on lines
    
      +23
     to 
      +28
    
   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. 
        Suggested change
       
 위와 같이 바꿔주면 더 좋을 것 같아요 ㅎ | ||||||||||||||||
| }; | ||||||||||||||||
|  | ||||||||||||||||
| const submitData = () => { | ||||||||||||||||
| if (!checkData()) return; | ||||||||||||||||
| 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. 좋네용 바로 리턴~ 더 읽어볼만한 글 첨부해드릴게요! | ||||||||||||||||
|  | ||||||||||||||||
| axios | ||||||||||||||||
| .post(process.env.API_HOST + "/auth/signin/", userData) | ||||||||||||||||
| 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. 템플릿 리터럴을 사용해볼까요? 2 | ||||||||||||||||
| .then(function (response) { | ||||||||||||||||
| 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. 화살표 함수로 바꿔주세요! | ||||||||||||||||
| console.log(response); | ||||||||||||||||
| alert("로그인에 성공하셨습니다!"); | ||||||||||||||||
| loginAccess(true); //왜 loginAccess = ture;는 안될까요? | ||||||||||||||||
| 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. 위에서 loginAccess로 setLogin을 넘겨주셨네요! | ||||||||||||||||
| }) | ||||||||||||||||
| .catch(function (error) { | ||||||||||||||||
| if (error.response.status === 404) { | ||||||||||||||||
| alert("이메일이 존재하지 않습니다."); | ||||||||||||||||
| setUserData({ | ||||||||||||||||
| email: "", | ||||||||||||||||
| password: "", | ||||||||||||||||
| }); | ||||||||||||||||
| console.log(error.response); | ||||||||||||||||
| return; | ||||||||||||||||
| } else if (error.response.status === 422) { | ||||||||||||||||
| alert("비밀번호가 존재하지 않습니다."); | ||||||||||||||||
| setUserData({ | ||||||||||||||||
| email, | ||||||||||||||||
| password: "", | ||||||||||||||||
| }); | ||||||||||||||||
| console.log(error.response); | ||||||||||||||||
| return; | ||||||||||||||||
| } | ||||||||||||||||
| console.log(error); | ||||||||||||||||
| 
      Comment on lines
    
      +42
     to 
      +59
    
   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. switch문을 사용해 이쁘게 리팩토링할 수 있을 것 같아요 ㅎㅎ | ||||||||||||||||
| }); | ||||||||||||||||
| }; | ||||||||||||||||
|  | ||||||||||||||||
| return ( | ||||||||||||||||
| <Wrapper> | ||||||||||||||||
| <Header>로그인</Header> | ||||||||||||||||
| <Row> | ||||||||||||||||
| <UserInfo> | ||||||||||||||||
| <Lable>EMAIL</Lable> | ||||||||||||||||
| <Input name="email" value={email} onChange={handleFormChange} /> | ||||||||||||||||
| </UserInfo> | ||||||||||||||||
| <UserInfo> | ||||||||||||||||
| <Lable>PASSWORD</Lable> | ||||||||||||||||
| <Input | ||||||||||||||||
| name="password" | ||||||||||||||||
| type="password" | ||||||||||||||||
| value={password} | ||||||||||||||||
| onChange={handleFormChange} | ||||||||||||||||
| /> | ||||||||||||||||
| </UserInfo> | ||||||||||||||||
| </Row> | ||||||||||||||||
| <SunmitButton onClick={submitData}>로그인</SunmitButton> | ||||||||||||||||
| </Wrapper> | ||||||||||||||||
| ); | ||||||||||||||||
| } | ||||||||||||||||
|  | ||||||||||||||||
| const Wrapper = styled.div` | ||||||||||||||||
|  | @@ -12,3 +90,42 @@ const Wrapper = styled.div` | |||||||||||||||
| font-size: 18px; | ||||||||||||||||
| padding: 3rem 4rem; | ||||||||||||||||
| `; | ||||||||||||||||
|  | ||||||||||||||||
| const Header = styled.h2` | ||||||||||||||||
| font-size: 3rem; | ||||||||||||||||
| margin-bottom: 4rem; | ||||||||||||||||
| `; | ||||||||||||||||
|  | ||||||||||||||||
| const Row = styled.div` | ||||||||||||||||
| width: 100%; | ||||||||||||||||
| `; | ||||||||||||||||
|  | ||||||||||||||||
| const Lable = styled.label` | ||||||||||||||||
| font-size: 2rem; | ||||||||||||||||
| margin-right: auto; | ||||||||||||||||
| `; | ||||||||||||||||
|  | ||||||||||||||||
| const Input = styled.input` | ||||||||||||||||
| width: 75%; | ||||||||||||||||
| padding: 0.5rem 1rem; | ||||||||||||||||
| border: 1px, solid, grey; | ||||||||||||||||
| border-radius: 1rem; | ||||||||||||||||
| `; | ||||||||||||||||
|  | ||||||||||||||||
| const UserInfo = styled.div` | ||||||||||||||||
| display: flex; | ||||||||||||||||
| flex-direction: row; | ||||||||||||||||
| width: 100%; | ||||||||||||||||
| margin-bottom: 2rem; | ||||||||||||||||
| `; | ||||||||||||||||
|  | ||||||||||||||||
| const SunmitButton = styled.button` | ||||||||||||||||
| display: block; | ||||||||||||||||
| margin-left: auto; | ||||||||||||||||
| font-size: 1.8rem; | ||||||||||||||||
| cursor: pointer; | ||||||||||||||||
| padding: 0.5rem 1rem; | ||||||||||||||||
| border-radius: 1rem; | ||||||||||||||||
| border: 0; | ||||||||||||||||
| outline: 0; | ||||||||||||||||
| `; | ||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,8 +1,55 @@ | ||||||||||
| import React from "react"; | ||||||||||
| import React, { useEffect, useState } from "react"; | ||||||||||
|  | ||||||||||
| import CandidateForm from "./candidate-form"; | ||||||||||
|  | ||||||||||
| import styled from "styled-components"; | ||||||||||
| import axios from "axios"; | ||||||||||
|  | ||||||||||
| export default function VoteForm(props) { | ||||||||||
| const [candidateList, setCandidateList] = useState([]); | ||||||||||
| const { name, voteCount, rank, id } = candidateList; | ||||||||||
|  | ||||||||||
| useEffect(() => { | ||||||||||
| getCandidateList(); | ||||||||||
| }, [candidateList]); | ||||||||||
| 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. 
        Suggested change
       
 이 배열안에 candidateList가 들어있으면 getCandidateList 함수가 계속해서 실행된답니다 😅 | ||||||||||
|  | ||||||||||
| export default function VoteForm() { | ||||||||||
| return <Wrapper>안녕 나는 투표 폼!</Wrapper>; | ||||||||||
| const getCandidateList = async () => { | ||||||||||
| const data = await axios | ||||||||||
| .get(process.env.API_HOST + "/candidates/") | ||||||||||
| .then(function (response) { | ||||||||||
| return response.data; | ||||||||||
| }) | ||||||||||
| .catch(function (error) { | ||||||||||
| console.log(error); | ||||||||||
| }); | ||||||||||
| setCandidateList(data); | ||||||||||
| }; | ||||||||||
|  | ||||||||||
| var i = 1; | ||||||||||
|  | ||||||||||
| return ( | ||||||||||
| <Wrapper> | ||||||||||
| <Header1> | ||||||||||
| <Strong>프론트앤드 인기쟁이는</Strong> 누구? | ||||||||||
| </Header1> | ||||||||||
| <Header2>CEOS 프론트엔드 개발자 인기 순위 및 투표 창입니다.</Header2> | ||||||||||
| <CandidateListWrapper> | ||||||||||
| {candidateList | ||||||||||
| .sort((a, b) => { | ||||||||||
| return b.voteCount - a.voteCount; | ||||||||||
| }) | ||||||||||
| 
      Comment on lines
    
      +38
     to 
      +40
    
   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. 
        Suggested change
       
 화살표함수에서 바로 return할땐 중괄호와 return문을 생략할 수 있습니다~ | ||||||||||
| .map((candidate, index) => ( | ||||||||||
| <CandidateForm | ||||||||||
| key={JSON.stringify(candidate)} | ||||||||||
| id={candidate._id} | ||||||||||
| rank={i++} | ||||||||||
| 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. 
        Suggested change
       
 이렇게 바꿀 수 있어요! | ||||||||||
| name={candidate.name} | ||||||||||
| voteCount={candidate.voteCount} | ||||||||||
| /> | ||||||||||
| ))} | ||||||||||
| </CandidateListWrapper> | ||||||||||
| </Wrapper> | ||||||||||
| ); | ||||||||||
| } | ||||||||||
|  | ||||||||||
| const Wrapper = styled.div` | ||||||||||
|  | @@ -12,3 +59,22 @@ const Wrapper = styled.div` | |||||||||
| font-size: 18px; | ||||||||||
| padding: 3rem 4rem; | ||||||||||
| `; | ||||||||||
| const Header1 = styled.h2` | ||||||||||
| font-size: 30px; | ||||||||||
| font-weight: bolder; | ||||||||||
| `; | ||||||||||
|  | ||||||||||
| const Strong = styled.strong` | ||||||||||
| color: red; | ||||||||||
| `; | ||||||||||
|  | ||||||||||
| const Header2 = styled.p` | ||||||||||
| font-size: 26px; | ||||||||||
| font-weight: bolder; | ||||||||||
| color: grey; | ||||||||||
| `; | ||||||||||
|  | ||||||||||
| const CandidateListWrapper = styled.div` | ||||||||||
| padding: 5rem 10rem; | ||||||||||
| border: 1px solid black; | ||||||||||
| `; | ||||||||||
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.
외부 라이브러리와, 그렇지 않은 import들을 구분지어 묶어주세요!