Skip to content
7 changes: 6 additions & 1 deletion src/components/AnswerContent/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useEffect, useState } from 'react';
import formatCreatedAt from 'utils/dateUtils';
import { postAnswer } from 'api/answers';

const AnswerContent = ({ answer, name, imageSource, id, onAnswerSubmit, setIsKebabLoading }) => {
const AnswerContent = ({ answer, name, imageSource, id, onAnswerSubmit, setIsKebabLoading, setIsToast }) => {
AnswerContent.propTypes = {
answer: PropTypes.shape({
id: PropTypes.number.isRequired,
Expand All @@ -17,6 +17,7 @@ const AnswerContent = ({ answer, name, imageSource, id, onAnswerSubmit, setIsKeb
id: PropTypes.number.isRequired,
onAnswerSubmit: PropTypes.func.isRequired,
setIsKebabLoading: PropTypes.func.isRequired,
setIsToast: PropTypes.func.isRequired,
};

AnswerContent.defaultProps = {
Expand Down Expand Up @@ -51,12 +52,16 @@ const AnswerContent = ({ answer, name, imageSource, id, onAnswerSubmit, setIsKeb
response = await postAnswer(id, postBody);
setUpdatedAnswer(response);
onAnswerSubmit(id, response);
setIsToast('등록');
} catch (err) {
// eslint-disable-next-line
console.error(err);
} finally {
setIsKebabLoading(false);
setIsLoading(false);
setTimeout(() => {
setIsToast(null);
}, 3000);
}
};

Expand Down
7 changes: 6 additions & 1 deletion src/components/AnswerDelete/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ 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, setIsKebabLoading }) => {
const AnswerDelete = ({ id, answerId, onAnswerDeleted, onKebabClick, setIsKebabLoading, setIsToast }) => {
AnswerDelete.propTypes = {
id: PropTypes.number.isRequired,
answerId: PropTypes.number.isRequired,
onAnswerDeleted: PropTypes.func.isRequired,
onKebabClick: PropTypes.func.isRequired,
setIsKebabLoading: PropTypes.func.isRequired,
setIsToast: PropTypes.func.isRequired,
};

const [isDeleting, setIsDeleting] = useState(false);
Expand Down Expand Up @@ -40,11 +41,15 @@ const AnswerDelete = ({ id, answerId, onAnswerDeleted, onKebabClick, setIsKebabL
throw new Error('답변 삭제 중 오류가 발생했습니다.');
}
onAnswerDeleted(answerId);
setIsToast('답변');
} catch (err) {
navigate('/');
} finally {
setIsDeleting(false);
setIsKebabLoading(false);
setTimeout(() => {
setIsToast(null);
}, 3000);
}
};

Expand Down
7 changes: 6 additions & 1 deletion src/components/AnswerEditForm/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useState } from 'react';
import { putAnswer } from 'api/answers';

// eslint-disable-next-line
const AnswerEditForm = ({ answer, name, imageSource, id, setEditId, setQuestionList, setIsKebabLoading }) => {
const AnswerEditForm = ({ answer, name, imageSource, id, setEditId, setQuestionList, setIsKebabLoading, setIsToast }) => {
AnswerEditForm.propTypes = {
answer: PropTypes.shape({
id: PropTypes.number.isRequired,
Expand All @@ -15,6 +15,7 @@ const AnswerEditForm = ({ answer, name, imageSource, id, setEditId, setQuestionL
imageSource: PropTypes.string,
id: PropTypes.number.isRequired,
setIsKebabLoading: PropTypes.func.isRequired,
setIsToast: PropTypes.func.isRequired,
};

AnswerEditForm.defaultProps = {
Expand Down Expand Up @@ -42,6 +43,7 @@ const AnswerEditForm = ({ answer, name, imageSource, id, setEditId, setQuestionL
content: textareaValue, // textareaValue에서 내용을 가져옵니다.
isRejected: false, // 필요하다면 다른 데이터도 추가 가능합니다.
});
setIsToast('수정');
setQuestionList((prevQuestions) =>
prevQuestions.map((question) => {
if (question.id === id) {
Expand All @@ -56,6 +58,9 @@ const AnswerEditForm = ({ answer, name, imageSource, id, setEditId, setQuestionL
setIsKebabLoading(false);
setIsLoading(false);
setEditId(null);
setTimeout(() => {
setIsToast(null);
}, 3000);
}
};

Expand Down
7 changes: 6 additions & 1 deletion src/components/AnswerRejection/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { useState } from 'react';
import { postAnswer } from 'api/answers';
import { ReactComponent as Rejection } from 'assets/images/icons/ic_Rejection.svg';

const AnswerRejection = ({ id, setQuestionList, onKebabClick, setIsKebabLoading }) => {
const AnswerRejection = ({ id, setQuestionList, onKebabClick, setIsKebabLoading, setIsToast }) => {
AnswerRejection.propTypes = {
id: PropTypes.number.isRequired,
setQuestionList: PropTypes.func.isRequired,
onKebabClick: PropTypes.func.isRequired,
setIsKebabLoading: PropTypes.func.isRequired,
setIsToast: PropTypes.func.isRequired,
};

const [isLoading, setIsLoading] = useState(false);
Expand All @@ -35,11 +36,15 @@ const AnswerRejection = ({ id, setQuestionList, onKebabClick, setIsKebabLoading
return question;
}),
);
setIsToast('거절');
} catch (err) {
setError('답변 거절 중 오류가 발생했습니다.');
} finally {
setIsLoading(false);
setIsKebabLoading(false);
setTimeout(() => {
setIsToast(null);
}, 3000);
}
};

Expand Down
2 changes: 1 addition & 1 deletion src/components/DeleteIdBtn/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const DeleteIdBtn = ({ onClick, id }) => {
<div className='relative w-full max-w-[716px] min-w-[144px] h-[25px] md:h-[35px] mx-6 mb-1.5 md:mx-8 md:mb-[9px]'>
<button
type='button'
className='absolute right-0 w-[70px] min-w-[70px] h-[25px] md:w-[100px] md:h-[35px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)] px-[17.5px] md:px-[24px] md:py-[5px] rounded-[200px] bg-brown-40 font-normal text-gray-10 text-[10px]/[25px] md:text-[15px]/[25px]'
className='absolute right-0 w-[70px] min-w-[70px] h-[25px] md:w-[100px] md:h-[35px] shadow-[0_4px_4px_0_rgba(0,0,0,0.25)] px-[17.5px] md:px-[24px] md:py-[5px] rounded-[200px] bg-brown-40 font-normal text-gray-10 text-[10px]/[25px] md:text-[15px]/[25px] hover:scale-105'
onClick={handleDelete}
>
삭제하기
Expand Down
11 changes: 6 additions & 5 deletions src/components/Kebab/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import kebab from 'assets/images/icons/ic_Kebab.svg';
import AnswerDelete from 'components/AnswerDelete';
import AnswerEdit from 'components/AnswerEdit';

const Kebab = ({ id, isAnswer, isKebabOpen, onKebabClick, onDeleteQuestion, onAnswerDeleted, setQuestionList, editId, setEditId, answerId, isKebabLoading, setIsKebabLoading }) => {
const Kebab = ({ id, isAnswer, isKebabOpen, onKebabClick, onDeleteQuestion, onAnswerDeleted, setQuestionList, editId, setEditId, answerId, isKebabLoading, setIsKebabLoading, setIsToast }) => {
Kebab.propTypes = {
id: PropTypes.number.isRequired,
isAnswer: PropTypes.shape({
Expand All @@ -26,6 +26,7 @@ const Kebab = ({ id, isAnswer, isKebabOpen, onKebabClick, onDeleteQuestion, onAn
answerId: PropTypes.number.isRequired,
isKebabLoading: PropTypes.bool.isRequired,
setIsKebabLoading: PropTypes.func.isRequired,
setIsToast: PropTypes.func.isRequired,
};

const menuRef = useRef(null);
Expand Down Expand Up @@ -65,10 +66,10 @@ const Kebab = ({ id, isAnswer, isKebabOpen, onKebabClick, onDeleteQuestion, onAn
{!isAnswer ? (
<>
<div className='flex justify-center items-center rounded-lg'>
<AnswerRejection id={id} setQuestionList={setQuestionList} onKebabClick={onKebabClick} setIsKebabLoading={setIsKebabLoading} />
<AnswerRejection id={id} setQuestionList={setQuestionList} onKebabClick={onKebabClick} setIsKebabLoading={setIsKebabLoading} setIsToast={setIsToast} />
</div>
<div className='flex justify-center items-center'>
<QuestionDelete id={id} onDeleteQuestion={onDeleteQuestion} setIsKebabLoading={setIsKebabLoading} />
<QuestionDelete id={id} onDeleteQuestion={onDeleteQuestion} onKebabClick={onKebabClick} setIsKebabLoading={setIsKebabLoading} setIsToast={setIsToast} />
</div>
</>
) : (
Expand All @@ -77,10 +78,10 @@ const Kebab = ({ id, isAnswer, isKebabOpen, onKebabClick, onDeleteQuestion, onAn
<AnswerEdit id={id} editId={editId} setEditId={setEditId} answerId={answerId} onKebabClick={onKebabClick} setIsKebabLoading={setIsKebabLoading} />
</div>
<div className='flex justify-center items-center'>
<QuestionDelete id={id} onDeleteQuestion={onDeleteQuestion} setIsKebabLoading={setIsKebabLoading} />
<QuestionDelete id={id} onDeleteQuestion={onDeleteQuestion} onKebabClick={onKebabClick} setIsKebabLoading={setIsKebabLoading} setIsToast={setIsToast} />
</div>
<div className='flex justify-center items-center'>
<AnswerDelete id={id} answerId={isAnswer.id} onAnswerDeleted={onDeleteAnswer} onKebabClick={onKebabClick} setIsKebabLoading={setIsKebabLoading} />
<AnswerDelete id={id} answerId={isAnswer.id} onAnswerDeleted={onDeleteAnswer} onKebabClick={onKebabClick} setIsKebabLoading={setIsKebabLoading} setIsToast={setIsToast} />
</div>
</>
)}
Expand Down
15 changes: 13 additions & 2 deletions src/components/QnAList/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Kebab from 'components/Kebab';
import questionBoxImg from 'assets/images/img_QuestionBox.svg';
import AnswerEditForm from 'components/AnswerEditForm';

const QnAList = ({ name, imageSource, questionList, setQuestionList, onDeleteQuestion }) => {
const QnAList = ({ name, imageSource, questionList, setQuestionList, onDeleteQuestion, setIsToast }) => {
QnAList.propTypes = {
name: PropTypes.string.isRequired,
imageSource: PropTypes.string.isRequired,
Expand All @@ -31,6 +31,7 @@ const QnAList = ({ name, imageSource, questionList, setQuestionList, onDeleteQue
).isRequired,
setQuestionList: PropTypes.func.isRequired,
onDeleteQuestion: PropTypes.func.isRequired,
setIsToast: PropTypes.func.isRequired,
};

const [visibleMenuId, setVisibleMenuId] = useState(null);
Expand Down Expand Up @@ -86,6 +87,7 @@ const QnAList = ({ name, imageSource, questionList, setQuestionList, onDeleteQue
answerId={question.answer ? question.answer.id : null}
isKebabLoading={isKebabLoading}
setIsKebabLoading={setIsKebabLoading}
setIsToast={setIsToast}
/>
)}
</div>
Expand All @@ -102,9 +104,18 @@ const QnAList = ({ name, imageSource, questionList, setQuestionList, onDeleteQue
setEditId={setEditId}
setQuestionList={setQuestionList}
setIsKebabLoading={setIsKebabLoading}
setIsToast={setIsToast}
/>
) : (
<AnswerContent answer={question.answer} name={name} imageSource={imageSource} id={question.id} onAnswerSubmit={handleAnswerSubmit} setIsKebabLoading={setIsKebabLoading} />
<AnswerContent
answer={question.answer}
name={name}
imageSource={imageSource}
id={question.id}
onAnswerSubmit={handleAnswerSubmit}
setIsKebabLoading={setIsKebabLoading}
setIsToast={setIsToast}
/>
)}

<CountFavorite like={question.like} dislike={question.dislike} id={question.id} />
Expand Down
10 changes: 9 additions & 1 deletion src/components/QuestionDelete/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ 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, setIsKebabLoading }) => {
const QuestionDelete = ({ id, onDeleteQuestion, onKebabClick, setIsKebabLoading, setIsToast }) => {
QuestionDelete.propTypes = {
id: PropTypes.number.isRequired,
onDeleteQuestion: PropTypes.func.isRequired,
onKebabClick: PropTypes.func.isRequired,
setIsKebabLoading: PropTypes.func.isRequired,
setIsToast: PropTypes.func.isRequired,
};

const [isLoading, setIsLoading] = useState(false);
Expand All @@ -21,6 +23,7 @@ const QuestionDelete = ({ id, onDeleteQuestion, setIsKebabLoading }) => {
};

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

Expand All @@ -37,12 +40,17 @@ const QuestionDelete = ({ id, onDeleteQuestion, setIsKebabLoading }) => {
throw new Error('질문 삭제 중 오류가 발생했습니다.');
}

setIsToast('질문');

onDeleteQuestion(id);
} catch (err) {
setError('질문 삭제 중 오류가 발생했습니다.');
} finally {
setIsKebabLoading(false);
setIsLoading(false);
setTimeout(() => {
setIsToast(null);
}, 3000);
}
};
if (error) {
Expand Down
37 changes: 37 additions & 0 deletions src/components/ToastSuccess/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import PropTypes from 'prop-types';

const ToastSuccess = ({ toastMsg }) => {
ToastSuccess.propTypes = {
toastMsg: PropTypes.string.isRequired,
};
if (toastMsg === '질문' || toastMsg === '답변') {
return (
<div className='fixed bottom-[100px] md:bottom-[60px] left-1/2 px-5 py-3 bg-black rounded-lg text-sm/[18px] font-medium text-white -translate-x-1/2 shadow-2pt animate-slide-up-fade-delete'>
{toastMsg}이 삭제되었습니다.
</div>
);
}
if (toastMsg === '수정') {
return (
<div className='fixed bottom-[100px] md:bottom-[60px] left-1/2 px-5 py-3 bg-black rounded-lg text-sm/[18px] font-medium text-white -translate-x-1/2 shadow-2pt animate-slide-up-fade-delete'>
{toastMsg}이 완료되었습니다.
</div>
);
}
if (toastMsg === '거절') {
return (
<div className='fixed bottom-[100px] md:bottom-[60px] left-1/2 px-5 py-3 bg-black rounded-lg text-sm/[18px] font-medium text-white -translate-x-1/2 shadow-2pt animate-slide-up-fade-delete'>
답변이 {toastMsg}되었습니다.
</div>
);
}
if (toastMsg === '등록') {
return (
<div className='fixed bottom-[100px] md:bottom-[60px] left-1/2 px-5 py-3 bg-black rounded-lg text-sm/[18px] font-medium text-white -translate-x-1/2 shadow-2pt animate-slide-up-fade-delete'>
답변이 {toastMsg}되었습니다.
</div>
);
}
return null;
};
export default ToastSuccess;
25 changes: 18 additions & 7 deletions src/pages/Answer/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ 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
import ToastDelete from 'components/ToastSuccess';

const getDynamicLimit = () => {
const screenHeight = window.innerHeight;
Expand All @@ -28,7 +29,8 @@ const Answer = () => {
const [profile, setProfile] = useState(null);
const [questionCount, setQuestionCount] = useState(0);
const [error, setError] = useState(null);
const [isDelete, setIsDelete] = useState(false);
const [isDeleteId, setIsDeleteId] = useState(false);
const [isToast, setIsToast] = useState(null);
const LocalId = localStorage.getItem('id');

const navigate = useNavigate();
Expand Down Expand Up @@ -60,8 +62,9 @@ const Answer = () => {
throw new Error('삭제 중 오류가 발생했습니다. 3초 후 페이지를 새로고침 합니다.');
}
localStorage.removeItem('id');
setIsDelete(true);
setIsDeleteId(true);
setTimeout(() => {
setIsDeleteId(true);
navigate('/');
}, 2000);
} catch (err) {
Expand All @@ -85,7 +88,7 @@ const Answer = () => {
try {
setProfileLoading(true);

if (!isDelete) {
if (!isDeleteId) {
if (LocalId === subjectId) {
const response = await getSubjectById(subjectId);
if (typeof response === 'string' && response.includes('에러')) {
Expand All @@ -109,7 +112,7 @@ const Answer = () => {
};

getProfile();
}, [subjectId, isDelete, LocalId, navigate]);
}, [subjectId, isDeleteId, LocalId, navigate]);

useEffect(() => {
const fetchQuestions = async () => {
Expand Down Expand Up @@ -175,15 +178,22 @@ const Answer = () => {
<Header imageSource={profile.imageSource} name={profile.name} />
<div className='flex flex-col items-center justify-center gap-[8px] px-[24px] md:px-[32px] pt-[176px] md:pt-[189px] pb-[168px] md:pb-[140px] bg-gray-20 md:gap-[19px]'>
<DeleteIdBtn onClick={handleDelete} id={subjectId} />
{isDelete ? (
{isDeleteId ? (
<div className='w-full max-w-full bg-brown-10 border border-brown-20 rounded-[16px] pb-[16px] desktop:max-w-[716px] md:max-w-[704px]'>
<CountQuestion count={0} />
<img src={questionBoxImg} alt='질문 박스 이미지' className='mx-auto mt-[50px] mb-[86px] h-[118px] w-[114px] md:mt-[54px] md:mb-[49px] md:h-[154px] md:w-[150px]' />
</div>
) : (
<ul className='w-full max-w-full bg-brown-10 border border-brown-20 rounded-[16px] pb-[16px] desktop:max-w-[716px] md:max-w-[704px]'>
<CountQuestion count={questionCount} />
<QnAList name={profile.name} imageSource={profile.imageSource} questionList={questionList} setQuestionList={setQuestionList} onDeleteQuestion={handleQuestionDelete} />
<QnAList
name={profile.name}
imageSource={profile.imageSource}
questionList={questionList}
setQuestionList={setQuestionList}
onDeleteQuestion={handleQuestionDelete}
setIsToast={setIsToast}
/>
{listLoading && (
<div className='flex justify-center items-center my-10'>
<div className='w-10 h-10 border-4 border-t-transparent border-brown-30 rounded-full animate-spin' />
Expand All @@ -193,7 +203,8 @@ const Answer = () => {
</ul>
)}
</div>
{isDelete && <ToastDeleteId />}
{isDeleteId && <ToastDeleteId />}
{isToast && <ToastDelete toastMsg={isToast} />}
<ConfirmModal isOpen={showModal} onConfirm={handleModalConfirm} onCancel={handleModalCancel} message='정말로 삭제하시겠습니까?' />
</div>
);
Expand Down