diff --git a/src/assets/css/Auth/Auth.scss b/src/assets/css/Auth/Auth.scss index df26d13..8dd711e 100644 --- a/src/assets/css/Auth/Auth.scss +++ b/src/assets/css/Auth/Auth.scss @@ -2,7 +2,7 @@ .auth--wrapper { @include medium_kor; - min-height: 450px; + min-height: 300px; @include desktop { @include basic--wrappers; } @@ -11,15 +11,6 @@ } } -.auth--hello { - @include medium_kor; - text-align: center; -} - -.signup { - margin-bottom: 100px; -} - .auth--profile { text-align: center; margin-top: 30px; @@ -38,18 +29,59 @@ } } -.auth--guide { - @include medium_kor; +.auth--signup_form { text-align: center; margin-top: 50px; } -.auth--mode_change { - @include medium_kor; +.authForm { + position: relative; + margin: 0 auto; + margin-top: 50px; + @include desktop { + width: 300px; + } + @include mobile { + width: 80%; + } text-align: center; - color: #1e4df5 !important; +} + +.authForm--input { + height: 24px; + border: none; + border-bottom: 1px solid $darkgrey_default; + font-size: $default_small_13; + text-align: center; + &:focus { + outline: none; + } + @include desktop { + width: 240px; + margin-left: 10px; + } + @include mobile { + width: 75%; + } +} + +.authForm--button { + padding: 0; + border: none; + color: $darkgrey_default; + background-color: lavender; + padding: 5px; + border-radius: 10px; + margin-top: 10px;; &:hover { cursor: pointer; transform: scale(1.1); } } + +.authForm--error_message { + @include medium_kor; + color: $pinkred; + display: flex; + align-items: center; +} \ No newline at end of file diff --git a/src/cert/AuthStorage.ts b/src/cert/AuthStorage.ts index 626e709..edb1e4d 100644 --- a/src/cert/AuthStorage.ts +++ b/src/cert/AuthStorage.ts @@ -1,8 +1,28 @@ const AUTH = 'auth'; -export function saveAuth(token: { id: string; url: string }) { - localStorage.setItem(AUTH, JSON.stringify(token)); +export function saveAuth(token: string) { + const decoded = decodeToken(token); + let userData: { id: string; url: string }; + userData = { id: decoded.username, url: decoded.imageUrl }; + localStorage.setItem(AUTH, JSON.stringify(userData)); } export function getAuth(): { id: string; url: string } { return JSON.parse(localStorage.getItem(AUTH)); } + +export function removeAuth() { + localStorage.removeItem(AUTH); +} + +const decodeToken = (token: string) => { + const base64Url = token.split('.')[1]; + const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); + const jsonPayload = decodeURIComponent( + atob(base64) + .split('') + .map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)) + .join(''), + ); + + return JSON.parse(jsonPayload); +}; diff --git a/src/components/Auth/AuthCallback.tsx b/src/components/Auth/AuthCallback.tsx index b553965..47adde1 100644 --- a/src/components/Auth/AuthCallback.tsx +++ b/src/components/Auth/AuthCallback.tsx @@ -2,16 +2,28 @@ import React, { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; import { saveToken } from '@cert/TokenStorage'; import { useNavigate } from 'react-router-dom'; +import { saveAuth, getAuth } from '@cert/AuthStorage'; +import GlobalLoginState from '@recoil/GlobalLoginState'; +import { useSetRecoilState } from 'recoil'; const AuthCallback = () => { const location = useLocation(); const searchParams = new URLSearchParams(location.search); const token = searchParams.get('token'); const navigate = useNavigate(); + const setLoginState = useSetRecoilState(GlobalLoginState); useEffect(() => { - console.log('LoginSucess', token); saveToken(token); + saveAuth(token); + setLoginState(() => { + return { + id: getAuth().id, + isLogin: true, + isAdmin: false, + profileUrl: getAuth().url, + }; + }); navigate('/'); }, []); diff --git a/src/components/Auth/AuthSignUp.tsx b/src/components/Auth/AuthSignUp.tsx index dd2a618..3bff2b8 100644 --- a/src/components/Auth/AuthSignUp.tsx +++ b/src/components/Auth/AuthSignUp.tsx @@ -1,24 +1,30 @@ -import React from 'react'; +import React, { useState } from 'react'; import '@css/Auth/Auth.scss'; import { useNavigate } from 'react-router'; import { useSetRecoilState, useRecoilValue } from 'recoil'; import errorAlert from '@globalObj/function/errorAlert'; import apiClient from '@service/apiClient'; import { saveToken } from '@cert/TokenStorage'; +import { saveAuth } from '@cert/AuthStorage'; import ProfileChangeModalShow from '@recoil/ProfileChangeModalShow'; import SignUpProfileState from '@recoil/SignUpProfileState'; import ProfileModal from '@auth/ProfileModal'; +import GlobalLoginState from '@recoil/GlobalLoginState'; const AuthSignUp = () => { const navigate = useNavigate(); const setOpenProfileModal = useSetRecoilState(ProfileChangeModalShow); const openProfileModal = useRecoilValue(ProfileChangeModalShow); const profileImage = useRecoilValue(SignUpProfileState); + const setLoginState = useSetRecoilState(GlobalLoginState); + const [nicknameError, setNicknameError] = useState(false); const handleSubmit = (e: any) => { e.preventDefault(); - console.log('submit', e.target[0].value); - console.log('submit', e.target[1].value); + if (!e.target[0].value) { + setNicknameError(true); + return; + } apiClient .post('/auth/signup', { nickname: e.target[0].value, @@ -28,6 +34,15 @@ const AuthSignUp = () => { .then((res) => { console.log('success', res.data); saveToken(res.data.access_token); + saveAuth(res.data.access_token); + setLoginState(() => { + return { + id: res.data.id, + isLogin: true, + isAdmin: false, + profileUrl: res.data.url, + }; + }); navigate('/'); }) .catch((err) => { @@ -40,20 +55,23 @@ const AuthSignUp = () => { }; return ( -
-
+ <> +
profile

프로필 변경

{openProfileModal && } +
+ + {nicknameError &&

닉네임을 입력해주세요.

} +
+ +
+ +
-
- - - -
-
+ ); }; diff --git a/src/components/Auth/PasswordForm.tsx b/src/components/Auth/PasswordForm.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/src/components/utils/Navbar.tsx b/src/components/utils/Navbar.tsx index e0dfa37..e262f93 100644 --- a/src/components/utils/Navbar.tsx +++ b/src/components/utils/Navbar.tsx @@ -4,6 +4,7 @@ import { useNavigate } from 'react-router-dom'; import { useSetRecoilState } from 'recoil'; import GlobalLoginState from '@recoil/GlobalLoginState'; import { clearToken, getToken } from '@cert/TokenStorage'; +import { removeAuth } from '@cert/AuthStorage'; import { Dropdown } from './Dropdown'; import getAddress from '@globalObj/function/getAddress'; import apiClient from '@service/apiClient'; @@ -14,36 +15,25 @@ function Navbar() { const url = `${getAddress()}/auth/google`; const onClickLogOut = () => { - // apiClient - // .post('/auth/logout') - // .then((res) => { - // console.log('logout', res); - // clearToken(); - // setLoginState(() => { - // return { - // id: '', - // isLogin: false, - // isAdmin: false, - // profileUrl: '', - // }; - // }); - // alert('로그아웃 되셨습니다!'); - // navigate('/'); - // }) - // .catch((err) => { - // console.log('logout error', err); - // }); - clearToken(); - setLoginState(() => { - return { - id: '', - isLogin: false, - isAdmin: false, - profileUrl: '', - }; - }); - alert('로그아웃 되셨습니다!'); - navigate('/'); + apiClient + .post('/auth/logout') + .then((res) => { + removeAuth(); + clearToken(); + setLoginState(() => { + return { + id: '', + isLogin: false, + isAdmin: false, + profileUrl: '', + }; + }); + alert('로그아웃 되셨습니다!'); + navigate('/'); + }) + .catch((err) => { + alert('로그아웃에 실패했습니다.'); + }); }; const onClickAuthTimeline = () => {