TIL_58_2차 프로젝트 회원가입

poohv7·2021년 4월 7일
1

내가 구현한 회원가입 페이지.

  • 이메일 주소와 비밀번호가 조건에 부합할 경우, 밑에 뜨는 빨간 글씨 경고가 사라지도록 했다.
  • 사이즈 선택 모달창을 구현했고, 자식 컴퍼넌트인 모달창에서 얻은 데이터를 부모 컴퍼넌트인 회원가입 페이지에 전달하였다.
  • 동의를 구하는 체크박스를 구현. true/ false 로 한번 클릭하면 true -> 한번 더 클릭하면 false를 지정해, 색깔이 바뀌도록 하는 건 당연히 알고있었지만.. styled component로는 처음 구현해보는거여서 좀 헷갈렸다.
  • 아이디와 비밀번호의 형식이 부합할 경우에 회원가입 버튼이 활성화 되도록 구현.
  • 백엔드 Api 통신도 완료. 서버에 연결되어있을 경우, 회원가입 성공 alert 메세지가 뜨면서 로그인 페이지로 바로 연결되도록 구현했다.
this.state = {
      email: "",
      pw: "",
      //emailCheck: false,
      //multiCheckEmail: false,
      //pwCheck: false,
  //아이디 비밀번호 유효성 확인을 위해 넣어놨던 것..
      modalOn: false,
      checkOn: false,
      checkOnSecond: false,
      sizeClick: "",
    };
  handleModal = e => {
    this.setState({ modalOn: !this.state.modalOn, 
                   sizeClick: e.target.name });
  };
//모달창과 사이즈 선택의 state 값을 업데이트 시켜주기 위한 함수.
  boxClick = () => {
    this.setState({
      checkOn: !this.state.checkOn,
    });
  };

  boxClickSecond = () => {
    this.setState({
      checkOnSecond: !this.state.checkOnSecond,
    });
  };
//동의를 구하는 체크박스를 위한 함수.
  handleInputValue = e => {
    const { name, value } = e.target;
    this.setState({
      [name]: value,
    });
  };
//아이디와 비밀번호를 입력했을 때를 위한 함수.
  signUp = () => {
    fetch("http://10.58.1.71:8000/account/signup", {
      method: "POST",
      body: JSON.stringify({
        email: this.state.email,
        password: this.state.pw,
      }),
    })
      .then(res => res.json())
      .then(res => {
        // if (res.maessage === "INVALID_EMAIL") {
        //  alert("이메일 형식이 올바르지 않습니다.");
        //  }
        // if (res.message === "REGISTERED_EAMIL") {
        //  alert("이미 가입된 이메일입니다.");
        //}
        // if (res.message === "INVALID_PASSWORD") {
        //   alert("비밀번호 형식이 올바르지 않습니다.");
        // }
        // if (res.message === "KEY_ERROR") {
        //   alert("이메일 또는 비밀번호가 입력되지 않았습니다.");
        // }
        //  if (res.message === "INVALID_JSON") {
        //   alert("이메일과 비밀번호를 입력하여주세요.");
        //  }
        if (res.message === "SUCCESS") {
          this.props.history.push("/login");
          alert("회원가입이 완료되었습니다.");
        }
      });
  };

  //handleEmail = e => {
  //   const { email } = this.state;
  //  const EMAIL = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;
  //   if (email === "") {
  //    this.setState({ emailCheck: false, multiCheckEmail: "" });
  //     return;
  //  }
  //  if (EMAIL.test(email)) {
  //    this.setState({ email: false });
  //  } else {
  //    this.setState({ email: true, multiCheckEmail: "" });
  //    return;
  //  }

  //  fetch("http://10.58.1.71:8000/account/email", {
  //   method: "POST",
  //   body: JSON.stringify({
  //    email: email,
  //  }),
  // })
  //  .then(res => {
  //    return res.json();
  //  })
  //  .then(res => {
  //    if (res.message === "INVALID_EMAIL") {
  //      alert("이메일 형식을 지켜주세요.");
  //   }
  //   if (res.message === "REGISTERED_EAMIL") {
  //    alert("이미 존재하는 이메일입니다.");
  //   }
  // });
  // };

  //handlePw = e => {
  // const { pw } = this.state;
  //fetch("http://10.58.1.71:8000/account/password", {
  //  method: "POST",
  //  body: JSON.stringify({
  //    password: pw,
  //  }),
  // })
  //  .then(res => {
  //    return res.json();
  //  })
  //  .then(res => {
  //     if (res.message === "INVALID_PASSWORD") {
  //    alert("비밀번호 형식을 지켜주세요");
  //   }
  //if (!/^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,25}$/.test(pw)) {
  //alert("숫자+영문자+특수문자 조합으로 8자리 이상 사용해야 합니다.");
  //}
  // });
  //  };
  sizeModal = e => {
    this.setState({ sizeClick: e });
  };
