Skip to content
This repository was archived by the owner on Sep 19, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 12 additions & 3 deletions pages/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import React from "react";
import React, { useState } from "react";
import styled from "styled-components";

import LoginForm from "../src/components/login-form";
import CandidateList from '../src/components/candidate-list'

export default function Home() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
return (
<Wrapper>
리액트 투-표
<LoginForm />
<Title>리액트 투-표</Title>
{isLoggedIn ? <CandidateList /> : <LoginForm setIsLoggedIn={setIsLoggedIn} />}
</Wrapper>
);
}
Expand All @@ -16,4 +18,11 @@ const Wrapper = styled.div`
min-height: 100vh;
padding: 10rem 40rem;
background-color: Azure;
position:relative;
`;

const Title = styled.div`

Choose a reason for hiding this comment

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

const Title=styled.h1`
과 같이 semantic tag로 쓰면 더 좋을 거 같아요👍

font-weight: bold;
font-size: 4rem;
margin-bottom: 20px;
`
78 changes: 78 additions & 0 deletions src/components/candidate-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React, { useEffect, useState } from "react";
import styled from "styled-components";
import axios from "axios"
import Candidate from './candidate';



export default function CandidateList() {
const [candidates, setCandidates] = useState([]);

const getData = async () => {
const response = await axios.get(process.env.API_HOST + '/candidates')
return response.data
}

const sendVoteRequest = async (id) => {
const response = await axios.put(process.env.API_HOST + `/candidates/${id}/vote`);
return response.data
}

const handleVote = (id) => {
sendVoteRequest(id).then(()=>{
getData().then((data)=> {
console.log('hhh')

Choose a reason for hiding this comment

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

코드 올릴때는 console.log 빼주세요!

setCandidates(data);
})
})
}


useEffect(() => {
getData().then((data) => {
setCandidates(data);
})
}, [])

return <Wrapper>
<Title><Red>프론트엔드 인기쟁이</Red>는 누구?</Title>
<SubTitle>CEOS 프론트엔드 개발자 인기 순위 및 투표 창입니다.</SubTitle>
<Board>
{candidates.sort((a, b) => {
return b.voteCount - a.voteCount
}).map((candidate, rank) => {
return <Candidate rank={rank+1} {...candidate} handleVote={handleVote}></Candidate>
})}
</Board>
</Wrapper>
}

const Wrapper = styled.div`
width: 100%;
min-height: 30rem;
background-color: white;
font-size: 18px;
padding: 3rem 4rem 10rem;
`

const Title = styled.h2`
font-size: 3rem;
`

const Red = styled.span`
color: red;
`

const SubTitle = styled.h3`
font-size: 2.5rem;
color: grey;
`

const Board = styled.div`
width: 100%;
padding: 5rem 10rem;
border-width: 1px;
border-style: solid;
border-color: black;
border-image: initial;
`
41 changes: 41 additions & 0 deletions src/components/candidate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from "react";
import styled from "styled-components";
import axios from 'axios';

export default function Candidate({ rank, name, voteCount, _id, handleVote}) {
console.log('id: ', _id)

Choose a reason for hiding this comment

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

이 console도 마찬가지로 지워주시면 좋을 거 같아요!

return <Wrapper>
<Rank>{rank}위:</Rank>
<Name>{name} [{voteCount}표]</Name>
<VoteButton onClick={() => {handleVote(_id)}}>투표</VoteButton>
</Wrapper>
}

const Wrapper = styled.div`
display: flex;
flex-direction: row;
align-items: center;
`

const Rank = styled.strong`
font-size: 2.5rem;
width: 10rem;
margin-bottom: 1rem;
`

const Name = styled.p`
font-size: 2.5rem;
margin: 0rem auto 1rem 0rem;
`

const VoteButton = styled.button`
background-color: navy;
Copy link
Member

Choose a reason for hiding this comment

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

navy라는 이름보다는 16진수를 사용한 색상표를 사용하시는 것이 좋을 것 같아요

