front-boilerplate 설정

This commit is contained in:
hyojin 2023-09-06 14:00:01 +09:00
parent 4f6510a031
commit 3a639e9a38
26 changed files with 262 additions and 142 deletions

8
.prettierrc Normal file
View File

@ -0,0 +1,8 @@
{
"singleQuote": true,
"semi": true,
"useTabs": false,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 80
}

132
package-lock.json generated
View File

@ -1,24 +1,18 @@
{
"name": "tuya-admin-front-2",
"version": "0.1.0",
"name": "front-boilerplate",
"version": "0.0.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "tuya-admin-front-2",
"version": "0.1.0",
"name": "front-boilerplate",
"version": "0.0.1",
"dependencies": {
"@sdt/sdt-ui-kit": "^0.1.17",
"@sdt/sdt-ui-kit": "^0.1.20",
"@tanstack/react-query": "^4.33.0",
"@tanstack/react-query-devtools": "^4.33.0",
"@types/lodash": "^4.14.197",
"@types/node": "20.5.1",
"@types/qs": "^6.9.7",
"@types/react": "18.2.20",
"@types/react-dom": "18.2.7",
"@types/react-modal": "^3.16.0",
"autoprefixer": "10.4.15",
"axios": "^1.4.0",
"cookies-next": "^3.0.0",
"eslint": "8.47.0",
"eslint-config-next": "13.4.19",
"lodash": "^4.17.21",
@ -36,6 +30,13 @@
"zustand": "^4.4.1"
},
"devDependencies": {
"@tanstack/react-query-devtools": "^4.33.0",
"@types/lodash": "^4.14.197",
"@types/node": "20.5.1",
"@types/qs": "^6.9.7",
"@types/react": "18.2.20",
"@types/react-dom": "18.2.7",
"@types/react-modal": "^3.16.0",
"@typescript-eslint/eslint-plugin": "^6.4.1",
"@typescript-eslint/parser": "^6.4.1",
"eslint-config-next": "13.4.19",
@ -3138,9 +3139,9 @@
"dev": true
},
"node_modules/@sdt/sdt-ui-kit": {
"version": "0.1.17",
"resolved": "http://192.168.1.232:8081/repository/npm-hosted/@sdt/sdt-ui-kit/-/sdt-ui-kit-0.1.17.tgz",
"integrity": "sha512-jf8xCO+Dlo/pMMXQxmXFzwguCYKEIgsBg1knZ/XWScAKvnQfpABEB3jo9+vAvEQ+gdteg2L+xIcuaCceJk/NAQ==",
"version": "0.1.20",
"resolved": "http://192.168.1.232:8081/repository/npm-hosted/@sdt/sdt-ui-kit/-/sdt-ui-kit-0.1.20.tgz",
"integrity": "sha512-vqRWbeDioEGgvgT2lDsQl13kPT/pX8N0NMk9FqN9W6+UIT/ZNP/uDvmVqnJyjQmC+xd5j/yJ5hwkuP0joVfqEQ==",
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
@ -3176,6 +3177,7 @@
"version": "8.8.4",
"resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.8.4.tgz",
"integrity": "sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw==",
"dev": true,
"dependencies": {
"remove-accents": "0.4.2"
},
@ -3226,6 +3228,7 @@
"version": "4.33.0",
"resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.33.0.tgz",
"integrity": "sha512-6gegkuDmOoiY5e6ZKj1id48vlCXchjfE/6tIpYO8dFlVMQ7t1bYna/Ce6qQJ69+kfEHbYiTTn2lj+FDjIBH7Hg==",
"dev": true,
"dependencies": {
"@tanstack/match-sorter-utils": "^8.7.0",
"superjson": "^1.10.0",
@ -3326,12 +3329,14 @@
"node_modules/@types/lodash": {
"version": "4.14.197",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz",
"integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g=="
"integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==",
"dev": true
},
"node_modules/@types/node": {
"version": "20.5.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.1.tgz",
"integrity": "sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg=="
"integrity": "sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==",
"dev": true
},
"node_modules/@types/parse-json": {
"version": "4.0.0",
@ -3346,7 +3351,8 @@
"node_modules/@types/qs": {
"version": "6.9.7",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
"dev": true
},
"node_modules/@types/react": {
"version": "18.2.20",
@ -3362,6 +3368,7 @@
"version": "18.2.7",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz",
"integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==",
"dev": true,
"dependencies": {
"@types/react": "*"
}
@ -3386,6 +3393,7 @@
"version": "3.16.0",
"resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.16.0.tgz",
"integrity": "sha512-iphdqXAyUfByLbxJn5j6d+yh93dbMgshqGP0IuBeaKbZXx0aO+OXsvEkt6QctRdxjeM9/bR+Gp3h9F9djVWTQQ==",
"dev": true,
"dependencies": {
"@types/react": "*"
}
@ -4262,10 +4270,39 @@
"node": ">= 0.6"
}
},
"node_modules/cookies-next": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cookies-next/-/cookies-next-3.0.0.tgz",
"integrity": "sha512-VaSrsjQJ8yHnGAGulV9zJxBr7hrKJ/O2mo87evsGIMF7XvJI3AJNguevotx0Gek1MMMBkZvZNWu2JueSNoSKEQ==",
"dependencies": {
"@types/cookie": "^0.4.1",
"@types/node": "^16.10.2",
"cookie": "^0.4.0"
}
},
"node_modules/cookies-next/node_modules/@types/cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q=="
},
"node_modules/cookies-next/node_modules/@types/node": {
"version": "16.18.48",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.48.tgz",
"integrity": "sha512-mlaecDKQ7rIZrYD7iiKNdzFb6e/qD5I9U1rAhq+Fd+DWvYVs+G2kv74UFHmSOlg5+i/vF3XxuR522V4u8BqO+Q=="
},
"node_modules/cookies-next/node_modules/cookie": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
"integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/copy-anything": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz",
"integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
"dev": true,
"dependencies": {
"is-what": "^4.1.8"
},
@ -6264,6 +6301,7 @@
"version": "4.1.15",
"resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.15.tgz",
"integrity": "sha512-uKua1wfy3Yt+YqsD6mTUEa2zSi3G1oPlqTflgaPJ7z63vUGN5pxFpnQfeSLMFnJDEsdvOtkp1rUWkYjB4YfhgA==",
"dev": true,
"engines": {
"node": ">=12.13"
},
@ -7500,7 +7538,8 @@
"node_modules/remove-accents": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz",
"integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA=="
"integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==",
"dev": true
},
"node_modules/resolve": {
"version": "1.22.4",
@ -8041,6 +8080,7 @@
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/superjson/-/superjson-1.13.1.tgz",
"integrity": "sha512-AVH2eknm9DEd3qvxM4Sq+LTCkSXE2ssfh1t11MHMXyYXFQyQ1HLgVvV+guLTsaQnJU3gnaVo34TohHPulY/wLg==",
"dev": true,
"dependencies": {
"copy-anything": "^3.0.2"
},
@ -10716,9 +10756,9 @@
"dev": true
},
"@sdt/sdt-ui-kit": {
"version": "0.1.17",
"resolved": "http://192.168.1.232:8081/repository/npm-hosted/@sdt/sdt-ui-kit/-/sdt-ui-kit-0.1.17.tgz",
"integrity": "sha512-jf8xCO+Dlo/pMMXQxmXFzwguCYKEIgsBg1knZ/XWScAKvnQfpABEB3jo9+vAvEQ+gdteg2L+xIcuaCceJk/NAQ==",
"version": "0.1.20",
"resolved": "http://192.168.1.232:8081/repository/npm-hosted/@sdt/sdt-ui-kit/-/sdt-ui-kit-0.1.20.tgz",
"integrity": "sha512-vqRWbeDioEGgvgT2lDsQl13kPT/pX8N0NMk9FqN9W6+UIT/ZNP/uDvmVqnJyjQmC+xd5j/yJ5hwkuP0joVfqEQ==",
"requires": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
@ -10749,6 +10789,7 @@
"version": "8.8.4",
"resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.8.4.tgz",
"integrity": "sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw==",
"dev": true,
"requires": {
"remove-accents": "0.4.2"
}
@ -10771,6 +10812,7 @@
"version": "4.33.0",
"resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.33.0.tgz",
"integrity": "sha512-6gegkuDmOoiY5e6ZKj1id48vlCXchjfE/6tIpYO8dFlVMQ7t1bYna/Ce6qQJ69+kfEHbYiTTn2lj+FDjIBH7Hg==",
"dev": true,
"requires": {
"@tanstack/match-sorter-utils": "^8.7.0",
"superjson": "^1.10.0",
@ -10864,12 +10906,14 @@
"@types/lodash": {
"version": "4.14.197",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz",
"integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g=="
"integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==",
"dev": true
},
"@types/node": {
"version": "20.5.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.1.tgz",
"integrity": "sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg=="
"integrity": "sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==",
"dev": true
},
"@types/parse-json": {
"version": "4.0.0",
@ -10884,7 +10928,8 @@
"@types/qs": {
"version": "6.9.7",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
"dev": true
},
"@types/react": {
"version": "18.2.20",
@ -10900,6 +10945,7 @@
"version": "18.2.7",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz",
"integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==",
"dev": true,
"requires": {
"@types/react": "*"
}
@ -10924,6 +10970,7 @@
"version": "3.16.0",
"resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.16.0.tgz",
"integrity": "sha512-iphdqXAyUfByLbxJn5j6d+yh93dbMgshqGP0IuBeaKbZXx0aO+OXsvEkt6QctRdxjeM9/bR+Gp3h9F9djVWTQQ==",
"dev": true,
"requires": {
"@types/react": "*"
}
@ -11505,10 +11552,38 @@
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="
},
"cookies-next": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cookies-next/-/cookies-next-3.0.0.tgz",
"integrity": "sha512-VaSrsjQJ8yHnGAGulV9zJxBr7hrKJ/O2mo87evsGIMF7XvJI3AJNguevotx0Gek1MMMBkZvZNWu2JueSNoSKEQ==",
"requires": {
"@types/cookie": "^0.4.1",
"@types/node": "^16.10.2",
"cookie": "^0.4.0"
},
"dependencies": {
"@types/cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q=="
},
"@types/node": {
"version": "16.18.48",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.48.tgz",
"integrity": "sha512-mlaecDKQ7rIZrYD7iiKNdzFb6e/qD5I9U1rAhq+Fd+DWvYVs+G2kv74UFHmSOlg5+i/vF3XxuR522V4u8BqO+Q=="
},
"cookie": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
"integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA=="
}
}
},
"copy-anything": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz",
"integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
"dev": true,
"requires": {
"is-what": "^4.1.8"
}
@ -12961,7 +13036,8 @@
"is-what": {
"version": "4.1.15",
"resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.15.tgz",
"integrity": "sha512-uKua1wfy3Yt+YqsD6mTUEa2zSi3G1oPlqTflgaPJ7z63vUGN5pxFpnQfeSLMFnJDEsdvOtkp1rUWkYjB4YfhgA=="
"integrity": "sha512-uKua1wfy3Yt+YqsD6mTUEa2zSi3G1oPlqTflgaPJ7z63vUGN5pxFpnQfeSLMFnJDEsdvOtkp1rUWkYjB4YfhgA==",
"dev": true
},
"is-wsl": {
"version": "2.2.0",
@ -13795,7 +13871,8 @@
"remove-accents": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz",
"integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA=="
"integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==",
"dev": true
},
"resolve": {
"version": "1.22.4",
@ -14157,6 +14234,7 @@
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/superjson/-/superjson-1.13.1.tgz",
"integrity": "sha512-AVH2eknm9DEd3qvxM4Sq+LTCkSXE2ssfh1t11MHMXyYXFQyQ1HLgVvV+guLTsaQnJU3gnaVo34TohHPulY/wLg==",
"dev": true,
"requires": {
"copy-anything": "^3.0.2"
}

View File

@ -1,6 +1,6 @@
{
"name": "tuya-admin-front",
"version": "0.1.0",
"name": "front-boilerplate",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "next dev",
@ -9,17 +9,11 @@
"lint": "next lint"
},
"dependencies": {
"@sdt/sdt-ui-kit": "^0.1.17",
"@sdt/sdt-ui-kit": "^0.1.20",
"@tanstack/react-query": "^4.33.0",
"@tanstack/react-query-devtools": "^4.33.0",
"@types/lodash": "^4.14.197",
"@types/node": "20.5.1",
"@types/qs": "^6.9.7",
"@types/react": "18.2.20",
"@types/react-dom": "18.2.7",
"@types/react-modal": "^3.16.0",
"autoprefixer": "10.4.15",
"axios": "^1.4.0",
"cookies-next": "^3.0.0",
"eslint": "8.47.0",
"eslint-config-next": "13.4.19",
"lodash": "^4.17.21",
@ -37,6 +31,13 @@
"zustand": "^4.4.1"
},
"devDependencies": {
"@tanstack/react-query-devtools": "^4.33.0",
"@types/lodash": "^4.14.197",
"@types/node": "20.5.1",
"@types/qs": "^6.9.7",
"@types/react": "18.2.20",
"@types/react-dom": "18.2.7",
"@types/react-modal": "^3.16.0",
"@typescript-eslint/eslint-plugin": "^6.4.1",
"@typescript-eslint/parser": "^6.4.1",
"eslint-config-next": "13.4.19",

View File

@ -1,9 +1,5 @@
import {
ACCESS_TOKEN_NAME,
getCookie,
REFREASH_TOKEN_NAME,
removeCookie,
} from '../utils/cookies';
import { ACCESS_TOKEN_NAME, REFREASH_TOKEN_NAME } from '@/utils';
import { deleteCookie, getCookie } from 'cookies-next';
import { setToken } from '../utils/setToken';
import axios, { AxiosRequestConfig, Method } from 'axios';
import { silentSignInApi } from './oauth';
@ -55,6 +51,7 @@ export const fetchApi = ({
defaultInstance.interceptors.request.use(
(req: any) => {
// console.log('######## req interceptors', req);
// todo fix
const SDT_AT = getCookie(ACCESS_TOKEN_NAME);
if (noToken) {
@ -101,9 +98,9 @@ export const fetchApi = ({
originalRequest.headers['Authorization'] = `Bearer ${accessToken}`;
return fetchApi({ ...originalRequest });
} else {
removeCookie(REFREASH_TOKEN_NAME);
removeCookie(ACCESS_TOKEN_NAME);
return (window.location.href = `${process.env.NEXT_PUBLIC_CLOUD_CONSOLE_PATH}/login?redirect=${window.location.href}`);
deleteCookie(REFREASH_TOKEN_NAME);
deleteCookie(ACCESS_TOKEN_NAME);
return (window.location.href = `/login`);
}
});
}

View File

@ -1,6 +1,7 @@
import { getCookie, REFREASH_TOKEN_NAME } from '../../utils/cookies';
import { REFREASH_TOKEN_NAME } from '@/utils';
import qs from 'qs';
import { fetchApi, afterAxios } from '../config';
import { getCookie } from 'cookies-next';
export interface SignInRequestType {
email: string;

View File

@ -1,9 +1,15 @@
import "./globals.css";
import type { Metadata } from "next";
import QueryClientProvider from '@/utils/QueryClientProvider';
import './globals.css';
import type { Metadata } from 'next';
import StyledComponentsRegistry from '@/utils/StyledComponentProvider/StyledComponentProvider';
import Layout from '@/components/Layout';
import { ACCESS_TOKEN_NAME } from '@/utils';
import { defaultInstance } from '@/api/config';
import { cookies } from 'next/headers';
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
title: 'Create Next App',
description: 'Generated by create next app',
};
export default function RootLayout({
@ -11,9 +17,21 @@ export default function RootLayout({
}: {
children: React.ReactNode;
}) {
const accessToken = cookies().get(ACCESS_TOKEN_NAME);
if (accessToken) {
defaultInstance.defaults.headers.common.Authorization = `Bearer ${accessToken.value}`;
}
return (
<html>
<body>{children}</body>
<body>
<QueryClientProvider>
<StyledComponentsRegistry>
<Layout>{children}</Layout>
</StyledComponentsRegistry>
</QueryClientProvider>
</body>
</html>
);
}

View File

@ -1 +0,0 @@
export { default } from './Login';

View File

@ -1,8 +1,8 @@
"use client";
import { Button, TextInput } from "@sdt/sdt-ui-kit";
import Link from "next/link";
import useLogin from "../hooks/useLogin";
import { emailRegex, passwordRegex } from "@/utils/reg";
'use client';
import { Button, TextInput } from '@sdt/sdt-ui-kit';
import Link from 'next/link';
import useLogin from '../hooks/useLogin';
import { emailRegex, passwordRegex } from '@/utils/reg';
interface LoginPropsType {}
@ -13,38 +13,36 @@ function Login({}: LoginPropsType) {
return (
<div className="flex justify-center items-center w-full h-screen bg-cover bg-center">
<div className="w-[37.5rem] shadow-md border rounded-[16px] px-10 sm:px-14 lg:px-5 py-7 sm:py-9 flex flex-col justify-center">
<h1 className="font-title-32 text-center"> </h1>
<form onSubmit={handleSubmit((data) => console.log(data))}>
<div className="mt-5 flex flex-col">
<TextInput
{...register("email", {
required: "이메일을 입력하세요.",
{...register('email', {
required: '이메일을 입력하세요.',
pattern: {
value: emailRegex,
message: "올바른 이메일을 입력하세요.",
message: '올바른 이메일을 입력하세요.',
},
})}
error={!!formState.errors.email}
message={(formState.errors.email?.message as string) ?? ""}
message={(formState.errors.email?.message as string) ?? ''}
maxLength={40}
type="text"
className={`rounded-t-[6px] text-[20px] w-full`}
placeholder="이메일 주소"
/>
</div>
<div className="flex flex-col">
<TextInput
{...register("password", {
required: "비밀번호를 다시 입력하세요.",
{...register('password', {
required: '비밀번호를 다시 입력하세요.',
pattern: {
value: passwordRegex,
message:
"8~16자 영문 대 소문자, 숫자, 특수문자를 사용하세요.",
'8~16자 영문 대 소문자, 숫자, 특수문자를 사용하세요.',
},
})}
error={!!formState.errors.password?.message}
message={(formState.errors.password?.message as string) ?? ""}
message={(formState.errors.password?.message as string) ?? ''}
maxLength={16}
type="password"
className={`rounded-b-[6px] text-[20px] w-full border-t-none`}
@ -64,9 +62,7 @@ function Login({}: LoginPropsType) {
<div className="w-full mt-2 flex justify-center">
<span className="mr-3 text-[#9e9e9e]"> ?</span>
<Link href={"/reset-password"} className="text-teal-500">
</Link>
<Link href={'/reset-password'}> </Link>
</div>
</div>
</div>

View File

@ -1,10 +1,7 @@
"use client";
import StyledComponentsRegistry from "@/components/__common/StyledComponentProvider/StyledComponentProvider";
export default function LoginLayout({
children,
}: {
children: React.ReactNode;
}) {
return <StyledComponentsRegistry>{children}</StyledComponentsRegistry>;
return <>{children}</>;
}

View File

@ -1,10 +1,8 @@
import React from 'react';
import Login from './Login/Login';
import Login from './components/Login';
function LoginPage() {
return (
<Login />
);
return <Login />;
}
export default LoginPage;
export default LoginPage;

View File

@ -1,4 +1,4 @@
import Image from 'next/image'
import Image from 'next/image';
export default function Home() {
return (
@ -109,5 +109,5 @@ export default function Home() {
</a>
</div>
</main>
)
);
}

View File

@ -1,6 +1,7 @@
import { useCallback, useEffect } from 'react';
import { useRouter } from 'next/router';
import { useAlertStore } from '@/stores';
import { usePathname } from 'next/navigation';
export function useAlert() {
const {
@ -10,7 +11,8 @@ export function useAlert() {
setAlertClose,
alertCallback,
} = useAlertStore();
const router = useRouter();
const pathname = usePathname();
/**
* Alert Close Handler
*/
@ -29,7 +31,7 @@ export function useAlert() {
setAlertClose();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [router]);
}, [pathname]);
return { alertOpen, alertContent, setAlertOpen, setAlertClose, onCloseAlert };
}

View File

@ -1,18 +1,15 @@
import Head from 'next/head';
'use client';
import useAlert from '../Alert/hooks/useAlert';
import Alert from '../Alert';
import useSilentAuth from '@/hooks/useSilentAuth';
export default function Layout({ children }: { children: React.ReactElement }) {
export default function Layout({ children }: { children: React.ReactNode }) {
const { alertOpen, alertContent, onCloseAlert } = useAlert();
useSilentAuth();
return (
<div className="w-full overflow-hidden">
<Head>
<title>BlokWorks</title>
<meta name="description" content="BlokWorks" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div className="flex pt-14">
<main className={`w-full p-12`}>{children}</main>
</div>

View File

@ -0,0 +1,46 @@
import { useAuthStore } from '@/stores';
import { ACCESS_TOKEN_NAME, REFREASH_TOKEN_NAME } from '@/utils';
import { getCookie, deleteCookie } from 'cookies-next';
import { usePathname, useRouter } from 'next/navigation';
import { useCallback, useEffect } from 'react';
function useSilentAuth() {
const router = useRouter();
// todo fix
const SDT_AT = getCookie(ACCESS_TOKEN_NAME) ?? '';
const { loggedIn, setSignIn, setSignOut } = useAuthStore();
const pathname = usePathname();
useEffect(() => {
if (SDT_AT && !loggedIn) {
setSignIn();
}
}, [SDT_AT, loggedIn, setSignIn]);
/**
* handle Logout
*/
const handleLogout = useCallback(async () => {
deleteCookie(ACCESS_TOKEN_NAME);
deleteCookie(REFREASH_TOKEN_NAME);
setSignOut();
}, [setSignOut]);
/**
* not Server redirect
*/
useEffect(() => {
if (
!loggedIn &&
!SDT_AT &&
!(pathname.includes('login') || pathname.includes('reset-password'))
) {
router.push(`/login`);
handleLogout();
}
}, [SDT_AT, handleLogout, loggedIn, pathname, router, setSignOut]);
return {};
}
export default useSilentAuth;

View File

@ -1,20 +1,11 @@
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
export interface ProfileType {
id: string;
sub: string;
iat: number;
exp: number;
}
/**
* Auth State Type
*/
export interface AuthStateType {
loggedIn: boolean;
email: string | null;
profile: ProfileType | null;
}
/**
@ -22,8 +13,7 @@ export interface AuthStateType {
*/
export interface AuthActionType {
setSignIn: (by: ProfileType) => void;
setEmail: (by: string) => void;
setSignIn: () => void;
setSignOut: () => void;
}
@ -33,19 +23,14 @@ export const useAuthStore = create<AuthStoreType>()(
devtools(
(set): AuthStoreType => ({
loggedIn: false,
email: null,
profile: null,
setSignIn: (by: ProfileType) =>
setSignIn: () =>
set(() => ({
profile: { ...by },
loggedIn: true,
})),
setEmail: (by: string) => set(() => ({ email: by })),
setSignOut: () =>
set(() => ({
loggedIn: false,
email: null,
})),
}),
{ name: 'auth' },

View File

@ -0,0 +1,18 @@
'use client';
import React from 'react';
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
function Providers({ children }: React.PropsWithChildren) {
const [client] = React.useState(new QueryClient());
return (
<QueryClientProvider client={client}>
{children}
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}
export default Providers;

View File

@ -0,0 +1 @@
export { default } from './QueryClientProviider';

View File

@ -1,7 +1,7 @@
"use client";
import React, { useState } from "react";
import { useServerInsertedHTML } from "next/navigation";
import { ServerStyleSheet, StyleSheetManager } from "styled-components";
'use client';
import React, { useState } from 'react';
import { useServerInsertedHTML } from 'next/navigation';
import { ServerStyleSheet, StyleSheetManager } from 'styled-components';
export default function StyledComponentsRegistry({
children,
@ -18,7 +18,7 @@ export default function StyledComponentsRegistry({
return styles;
});
if (typeof window !== "undefined") return <>{children}</>;
if (typeof window !== 'undefined') return <>{children}</>;
return (
<StyleSheetManager sheet={styledComponentsStyleSheet.instance}>

View File

@ -1,25 +0,0 @@
import { Cookies } from 'react-cookie';
import { CookieSetOptions } from 'universal-cookie';
const cookies = new Cookies();
export const REFREASH_TOKEN_NAME = 'SDT_RT';
export const ACCESS_TOKEN_NAME = 'SDT_AT';
export const setCookie = (
name: string,
value: string,
option: CookieSetOptions | undefined,
) => {
return cookies.set(name, value, { ...option });
};
export const getCookie = (name: string) => {
return cookies.get(name);
};
export const removeCookie = (name: string) => {
return cookies.remove(name, {
path: '/',
});
};

View File

@ -1,3 +1,2 @@
export * from './cookies';
export * from './setToken';
export * from './reg';

View File

@ -1,5 +1,9 @@
import { SignInResponseType } from '../api/oauth';
import { ACCESS_TOKEN_NAME, REFREASH_TOKEN_NAME, setCookie } from './cookies';
import { setCookie } from 'cookies-next';
// todo fix
export const REFREASH_TOKEN_NAME = 'SDT_RT';
export const ACCESS_TOKEN_NAME = 'SDT_AT';
export function setToken(
loginResponse: SignInResponseType,