Commit 598bf2fc authored by 한규민's avatar 한규민
Browse files

서버연결성공

parent ae3326aa
......@@ -2,8 +2,8 @@ import axios from "axios";
import { baseUrl } from "../utils/baseUrl.js";
import config from "../utils/clientConfig.js";
const login = async (id, password) => {
const payload = { id, password };
const login = async (login) => {
const payload = login;
const { data } = await axios.post(`${baseUrl}/api/auth/login`, payload);
return data
};
......
import { useState } from "react";
import styles from "./login.module.scss";
import { useState } from "react";
import authApi from "../../apis/auth.api.js";
import { Redirect } from "react-router";
import catchErrors from "../../utils/catchErrors";
const Login = () => {
//useState를 이용해서 각 state 생성 및 초기값 저장
......@@ -9,9 +12,11 @@ const Login = () => {
id:'',
password:''
});
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(false);
const [guestText, setGusetText] = useState({
const [guest, setGuset] = useState({
guestName:'',
gusetBirthday:'',
gusetMbnum:'',
......@@ -28,15 +33,54 @@ const Login = () => {
};
const handleGuestOnChange = (e) =>{
setGusetText({ ...guestText,
setGuset({ ...guest,
[e.target.name]:e.target.value
})
}
const handleOnSummitUser = async(e) => {
e.preventDefault();
try{
console.log("하하")
setError("");
setLoading(true);
const userData = login;
await authApi.login(userData);
alert('로그인이 완료되었습니다.')
setSuccess(true);
}catch(error){
catchErrors(error, setError);
}finally{
setLoading(false);
}
}
const handleOnSummitGuest = async(e) => {
e.preventDefault();
try{
setError("");
setLoading(true);
const gusetData = guest;
await authApi.post(gusetData);
alert('로그인이 완료되었습니다.')
setSuccess(true);
}catch(error){
catchErrors(error, setError);
}finally{
setLoading(false);
}
}
if (success) {
return <Redirect to="/" />;
}
return (
<div className={`d-flex flex-column col-md-5 col-10`}>
{/* nav-tabs */}
{/* {console.log(login)} */}
{console.log(success)}
<ul className="nav nav-fill nav-tabs w-100" id="loginTab" role="tablist">
<li className="nav-item fs-6" role="presentation">
<button className={`nav-link active px-2 ${styles.fontSize}`} style={{ color: state ? "black" : "#FEDC00", backgroundColor: state ? "#FEDC00" : "black"}}
......@@ -53,27 +97,27 @@ const Login = () => {
<div className="tab-content w-100" id="myTabContent">
{/* 로그인 */}
<div className="tab-pane fade show active" id="login" role="tabpanel" aria-labelledby="login-tab">
<div className="d-flex flex-column ">
<input className={styles.input} type="text" name="id" placeholder="ID" onChange={handleLoginOnChange}/>
<input className={styles.input} type="text" name="password" placeholder="Password" onChange={handleLoginOnChange} minlength="8" required />
<input className={`rounded-2 mt-2 ${styles.butterYellowAndBtn} ${styles.btnHover}`} type="submit" value="Login" />
<form className="d-flex flex-column" onSubmit={handleOnSummitUser}>
<input className={styles.input} type="text" name="id" placeholder="ID" onChange={handleLoginOnChange} maxLength="10" required/>
<input className={styles.input} type="password" name="password" placeholder="Password" onChange={handleLoginOnChange} maxLength="8" required />
<input className={`rounded-2 mt-2 ${styles.butterYellowAndBtn} ${styles.btnHover}`} type="submit" value="Login" disabled={loading} />
<span><a href="./signup" className={styles.intoSignupPage}>회원이 아니십니까?</a></span>
</div>
</form>
</div>
{/* 비회원예매 학인 */}
<div className="tab-pane fade" id="guest" role="tabpanel" aria-labelledby="guest-tab">
<div className="d-flex flex-column">
<input className={styles.input} type="text" name="guestName" id="guestName" placeholder="이름" onChange={handleGuestOnChange} minlength="8" required />
<input className={styles.input} type="number" name="gusetBirthday" id="gusetBirthday" placeholder="생년월일" onChange={handleGuestOnChange} minlength="8" required />
<input className={styles.input} type="number" name="gusetMbnum" id="gusetMbnum" placeholder="휴대폰 번호" onChange={handleGuestOnChange} minlength="8" required />
<input className={styles.input} type="text" name="guestPassword" id="password" placeholder="비밀번호" onChange={handleGuestOnChange} minlength="8" required />
<form className="d-flex flex-column" onSubmit={handleOnSummitGuest}>
<input className={styles.input} type="text" name="guestName" id="guestName" placeholder="이름" onChange={handleGuestOnChange} maxLength="5" required />
<input className={styles.input} type="number" name="gusetBirthday" id="gusetBirthday" placeholder="생년월일" onChange={handleGuestOnChange} maxLength="6" required />
<input className={styles.input} type="number" name="gusetMbnum" id="gusetMbnum" placeholder="휴대폰 번호" onChange={handleGuestOnChange} maxLength="11" required />
<input className={styles.input} type="password" name="guestPassword" id="password" placeholder="비밀번호" onChange={handleGuestOnChange} maxLength="8" required />
<p className={`text-white ${styles.fontSizeTwo}`}>
비회원 정보 입력 예매 내역 확인/취소 티켓 발권이 어려울 있으니 다시 한번 확인해 주시기 바랍니다.
</p>
<input className={`rounded-2 mt-2 ${styles.butterYellowAndBtn} ${styles.btnHover}`} type="submit" value="비회원 예매 확인" />
</div>
<input className={`rounded-2 mt-2 ${styles.butterYellowAndBtn} ${styles.btnHover}`} type="submit" value="비회원 예매 확인" disabled={loading}/>
</form>
</div>
</div>
</div>
......
......@@ -14,6 +14,14 @@
border-radius: 3px;
}
input[type=password]{
font-family: 'Courier New', Courier, monospace;
}
input::placeholder{
font-family: 'HangeulNuriB'
}
.fontSize{
font-size: 16px;
}
......
import styles from "./signup.module.scss";
import { useState, useEffect } from 'react';
import { useState } from 'react';
import authApi from "../../apis/auth.api.js";
import { Redirect } from "react-router";
import catchErrors from "../../utils/catchErrors.js";
const Signup = () => {
const [user, setUser] = useState({
userId: '',
userName: '',
userBirthday: '',
userMbnum: '',
userPassword: '',
userRePassword: ''
userId: "",
userNickName: "",
userBirthday: "",
userMbnum: "",
userPassword: "",
userRePassword: ""
})
const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(false);
//각 타입별 error 유무 state
const [error,setError] = useState("");
const [errorMsg, setErrorMsg] = useState({
errorId: null,
errorName: false,
errorNickName: false,
errorBirthday: false,
errorMbnum: false,
errorPassword: false,
......@@ -41,13 +41,13 @@ const Signup = () => {
//id(중복확인 체크, 형식 에러)
const handleOnClickId = async (e) => {
e.preventDefault();
const existId = await authApi.compareId(user.userId)
// const existId = await authApi.compareId(user.userId)
if (user.userId.length < 5) {
setErrorMsg(errorMsg => ({
...errorMsg,
[e.target.name]: true
}));
if (existId === true) {
if (overlapId === true) {
setOverlapId(() => (false));
};
} else {
......@@ -106,7 +106,7 @@ const Signup = () => {
}
//별명 유효성 검사
vaildationData((user.userName.length === 0), false, "errorName");
vaildationData((user.userNickName.length === 0), false, "errorNickName");
// 생일 유효성 검사
vaildationData(user.userBirthday.length, 6, "errorBirthday");
// 휴대폰 유효성 검사
......@@ -118,9 +118,7 @@ const Signup = () => {
// 최종 유효성 검사
if (overlapId && (Object.values(errorMsg).some((element) => (element)) === false)) {
console.log(";sadasda")
}else{
console.log("에러발생")
throw new Error("유효하지 않은 데이터입니다.");
}
}
......@@ -152,9 +150,9 @@ const Signup = () => {
<div className="d-flex flex-column">
<div className={styles.inputContent}>
<label className={styles.signupLabel}>별명</label>
<input className={`${styles.input} ${styles.inputSize}`} type="text" name="userName" id="userName" placeholder="10자리 이내" onChange={handleUserOnChange} maxLength="10" required />
<input className={`${styles.input} ${styles.inputSize}`} type="text" name="userNickName" id="userNickName" placeholder="10자리 이내" onChange={handleUserOnChange} maxLength="10" required />
</div>
{errorMsg.errorName && <p className={styles.passwordConfirmError}>10 이내로 입력해주세요.</p>}
{errorMsg.errorNickName && <p className={styles.passwordConfirmError}>10 이내로 입력해주세요.</p>}
</div>
<div className="d-flex flex-column">
......
const config = {
env: process.env.NODE_ENV === 'production' ? 'production' : 'development',
port: process.env.PORT || 3001,
// jwtSecret: 'dfkasf23i$efksdfks!',
jwtSecret: 'dfkasf23i$efksdfks!',
jwtExpires: '7d',
cookieName: 'butterStudio',
cookieMaxAge: 60 * 60 * 24 * 7 * 1000,
......
import axios from 'axios'
import sequelize from 'sequelize'
import jwt from "jsonwebtoken";
import config from "../config/app.config.js";
import { User } from '../db/index.js'
const login = async(req, res) => {
try {
console.log(req.body);
const { id, password } = req.body;
//사용자 존재 확인
const user = await User.scope("withPassword").findOne({ where: { userId: id } });
if (!user) {
return res.status(422).send(`사용자가 존재하지 않습니다`);
}
// 2) 비밀번호 확인은 데이터베이스 프로토타입 메소드에서 처리
const passwordMatch = await user.comparePassword(password);
if (passwordMatch) {
// 3) 비밀번호가 맞으면 토큰 생성
// const userRole = await user.getRole();
const signData = {
userId: user.id,
// role: userRole.name,
};
const token = jwt.sign(signData, config.jwtSecret, {
expiresIn: config.jwtExpires,
});
// 4) 토큰을 쿠키에 저장
res.cookie(config.cookieName, token, {
maxAge: config.cookieMaxAge,
path: "/",
httpOnly: config.env === "production",
secure: config.env === "production",
});
// 5) 사용자 반환
res.json({
userId: user.id,
isLoggedIn: true,
// role: userRole.name,
// isMember: user.isMember,
});
} else {
// 6) 비밀번호 불일치
res.status(401).send("비밀번호가 일치하지 않습니다");
}
} catch (error) {
console.error(error);
return res.status(500).send("로그인 에러");
}
}
const compareId = async (req, res) => {
const id = req.params.userId;
const userid = await User.findAll({where:{userId: id}});
......@@ -12,6 +61,35 @@ const compareId = async (req, res) => {
}
}
const signup = async (req, res) => {
const { userId, userNickName, userBirthday, userPassword } = req.body;
// 휴대폰 중복 확인
const userMbnum = String(req.body.userMbnum);
console.log(userMbnum);
console.log(typeof userMbnum);
try {
const mbnum = await User.findOne({ where: { phoneNumber: userMbnum } });
if (mbnum) {
return res.status(422).send(`이미 있는 휴대폰번호입니다.`);
}
const newUser = await User.create({
userId: userId,
nickname: userNickName,
birth: userBirthday,
phoneNumber: userMbnum,
password: userPassword
});
console.log("signup new user=", newUser);
res.json(newUser);
} catch (error) {
console.error(error.message);
res.status(500).send("회원가입 에러. 나중에 다시 시도 해주세요");
}
};
export default {
compareId
login,
compareId,
signup
}
......@@ -16,17 +16,17 @@ const UserModel = (sequelize) => {
userId: {
type: DataTypes.STRING,
},
password: {
type: DataTypes.STRING,
},
nickname: {
type: DataTypes.STRING,
},
birth: {
type: DataTypes.INTEGER,
type: DataTypes.STRING,
},
phoneNumber: {
type: DataTypes.INTEGER
type: DataTypes.STRING
},
password: {
type: DataTypes.STRING,
},
// role: {
// type: DataTypes.ENUM({
......@@ -37,17 +37,37 @@ const UserModel = (sequelize) => {
{
timestamps: true,
freezeTableName: true,
tableName: "users"
// defaultScope: {
// attributes: { exclude: ["password"] },
// },
// scopes: {
// withPassword: {
// attributes: { include: ["password"] },
// },
// },
tableName: "users",
defaultScope: {
attributes: { exclude: ["password"] },
},
scopes: {
withPassword: {
attributes: { include: ["password"] },
},
},
}
);
User.beforeSave(async (user) => {
if (!user.changed("password")) {
return;
}
if (user.password) {
const hashedPassword = await bcrypt.hash(user.password, 10);
user.password = hashedPassword;
}
});
User.prototype.comparePassword = async function (plainPassword) {
const passwordMatch = await bcrypt.compare(
plainPassword,
this.password
);
return passwordMatch;
};
return User
};
......
......@@ -4,9 +4,13 @@ import userCtrl from "../controllers/user.controller.js";
const router = express.Router();
router
.route("/")
.post()
.get()
.route("/login")
.post(userCtrl.login)
router
.route("/signup")
.post(userCtrl.signup)
router
.route("/:userId")
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment