diff --git a/src/components/AnswerEditForm/index.jsx b/src/components/AnswerEditForm/index.jsx index 49b2cbd..8025ba5 100644 --- a/src/components/AnswerEditForm/index.jsx +++ b/src/components/AnswerEditForm/index.jsx @@ -2,9 +2,8 @@ import PropTypes from 'prop-types'; import { useState } from 'react'; import { putAnswer } from 'api/answers'; import { ReactComponent as Close } from 'assets/images/icons/ic_Close.svg'; -import ConfirmModal from 'components/ConfirmModal'; +import ConfirmModal from 'components/UI/Modals/ConfirmModal'; -// eslint-disable-next-line const AnswerEditForm = ({ answer, name, imageSource, id, setEditId, setQuestionList, setIsKebabLoading, setIsToast }) => { AnswerEditForm.propTypes = { answer: PropTypes.shape({ @@ -18,13 +17,14 @@ const AnswerEditForm = ({ answer, name, imageSource, id, setEditId, setQuestionL id: PropTypes.number.isRequired, setIsKebabLoading: PropTypes.func.isRequired, setIsToast: PropTypes.func.isRequired, + setEditId: PropTypes.number.isRequired, + setQuestionList: PropTypes.func.isRequired, }; AnswerEditForm.defaultProps = { imageSource: 'https://fastly.picsum.photos/id/772/200/200.jpg?hmac=9euSj4JHTPr7uT5QWVmeNJ8JaqAXY8XmJnYfr_DfBJc', }; - // 초기값 설정 시 answer.content가 null일 경우 빈 문자열로 처리 const [textareaValue, setTextareaValue] = useState(answer.content === null || answer.content === 'reject' ? '' : answer.content); const [isLoading, setIsLoading] = useState(false); const [isValid, setIsValid] = useState(false); @@ -43,8 +43,8 @@ const AnswerEditForm = ({ answer, name, imageSource, id, setEditId, setQuestionL setIsKebabLoading(true); setIsLoading(true); const result = await putAnswer(answer.id, { - content: textareaValue, // textareaValue에서 내용을 가져옵니다. - isRejected: false, // 필요하다면 다른 데이터도 추가 가능합니다. + content: textareaValue, + isRejected: false, }); setIsToast('수정'); setQuestionList((prevQuestions) => @@ -56,7 +56,8 @@ const AnswerEditForm = ({ answer, name, imageSource, id, setEditId, setQuestionL }), ); } catch (err) { - // handle error here (e.g., show error message) + // eslint-disable-next-line + console.error(err); } finally { setIsKebabLoading(false); setIsLoading(false); diff --git a/src/components/App.jsx b/src/components/App/index.jsx similarity index 89% rename from src/components/App.jsx rename to src/components/App/index.jsx index d86e436..eca0b00 100644 --- a/src/components/App.jsx +++ b/src/components/App/index.jsx @@ -4,7 +4,7 @@ import 'assets/styles/index.scss'; import { AppProvider } from 'components/Context'; import ModalPortal from 'utils/portal'; -import Modal from 'components/Modals'; +import Modal from 'components/UI/Modals'; const App = () => ( diff --git a/src/components/AnswerContent/index.jsx b/src/components/Common/AnswerContent/index.jsx similarity index 100% rename from src/components/AnswerContent/index.jsx rename to src/components/Common/AnswerContent/index.jsx diff --git a/src/components/AnswerStatus/index.jsx b/src/components/Common/AnswerStatus/index.jsx similarity index 100% rename from src/components/AnswerStatus/index.jsx rename to src/components/Common/AnswerStatus/index.jsx diff --git a/src/components/CountFavorite/index.jsx b/src/components/Common/CountFavorite/index.jsx similarity index 100% rename from src/components/CountFavorite/index.jsx rename to src/components/Common/CountFavorite/index.jsx diff --git a/src/components/CountQuestion/index.jsx b/src/components/Common/CountQuestion/index.jsx similarity index 100% rename from src/components/CountQuestion/index.jsx rename to src/components/Common/CountQuestion/index.jsx diff --git a/src/components/Header/index.jsx b/src/components/Common/Header/index.jsx similarity index 89% rename from src/components/Header/index.jsx rename to src/components/Common/Header/index.jsx index aa1f60b..212d5ed 100644 --- a/src/components/Header/index.jsx +++ b/src/components/Common/Header/index.jsx @@ -39,7 +39,6 @@ const Header = ({ imageSource, name }) => { handleToastUrlCopyLoad(); }; - // ↓ URL 복사 알림 컴포넌트 const ToastUrlCopy = () => (
URL이 복사되었습니다 @@ -51,13 +50,13 @@ const Header = ({ imageSource, name }) => {
- +
- Logo + Logo - {imageSource && Profile_Img} + {imageSource && Profile_Img}
{name}
- + {question.answer && question.answer.id === editId ? ( { - /** - * children prop 유효성 검사 - * PropType.node : 해당 prop 값이 렌더링 가능한 값이어야 됨 - * isRequired : children prop은 필수임 - */ AppProvider.propTypes = { children: PropTypes.node.isRequired, }; diff --git a/src/components/ToastSuccess/index.jsx b/src/components/ToastSuccess/index.jsx deleted file mode 100644 index 6fd27ef..0000000 --- a/src/components/ToastSuccess/index.jsx +++ /dev/null @@ -1,37 +0,0 @@ -import PropTypes from 'prop-types'; - -const ToastSuccess = ({ toastMsg }) => { - ToastSuccess.propTypes = { - toastMsg: PropTypes.string.isRequired, - }; - if (toastMsg === '질문' || toastMsg === '답변') { - return ( -
- {toastMsg}이 삭제되었습니다. -
- ); - } - if (toastMsg === '수정') { - return ( -
- {toastMsg}이 완료되었습니다. -
- ); - } - if (toastMsg === '거절') { - return ( -
- 답변이 {toastMsg}되었습니다. -
- ); - } - if (toastMsg === '등록') { - return ( -
- 답변이 {toastMsg}되었습니다. -
- ); - } - return null; -}; -export default ToastSuccess; diff --git a/src/components/AnswerDelete/index.jsx b/src/components/UI/Kebab/AnswerDelete/index.jsx similarity index 89% rename from src/components/AnswerDelete/index.jsx rename to src/components/UI/Kebab/AnswerDelete/index.jsx index 79584aa..900d28c 100644 --- a/src/components/AnswerDelete/index.jsx +++ b/src/components/UI/Kebab/AnswerDelete/index.jsx @@ -3,7 +3,7 @@ import { ReactComponent as Close } from 'assets/images/icons/ic_Close.svg'; import PropTypes from 'prop-types'; import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import ConfirmModal from 'components/ConfirmModal'; // Import the modal component +import ConfirmModal from 'components/UI/Modals/ConfirmModal'; const AnswerDelete = ({ id, answerId, onAnswerDeleted, onKebabClick, setIsKebabLoading, setIsToast, editId, setEditId }) => { AnswerDelete.propTypes = { @@ -23,18 +23,18 @@ const AnswerDelete = ({ id, answerId, onAnswerDeleted, onKebabClick, setIsKebabL const [showModal, setShowModal] = useState(false); const handleDelete = async () => { - setShowModal(true); // Show the modal when delete is clicked + setShowModal(true); }; const handleModalCancel = () => { onKebabClick(id); - setShowModal(false); // Close the modal if canceled + setShowModal(false); }; const handleModalConfirm = async () => { onKebabClick(id); setIsKebabLoading(true); - setShowModal(false); // Close the modal + setShowModal(false); setIsDeleting(true); try { diff --git a/src/components/AnswerEdit/index.jsx b/src/components/UI/Kebab/AnswerEdit/index.jsx similarity index 94% rename from src/components/AnswerEdit/index.jsx rename to src/components/UI/Kebab/AnswerEdit/index.jsx index c20af6d..ad49a2d 100644 --- a/src/components/AnswerEdit/index.jsx +++ b/src/components/UI/Kebab/AnswerEdit/index.jsx @@ -1,13 +1,13 @@ import PropTypes from 'prop-types'; import { ReactComponent as Edit } from 'assets/images/icons/ic_Edit.svg'; -// eslint-disable-next-line const AnswerEdit = ({ id, editId, setEditId, answerId, onKebabClick }) => { AnswerEdit.propTypes = { id: PropTypes.number.isRequired, editId: PropTypes.number.isRequired, setEditId: PropTypes.func.isRequired, onKebabClick: PropTypes.func.isRequired, + answerId: PropTypes.number.isRequired, }; const handleEdit = () => { diff --git a/src/components/AnswerRejection/index.jsx b/src/components/UI/Kebab/AnswerRejection/index.jsx similarity index 100% rename from src/components/AnswerRejection/index.jsx rename to src/components/UI/Kebab/AnswerRejection/index.jsx diff --git a/src/components/QuestionDelete/index.jsx b/src/components/UI/Kebab/QuestionDelete/index.jsx similarity index 90% rename from src/components/QuestionDelete/index.jsx rename to src/components/UI/Kebab/QuestionDelete/index.jsx index 39ccd53..33c6153 100644 --- a/src/components/QuestionDelete/index.jsx +++ b/src/components/UI/Kebab/QuestionDelete/index.jsx @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import { useState } from 'react'; import { deleteQuestion } from 'api/questions'; import { ReactComponent as Close } from 'assets/images/icons/ic_Close.svg'; -import ConfirmModal from 'components/ConfirmModal'; +import ConfirmModal from 'components/UI/Modals/ConfirmModal'; const QuestionDelete = ({ id, onDeleteQuestion, onKebabClick, setIsKebabLoading, setIsToast, editId, setEditId }) => { QuestionDelete.propTypes = { @@ -21,16 +21,16 @@ const QuestionDelete = ({ id, onDeleteQuestion, onKebabClick, setIsKebabLoading, const [showModal, setShowModal] = useState(false); const handleDelete = async () => { - setShowModal(true); // Show the modal when delete is clicked + setShowModal(true); }; const handleModalCancel = () => { onKebabClick(id); - setShowModal(false); // Close the modal if canceled + setShowModal(false); }; const handleModalConfirm = async () => { - setShowModal(false); // Close the moda + setShowModal(false); try { setIsKebabLoading(true); diff --git a/src/components/Kebab/index.jsx b/src/components/UI/Kebab/index.jsx similarity index 94% rename from src/components/Kebab/index.jsx rename to src/components/UI/Kebab/index.jsx index 2f10d21..4bf8208 100644 --- a/src/components/Kebab/index.jsx +++ b/src/components/UI/Kebab/index.jsx @@ -1,11 +1,11 @@ import PropTypes from 'prop-types'; import { useEffect, useRef, useState } from 'react'; -import QuestionDelete from 'components/QuestionDelete'; -import AnswerRejection from 'components/AnswerRejection'; +import QuestionDelete from 'components/UI/Kebab/QuestionDelete'; +import AnswerRejection from 'components/UI/Kebab/AnswerRejection'; import kebab from 'assets/images/icons/ic_Kebab.svg'; -import AnswerDelete from 'components/AnswerDelete'; -import AnswerEdit from 'components/AnswerEdit'; -import ConfirmModal from 'components/ConfirmModal'; +import AnswerDelete from 'components/UI/Kebab/AnswerDelete'; +import AnswerEdit from 'components/UI/Kebab/AnswerEdit'; +import ConfirmModal from 'components/UI/Modals/ConfirmModal'; const Kebab = ({ id, isAnswer, isKebabOpen, onKebabClick, onDeleteQuestion, onAnswerDeleted, setQuestionList, editId, setEditId, answerId, isKebabLoading, setIsKebabLoading, setIsToast }) => { Kebab.propTypes = { diff --git a/src/components/ConfirmModal/index.jsx b/src/components/UI/Modals/ConfirmModal/index.jsx similarity index 85% rename from src/components/ConfirmModal/index.jsx rename to src/components/UI/Modals/ConfirmModal/index.jsx index 067decc..23f60f8 100644 --- a/src/components/ConfirmModal/index.jsx +++ b/src/components/UI/Modals/ConfirmModal/index.jsx @@ -11,20 +11,24 @@ const ConfirmModal = ({ isOpen, onConfirm, onCancel, message }) => { const modalRef = useRef(null); - // Close the modal if the user clicks outside of it useEffect(() => { const handleClickOutside = (event) => { if (modalRef.current && !modalRef.current.contains(event.target)) { - onCancel(); // Close the modal if clicked outside + onCancel(); } }; if (isOpen) { + const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth; + document.body.style.overflow = 'hidden'; + document.body.style.paddingRight = `${scrollBarWidth}px`; document.addEventListener('mousedown', handleClickOutside); } return () => { document.removeEventListener('mousedown', handleClickOutside); + document.body.style.overflow = ''; + document.body.style.paddingRight = 0; }; }, [isOpen, onCancel]); diff --git a/src/components/Modals/index.jsx b/src/components/UI/Modals/index.jsx similarity index 94% rename from src/components/Modals/index.jsx rename to src/components/UI/Modals/index.jsx index 7c26af3..710141d 100644 --- a/src/components/Modals/index.jsx +++ b/src/components/UI/Modals/index.jsx @@ -13,17 +13,17 @@ const Modal = () => { closeModal(); setIsContent(false); }; - // Form 제출 이벤트 + const postFormHandler = async (e) => { e.preventDefault(); setPostObject(await postQuestion(profile.id, { content: content.current.value.trim() })); exitModal(); }; - // 실제 이벤트 발생 지점과 버블링 지점에서 target이 일치하면 모달 닫기 + const clickOutsideModal = ({ target, currentTarget }) => { if (target === currentTarget) exitModal(); }; - // TextArea 유효성 검사 + const changeContentHandler = () => { if (content.current.value.trim() !== '') setIsContent(true); else setIsContent(false); diff --git a/src/components/Pagination/index.jsx b/src/components/UI/Pagination/index.jsx similarity index 69% rename from src/components/Pagination/index.jsx rename to src/components/UI/Pagination/index.jsx index e07a213..c57425d 100644 --- a/src/components/Pagination/index.jsx +++ b/src/components/UI/Pagination/index.jsx @@ -21,12 +21,10 @@ const Pagination = ({ data }) => { const btnHoverAnimation = 'hover:transform hover:translate-y-[-5px] transition-transform duration-300 ease-in-out'; - // 페이지네이션의 시작 번호 계산 (ex.두번째 페이지네이션 : 6) const startNum = Math.floor((activeNum - 1) / 5) * 5 + 1; - // 페이지네이션 번호 버튼 배열 + const pages = Array.from({ length: Math.min(5, Math.ceil(count / limit - startNum) + 1) }, (_, i) => startNum + i); - // 페이지 번호 선택에 따른 상태 변경 함수 const pageSelect = useCallback( (pageNum) => { setActiveNum(pageNum); @@ -36,7 +34,6 @@ const Pagination = ({ data }) => { [limit, setOffset, setLimit], ); - // 페이지네이션 이동 버튼 유효성 검사 const checkArrowBtn = useCallback(() => { const divActiveNum = Math.floor((activeNum - 1) / 5); const divTotalPageNum = Math.floor((Math.ceil(count / limit) - 1) / 5); @@ -79,21 +76,27 @@ const Pagination = ({ data }) => { }, [pageWidth, count, setLimit, setOffset, activeNum]); return ( -
- - {pages.map((value) => { - const activeColor = activeNum === value ? 'font-semibold text-brown-40' : 'text-gray-40'; - return ( - + {pages.map((value) => { + const activeColor = activeNum === value ? 'font-semibold text-brown-40' : 'text-gray-40'; + return ( + + ); + })} + - ); - })} - + + )}
); }; diff --git a/src/components/SortDropDown/index.jsx b/src/components/UI/SortDropDown/index.jsx similarity index 95% rename from src/components/SortDropDown/index.jsx rename to src/components/UI/SortDropDown/index.jsx index 8c5e39d..6d3554a 100644 --- a/src/components/SortDropDown/index.jsx +++ b/src/components/UI/SortDropDown/index.jsx @@ -25,14 +25,12 @@ const SortDropDown = ({ changeSort }) => { changeSort(target.textContent); }; - // 외부 클릭 시 드롭다운을 닫는 함수 const handleClickOutside = (event) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { setIsOpen(false); } }; - // 컴포넌트 마운트 시 이벤트 리스너 추가 useEffect(() => { document.addEventListener('click', handleClickOutside); return () => { diff --git a/src/components/ToastDeleteId/index.jsx b/src/components/UI/Toast/ToastDeleteId/index.jsx similarity index 100% rename from src/components/ToastDeleteId/index.jsx rename to src/components/UI/Toast/ToastDeleteId/index.jsx diff --git a/src/components/ToastHome/index.jsx b/src/components/UI/Toast/ToastHome/index.jsx similarity index 100% rename from src/components/ToastHome/index.jsx rename to src/components/UI/Toast/ToastHome/index.jsx diff --git a/src/components/ToastMovePage/index.jsx b/src/components/UI/Toast/ToastMovePage/index.jsx similarity index 66% rename from src/components/ToastMovePage/index.jsx rename to src/components/UI/Toast/ToastMovePage/index.jsx index 3b18833..d39a451 100644 --- a/src/components/ToastMovePage/index.jsx +++ b/src/components/UI/Toast/ToastMovePage/index.jsx @@ -1,14 +1,15 @@ import PropTypes from 'prop-types'; -const ToastMovePage = ({ toastMessage }) => - toastMessage ? ( +const ToastMovePage = ({ toastMessage }) => { + ToastMovePage.propTypes = { + toastMessage: PropTypes.string.isRequired, + }; + + return toastMessage ? (
{toastMessage}
) : null; - -ToastMovePage.propTypes = { - toastMessage: PropTypes.string.isRequired, }; export default ToastMovePage; diff --git a/src/components/ToastPostQuestion/index.jsx b/src/components/UI/Toast/ToastPostQuestion/index.jsx similarity index 100% rename from src/components/ToastPostQuestion/index.jsx rename to src/components/UI/Toast/ToastPostQuestion/index.jsx diff --git a/src/components/UI/Toast/ToastSuccess/index.jsx b/src/components/UI/Toast/ToastSuccess/index.jsx new file mode 100644 index 0000000..4a9f24d --- /dev/null +++ b/src/components/UI/Toast/ToastSuccess/index.jsx @@ -0,0 +1,32 @@ +import PropTypes from 'prop-types'; + +const getMsg = (toastMsg) => { + switch (toastMsg) { + case '질문': + case '답변': + return `${toastMsg}이 삭제되었습니다.`; + case '수정': + return '수정이 완료되었습니다.'; + case '거절': + return '답변이 거절되었습니다.'; + case '등록': + return '답변이 등록되었습니다.'; + default: + return '알 수 없는 메시지입니다.'; + } +}; + +const ToastSuccess = ({ toastMsg }) => { + ToastSuccess.propTypes = { + toastMsg: PropTypes.string.isRequired, + }; + const PRINT_MSG = getMsg(toastMsg); + + return ( +
+ {PRINT_MSG} +
+ ); +}; + +export default ToastSuccess; diff --git a/src/config/constat.js b/src/config/constat.js deleted file mode 100644 index e69de29..0000000 diff --git a/src/hooks/useKakaoShare/index.jsx b/src/hooks/useKakaoShare/index.jsx index d362e5d..611e2ed 100644 --- a/src/hooks/useKakaoShare/index.jsx +++ b/src/hooks/useKakaoShare/index.jsx @@ -10,11 +10,9 @@ const useKakaoShare = (name) => { useEffect(() => { Kakao.cleanup(); - // Kakao SDK 초기화 Kakao.init(process.env.REACT_APP_KAKAO_JS_KEY); }, []); - // 카카오 공유 함수 const shareKakao = () => { try { if (Kakao.isInitialized()) { diff --git a/src/pages/Answer/index.jsx b/src/pages/Answer/index.jsx index 8f2ab13..69d8619 100644 --- a/src/pages/Answer/index.jsx +++ b/src/pages/Answer/index.jsx @@ -2,36 +2,25 @@ import { useState, useEffect, useRef, useCallback } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { getSubjectById, deleteSubject } from 'api/subjects'; import { getQuestionBySubjectId } from 'api/questions'; -import Header from 'components/Header'; +import Header from 'components/Common/Header'; import DeleteIdBtn from 'components/DeleteIdBtn'; -import CountQuestion from 'components/CountQuestion'; -import QnAList from 'components/QnAList'; -import ToastDeleteId from 'components/ToastDeleteId'; +import CountQuestion from 'components/Common/CountQuestion'; +import QnAList from 'components/Common/QnAList'; +import ToastDeleteId from 'components/UI/Toast/ToastDeleteId'; import questionBoxImg from 'assets/images/img_QuestionBox.svg'; -import ConfirmModal from 'components/ConfirmModal'; // Import the modal component -import ToastDelete from 'components/ToastSuccess'; - -const getDynamicLimit = () => { - const screenHeight = window.innerHeight; - if (screenHeight <= 600) { - return 5; - } - if (screenHeight <= 1200) { - return 10; - } - return 15; -}; +import ConfirmModal from 'components/UI/Modals/ConfirmModal'; +import ToastDelete from 'components/UI/Toast/ToastSuccess'; +import getDynamicLimit from 'utils/getDynamicLimit'; const Answer = () => { const { id: subjectId } = useParams(); const [profileLoading, setProfileLoading] = useState(true); - const [profileError, setProfileError] = useState(''); - const [profile, setProfile] = useState(null); + const [profile, setProfile] = useState({}); const [questionCount, setQuestionCount] = useState(0); - const [error, setError] = useState(null); const [isDeleteId, setIsDeleteId] = useState(false); const [isToast, setIsToast] = useState(null); const LocalId = localStorage.getItem('id'); + const [errorMsg, setErrorMsg] = useState(''); const navigate = useNavigate(); @@ -44,22 +33,24 @@ const Answer = () => { const observerRef = useRef(null); - const [showModal, setShowModal] = useState(false); // State for showing the modal + const [showModal, setShowModal] = useState(false); const handleDelete = async () => { - setShowModal(true); // Show the modal when delete is clicked + setShowModal(true); }; const handleModalCancel = () => { - setShowModal(false); // Close the modal if canceled + setShowModal(false); + document.body.style.overflow = ''; + document.body.style.paddingRight = 0; }; const handleModalConfirm = async () => { - setShowModal(false); // Close the modal + setShowModal(false); try { const response = await deleteSubject(subjectId); if (!response.ok) { - throw new Error('삭제 중 오류가 발생했습니다. 3초 후 페이지를 새로고침 합니다.'); + throw new Error('삭제 중 오류가 발생했습니다.'); } localStorage.removeItem('id'); setIsDeleteId(true); @@ -67,11 +58,8 @@ const Answer = () => { setIsDeleteId(true); navigate('/'); }, 2000); - } catch (err) { - setError(err.message); - setTimeout(() => { - setError(null); - }, 3000); + } catch (e) { + setErrorMsg(e.message); } }; @@ -92,20 +80,17 @@ const Answer = () => { if (LocalId === subjectId) { const response = await getSubjectById(subjectId); if (typeof response === 'string' && response.includes('에러')) { - throw new Error('존재하지 않는 피드로 접근하여 오류가 발생했습니다. 잠시 후 홈으로 이동합니다.'); + throw new Error('존재하지 않는 답변 페이지입니다.'); } else { setProfile(response); setQuestionCount(response.questionCount); } } else { - throw new Error('잘못된 접근입니다. 잠시 후 홈으로 이동합니다.'); + throw new Error('허용되지 않은 페이지 접근입니다.'); } } - } catch (err) { - setProfileError(err.toString()); - setTimeout(() => { - navigate('/'); - }, 3000); + } catch (e) { + setErrorMsg(e.message); } finally { setProfileLoading(false); } @@ -129,18 +114,17 @@ const Answer = () => { }); setHasMore(response.next !== null); } else { - throw new Error('질문 목록을 불러오는 데 실패했습니다.'); + throw new Error('질문 목록을 불러올 수 없습니다.'); } - } catch (err) { - // eslint-disable-next-line - console.error(err.toString()); + } catch (e) { + setErrorMsg(e.message); } finally { setListLoading(false); } }; fetchQuestions(); - }, [subjectId, offset]); + }, [subjectId, offset, navigate]); const loadMoreQuestions = useCallback( (entries) => { @@ -169,9 +153,16 @@ const Answer = () => { }; }, [loadMoreQuestions]); - if (profileLoading) return
로딩 중...
; - if (profileError) return
오류: {profileError}
; - if (error) return
오류: {error}
; + if (errorMsg) { + navigate('/error', { state: { message: errorMsg } }); + } + + if (profileLoading) + return ( +
+
+
+ ); return (
diff --git a/src/pages/Error/index.jsx b/src/pages/Error/index.jsx index fa75399..6b96c65 100644 --- a/src/pages/Error/index.jsx +++ b/src/pages/Error/index.jsx @@ -1,10 +1,12 @@ import { useState } from 'react'; -import { useNavigate } from 'react-router-dom'; +import { useNavigate, useLocation } from 'react-router-dom'; import imgLogo from 'assets/images/img_Logo.svg'; const Error = () => { const [showToast, setShowToast] = useState(false); const navigate = useNavigate(); + const location = useLocation(); + const errorMessage = location.state && location.state.message ? location.state.message : '페이지를 찾을 수 없습니다.'; const handleButtonClick = () => { setShowToast(true); @@ -19,7 +21,7 @@ const Error = () => { 오픈마인드 로고

404

-

페이지를 찾을 수 없어요

+

{errorMessage}