Web 개발

[React] 해커톤 웹 프로젝트 - 4

javadocq 2024. 8. 11. 14:18
728x90

이번에는 회원가입과 마이페이지에 대해 알아보자.

 

회원 가입은 다른 사이트랑 특별히 다르지는 않으나 axios를 통해 백엔드로 입력되어진 정보를 보내는 게 처음이기도 했고

 

같은 창을 유지하면서 다른 정보를 받는다는 게 생각외로 골치가 아팠다.

 

또 로그인 창 같은 경우에는 네이버, 구글, 카카오 로그인을 추가해서 좀 더 여러 경로로 로그인이 가능하게 기획을 하였는데 

 

아무래도 api를 끌어오는 데 많은 오류가 생겨서 네이버 로그인 하나만 추가하게 되었다.

 

<Login.jsx>

 

import styles from "../styles/Login.module.css";
import Logo from "../assets/logo.png";
import { Link, useNavigate } from "react-router-dom"; // useNavigate로 변경
import naverLogin from '../assets/naverLogin.png';
import { useState } from "react";
import axios from 'axios';

const BASE_URL = "http://3.39.26.152:8000";

export default function Login() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const navigate = useNavigate(); // useNavigate 훅 사용

const handleLogin = async () => {
if (email && password) {
try {
const response = await axios.post(`${BASE_URL}/api/login`, {
email,
password
});
// 로그인 성공 시 페이지 이동
navigate('/'); // 성공적으로 로그인한 후 메인 페이지로 이동
} catch (error) {
console.error("Error during login:", error);
}
}
};

return (
<div className={styles.LoginWrapper}>
<div className={styles.LoginContainer}>
<div className={styles.logo}>
<Link to="/">
<img src={Logo} alt="Logo" className={styles.headerLogo} />
</Link>
</div>

<div className={styles.loginBoxContainerWrap}>
<div className={styles.loginBoxContainer}>
<div className={styles.loginBox}>
<div className={styles.loginTitle}>이메일 주소</div>
<input
placeholder=""
className={styles.loginEnterBox}
onChange={(event) => setEmail(event.target.value)}
/>
</div>
<div className={styles.loginBox}>
<div className={styles.loginTitle}>비밀번호</div>
<input
type={"password"}
className={styles.loginEnterBox}
onChange={(event) => setPassword(event.target.value)}
/>
</div>
</div>
</div>
<div style={{ width: "100%", marginLeft: "23%" }}>
<button
className={styles.loginFinishClick}
onClick={handleLogin} // 수정된 부분
>
로그인
</button>
</div>

<p style={{ marginTop: '-5%' }}>SNS로 간편하게 회원가입하기</p>
<img style={{ marginTop: '-7%', width: '30%', height: '9%' }} src={naverLogin} />
<div style={{ width: '100%', alignItems: 'center', justifyContent: 'center', display: 'flex', marginTop: '-4%', gap: '1%' }}>
<p style={{ color: "rgba(0, 0, 0, 0.40)", fontSize: '16px', fontStyle: 'normal', fontWeight: '500', lineHeight: '16px' }}>아직 회원이 아니라면?</p>
<Link to='/signup' style={{ fontStyle: 'none' }}>
<p>회원가입하기</p>
</Link>
</div>
</div>
</div>
);
}

 

 

 

<SignUp.jsx>

import { useState } from "react";
import useInput from "../utils/useInput";
import Logo from "../assets/logo.png";
import { Link, useNavigate } from "react-router-dom";
import agreement from '../assets/agreement.svg';
import agreementBlack from '../assets/agreementBlack.svg';
import styles from "../styles/SignUp.module.css"; // css를 모듈화해서 여기에만 적용되게 하기! 사용법은 className={styles.클래스이름}
import axios from 'axios'; // axios 추가

const BASE_URL = "http://3.39.26.152:8000";

