From 64bb31d2f0680ea609be0f39082b42551841e631 Mon Sep 17 00:00:00 2001 From: Seongcheol Jo Date: Mon, 25 Jul 2022 23:38:27 +0900 Subject: [PATCH 1/7] add: kakao login(wip) --- packages/santa_close_frame/package.json | 6 ++- packages/santa_close_frame/src/App.tsx | 65 ++++++++++++++++++++----- yarn.lock | 55 +++++++++++++++++++++ 3 files changed, 113 insertions(+), 13 deletions(-) diff --git a/packages/santa_close_frame/package.json b/packages/santa_close_frame/package.json index fb7740b..80b463f 100644 --- a/packages/santa_close_frame/package.json +++ b/packages/santa_close_frame/package.json @@ -17,11 +17,15 @@ "react": "^18.1.0", "react-dom": "^18.1.0", "recoil": "^0.7.2", - "@karrotframe/navigator": "^0.24.2" + "@karrotframe/navigator": "^0.24.2", + "urql": "^2.2.3", + "graphql": "^16.5.0", + "react-router-dom": "^6.3.0" }, "devDependencies": { "@types/react": "^18.0.8", "@types/react-dom": "^18.0.3", + "@types/kakao-js-sdk": "^1.39.1", "@babel/core": "^7.17.10", "@babel/preset-react": "^7.16.7", "@babel/preset-env": "^7.17.10", diff --git a/packages/santa_close_frame/src/App.tsx b/packages/santa_close_frame/src/App.tsx index 76ef352..7aeb3b5 100644 --- a/packages/santa_close_frame/src/App.tsx +++ b/packages/santa_close_frame/src/App.tsx @@ -1,17 +1,57 @@ -import React, {ChangeEvent} from 'react' -import {Navigator, Screen} from '@karrotframe/navigator' +import React, {ChangeEvent, useEffect} from 'react' import {RecoilRoot, useRecoilState} from 'recoil' import {sampleState} from 'map_app/atoms' import {UrqlProvider} from 'santa_close_common' +import {BrowserRouter, Routes, Route} from 'react-router-dom' const MapApp = React.lazy(() => import('map_app/MapApp')) -const Page1 = () => { - return

Here is PAGE1

-} +const Login = () => { + const handleKaKaoLoginClick = () => { + Kakao.Auth.login({ + success(authObj) { + console.log(authObj) + }, + fail(err) { + console.log(err) + }, + }) + } + + useEffect(() => { + const initKakaoScript = async () => { + const scriptInitResult = new Promise((resolve, reject) => { + const script = document.createElement('script') + script.src = 'https://developers.kakao.com/sdk/js/kakao.js' + script.defer = true + document.head.appendChild(script) + + script.addEventListener('load', () => { + resolve({isLoaded: true, isError: false}) + }) + + script.addEventListener('error', () => { + // eslint-disable-next-line prefer-promise-reject-errors + reject({isLoaded: false, isError: true}) + }) + }) + + await scriptInitResult -const Page2 = () => { - return

Here is PAGE2

+ Kakao.init('1a01c6b9fba660692d7388f0f7c5baaf') + console.log(Kakao.isInitialized()) + } + + initKakaoScript() + }, []) + + return ( +
+ +
+ ) } const MapAppContainer = () => { @@ -46,11 +86,12 @@ const App = () => { return ( - - - - - + + + } /> + } /> + + ) diff --git a/yarn.lock b/yarn.lock index fdef5ba..e72469c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1093,6 +1093,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.7.6": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a" + integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.0.0", "@babel/template@^7.16.7", "@babel/template@^7.3.3": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" @@ -3723,6 +3730,11 @@ dependencies: "@types/node" "*" +"@types/kakao-js-sdk@^1.39.1": + version "1.39.1" + resolved "https://registry.yarnpkg.com/@types/kakao-js-sdk/-/kakao-js-sdk-1.39.1.tgz#329773d673acc3dadd4ff9e4ba2d0a3f170b764b" + integrity sha512-kB0nXS97K7zFgIhLi7oDi1zeR7WV6zRNvRwtJ3KxICz8VWcuqnFYwMq1eBzyhOIJsBTCFRhB4tR1IPHKp7qcKw== + "@types/mime@^1": version "1.3.2" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" @@ -4073,6 +4085,14 @@ "@graphql-typed-document-node/core" "^3.1.1" wonka "^4.0.14" +"@urql/core@^2.6.1": + version "2.6.1" + resolved "https://registry.yarnpkg.com/@urql/core/-/core-2.6.1.tgz#c10ee972c5e81df6d7bf1e778ef1b5d30e2906e5" + integrity sha512-gYrEHy3tViJhwIhauK6MIf2Qp09QTsgNHZRd0n71rS+hF6gdwjspf1oKljl4m25+272cJF7fPjBUGmjaiEr7Kg== + dependencies: + "@graphql-typed-document-node/core" "^3.1.1" + wonka "^4.0.14" + "@vanilla-extract/dynamic@^2.0.0": version "2.0.2" resolved "https://registry.yarnpkg.com/@vanilla-extract/dynamic/-/dynamic-2.0.2.tgz#13a3e461964c8029a52e6b6b631009ca6a8b27f5" @@ -8198,6 +8218,11 @@ graphql@^16.4.0: resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.4.0.tgz#bb10b1b4683045dedcb67000eb4ad134a36c59e6" integrity sha512-tYDNcRvKCcfHREZYje3v33NSrSD/ZpbWWdPtBtUUuXx9NCo/2QDxYzNqCnMvfsrnbwRpEHMovVrPu/ERoLrIRg== +graphql@^16.5.0: + version "16.5.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.5.0.tgz#41b5c1182eaac7f3d47164fb247f61e4dfb69c85" + integrity sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA== + growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -8369,6 +8394,13 @@ history@^4.7.8, history@^4.9.0: tiny-warning "^1.0.0" value-equal "^1.0.1" +history@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b" + integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ== + dependencies: + "@babel/runtime" "^7.7.6" + hoist-non-react-statics@^3.1.0: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -12924,6 +12956,14 @@ react-router-dom@^5.3.0: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" +react-router-dom@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.3.0.tgz#a0216da813454e521905b5fa55e0e5176123f43d" + integrity sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw== + dependencies: + history "^5.2.0" + react-router "6.3.0" + react-router@5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.3.1.tgz#b13e84a016c79b9e80dde123ca4112c4f117e3cf" @@ -12940,6 +12980,13 @@ react-router@5.3.1: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" +react-router@6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557" + integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ== + dependencies: + history "^5.2.0" + react-shallow-renderer@^16.13.1: version "16.15.0" resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz#48fb2cf9b23d23cde96708fe5273a7d3446f4457" @@ -15146,6 +15193,14 @@ urql@^2.2.0: "@urql/core" "^2.4.3" wonka "^4.0.14" +urql@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/urql/-/urql-2.2.3.tgz#84c6ad962d771235106f24de56b5dc6bd85a2c3a" + integrity sha512-XMkSYJKW9s4ZlbSuxcUz3fTBIykOn0sGileRXQeyZpaRBXJPVz5saSY05k7jdefNxShZtTI+/nr7PYUWQertfg== + dependencies: + "@urql/core" "^2.6.1" + wonka "^4.0.14" + use-subscription@^1.0.0: version "1.7.0" resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.7.0.tgz#c7505263315deac9fd2581cdf4ab1e3ff2585d0f" From 74117e86f65ae3a6952da3fd93e8eb2f0b515227 Mon Sep 17 00:00:00 2001 From: Seongcheol Jo Date: Tue, 26 Jul 2022 00:38:38 +0900 Subject: [PATCH 2/7] =?UTF-8?q?add:=20kakao=20login(wip)=20-=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=84=B0=EB=A7=81=20=ED=95=84=EC=9A=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/santa_close_frame/package.json | 1 + packages/santa_close_frame/src/App.tsx | 32 +++++++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/packages/santa_close_frame/package.json b/packages/santa_close_frame/package.json index 80b463f..0706499 100644 --- a/packages/santa_close_frame/package.json +++ b/packages/santa_close_frame/package.json @@ -20,6 +20,7 @@ "@karrotframe/navigator": "^0.24.2", "urql": "^2.2.3", "graphql": "^16.5.0", + "graphql-tag": "^2.12.6", "react-router-dom": "^6.3.0" }, "devDependencies": { diff --git a/packages/santa_close_frame/src/App.tsx b/packages/santa_close_frame/src/App.tsx index 7aeb3b5..ab85754 100644 --- a/packages/santa_close_frame/src/App.tsx +++ b/packages/santa_close_frame/src/App.tsx @@ -1,19 +1,43 @@ import React, {ChangeEvent, useEffect} from 'react' import {RecoilRoot, useRecoilState} from 'recoil' import {sampleState} from 'map_app/atoms' -import {UrqlProvider} from 'santa_close_common' +import {UrqlProvider, urqlClient} from 'santa_close_common' import {BrowserRouter, Routes, Route} from 'react-router-dom' +import gql from 'graphql-tag' const MapApp = React.lazy(() => import('map_app/MapApp')) const Login = () => { const handleKaKaoLoginClick = () => { Kakao.Auth.login({ - success(authObj) { - console.log(authObj) + success({access_token}) { + const foo = async () => { + const result = await urqlClient + .mutation( + gql` + mutation SignIn($input: SignInAppInput!) { + signIn(input: $input) { + accessToken + expiredAt + } + } + `, + { + input: { + code: access_token, + type: 'KAKAO', + }, + }, + ) + .toPromise() + + localStorage.setItem('token', JSON.stringify(result.data.signIn)) + } + + foo() }, fail(err) { - console.log(err) + console.log('err', err) }, }) } From ab1ae898a124acd4081f96fc58c7ae3587ef957f Mon Sep 17 00:00:00 2001 From: Seongcheol Jo Date: Tue, 26 Jul 2022 22:22:44 +0900 Subject: [PATCH 3/7] =?UTF-8?q?update:=20kakao=20login(wip)=20-=20?= =?UTF-8?q?=ED=9B=85=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/santa_close_frame/src/App.tsx | 77 +--------------- packages/santa_close_frame/src/Login.tsx | 108 +++++++++++++++++++++++ 2 files changed, 111 insertions(+), 74 deletions(-) create mode 100644 packages/santa_close_frame/src/Login.tsx diff --git a/packages/santa_close_frame/src/App.tsx b/packages/santa_close_frame/src/App.tsx index ab85754..e6721ea 100644 --- a/packages/santa_close_frame/src/App.tsx +++ b/packages/santa_close_frame/src/App.tsx @@ -1,83 +1,12 @@ -import React, {ChangeEvent, useEffect} from 'react' +import React, {ChangeEvent} from 'react' import {RecoilRoot, useRecoilState} from 'recoil' import {sampleState} from 'map_app/atoms' -import {UrqlProvider, urqlClient} from 'santa_close_common' +import {UrqlProvider} from 'santa_close_common' import {BrowserRouter, Routes, Route} from 'react-router-dom' -import gql from 'graphql-tag' +import Login from './Login' const MapApp = React.lazy(() => import('map_app/MapApp')) -const Login = () => { - const handleKaKaoLoginClick = () => { - Kakao.Auth.login({ - success({access_token}) { - const foo = async () => { - const result = await urqlClient - .mutation( - gql` - mutation SignIn($input: SignInAppInput!) { - signIn(input: $input) { - accessToken - expiredAt - } - } - `, - { - input: { - code: access_token, - type: 'KAKAO', - }, - }, - ) - .toPromise() - - localStorage.setItem('token', JSON.stringify(result.data.signIn)) - } - - foo() - }, - fail(err) { - console.log('err', err) - }, - }) - } - - useEffect(() => { - const initKakaoScript = async () => { - const scriptInitResult = new Promise((resolve, reject) => { - const script = document.createElement('script') - script.src = 'https://developers.kakao.com/sdk/js/kakao.js' - script.defer = true - document.head.appendChild(script) - - script.addEventListener('load', () => { - resolve({isLoaded: true, isError: false}) - }) - - script.addEventListener('error', () => { - // eslint-disable-next-line prefer-promise-reject-errors - reject({isLoaded: false, isError: true}) - }) - }) - - await scriptInitResult - - Kakao.init('1a01c6b9fba660692d7388f0f7c5baaf') - console.log(Kakao.isInitialized()) - } - - initKakaoScript() - }, []) - - return ( -
- -
- ) -} - const MapAppContainer = () => { const [state, setState] = useRecoilState(sampleState) diff --git a/packages/santa_close_frame/src/Login.tsx b/packages/santa_close_frame/src/Login.tsx new file mode 100644 index 0000000..a90dba6 --- /dev/null +++ b/packages/santa_close_frame/src/Login.tsx @@ -0,0 +1,108 @@ +import {useEffect, useState} from 'react' +import {urqlClient} from 'santa_close_common' +import {gql} from 'urql' + +const SignInDocumnet = gql` + mutation SignIn($input: SignInAppInput!) { + signIn(input: $input) { + accessToken + expiredAt + } + } +` + +const useKakaoSDKInit = ({ + appKey, + isLazy = false, +}: { + appKey: string + isLazy: boolean +}) => { + const [initResult, setInitResult] = useState({ + isLoaded: false, + isError: false, + }) + + useEffect(() => { + const kakaoSdkScript = document.getElementById('kakao-sdk') + if (kakaoSdkScript) return + + const initKakaoScript = async () => { + const scriptInitResult = new Promise<{ + isLoaded: boolean + isError: boolean + }>((resolve, reject) => { + const script = document.createElement('script') + script.id = 'kakao-sdk' + script.src = 'https://developers.kakao.com/sdk/js/kakao.js' + + if (isLazy) { + script.defer = true + } + + document.head.appendChild(script) + + script.addEventListener('load', () => { + resolve({isLoaded: true, isError: false}) + }) + + script.addEventListener('error', () => { + // eslint-disable-next-line prefer-promise-reject-errors + reject({isLoaded: false, isError: true}) + }) + }) + + const result = await scriptInitResult + setInitResult(result) + + Kakao.init(appKey) + } + + initKakaoScript() + }, [appKey, isLazy]) + + return initResult +} + +const Login = () => { + const handleKaKaoLoginClick = () => { + Kakao.Auth.login({ + success({access_token}) { + ;(async () => { + const result = await urqlClient + .mutation(SignInDocumnet, { + input: { + code: access_token, + type: 'KAKAO', + }, + }) + .toPromise() + + localStorage.setItem('token', JSON.stringify(result.data.signIn)) + })() + }, + fail(error) { + console.error(error) + }, + }) + } + + const {isLoaded} = useKakaoSDKInit({ + appKey: '1a01c6b9fba660692d7388f0f7c5baaf', + isLazy: true, + }) + + if (!isLoaded) { + console.log('loading') + } + + return ( +
+ +
+ ) +} + +export default Login From 24ee41bb57f83805847304ff03dea424246adf2b Mon Sep 17 00:00:00 2001 From: Seongcheol Jo Date: Wed, 27 Jul 2022 23:03:23 +0900 Subject: [PATCH 4/7] add: useKakaoInit --- packages/santa_close_frame/src/App.tsx | 6 +- packages/santa_close_frame/src/Login.tsx | 108 ------------------ packages/santa_close_frame/src/hooks/index.ts | 1 + .../src/hooks/useKakaoInit.ts | 65 +++++++++++ .../santa_close_frame/src/pages/Login.tsx | 55 +++++++++ 5 files changed, 124 insertions(+), 111 deletions(-) delete mode 100644 packages/santa_close_frame/src/Login.tsx create mode 100644 packages/santa_close_frame/src/hooks/index.ts create mode 100644 packages/santa_close_frame/src/hooks/useKakaoInit.ts create mode 100644 packages/santa_close_frame/src/pages/Login.tsx diff --git a/packages/santa_close_frame/src/App.tsx b/packages/santa_close_frame/src/App.tsx index e6721ea..457ad7a 100644 --- a/packages/santa_close_frame/src/App.tsx +++ b/packages/santa_close_frame/src/App.tsx @@ -3,17 +3,17 @@ import {RecoilRoot, useRecoilState} from 'recoil' import {sampleState} from 'map_app/atoms' import {UrqlProvider} from 'santa_close_common' import {BrowserRouter, Routes, Route} from 'react-router-dom' -import Login from './Login' +import Login from './pages/Login' const MapApp = React.lazy(() => import('map_app/MapApp')) const MapAppContainer = () => { const [state, setState] = useRecoilState(sampleState) - const handleStateChange = (e: ChangeEvent) => { + const handleStateChange = (event: ChangeEvent) => { const { target: {value}, - } = e + } = event setState(value) } diff --git a/packages/santa_close_frame/src/Login.tsx b/packages/santa_close_frame/src/Login.tsx deleted file mode 100644 index a90dba6..0000000 --- a/packages/santa_close_frame/src/Login.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import {useEffect, useState} from 'react' -import {urqlClient} from 'santa_close_common' -import {gql} from 'urql' - -const SignInDocumnet = gql` - mutation SignIn($input: SignInAppInput!) { - signIn(input: $input) { - accessToken - expiredAt - } - } -` - -const useKakaoSDKInit = ({ - appKey, - isLazy = false, -}: { - appKey: string - isLazy: boolean -}) => { - const [initResult, setInitResult] = useState({ - isLoaded: false, - isError: false, - }) - - useEffect(() => { - const kakaoSdkScript = document.getElementById('kakao-sdk') - if (kakaoSdkScript) return - - const initKakaoScript = async () => { - const scriptInitResult = new Promise<{ - isLoaded: boolean - isError: boolean - }>((resolve, reject) => { - const script = document.createElement('script') - script.id = 'kakao-sdk' - script.src = 'https://developers.kakao.com/sdk/js/kakao.js' - - if (isLazy) { - script.defer = true - } - - document.head.appendChild(script) - - script.addEventListener('load', () => { - resolve({isLoaded: true, isError: false}) - }) - - script.addEventListener('error', () => { - // eslint-disable-next-line prefer-promise-reject-errors - reject({isLoaded: false, isError: true}) - }) - }) - - const result = await scriptInitResult - setInitResult(result) - - Kakao.init(appKey) - } - - initKakaoScript() - }, [appKey, isLazy]) - - return initResult -} - -const Login = () => { - const handleKaKaoLoginClick = () => { - Kakao.Auth.login({ - success({access_token}) { - ;(async () => { - const result = await urqlClient - .mutation(SignInDocumnet, { - input: { - code: access_token, - type: 'KAKAO', - }, - }) - .toPromise() - - localStorage.setItem('token', JSON.stringify(result.data.signIn)) - })() - }, - fail(error) { - console.error(error) - }, - }) - } - - const {isLoaded} = useKakaoSDKInit({ - appKey: '1a01c6b9fba660692d7388f0f7c5baaf', - isLazy: true, - }) - - if (!isLoaded) { - console.log('loading') - } - - return ( -
- -
- ) -} - -export default Login diff --git a/packages/santa_close_frame/src/hooks/index.ts b/packages/santa_close_frame/src/hooks/index.ts new file mode 100644 index 0000000..98f9d6f --- /dev/null +++ b/packages/santa_close_frame/src/hooks/index.ts @@ -0,0 +1 @@ +export * from './useKakaoInit' diff --git a/packages/santa_close_frame/src/hooks/useKakaoInit.ts b/packages/santa_close_frame/src/hooks/useKakaoInit.ts new file mode 100644 index 0000000..f05ff05 --- /dev/null +++ b/packages/santa_close_frame/src/hooks/useKakaoInit.ts @@ -0,0 +1,65 @@ +import {useState, useEffect} from 'react' + +type ScriptLoadType = 'async' | 'defer' + +const createKakaoScript = (loadType?: ScriptLoadType) => { + const script = document.createElement('script') + script.id = 'kakao-sdk' + script.src = 'https://developers.kakao.com/sdk/js/kakao.js' + + if (loadType) { + script[loadType] = true + } + + return script +} + +const appendScriptIntoHeaders = (script: HTMLScriptElement) => { + document.head.appendChild(script) +} + +export const useKakaoInit = ({ + appKey, + loadType, +}: { + appKey: string + loadType?: ScriptLoadType +}) => { + const [initResult, setInitResult] = useState({ + isLoaded: false, + isError: false, + }) + + useEffect(() => { + const kakaoSdkScript = document.getElementById('kakao-sdk') + if (kakaoSdkScript) return + + const initKakaoScript = async () => { + const scriptInitResult = new Promise<{ + isLoaded: boolean + isError: boolean + }>((resolve, reject) => { + const script = createKakaoScript(loadType) + appendScriptIntoHeaders(script) + + script.addEventListener('load', () => { + resolve({isLoaded: true, isError: false}) + }) + + script.addEventListener('error', () => { + // eslint-disable-next-line prefer-promise-reject-errors + reject({isLoaded: false, isError: true}) + }) + }) + + const result = await scriptInitResult + setInitResult(result) + + Kakao.init(appKey) + } + + initKakaoScript() + }, [appKey, loadType]) + + return initResult +} diff --git a/packages/santa_close_frame/src/pages/Login.tsx b/packages/santa_close_frame/src/pages/Login.tsx new file mode 100644 index 0000000..fcf14c6 --- /dev/null +++ b/packages/santa_close_frame/src/pages/Login.tsx @@ -0,0 +1,55 @@ +import {urqlClient} from 'santa_close_common' +import {gql} from 'urql' +import {useKakaoInit} from '../hooks' + +const SignInDocumnet = gql` + mutation SignIn($input: SignInAppInput!) { + signIn(input: $input) { + accessToken + expiredAt + } + } +` + +const Login = () => { + const handleKaKaoLoginClick = () => { + Kakao.Auth.login({ + success({access_token}) { + ;(async () => { + const result = await urqlClient + .mutation(SignInDocumnet, { + input: { + code: access_token, + type: 'KAKAO', + }, + }) + .toPromise() + + localStorage.setItem('token', JSON.stringify(result.data.signIn)) + })() + + console.log('kakao login success') + }, + fail(error) { + console.error('kakao login failed', error) + }, + }) + } + + const {isLoaded} = useKakaoInit({ + appKey: '1a01c6b9fba660692d7388f0f7c5baaf', + loadType: 'defer', + }) + + if (!isLoaded) return null + + return ( +
+ +
+ ) +} + +export default Login From 811f11b4f7f9df0a60edcb87fdbf86344c92a3be Mon Sep 17 00:00:00 2001 From: Seongcheol Jo Date: Sun, 31 Jul 2022 23:03:12 +0900 Subject: [PATCH 5/7] =?UTF-8?q?add:=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20-=20ProtectedRoute=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20-=20useAccessToken=20=EC=B6=94=EA=B0=80=20-=20useLo?= =?UTF-8?q?calStorage=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/santa_close_frame/src/App.tsx | 12 +++++++ .../src/components/ProtectedRoute.tsx | 20 +++++++++++ .../santa_close_frame/src/components/index.ts | 1 + packages/santa_close_frame/src/hooks/index.ts | 2 ++ .../src/hooks/useAccessToken.ts | 21 +++++++++++ .../src/hooks/useLocalStorage.ts | 28 +++++++++++++++ .../santa_close_frame/src/pages/Login.tsx | 35 +++++++++++++------ 7 files changed, 108 insertions(+), 11 deletions(-) create mode 100644 packages/santa_close_frame/src/components/ProtectedRoute.tsx create mode 100644 packages/santa_close_frame/src/components/index.ts create mode 100644 packages/santa_close_frame/src/hooks/useAccessToken.ts create mode 100644 packages/santa_close_frame/src/hooks/useLocalStorage.ts diff --git a/packages/santa_close_frame/src/App.tsx b/packages/santa_close_frame/src/App.tsx index 457ad7a..f48ec85 100644 --- a/packages/santa_close_frame/src/App.tsx +++ b/packages/santa_close_frame/src/App.tsx @@ -4,6 +4,8 @@ import {sampleState} from 'map_app/atoms' import {UrqlProvider} from 'santa_close_common' import {BrowserRouter, Routes, Route} from 'react-router-dom' import Login from './pages/Login' +import {ProtectedRoute} from './components' +import {useAccessToken} from './hooks' const MapApp = React.lazy(() => import('map_app/MapApp')) @@ -36,6 +38,8 @@ const MapAppContainer = () => { } const App = () => { + const {isAvailable} = useAccessToken() + return ( @@ -43,6 +47,14 @@ const App = () => { } /> } /> + +
Protected Page
+ + } + />
diff --git a/packages/santa_close_frame/src/components/ProtectedRoute.tsx b/packages/santa_close_frame/src/components/ProtectedRoute.tsx new file mode 100644 index 0000000..40db374 --- /dev/null +++ b/packages/santa_close_frame/src/components/ProtectedRoute.tsx @@ -0,0 +1,20 @@ +import {FC, ReactElement} from 'react' +import {Navigate} from 'react-router-dom' + +interface ProtectedRouteProps { + isAllowed: boolean + redirectTo: string + children: ReactElement +} + +export const ProtectedRoute: FC = ({ + isAllowed, + redirectTo, + children, +}) => { + if (!isAllowed) { + return + } + + return children +} diff --git a/packages/santa_close_frame/src/components/index.ts b/packages/santa_close_frame/src/components/index.ts new file mode 100644 index 0000000..5831efa --- /dev/null +++ b/packages/santa_close_frame/src/components/index.ts @@ -0,0 +1 @@ +export * from './ProtectedRoute' diff --git a/packages/santa_close_frame/src/hooks/index.ts b/packages/santa_close_frame/src/hooks/index.ts index 98f9d6f..48368ca 100644 --- a/packages/santa_close_frame/src/hooks/index.ts +++ b/packages/santa_close_frame/src/hooks/index.ts @@ -1 +1,3 @@ export * from './useKakaoInit' +export * from './useLocalStorage' +export * from './useAccessToken' diff --git a/packages/santa_close_frame/src/hooks/useAccessToken.ts b/packages/santa_close_frame/src/hooks/useAccessToken.ts new file mode 100644 index 0000000..7945978 --- /dev/null +++ b/packages/santa_close_frame/src/hooks/useAccessToken.ts @@ -0,0 +1,21 @@ +import {useLocalStorage} from './useLocalStorage' + +export const useAccessToken = (key = 'accessToken') => { + const [{accessToken, expiredAt}] = useLocalStorage(key, { + accessToken: '', + expiredAt: '', + }) + + if (!accessToken || !expiredAt) { + return {isAvailable: false, accessToken: {accessToken, expiredAt}} + } + + const now = new Date().getTime() + const expiredAtTime = new Date(expiredAt).getTime() + + if (now > expiredAtTime) { + return {isAvailable: false, accessToken: {accessToken, expiredAt}} + } + + return {isAvailable: true, accessToken: {accessToken, expiredAt}} +} diff --git a/packages/santa_close_frame/src/hooks/useLocalStorage.ts b/packages/santa_close_frame/src/hooks/useLocalStorage.ts new file mode 100644 index 0000000..3f89a67 --- /dev/null +++ b/packages/santa_close_frame/src/hooks/useLocalStorage.ts @@ -0,0 +1,28 @@ +import {useState} from 'react' + +const isClient = typeof window !== 'undefined' + +export function useLocalStorage(key: string, initialValue: T) { + const [storedValue, setStoredValue] = useState(() => { + if (!isClient) return initialValue + + try { + const item = window.localStorage.getItem(key) + return item ? JSON.parse(item) : initialValue + } catch (error) { + console.error(error) + return initialValue + } + }) + + const setValue = (value: T | ((value: T) => T)) => { + const valueToStore = value instanceof Function ? value(storedValue) : value + setStoredValue(valueToStore) + + if (isClient) { + window.localStorage.setItem(key, JSON.stringify(valueToStore)) + } + } + + return [storedValue, setValue] as const +} diff --git a/packages/santa_close_frame/src/pages/Login.tsx b/packages/santa_close_frame/src/pages/Login.tsx index fcf14c6..b66bf9d 100644 --- a/packages/santa_close_frame/src/pages/Login.tsx +++ b/packages/santa_close_frame/src/pages/Login.tsx @@ -1,6 +1,7 @@ +import {useNavigate} from 'react-router-dom' import {urqlClient} from 'santa_close_common' import {gql} from 'urql' -import {useKakaoInit} from '../hooks' +import {useKakaoInit, useLocalStorage} from '../hooks' const SignInDocumnet = gql` mutation SignIn($input: SignInAppInput!) { @@ -12,11 +13,27 @@ const SignInDocumnet = gql` ` const Login = () => { + const navigate = useNavigate() + const {isLoaded} = useKakaoInit({ + appKey: '1a01c6b9fba660692d7388f0f7c5baaf', + loadType: 'defer', + }) + + // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-unused-vars + const [_, setAccessToken] = useLocalStorage('accessToken', { + accessToken: '', + expiredAt: '', + }) + const handleKaKaoLoginClick = () => { Kakao.Auth.login({ - success({access_token}) { + success: ({access_token}) => { ;(async () => { - const result = await urqlClient + const { + data: { + signIn: {accessToken, expiredAt}, + }, + } = await urqlClient .mutation(SignInDocumnet, { input: { code: access_token, @@ -25,22 +42,18 @@ const Login = () => { }) .toPromise() - localStorage.setItem('token', JSON.stringify(result.data.signIn)) + const result = {accessToken, expiredAt} + setAccessToken(result) })() - console.log('kakao login success') + navigate('/', {replace: true}) }, - fail(error) { + fail: (error) => { console.error('kakao login failed', error) }, }) } - const {isLoaded} = useKakaoInit({ - appKey: '1a01c6b9fba660692d7388f0f7c5baaf', - loadType: 'defer', - }) - if (!isLoaded) return null return ( From c7abf33dfb103bc12842c67050cf1d77956ddb3c Mon Sep 17 00:00:00 2001 From: Seongcheol Jo Date: Sun, 31 Jul 2022 23:12:25 +0900 Subject: [PATCH 6/7] refactor: useAccessToken --- .../santa_close_frame/src/hooks/useAccessToken.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/santa_close_frame/src/hooks/useAccessToken.ts b/packages/santa_close_frame/src/hooks/useAccessToken.ts index 7945978..5a3f556 100644 --- a/packages/santa_close_frame/src/hooks/useAccessToken.ts +++ b/packages/santa_close_frame/src/hooks/useAccessToken.ts @@ -1,5 +1,12 @@ import {useLocalStorage} from './useLocalStorage' +const validateExpiryDate = (expiredAt: string) => { + const now = new Date().getTime() + const expiredAtTime = new Date(expiredAt).getTime() + + return now < expiredAtTime +} + export const useAccessToken = (key = 'accessToken') => { const [{accessToken, expiredAt}] = useLocalStorage(key, { accessToken: '', @@ -10,10 +17,8 @@ export const useAccessToken = (key = 'accessToken') => { return {isAvailable: false, accessToken: {accessToken, expiredAt}} } - const now = new Date().getTime() - const expiredAtTime = new Date(expiredAt).getTime() - - if (now > expiredAtTime) { + const isAvailableToken = validateExpiryDate(expiredAt) + if (isAvailableToken) { return {isAvailable: false, accessToken: {accessToken, expiredAt}} } From 92835f1c853fae6bd98aabe7fcad246472ee3b0d Mon Sep 17 00:00:00 2001 From: Seongcheol Jo Date: Sun, 31 Jul 2022 23:39:58 +0900 Subject: [PATCH 7/7] =?UTF-8?q?refactor:=20useLocalStorage=20-=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=ED=91=9C=ED=98=84=EC=8B=9D=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/santa_close_frame/src/hooks/useLocalStorage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/santa_close_frame/src/hooks/useLocalStorage.ts b/packages/santa_close_frame/src/hooks/useLocalStorage.ts index 3f89a67..ea9c27f 100644 --- a/packages/santa_close_frame/src/hooks/useLocalStorage.ts +++ b/packages/santa_close_frame/src/hooks/useLocalStorage.ts @@ -2,7 +2,7 @@ import {useState} from 'react' const isClient = typeof window !== 'undefined' -export function useLocalStorage(key: string, initialValue: T) { +export const useLocalStorage = (key: string, initialValue: T) => { const [storedValue, setStoredValue] = useState(() => { if (!isClient) return initialValue