Skip to content
64 changes: 38 additions & 26 deletions src/components/AnswerDelete/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +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

const AnswerDelete = ({ id, answerId, onAnswerDeleted, onKebabClick }) => {
AnswerDelete.propTypes = {
Expand All @@ -13,39 +14,50 @@ const AnswerDelete = ({ id, answerId, onAnswerDeleted, onKebabClick }) => {
};

const [isDeleting, setIsDeleting] = useState(false);
// const [error, setError] = useState(null);
const navigate = useNavigate();

const handleAnswerDelete = async () => {
const userConfirmed = window.confirm('정말로 삭제하시겠습니까?', ''); // user 확인작업은 confirm으로 임시로 만들었습니다.
if (userConfirmed) {
onKebabClick(id);
setIsDeleting(true);

try {
const response = await deleteAnswer(answerId);
if (!response.ok) {
throw new Error('답변 삭제 중 오류가 발생했습니다.');
}
onAnswerDeleted(answerId);
} catch (err) {
navigate('/');
} finally {
setIsDeleting(false);
const [showModal, setShowModal] = useState(false);

const handleDelete = async () => {
setShowModal(true); // Show the modal when delete is clicked
};

const handleModalCancel = () => {
onKebabClick(id);
setShowModal(false); // Close the modal if canceled
};

const handleModalConfirm = async () => {
onKebabClick(id);
setShowModal(false); // Close the modal
setIsDeleting(true);

try {
const response = await deleteAnswer(answerId);
if (!response.ok) {
throw new Error('답변 삭제 중 오류가 발생했습니다.');
}
onAnswerDeleted(answerId);
} catch (err) {
navigate('/');
} finally {
setIsDeleting(false);
}
};

return (
<button
type='button'
className='flex justify-center items-center gap-2 rounded-lg w-[103px] h-[30px] text-gray-50 hover:text-gray-60 hover:bg-gray-20'
disabled={isDeleting}
onClick={handleAnswerDelete}
>
<Close className='w-3.5 h-3.5 fill-current' />
<p>답변삭제</p>
</button>
<>
<button
type='button'
className='flex justify-center items-center gap-2 rounded-lg w-[103px] h-[30px] text-gray-50 hover:text-blue-50 hover:bg-gray-20'
disabled={isDeleting}
onClick={handleDelete}
>
<Close className='w-3.5 h-3.5 fill-current' />
<p>답변삭제</p>
</button>
<ConfirmModal isOpen={showModal} onConfirm={handleModalConfirm} onCancel={handleModalCancel} message='답변을 삭제하시겠습니까?' />
</>
);
};

Expand Down
2 changes: 1 addition & 1 deletion src/components/AnswerEdit/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const AnswerEdit = ({ id, editId, setEditId, answerId, onKebabClick }) => {

return (
editId === null && (
<button type='button' className='flex justify-center items-center gap-2 rounded-lg w-[103px] h-[30px] text-gray-50 hover:text-gray-60 hover:bg-gray-20' onClick={handleEdit}>
<button type='button' className='flex justify-center items-center gap-2 rounded-lg w-[103px] h-[30px] text-gray-50 hover:text-blue-50 hover:bg-gray-20' onClick={handleEdit}>
<Edit className='w-3.5 h-3.5 fill-current' />
답변수정
</button>
Expand Down
2 changes: 1 addition & 1 deletion src/components/AnswerRejection/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const AnswerRejection = ({ id, setQuestionList, onKebabClick }) => {
return (
<button
type='button'
className='flex justify-center items-center gap-2 rounded-lg w-[103px] h-[30px] text-gray-50 hover:text-gray-60 hover:bg-gray-20'
className='flex justify-center items-center gap-2 rounded-lg w-[103px] h-[30px] text-gray-50 hover:text-blue-50 hover:bg-gray-20'
onClick={handleRejection}
disabled={isLoading}
>
Expand Down
52 changes: 52 additions & 0 deletions src/components/ConfirmModal/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useEffect, useRef } from 'react';
import PropTypes from 'prop-types';

const ConfirmModal = ({ isOpen, onConfirm, onCancel, message }) => {
ConfirmModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onConfirm: PropTypes.func.isRequired,
onCancel: PropTypes.func.isRequired,
message: PropTypes.string.isRequired,
};

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
}
};

if (isOpen) {
document.addEventListener('mousedown', handleClickOutside);
}

return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [isOpen, onCancel]);

if (!isOpen) return null;

return (
<div className='modal-overlay fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50'>
<div ref={modalRef} className='modal-content p-6 rounded-2xl bg-gray-20 shadow-2pt' role='dialog' aria-labelledby='confirm-modal-title'>
<h2 id='confirm-modal-title' className='text-center text-lg font-medium mb-4'>
{message}
</h2>
<div className='flex justify-center gap-4'>
<button type='button' onClick={onConfirm} className='bg-brown-50 text-white px-4 py-2 rounded'>
확인
</button>
<button type='button' onClick={onCancel} className='bg-gray-300 text-black px-4 py-2 rounded'>
취소
</button>
</div>
</div>
</div>
);
};

export default ConfirmModal;
58 changes: 38 additions & 20 deletions src/components/QuestionDelete/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +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 the modal component

const QuestionDelete = ({ id, onDeleteQuestion }) => {
QuestionDelete.propTypes = {
Expand All @@ -12,35 +13,52 @@ const QuestionDelete = ({ id, onDeleteQuestion }) => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);

const [showModal, setShowModal] = useState(false);

const handleDelete = async () => {
const userConfirmed = window.confirm('정말로 삭제하시겠습니까?', ''); // user 확인작업은 confirm으로 임시로 만들었습니다.
if (userConfirmed) {
try {
setIsLoading(true);
setError(null);

const response = await deleteQuestion(id);
if (!response.ok) {
throw new Error('질문 삭제 중 오류가 발생했습니다.');
}

onDeleteQuestion(id);
} catch (err) {
setError('질문 삭제 중 오류가 발생했습니다.');
} finally {
setIsLoading(false);
setShowModal(true); // Show the modal when delete is clicked
};

const handleModalCancel = () => {
setShowModal(false); // Close the modal if canceled
};

const handleModalConfirm = async () => {
setShowModal(false); // Close the moda

try {
setIsLoading(true);
setError(null);

const response = await deleteQuestion(id);
if (!response.ok) {
throw new Error('질문 삭제 중 오류가 발생했습니다.');
}

onDeleteQuestion(id);
} catch (err) {
setError('질문 삭제 중 오류가 발생했습니다.');
} finally {
setIsLoading(false);
}
};
if (error) {
return <div>에러: {error}</div>;
}

return (
<button type='button' className='flex justify-center items-center gap-2 rounded-lg w-[103px] h-[30px] text-gray-50 hover:text-gray-60 hover:bg-gray-20' onClick={handleDelete} disabled={isLoading}>
<Close className='w-3.5 h-3.5 fill-current' />
질문삭제
</button>
<>
<button
type='button'
className='flex justify-center items-center gap-2 rounded-lg w-[103px] h-[30px] text-gray-50 hover:text-blue-50 hover:bg-gray-20'
onClick={handleDelete}
disabled={isLoading}
>
<Close className='w-3.5 h-3.5 fill-current' />
질문삭제
</button>
<ConfirmModal isOpen={showModal} onConfirm={handleModalConfirm} onCancel={handleModalCancel} message='질문을 삭제하시겠습니까?' />
</>
);
};

Expand Down
44 changes: 27 additions & 17 deletions src/pages/Answer/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import CountQuestion from 'components/CountQuestion';
import QnAList from 'components/QnAList';
import ToastDeleteId from 'components/ToastDeleteId';
import questionBoxImg from 'assets/images/img_QuestionBox.svg';
import ConfirmModal from 'components/ConfirmModal'; // Import the modal component

const getDynamicLimit = () => {
const screenHeight = window.innerHeight;
Expand Down Expand Up @@ -41,25 +42,33 @@ const Answer = () => {

const observerRef = useRef(null);

const [showModal, setShowModal] = useState(false); // State for showing the modal

const handleDelete = async () => {
const userConfirmed = window.confirm('정말로 삭제하시겠습니까?', ''); // user 확인작업은 confirm으로 임시로 만들었습니다.
if (userConfirmed) {
try {
const response = await deleteSubject(subjectId);
if (!response.ok) {
throw new Error('삭제 중 오류가 발생했습니다. 3초 후 페이지를 새로고침 합니다.');
}
localStorage.removeItem('id');
setIsDelete(true);
setTimeout(() => {
navigate('/');
}, 2000);
} catch (err) {
setError(err.message);
setTimeout(() => {
setError(null);
}, 3000);
setShowModal(true); // Show the modal when delete is clicked
};

const handleModalCancel = () => {
setShowModal(false); // Close the modal if canceled
};

const handleModalConfirm = async () => {
setShowModal(false); // Close the modal
try {
const response = await deleteSubject(subjectId);
if (!response.ok) {
throw new Error('삭제 중 오류가 발생했습니다. 3초 후 페이지를 새로고침 합니다.');
}
localStorage.removeItem('id');
setIsDelete(true);
setTimeout(() => {
navigate('/');
}, 2000);
} catch (err) {
setError(err.message);
setTimeout(() => {
setError(null);
}, 3000);
}
};

Expand Down Expand Up @@ -185,6 +194,7 @@ const Answer = () => {
)}
</div>
{isDelete && <ToastDeleteId />}
<ConfirmModal isOpen={showModal} onConfirm={handleModalConfirm} onCancel={handleModalCancel} message='정말로 삭제하시겠습니까?' />
</div>
);
};
Expand Down