From d8adcd80161342822aa59f6bad3f1664f2d49f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A7=80=EC=9D=80=20=28=EC=98=A4=EC=9B=94=29?= Date: Thu, 30 Nov 2023 21:45:01 +0900 Subject: [PATCH] =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EC=83=81=EC=84=B8=20?= =?UTF-8?q?=EB=82=B4=EC=9A=A9=20=EA=B4=80=EB=A0=A8=20API=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Loading 컴포넌트 구현 Loading 컴포넌트 구현 * feat: 질문 상세 페이지 관련 API 구현 - getQuestionDetailContentData : 질문 상세 내용를 가져오는 API - getQuestionAnswerListData : 질문별 답변 리스트를 가져오는 API - postAnswer : 질문을 생성하는 API * feat: 질문 상세 페이지 API 도입 - 질문 상세 내용을 서버에서 가져오는 로직 추가 - 질문 상세 내용에 대한 답변 리스트를 서버에서 가져오는 로직 추가 - 질문 답변을 서버에 업로드하는 로직 추가 - 로딩 상태 관리 로직 추가 * feat: 질문에 대한 답변 API 적용 - 질문 답변 데이터 type 변경 - 질문 답변 API 적용 * refactor: styled-component props 변수명 변경 styled-component에서 사용되고 있던 props의 변수명을 camelCase에서 lowercase로 변경해주었습니다. * refactor: 질문 답변 등록 API body 수정 질문 답변을 등록하는 API의 body 객체에 questionId를 추가했습니다. --- FE/public/images/walking-penguin.webp | Bin 0 -> 20526 bytes FE/src/api/index.ts | 49 ++++++ FE/src/components/Loading/Loading.styles.ts | 14 ++ FE/src/components/Loading/Loading.tsx | 15 ++ .../QuestionAnswerCard.styles.ts | 5 +- .../QuestionAnswerCard/QuestionAnswerCard.tsx | 16 +- .../QuestionDetailContent.tsx | 2 +- .../components/QuestionList/QuestionList.tsx | 2 +- .../components/TagButton/TagButton.styles.ts | 25 ++-- FE/src/components/TagButton/TagButton.tsx | 4 +- FE/src/components/index.ts | 2 + .../QuestionDetailPage.styles.ts | 7 + .../QuestionDetailPage/QuestionDetailPage.tsx | 140 +++++++++--------- FE/src/types/type.d.ts | 20 +-- 14 files changed, 197 insertions(+), 104 deletions(-) create mode 100644 FE/public/images/walking-penguin.webp create mode 100644 FE/src/components/Loading/Loading.styles.ts create mode 100644 FE/src/components/Loading/Loading.tsx diff --git a/FE/public/images/walking-penguin.webp b/FE/public/images/walking-penguin.webp new file mode 100644 index 0000000000000000000000000000000000000000..e7a9a5229d8b25127dc0097ff58f7c07fcad5d80 GIT binary patch literal 20526 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

