Skip to content

Commit

Permalink
chore : 편지 상세 보기 페이지 답장하기 버튼 수정 (#398)
Browse files Browse the repository at this point in the history
  • Loading branch information
mmjjaa authored Dec 9, 2024
1 parent 5c54a25 commit 16b0a5f
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ type KeywordLetterDetailProps = {
export const KeywordLetterDetail = ({
letterData
}: KeywordLetterDetailProps) => {
const { dataType } = useParams<{
const { dataType, letterType } = useParams<{
dataType: string;
letterType: string;
}>();
const navigate = useNavigate();
const { letterId, title, content, keywords, createdAt, font, label } =
Expand All @@ -50,6 +51,7 @@ export const KeywordLetterDetail = ({
if (keywordReplyListDataError instanceof Error) {
return <div>오류...: {keywordReplyListDataError.message}</div>;
}
console.log(keywordReplyListData);

return (
<div className={clsx(font ? font : 'font-sans')}>
Expand Down Expand Up @@ -85,7 +87,7 @@ export const KeywordLetterDetail = ({
</div>
) : null}

{dataType === 'received' && (
{dataType === 'received' && letterType === 'LETTER' && (
<button
className="btn-base flex-center rounded-3xl h-[40px]"
onClick={() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,15 @@ export const MapLetterArchieveDetail = ({
</span>
<span>{DayCounter({ createdAt })}</span>
</div>
<Margin bottom={30} />
{mapReplyListData?.content ? (
<div className="mt-16 mx-auto">
<ReplyList
title={title}
keywordReplyListData={mapReplyListData.content}
/>
</div>
) : null}
</div>

{mapReplyListData?.content ? (
<div className="mt-16 mx-auto">
<ReplyList
title={title}
keywordReplyListData={mapReplyListData.content}
/>
</div>
) : null}
</div>
);
};
131 changes: 126 additions & 5 deletions src/components/LetterDetailPage/LetterDatail/ReplyLetterDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
import { DayCounter } from '@/components/Common/DayCounter/DayCounter';
import { Margin } from '@/components/Common/Margin/Margin';
import { TextArea } from '@/components/Common/TextArea/TextArea';
import { useToastStore } from '@/hooks';
import { usePostNearByLetterStorage } from '@/hooks/usePostNearByLetterStorage';
import { formatDate } from '@/util/formatDate';
import { getLetter } from '@/service/storage/getLetter';
import { useGetCheckMapReplyLetter } from '@/hooks/useGetCheckMapReplyLetter';
import clsx from 'clsx';
import { useParams, useNavigate } from 'react-router-dom';
import { useEffect, useState } from 'react';
import { ReportButton } from '@/components/LetterDetailPage/Report/ReportButton';
import { DeleteButton } from '@/components/LetterDetailPage/Delete/DeleteButton';

type ReplyLetterDetailProps = {
letterData: {
Expand All @@ -11,14 +23,123 @@ type ReplyLetterDetailProps = {
};

export const ReplyLetterDetail = ({ letterData }: ReplyLetterDetailProps) => {
const { content, createdAt } = letterData;
const { letterId } = useParams<{ letterId: string }>();
const { content, createdAt, font, label } = letterData;
const navigate = useNavigate();
const [isStored, setIsStored] = useState(false);

const { data: isReplied } = useGetCheckMapReplyLetter({
letterId: Number(letterId)
});

useEffect(() => {
const checkStoredLetter = async () => {
const storedLetters = await getLetter({
apiEndpoint: '/map/archived',
page: 1,
size: 100
});

const letter = storedLetters.result.content.find(
(letter) => letter.letterId === Number(letterId)
);
if (letter) {
setIsStored(true);
}
};

checkStoredLetter();
}, [letterId]);

const postMutation = usePostNearByLetterStorage(Number(letterId) || 0);

const { addToast } = useToastStore();

const onStorageClick = () => {
if (!isStored) {
postMutation.mutate(undefined, {
onSuccess: (response) => {
if (response.isSuccess) {
if (response.code === 'COMMON201') {
addToast('편지 저장에 성공했습니다', 'success');
setIsStored(true);
localStorage.setItem(
`storedLetter-${letterId}`,
'true'
);
} else if (response.code === 'MAP4009') {
addToast('편지가 이미 저장되어 있습니다.', 'error');
setIsStored(true);
localStorage.setItem(
`storedLetter-${letterId}`,
'true'
);
}
} else {
addToast('편지 저장에 실패했습니다.', 'error');
}
}
});
}
};

const onReplyClick = () => {
navigate(`/letter/map/reply/create/${letterId}`);
};

return (
<>
<div className="absolute bottom-4 translate-x-40"></div>
<p className="absolute left-24 top-[19rem]">{content}</p>
<div className="absolute top-8 right-16 cursor-pointer">
<div className="flex">
<DeleteButton />
<ReportButton />
</div>
</div>
<div className={clsx(font ? font : 'font-sans')}>
<Margin top={20} />
<div className="relative z-20 flex flex-col justify-center w-9/12 m-auto py-9">
<img src={'/to_line.f4c129e6.svg'} className="w-full" />

<div className="relative">
<TextArea
value={content}
font={font}
isReadonly={true}
/>
</div>

<div className="absolute bottom-4 sflex-col">
<p>{formatDate(createdAt)}</p>
<Margin top={30} />
<div className="flex justify-between w-full ">
<div>
<p className="">{formatDate(createdAt)}</p>
</div>
</div>
<Margin bottom={2} />
</div>
<div className="flex justify-between">
<span className="block w-9/12 break-words whitespace-normal">
{content}
</span>
<span>{DayCounter({ createdAt })}</span>
</div>
{!isStored && (
<div className="flex">
<button
className="btn-base flex-center rounded-3xl h-[40px]"
onClick={onStorageClick}
>
보관하기
</button>
{!isReplied && (
<button
className="btn-base flex-center rounded-3xl h-[40px]"
onClick={onReplyClick}
>
편지에 답장하기
</button>
)}
</div>
)}
</div>
</>
);
Expand Down
4 changes: 2 additions & 2 deletions src/components/LetterDetailPage/ReplyList/ReplyList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const ReplyList = ({ title, keywordReplyListData }: ReplyListProps) => {
{keywordReplyListData.map((reply, index) => (
<NavLink
key={reply.replyLetterId}
to={`/letter/${basePath}/reply/${reply.replyLetterId}`}
to={`/letter/${basePath}/REPLY_LETTER/${reply.replyLetterId}`}
className={`flex items-center cursor-pointer h-1 p-6 ${
index < keywordReplyListData.length - 1
? 'border-b border-l-neutral-300'
Expand All @@ -25,7 +25,7 @@ export const ReplyList = ({ title, keywordReplyListData }: ReplyListProps) => {
>
<div className="flex items-center justify-between w-full hover:opacity-70">
<span className="font-bold w-44 truncate mr-4">
RE: {title}
{title ? `RE: ${title}` : reply.title}
</span>
<span className="text-sm truncate flex-1 text-gray-600">
{formatDate(reply.createdAt)}
Expand Down
71 changes: 22 additions & 49 deletions src/pages/Letter/Detail/ReplyLetterDetailPage.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,17 @@
import { BackButton } from '@/components/Common/BackButton/BackButton';
import { useNavigate } from 'react-router-dom';
import { useParams } from 'react-router-dom';
import { DeleteButton } from '@/components/LetterDetailPage/Delete/DeleteButton';
import { ReportButton } from '@/components/LetterDetailPage/Report/ReportButton';
import { TopBar } from '@/components/Common/TopBar/TopBar';
import { useNavigate, useParams } from 'react-router-dom';
import { ReplyLetterDetail } from '@/components/LetterDetailPage/LetterDatail/ReplyLetterDetail';
import { useGetKeywordReplyLetterDetail } from '@/hooks/useGetKeywordReplyLetterDetail';
import { useGetMapReplyLetterDetail } from '@/hooks/useGetMapReplyLetterDetail';
import { ThemeWrapper } from '@/components/CreatLetterPage/ThemeWrapper/ThemeWrapper';

export const ReplyLetterDetailPage = () => {
const { type, replyLetterId } = useParams<{
type: 'map' | 'keyword';
replyLetterId: string;
}>();

const imageItem = {
id: '편지지_샘플_1',
name: '이미지',
src: '/편지지_샘플_1.png'
};
const labelItem = {
id: '라벨_샘플',
name: '이미지',
src: '/라벨_샘플.png'
};

const navigate = useNavigate();

const isMapType = type === 'map';

const {
Expand All @@ -43,11 +29,11 @@ export const ReplyLetterDetailPage = () => {
} = useGetMapReplyLetterDetail({
letterId: replyLetterId ? Number(replyLetterId) || 0 : 0
});
console.log(mapReplyData, keywordReplyData);

if (isKeywordLoading || isMapLoading) {
return <div>Loading...</div>;
}

if (!isMapType && keywordError instanceof Error) {
console.error('Keyword Error:', keywordError.message);
return <div>Error: 키워드 답장 편지가 존재하지 않습니다.</div>;
Expand All @@ -66,39 +52,26 @@ export const ReplyLetterDetailPage = () => {
navigate(-1);
};

const letterData = isMapType ? mapReplyData : keywordReplyData;

return (
<>
<div className="relative mx-auto max-w">
<div className="mx-auto w-[710px]">
<BackButton onClick={onBackClick} />
</div>
{replyLetterId && (
<div className="absolute top-0 flex mt-10 right-8">
<DeleteButton />
<ReportButton />
<div className="w-full min-h-screen">
<TopBar handleBackClick={onBackClick} />
<ThemeWrapper
themeId={Number(
mapReplyData?.paper || keywordReplyData?.paper || 1
)}
>
{letterData ? (
<div className="relative mx-auto max-w">
<div className="relative mt-16 flex-center">
<ReplyLetterDetail letterData={letterData} />
</div>
</div>
) : (
<div>Error: 편지가 존재하지 않습니다.</div>
)}
<div className="relative mt-16 flex-center">
<img
src={imageItem.src}
alt={imageItem.name}
className=" h-[700px] relative"
/>
<img
src={labelItem.src}
alt={labelItem.name}
className="absolute top-4 translate-x-40 w-[125.32px] h-[201.1px]"
/>

{isMapType && mapReplyData ? (
<ReplyLetterDetail letterData={mapReplyData} />
) : keywordReplyData ? (
<ReplyLetterDetail letterData={keywordReplyData} />
) : (
<div>Error: 편지가 존재하지 않습니다.</div>
)}
</div>
</div>
</>
</ThemeWrapper>
</div>
);
};

0 comments on commit 16b0a5f

Please sign in to comment.