내일배움캠프 최종 프로젝트 - 로그인과 회원가입 (3)

새벽로즈·2024년 1월 11일
post-thumbnail
  1. 필요한 것 import
'use client';
import {auth, db} from '@/firebase';
import {Button, Input} from '@nextui-org/react';
import {createUserWithEmailAndPassword} from 'firebase/auth/cordova';
import {doc, setDoc} from 'firebase/firestore';
import {useRouter} from 'next/navigation';
import React, {useState} from 'react';
  1. useState 훅을 사용해 필요한 상태값 설정
const JoinPage = () => {
  const [step, setStep] = useState<number>(1); // 회원가입 진행 단계
  const [email, setEmail] = useState<string>('');
  const [password, setPassword] = useState<string>('');
  const [confirmPassword, setConfirmPassword] = useState<string>('');
  const [birthDate, setBirthDate] = useState<string>('');
  const [nickname, setNickname] = useState<string>('');
  const [progress, setProgress] = useState<number>(20);
  // 비밀번호 일치 여부를 저장할 상태 추가
  const [isPasswordMatch, setIsPasswordMatch] = useState<boolean>(true);
  const router = useRouter();
  const progressBarStyle = {
    width: `${progress}%`,
    // 진행률이 변경될 때 부드럽게 애니메이션 적용
    transition: 'width 0.3s ease-in-out',
  };
  1. 여러 함수 정의
  // 다음 단계로 이동하는 함수
  const moveToNextStep = () => {
    setStep(step + 1);
    // 진행률 갱신
    setProgress((step + 1) * 20);
  };

  // 회원가입 함수
  const clickJoinHandler = async (event: React.FormEvent) => {
    event.preventDefault();

    if (step !== 4) {
      alert('모든 단계를 완료해야 회원가입이 가능합니다.');
      return;
    }

    try {
      const userCredential = await createUserWithEmailAndPassword(auth, email, password);
      const user = userCredential.user;

      // Firestore에 사용자 추가 정보 저장
      await setDoc(doc(db, 'users', user.uid), {
        email,
        birthdate: birthDate,
        nickname,
      });

      // 회원가입 성공 메시지 표시
      alert('회원가입 성공!');
      setStep(5);
      // 프로그래스 바 완료 상태로 설정
      setProgress(100);
    } catch (error) {
      setNickname('');
      console.error(error);
      alert(error);
    }
  };
  1. 스텝 렌더링 함수
  • 현재 단계에 따라 어떤 컴포넌트를 렌더링할지 결정하는 함수 정의
  • switch 문을 사용해 현재 단계에 따라 다른 컴포넌트를 반환
  const renderStep = () => {
    switch (step) {
      case 1:
        return (
          <div>
            <Input
              type="email"
              label="이메일"
              value={email}
              onChange={e => setEmail(e.target.value)}
              placeholder="이메일을 입력해주세요."
            />
            <Button onClick={moveToNextStep} type="button">
              다음
            </Button>
          </div>
        );
      case 2:
        return (
          <div>
            <Input
              type="password"
              label="비밀번호"
              value={password}
              onChange={e => setPassword(e.target.value)}
              placeholder="비밀번호를 입력해주세요."
            />
            <Input
              type="password"
              value={confirmPassword}
              onChange={e => setConfirmPassword(e.target.value)}
              placeholder="다시 한번 비밀번호를 입력해주세요."
              label="비밀번호 확인"
            />
            <Button onClick={moveToNextStep} type="button">
              다음
            </Button>
          </div>
        );
      case 3:
        return (
          <div>
            <Input
              type="date"
              label="생년월일"
              value={birthDate}
              onChange={e => setBirthDate(e.target.value)}
              placeholder="생년월일"
            />
            <Button onClick={moveToNextStep} type="button">
              다음
            </Button>
          </div>
        );
      case 4:
        return (
          <div>
            <Input
              type="text"
              label="닉네임"
              value={nickname}
              onChange={e => setNickname(e.target.value)}
              placeholder="닉네임을 입력해주세요. "
              maxLength={10}
            />
            <Button onClick={clickJoinHandler} type="button">
              회원가입
            </Button>
          </div>
        );
      case 5:
        return (
          <div>
            <p>회원가입 완료</p>
            <Button color="primary" type="button" onClick={() => router.replace('auth')}>
              로그인하러가기
            </Button>
          </div>
        );

      default:
        return null;
    }
  };
  1. 렌더링
  • 최종적으로 위에서 정의한 상태값, 함수, 컴포넌트 등을 사용해서 UI 렌더링
  • 프로그레스 바와 함께 현재 단계에 맞는 입력 폼을 보여주는 형태로 만듬
  return (
    <div>
      {/* 프로그래스 바 */}
      <div className="progress-bar">
        <div className="bg-gray-200 w-full h-4">
          <div className="bg-blue-500 h-4" style={progressBarStyle}></div>
        </div>
      </div>
      <form onSubmit={clickJoinHandler} className="w-2/3 flex flex-wrap justify-center m-auto">
        {renderStep()}
      </form>
    </div>
  );
};

export default JoinPage;

오늘의 한줄평 : 유효성 검사랑 자꾸 겹쳐서 오류가 나서 일단 먼저 단계 구현부터 우선했다.

profile
귀여운 걸 좋아하고 흥미가 있으면 불타오릅니다💙 최근엔 코딩이 흥미가 많아요🥰

0개의 댓글