render() {
    const btnChange = this.state.checkOn ? "checkOn" : "checkOff";
    const btnChangeSecond = this.state.checkOnSecond
      ? "checkOnSecond"
      : "checkOff";
  //뭔가 하나로 줄일 수 있을 것 같긴한데..
  //두번 지정해준 이유는 한 번만 지정하면 클릭할 때 두 개가 동시에 바뀌기 때문.. 
    return (
      <JoinArea>
        <JoinTitle>회원가입</JoinTitle>
        <ButtonInputBox>
          <InputTitle>이메일 주소*</InputTitle>
          <InputTxt
            name="email"
            type="text"
            placeholder="예) heuream@heuream.co.kr"
            onChange={this.handleInputValue}
          />
          {this.state.email && this.state.email.includes("@") ? null : (
            <div style={{ color: "red", fontSize: "10px" }}>
              이메일 형식을 지켜주세요.
            </div>
          )}
          //"@"가 포함되면 경고문자가 사라지도록.
        </ButtonInputBox>
        <ButtonInputBox>
          <InputTitle>비밀번호*</InputTitle>
          <InputTxt
            name="pw"
            type="password"
            placeholder="영문,숫자,특수문자 조합 8-16자"
            onChange={this.handleInputValue}
          />
          {this.state.pw && this.state.pw.length >= 8 ? null : (
            <div style={{ color: "red", fontSize: "10px" }}>
              비밀번호 형식을 지켜주세요.
            </div>
          )}
          //8자 이상이면 경고문자가 사라지도록.
          //다음엔 위의 조건 그대로 적용해보자.
        </ButtonInputBox>
        <ButtonInputBox>
          <InputTitle>스니커즈 사이즈 (선택)</InputTitle>
          <Modal
            handleModal={this.handleModal}
            modalOn={this.state.modalOn}
            sizeClick={this.state.sizeClick}
          />
          //Modal 컴퍼넌트에 sizeClick을 props로 넘겨주고 있다.
          <InputTxt
            type="text"
            placeholder="선택하세요"
            onClick={this.handleModal}
            value={this.state.sizeClick}
          ></InputTxt>
          //선택하세요 인풋창에 사이즈 클릭 값이 들어올 수 있도록
        </ButtonInputBox>
        <JoinWrap>
          <LabelTxt>
            <FiCheckSquare
              className={btnChange}
              size="20px"
              onClick={this.boxClick}
            />
            &nbsp;&nbsp;[필수]14세 이상이며 모두 동의합니다.
          </LabelTxt>
          <LabelTxt2>
            <FiCheckSquare
              className={btnChangeSecond}
              size="20px"
              onClick={this.boxClickSecond}
            />
            &nbsp;&nbsp;[선택] 광고성 정보 수신에 모두 동의합니다.
          </LabelTxt2>
        </JoinWrap>
        <JoinBtnBox>
          <JoinBtn
            email={this.state.email}
            pw={this.state.pw}
            onClick={this.signUp}
          >
            회원가입
          </JoinBtn>
        </JoinBtnBox>
      </JoinArea>
    );
  }
}
const JoinArea = styled.div`
  width: 400px;
  height: 678px;
  padding: 60px 0 160px;
  padding-top: 150px;
  margin: 0 auto;
`;

const JoinTitle = styled.h2`
  padding-bottom: 50px;
  font-size: 30px;
  font-weight: bold;
  text-align: center;
`;

const ButtonInputBox = styled.div`
  width: 400px;
  height: 80px;
  position: relative;
  padding: 10px 0 14px;
`;

const InputTitle = styled.h3`
  width: 400px;
  font-size: 13px;
  font-weight: bold;
  letter-spacing: -0.07px;
  line-height: 18px;
`;

const InputTxt = styled.input`
  width: 400px;
  height: 38px;
  cursor: text;
  margin-right: 300px;
  border-bottom: 1px solid #ebebeb;
  &::placeholder {
    font-size: 14px;
    color: lightgray;
  }
  &:hover {
    cursor: pointer;
    border-bottom: 2px solid black;
  }
`;

const JoinWrap = styled.div`
  padding: 24px 0 40px;
`;

const LabelTxt = styled.div`
  margin-bottom: 17px;
  font-size: 12px;
  .checkOn {
    background-color: black;
    color: white;
  }
`;
//checkOn 클라스에 효과를 넣었다.
//체크박스를 누를 때마다 바뀌도록.

const LabelTxt2 = styled.div`
  margin-bottom: 17px;
  font-size: 12px;
  .checkOnSecond {
    background-color: black;
    color: white;
  }
`;

const JoinBtnBox = styled.div`
  width: 400px;
  height: 140px;
`;

const JoinBtn = styled.button`
  width: 400px;
  height: 52px;
  border-radius: 12px;
  background-color: ${props =>
    props.email.includes("@") && props.pw.length >= 8
      ? "black"
      : "rgb(235, 235, 235)"};
  color: white;
  font-weight: bold;
`;
//별거 아니지만 하고나서 좀 뿌듯했던 것...
//스타일드 컴퍼넌트의 장점 중 하나. 
//프롭스로 받아서 조건문을 작성할 수 있다.
class Modal extends React.Component {
  render() {
    return (
      <>
        {this.props.modalOn ? (
          <WrapModal onClick={this.props.handleModal}>
            <ModalContainer>
              <LayerHeader>
                <Title>사이즈 선택</Title>
              </LayerHeader>
              <LayerContent>
                <SizeList>
                  <SizeItem>
                    {SIZE.map((size, index) => (
                      <ItemBtn
                        onClick={this.props.handleModal}
                        name={size.size}
                       //모달에서 바뀐 내용은 위 하나.
                        id={size.id}
                        key={size.id}
                      >
                        {size.size}
                      </ItemBtn>
                    ))}
                  </SizeItem>
                </SizeList>
                <LayerBtn>
                  <Button onClick={this.props.handleModal}>확인</Button>
                </LayerBtn>
              </LayerContent>
            </ModalContainer>
          </WrapModal>
        ) : null}
      </>
    );
  }
}

0개의 댓글