color: white;
font-size: 2rem;
padding: 0.5rem 1rem;
border-width: initial;
border-style: none;
border-color: initial;
border-image: initial;
border-radius: 1rem;
`
87 changes: 84 additions & 3 deletions src/components/login-form.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,95 @@
import React from "react";
import React, { useState } from "react";
import styled from "styled-components";
import axios from 'axios'

export default function LoginForm() {
return <Wrapper>안녕 나는 로그인 폼!</Wrapper>;
export default function LoginForm({ setIsLoggedIn }) {
const [loginData, setLoginData] = useState({ email: "", password: "" })

const handleInputChange = (e) => {
const { name, value } = e.target;
setLoginData({ ...loginData, [name]: value });
console.log(loginData);
}


const handleSubmit = () => {
if (validateInput(loginData)) {
axios.post(process.env.API_HOST + '/auth/signin', loginData).
then((response) => {
console.log(response.data)

Choose a reason for hiding this comment

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

console.log는 commit할 때 지워주세용

setIsLoggedIn(true)
})
.catch((error) => {
console.error(error);
alert('로그인에 실패했습니다')
})
}
}

const validateInput = (data) => {
const { email, password } = data;
if ((!email) || (!password)) {
alert('폼을 다 채워주세요')
return false;
} else {
return true;
}
}

return <Wrapper>
<Title>로그인</Title>
<Row>
<Label>EMAIL</Label>
<Input name="email" onChange={handleInputChange} />
</Row>
<Row>
<Label>PASSWORD</Label>
<Input name="password" type="password" onChange={handleInputChange} />

Choose a reason for hiding this comment

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

type="password"
이 부분이 페이지에 반영이 안되고 있는거 같은데 확인해주세요!

</Row>
<Row>
<div style={{ marginRight: 'auto' }}></div>
<Button onClick={handleSubmit}>로그인</Button>
</Row>

</Wrapper>;
Comment on lines +39 to +54

Choose a reason for hiding this comment

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

  1. Email과 Password 넣는 칸을 Input으로 묶어서 하나의 컴포넌트 안에 넣는 건 어떨까요?
    <InputWrapper> <Row> <Label>EMAIL</Label> <Input name="email" onChange={handleInputChange} /> </Row> <Row> <Label>PASSWORD</Label> <Input name="password" type="password" onChange={handleInputChange} /> </Row> </InputWrapper> <SubmitButton onClick={handleSubmit}>로그인</SubmitButton>
    이런식으로요!!
    그렇게 되면
    <div style={{ marginRight: 'auto' }}></div>
    따로 이 코드를 안 넣어도 되고 알아보기도 좋을 거 같아요!
  2. 핸들링 네이밍 잘하셨네요!

}

const Row = styled.div`
margin-bottom: 10px;
margin-top: 20px;
font-size: 15px;
display: flex;
`
const Label = styled.div`
margin-right: auto;
`
const Input = styled.input`
width: 75%;
border: 1px solid grey;
padding: 5px;
outline: none;
`

const Wrapper = styled.div`
width: 100%;
min-height: 30rem;
background-color: white;
font-size: 18px;
padding: 3rem 4rem;
`;

const Title = styled.div`
Copy link

@LEE-SOOWAN65 LEE-SOOWAN65 Apr 19, 2020

Choose a reason for hiding this comment

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

글씨에 관한 스타일링은 p태그를 써주면 됩니다!
const Title=styled.p
이렇게요!

font-size: 25px;
`

const Button = styled.button`
outline:none;
background-color:#d6d6d6;
border-radius:3px;
border:none;
width: 150px;
margin-left: auto;
font-size: 15px;
padding: 5px;
`
Comment on lines +57 to +95

Choose a reason for hiding this comment

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

, <Title>, 순으로 컴포넌트가 나타나니까 컴포넌트 정의를 할 때도 먼저 나타나는 컴포넌트 순으로 정리하면 나중에 수정할 때 찾기 더 용이할 거 같아요!