Skip to content
Snippets Groups Projects
Select Git revision
  • 743a8bd60fa3e67875b78a36a8f95d86d754a82d
  • main default protected
  • issue-28
3 results

SignUp.js

  • SignUp.js 12.02 KiB
    import '../assets/App.css';
    import '../assets/style.css';
    import '../assets/signup.css';
    import Region from './Region.js';
    import {Link, useNavigate} from 'react-router-dom';
    import { useRef, useContext, useState, useEffect } from 'react';
    import { CrewContext } from '../contexts/CrewContext.js';
    
    const apiUrl = process.env.REACT_APP_API_URL;
    
    function SignUp(){
    
      const { onCreateUser } = useContext(CrewContext);
      const navigate = useNavigate();
    
      const [signUpSection, setSignUpSection] = useState(true);
      const [profileSection, setProfileSection] = useState(false);
      const [nextProfileSection, setNextProfileSection] = useState(false); //다음 프로필 설정 페이지로 가기 위한 state
    
    
      const [imagePreview, setImagePreview] = useState(null); // 이미지 미리보기를 위한 state
      const [imageFile, setImageFile] = useState(null); // 이미지 파일을 저장할 state
    
      // 필수 입력 항목 저장
      const [name, setName] = useState('');
      const [password, setPassword] = useState('');
      const [email, setEmail] = useState('');
      const [regionID, setRegionID] = useState(0);
      const [sportTypeID, setSportTypeID] = useState(0);
    
      // 프로필 항목 저장
      const [job, setJob] = useState('');
      const [birthdate, setBirthdate] = useState('');
      const [experience, setExperience] = useState('');
      const [introduction, setIntroduction] = useState('');
    
    
      // 유효성 검사
      const [isName, setIsName] = useState(false);
      const [isPassword, setIsPassword] = useState(false);
      const [isEmail, setIsEmail] = useState(false);
      const [isRegionID, setIsRegionID] = useState(false);
      const [isSportTypeID, setIsSportTypeID] = useState(false);
    
      const sportTypeMapping = {
        'running': 1,
        'climbing': 2,
        'fitness': 3,
      };
    
    
      const handleImageChange = (e) => {
        const file = e.target.files[0];
        setImageFile(file);             // 실제 파일
        console.log(imageFile);
        if (file) {
          const reader = new FileReader();
          
          reader.onloadend = () => {
            setImagePreview(reader.result);  // 미리보기용 이미지
          };
        }
      };
    
      const handleImageUpload = async (e) => {
    
        e.preventDefault();
    
        const formData = new FormData();
        formData.append('image', imageFile);
      
        try {
          const response = await fetch(`${apiUrl}/api/images`, {
            method: 'POST',
            body: formData,
          });
      
          const data = await response.json();
      
          if (response.ok) {
            // 업로드 성공시, 서버에서 반환된 이미지 URL을 받음
            const imageUrl = data.image_url;
            return imageUrl
          } else {
            console.error(data.error);
            alert(data.error);
          }
        } catch (error) {
          console.log(error);
        }
      }
    
    
      const handleSubmit = async (e) => {
    
        e.preventDefault();
        const imageUrl = await handleImageUpload(imageFile); // 이미지 업로드 함수 호출
        console.log(imageUrl);
        
        if(isSportTypeID) {
    
          const user = {
              
            name: name,
            email: email,
            password: password,
            profile: {
              profileImage: imageUrl,
              regionID: regionID,
              job: job,
              birthDate: birthdate,
              experience: experience,
              introduction: introduction,
              sportTypeID: sportTypeID,
            },
          };
          createUser(user);
        }
        else {
          alert("원하는 운동 종목을 입력해 주세요.");
      }
    }
    
    const createUser = async (newUser) => {
    
      try {
        const response = await fetch(`${apiUrl}/api/users`, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(newUser),
        })
        const data = await response.json();
        console.log(data)
        if(data) {
          navigate('/login');
        }
      }catch (error) {
        console.error(error);
      }
    
    };
    
    
      const handleNameChange = (e) => {
        const currentName = e.target.value;
        setName(currentName);
        /*if(name.length > 0) {
          setIsName(true);
        }*/
        setIsName(currentName.trim().length > 0);
      }
    
      const handleEmailChange = (e) => {
        const currentEmail = e.target.value;
        setEmail(currentEmail);
        const emailRegExp =
          /^[A-Za-z0-9_]+[A-Za-z0-9]*[@]{1}[A-Za-z0-9]+[A-Za-z0-9]*[.]{1}[A-Za-z]{1,3}$/;
        setIsEmail(emailRegExp.test(currentEmail));
      };
    
      const handleEmailVerify = async (e) => {
    
        e.preventDefault();
    
        try {
          const response = await fetch(`${apiUrl}/api/verify_email`, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({ email }),
          });
    
    
          const data = await response.json();
    
          if (response.ok) {
            alert(data.message);
          } else {
            alert(data.error);
          }
        } catch (error) {
          console.error(error);
        }
      };
    
      const handlePasswordChange = (e) => {
        const currentPassword = e.target.value;
        setPassword(currentPassword);
        const passwordRegExp =
          /^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,16}$/;
        setIsPassword(passwordRegExp.test(currentPassword));
      };
    
      // 회원가입 버튼 클릭 후 프로필 설정으로
      const handleProfileSection = (e) => {
        e.preventDefault();
        if(isName && isEmail && isPassword) { //필수 입력 항목 확인 후 프로필 설정으로
          setSignUpSection(false);
          setProfileSection(true);
        }
        else {
          alert("양식에 맞게 입력해주세요.");
        }
      }
    
      const handleRegionChange = (newRegionID) => {
        setRegionID(newRegionID);
      }
    
      useEffect(()=>{
        if(regionID) {
          setIsRegionID(true);
        }
      },[regionID])
    
      const handleJobChange = (e) => {
        const currentJob = e.target.value;
        setJob(currentJob);
      }
    
      const handleBirthdateChange = (e) => {
        const currentBirth = e.target.value;
        setBirthdate(currentBirth);
      }
    
      const handleNextProfileSection = (e) => {
        e.preventDefault();
        if(isRegionID) { //필수 입력 항목(지역) 확인 후 다음 프로필 설정으로
          setNextProfileSection(true);
        }
        else {
          alert("거주 중인 지역을 선택해 주세요.");
        }
      }
    
      const handleSportTypeChange = (e) => {
        const currentSportType = e.target.value;
        setSportTypeID(currentSportType);
      }
    
      useEffect(()=>{
        if(sportTypeID) {
          setIsSportTypeID(true);
        }
      },[sportTypeID])
    
      const handleExperienceChange = (e) => {
        const currentEx = e.target.value;
        setExperience(currentEx);
      }
    
      const handleIntroductionChange = (e) => {
        const currentIntro = e.target.value;
        setIntroduction(currentIntro);
      }
    
      return(
        <>
          { signUpSection &&
            <div className="signUp">
            <form className="signUpForm">
              <label htmlFor="userName" className='signUpLabel' >이름</label>
              <input type="text" placeholder="ex) 김아주" id="userName" name='name' value={name}
              onChange={handleNameChange}/>
    
              <label htmlFor="userEmail" className='signUpLabel'>이메일</label>
              <input type="text" placeholder="ex) kimaj@ajou.ac.kr" id="userEmail" name='email' value={email}
              onChange={handleEmailChange}/>
              <button className='verifyEmail' onClick={handleEmailVerify}>이메일 중복 확인</button>
    
              <label htmlFor="userPassword" className='signUpLabel'>비밀번호</label>
              <input type="password" id="userPassword" value={password} name='password'
              onChange={handlePasswordChange}/>
              <div className='passwordGuide'>영문, 숫자, 특수문자를 조합하여 8~~16자리로 입력해주세요.</div>
    
              <button className="signUpButton" onClick={handleProfileSection}>회원가입</button>
              <div className="ifUser">CrewUp 계정이 있다면? <Link to={'/login'}>로그인</Link></div>
              </form>
            </div>
          }
          { profileSection &&
            <div className='profile'>
              <section className='profileLeft'>
                <div className="profileMessageText">
                  나만의 <br />
                  프로필을 <br />
                  완성해주세요
                  {imagePreview && (
                <div className="imagePreview">
                  <img src={imagePreview} alt="Preview" className="previewImage" />
                </div>
              )}
                </div>
              </section>
        
              <section className="profileRight">
                {
                  !nextProfileSection &&
                  <form className="profileForm">
                  <label htmlFor="userImage" className='userImageLabel'>프로필 이미지 </label>
                  <input
                    type="file"
                    id="userImage"
                    name="image"
                    accept="image/*"
                    onChange={handleImageChange}
                  />
        
                  <label htmlFor="userRegion" className='userRegionLabel'>사는 곳 </label>
                  <Region onRegionSelect={handleRegionChange}/>
        
                  <label htmlFor="userIdentity" className='userIdentityLabel'>현재 신분 </label>
                  <select name="identity" id="userIdentity" value={job} onChange={handleJobChange}>
                    <option value="">
                    신분 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;선택 ▼
                    </option>
                    <option value="student">대학생</option>
                    <option value="employee">직장인</option>
                  </select>
        
                  <label htmlFor="userBirthDay" className='userBirthDayLabel'>생년월일 </label>
                  <input
                    type="date"
                    id="userBirthDay"
                    name="birthDay"
                    value={birthdate} onChange={handleBirthdateChange}
                  />
        
                  <div className='setProfilePage'> 1/2 <button onClick={handleNextProfileSection}>다음 ▶</button></div>
                </form>
                }
                {
                  nextProfileSection &&
                  <form className="profileForm" onSubmit={handleSubmit}>
        
                    <label htmlFor="userSportType" className='userSportTypeLabel'>원하는 운동 종목 </label>
                    <select name="type" id="userSportType" value={sportTypeID} onChange={handleSportTypeChange}>
                      <option value="">
                        종목 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;선택 ▼
                      </option>
                      <option value="1">러닝</option>
                      <option value="3">클라이밍</option>
                      <option value="2">헬스</option>
                    </select>
                    
                    <label htmlFor="userSportExperience" className='userSportExperienceLabel'>나의 운동 경험(최대 50자) </label>
                    <input
                      type="textarea"
                      id="userSportExperience"
                      name="experience"
                      placeholder="입력하기"
                      value={experience} onChange={handleExperienceChange}
                    />
        
                    <label htmlFor="userBio" className='userBioLabel'>자기소개(최대 50자) </label>
                    <input
                      type="textarea"
                      id="userBio"
                      name="bio"
                      placeholder="입력하기"
                      value={introduction} onChange={handleIntroductionChange}
                    />
        
                    <div className='setProfilePage'> 2/2 <button onClick={()=>{setNextProfileSection(false)}}>◀ 이전</button> 
                    <button className='setProfileButton'>프로필 생성</button></div>
                  </form>
                }
              </section>
            </div>
          }
        </>
      );
    }
    
    export default SignUp;
    
    /*<button className='uploadImage' onClick={handleImageUpload}>이미지 등록하기</button>*/