회원가입 페이지가 총 3페이지로 나누어져 있어서 카운트 변수를 만들어 해당 변수값에 따라 컴포넌트를 보여주기로 했다.
import styled from "styled-components";
import Signup1 from "../components/signup/signup1";
import Signup2 from "../components/signup/signup2";
import Signup3 from "../components/signup/signup3";
import BackHeader from "../components/common/backHeader";
import { useState } from "react";
const Signup: React.FC = () => {
const [step, setStep] = useState(1);
const handleNext = () => {
if (step < 3) {
setStep(step + 1);
}
};
const handleBack = () => {
if (step > 1) {
setStep(step - 1);
}
};
return (
<>
<SignupWrapper>
<BackHeader onBack={handleBack} />
{step === 1 && <Signup1 onNext={handleNext} />}
{step === 2 && <Signup2 onNext={handleNext} />}
{step === 3 && <Signup3 />}
</SignupWrapper>
</>
);
};
export default Signup;
const SignupWrapper = styled.div`
width: 55%;
margin: 0 auto;
`;
해당 BackHeader 컴포넌트로 카운트를 낮춰서 회원가입의 뒤로가기 구현을 했다. 이제 걸리는 점은 저 뒤로가기 컴포넌트를 다른 곳에서도 사용해야 하는데 지금 사용하는 변수 낮추기와는 다르게 그 때는 navigate를 사용해 페이지를 이동시켜야 한다. onClick시의 함수 변화를 상황에 따라 다르게 주거나 아니면 컴포넌트를 나눠서 현재 뒤로가기는 회원가입에서만 사용하던지 결정해야 한다. 이 부분은 나중에 기능 작업 들어갈 때 수정할 예정
뒤로가기는 해당 컴포넌트로 사용되고 넘어가는 건 각 회원가입마다 다음 버튼이 있는데 해당 버튼을 상호작용해서 넘어가는 방식이다.
import styled from "styled-components";
import BackHeader from "../common/backHeader";
import CommonInput from "../common/commonInput";
import NextBtn from "./nextBtn";
import SignupCount from "./signupCount";
import SignupGuide from "./signupGuide";
import PwVisible from "../common/pwVisible";
import React, { useState } from "react";
interface NextProps {
onNext: () => void;
}
const Signup1: React.FC<NextProps> = ({ onNext }) => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [passwordConfirm, setPasswordConfirm] = useState("");
return (
<>
<Signup1Wrapper>
<SignupBox>
<SignupCount count="1" />
<SignupGuide text="이메일과 비밀번호를 입력해주세요." />
<EmailBox>
<CommonInput
typeValue="email"
placeholderValue="이메일"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<EmailCheck>√ 8자리 이상</EmailCheck>
<EmailCheck>
√ 대문자, 소문자, 숫자, 특수문자 중 2개 이상
</EmailCheck>
</EmailBox>
<CommonInput
typeValue="password"
placeholderValue="비밀번호"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<PwVisible />
<CommonInput
typeValue="password"
placeholderValue="비밀번호 확인"
value={passwordConfirm}
onChange={(e) => setPasswordConfirm(e.target.value)}
/>
<NextBtn onClick={onNext} />
</SignupBox>
</Signup1Wrapper>
</>
);
};
export default Signup1;
const Signup1Wrapper = styled.div`
width: 100%;
display: flex;
flex-direction: column;
`;
const SignupBox = styled.div`
width: 100%;
margin: 50px auto;
`;
const EmailBox = styled.div`
display: flex;
flex-direction: column;
margin: 10px 0;
`;
const EmailCheck = styled.div`
font-size: 11px;
margin-left: 10px;
color: #c9c9c9;
`;
회원가입 1번을 보면 이메일과 비밀번호를 입력하는 input칸이 있고 맨 밑에 NextBtn 컴포넌트가 있다.
import styled from "styled-components";
const NextBtn = ({ onClick }) => {
return (
<>
<NextBtnCss onClick={onClick}>다음</NextBtnCss>
</>
);
};
export default NextBtn;
const NextBtnCss = styled.button`
width: 100%;
background-color: rgba(255, 164, 228, 0.7);
border: none;
border-radius: 10px;
padding: 10px 0;
margin-top: 20px;
outline: none;
font-size: 14px;
font-weight: bold;
color: white;
cursor: pointer;
`;
해당 컴포넌트는 버튼만 작성되어있는 컴포넌트이고 해당 버튼에 onClick을 지정하되 그걸 상위 컴포넌트까지 가지고 와서 입력해주는 방식이다.
그래서 회원가입 페이지에서 입력한 값을 클릭이벤트에 담아 하위로 보내 작동시킨다.
import styled from "styled-components";
import BackHeader from "../common/backHeader";
import SignupCount from "./signupCount";
import SignupGuide from "./signupGuide";
import CommonInput from "../common/commonInput";
import NextBtn from "./nextBtn";
import { useState } from "react";
interface NextProps {
onNext: () => void;
}
const Signup2: React.FC<NextProps> = ({ onNext }) => {
const [nickname, setNickname] = useState("");
return (
<>
<Signup2Wrapper>
<SignupBox>
<SignupCount count="2" />
<SignupGuide text="닉네임을 설정해주세요" />
<NicknameBox>
<CommonInput
typeValue="text"
placeholderValue="닉네임"
value={nickname}
onChange={(e) => setNickname(e.target.value)}
/>
<NickCheckWrapper>
<NicknameCheck>사용할 수 있는 닉네임이에요</NicknameCheck>
<span>0/10</span>
</NickCheckWrapper>
<NickCheckWrapper>
<NicknameCheck>사용할 수 없는 닉네임이에요</NicknameCheck>
<span>10/10</span>
</NickCheckWrapper>
<RandomCreate>랜덤 생성</RandomCreate>
</NicknameBox>
<NextBtn onClick={onNext} />
</SignupBox>
</Signup2Wrapper>
</>
);
};
export default Signup2;
const Signup2Wrapper = styled.div`
width: 100%;
display: flex;
flex-direction: column;
`;
const SignupBox = styled.div`
width: 100%;
margin: 50px auto;
`;
const NicknameBox = styled.div`
display: flex;
flex-direction: column;
margin: 10px 0;
`;
const NicknameCheck = styled.div`
font-size: 11px;
margin-left: 10px;
color: #585858;
`;
const NickCheckWrapper = styled.div`
display: flex;
justify-content: space-between;
span {
font-size: 10px;
}
`;
const RandomCreate = styled.button`
width: 30%;
border: 1px solid #b0b0b0;
border-radius: 5px;
background-color: white;
color: #848484;
font-size: 10px;
font-weight: bold;
margin: 10px 0;
padding: 3px 0;
`;
회원가입 2번에도 동일하게 닉네임을 담는 input칸과 다음으로 넘어가는 버튼이 있고
import styled from "styled-components";
import BackHeader from "../common/backHeader";
import SignupCount from "./signupCount";
import SignupGuide from "./signupGuide";
import CommonInput from "../common/commonInput";
import { useState } from "react";
import CommonCheckBox from "./commonCheckbox";
import CommonRadioBox from "./commonRadiobox";
import CompleteBtn from "./completeBtn";
const Signup3: React.FC = () => {
const [nickname, setNickname] = useState("");
return (
<>
<Signup3Wrapper>
<SignupBox>
<SignupCount count="3" />
<SignupGuide text="태어난 연도를 알려주세요" />
<CommonInput
typeValue="text"
placeholderValue="예) 1995"
value={nickname}
onChange={(e) => setNickname(e.target.value)}
/>
<SignupGuide text="성별을 선택해주세요" />
<GenderBox>
<CommonRadioBox label="남자" name="gender" />
<CommonRadioBox label="여자" name="gender" />
</GenderBox>
<SignupGuide text="어떤 피부 타입인가요?" />
<SkinBox1>
<CommonRadioBox label="건성" name="skin" />
<CommonRadioBox label="중성" name="skin" />
<CommonRadioBox label="지성" name="skin" />
</SkinBox1>
<SkinBox2>
<CommonRadioBox label="복합성" name="skin" />
<CommonRadioBox label="수부지" name="skin" />
</SkinBox2>
<SignupGuide text="퍼스널컬러를 골라주세요" />
<ColorBox1>
<CommonRadioBox label="봄웜톤" name="color" />
<CommonRadioBox label="여름쿨톤" name="color" />
<CommonRadioBox label="가을웜톤" name="color" />
<CommonRadioBox label="겨울쿨톤" name="color" />
</ColorBox1>
<ColorBox2>
<CommonRadioBox label="잘 모르겠어요.." name="color" />
</ColorBox2>
<SignupGuide text="피부 고민이 있나요?" />
<TroubleBox>
<CommonCheckBox label="아토피" />
<CommonCheckBox label="여드름" />
<CommonCheckBox label="민감성" />
<CommonCheckBox label="홍조" />
<CommonCheckBox label="각질" />
<CommonCheckBox label="속건조" />
<CommonCheckBox label="등" />
<CommonCheckBox label="등등" />
<CommonCheckBox label="등등등" />
</TroubleBox>
<CompleteBtn />
</SignupBox>
</Signup3Wrapper>
</>
);
};
export default Signup3;
const Signup3Wrapper = styled.div`
width: 100%;
display: flex;
flex-direction: column;
`;
const SignupBox = styled.div`
width: 100%;
margin: 50px auto;
`;
const GenderBox = styled.div`
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
`;
const SkinBox1 = styled.div`
width: 100%;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 5px;
`;
const SkinBox2 = styled.div`
width: 72%;
margin: 0 auto;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 5px;
`;
const ColorBox1 = styled.div`
width: 100%;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 5px;
`;
const ColorBox2 = styled.div`
width: 100%;
`;
const TroubleBox = styled.div`
width: 100%;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 5px;
`;
회원가입 3번은 마지막 컴포넌트라 다음 버튼 대신 회원가입을 완료하는 버튼이 있다.
아직 데이터를 저장하는 리액트 훅을 작성하진 않았는데 이 후에 기능 작업에 들어가면서 백엔드와 연동할 때 리덕스를 사용해 회원가입 데이터를 담아줄 생각이다.
예전에 다른 프로젝트를 진행했을 때도 회원가입이 페이지가 5페이지가 있었는데 원래는 navigate의 localtion 기능에 컨텍스트 api처럼 데이터를 담아 보낼 수 있는 기능이 있다고 했으나 매번 데이터를 누적시켜서 마지막 페이지까지 보내는게 너무 까다롭고 불필요해 보여서 리덕스 툴킷을 사용해서 해볼 예정이다.
![]() |
![]() |
![]() |
3번의 버튼들은 필수가 아닌 선택형이며 제일 하단의 컨텐츠만 체크박스로 중복선택이 가능하고 나머지는 라디오 버튼으로 하나만 선택 가능하게 해놨다.
import styled from "styled-components";
const CommonRadioBox = ({ label, name }: { label: string; name: string }) => {
return (
<>
<Label>
<HiddenRadioButton type="radio" name={name} />
<RadioButtonText>{label}</RadioButtonText>
</Label>
</>
);
};
export default CommonRadioBox;
const Label = styled.label`
display: flex;
align-items: center;
cursor: pointer;
`;
const HiddenRadioButton = styled.input`
position: absolute;
opacity: 0;
cursor: pointer;
`;
const RadioButtonText = styled.div`
width: 100%;
border: 3px solid rgba(255, 164, 228, 0.5);
border-radius: 13px;
padding: 10px 10px;
margin-bottom: 5px;
font-size: 16px;
text-align: center;
outline: none;
color: #848484;
${HiddenRadioButton}:checked + & {
background-color: #ffa4e4;
color: white;
font-weight: bold;
}
`;
체크박스와 라디오박스는 css는 비슷하게 해놨으나 기능이 다르기에 컴포넌트를 나누어놨고 해당 체크박스 선택 부분에는 grid를 사용해 같은 비율로 지정을 해놓았다. flex도 좋지만 grid도 사용할 줄 알면 되게 편리해서 익숙해져야 할 것 같다.
'개발 TIL' 카테고리의 다른 글
24.08.26 day53 작업 일지 (2) | 2024.08.26 |
---|---|
24.08.23 day52 캡슐화, 미들웨어 (0) | 2024.08.23 |
24.08.21 day50 공용 컴포넌트 작성 방식 (0) | 2024.08.21 |
24.08.20 day49 로그인 UI (0) | 2024.08.20 |
24.08.19 day48 HTML 작성 규칙 (0) | 2024.08.19 |