Select Git revision
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="">
신분 선택 ▼
</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="">
종목 선택 ▼
</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>*/