const SignUp = () => {
const navigate = useNavigate();


const [clickAgreement, setClickAgreement] = useState(0);
const [subscribed, setSubscribed] = useState(false);
const [currentIndex, setCurrentIndex] = useState(0); // index에 따라 화면 다르게 보여주기
const [showPassword, setShowPassword] = useState(false);

// 입력값 상태 관리
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [name, setName] = useState("");
const [phone, setPhone] = useState("");
const [username, setUsername] = useState("");

const togglePasswordVisibility = () => {
setShowPassword(!showPassword);
};

const handleSignup = async () => {
if (email && password && name && phone && username) {
try {
const response = await axios.post(`${BASE_URL}/api/users`, {
email,
password,
name,
phone,
username,
subscribed: clickAgreement === 1 // 동의 여부
});
// 회원가입 성공 시 페이지 이동
navigate('/login'); // 성공적으로 가입한 후 메인 페이지로 이동
} catch (error) {
console.error("Error during signup:", error);
}
}
};

return (
<div className={styles.pageWrapper}>
<div className={styles.signupContainer}>
<div className={styles.header}>
<div className={styles.logo}>
<Link to="/">
<img src={Logo} alt="Logo" />
</Link>
</div>
<div className={styles.mainTitle}>
<div>회원정보 입력하기</div>
</div>
</div>

<div className={styles.inputBoxContainerWrap}>
<div className={styles.inputBoxContainer}>
{currentIndex === 0 && (
<>
<div className={styles.inputBox}>
<div className={styles.inputTitle}>이메일 주소</div>
<input
placeholder=""
value={email}
onChange={(e) => setEmail(e.target.value)}
className={styles.inputEnterBox}
/>
</div>
<div className={styles.inputBox}>
<div className={styles.inputTitle}>비밀번호</div>
<input
type={showPassword ? "text" : "password"}
placeholder="8자 이상"
value={password}
onChange={(e) => setPassword(e.target.value)}
className={styles.inputEnterBox}
/>
<div className={styles.eyeIcon} onClick={togglePasswordVisibility}></div>
</div>
<div className={styles.inputBox}>
<div className={styles.inputTitle}>비밀번호 확인</div>
<input
type={showPassword ? "text" : "password"}
placeholder="8자 이상"
className={styles.inputEnterBox}
/>
</div>
</>
)}
{currentIndex === 1 && (
<>
<div className={styles.inputBox}>
<div className={styles.inputTitle}>사용자 이름</div>
<input
placeholder=""
value={name}
onChange={(e) => setName(e.target.value)}
className={styles.inputEnterBox}
/>
</div>
<div className={styles.inputBox}>
<div className={styles.inputTitle}>휴대폰 번호</div>
<input
placeholder="000-0000-0000"
value={phone}
onChange={(e) => setPhone(e.target.value)}
className={styles.inputEnterBox}
/>
</div>
<div className={styles.inputBox}>
<div className={styles.inputTitle}>닉네임</div>
<input
placeholder=""
value={username}
onChange={(e) => setUsername(e.target.value)}
className={styles.inputEnterBox}
/>
</div>
<div className={styles.signupAgreement}>
<button className={styles.signupAgreementButton} onClick={() => setClickAgreement(1)}>
{clickAgreement === 0 ?
<img src={agreement} alt="" className={styles.signupAgreementImg}/> :
<img src={agreementBlack} alt="" className={styles.signupAgreementImg}/>}
</button>
<div>
<p className={styles.signupAgreementFirstP}>메일 및 문자 수신에 동의합니다.</p>
<p className={styles.signupAgreementSecondP}>광고 및 마케팅 정보 제공에 동의하시겠습니까?</p>
</div>
</div>
</>
)}

<div className={styles.footer}>
{currentIndex === 0 && (
<>
<button
className={styles.signupLeftButton}
onClick={() => {/* 이전 버튼 클릭 시 동작 */}}
>
이전
</button>
<button
className={styles.signupRightButton}
onClick={() => setCurrentIndex(1)}
>
다음
</button>
</>
)}
{currentIndex === 1 && (
<div style={{ width: "100%", marginLeft: "23%" }}>
<button
className={styles.finishClick}
onClick={handleSignup}
>
완료
</button>
</div>
)}
</div>
</div>
</div>
</div>
</div>
);
};

export default SignUp;

 

 

최신 버전과 css도 확인하고 싶다면 다음의 github 주소에서 확인 가능합니다.

 

https://github.com/Hackathon-Phorest

 

Hackathon-Phorest

Hackathon-Phorest has one repository available. Follow their code on GitHub.

github.com