From 300281195045972ba8094dfab23e73fa30c35d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=97=A4=EC=9D=B8?= Date: Tue, 6 Aug 2024 22:07:31 +0900 Subject: [PATCH 01/16] =?UTF-8?q?fix(src):=20=EC=BF=BC=EB=A6=AC=ED=82=A4?= =?UTF-8?q?=20CATEGORY=5FLIST=20=EB=A1=9C=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/queryKeys.ts | 1 - frontend/src/queries/category/useCategoryUpload.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/api/queryKeys.ts b/frontend/src/api/queryKeys.ts index f9bc3b76e..a1dfa92e0 100644 --- a/frontend/src/api/queryKeys.ts +++ b/frontend/src/api/queryKeys.ts @@ -1,5 +1,4 @@ export const QUERY_KEY = { - CATEGORY: 'category', CATEGORY_LIST: 'categoryList', CHECK_EMAIL: 'checkEmail', CHECK_USERNAME: 'userName', diff --git a/frontend/src/queries/category/useCategoryUpload.ts b/frontend/src/queries/category/useCategoryUpload.ts index 06341e94e..d1efbdca5 100644 --- a/frontend/src/queries/category/useCategoryUpload.ts +++ b/frontend/src/queries/category/useCategoryUpload.ts @@ -8,7 +8,7 @@ export const useCategoryUpload = () => { return useMutation({ mutationFn: postCategory, onSuccess: () => { - queryClient.invalidateQueries({ queryKey: [QUERY_KEY.CATEGORY] }); + queryClient.invalidateQueries({ queryKey: [QUERY_KEY.CATEGORY_LIST] }); }, }); }; From 0ac379fa0b9d78d8d57df27a779e114b1925a7f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=97=A4=EC=9D=B8?= Date: Tue, 6 Aug 2024 22:34:34 +0900 Subject: [PATCH 02/16] =?UTF-8?q?feat(authentication):=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EA=B4=80=EB=A0=A8=20Toast=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/hooks/authentication/useCheckLoginState.ts | 11 +++++++---- frontend/src/hooks/authentication/useLoginForm.ts | 5 +++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/frontend/src/hooks/authentication/useCheckLoginState.ts b/frontend/src/hooks/authentication/useCheckLoginState.ts index 163faeb92..eee293076 100644 --- a/frontend/src/hooks/authentication/useCheckLoginState.ts +++ b/frontend/src/hooks/authentication/useCheckLoginState.ts @@ -1,13 +1,16 @@ import { useCallback, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; +import { ToastContext } from '@/context/ToastContext'; import { useLoginStateQuery } from '@/queries/authentication/useLoginStateQuery'; +import useCustomContext from '../utils/useCustomContext'; import { useAuth } from './useAuth'; export const useCheckLoginState = () => { - const { error, isError, isSuccess } = useLoginStateQuery(); + const { error, isError, status } = useLoginStateQuery(); const navigate = useNavigate(); const { handleLoginState } = useAuth(); + const { infoAlert } = useCustomContext(ToastContext); const handleLoginNavigate = useCallback(() => { navigate('/login'); @@ -15,13 +18,13 @@ export const useCheckLoginState = () => { useEffect(() => { if (isError) { - alert(error.message); + infoAlert('로그인을 해주세요'); handleLoginNavigate(); handleLoginState(false); } - if (isSuccess) { + if (status === 'success') { handleLoginState(true); } - }, [error, isError, isSuccess, handleLoginNavigate, handleLoginState]); + }, [error, isError, status, handleLoginNavigate, handleLoginState, infoAlert]); }; diff --git a/frontend/src/hooks/authentication/useLoginForm.ts b/frontend/src/hooks/authentication/useLoginForm.ts index 7721d6df9..b2ba1aec0 100644 --- a/frontend/src/hooks/authentication/useLoginForm.ts +++ b/frontend/src/hooks/authentication/useLoginForm.ts @@ -2,11 +2,14 @@ import { FormEvent } from 'react'; import { useNavigate } from 'react-router-dom'; import { postLogin } from '@/api/authentication'; +import { ToastContext } from '@/context/ToastContext'; import { useInputWithValidate } from '../useInputWithValidate'; +import useCustomContext from '../utils/useCustomContext'; import { validateEmail, validatePassword } from './validates'; export const useLoginForm = () => { const navigate = useNavigate(); + const { failAlert, successAlert } = useCustomContext(ToastContext); const { value: email, @@ -30,11 +33,13 @@ export const useLoginForm = () => { if (!response.ok) { console.error(response); + failAlert('로그인에 실패하였습니다.'); return; } navigate('/'); + successAlert('로그인 성공!'); } }; From 1e147d919dd53293ddf7cdf00619517a3ef47abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9B=94=ED=95=98?= Date: Wed, 7 Aug 2024 14:37:07 +0900 Subject: [PATCH 03/16] =?UTF-8?q?test(mocks):=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=EB=AA=A9=EB=A1=9D,=20=ED=85=9C=ED=94=8C?= =?UTF-8?q?=EB=A6=BF=EB=AA=A9=EB=A1=9D=20=EB=AA=A9=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/mocks/categoryList.json | 4 + frontend/src/mocks/templateList.json | 492 ++++++++++++++++++++++++--- 2 files changed, 448 insertions(+), 48 deletions(-) diff --git a/frontend/src/mocks/categoryList.json b/frontend/src/mocks/categoryList.json index 9cba418a2..ed83c49aa 100644 --- a/frontend/src/mocks/categoryList.json +++ b/frontend/src/mocks/categoryList.json @@ -1,5 +1,9 @@ { "categories": [ + { + "id": 1, + "name": "카테고리 없음" + }, { "id": 2, "name": "Category1" diff --git a/frontend/src/mocks/templateList.json b/frontend/src/mocks/templateList.json index 0c21ae984..6d0f6830e 100644 --- a/frontend/src/mocks/templateList.json +++ b/frontend/src/mocks/templateList.json @@ -4,7 +4,20 @@ "id": 1, "title": "title1", "description": "description1", - "snippets": [], + "snippets": [ + { + "id": 1, + "filename": "MyComponent.tsx", + "content": "import React from 'react';\n\ninterface MyComponentProps {\n name: string;\n age: number;\n}\n\nconst MyComponent: React.FC = ({ name, age }) => {\n return (\n
\n

Hello, {name}!

\n

You are {age} years old.

\n
\n );\n};\n\nexport default MyComponent;", + "ordinal": 1 + }, + { + "id": 2, + "filename": "App.tsx", + "content": "import React from 'react';\nimport MyComponent from './MyComponent';\n\nconst App: React.FC = () => {\n return (\n
\n \n
\n );\n};\n\nexport default App;", + "ordinal": 2 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [ { "id": 3, "name": "JavaScript" }, @@ -16,7 +29,20 @@ "id": 2, "title": "title2", "description": "description2", - "snippets": [], + "snippets": [ + { + "id": 3, + "filename": "script1.js", + "content": "console.log('Hello, world!');", + "ordinal": 1 + }, + { + "id": 4, + "filename": "script2.js", + "content": "const add = (a, b) => a + b;", + "ordinal": 2 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [ { "id": 3, "name": "JavaScript" }, @@ -28,7 +54,14 @@ "id": 3, "title": "title3", "description": "description3", - "snippets": [], + "snippets": [ + { + "id": 5, + "filename": "example.java", + "content": "public class Example { public static void main(String[] args) { System.out.println(\"Hello, World!\"); } }", + "ordinal": 1 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [{ "id": 1, "name": "Java" }], "modifiedAt": "2024-07-10 12:34" @@ -37,7 +70,14 @@ "id": 4, "title": "title4", "description": "description4", - "snippets": [], + "snippets": [ + { + "id": 6, + "filename": "style.css", + "content": "body { margin: 0; padding: 0; }", + "ordinal": 1 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [ { "id": 6, "name": "CSS" }, @@ -49,7 +89,14 @@ "id": 5, "title": "title5", "description": "description5", - "snippets": [], + "snippets": [ + { + "id": 7, + "filename": "program.java", + "content": "public class Program { public static void main(String[] args) { System.out.println(\"Run program\"); } }", + "ordinal": 1 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [{ "id": 1, "name": "Java" }], "modifiedAt": "2024-07-08 12:34" @@ -58,7 +105,20 @@ "id": 6, "title": "title6", "description": "description6", - "snippets": [], + "snippets": [ + { + "id": 8, + "filename": "Example.java", + "content": "public class Example { public static void main(String[] args) { System.out.println(\"Hello, Example!\"); } }", + "ordinal": 1 + }, + { + "id": 9, + "filename": "Sample.java", + "content": "public class Sample { public static void main(String[] args) { System.out.println(\"Sample code\"); } }", + "ordinal": 2 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [ { "id": 1, "name": "Java" }, @@ -70,7 +130,20 @@ "id": 7, "title": "title7", "description": "description7", - "snippets": [], + "snippets": [ + { + "id": 10, + "filename": "App.js", + "content": "console.log('App running');", + "ordinal": 1 + }, + { + "id": 11, + "filename": "Component.js", + "content": "export const Component = () => console.log('Component loaded');", + "ordinal": 2 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [ { "id": 4, "name": "React" }, @@ -82,7 +155,14 @@ "id": 8, "title": "title8", "description": "description8", - "snippets": [], + "snippets": [ + { + "id": 12, + "filename": "index.js", + "content": "console.log('Index file');", + "ordinal": 1 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [], "modifiedAt": "2024-07-05 12:34" @@ -91,7 +171,20 @@ "id": 9, "title": "title9", "description": "description9", - "snippets": [], + "snippets": [ + { + "id": 13, + "filename": "main.js", + "content": "console.log('Main file');", + "ordinal": 1 + }, + { + "id": 14, + "filename": "helper.js", + "content": "export const helper = () => console.log('Helper function');", + "ordinal": 2 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [ { "id": 3, "name": "JavaScript" }, @@ -103,7 +196,14 @@ "id": 10, "title": "title10", "description": "description10", - "snippets": [], + "snippets": [ + { + "id": 15, + "filename": "frontend.py", + "content": "print('Hello, Frontend!')", + "ordinal": 1 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [ { "id": 9, "name": "Frontend" }, @@ -115,7 +215,20 @@ "id": 11, "title": "title11", "description": "description11", - "snippets": [], + "snippets": [ + { + "id": 16, + "filename": "backend.js", + "content": "console.log('Backend logic');", + "ordinal": 1 + }, + { + "id": 17, + "filename": "database.js", + "content": "console.log('Database connection');", + "ordinal": 2 + } + ], "category": { "id": 1, "name": "" }, "tags": [ { "id": 3, "name": "JavaScript" }, @@ -127,7 +240,14 @@ "id": 12, "title": "title12", "description": "description12", - "snippets": [], + "snippets": [ + { + "id": 18, + "filename": "example1.js", + "content": "console.log('Example snippet');", + "ordinal": 1 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [], "modifiedAt": "2024-07-01 12:34" @@ -136,7 +256,20 @@ "id": 13, "title": "title13", "description": "description13", - "snippets": [], + "snippets": [ + { + "id": 19, + "filename": "oop.js", + "content": "class OOPExample { constructor() { console.log('OOP Example'); } }", + "ordinal": 1 + }, + { + "id": 20, + "filename": "styling.js", + "content": "const style = { color: 'blue' };", + "ordinal": 2 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [ { "id": 7, "name": "Styling" }, @@ -148,7 +281,14 @@ "id": 14, "title": "title14", "description": "description14", - "snippets": [], + "snippets": [ + { + "id": 21, + "filename": "hello.java", + "content": "public class Hello { public static void main(String[] args) { System.out.println(\"Hello\"); } }", + "ordinal": 1 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [{ "id": 1, "name": "Java" }], "modifiedAt": "2024-07-10 12:34" @@ -157,7 +297,20 @@ "id": 15, "title": "title15", "description": "description15", - "snippets": [], + "snippets": [ + { + "id": 22, + "filename": "example.py", + "content": "print('Example snippet')", + "ordinal": 1 + }, + { + "id": 23, + "filename": "sample.py", + "content": "print('Sample code')", + "ordinal": 2 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [ { "id": 10, "name": "Python" }, @@ -169,7 +322,14 @@ "id": 16, "title": "title16", "description": "description16", - "snippets": [], + "snippets": [ + { + "id": 24, + "filename": "backend.java", + "content": "public class Backend { public static void main(String[] args) { System.out.println(\"Backend\"); } }", + "ordinal": 1 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [ { "id": 3, "name": "JavaScript" }, @@ -181,7 +341,14 @@ "id": 17, "title": "title17", "description": "description17", - "snippets": [], + "snippets": [ + { + "id": 25, + "filename": "react.js", + "content": "import React from 'react';", + "ordinal": 1 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [ { "id": 4, "name": "React" }, @@ -193,7 +360,20 @@ "id": 18, "title": "title18", "description": "description18", - "snippets": [], + "snippets": [ + { + "id": 26, + "filename": "oop.js", + "content": "class OOP { constructor() { console.log('OOP'); } }", + "ordinal": 1 + }, + { + "id": 27, + "filename": "example.js", + "content": "console.log('Example');", + "ordinal": 2 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [ { "id": 7, "name": "Styling" }, @@ -206,7 +386,14 @@ "id": 19, "title": "title19", "description": "description19", - "snippets": [], + "snippets": [ + { + "id": 28, + "filename": "java_snippet.java", + "content": "public class JavaSnippet { public static void main(String[] args) { System.out.println(\"Java Snippet\"); } }", + "ordinal": 1 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [{ "id": 1, "name": "Java" }], "modifiedAt": "2024-07-05 12:34" @@ -215,7 +402,14 @@ "id": 20, "title": "title20", "description": "description20", - "snippets": [], + "snippets": [ + { + "id": 29, + "filename": "python_example.py", + "content": "print('Python example')", + "ordinal": 1 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [ { "id": 10, "name": "Python" }, @@ -227,7 +421,14 @@ "id": 21, "title": "title21", "description": "description21", - "snippets": [], + "snippets": [ + { + "id": 30, + "filename": "log.js", + "content": "console.log('Log snippet');", + "ordinal": 1 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [], "modifiedAt": "2024-07-03 12:34" @@ -236,7 +437,14 @@ "id": 22, "title": "title22", "description": "description22", - "snippets": [], + "snippets": [ + { + "id": 31, + "filename": "react_component.js", + "content": "import React from 'react';\n\nconst Component = () =>
React Component
;\n\nexport default Component;", + "ordinal": 1 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [ { "id": 4, "name": "React" }, @@ -248,7 +456,14 @@ "id": 23, "title": "title23", "description": "description23", - "snippets": [], + "snippets": [ + { + "id": 32, + "filename": "snippet.js", + "content": "console.log('Snippet');", + "ordinal": 1 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [], "modifiedAt": "2024-07-01 12:34" @@ -257,7 +472,14 @@ "id": 24, "title": "title24", "description": "description24", - "snippets": [], + "snippets": [ + { + "id": 33, + "filename": "frontend_snippet.js", + "content": "console.log('Frontend snippet');", + "ordinal": 1 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [ { "id": 1, "name": "Java" }, @@ -269,7 +491,14 @@ "id": 25, "title": "title25", "description": "description25", - "snippets": [], + "snippets": [ + { + "id": 34, + "filename": "python_code.py", + "content": "print('Python code')", + "ordinal": 1 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [ { "id": 10, "name": "Python" }, @@ -281,7 +510,14 @@ "id": 26, "title": "title26", "description": "description26", - "snippets": [], + "snippets": [ + { + "id": 35, + "filename": "backend_code.js", + "content": "console.log('Backend code');", + "ordinal": 1 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [ { "id": 3, "name": "JavaScript" }, @@ -293,7 +529,14 @@ "id": 27, "title": "title27", "description": "description27", - "snippets": [], + "snippets": [ + { + "id": 36, + "filename": "react_code.js", + "content": "console.log('React code');", + "ordinal": 1 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [ { "id": 4, "name": "React" }, @@ -305,7 +548,14 @@ "id": 28, "title": "title28", "description": "description28", - "snippets": [], + "snippets": [ + { + "id": 37, + "filename": "style_snippet.js", + "content": "console.log('Style snippet');", + "ordinal": 1 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [{ "id": 7, "name": "Styling" }], "modifiedAt": "2024-07-07 12:34" @@ -314,7 +564,14 @@ "id": 29, "title": "title29", "description": "description29", - "snippets": [], + "snippets": [ + { + "id": 38, + "filename": "frontend_code.js", + "content": "console.log('Frontend code');", + "ordinal": 1 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [ { "id": 1, "name": "Java" }, @@ -326,7 +583,14 @@ "id": 30, "title": "title30", "description": "description30", - "snippets": [], + "snippets": [ + { + "id": 39, + "filename": "python_example2.py", + "content": "print('Another Python example')", + "ordinal": 1 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [{ "id": 10, "name": "Python" }], "modifiedAt": "2024-07-05 12:34" @@ -335,7 +599,14 @@ "id": 31, "title": "title31", "description": "description31", - "snippets": [], + "snippets": [ + { + "id": 40, + "filename": "javascript_example.js", + "content": "console.log('JavaScript example');", + "ordinal": 1 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [{ "id": 3, "name": "JavaScript" }], "modifiedAt": "2024-07-04 12:34" @@ -344,7 +615,14 @@ "id": 32, "title": "title32", "description": "description32", - "snippets": [], + "snippets": [ + { + "id": 41, + "filename": "react_component2.js", + "content": "const Component = () =>
Another React Component
;\n\nexport default Component;", + "ordinal": 1 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [ { "id": 4, "name": "React" }, @@ -356,7 +634,14 @@ "id": 33, "title": "title33", "description": "description33", - "snippets": [], + "snippets": [ + { + "id": 42, + "filename": "empty_snippet.js", + "content": "console.log('Empty snippet');", + "ordinal": 1 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [], "modifiedAt": "2024-07-02 12:34" @@ -365,7 +650,14 @@ "id": 34, "title": "title34", "description": "description34", - "snippets": [], + "snippets": [ + { + "id": 43, + "filename": "frontend_snippet2.js", + "content": "console.log('Another frontend snippet');", + "ordinal": 1 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [ { "id": 1, "name": "Java" }, @@ -377,7 +669,14 @@ "id": 35, "title": "title35", "description": "description35", - "snippets": [], + "snippets": [ + { + "id": 44, + "filename": "python_code2.py", + "content": "print('Another Python code')", + "ordinal": 1 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [{ "id": 10, "name": "Python" }], "modifiedAt": "2024-07-11 12:34" @@ -386,7 +685,14 @@ "id": 36, "title": "title36", "description": "description36", - "snippets": [], + "snippets": [ + { + "id": 45, + "filename": "javascript_code.js", + "content": "console.log('JavaScript code');", + "ordinal": 1 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [ { "id": 3, "name": "JavaScript" }, @@ -398,7 +704,20 @@ "id": 37, "title": "title37", "description": "description37", - "snippets": [], + "snippets": [ + { + "id": 46, + "filename": "react_styling.js", + "content": "console.log('React styling');", + "ordinal": 1 + }, + { + "id": 47, + "filename": "css_styling.js", + "content": "console.log('CSS styling');", + "ordinal": 2 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [ { "id": 4, "name": "React" }, @@ -411,7 +730,14 @@ "id": 38, "title": "title38", "description": "description38", - "snippets": [], + "snippets": [ + { + "id": 48, + "filename": "style_example.js", + "content": "console.log('Style example');", + "ordinal": 1 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [{ "id": 7, "name": "Styling" }], "modifiedAt": "2024-07-08 12:34" @@ -420,7 +746,14 @@ "id": 39, "title": "title39", "description": "description39", - "snippets": [], + "snippets": [ + { + "id": 49, + "filename": "empty.js", + "content": "console.log('Empty file');", + "ordinal": 1 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [], "modifiedAt": "2024-07-07 12:34" @@ -429,7 +762,14 @@ "id": 40, "title": "title40", "description": "description40", - "snippets": [], + "snippets": [ + { + "id": 50, + "filename": "python_log.py", + "content": "print('Python log')", + "ordinal": 1 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [ { "id": 10, "name": "Python" }, @@ -441,7 +781,14 @@ "id": 41, "title": "title41", "description": "description41", - "snippets": [], + "snippets": [ + { + "id": 51, + "filename": "empty_file.js", + "content": "console.log('Empty file content');", + "ordinal": 1 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [], "modifiedAt": "2024-07-05 12:34" @@ -450,7 +797,14 @@ "id": 42, "title": "title42", "description": "description42", - "snippets": [], + "snippets": [ + { + "id": 52, + "filename": "react_css.js", + "content": "console.log('React and CSS');", + "ordinal": 1 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [ { "id": 4, "name": "React" }, @@ -462,7 +816,14 @@ "id": 43, "title": "title43", "description": "description43", - "snippets": [], + "snippets": [ + { + "id": 53, + "filename": "oop_snippet.js", + "content": "class OOPSnippet { constructor() { console.log('OOP Snippet'); } }", + "ordinal": 1 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [ { "id": 7, "name": "Styling" }, @@ -474,7 +835,14 @@ "id": 44, "title": "title44", "description": "description44", - "snippets": [], + "snippets": [ + { + "id": 54, + "filename": "log_file.js", + "content": "console.log('Log file');", + "ordinal": 1 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [], "modifiedAt": "2024-07-02 12:34" @@ -483,7 +851,14 @@ "id": 45, "title": "title45", "description": "description45", - "snippets": [], + "snippets": [ + { + "id": 55, + "filename": "python_log2.py", + "content": "print('Another Python log')", + "ordinal": 1 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [{ "id": 10, "name": "Python" }], "modifiedAt": "2024-07-01 12:34" @@ -492,7 +867,14 @@ "id": 46, "title": "title46", "description": "description46", - "snippets": [], + "snippets": [ + { + "id": 56, + "filename": "backend_snippet.js", + "content": "console.log('Backend snippet');", + "ordinal": 1 + } + ], "category": { "id": 3, "name": "CategoryID3" }, "tags": [ { "id": 3, "name": "JavaScript" }, @@ -505,7 +887,14 @@ "id": 47, "title": "title47", "description": "description47", - "snippets": [], + "snippets": [ + { + "id": 57, + "filename": "react_snippet.js", + "content": "console.log('React snippet');", + "ordinal": 1 + } + ], "category": { "id": 4, "name": "CategoryID4" }, "tags": [{ "id": 4, "name": "React" }], "modifiedAt": "2024-07-10 12:34" @@ -514,7 +903,14 @@ "id": 48, "title": "title48", "description": "description48", - "snippets": [], + "snippets": [ + { + "id": 58, + "filename": "styling_snippet.js", + "content": "console.log('Styling snippet');", + "ordinal": 1 + } + ], "category": { "id": 2, "name": "CategoryID2" }, "tags": [ { "id": 7, "name": "Styling" }, From 4ec07f133efc8fc391e91adfda456aafb7909289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9B=94=ED=95=98?= Date: Wed, 7 Aug 2024 14:37:36 +0900 Subject: [PATCH 04/16] =?UTF-8?q?feat(src):=20'=EB=82=B4=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF'=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/templates.ts | 25 +++++++++++++------ frontend/src/hooks/index.ts | 1 + frontend/src/hooks/utils/useDebounce.ts | 17 +++++++++++++ frontend/src/mocks/handlers.ts | 14 +++++++++-- .../pages/MyTemplatesPage/MyTemplatePage.tsx | 23 +++++++++++++++-- .../queries/template/useTemplateListQuery.ts | 7 +++--- frontend/src/types/api.ts | 8 ++++++ frontend/src/types/index.ts | 1 + 8 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 frontend/src/hooks/utils/useDebounce.ts diff --git a/frontend/src/api/templates.ts b/frontend/src/api/templates.ts index 81c3767ce..3a34e7ca2 100644 --- a/frontend/src/api/templates.ts +++ b/frontend/src/api/templates.ts @@ -1,24 +1,33 @@ -import type { Template, TemplateEditRequest, TemplateListResponse, TemplateUploadRequest } from '@/types'; +import type { + Template, + TemplateEditRequest, + TemplateListResponse, + TemplateUploadRequest, + TemplateListRequest, +} from '@/types'; import { customFetch } from './customFetch'; const API_URL = process.env.REACT_APP_API_URL; export const TEMPLATE_API_URL = `${API_URL}/templates`; -export const getTemplateList = async ( - categoryId?: number, - tagId?: number, - page: number = 1, - pageSize: number = 20, -): Promise => { +export const getTemplateList = async ({ + categoryId, + tagId, + page = 1, + pageSize = 20, + keyword = '', +}: TemplateListRequest): Promise => { const url = new URL(TEMPLATE_API_URL); + url.searchParams.append('keyword', keyword); + if (categoryId) { url.searchParams.append('categoryId', categoryId.toString()); } if (tagId) { - url.searchParams.append('tags', tagId.toString()); + url.searchParams.append('tagId', tagId.toString()); } url.searchParams.append('pageNumber', page.toString()); diff --git a/frontend/src/hooks/index.ts b/frontend/src/hooks/index.ts index c1250a3ca..f748a4c56 100644 --- a/frontend/src/hooks/index.ts +++ b/frontend/src/hooks/index.ts @@ -1 +1,2 @@ export { useWindowWidth } from './useWindowWidth'; +export { useDebounce } from './utils/useDebounce'; diff --git a/frontend/src/hooks/utils/useDebounce.ts b/frontend/src/hooks/utils/useDebounce.ts new file mode 100644 index 000000000..576c6688f --- /dev/null +++ b/frontend/src/hooks/utils/useDebounce.ts @@ -0,0 +1,17 @@ +import { useState, useEffect } from 'react'; + +export const useDebounce = (value: string, delay: number) => { + const [debouncedValue, setDebouncedValue] = useState(value); + + useEffect(() => { + const handler = setTimeout(() => { + setDebouncedValue(value); + }, delay); + + return () => { + clearTimeout(handler); + }; + }, [value, delay]); + + return debouncedValue; +}; diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index fc4f226af..521e8050d 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -17,13 +17,23 @@ import mockTemplateList from './templateList.json'; export const templateHandlers = [ http.get(`${TEMPLATE_API_URL}`, (req) => { const url = new URL(req.request.url); - const categoryId = url.searchParams.get('category'); - const tagId = url.searchParams.get('tag'); + const keyword = url.searchParams.get('keyword'); + const categoryId = url.searchParams.get('categoryId'); + const tagId = url.searchParams.get('tagId'); const page = parseInt(url.searchParams.get('page') || '1', 10); const pageSize = parseInt(url.searchParams.get('pageSize') || '20', 10); let filteredTemplates = mockTemplateList.templates; + if (keyword) { + filteredTemplates = filteredTemplates.filter( + (template) => + template.title.includes(keyword) || + template.description.includes(keyword) || + template.snippets.some((snippet) => snippet.content.includes(keyword)), + ); + } + if (categoryId) { filteredTemplates = filteredTemplates.filter((template) => template.category.id.toString() === categoryId); } diff --git a/frontend/src/pages/MyTemplatesPage/MyTemplatePage.tsx b/frontend/src/pages/MyTemplatesPage/MyTemplatePage.tsx index e45bd79c6..b05bafa09 100644 --- a/frontend/src/pages/MyTemplatesPage/MyTemplatePage.tsx +++ b/frontend/src/pages/MyTemplatesPage/MyTemplatePage.tsx @@ -2,7 +2,7 @@ import { useState, useCallback } from 'react'; import { searchIcon } from '@/assets/images'; import { CategoryMenu, Flex, Heading, Input, TemplateGrid, PagingButton } from '@/components'; -import { useWindowWidth } from '@/hooks'; +import { useWindowWidth, useDebounce } from '@/hooks'; import { useCategoryListQuery } from '@/queries/category'; import { useTemplateListQuery } from '@/queries/template'; import { theme } from '@/style/theme'; @@ -16,11 +16,15 @@ const MyTemplatePage = () => { const [selectedCategoryId, setSelectedCategoryId] = useState(undefined); const [page, setPage] = useState(1); const [pageSize] = useState(20); + const [keyword, setKeyword] = useState(''); + + const debouncedKeyword = useDebounce(keyword, 250); const { data: templateData } = useTemplateListQuery({ categoryId: selectedCategoryId, page, pageSize, + keyword: debouncedKeyword, }); const { data: categoryData } = useCategoryListQuery(); @@ -30,6 +34,16 @@ const MyTemplatePage = () => { setPage(1); }, []); + const handleSearchChange = (e: React.ChangeEvent) => { + setKeyword(e.target.value); + }; + + const handleSearchSubmit = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + setPage(1); + } + }; + const templates = templateData?.templates || []; const categories = categoryData?.categories || []; const totalPages = templateData?.totalPages || 0; @@ -60,7 +74,12 @@ const MyTemplatePage = () => { - + diff --git a/frontend/src/queries/template/useTemplateListQuery.ts b/frontend/src/queries/template/useTemplateListQuery.ts index 375b4f4b1..275105f68 100644 --- a/frontend/src/queries/template/useTemplateListQuery.ts +++ b/frontend/src/queries/template/useTemplateListQuery.ts @@ -8,11 +8,12 @@ interface Props { tagId?: number; page?: number; pageSize?: number; + keyword?: string; } -export const useTemplateListQuery = ({ categoryId, tagId, page = 1, pageSize = 20 }: Props) => +export const useTemplateListQuery = ({ categoryId, tagId, page = 1, pageSize = 20, keyword }: Props) => useQuery({ - queryKey: [QUERY_KEY.TEMPLATE_LIST, categoryId, tagId, page, pageSize], - queryFn: () => getTemplateList(categoryId, tagId, page, pageSize), + queryKey: [QUERY_KEY.TEMPLATE_LIST, categoryId, tagId, page, pageSize, keyword], + queryFn: () => getTemplateList({ categoryId, tagId, page, pageSize, keyword }), placeholderData: keepPreviousData, }); diff --git a/frontend/src/types/api.ts b/frontend/src/types/api.ts index 5469b0d8b..15eb106be 100644 --- a/frontend/src/types/api.ts +++ b/frontend/src/types/api.ts @@ -32,3 +32,11 @@ export interface CategoryListResponse { export interface CategoryRequest { name: string; } + +export interface TemplateListRequest { + categoryId?: number; + tagId?: number; + page?: number; + pageSize?: number; + keyword?: string; +} diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index 166f1895f..20297ed4f 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -3,6 +3,7 @@ export type { TemplateEditRequest, TemplateListResponse, TemplateUploadRequest, + TemplateListRequest, CategoryRequest, CategoryListResponse, } from './api'; From 4939afd20ecabcc5f73fc6ae6f9d91b5895181de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9B=94=ED=95=98?= Date: Wed, 7 Aug 2024 15:27:42 +0900 Subject: [PATCH 05/16] =?UTF-8?q?refactor(src):=20pageSize=20=EC=83=81?= =?UTF-8?q?=EC=88=98=ED=99=94=20=EB=B0=8F=20=EA=B2=80=EC=83=89=EC=97=90?= =?UTF-8?q?=EC=84=9C=20'useInput'=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/index.ts | 1 + frontend/src/api/templates.ts | 4 +++- frontend/src/pages/MyTemplatesPage/MyTemplatePage.tsx | 11 +++-------- frontend/src/queries/template/useTemplateListQuery.ts | 4 ++-- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index 8654cf40f..c19d2c666 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -3,6 +3,7 @@ export { customFetch } from './customFetch'; export { QUERY_KEY } from './queryKeys'; export { TEMPLATE_API_URL, + PAGE_SIZE, getTemplateList, getTemplate, postTemplate, diff --git a/frontend/src/api/templates.ts b/frontend/src/api/templates.ts index 3a34e7ca2..0bc4122c9 100644 --- a/frontend/src/api/templates.ts +++ b/frontend/src/api/templates.ts @@ -11,11 +11,13 @@ const API_URL = process.env.REACT_APP_API_URL; export const TEMPLATE_API_URL = `${API_URL}/templates`; +export const PAGE_SIZE = 20; + export const getTemplateList = async ({ categoryId, tagId, page = 1, - pageSize = 20, + pageSize = PAGE_SIZE, keyword = '', }: TemplateListRequest): Promise => { const url = new URL(TEMPLATE_API_URL); diff --git a/frontend/src/pages/MyTemplatesPage/MyTemplatePage.tsx b/frontend/src/pages/MyTemplatesPage/MyTemplatePage.tsx index b05bafa09..6979a81b8 100644 --- a/frontend/src/pages/MyTemplatesPage/MyTemplatePage.tsx +++ b/frontend/src/pages/MyTemplatesPage/MyTemplatePage.tsx @@ -3,6 +3,7 @@ import { useState, useCallback } from 'react'; import { searchIcon } from '@/assets/images'; import { CategoryMenu, Flex, Heading, Input, TemplateGrid, PagingButton } from '@/components'; import { useWindowWidth, useDebounce } from '@/hooks'; +import { useInput } from '@/hooks/utils/useInput'; import { useCategoryListQuery } from '@/queries/category'; import { useTemplateListQuery } from '@/queries/template'; import { theme } from '@/style/theme'; @@ -15,15 +16,13 @@ const MyTemplatePage = () => { const windowWidth = useWindowWidth(); const [selectedCategoryId, setSelectedCategoryId] = useState(undefined); const [page, setPage] = useState(1); - const [pageSize] = useState(20); - const [keyword, setKeyword] = useState(''); + const [keyword, handleKeywordChange] = useInput(''); const debouncedKeyword = useDebounce(keyword, 250); const { data: templateData } = useTemplateListQuery({ categoryId: selectedCategoryId, page, - pageSize, keyword: debouncedKeyword, }); const { data: categoryData } = useCategoryListQuery(); @@ -34,10 +33,6 @@ const MyTemplatePage = () => { setPage(1); }, []); - const handleSearchChange = (e: React.ChangeEvent) => { - setKeyword(e.target.value); - }; - const handleSearchSubmit = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { setPage(1); @@ -77,7 +72,7 @@ const MyTemplatePage = () => { diff --git a/frontend/src/queries/template/useTemplateListQuery.ts b/frontend/src/queries/template/useTemplateListQuery.ts index 275105f68..1bab7f446 100644 --- a/frontend/src/queries/template/useTemplateListQuery.ts +++ b/frontend/src/queries/template/useTemplateListQuery.ts @@ -1,6 +1,6 @@ import { keepPreviousData, useQuery } from '@tanstack/react-query'; -import { QUERY_KEY, getTemplateList } from '@/api'; +import { PAGE_SIZE, QUERY_KEY, getTemplateList } from '@/api'; import type { TemplateListResponse } from '@/types'; interface Props { @@ -11,7 +11,7 @@ interface Props { keyword?: string; } -export const useTemplateListQuery = ({ categoryId, tagId, page = 1, pageSize = 20, keyword }: Props) => +export const useTemplateListQuery = ({ categoryId, tagId, page = 1, pageSize = PAGE_SIZE, keyword }: Props) => useQuery({ queryKey: [QUERY_KEY.TEMPLATE_LIST, categoryId, tagId, page, pageSize, keyword], queryFn: () => getTemplateList({ categoryId, tagId, page, pageSize, keyword }), From a7db672e2f1f0c723794696a4f43fc63e78af5bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9B=94=ED=95=98?= Date: Wed, 7 Aug 2024 15:35:56 +0900 Subject: [PATCH 06/16] =?UTF-8?q?refactor(src):=20GET=20templateList=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EC=8B=9C=20=ED=83=9C=EA=B7=B8=EC=9D=98=20?= =?UTF-8?q?=EB=B0=B0=EC=97=B4=EC=9D=84=20=EC=A0=84=EB=8B=AC=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/templates.ts | 6 +++--- frontend/src/mocks/handlers.ts | 6 +++--- frontend/src/queries/template/useTemplateListQuery.ts | 8 ++++---- frontend/src/types/api.ts | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/frontend/src/api/templates.ts b/frontend/src/api/templates.ts index 0bc4122c9..eb9be0254 100644 --- a/frontend/src/api/templates.ts +++ b/frontend/src/api/templates.ts @@ -15,7 +15,7 @@ export const PAGE_SIZE = 20; export const getTemplateList = async ({ categoryId, - tagId, + tagIds, page = 1, pageSize = PAGE_SIZE, keyword = '', @@ -28,8 +28,8 @@ export const getTemplateList = async ({ url.searchParams.append('categoryId', categoryId.toString()); } - if (tagId) { - url.searchParams.append('tagId', tagId.toString()); + if (tagIds) { + url.searchParams.append('tagIds', tagIds.toString()); } url.searchParams.append('pageNumber', page.toString()); diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 521e8050d..c94b38b66 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -19,7 +19,7 @@ export const templateHandlers = [ const url = new URL(req.request.url); const keyword = url.searchParams.get('keyword'); const categoryId = url.searchParams.get('categoryId'); - const tagId = url.searchParams.get('tagId'); + const tagIds = url.searchParams.get('tagIds'); const page = parseInt(url.searchParams.get('page') || '1', 10); const pageSize = parseInt(url.searchParams.get('pageSize') || '20', 10); @@ -38,9 +38,9 @@ export const templateHandlers = [ filteredTemplates = filteredTemplates.filter((template) => template.category.id.toString() === categoryId); } - if (tagId) { + if (tagIds) { filteredTemplates = filteredTemplates.filter((template) => - template.tags.some((tag) => tag.id.toString() === tagId), + template.tags.some((tag) => tagIds.split(',').includes(tag.id.toString())), ); } diff --git a/frontend/src/queries/template/useTemplateListQuery.ts b/frontend/src/queries/template/useTemplateListQuery.ts index 1bab7f446..4bb43b780 100644 --- a/frontend/src/queries/template/useTemplateListQuery.ts +++ b/frontend/src/queries/template/useTemplateListQuery.ts @@ -5,15 +5,15 @@ import type { TemplateListResponse } from '@/types'; interface Props { categoryId?: number; - tagId?: number; + tagIds?: number[]; page?: number; pageSize?: number; keyword?: string; } -export const useTemplateListQuery = ({ categoryId, tagId, page = 1, pageSize = PAGE_SIZE, keyword }: Props) => +export const useTemplateListQuery = ({ categoryId, tagIds, page = 1, pageSize = PAGE_SIZE, keyword }: Props) => useQuery({ - queryKey: [QUERY_KEY.TEMPLATE_LIST, categoryId, tagId, page, pageSize, keyword], - queryFn: () => getTemplateList({ categoryId, tagId, page, pageSize, keyword }), + queryKey: [QUERY_KEY.TEMPLATE_LIST, categoryId, tagIds, page, pageSize, keyword], + queryFn: () => getTemplateList({ categoryId, tagIds, page, pageSize, keyword }), placeholderData: keepPreviousData, }); diff --git a/frontend/src/types/api.ts b/frontend/src/types/api.ts index 15eb106be..b4aa7e888 100644 --- a/frontend/src/types/api.ts +++ b/frontend/src/types/api.ts @@ -35,7 +35,7 @@ export interface CategoryRequest { export interface TemplateListRequest { categoryId?: number; - tagId?: number; + tagIds?: number[]; page?: number; pageSize?: number; keyword?: string; From a48e5c847debb759828d81b8176a55265fde8e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9B=94=ED=95=98?= Date: Wed, 7 Aug 2024 15:37:05 +0900 Subject: [PATCH 07/16] =?UTF-8?q?refactor(MyTemplatePage):=20=EB=82=B4=20?= =?UTF-8?q?=ED=85=9C=ED=94=8C=EB=A6=BF=20=EA=B2=80=EC=83=89=20=EB=94=94?= =?UTF-8?q?=EB=B0=94=EC=9A=B4=EC=8A=A4=20=EC=8B=9C=EA=B0=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20(250ms=20>=20300ms)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/MyTemplatesPage/MyTemplatePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/pages/MyTemplatesPage/MyTemplatePage.tsx b/frontend/src/pages/MyTemplatesPage/MyTemplatePage.tsx index 6979a81b8..7de4a12e6 100644 --- a/frontend/src/pages/MyTemplatesPage/MyTemplatePage.tsx +++ b/frontend/src/pages/MyTemplatesPage/MyTemplatePage.tsx @@ -18,7 +18,7 @@ const MyTemplatePage = () => { const [page, setPage] = useState(1); const [keyword, handleKeywordChange] = useInput(''); - const debouncedKeyword = useDebounce(keyword, 250); + const debouncedKeyword = useDebounce(keyword, 300); const { data: templateData } = useTemplateListQuery({ categoryId: selectedCategoryId, From 9353d208877737c49233e03b5479206785f45a8f Mon Sep 17 00:00:00 2001 From: jayming66 Date: Wed, 7 Aug 2024 15:55:08 +0900 Subject: [PATCH 08/16] =?UTF-8?q?chore:=20gitignore=EC=97=90=20SLL=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=EC=84=9C=20=EA=B4=80=EB=A0=A8=20=ED=82=A4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index f66c490a5..7d19c014c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,8 @@ ### Environment Variable ### .env + +*.crt +*.csr +*.key +*.pem From 3783fd5fc21a2f248584ff1523e563dc7218a05b Mon Sep 17 00:00:00 2001 From: jayming66 Date: Wed, 7 Aug 2024 17:03:47 +0900 Subject: [PATCH 09/16] =?UTF-8?q?fix(authentication):=20useCheckLoginState?= =?UTF-8?q?=20=ED=9B=85=EC=97=90=EC=84=9C=20=ED=86=A0=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/hooks/authentication/useCheckLoginState.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/src/hooks/authentication/useCheckLoginState.ts b/frontend/src/hooks/authentication/useCheckLoginState.ts index eee293076..8ab2a5545 100644 --- a/frontend/src/hooks/authentication/useCheckLoginState.ts +++ b/frontend/src/hooks/authentication/useCheckLoginState.ts @@ -18,8 +18,6 @@ export const useCheckLoginState = () => { useEffect(() => { if (isError) { - infoAlert('로그인을 해주세요'); - handleLoginNavigate(); handleLoginState(false); } From c364298574a87d96a596c0f905f273179b8166ac Mon Sep 17 00:00:00 2001 From: jayming66 Date: Wed, 7 Aug 2024 17:05:45 +0900 Subject: [PATCH 10/16] =?UTF-8?q?refactor(Header):=20Header=EC=97=90?= =?UTF-8?q?=EC=84=9C=EC=9D=98=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=B2=B4=ED=81=AC=20=ED=9B=85=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Header/Header.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontend/src/components/Header/Header.tsx b/frontend/src/components/Header/Header.tsx index ed0b79a44..3e6f1d52f 100644 --- a/frontend/src/components/Header/Header.tsx +++ b/frontend/src/components/Header/Header.tsx @@ -2,7 +2,6 @@ import { Link } from 'react-router-dom'; import { logoIcon, newTemplateIcon, userMenuIcon } from '@/assets/images'; import { Button, Flex, Heading, Text } from '@/components'; -import { useCheckLoginState } from '@/hooks/authentication'; import { useAuth } from '@/hooks/authentication/useAuth'; import { useLogoutMutation } from '@/queries/authentication/useLogoutMutation'; import { theme } from '../../style/theme'; @@ -11,8 +10,6 @@ import * as S from './Header.style'; const Header = ({ headerRef }: { headerRef: React.RefObject }) => { const { isLogin } = useAuth(); - useCheckLoginState(); - return ( From 7d37f43bb4f605f5c149c0693a9761334c63d065 Mon Sep 17 00:00:00 2001 From: jayming66 Date: Wed, 7 Aug 2024 17:07:13 +0900 Subject: [PATCH 11/16] =?UTF-8?q?refactor(authentication):=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EC=84=B1=EA=B3=B5=20=EC=8B=9C,=20useAuth?= =?UTF-8?q?=EC=9D=98=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=83=81=ED=83=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 --- frontend/src/hooks/authentication/useLoginForm.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/src/hooks/authentication/useLoginForm.ts b/frontend/src/hooks/authentication/useLoginForm.ts index b2ba1aec0..be2b964e4 100644 --- a/frontend/src/hooks/authentication/useLoginForm.ts +++ b/frontend/src/hooks/authentication/useLoginForm.ts @@ -5,12 +5,15 @@ import { postLogin } from '@/api/authentication'; import { ToastContext } from '@/context/ToastContext'; import { useInputWithValidate } from '../useInputWithValidate'; import useCustomContext from '../utils/useCustomContext'; +import { useAuth } from './useAuth'; import { validateEmail, validatePassword } from './validates'; export const useLoginForm = () => { const navigate = useNavigate(); const { failAlert, successAlert } = useCustomContext(ToastContext); + const { handleLoginState } = useAuth(); + const { value: email, errorMessage: emailError, @@ -38,6 +41,7 @@ export const useLoginForm = () => { return; } + handleLoginState(true); navigate('/'); successAlert('로그인 성공!'); } From e8643766bc525d4f17e7308f6048634438a5be34 Mon Sep 17 00:00:00 2001 From: jayming66 Date: Wed, 7 Aug 2024 17:07:53 +0900 Subject: [PATCH 12/16] =?UTF-8?q?feat(routes):=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=EC=97=90=20AuthGuard,=20GuestGuard=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/routes/AuthGuard.tsx | 25 +++++++++++++++++++++++ frontend/src/routes/GuestGuard.tsx | 25 +++++++++++++++++++++++ frontend/src/routes/router.tsx | 32 +++++++++++++++++++++++++----- 3 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 frontend/src/routes/AuthGuard.tsx create mode 100644 frontend/src/routes/GuestGuard.tsx diff --git a/frontend/src/routes/AuthGuard.tsx b/frontend/src/routes/AuthGuard.tsx new file mode 100644 index 000000000..9d417bd97 --- /dev/null +++ b/frontend/src/routes/AuthGuard.tsx @@ -0,0 +1,25 @@ +import { ReactNode } from 'react'; +import { Navigate } from 'react-router-dom'; + +import { ToastContext } from '@/context/ToastContext'; +import { useAuth } from '@/hooks/authentication/useAuth'; +import useCustomContext from '@/hooks/utils/useCustomContext'; + +type AuthGuardProps = { + children: ReactNode; +}; + +const AuthGuard = ({ children }: AuthGuardProps) => { + const { isLogin } = useAuth(); + const { infoAlert } = useCustomContext(ToastContext); + + if (isLogin) { + infoAlert('이미 로그인된 사용자입니다.'); + + return ; + } + + return children; +}; + +export default AuthGuard; diff --git a/frontend/src/routes/GuestGuard.tsx b/frontend/src/routes/GuestGuard.tsx new file mode 100644 index 000000000..787215baa --- /dev/null +++ b/frontend/src/routes/GuestGuard.tsx @@ -0,0 +1,25 @@ +import { ReactNode } from 'react'; +import { Navigate } from 'react-router-dom'; + +import { ToastContext } from '@/context/ToastContext'; +import { useAuth } from '@/hooks/authentication/useAuth'; +import useCustomContext from '@/hooks/utils/useCustomContext'; + +type GuestGuardProps = { + children: ReactNode; +}; + +const GuestGuard = ({ children }: GuestGuardProps) => { + const { isLogin } = useAuth(); + const { infoAlert } = useCustomContext(ToastContext); + + if (!isLogin) { + infoAlert('로그인을 해주세요.'); + + return ; + } + + return children; +}; + +export default GuestGuard; diff --git a/frontend/src/routes/router.tsx b/frontend/src/routes/router.tsx index 0ad118ecb..6477522cb 100644 --- a/frontend/src/routes/router.tsx +++ b/frontend/src/routes/router.tsx @@ -2,6 +2,8 @@ import { createBrowserRouter } from 'react-router-dom'; import { Layout } from '@/components'; import { TemplatePage, MyTemplatePage, TemplateUploadPage, SignupPage, LoginPage } from '@/pages'; +import AuthGuard from './AuthGuard'; +import GuestGuard from './GuestGuard'; const router = createBrowserRouter([ { @@ -9,23 +11,43 @@ const router = createBrowserRouter([ children: [ { path: '/', - element: , + element: ( + + , + + ), }, { path: 'templates/:id', - element: , + element: ( + + + + ), }, { path: 'templates/upload', - element: , + element: ( + + + + ), }, { path: 'signup', - element: , + element: ( + + + + ), }, { path: 'login', - element: , + element: ( + + , + + ), }, ], }, From 8c3c9f5e47a6abbb71b8a7166753ec7e483aecd1 Mon Sep 17 00:00:00 2001 From: jayming66 Date: Wed, 7 Aug 2024 17:38:57 +0900 Subject: [PATCH 13/16] =?UTF-8?q?feat(Header):=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=B2=84=ED=8A=BC=20->=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=95=84=EC=9B=83=20=EB=B2=84=ED=8A=BC?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EA=B5=90=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Header/Header.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/Header/Header.tsx b/frontend/src/components/Header/Header.tsx index 3e6f1d52f..6f885e7e5 100644 --- a/frontend/src/components/Header/Header.tsx +++ b/frontend/src/components/Header/Header.tsx @@ -1,6 +1,6 @@ import { Link } from 'react-router-dom'; -import { logoIcon, newTemplateIcon, userMenuIcon } from '@/assets/images'; +import { logoIcon, newTemplateIcon } from '@/assets/images'; import { Button, Flex, Heading, Text } from '@/components'; import { useAuth } from '@/hooks/authentication/useAuth'; import { useLogoutMutation } from '@/queries/authentication/useLogoutMutation'; @@ -25,7 +25,7 @@ const Header = ({ headerRef }: { headerRef: React.RefObject }) = 새 템플릿 - {isLogin ? : } + {isLogin ? : } @@ -51,7 +51,7 @@ const NavOption = ({ route, name }: { route: string; name: string }) => ( ); -const UserMenuButton = () => { +const LogoutButton = () => { const { mutateAsync } = useLogoutMutation(); const handleLogoutButton = async () => { @@ -59,9 +59,9 @@ const UserMenuButton = () => { }; return ( - - 사용자 메뉴 - + ); }; From aaea1629a3c2c6412cdff4d293fe40c1f734cf89 Mon Sep 17 00:00:00 2001 From: jayming66 Date: Wed, 7 Aug 2024 17:39:28 +0900 Subject: [PATCH 14/16] =?UTF-8?q?refactor(workflows):=20frontend=5Fcd=20-?= =?UTF-8?q?=20Sentry=20=ED=99=98=EA=B2=BD=EB=B3=80=EC=88=98=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/frontend_cd.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/frontend_cd.yml b/.github/workflows/frontend_cd.yml index 5571b95cd..652a80e76 100644 --- a/.github/workflows/frontend_cd.yml +++ b/.github/workflows/frontend_cd.yml @@ -23,10 +23,16 @@ jobs: run: | echo "REACT_APP_API_URL=${{ secrets.REACT_APP_API_URL }}" > ${{ env.frontend-directory }}/.env.production echo "REACT_APP_BASE_URL=${{ secrets.REACT_APP_BASE_URL }}" >> ${{ env.frontend-directory }}/.env.production + echo "SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" >> ${{ env.frontend-directory }}/.env.production + echo "SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> ${{ env.frontend-directory }}/.env.production + echo "SENTRY_DSN=${{ secrets.SENTRY_AUTH_TOKEN }}" >> ${{ env.frontend-directory }}/.env.sentry-build-plugin - name: Set environment file permissions run: chmod 644 ${{ env.frontend-directory }}/.env.production + - name: Set Sentry environment file permissions + run: chmod 644 ${{ env.frontend-directory }}/.env.sentry-build-plugin + - name: Install Dependencies run: npm install working-directory: ${{ env.frontend-directory }} From 5aaafd10cbe013b06bf56a4fee34b1f7410dfeed Mon Sep 17 00:00:00 2001 From: jayming66 Date: Wed, 7 Aug 2024 17:50:28 +0900 Subject: [PATCH 15/16] =?UTF-8?q?design(LoginPage):=20'=EA=B3=84=EC=A0=95?= =?UTF-8?q?=EC=9D=B4=20=EC=97=86=EC=9C=BC=EC=8B=A0=EA=B0=80=EC=9A=94'=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=EC=9D=98=20align,=20size,=20gap=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 --- frontend/src/pages/LoginPage/LoginPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/LoginPage/LoginPage.tsx b/frontend/src/pages/LoginPage/LoginPage.tsx index 739eb0bd5..c0e16ec18 100644 --- a/frontend/src/pages/LoginPage/LoginPage.tsx +++ b/frontend/src/pages/LoginPage/LoginPage.tsx @@ -43,8 +43,8 @@ const LoginPage = () => { - - 계정이 없으신가요? + + 계정이 없으신가요? - - 이미 계정이 있으신가요? + + 이미 계정이 있으신가요?