Commit 87029678 authored by 한규민's avatar 한규민
Browse files

회원정보 수정

parent ea3c348e
......@@ -3073,14 +3073,6 @@
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.2.3.tgz",
"integrity": "sha512-pXnVMfJKSIWU2Ml4JHP7pZEPIrgBO1Fd3WGx+fPBsS+KRGhE4vxooD8XBGWbQOIVSZsVK7pUDBBkCicNu80yzQ=="
},
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"requires": {
"follow-redirects": "^1.10.0"
}
},
"axobject-query": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
......@@ -3873,11 +3865,6 @@
}
}
},
"buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
......@@ -4432,9 +4419,9 @@
}
},
"cookie": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
},
"cookie-signature": {
"version": "1.0.6",
......@@ -4938,11 +4925,6 @@
"whatwg-url": "^8.0.0"
}
},
"dayjs": {
"version": "1.10.6",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.6.tgz",
"integrity": "sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw=="
},
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
......@@ -5380,14 +5362,6 @@
"safer-buffer": "^2.1.0"
}
},
"ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
......@@ -6536,6 +6510,11 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"cookie": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
......@@ -9968,30 +9947,6 @@
"universalify": "^2.0.0"
}
},
"jsonwebtoken": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
"requires": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1",
"semver": "^5.6.0"
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
}
}
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
......@@ -10012,25 +9967,6 @@
"object.assign": "^4.1.2"
}
},
"jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"requires": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"requires": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"killable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
......@@ -10162,36 +10098,6 @@
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
},
"lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
},
"lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
},
"lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
},
"lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
},
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
},
"lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
......@@ -10202,11 +10108,6 @@
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
},
"lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
},
"lodash.template": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz",
......@@ -11521,11 +11422,6 @@
"ts-pnp": "^1.1.6"
}
},
"pop-iterate": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/pop-iterate/-/pop-iterate-1.0.1.tgz",
"integrity": "sha1-zqz9q0q/NT16DyqqLB/Hs/lBO6M="
},
"portfinder": {
"version": "1.0.28",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
......@@ -13758,11 +13654,6 @@
}
}
},
"rootpath": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/rootpath/-/rootpath-0.1.2.tgz",
"integrity": "sha1-Wzeah9ypBum5HWkKWZQ5vvJn6ms="
},
"rsvp": {
"version": "4.8.5",
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
......@@ -14004,11 +13895,6 @@
"ajv-keywords": "^3.5.2"
}
},
"scmp": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz",
"integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q=="
},
"scss-tokenizer": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
......@@ -15425,44 +15311,6 @@
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
},
"twilio": {
"version": "3.66.0",
"resolved": "https://registry.npmjs.org/twilio/-/twilio-3.66.0.tgz",
"integrity": "sha512-2jek7akXcRMusoR20EWA1+e5TQp9Ahosvo81wTUoeS7H24A1xbVQJV4LfSWQN4DLUY1oZ4d6tH2oCe/+ELcpNA==",
"requires": {
"axios": "^0.21.1",
"dayjs": "^1.8.29",
"https-proxy-agent": "^5.0.0",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.21",
"q": "2.0.x",
"qs": "^6.9.4",
"rootpath": "^0.1.2",
"scmp": "^2.1.0",
"url-parse": "^1.5.0",
"xmlbuilder": "^13.0.2"
},
"dependencies": {
"q": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/q/-/q-2.0.3.tgz",
"integrity": "sha1-dbjbAlWhpa+C9Yw/Oqoe/sfQ0TQ=",
"requires": {
"asap": "^2.0.0",
"pop-iterate": "^1.0.1",
"weak-map": "^1.0.5"
}
},
"qs": {
"version": "6.10.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz",
"integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
"requires": {
"side-channel": "^1.0.4"
}
}
}
},
"type": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
......@@ -16080,11 +15928,6 @@
"minimalistic-assert": "^1.0.0"
}
},
"weak-map": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.5.tgz",
"integrity": "sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes="
},
"web-vitals": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-1.1.2.tgz",
......@@ -17109,11 +16952,6 @@
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
"integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw=="
},
"xmlbuilder": {
"version": "13.0.2",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz",
"integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ=="
},
"xmlchars": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
......
......@@ -9,13 +9,13 @@
"@testing-library/user-event": "^12.1.10",
"bootstrap": "^5.0.2",
"bootstrap-icons": "^1.5.0",
"cookie": "^0.4.1",
"node-sass": "^6.0.1",
"query-string": "^7.0.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"twilio": "^3.66.0",
"web-vitals": "^1.0.1"
},
"scripts": {
......
......@@ -2,6 +2,13 @@ import axios from "axios";
import { baseUrl } from "../utils/baseUrl.js";
import config from "../utils/clientConfig.js";
const getUser = async () => {
const url = `${baseUrl}/api/auth/user`
const { data } = await axios.get(url)
return data
}
const login = async (login) => {
const payload = login;
const { data } = await axios.post(`${baseUrl}/api/auth/login`, payload);
......@@ -10,8 +17,8 @@ const login = async (login) => {
const logout = async () => {
alert("로그아웃되었습니다.");
localStorage.removeItem(config.loginUser);
await axios.get(`${baseUrl}/api/auth/logout`);
const { data } = await axios.get(`${baseUrl}/api/auth/logout`);
return data
};
const signup = async (user) => {
......@@ -25,30 +32,38 @@ const compareId = async (userId) => {
return data
}
const confirmMbnum = async (id,token) => {
const confirmMbnum = async (id, token) => {
const url = `${baseUrl}/api/auth/${id}/${token}`
const { data } = await axios.get(url)
return data
}
const getNickName = async (id) =>{
const getNickName = async (id) => {
const url = `${baseUrl}/api/auth/nickname/${id}`
const { data } = await axios.get(url)
return data
}
const comparePw = async (pw) => {
const url = `${baseUrl}/api/auth/pw/${pw}`
const { data } = await axios.get(url)
return data
}
const modifyUser = async (user) => {
const url = `${baseUrl}/api/auth/modify`
await axios.post(url, user)
}
const authApi = {
getUser,
login,
logout,
signup,
compareId,
confirmMbnum,
getNickName,
comparePw,
modifyUser,
};
export default authApi
\ No newline at end of file
......@@ -6,16 +6,20 @@ import catchErrors from "../../utils/catchErrors.js";
const MyInfo = () => {
const { user } = useAuth();
const [userNickName, setUserNickName] = useState(user.nickName);
const [userNickName, setUserNickName] = useState("사용자");
// 사용자 이름 가져오는 함수
const getNickName = async (id) => {
console.log(id);
const nickname = await authApi.getNickName(id);
console.log(nickname);
setUserNickName(nickname);
}
//현재 비밀번호 state
const [presentPw, setPresentPw] = useState("");
const [loading, setLoading] = useState(false);
const [style, setStyle] = useState("visually-hidden-focusable");
//변경할 데이터 입력받는 state
const [userRe, setUserRe] = useState({
userEmail: "",
userNickName: "",
......@@ -24,9 +28,6 @@ const MyInfo = () => {
userRePassword: ""
})
const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(false);
//각 타입별 error 유무 state
const [error, setError] = useState("");
const [errorMsg, setErrorMsg] = useState({
......@@ -41,6 +42,9 @@ const MyInfo = () => {
getNickName(user.id);
}, [])
const handlePwOnChange = (e) => {
setPresentPw(e.target.value)
}
//입력할때마다 state에 저장
const handleUserOnChange = (e) => {
......@@ -55,6 +59,32 @@ const MyInfo = () => {
})
}
}
const enterKey = (e) => {
if (e.key === "Enter") {
handleOnSummitVerify(e);
}
}
//기존 비밀번호 확인
const handleOnSummitVerify = async (e) => {
e.preventDefault();
try {
setError(() => (""));
setLoading(() => (true));
const pw = presentPw;
const confirmPw = await authApi.comparePw(pw);
if (confirmPw) {
setStyle("");
} else {
setStyle("visually-hidden-focusable");
alert("비밀번호가 일치하지 않습니다.");
}
} catch (error) {
catchErrors(error, setError);
} finally {
setLoading(false);
}
}
//비교하여 error메세지 반환
const vaildationData = (text, compareValue, error) => {
......@@ -73,73 +103,107 @@ const MyInfo = () => {
}
}
//유효성 검사
const validation = () => {
//별명 유효성 검사
const validation = async () => {
try {//별명 유효성 검사
vaildationData((userRe.userNickName.length === 0), false, "errorNickName");
// 휴대폰 유효성 검사
vaildationData(userRe.userMbnum.length, 11, "errorMbnum");
// 비밀번호 유효성 검사
vaildationIdPw(userRe.userPassword.length, 8, "errorPassword");
// 비밀번호 확인 유효성 검사
vaildationIdPw(userRe.userPassword.length, 8, "errorRePassword");
vaildationData(userRe.userPassword, userRe.userRePassword, "errorRePassword");
// 최종 유효성 검사
if ((Object.values(errorMsg).some((element) => (element)) === false)) {
return true
} else {
throw new Error("유효하지 않은 데이터입니다.");
}
} catch (error) {
catchErrors(error, setError);
}
if (success) {
alert("회원정보 수정이 완료되었습니다.")
}
const handleOnSummit = async (e) => {
e.preventDefault();
try {
setError(() => (""));
//처리가 될때까지 버튼(가입하기)이 안눌리게 지정
setLoading(() => (true));
console.log("userRe : " + userRe.userEmail);
//유효성 검사
validation();
const vaild = validation();
if (vaild) {
const userData = userRe;
console.log(userData);
//서버로 전송
await authApi.modifyUser(userData);
const process = await authApi.modifyUser(userData);
console.log("process : " + process);
alert("회원정보 수정 완료");
setSuccess(true);
}
} catch (error) {
//에러전송
catchErrors(error, setError);
} finally {
setLoading(false);
setLoading(() => (false));
}
}
return (<>
return (
<>
{/* 마이페이지 창 */}
<div className="d-flex flex-column">
<span className={styles.title}>마이페이지</span>
<div className="d-flex flex mh-100">
<img src="/images/cat.jpg" className="img-thumbnail rounded-circle" />
<div className="d-flex flex-column">
<div className="d-flex flex justify-content-center">
<img src="https://search.pstatic.net/sunny/?src=https%3A%2F%2Fi.pinimg.com%2Foriginals%2F1e%2F1c%2F2e%2F1e1c2e4e07f5c440c3adad38bcd6f854.jpg&type=a340"
className="img-fluid px-5 rounded-circle" />
{/* <button type="submit"></button> */}
<div className="d-flex flex-column py-4 justify-content-around">
<span className={`${styles.userName}`}>{`${userNickName}`} 반갑습니다!</span>
<button type="button" class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#exampleModal">회원정보 수정</button>
<button className={`rounded my-3 fs-5 ${styles.butterYellowAndBtn} ${styles.btnHover}`} data-bs-toggle="modal" href="#verifyPassword" >회원정보 수정</button>
</div>
</div>
</div>
{/* 기존 비밀번호 확인 모달창 */}
<div className="modal fade" id="verifyPassword" data-bs-backdrop="static" data-bs-keyboard="false" aria-hidden="true" aria-labelledby="verifyPasswordLabel" tabindex="-1">
<div className="modal-dialog modal-dialog-centered">
<form className="modal-content" onSubmit={handleOnSummitVerify}>
<div className="modal-header">
<h5 className="modal-title" id="verifyPasswordLabel">기존 비밀번호 확인</h5>
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div clasNames="modal-body">
<div className="d-flex flex-column ">
<div className="d-flex justify-content-around align-items-center my-4">
<label className={styles.signupLabel}>현재 비밀번호</label>
<input className={`${styles.input} ${styles.inputSize}`} type="password" name="userPassword" placeholder="8~11자리 사이" onChange={handlePwOnChange} onKeyPress={enterKey} maxLength="11" required />
</div>
{(style !== "visually-hidden-focusable") && <p className={styles.passwordConfirmError}>다음을 클릭해주세요.</p>}
</div>
</div>
<div className="modal-footer">
<button className={`${style} rounded my-3 fs-5 ${styles.butterYellowAndBtn} ${styles.btnHover}`} data-bs-target="#modify" data-bs-toggle="modal" data-bs-dismiss="modal" disable={style === "visually-hidden-focusable"}>다음</button>
<button type="submit" className={`rounded my-3 fs-5 ${styles.butterYellowAndBtn} ${styles.btnHover}`} disabled={loading}>확인</button>
</div>
</form>
</div>
</div>
{/* 회원정보 수정 모달창 */}
<div className="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div className="modal-dialog modal-dialog-scrollable">
<div className="modal-content">
<div class="modal-header">
<h5 className="modal-title" id="exampleModalLabel">회원정보 수정</h5>
<div className="modal fade" id="modify" data-bs-backdrop="static" data-bs-keyboard="false" aria-hidden="true" aria-labelledby="modifyLabel" tabindex="-1">
<div className="modal-dialog modal-dialog-centered">
<form className={`modal-content d-flex col-md-6 col-12 justify-content-center d-flex flex-column`} onSubmit={handleOnSummit}>
<div className="modal-header">
<h5 className="modal-title" id="modifyLabel">회원정보 수정</h5>
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form className={`d-flex col-md-6 col-12 justify-content-center d-flex flex-column`} onSubmit={handleOnSummit}>
<div className="modal-body">
<div className={`d-flex col-md-6 col-12 justify-content-center d-flex flex-column`}>
<div className={`modal-body`}>
<div className="d-flex flex-column">
<div className={styles.inputContent}>
<label className={styles.signupLabel}>이메일</label>
......@@ -159,25 +223,28 @@ const MyInfo = () => {
<div className={styles.inputContent}>
<label className={styles.signupLabel}>휴대폰 번호</label>
<div className="d-flex col-md-auto">
<input className={`${styles.input}`} type="number" name="userMbnum" placeholder="-없이 11자리 입력" onChange={handleUserOnChange} min="" max="99999999999" required />
<input className={`${styles.input} ${styles.inputSize}`} type="number" name="userMbnum" placeholder="-없이 11자리 입력" onChange={handleUserOnChange} min="" max="99999999999" required />
</div>
</div>
{errorMsg.errorMbnum && <p className={styles.passwordConfirmError}>-없이 숫자 11자리를 입력해주세요.</p>}
</div>
<div className="d-flex flex-column">
<div className={`${styles.inputContent}`}>
<label className={styles.signupLabel}>기존 비밀번호</label>
<div className={styles.inputContent}>
<label className={styles.signupLabel}> 비밀번호</label>
<input className={`${styles.input} ${styles.inputSize}`} type="password" name="userPassword" placeholder="8~11자리 사이" onChange={handleUserOnChange} maxLength="11" required />
</div>
{errorMsg.errorPassword && <p className={styles.passwordConfirmError}>8~11자리 사이로 입력해주세요.</p>}
</div>
<div className="d-flex flex-column">
<div className={styles.inputContent}>
<label className={styles.signupLabel}>변경 비밀번호</label>
<label className={styles.signupLabel}> 비밀번호 확인</label>
<input className={`${styles.input} ${styles.inputSize}`} type="password" name="userRePassword" placeholder="8~11자리 사이" onChange={handleUserOnChange} maxLength="11" required />
</div>
{errorMsg.errorRePassword && <p className={styles.passwordConfirmError}>비밀번호가 일치하지 않습니다.</p>}
</div>
</div>
......@@ -185,11 +252,9 @@ const MyInfo = () => {
<button type="button" className="btn btn-secondary rounded my-3 py-2 fs-5" data-bs-dismiss="modal" disabled={loading}>닫기</button>
<button type="submit" className={`rounded my-3 py-2 fs-5 ${styles.butterYellowAndBtn} ${styles.btnHover}`} disabled={loading}>수정하기</button>
</div>
</div>
</form>
</div>
</div>
</div>
</>
)
}
......
......@@ -2,15 +2,18 @@
display: flex;
justify-content: center;
color: #FEDC00;
font-size: 25px;
margin: 1rem 0;
font-size: 1.8rem;
margin: 2rem 0;
}
img{
width: 40%;
}
.userName{
color: white;
font-size: 1rem;
}
font-size: 1.3rem;
}
.contents{
display: flex;
......@@ -19,6 +22,7 @@
align-items: center;
padding-top: 5px;
}
.signupLabel{
color: black;
padding-right: 8px;
......@@ -27,9 +31,9 @@
.inputContent{
display: flex;
justify-content: space-between;
justify-content: space-around;
align-items: center;
margin-top: 1rem;
margin: 1rem 0;
}
.input {
margin: 0.5rem 0 0 0;
......@@ -78,3 +82,7 @@
font-size: 13px;
color: #FEDC00;
}
@media (max-width: 403px) {
}
\ No newline at end of file
import { useState } from "react";
import { useHistory } from "react-router";
import { Link, useHistory } from "react-router-dom";
import Search from "../Search";
const MainNav = () => {
......@@ -12,9 +13,9 @@ const MainNav = () => {
return (
<nav className="nav justify-content-evenly border border-start-0 border-end-0 border-white border-2 py-1">
<a className="nav-link text-white" href="/movielist">영화</a>
<a className="nav-link text-white" href="/ticket">빠른예매</a>
<a className="nav-link text-white" href="/theater">극장</a>
<Link className="nav-link text-white" to="/movielist">영화</Link>
<Link className="nav-link text-white" to="/ticket">빠른예매</Link>
<Link className="nav-link text-white" to="/theater">극장</Link>
<Search search={search} setSearch={setSearch} handleClick={searchMovie} />
</nav>
)
......
import { useEffect } from "react";
import { Link } from "react-router-dom";
import { useAuth } from "../../context/auth_context.js"
const SubNav = () => {
const { user, logout } = useAuth();
const { user, setUser, logout } = useAuth();
console.log("user : ", user);
return (
<> {(user) ?
<> {(user.role !== "user") ?
<nav className="nav justify-content-end py-1">
{(user.role === "member")
? <Link className="nav-link text-white" to="/mypage">마이페이지</Link>
......
import styles from "./signup.module.scss";
import { useState } from "react";
import authApi from "../../apis/auth.api.js";
import { Redirect } from "react-router";
import { Redirect } from "react-router-dom";
import catchErrors from "../../utils/catchErrors.js";
const Signup = () => {
......
import { createContext, useCallback, useContext, useState } from "react";
import { createContext, useCallback, useContext, useEffect, useState } from "react";
import authApi from "../apis/auth.api";
import { getLocalUser } from "../utils/auth";
import catchErrors from "../utils/catchErrors";
import config from "../utils/clientConfig";
const AuthContext = createContext({
error: "",
loading: false,
user: {id:0, nickName:"비회원", role:"user"},
user: {id:0, role:"user"},
setUser: () => { },
login: () => Promise.resolve(false),
logout: () => { },
......@@ -17,7 +16,17 @@ const AuthContext = createContext({
const AuthProvider = ({ children }) => {
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const [user, setUser] = useState(getLocalUser());
const [user, setUser] = useState({id:0, role:"user"});
const getUser = async() => {
const {id, role} = await authApi.getUser();
const user = {"id" : id, "role" : role};
setUser(user);
};
useEffect(() => {
getUser();
},[]);
const login = useCallback(async (id, password) => {
try {
......@@ -25,7 +34,6 @@ const AuthProvider = ({ children }) => {
setLoading(true);
const user = await authApi.login(id, password);
console.log("user : ", user);
localStorage.setItem(config.loginUser, JSON.stringify(user));
setUser(user);
return true;
} catch (error) {
......@@ -39,11 +47,10 @@ const AuthProvider = ({ children }) => {
const logout = useCallback(async () => {
try {
setError("");
setUser(null);
alert("로그아웃되었습니다.");
localStorage.removeItem(config.loginUser);
setLoading(true);
await authApi.logout();
const user = await authApi.logout();
setUser(user);
alert("로그아웃되었습니다.");
} catch (error) {
catchErrors(error, setError);
} finally {
......
......@@ -2,7 +2,7 @@ import MyInfo from "../components/MyInfo/MyInfo"
const MyPage = () => {
return (
<div className="d-flex justify-content-center py-5">
<div className="d-flex justify-content-center py-4">
<MyInfo/>
</div>
)
......
......@@ -2,12 +2,26 @@ import jwt from "jsonwebtoken";
import config from "../config/app.config.js";
import { User, Role } from '../db/index.js';
const getUser = async (req, res) => {
try {
if (req.cookies) {
const token = req.cookies.butterStudio;
const decoded = jwt.verify(token, config.jwtSecret);
res.json(decoded);
} else {
res.json({ id: 0, role: "user" });
}
} catch (error) {
console.error(error);
return res.status(500).send("유저를 가져오지 못했습니다.");
}
}
const login = async (req, res) => {
try {
const { id, password } = req.body;
//사용자 존재 확인
const user = await User.scope("withPassword").findOne({ where: { userId: id } });
console.log("user : ", user);
if (!user) {
return res.status(422).send(`사용자가 존재하지 않습니다`);
}
......@@ -16,16 +30,10 @@ const login = async (req, res) => {
if (passwordMatch) {
// 3) 비밀번호가 맞으면 토큰 생성
const userRole = await user.getRole();
// const userId = await user.getId();
console.log("userRole1111 : ", userRole);
// console.log("userId : ", userId);
const signData = {
id: user.id,
nickName: user.nickname,
role: userRole.name,
};
console.log("signData : ", signData);
const token = jwt.sign(signData, config.jwtSecret, {
expiresIn: config.jwtExpires,
});
......@@ -40,7 +48,6 @@ const login = async (req, res) => {
// 5) 사용자 반환
res.json({
id: user.id,
nickName: user.nickname,
role: userRole.name,
});
} else {
......@@ -56,8 +63,11 @@ const login = async (req, res) => {
const logout = async (req, res) => {
try {
console.log(req.cookies);
res.clearCookie(config.cookieName);
res.json({
id: 0,
role: "user",
})
res.send('successfully cookie cleared.')
} catch (error) {
console.error(error);
......@@ -66,6 +76,7 @@ const logout = async (req, res) => {
}
const compareId = async (req, res) => {
try {
const id = req.params.userId;
const userid = await User.findOne({ where: { userId: id } });
if (userid !== null) {
......@@ -73,6 +84,10 @@ const compareId = async (req, res) => {
} else {
return res.json(false);
}
} catch (error) {
console.error(error);
return res.status(500).send("아이디 중복 확인 에러");
}
}
const confirmMbnum = async (req, res) => {
......@@ -85,7 +100,7 @@ const confirmMbnum = async (req, res) => {
// .create({
// to: '+8201086074580',
// from: '+14159428621',
// body: '[ButterStudio] 인증번호[1234]를 입력해주세요',
// body: '[config.cookieName] 인증번호[1234]를 입력해주세요',
// })
// .then(message => console.log(message.sid))
// .catch(e => console.log(error));
......@@ -120,43 +135,63 @@ const signup = async (req, res) => {
};
const getNickName = async (req, res) => {
const id = req.params.id;
try {
const userNickName = await User.findOne({ where: { id: id }, attributes:["nickname"] });
res.json(userNickName.nickname)
const token = req.cookies.butterStudio;
const decoded = jwt.verify(token, config.jwtSecret);
if (decoded.role === "member") {
const user = await User.findOne({ where: { id: decoded.id }, attributes: ["nickname"] });
res.json(user.nickname);
} else {
res.status(401).send("잘못된 접근입니다.");
}
} catch (error) {
console.error("error : ",error.message);
res.status(500).send("회원가입 에러. 나중에 다시 시도 해주세요");
console.error("error : ", error.message);
res.status(500).send("잘못된 접근입니다.");
}
}
const comparePw = async (req, res) => {
try {
//쿠키 안 토큰에서 id추출
const token = req.cookies.butterStudio;
const decoded = jwt.verify(token, config.jwtSecret);
//해당 id의 행 추출
const user = await User.scope("withPassword").findOne({ where: { id: decoded.id } });
//입력한 비번과 해당 행 비번을 비교
const passwordMatch = await user.comparePassword(req.params.pw);
//클라이언트로 동일여부를 전송
if (passwordMatch) {
return res.json(true)
} else {
return res.json(false)
}
} catch (error) {
console.error("error : ", error.message);
res.status(500).send("인증 에러");
}
}
const modifyUser = async (req, res) => {
const { userEmail, userNickName, userMbnum, userPassword, userRePassword } = req.body;
// 휴대폰 중복 확인
try {
const token = req.cookies.butterStudio;
const decoded = jwt.verify(token, config.jwtSecret);
const { userEmail, userNickName, userMbnum, userPassword } = req.body;
const emailOverlap = await User.findOne({ where: { email: userEmail } });
console.log("emailOverlap : ",emailOverlap);
if (emailOverlap) {
return res.status(422).send(`이미 있는 이메일입니다.`);
}else{
const user = await User.findOne({ where: { password: userPassword } });
console.log("user", user);
user.email = userEmail;
user.nickname = userNickName;
user.phoneNumber = userMbnum;
user.password = userRePassword;
await user.save({ fields: ['email'] });
await user.reload();
}
res.clearCookie(config.cookieName);
res.cookie(config.cookieName, token, {
maxAge: config.cookieMaxAge,
path: "/",
httpOnly: config.env === "production",
secure: config.env === "production",
} else {
if (decoded) {
let user = await User.findOne({ where: { id: decoded.id } });
await user.update({
email : userEmail,
nickname : userNickName,
phoneNumber : userMbnum,
password : userPassword,
});
res.send('successfully cookie cleared.')
res.json(user);
}
}
} catch (error) {
console.error(error.message);
res.status(500).send("수정 에러. 나중에 다시 시도 해주세요");
......@@ -164,11 +199,13 @@ const modifyUser = async (req, res) => {
};
export default {
getUser,
login,
logout,
compareId,
confirmMbnum,
signup,
getNickName,
comparePw,
modifyUser
}
......@@ -20,7 +20,7 @@ sequelize
const adminRole = await Role.findOne({ where: { name: "admin" } });
console.log("adminRole : ", adminRole);
// if (!adminRole) {
if (!adminRole) {
await User.create({
userId: "admin",
email: "han35799@naver.com",
......@@ -30,7 +30,7 @@ sequelize
password: "admin!",
roleId: adminRole?.id,
});
// }else{}
}else{}
app.listen(appConfig.port, () => {
console.log(`Server is running on port ${appConfig.port}`);
......
......@@ -3,6 +3,10 @@ import userCtrl from "../controllers/user.controller.js";
const router = express.Router();
router
.route("/user")
.get(userCtrl.getUser)
router
.route("/login")
.post(userCtrl.login)
......@@ -20,11 +24,14 @@ router
.route("/modify")
.post(userCtrl.modifyUser)
router
.route("/nickname/:id")
.get(userCtrl.getNickName)
router
.route("/pw/:pw")
.get(userCtrl.comparePw)
router
.route("/:userId")
.get(userCtrl.compareId)
......
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