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>*/