@@ -40,7 +42,7 @@ function TitleController({ initialTitle }: TitleControllerProps) {
name={field.name}
id={field.name}
className={"text-base placeholder:text-base"}
- placeholder="제목을 입력해주세요(5자 이상 100자 이하)"
+ placeholder={placeholder}
spellCheck="false"
autoComplete="off"
fullWidth
diff --git a/src/page/coding-meetings/create/controls/rules/title/title-rules.ts b/src/page/coding-meetings/create/controls/rules/title/title-rules.ts
index 93aa9927..37557035 100644
--- a/src/page/coding-meetings/create/controls/rules/title/title-rules.ts
+++ b/src/page/coding-meetings/create/controls/rules/title/title-rules.ts
@@ -12,10 +12,10 @@ export const codingMeetingTitleRules: CodingMeetingTitleRules = {
required: validationMessage.notitle,
minLength: {
value: CODING_MEETING_LIMITS.title.minLength,
- message: validationMessage.underTitleLimit,
+ message: `제목은 ${CODING_MEETING_LIMITS.title.minLength}자 이상이어야 합니다`,
},
maxLength: {
value: CODING_MEETING_LIMITS.title.maxLength,
- message: validationMessage.overTitleLimit,
+ message: `제목은 ${CODING_MEETING_LIMITS.title.maxLength}자 이하여야 합니다`,
},
}
diff --git a/src/page/coding-meetings/detail/DetailHeader.tsx b/src/page/coding-meetings/detail/DetailHeader.tsx
deleted file mode 100644
index 7052c285..00000000
--- a/src/page/coding-meetings/detail/DetailHeader.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-"use client"
-
-import { DirectionIcons } from "@/components/icons/Icons"
-import { getCodingMeetingsTargetHistory } from "@/util/historySession/coding-meetings"
-import { useRouter } from "next/navigation"
-
-function DetailHeader() {
- const { push } = useRouter()
-
- const viewCodingMeetingList = () => {
- const searchParams = new URLSearchParams()
-
- const codingMeetingsTargetHistory = getCodingMeetingsTargetHistory()
-
- searchParams.set("page", `${codingMeetingsTargetHistory.page}`)
- searchParams.set("size", `${codingMeetingsTargetHistory.size}`)
- searchParams.set("filter", codingMeetingsTargetHistory.filter)
-
- push(`/coding-meetings?${searchParams.toString()}`)
- }
-
- return (
-
-
- 목록 보기
-
- )
-}
-
-export default DetailHeader
-
-function validPageSearchParams(pageSearchParam: string) {
- const pageNumber = Number(pageSearchParam)
-
- return (
- !Number.isNaN(pageNumber) &&
- pageNumber > 0 &&
- !pageSearchParam.includes(".")
- )
-}
diff --git a/src/page/coding-meetings/detail/DetailPage.tsx b/src/page/coding-meetings/detail/DetailPage.tsx
index 17015ec6..039d40d8 100644
--- a/src/page/coding-meetings/detail/DetailPage.tsx
+++ b/src/page/coding-meetings/detail/DetailPage.tsx
@@ -85,7 +85,7 @@ const CodingMeetingsDetailPage = ({
return (
<>
-
+
{detail.coding_meeting_title}
diff --git a/src/page/coffee-chat/create/CreateCoffeeChatReservationPage.tsx b/src/page/coffee-chat/create/CreateCoffeeChatReservationPage.tsx
index 42c2ae89..b4e64b71 100644
--- a/src/page/coffee-chat/create/CreateCoffeeChatReservationPage.tsx
+++ b/src/page/coffee-chat/create/CreateCoffeeChatReservationPage.tsx
@@ -133,6 +133,9 @@ function CreateCoffeeChatReservationPage({
buttonTheme="primary"
className="w-full pc:w-fit p-5 py-3 my-10 disabled:bg-colorsGray disabled:text-colorsDarkGray"
type="submit"
+ onClick={(e) => {
+ if (e.detail === 0) e.preventDefault()
+ }}
>
{createCoffeeChatApiStatus === "pending"
? "처리 중"
diff --git a/src/page/coffee-chat/create/components/TimeOptionButton.tsx b/src/page/coffee-chat/create/components/TimeOptionButton.tsx
index e3cb0db4..44bfa191 100644
--- a/src/page/coffee-chat/create/components/TimeOptionButton.tsx
+++ b/src/page/coffee-chat/create/components/TimeOptionButton.tsx
@@ -32,7 +32,7 @@ function TimeOptionButton({ dateTime }: TimeOptionButtonProps) {
const handleTime = () => {
if (!selected && count >= MAXIMUM_SELCTE_CHAT_TIME_NUM) {
- toast.error(validationMessage.overtimeCntLimit, {
+ toast.error(validationMessage.coffeeChat.maximumReservationTimeLength, {
position: "top-center",
toastId: "maxChatTimes",
})
diff --git a/src/page/coffee-chat/create/components/sections/content/ContentEditor.tsx b/src/page/coffee-chat/create/components/sections/content/ContentEditor.tsx
index ff81794d..2755581a 100644
--- a/src/page/coffee-chat/create/components/sections/content/ContentEditor.tsx
+++ b/src/page/coffee-chat/create/components/sections/content/ContentEditor.tsx
@@ -1,8 +1,8 @@
"use client"
import { useRef } from "react"
-import MdEditor from "@/components/shared/markdown/Editor/MarkdownEditor"
import { Editor } from "@toast-ui/react-editor"
+import CoffeeChatContentEditor from "@/components/shared/toast-ui-editor/editor/ContentEditor"
interface ContentEditorProps {
onChange: (markdown: string) => void
@@ -13,13 +13,13 @@ function ContentEditor({ onChange, initialValue = "" }: ContentEditorProps) {
const editorRef = useRef(null)
return (
- {
- onChange(editorRef.current?.getInstance().getMarkdown() ?? "")
+ onChange(editorRef.current?.getInstance()?.getMarkdown() ?? "")
}}
/>
)
diff --git a/src/page/coffee-chat/create/components/sections/content/ContentSection.tsx b/src/page/coffee-chat/create/components/sections/content/ContentSection.tsx
index 60386a92..ada17c19 100644
--- a/src/page/coffee-chat/create/components/sections/content/ContentSection.tsx
+++ b/src/page/coffee-chat/create/components/sections/content/ContentSection.tsx
@@ -4,7 +4,7 @@ import { CoffeeChatFormData } from "@/interfaces/form"
import { Control, Controller } from "react-hook-form"
import CoffeeChatSection from "../../CoffeeChatSection"
import TextCounter from "@/components/shared/TextCounter"
-import Limitation from "@/constants/limitation"
+import { COFFEE_CHAT_LIMITS } from "@/constants/limitation"
import { chatContentRules } from "../../../controls/rules/chat-content-rules"
import dynamic from "next/dynamic"
@@ -33,8 +33,8 @@ function CoffeeChatContentSection({ control }: CoffeeChatContentSectionProps) {
diff --git a/src/page/coffee-chat/create/components/sections/hashtag/HashTagsSection.tsx b/src/page/coffee-chat/create/components/sections/hashtag/HashTagsSection.tsx
index 836a77d8..a37bdf87 100644
--- a/src/page/coffee-chat/create/components/sections/hashtag/HashTagsSection.tsx
+++ b/src/page/coffee-chat/create/components/sections/hashtag/HashTagsSection.tsx
@@ -1,7 +1,7 @@
"use client"
import CoffeeChatSection from "../../CoffeeChatSection"
-import Limitation from "@/constants/limitation"
+import { HASHTAG_LIMITS } from "@/constants/limitation"
import { useRecoilValue, useResetRecoilState } from "recoil"
import { HashTagList } from "@/recoil/atoms/coffee-chat/hashtags"
import { Control } from "react-hook-form"
@@ -41,7 +41,7 @@ const HashTagLabel = () => {
(
{
{hashTagList.length}
/
-
{Limitation.hashtags_cnt}
+
{HASHTAG_LIMITS.tags.maxLength}
)
)
diff --git a/src/page/coffee-chat/create/components/sections/introduction/IntroductionSection.tsx b/src/page/coffee-chat/create/components/sections/introduction/IntroductionSection.tsx
index 5e4c26d0..865c2e1a 100644
--- a/src/page/coffee-chat/create/components/sections/introduction/IntroductionSection.tsx
+++ b/src/page/coffee-chat/create/components/sections/introduction/IntroductionSection.tsx
@@ -1,9 +1,9 @@
import { CoffeeChatFormData } from "@/interfaces/form"
-import { Control, Controller } from "react-hook-form"
+import { Control, useController } from "react-hook-form"
import CoffeeChatSection from "../../CoffeeChatSection"
import Textarea from "@/components/shared/textarea/Textarea"
import TextCounter from "@/components/shared/TextCounter"
-import Limitation from "@/constants/limitation"
+import { COFFEE_CHAT_LIMITS } from "@/constants/limitation"
import { chatIntroductionRules } from "../../../controls/rules/introduction-rules"
interface IntroductionSectionProps {
@@ -11,37 +11,35 @@ interface IntroductionSectionProps {
}
function IntroductionSection({ control }: IntroductionSectionProps) {
+ const { field } = useController({
+ control,
+ name: "introduction",
+ rules: chatIntroductionRules,
+ })
+
+ const placeholder = `커피챗의 내용이 명확하게 전달되도록 간결하게 요약해주세요. (${COFFEE_CHAT_LIMITS.introduction.minLength}자 이상 ${COFFEE_CHAT_LIMITS.introduction.maxLength}자 이하)`
+
return (
-
{
- return (
-
-
-
-
-
-
-
-
- )
- }}
- />
+
+
+
+
+
+
+
+
)
}
diff --git a/src/page/coffee-chat/create/components/sections/title/TitleSection.tsx b/src/page/coffee-chat/create/components/sections/title/TitleSection.tsx
index 03b2cc6e..4f6cc08f 100644
--- a/src/page/coffee-chat/create/components/sections/title/TitleSection.tsx
+++ b/src/page/coffee-chat/create/components/sections/title/TitleSection.tsx
@@ -3,7 +3,7 @@ import CoffeeChatSection from "../../CoffeeChatSection"
import { CoffeeChatFormData } from "@/interfaces/form"
import { Control, Controller } from "react-hook-form"
import TextCounter from "@/components/shared/TextCounter"
-import Limitation from "@/constants/limitation"
+import { COFFEE_CHAT_LIMITS } from "@/constants/limitation"
import { chatTitleRules } from "../../../controls/rules/chat-title-rules"
interface TitleSectionProps {
@@ -11,6 +11,8 @@ interface TitleSectionProps {
}
function TitleSection({ control }: TitleSectionProps) {
+ const placeholder = `제목(${COFFEE_CHAT_LIMITS.title.minLength}자 이상 ${COFFEE_CHAT_LIMITS.title.maxLength}자 이하)`
+
return (
Limitation.title_limit_over)
+ (field.value.length < COFFEE_CHAT_LIMITS.title.minLength ||
+ field.value.length > COFFEE_CHAT_LIMITS.title.maxLength)
}
onChange={field.onChange}
onBlur={field.onBlur}
@@ -60,8 +62,8 @@ const TitleTextCounter = ({
return (
)
diff --git a/src/page/coffee-chat/create/controls/rules/chat-content-rules.ts b/src/page/coffee-chat/create/controls/rules/chat-content-rules.ts
index 9780c7a5..4a5f802a 100644
--- a/src/page/coffee-chat/create/controls/rules/chat-content-rules.ts
+++ b/src/page/coffee-chat/create/controls/rules/chat-content-rules.ts
@@ -1,4 +1,4 @@
-import Limitation from "@/constants/limitation"
+import { COFFEE_CHAT_LIMITS } from "@/constants/limitation"
import { validationMessage } from "@/constants/message/validation"
import { CoffeeChatFormData } from "@/interfaces/form"
import { RegisterOptions } from "react-hook-form"
@@ -11,11 +11,11 @@ type ChatContentRules = Omit<
export const chatContentRules: ChatContentRules = {
required: validationMessage.noContent,
minLength: {
- value: Limitation.chat_content_min_length,
- message: validationMessage.chatContentLength,
+ value: COFFEE_CHAT_LIMITS.content.minLength,
+ message: `소개글은 ${COFFEE_CHAT_LIMITS.content.minLength}자 이상이어야 합니다`,
},
maxLength: {
- value: Limitation.chat_content_max_length,
- message: validationMessage.chatContentLength,
+ value: COFFEE_CHAT_LIMITS.content.maxLength,
+ message: `소개글은 ${COFFEE_CHAT_LIMITS.content.maxLength}자 이하여야 합니다`,
},
}
diff --git a/src/page/coffee-chat/create/controls/rules/chat-title-rules.ts b/src/page/coffee-chat/create/controls/rules/chat-title-rules.ts
index 5930200e..87012282 100644
--- a/src/page/coffee-chat/create/controls/rules/chat-title-rules.ts
+++ b/src/page/coffee-chat/create/controls/rules/chat-title-rules.ts
@@ -1,4 +1,4 @@
-import Limitation from "@/constants/limitation"
+import { COFFEE_CHAT_LIMITS } from "@/constants/limitation"
import { validationMessage } from "@/constants/message/validation"
import { CoffeeChatFormData } from "@/interfaces/form"
import { RegisterOptions } from "react-hook-form"
@@ -11,11 +11,11 @@ type ChatTitleRules = Omit<
export const chatTitleRules: ChatTitleRules = {
required: validationMessage.notitle,
minLength: {
- value: Limitation.title_limit_under,
+ value: COFFEE_CHAT_LIMITS.title.minLength,
message: "제목은 5자 이상 100자 이하여야 합니다.",
},
maxLength: {
- value: Limitation.title_limit_over,
+ value: COFFEE_CHAT_LIMITS.title.maxLength,
message: "제목은 5자 이상 100자 이하여야 합니다.",
},
}
diff --git a/src/page/coffee-chat/create/controls/rules/datetime-rules.ts b/src/page/coffee-chat/create/controls/rules/datetime-rules.ts
index d7e070d2..44429a39 100644
--- a/src/page/coffee-chat/create/controls/rules/datetime-rules.ts
+++ b/src/page/coffee-chat/create/controls/rules/datetime-rules.ts
@@ -19,18 +19,18 @@ export const enum DateTimeRuleValidateType {
}
export const dateTimeRules: DateTimeFieldRules = {
- required: validationMessage.undertimeCntLimit,
+ required: validationMessage.coffeeChat.emptyReservationTime,
validate: {
[DateTimeRuleValidateType.Empty]: (dateTimes) => {
if (!dateTimes?.length) {
- return validationMessage.undertimeCntLimit
+ return validationMessage.coffeeChat.emptyReservationTime
}
},
[DateTimeRuleValidateType.Maximum]: (dateTimes) => {
if (!dateTimes) return true
if (dateTimes.length > MAXIMUM_SELCTE_CHAT_TIME_NUM) {
- return validationMessage.overtimeCntLimit
+ return validationMessage.coffeeChat.maximumReservationTimeLength
}
return true
diff --git a/src/page/coffee-chat/create/controls/rules/hashtag-rules.ts b/src/page/coffee-chat/create/controls/rules/hashtag-rules.ts
index 75f86d89..3eb9b372 100644
--- a/src/page/coffee-chat/create/controls/rules/hashtag-rules.ts
+++ b/src/page/coffee-chat/create/controls/rules/hashtag-rules.ts
@@ -1,4 +1,4 @@
-import Limitation from "@/constants/limitation"
+import { HASHTAG_LIMITS } from "@/constants/limitation"
import { validationMessage } from "@/constants/message/validation"
import { CoffeeChatFormData, HashTagFormData } from "@/interfaces/form"
import { validatorInstance } from "@/util/validate"
@@ -30,10 +30,10 @@ export const hashTagRules: ({
hashTagList: string[]
}) => HashTagRules = ({ hashTagList }) => {
return {
- required: validationMessage.noValue,
+ required: validationMessage.hashTag.emptyValue,
maxLength: {
- value: Limitation.hashtags_word,
- message: validationMessage.overHashtagWordLimit,
+ value: HASHTAG_LIMITS.tag.maxLength,
+ message: validationMessage.hashTag.maximumHashTagTextLength,
},
validate: {
[HashTagRuleValidateType.InvalidFormat]: (hashTag) => {
@@ -41,7 +41,7 @@ export const hashTagRules: ({
return true
}
- return validationMessage.preventSpecialCharacter
+ return validationMessage.hashTag.includeSpecialCharacter
},
[HashTagRuleValidateType.WhiteSpace]: (hashTag) => {
if (validatorInstance.validateHashTag(hashTag).whiteSpace()) {
@@ -57,14 +57,14 @@ export const hashTagRules: ({
return true
}
- return validationMessage.preventDuplicateValue
+ return validationMessage.hashTag.duplicatedHashTag
},
[HashTagListRuleValidateType.Maximum]: (hashTag) => {
if (validatorInstance.validateHashTagList(hashTagList).length()) {
return true
}
- return validationMessage.overHashtagCntLimit
+ return validationMessage.hashTag.maximumHashTagsLength
},
},
}
diff --git a/src/page/coffee-chat/create/controls/rules/introduction-rules.ts b/src/page/coffee-chat/create/controls/rules/introduction-rules.ts
index 33952165..7322c0c1 100644
--- a/src/page/coffee-chat/create/controls/rules/introduction-rules.ts
+++ b/src/page/coffee-chat/create/controls/rules/introduction-rules.ts
@@ -1,4 +1,4 @@
-import Limitation from "@/constants/limitation"
+import { COFFEE_CHAT_LIMITS } from "@/constants/limitation"
import { CoffeeChatFormData } from "@/interfaces/form"
import { RegisterOptions } from "react-hook-form"
@@ -10,11 +10,11 @@ type ChatIntroductionRules = Omit<
export const chatIntroductionRules: ChatIntroductionRules = {
required: "커피챗 요약 글을 작성해주세요.",
minLength: {
- value: Limitation.chat_introduction_limit_under,
- message: `커피챗 요약 글은 ${Limitation.chat_introduction_limit_under}자 이상 ${Limitation.chat_introduction_limit_over}자 이하여야 합니다.`,
+ value: COFFEE_CHAT_LIMITS.introduction.minLength,
+ message: `커피챗 요약 글은 ${COFFEE_CHAT_LIMITS.introduction.minLength}자 이상 ${COFFEE_CHAT_LIMITS.introduction.maxLength}자 이하여야 합니다.`,
},
maxLength: {
- value: Limitation.chat_introduction_limit_over,
- message: `커피챗 요약 글은 ${Limitation.chat_introduction_limit_under}자 이상 ${Limitation.chat_introduction_limit_over}자 이하여야 합니다.`,
+ value: COFFEE_CHAT_LIMITS.introduction.maxLength,
+ message: `커피챗 요약 글은 ${COFFEE_CHAT_LIMITS.introduction.minLength}자 이상 ${COFFEE_CHAT_LIMITS.introduction.maxLength}자 이하여야 합니다.`,
},
}
diff --git a/src/page/coffee-chat/detail/CoffeeChatDetailContent.tsx b/src/page/coffee-chat/detail/CoffeeChatDetailContent.tsx
index d1189e4f..fbf6a9b9 100644
--- a/src/page/coffee-chat/detail/CoffeeChatDetailContent.tsx
+++ b/src/page/coffee-chat/detail/CoffeeChatDetailContent.tsx
@@ -1,6 +1,5 @@
"use client"
-import { handleViewerLink } from "@/util/editor"
import dynamic from "next/dynamic"
interface CoffeeChatDetailContentProps {
@@ -8,7 +7,7 @@ interface CoffeeChatDetailContentProps {
}
const CoffeeChatContentMdViewer = dynamic(
- () => import("../../../components/shared/markdown/Viewer/MarkdownViewer"),
+ () => import("@/components/shared/toast-ui-editor/viewer/ContentViewer"),
{
ssr: false,
loading(loadingProps) {
@@ -19,8 +18,8 @@ const CoffeeChatContentMdViewer = dynamic(
function CoffeeChatDetailContent({ content }: CoffeeChatDetailContentProps) {
return (
-
-
+
+
)
}
diff --git a/src/page/coffee-chat/detail/reservation/mentee/reservation-time/TimeOptionButton.tsx b/src/page/coffee-chat/detail/reservation/mentee/reservation-time/TimeOptionButton.tsx
index 0f9c7f92..d62ff032 100644
--- a/src/page/coffee-chat/detail/reservation/mentee/reservation-time/TimeOptionButton.tsx
+++ b/src/page/coffee-chat/detail/reservation/mentee/reservation-time/TimeOptionButton.tsx
@@ -11,7 +11,6 @@ import { twMerge } from "tailwind-merge"
import { useCreateChatReservation } from "../hooks/useCreateChatReservation"
import { useDeleteChatReservation } from "../hooks/useDeleteChatReservation"
import { toast } from "react-toastify"
-import { validationMessage } from "@/constants/message/validation"
import useModal from "@/hooks/useModal"
import ConfirmModal from "@/components/shared/confirm-modal/ConfirmModal"
import cancelMessage from "@/constants/message/cancel"
@@ -89,7 +88,7 @@ function TimeOptionButton({
// 지난 시간을 예약했을 경우
if (isAfter) {
- toast.error(validationMessage.beforeNow, {
+ toast.error("지난 시간의 커피챗은 예약할 수 없습니다.", {
toastId: "beforeNow",
position: "top-center",
})
@@ -99,7 +98,7 @@ function TimeOptionButton({
// 이미 해당 커피챗의 다른 시간을 예약했을 경우
if (hasReservation) {
- toast.error(validationMessage.youAlreadyReserved, {
+ toast.error("예약된 시간대가 있어 커피챗을 예약할 수 없습니다", {
toastId: "youAlreadyReserved",
position: "top-center",
})
@@ -108,7 +107,7 @@ function TimeOptionButton({
// 다른 사람이 이미 예약한 시간대를 선택했을 경우
if (!!user && reservationInfo.mentee_nickname && !isReservedByMe) {
- toast.error(validationMessage.alreadyReserved, {
+ toast.error("이미 예약된 시간대입니다", {
toastId: "othersAlreadyReserved",
position: "top-center",
})
diff --git a/src/page/qna-detail/QnADetail.tsx b/src/page/qna-detail/QnADetail.tsx
index 616e749b..4bf980c6 100644
--- a/src/page/qna-detail/QnADetail.tsx
+++ b/src/page/qna-detail/QnADetail.tsx
@@ -2,18 +2,18 @@
import React from "react"
import Question from "./components/Question/Question"
-import MyAnswer from "./components/MyAnswer"
+import CreateAnswer from "./components/Answers/CreateAnswer"
import AnswerListContainer from "./components/Answers/AnswerListContainer"
-import { questionQueries } from "@/react-query/question"
import ContentLoading from "@/components/shared/animation/ContentLoading"
-import { answerQueries } from "@/react-query/answers"
import { useClientSession } from "@/hooks/useClientSession"
import NotFound from "@/app/not-found"
import Spacing from "@/components/shared/Spacing"
import LinkToListPage from "@/components/LinkToListPage"
+import { useQuestionDetail } from "./hooks/question/useQuestionDetail"
+import { useGetAnswers } from "./hooks/answer/useGetAnswers"
const QnADetail: React.FC<{ id: string }> = ({ id }) => {
- const { data, isPending } = questionQueries.useQuestionData({
+ const { data, isPending } = useQuestionDetail({
id: Number(id),
})
@@ -23,7 +23,7 @@ const QnADetail: React.FC<{ id: string }> = ({ id }) => {
data: answers,
isPending: isAnswerPending,
isError,
- } = answerQueries.useGetAnswers({
+ } = useGetAnswers({
questionId: Number(id),
})
@@ -43,7 +43,7 @@ const QnADetail: React.FC<{ id: string }> = ({ id }) => {
- import("../Markdown/MdViewer"), {
- ssr: false,
- loading(loadingProps) {
- // 답변 콘텐츠 로딩 (답변 viewer 로딩)
- return
+const AnswerMdViewer = dynamic(
+ () => import("@/components/shared/toast-ui-editor/viewer/ContentViewer"),
+ {
+ ssr: false,
+ loading(loadingProps) {
+ // 답변 콘텐츠 로딩 (답변 viewer 로딩)
+ return
+ },
},
-})
+)
const AnswerContentBox: React.FC = ({ answer }) => {
- const queryClient = useQueryClient()
-
- const {
- handleSubmit,
- control,
- formState: { isSubmitting },
- } = useForm()
-
- const [answerEditorAtom, setAnswerEditorAtom] = useRecoilState(
- answerEditorAtomFamily(answer.answer_id),
- )
-
- const { isAnswerEditMode, setIsAnswerEditMode } = useHandleMyAnswer({
+ const { answerIsEditMode } = useHandleMyAnswer({
answerId: Number(answer.answer_id),
questionId: Number(answer.question_id),
})
- const { updateAnswer } = answerQueries.useUpdateAnswer({
- answerId: answer.answer_id,
- })
-
- const onSubmit = (data: AnswerFormData) => {
- const markdown = data.answer
-
- const previousUploadedImageLink = answer.answer_image_url
- const uploadedImageLink = getUploadedImageLinkFromMarkdown(markdown)
-
- function getImagePayload({
- previousUploadedImageLink,
- uploadedImageLink,
- }: {
- previousUploadedImageLink: string | null
- uploadedImageLink: string | null
- }): { image_url: string | null; shouldDelete: boolean } {
- if (!uploadedImageLink) {
- /*
- - 현재 업로드 이미지 주소가 없을 경우 요청 이미지 주소는 null
- - 만약 이전 업로드 이미지 주소가 있을 경우 삭제 요청
- */
- return {
- image_url: null,
- shouldDelete: !!previousUploadedImageLink,
- }
- }
-
- if (previousUploadedImageLink === uploadedImageLink) {
- /*
- - 현재 이미지 주소와 이전 이미지 주소가 같을 경우
- 이미지 주소는 이전 이미지 주소
- - 이미지 삭제 요청하지 않음
- */
- return {
- image_url: previousUploadedImageLink,
- shouldDelete: false,
- }
- }
-
- /*
- - 현재 이미지 주소가 존재하고, 이전 이미지 주소와 다른 경우
- 이미지 주소는 현재 이미지 주소
- - 이전 이미지가 있을 경우 삭제 요청
- */
- return {
- image_url: uploadedImageLink,
- shouldDelete: !!previousUploadedImageLink,
- }
- }
-
- const imagePayload = getImagePayload({
- previousUploadedImageLink,
- uploadedImageLink,
- })
-
- const answerPayload: UpdateAnswerRequest = {
- answerId: answer.answer_id,
- content: markdown,
- image_url: imagePayload.image_url,
- }
-
- updateAnswer(answerPayload, {
- onSuccess: async (data, variables, context) => {
- if (!!previousUploadedImageLink && imagePayload.shouldDelete) {
- // 이미지 삭제API 에서 에러발생시 에러 전파 X
- // 이미지 삭제는 답변 수정에 의존하지 않는 개별적인 작업
- // (답변은 이미지 삭제 API에 의존하지 않음)
- await deleteImages({ imageUrl: previousUploadedImageLink }).catch(
- (error) => error,
- )
- }
-
- await queryClient.invalidateQueries({
- queryKey: [queryKey.answer, answer.question_id],
- })
-
- setTimeout(() => {
- setIsAnswerEditMode(false)
-
- // 리코일 - update
- setAnswerEditorAtom((prev) => ({
- ...prev,
- content: markdown,
- fileUploadImageLinks: imagePayload.image_url
- ? [imagePayload.image_url]
- : [],
- }))
-
- toast.success(successMessage.updateAnswer, {
- toastId: "successToUpdateAnswer",
- position: "top-center",
- })
- }, 0)
- },
- onError: () =>
- toast.error(errorMessage.updateAnswer, { position: "top-center" }),
- })
- }
-
- const onInvalid = (errors: FieldErrors) => {
- if (errors.answer) {
- const { type } = errors.answer
-
- if (type === "required") {
- toast.error(validationMessage.noAnswerContent, {
- toastId: "emptyAnswerContent",
- position: "top-center",
- })
- return
- }
-
- if (type === "whiteSpaceOnly") {
- toast.error(validationMessage.notAllowedWhiteSpaceOnly, {
- toastId: "whiteSpaceOnlyAnswerContent",
- position: "top-center",
- })
- return
- }
-
- if (type === "minLength") {
- toast.error(validationMessage.underAnswerLimit, {
- toastId: "underAnswerLimit",
- position: "top-center",
- })
- return
- }
-
- if (type === "maxLength") {
- toast.error(validationMessage.overAnswerLimit, {
- toastId: "overAnswerLimit",
- position: "top-center",
- })
- return
- }
- }
- }
-
- useEffect(() => {
- // 리코일 - 이미지 initiailize
- if (
- !answerEditorAtom.fileUploadImageLinks?.length &&
- answer.answer_image_url
- ) {
- setAnswerEditorAtom((prev) => ({
- ...prev,
- fileUploadImageLinks: [answer.answer_image_url!],
- }))
- }
- }, []) /* eslint-disable-line */
-
/**
* 답변 보기 상태일 경우
*/
- if (!isAnswerEditMode)
+ if (!answerIsEditMode)
return (
-
+
)
@@ -217,37 +44,10 @@ const AnswerContentBox: React.FC = ({ answer }) => {
*/
return (
-
+
+
+
+
)
}
diff --git a/src/page/qna-detail/components/Answers/AnswerListContainer.tsx b/src/page/qna-detail/components/Answers/AnswerListContainer.tsx
index 087767bb..8c973962 100644
--- a/src/page/qna-detail/components/Answers/AnswerListContainer.tsx
+++ b/src/page/qna-detail/components/Answers/AnswerListContainer.tsx
@@ -1,6 +1,5 @@
"use client"
-import { answerQueries } from "@/react-query/answers"
import ContentLoading from "@/components/shared/animation/ContentLoading"
import LightBulb from "@/components/shared/animation/LightBulb"
import useQnADetail from "../../hooks/useQnADetail"
@@ -9,6 +8,7 @@ import { Switch } from "@/components/ui/Switch"
import { useId, useMemo } from "react"
import dayjs from "dayjs"
import AnswerList from "./AnswerList"
+import { useGetAnswers } from "../../hooks/answer/useGetAnswers"
export interface AnswerProps {
questionId: number
@@ -24,9 +24,9 @@ const AnswerListContainer: React.FC = ({
const id = useId()
const switchId = `${id}-answer`
- const { filterMyAnswer, handleIsChecked } = useQnADetail()
+ const { filterMyAnswer, setChecked } = useQnADetail()
- const { data, isPending } = answerQueries.useGetAnswers({
+ const { data, isPending } = useGetAnswers({
questionId,
})
@@ -62,7 +62,7 @@ const AnswerListContainer: React.FC = ({
) : null}
diff --git a/src/page/qna-detail/components/Answers/AnswerListItem.tsx b/src/page/qna-detail/components/Answers/AnswerListItem.tsx
index 23cf4a05..12e5ee77 100644
--- a/src/page/qna-detail/components/Answers/AnswerListItem.tsx
+++ b/src/page/qna-detail/components/Answers/AnswerListItem.tsx
@@ -2,15 +2,13 @@
import type { Answer } from "@/interfaces/answer"
import Image from "next/image"
-import useQnADetail from "../../hooks/useQnADetail"
-import { useClientSession } from "@/hooks/useClientSession"
-import VoteBox from "./VoteBox"
import HandleAnswerBox from "./HandleAnswerBox"
import AnswerContentBox from "./AnswerContentBox"
import React from "react"
import { twMerge } from "tailwind-merge"
import AnswerAuthorInfo from "./info/AnswerAuthorInfo"
import AnswerDate from "./info/AnswerDate"
+import VoteAnswer from "./vote/VoteAnswer"
export interface AnswerListItemProps {
answer: Answer
@@ -18,9 +16,6 @@ export interface AnswerListItemProps {
}
const AnswerListItem: React.FC