diff --git a/frontend/package.json b/frontend/package.json index 6664f47..1fc22b5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,15 +17,18 @@ "prismjs": "^1.30.0", "quill": "^1.3.7", "quill-drag-and-drop-module": "^0.3.0", + "quill-image-resize": "^3.0.9", "quill-image-resize-module-react": "^3.0.0", "react": "^18.2.0", "react-bootstrap": "^2.10.9", "react-dom": "^18.2.0", "react-drag-drop-files": "^3.0.1", "react-quill-new": "^3.4.6", - "react-router-dom": "^7.5.0" + "react-router-dom": "^7.5.0", + "vite-plugin-node-polyfills": "^0.23.0" }, "devDependencies": { + "@ammarkhalidfarooq/quill-image-resize-module-react-fix-for-mobile": "^3.2.2", "@eslint/js": "^9.21.0", "@syncfusion/ej2-react-richtexteditor": "^29.1.37", "@tailwindcss/vite": "^4.1.3", diff --git a/frontend/src/pages/Home.jsx b/frontend/src/pages/Home.jsx index 1d6bce5..fb07cce 100644 --- a/frontend/src/pages/Home.jsx +++ b/frontend/src/pages/Home.jsx @@ -1,11 +1,67 @@ -import React from 'react'; +import React, {useEffect, useState} from 'react'; import {Button, Card, Col, Container, Row} from 'react-bootstrap'; import {Link, useNavigate} from 'react-router-dom'; import LogoLink from "../components/LogoLink.jsx"; +import api from "../api/axiosInstance.jsx"; const Home = () => { - const isLoggedIn = localStorage.getItem('user') !== null; + const [isLoggedIn, setIsLoggedIn] = useState(localStorage.getItem('user') !== null); const navigate = useNavigate(); + + // 쿠키에서 값을 가져오는 함수 + const getCookie = (name) => { + const value = `; ${document.cookie}`; + const parts = value.split(`; ${name}=`); + if (parts.length === 2) return parts.pop().split(';').shift(); + return null; + }; + + // 쿠키 삭제 함수 + const deleteCookie = (name) => { + document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`; + }; + + useEffect(() => { + // 쿠키에서 accessToken 확인 + const accessToken = getCookie('access'); + + if (accessToken) { + console.log('쿠키에서 accessToken을 찾았습니다.'); + + // Authorization 헤더에 토큰 추가 + api.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`; + localStorage.setItem('accessToken', `Bearer ${accessToken}`); + + // 사용자 정보 가져오기 + api.get('users') + .then(response => { + if (response.status === 200) { + console.log("성공적으로 데이터를 가져왔습니다."); + + // 사용자 정보 localStorage에 저장 + localStorage.setItem('user', JSON.stringify({ + id: response.data.id, + email: response.data.email, // 이메일 정보도 response에서 가져옴 + name: response.data.name, + nickname: response.data.nickname + })); + + // 로그인 상태 업데이트 + setIsLoggedIn(true); + + // 쿠키에서 accessToken 삭제 + deleteCookie('access'); + console.log('쿠키에서 accessToken을 삭제했습니다.'); + } + }) + .catch(error => { + console.error('사용자 정보를 가져오는 중 오류 발생:', error); + // 오류 발생 시에도 쿠키 삭제 + deleteCookie('access'); + }); + } + }, []); + return ( diff --git a/frontend/src/pages/Login.jsx b/frontend/src/pages/Login.jsx index 7fa6d79..5ccd7e6 100644 --- a/frontend/src/pages/Login.jsx +++ b/frontend/src/pages/Login.jsx @@ -42,7 +42,7 @@ const Login = () => { name: response.data.name, nickname: response.data.nickname })); - console.log('로그인 성공:'); + console.log('로그인 성공'); navigate('/'); } else { console.log(`오류 발생: ${response.status}`); @@ -52,11 +52,15 @@ const Login = () => { console.error('로그인 실패'); setShowError(true); } - setShowError(false); } setValidated(true); }; + // 카카오 로그인 버튼 클릭 시 리다이렉트 함수 + const handleKakaoLogin = () => { + window.location.href = 'http://localhost/api/oauth2/authorization/kakao'; + }; + return ( @@ -121,6 +125,16 @@ const Login = () => { 로그인 + +
비밀번호를 잊으셨나요?
diff --git a/frontend/src/pages/post/PostDetail.jsx b/frontend/src/pages/post/PostDetail.jsx index 24cdbd6..14ef7ec 100644 --- a/frontend/src/pages/post/PostDetail.jsx +++ b/frontend/src/pages/post/PostDetail.jsx @@ -231,6 +231,20 @@ const PostDetail = () => { } }; + // 게시글 삭제 핸들러 + const handleDelete = async () => { + if (window.confirm('정말로 이 게시글을 삭제하시겠습니까?')) { + try { + await api.delete(`/posts/${id}`); + alert('게시글이 삭제되었습니다.'); + navigate('/posts'); // 게시글 목록으로 이동 + } catch (err) { + console.error('게시글 삭제 중 오류 발생:', err); + alert('게시글 삭제에 실패했습니다.'); + } + } + }; + // 댓글 작성자인지 확인 const isCommentAuthor = (comment) => { return comment.author === nickname; @@ -269,13 +283,22 @@ const PostDetail = () => {
{isPostAuthor() && ( - + <> + + + )} 목록으로
diff --git a/frontend/src/pages/post/PostForm.jsx b/frontend/src/pages/post/PostForm.jsx index 0b15806..d738b43 100644 --- a/frontend/src/pages/post/PostForm.jsx +++ b/frontend/src/pages/post/PostForm.jsx @@ -5,7 +5,7 @@ import 'react-quill-new/dist/quill.snow.css'; import '../../style/PostCreate.css'; import api from '../../api/axiosInstance.jsx'; import {useNavigate} from 'react-router-dom'; -import ImageResize from 'quill-image-resize-module-react'; +import ImageResize from 'quill-image-resize'; const BaseImage = Quill.import('formats/image'); @@ -34,11 +34,10 @@ class CustomImage extends BaseImage { } } -Quill.register('formats/image', CustomImage, true); - if (typeof window !== 'undefined') { window.Quill = Quill; Quill.register('modules/imageResize', ImageResize); + Quill.register('formats/image', CustomImage, true); } diff --git a/frontend/src/style/PostDetil.css b/frontend/src/style/PostDetil.css index cf648f1..3e1bb81 100644 --- a/frontend/src/style/PostDetil.css +++ b/frontend/src/style/PostDetil.css @@ -236,3 +236,18 @@ justify-content: flex-end; margin-top: 8px; } + +button.potato-btn-danger { + background-color: whitesmoke; + color: #dc3545; + border-color: #dc3545; +} + +button.potato-btn-danger:hover { + background-color: #c82333; + border-color: #bd2130; +} + +.me-2 { + margin-right: 0.5rem; +} diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 555c207..6ab2fe9 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -8,4 +8,14 @@ export default defineConfig({ host: "0.0.0.0" }, plugins: [react()], + build: { + chunkSizeWarningLimit: 1000 + }, + esbuild: { + tsconfigRaw: { + compilerOptions: { + experimentalDecorators: true + } + } + } })