4+L(!r{_ZPV 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 U!Y?60&BltxYCjS { console.error(e); } }; + +export const getQuestionDetailContentData = async (questionId: number) => { + try { + const url = `/api/questions/${questionId}`; + const { status, data } = await instance.get(url); + if (status !== 200) { + throw new Error(); + } + return data; + } catch (e) { + console.error(e); + } +}; + +export const getQuestionAnswerListData = async (questionId: number) => { + try { + const url = `/api/answers/${questionId}`; + const { data } = await instance.get(url); + const { answers } = data; + return answers; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (error: any) { + if (error.response) { + if (error.response.status === 404) { + return null; + } + } else { + console.error('Error from get answer list data:', error.message); + } + throw error; + } +}; + +export const postAnswer = async (content: string, questionId: number) => { + try { + const url = '/api/answers'; + const { status, data } = await instance.post(url, { + questionId, + content, + videoLink: 'https://localhost.com', + }); + if (status !== 201) { + throw new Error('답변 작성 실패'); + } + return data; + } catch (e) { + console.error(e); + } +}; diff --git a/FE/src/components/Loading/Loading.styles.ts b/FE/src/components/Loading/Loading.styles.ts new file mode 100644 index 0000000..0a2568e --- /dev/null +++ b/FE/src/components/Loading/Loading.styles.ts @@ -0,0 +1,14 @@ +import styled from 'styled-components'; + +export const LoadingContainer = styled.div` + position: absolute; + top: calc(50% - 2rem); + left: calc(50% - 3rem); + width: 6rem; + height: 6rem; + + img { + width: 100%; + height: 100%; + } +`; diff --git a/FE/src/components/Loading/Loading.tsx b/FE/src/components/Loading/Loading.tsx new file mode 100644 index 0000000..6b08c9f --- /dev/null +++ b/FE/src/components/Loading/Loading.tsx @@ -0,0 +1,15 @@ +import WalkingPenguin from '/images/walking-penguin.webp'; +import { LoadingContainer } from './Loading.styles'; + +const Loading = () => { + return ( + + + + + + + ); +}; + +export default Loading; diff --git a/FE/src/components/QuestionAnswerCard/QuestionAnswerCard.styles.ts b/FE/src/components/QuestionAnswerCard/QuestionAnswerCard.styles.ts index 207070e..288090e 100644 --- a/FE/src/components/QuestionAnswerCard/QuestionAnswerCard.styles.ts +++ b/FE/src/components/QuestionAnswerCard/QuestionAnswerCard.styles.ts @@ -19,7 +19,7 @@ export const Inner = styled.div` `; interface HeaderProps { - isadopted: boolean; + isadopted: string; } export const Header = styled.div` @@ -30,7 +30,8 @@ export const Header = styled.div` height: 100%; align-items: center; color: ${({ theme }) => theme.color.mainColor.blueMain}; - border-bottom: ${({ isadopted }) => (isadopted ? '0.25rem solid' : 'none')}; + border-bottom: ${({ isadopted }) => + isadopted === 'false' ? '0.25rem solid' : 'none'}; > div { font-weight: 900; diff --git a/FE/src/components/QuestionAnswerCard/QuestionAnswerCard.tsx b/FE/src/components/QuestionAnswerCard/QuestionAnswerCard.tsx index 659b751..fc13f31 100644 --- a/FE/src/components/QuestionAnswerCard/QuestionAnswerCard.tsx +++ b/FE/src/components/QuestionAnswerCard/QuestionAnswerCard.tsx @@ -15,13 +15,13 @@ import { const QuestionAnswerCard = ({ cardData }: QuestionAnswerCardProps) => { const { - content, - nickname, - createdAt, - isAdopted, - isLiked: isLikedInitial, + Content: content, + CreatedAt: createdAt, + IsAdopted: isAdopted, + User, } = cardData; - const [isLiked, setIsLiked] = useState(isLikedInitial); + const { Nickname: nickname } = User; + const [isLiked, setIsLiked] = useState(false); useEffect(() => { // useDidMoundEffect로 변경 & API 로직 구현 @@ -30,7 +30,7 @@ const QuestionAnswerCard = ({ cardData }: QuestionAnswerCardProps) => { return ( -

+
A
{isAdopted && ( @@ -40,7 +40,7 @@ const QuestionAnswerCard = ({ cardData }: QuestionAnswerCardProps) => { )}
- {content} + {nickname} {getFormalizedDate(createdAt)} diff --git a/FE/src/components/QuestionDetailContent/QuestionDetailContent.tsx b/FE/src/components/QuestionDetailContent/QuestionDetailContent.tsx index b1cae00..13c2698 100644 --- a/FE/src/components/QuestionDetailContent/QuestionDetailContent.tsx +++ b/FE/src/components/QuestionDetailContent/QuestionDetailContent.tsx @@ -53,7 +53,7 @@ const QuestionDetailContent = ({
Q
{title} - {content} + diff --git a/FE/src/components/QuestionList/QuestionList.tsx b/FE/src/components/QuestionList/QuestionList.tsx index ffadaf8..fe2dc91 100644 --- a/FE/src/components/QuestionList/QuestionList.tsx +++ b/FE/src/components/QuestionList/QuestionList.tsx @@ -60,7 +60,7 @@ export function Item({ itemData }: { itemData: ItemData }) { } = itemData; const handleItemClick = () => { - navigate(`/question/${id}`); + navigate(`/question/${id}`, { state: { questionId: id } }); }; return ( diff --git a/FE/src/components/TagButton/TagButton.styles.ts b/FE/src/components/TagButton/TagButton.styles.ts index 9ace990..cbed318 100644 --- a/FE/src/components/TagButton/TagButton.styles.ts +++ b/FE/src/components/TagButton/TagButton.styles.ts @@ -1,8 +1,8 @@ import styled from 'styled-components'; interface ContainerProps { - isSelected: boolean; - isInteractive: boolean; + isselected: string; + isinteractive: string; } export const Container = styled.button` @@ -10,12 +10,19 @@ export const Container = styled.button` padding: 0.3rem 1rem; border-radius: 1rem; border: none; - box-shadow: ${({ isSelected, theme }) => - isSelected ? `0 0 0 1px ${theme.color.grayscale.black} inset` : 'none'}; - background-color: ${({ isSelected, theme }) => - isSelected ? theme.color.grayscale.white : theme.color.grayscale[50]}; - color: ${({ isSelected, theme }) => - isSelected ? theme.color.grayscale.black : theme.color.grayscale[200]}; + box-shadow: ${({ isselected, theme }) => + isselected === 'true' + ? `0 0 0 1px ${theme.color.grayscale.black} inset` + : 'none'}; + background-color: ${({ isselected, theme }) => + isselected === 'true' + ? theme.color.grayscale.white + : theme.color.grayscale[50]}; + color: ${({ isselected, theme }) => + isselected === 'true' + ? theme.color.grayscale.black + : theme.color.grayscale[200]}; ${({ theme }) => theme.font.medium14} - cursor: ${({ isInteractive }) => (isInteractive ? 'pointer' : 'default')}; + cursor: ${({ isinteractive }) => + isinteractive === 'true' ? 'pointer' : 'default'}; `; diff --git a/FE/src/components/TagButton/TagButton.tsx b/FE/src/components/TagButton/TagButton.tsx index fae61da..72ef7b9 100644 --- a/FE/src/components/TagButton/TagButton.tsx +++ b/FE/src/components/TagButton/TagButton.tsx @@ -24,8 +24,8 @@ const TagButton = ({ return ( {content} diff --git a/FE/src/components/index.ts b/FE/src/components/index.ts index 35d15f9..f108a17 100644 --- a/FE/src/components/index.ts +++ b/FE/src/components/index.ts @@ -15,6 +15,7 @@ import SquareButton from './SquareButton/SquareButton'; import QuestionAnswerCard from './QuestionAnswerCard/QuestionAnswerCard'; import QuestionAnswerFormCard from './QuestionAnswerFormCard/QuestionAnswerFormCard'; import Scroller from './Scroller/Scroller'; +import Loading from './Loading/Loading'; export { MainHeader, @@ -32,4 +33,5 @@ export { QuestionAnswerCard, QuestionAnswerFormCard, Scroller, + Loading, }; diff --git a/FE/src/pages/QuestionDetailPage/QuestionDetailPage.styles.ts b/FE/src/pages/QuestionDetailPage/QuestionDetailPage.styles.ts index c57ca3a..0cf21a6 100644 --- a/FE/src/pages/QuestionDetailPage/QuestionDetailPage.styles.ts +++ b/FE/src/pages/QuestionDetailPage/QuestionDetailPage.styles.ts @@ -8,8 +8,15 @@ export const Container = styled.div` width: 100%; height: fit-content; background-color: ${({ theme }) => theme.color.grayscale[50]}; + margin-bottom: 6rem; > * { background-color: ${({ theme }) => theme.color.grayscale.white}; } `; + +export const NoAnswer = styled.div` + text-align: center; + padding: 3rem; + color: ${({ theme }) => theme.color.grayscale[200]}; +`; diff --git a/FE/src/pages/QuestionDetailPage/QuestionDetailPage.tsx b/FE/src/pages/QuestionDetailPage/QuestionDetailPage.tsx index 0574c99..0ab9266 100644 --- a/FE/src/pages/QuestionDetailPage/QuestionDetailPage.tsx +++ b/FE/src/pages/QuestionDetailPage/QuestionDetailPage.tsx @@ -1,64 +1,31 @@ import { useState, useLayoutEffect } from 'react'; +import { useLocation } from 'react-router-dom'; import { QuestionDetailContent, QuestionAnswerRequestCard, QuestionAnswerCard, QuestionAnswerFormCard, + Loading, } from '../../components'; -import { QuestionAnswerCardProps } from 'src/types/type'; -import { Container } from './QuestionDetailPage.styles'; +import { + getQuestionDetailContentData, + getQuestionAnswerListData, + postAnswer, +} from '../../api'; +import { + QuestionDetailData as QuestionData, + QuestionAnswerCardProps, +} from 'src/types/type'; -const QuestionDetailContentProps = { - questionData: { - id: 123, - title: 'Voluptas consequatur iure ea cupiditate.', - nickname: '닉네임', - tag: 'baekjoon', - createdAt: '2023-11-27T13:17:31.000Z', - programmingLanguage: 'C', - isAdopted: false, - viewCount: 123, - likeCount: 12, - isLiked: true, - content: - 'Molestiae vel fugit vitae ut consequuntur minima sunt eaque ut. Dolor aut incidunt. Ut fugit possimus sequi voluptatem. Qui quas reprehenderit ut repellendus sint aut voluptatibus. Veniam vel ut dolorum voluptas. Culpa deleniti rerum inventore enim asperiores eius neque eveniet.', - }, -} as const; -const dummyQuestionAnswerCardProps = { - cardData: { - userId: 122, - nickname: '질문자 본인', - answerId: 1243, - content: - 't incidunt. Ut fugit possimus sequi voluptatem. Qui quas reprehenderit ut repellendus sint aut voluptatibus. Veniam vel ut dolorum voluptas. Culpa deleniti rerum inventore enim asperiores eius neque eveniet.', - videoLink: '', - isAdopted: true, - createdAt: '2023-11-27T13:17:31.000Z', - isLiked: false, - }, -} as const; -const dummyQuestionAnswerCardProps2 = { - cardData: { - userId: 124, - nickname: '제주도 감귤', - answerId: 1243, - content: - 't incidunt. Ut fugit possimus sequi voluptatem. Qui quas reprehenderit ut repellendus sint aut voluptatibus. Veniam vel ut dolorum voluptas. Culpa deleniti rerum inventore enim asperiores eius neque eveniet.', - videoLink: '', - isAdopted: false, - createdAt: '2023-11-27T13:17:31.000Z', - isLiked: false, - }, -} as const; -const dummyQuestionAnswerList = [ - dummyQuestionAnswerCardProps, - dummyQuestionAnswerCardProps2, -]; +import { Container, NoAnswer } from './QuestionDetailPage.styles'; const GLOBAL_USER_ID = 123; const QuestionDetailPage = () => { + const { state } = useLocation(); + const [isLoading, setIsLoading] = useState(true); const [isUserAnswering, setIsUserAnswering] = useState(false); const [isUserAnswered, setIsUserAnswered] = useState(false); + const [questionData, setQuestionData] = useState(null); const [answerList, setAnswerList] = useState< QuestionAnswerCardProps[] | null >(null); @@ -71,25 +38,50 @@ const QuestionDetailPage = () => { setIsUserAnswering(false); }; - const submitUserAnswer = (content: string) => { + const submitUserAnswer = async (content: string) => { + const { questionId } = state; + await postAnswer(content, questionId); setIsUserAnswered(true); - // ⚠️ 서버로의 POST 로직 initAnswerList(); - alert(`${content} 추가 완료`); + + alert('답변이 성공적으로 추가되었습니다.'); deactivateUserAnswering(); }; const isAnswerListContainsUserAnswer = () => { return answerList!.find( - ({ cardData }) => cardData.userId === GLOBAL_USER_ID, + ({ cardData }) => cardData.User.Id === GLOBAL_USER_ID, ); }; const initAnswerList = async () => { - const answerList = dummyQuestionAnswerList; + const { questionId } = state; + const answersData = await getQuestionAnswerListData(questionId); + if (!answersData) { + return; + } + const answerList = answersData.map((answer: QuestionAnswerCardProps) => { + return { cardData: answer }; + }); setAnswerList(answerList); }; + const initQuestionDetailContentData = async () => { + const { questionId } = state; + const questionData = await getQuestionDetailContentData(questionId); + setQuestionData(questionData); + }; + + const initFetchData = async () => { + await initQuestionDetailContentData(); + await initAnswerList(); + setIsLoading(false); + }; + + useLayoutEffect(() => { + initFetchData(); + }, []); + useLayoutEffect(() => { if (answerList && isAnswerListContainsUserAnswer()) { setIsUserAnswered(true); @@ -98,28 +90,32 @@ const QuestionDetailPage = () => { } }, [answerList]); - useLayoutEffect(() => { - initAnswerList(); - }, []); - return ( - - {!isUserAnswered && !isUserAnswering && ( - - )} - {isUserAnswering && ( - + {isLoading && } + {!isLoading && ( + <> + {questionData && ( + + )} + {!isUserAnswered && !isUserAnswering && ( + + )} + {isUserAnswering && ( + + )} + {!!answerList && + answerList.map(({ cardData }, idx) => ( + + ))} + {!answerList && 답변이 없습니다} + )} - {!!answerList && - answerList.map(({ cardData }) => ( - - ))} ); }; diff --git a/FE/src/types/type.d.ts b/FE/src/types/type.d.ts index a31300b..02d961d 100644 --- a/FE/src/types/type.d.ts +++ b/FE/src/types/type.d.ts @@ -4,7 +4,7 @@ export interface UniqueQuestionItem { url: string; } -interface QuestionDetailData { +export interface QuestionDetailData { id: number; title: string; nickname: string; @@ -50,14 +50,16 @@ export interface SquareButtonProps { export interface QuestionAnswerCardProps { cardData: { - userId: number; - nickname: string; - answerId: number; - content: string; - videoLink: unknown; - isAdopted: boolean; - createdAt: string; - isLiked: boolean; + Id: number; + User: { + Id: number; + Nickname: string; + ProfileImage: string; + }; + Content: string; + VideoLink: string; + IsAdopted: boolean; + CreatedAt: string; }; }