diff --git a/utils/accessToken.js b/utils/accessToken.js new file mode 100644 index 000000000..bc0290906 --- /dev/null +++ b/utils/accessToken.js @@ -0,0 +1,9 @@ +const getAccessToken = () => { + return localStorage.getItem("accessToken"); +}; + +const setAccessToken = (accessToken) => { + localStorage.setItem("accessToken", accessToken); +}; + +export { getAccessToken, setAccessToken }; diff --git a/utils/apiClient.js b/utils/apiClient.js new file mode 100644 index 000000000..858d7171b --- /dev/null +++ b/utils/apiClient.js @@ -0,0 +1,19 @@ +import { BASE_URL } from "./constants.js"; + +export const fetchClient = async ({ url, method, body }) => { + try { + const response = await fetch(`${BASE_URL}/${url}`, { + method, + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body), + }); + + if (response.status !== 200) { + throw new Error(response.status); + } + } catch (error) { + throw error; + } +}; diff --git a/utils/authorize.js b/utils/authorize.js new file mode 100644 index 000000000..22d79148d --- /dev/null +++ b/utils/authorize.js @@ -0,0 +1,131 @@ +import { + USERS, + EMAIL_PATTERN, + PASSWORD_PATTERN, + FOLDER_PAGE_PATH, +} from "/utils/constants.js"; + +import { fetchClient } from "./apiClient.js"; + +import { getAccessToken, setAccessToken } from "./accessToken.js"; + +function goToFolderPage() { + location.href = FOLDER_PAGE_PATH; +} + +function getIsFilledEmail(email) { + if (email !== "") { + return true; + } else { + return false; + } +} + +function getIsValidEmail(email) { + if (EMAIL_PATTERN.test(email)) { + return true; + } else { + return false; + } +} + +function getIsFilledPassword(password) { + if (password !== "") { + return true; + } else { + return false; + } +} + +function getIsValidPassword(password) { + if (PASSWORD_PATTERN.test(password)) { + return true; + } else { + return false; + } +} + +function getIsCorrectPassword(password) { + if (password === USERS[0].password) { + return true; + } else { + return false; + } +} + +function getIsFilledConfirmPassword(confirmPassword) { + if (confirmPassword !== "") { + return true; + } else { + return false; + } +} + +function getIsConfirmedConfirmPassword( + confirmPassword, + passwordInputElementValue +) { + if (confirmPassword === passwordInputElementValue) { + return true; + } else { + return false; + } +} + +const redirectIfSignedIn = () => { + if (getAccessToken()) { + goToFolderPage(); + } +}; + +const signIn = async (email, password) => { + const response = await fetchClient({ + url: "sign-in", + method: "POST", + body: { email, password }, + }); + const result = await response.json(); + const accessToken = result.data.accessToken; + setAccessToken(accessToken); + redirectIfSignedIn(); +}; + +const getIsNewEmail = async (email) => { + try { + await fetchClient({ + url: "check-email", + method: "POST", + body: { email }, + }); + return true; + } catch { + return false; + } +}; + +const signUp = async (email, password) => { + const response = await fetchClient({ + url: "sign-up", + method: "POST", + body: { email, password }, + }); + const result = await response.json(); + const accessToken = result.data.accessToken; + setAccessToken(accessToken); + redirectIfSignedIn(); +}; + +export { + goToFolderPage, + getIsFilledEmail, + getIsValidEmail, + getIsFilledPassword, + getIsValidPassword, + getIsCorrectPassword, + getIsFilledConfirmPassword, + getIsConfirmedConfirmPassword, + signIn, + getIsNewEmail, + signUp, + redirectIfSignedIn, +}; diff --git a/utils/auth.js b/utils/constants.js similarity index 76% rename from utils/auth.js rename to utils/constants.js index 889aafe04..22ee1ae44 100644 --- a/utils/auth.js +++ b/utils/constants.js @@ -1,5 +1,4 @@ -/* 비밀번호 토글 */ -// 상수 +// 로그인, 회원가입 폼 비밀번호 토글 const PASSWORD_TOGGLE_CONSTANT = { visible: { inputType: "text", @@ -13,18 +12,7 @@ const PASSWORD_TOGGLE_CONSTANT = { }, }; -// DOM 요소 -const passwordToggleElement = document.querySelector(".auth__toggle-password"); - -// 함수 -function getPasswordVisibility(inputType) { - return inputType === "password" - ? PASSWORD_TOGGLE_CONSTANT.visible - : PASSWORD_TOGGLE_CONSTANT.invisible; -} - -/* 유효성 검사 */ -// 상수 +// 로그인, 회원가입 const USERS = [ { email: "test@codeit.com", @@ -43,7 +31,7 @@ const AUTH_HINT = { password: { default: "", isNotFilled: "비밀번호를 입력해주세요.", - isNotExists: "비밀번호를 변경해주세요.", + isNotCorrect: "비밀번호를 변경해주세요.", isNotValidated: "비밀번호는 영문, 숫자 조합 8자 이상 입력해 주세요.", isNotConfirmed: "비밀번호가 일치하지 않아요.", }, @@ -51,6 +39,8 @@ const AUTH_HINT = { const EMAIL_PATTERN = /^[a-zA-Z0-9+-\_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/; +const PASSWORD_PATTERN = /^(?=.*[A-Za-z])(?=.*\d).{8,}$/; + const INPUT_STATUS = { default: "default", isNotFilled: "isNotFilled", @@ -58,19 +48,23 @@ const INPUT_STATUS = { isExists: "isExists", isNotExists: "isNotExists", isNotConfirmed: "isNotConfirmed", + isNotCorrect: "isNotCorrect", }; const INPUT_HINT_CLASSNAME = "auth__input--hint"; const FOLDER_PAGE_PATH = "/pages/forder.html"; +const BASE_URL = "https://bootcamp-api.codeit.kr/api"; + export { - passwordToggleElement, - getPasswordVisibility, + PASSWORD_TOGGLE_CONSTANT, USERS, AUTH_HINT, EMAIL_PATTERN, + PASSWORD_PATTERN, INPUT_STATUS, INPUT_HINT_CLASSNAME, FOLDER_PAGE_PATH, + BASE_URL, }; diff --git a/utils/getPasswordVisibility.js b/utils/getPasswordVisibility.js new file mode 100644 index 000000000..483fb025d --- /dev/null +++ b/utils/getPasswordVisibility.js @@ -0,0 +1,9 @@ +import { PASSWORD_TOGGLE_CONSTANT } from "/utils/constants.js"; + +function getPasswordVisibility(inputType) { + return inputType === "password" + ? PASSWORD_TOGGLE_CONSTANT.visible + : PASSWORD_TOGGLE_CONSTANT.invisible; +} + +export { getPasswordVisibility }; diff --git a/utils/signin.js b/utils/signin.js index c3e3d3e53..49142516e 100644 --- a/utils/signin.js +++ b/utils/signin.js @@ -1,16 +1,31 @@ import { - passwordToggleElement, - getPasswordVisibility, - USERS, + goToFolderPage, + getIsFilledEmail, + getIsValidEmail, + getIsFilledPassword, + signIn, +} from "/utils/authorize.js"; + +import { AUTH_HINT, - EMAIL_PATTERN, INPUT_STATUS, INPUT_HINT_CLASSNAME, - FOLDER_PAGE_PATH, -} from "/utils/auth.js"; +} from "/utils/constants.js"; + +import { getAccessToken } from "/utils/accessToken.js"; + +import { getPasswordVisibility } from "./getPasswordVisibility.js"; + +/* 로그인 상태로 접근 시 리다이렉트 */ +(function () { + if (getAccessToken()) { + goToFolderPage(); + } +})(); /* 비밀번호 토글 */ -// 이벤트 핸들러 +const passwordToggleElement = document.querySelector(".auth__toggle-password"); + passwordToggleElement.addEventListener("click", () => { const passwordInput = document.querySelector(".auth__input-password"); const passwordIcon = document.querySelector(".auth__icon-password"); @@ -23,14 +38,12 @@ passwordToggleElement.addEventListener("click", () => { }); /* 유효성 검사 */ -// DOM 요소 const emailInputElement = document.querySelector(".auth__input-email"); const passwordInputElement = document.querySelector(".auth__input-password"); const emailHintElement = document.querySelector(".auth__email-hint"); const passwordHintElement = document.querySelector(".auth__password-hint"); const signinButtonElement = document.querySelector(".signin__button"); -// 함수 function changeEmailHint(hintType) { if (emailHintElement.innerText === AUTH_HINT.email[hintType]) return; // 이전 상태와 바꾸려는 상태가 동일할 경우 리턴 emailHintElement.innerText = AUTH_HINT.email[hintType]; @@ -53,11 +66,10 @@ function changePasswordHint(hintType) { } } -// 함수 function checkEmailFocusout(email) { - if (email === "") { + if (!getIsFilledEmail(email)) { changeEmailHint(INPUT_STATUS.isNotFilled); - } else if (!EMAIL_PATTERN.test(email)) { + } else if (!getIsValidEmail(email)) { changeEmailHint(INPUT_STATUS.isNotValidated); } else { changeEmailHint(INPUT_STATUS.default); @@ -72,47 +84,33 @@ function checkPasswordFocusout(password) { } } -function getIsUserEmail(email) { - if (email === "") { +function getIsCompleteEmail(email) { + if (!getIsFilledEmail(email)) { changeEmailHint(INPUT_STATUS.isNotFilled); return false; - } else if (!EMAIL_PATTERN.test(email)) { + } else if (!getIsValidEmail(email)) { changeEmailHint(INPUT_STATUS.isNotValidated); return false; - } else if (email !== USERS[0].email) { - changeEmailHint(INPUT_STATUS.isNotExists); - return false; } else { changeEmailHint(INPUT_STATUS.default); return true; } } -function getIsUserPassword(password) { - if (password === "") { +function getIsCompletePassword(password) { + if (!getIsFilledPassword(password)) { changePasswordHint(INPUT_STATUS.isNotFilled); return false; - } else if (password !== USERS[0].password) { - changePasswordHint(INPUT_STATUS.isNotExists); - return false; } else { changePasswordHint(INPUT_STATUS.default); return true; } } - -function signinSuccess() { - location.href = FOLDER_PAGE_PATH; -} - function clickSignin(email, password) { - const isUserEmail = getIsUserEmail(email); - if (!isUserEmail) return checkPasswordFocusout(password); // TODO 유저 이메일이 아닌경우 비밀번호 입력 여부만 검사하고 리턴 - const isUserPassword = getIsUserPassword(password); - if (isUserEmail && isUserPassword) signinSuccess(); + if (getIsCompleteEmail(email) && getIsCompletePassword(password)) + signIn(email, password); } -// 이벤트 핸들러 등록 emailInputElement.addEventListener("focusout", (e) => { checkEmailFocusout(e.target.value); }); diff --git a/utils/signup.js b/utils/signup.js index e60b41482..f705c0db9 100644 --- a/utils/signup.js +++ b/utils/signup.js @@ -1,27 +1,38 @@ import { - passwordToggleElement, - getPasswordVisibility, - USERS, + getIsFilledEmail, + getIsValidEmail, + getIsFilledPassword, + getIsValidPassword, + getIsFilledConfirmPassword, + getIsConfirmedConfirmPassword, + signUp, + getIsNewEmail, + redirectIfSignedIn, +} from "/utils/authorize.js"; + +import { AUTH_HINT, - EMAIL_PATTERN, INPUT_STATUS, INPUT_HINT_CLASSNAME, - FOLDER_PAGE_PATH, -} from "/utils/auth.js"; +} from "/utils/constants.js"; + +import { getPasswordVisibility } from "./getPasswordVisibility.js"; + +/* 로그인 상태로 접근 시 리다이렉트 */ +redirectIfSignedIn(); /* 비밀번호 토글 */ -// DOM 요소 -const passwordConfirmToggleElement = document.querySelector( +const confirmPasswordToggleElement = document.querySelector( ".auth__toggle-password--confirm" ); -const passwordConfirmInputElement = document.querySelector( +const confirmPasswordInputElement = document.querySelector( ".auth__input-password--confirm" ); -const passwordConfirmIconElement = document.querySelector( +const confirmPasswordIconElement = document.querySelector( ".auth__icon-password--confirm" ); +const passwordToggleElement = document.querySelector(".auth__toggle-password"); -// 핸들러 passwordToggleElement.addEventListener("click", () => { const passwordInput = document.querySelector(".auth__input-password"); const passwordIcon = document.querySelector(".auth__icon-password"); @@ -33,31 +44,26 @@ passwordToggleElement.addEventListener("click", () => { passwordIcon.alt = passwordVisibility.imageAlt; }); -passwordConfirmToggleElement.addEventListener("click", () => { +confirmPasswordToggleElement.addEventListener("click", () => { const passwordVisibility = getPasswordVisibility( - passwordConfirmInputElement.type + confirmPasswordInputElement.type ); - passwordConfirmInputElement.type = passwordVisibility.inputType; - passwordConfirmIconElement.src = passwordVisibility.imageSrc; - passwordConfirmIconElement.alt = passwordVisibility.imageAlt; + confirmPasswordInputElement.type = passwordVisibility.inputType; + confirmPasswordIconElement.src = passwordVisibility.imageSrc; + confirmPasswordIconElement.alt = passwordVisibility.imageAlt; }); /* 유효성 검사 */ -// 상수 -const PASSWORD_PATTERN = /^(?=.*[A-Za-z])(?=.*\d).{8,}$/; - -// DOM 요소 const emailInputElement = document.querySelector(".auth__input-email"); const passwordInputElement = document.querySelector(".auth__input-password"); const emailHintElement = document.querySelector(".auth__email-hint"); const passwordHintElement = document.querySelector(".auth__password-hint"); -const passwordConfirmHintElement = document.querySelector( +const confirmPasswordHintElement = document.querySelector( ".auth__password-hint--confirm" ); const signupButtonElement = document.querySelector(".signup__button"); -// 함수 function changeEmailHint(hintType) { if (emailHintElement.innerText === AUTH_HINT.email[hintType]) return; // 이전 상태와 바꾸려는 상태가 동일할 경우 리턴 emailHintElement.innerText = AUTH_HINT.email[hintType]; @@ -81,70 +87,86 @@ function changePasswordHint(hintType) { } function changePasswordConfirmHint(hintType) { - if (passwordConfirmHintElement.innerText === AUTH_HINT.password[hintType]) + if (confirmPasswordHintElement.innerText === AUTH_HINT.password[hintType]) return; // 이전 상태와 바꾸려는 상태가 동일할 경우 리턴 - passwordConfirmHintElement.innerText = AUTH_HINT.password[hintType]; + confirmPasswordHintElement.innerText = AUTH_HINT.password[hintType]; if (hintType === INPUT_STATUS.default) { - passwordConfirmInputElement.classList.remove(INPUT_HINT_CLASSNAME); + confirmPasswordInputElement.classList.remove(INPUT_HINT_CLASSNAME); } else { - passwordConfirmInputElement.classList.add(INPUT_HINT_CLASSNAME); + confirmPasswordInputElement.classList.add(INPUT_HINT_CLASSNAME); } } -function checkEmailFocusout(email) { - if (email === "") { + +async function checkEmailFocusout(email) { + if (!getIsFilledEmail(email)) { changeEmailHint(INPUT_STATUS.isNotFilled); - } else if (!EMAIL_PATTERN.test(email)) { + return; + } + + if (!getIsValidEmail(email)) { changeEmailHint(INPUT_STATUS.isNotValidated); - } else if (email === USERS[0].email) { + return; + } + + const isNewEmail = await getIsNewEmail(email); + if (!isNewEmail) { changeEmailHint(INPUT_STATUS.isExists); - } else { - changeEmailHint(INPUT_STATUS.default); + return; } + + changeEmailHint(INPUT_STATUS.default); } function checkPasswordFocusout(password) { - if (password === "") { + if (!getIsFilledPassword(password)) { changePasswordHint(INPUT_STATUS.isNotFilled); - } else if (!PASSWORD_PATTERN.test(password)) { + } else if (!getIsValidPassword(password)) { changePasswordHint(INPUT_STATUS.isNotValidated); } else { changePasswordHint(INPUT_STATUS.default); } } -function checkPasswordConfirmFocusout(passwordConfirm) { - console.log(passwordConfirm, passwordInputElement.value); - if (passwordConfirm === "") { +function checkPasswordConfirmFocusout(confirmPassword) { + if (!getIsFilledConfirmPassword(confirmPassword)) { changePasswordConfirmHint(INPUT_STATUS.isNotFilled); - } else if (passwordConfirm !== passwordInputElement.value) { + } else if ( + !getIsConfirmedConfirmPassword(confirmPassword, passwordInputElement.value) + ) { changePasswordConfirmHint(INPUT_STATUS.isNotConfirmed); } else { changePasswordConfirmHint(INPUT_STATUS.default); } } -function getIsValidatedEmail(email) { - if (email === "") { +async function getIsCompleteEmail(email) { + if (!getIsFilledEmail(email)) { changeEmailHint(INPUT_STATUS.isNotFilled); return false; - } else if (!EMAIL_PATTERN.test(email)) { + } + + if (!getIsValidEmail(email)) { changeEmailHint(INPUT_STATUS.isNotValidated); return false; - } else if (email === USERS[0].email) { + } + + const isNewEmail = await getIsNewEmail(email); + + if (!isNewEmail) { changeEmailHint(INPUT_STATUS.isExists); return false; - } else { - changeEmailHint(INPUT_STATUS.default); - return true; } + + changeEmailHint(INPUT_STATUS.default); + return true; } -function getIsValidatedPassword(password) { - if (password === "") { +function getIsCompletePassword(password) { + if (!getIsFilledPassword(password)) { changePasswordHint(INPUT_STATUS.isNotFilled); return false; - } else if (!PASSWORD_PATTERN.test(password)) { + } else if (!getIsValidPassword(password)) { changePasswordHint(INPUT_STATUS.isNotValidated); return false; } else { @@ -153,12 +175,13 @@ function getIsValidatedPassword(password) { } } -function getIsConfirmedPassword(passwordConfirm) { - console.log(passwordConfirm, passwordInputElement.value); - if (passwordConfirm === "") { +function getIsConfirmedPassword(confirmPassword) { + if (!getIsFilledConfirmPassword(confirmPassword)) { changePasswordConfirmHint(INPUT_STATUS.isNotFilled); return false; - } else if (passwordConfirm !== passwordInputElement.value) { + } else if ( + !getIsConfirmedConfirmPassword(confirmPassword, passwordInputElement.value) + ) { changePasswordConfirmHint(INPUT_STATUS.isNotConfirmed); return false; } else { @@ -166,17 +189,13 @@ function getIsConfirmedPassword(passwordConfirm) { } } -function signupSuccess() { - location.href = FOLDER_PAGE_PATH; -} - -function clickSignup(email, password, passwordConfirm) { - const isValidatedEmail = getIsValidatedEmail(email); - const isValidatedPassword = getIsValidatedPassword(password); - const isConfirmedPassword = getIsConfirmedPassword(passwordConfirm); - - if (isValidatedEmail && isValidatedPassword && isConfirmedPassword) - signupSuccess(); +function clickSignup({ email, password, confirmPassword }) { + if ( + getIsCompleteEmail(email) && + getIsCompletePassword(password) && + getIsConfirmedPassword(confirmPassword) + ) + signUp(email, password); } emailInputElement.addEventListener("focusout", (e) => { @@ -187,23 +206,15 @@ passwordInputElement.addEventListener("focusout", (e) => { checkPasswordFocusout(e.target.value); }); -passwordConfirmInputElement.addEventListener("focusout", (e) => { +confirmPasswordInputElement.addEventListener("focusout", (e) => { checkPasswordConfirmFocusout(e.target.value); }); -emailInputElement.addEventListener("focusout", (e) => { - checkEmailFocusout(e.target.value); -}); - -passwordInputElement.addEventListener("focusout", (e) => { - checkPasswordFocusout(e.target.value); -}); - signupButtonElement.addEventListener("click", (e) => { e.preventDefault(); - clickSignup( - emailInputElement.value, - passwordInputElement.value, - passwordConfirmInputElement.value - ); + clickSignup({ + email: emailInputElement.value, + password: passwordInputElement.value, + confirmPassword: confirmPasswordInputElement.value, + }); });