Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
a621403
feat:편지 상세 페이지 삭제 모달 추가
wldnjs990 Feb 24, 2025
21f5479
chore:기존 파일들 컴포넌트파일로 이동
wldnjs990 Feb 24, 2025
f39cad4
feat:쿨타임 컴포넌트 생성 + 랜덤편지 타입 수정
wldnjs990 Feb 24, 2025
ff7fe17
feat:차단된 편지 버튼 disabled처리
wldnjs990 Feb 24, 2025
e7aa076
feat:편지 상세보기 모달 생성(매칭편지는 상세페이지와 분리)
wldnjs990 Feb 24, 2025
6824bf0
Merge branch 'develop' of https://github.com/prgrms-web-devcourse-fin…
wldnjs990 Feb 25, 2025
0d96316
fix:쿨타임 페이지 letterWrapper 적용
wldnjs990 Feb 25, 2025
b763c5f
feat:편지 상세, 랜덤 편지 api throw error 예외처리 추가
wldnjs990 Feb 25, 2025
a29ebfa
feat:편지 매칭 제한시간 구현
wldnjs990 Feb 26, 2025
033ded0
Merge branch '31-feat-random-letter' of https://github.com/prgrms-web…
wldnjs990 Feb 26, 2025
5998700
Merge branch 'develop' of https://github.com/prgrms-web-devcourse-fin…
wldnjs990 Feb 26, 2025
5dc58dc
feat:랜덤편지 페이지 매칭 제한시간, 쿨타임 로직 구현
wldnjs990 Feb 26, 2025
59415aa
feat:랜덤편지 페이지 편지 매칭 제한시간, 쿨타임 시간 구현
wldnjs990 Feb 26, 2025
35e9227
Merge branch '31-feat-random-letter' of https://github.com/prgrms-web…
wldnjs990 Feb 26, 2025
3128728
feat:매칭된 편지 전달시 location값 전달처리({randomMatched: true})
wldnjs990 Feb 26, 2025
3937a0f
feat:코드리뷰 사항 수정
wldnjs990 Feb 27, 2025
99c5ac4
Merge branch 'develop' of https://github.com/prgrms-web-devcourse-fin…
wldnjs990 Feb 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/apis/letterDetail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const getLetter = async (
) => {
try {
const res = await client.get(`/api/letters/${letterId}`);
if (!res) throw new Error('편지 데이터를 가져오는 도중 에러가 발생했습니다.');
setLetterState(res.data.data);
if (callBack) callBack();
console.log(res);
Expand All @@ -19,6 +20,7 @@ const deleteLetter = async (letterId: string, callBack?: () => void) => {
try {
console.log(`/api/letters/${letterId}`);
const res = await client.delete(`/api/letters/${letterId}`);
if (!res) throw new Error('편지 삭제 요청 도중 에러가 발생했습니다.');
if (callBack) callBack();
console.log(res);
} catch (error) {
Expand Down
17 changes: 17 additions & 0 deletions src/apis/randomLetter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import client from './client';

const getRandomLetters = async (
setRandomLettersState: React.Dispatch<React.SetStateAction<RandomLetters[]>>,
category: string | null,
) => {
try {
const res = await client.get(`/api/random/${category}`);
if (!res) throw new Error('랜덤 편지 데이터를 가져오는 도중 에러가 발생했습니다.');
setRandomLettersState(res.data.data);
console.log(res);
} catch (error) {
console.error(error);
}
};

export { getRandomLetters };
2 changes: 1 addition & 1 deletion src/components/ResultLetter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import LetterWrapper from './LetterWrapper';
export default function ResultLetter({
categoryName = 'CONSOLATION',
title,
zipCode = 'error',
zipCode = 'ERROR',
}: {
categoryName: Category;
title: string;
Expand Down
25 changes: 21 additions & 4 deletions src/pages/LetterDetail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
WarmIcon,
} from '@/assets/icons';
import BackButton from '@/components/BackButton';
import ConfirmModal from '@/components/ConfirmModal';
import ReportModal from '@/components/ReportModal';
import { FONT_TYPE_OBJ, PAPER_TYPE_OBJ } from '@/pages/Write/constants';

Expand All @@ -28,6 +29,7 @@ const LetterDetailPage = () => {
];
const [degreeModalOpen, setDegreeModalOpen] = useState<boolean>(false);
const [reportModalOpen, setReportModalOpen] = useState<boolean>(false);
const [deleteModalOpen, setDeleteModalOpen] = useState<boolean>(false);

const degreeButtonRef = useRef<HTMLButtonElement>(null);
const handleOutsideClick = (event: MouseEvent) => {
Expand All @@ -41,7 +43,6 @@ const LetterDetailPage = () => {
document.body.addEventListener('click', handleOutsideClick);
if (params.id) {
getLetter(params.id, setLetterDetail);
// 편지 삭제 요청 테스트(내일 삭제 버튼 만들어서 여기다 추가하긔)
}

return () => {
Expand Down Expand Up @@ -72,7 +73,7 @@ const LetterDetailPage = () => {
</button>
<button
onClick={() => {
if (params.id) deleteLetter(params.id);
setDeleteModalOpen(true);
}}
>
<DeleteIcon className="text-primary-1 h-6 w-6" />
Expand Down Expand Up @@ -118,13 +119,29 @@ const LetterDetailPage = () => {
></textarea>
<span className="body-sb mt-10 flex justify-end">FROM. {'12E12'}</span>
<button
className="bg-primary-3 body-m mt-3 w-full rounded-lg py-2"
className="bg-primary-3 disabled:bg-gray-30 body-m mt-3 w-full rounded-lg py-2 disabled:text-white"
onClick={() => {
navigate(`/letter/write/?letterId=${letterDetail?.letterId}`);
}}
disabled={!letterDetail?.matched}
>
편지 작성하기
{letterDetail?.matched ? '편지 작성하기' : '대화가 종료된 편지입니다.'}
</button>
{deleteModalOpen && (
<ConfirmModal
title="편지를 삭제하시겠습니까?"
description="삭제된 편지는 복구할 수 없습니다."
cancelText="취소"
confirmText="삭제"
onCancel={() => {
setDeleteModalOpen(false);
}}
onConfirm={() => {
if (params.id) deleteLetter(params.id);
navigate(-1);
}}
/>
)}
</div>
</>
);
Expand Down
20 changes: 0 additions & 20 deletions src/pages/RandomLetters/Matched.tsx

This file was deleted.

91 changes: 0 additions & 91 deletions src/pages/RandomLetters/MatchingSelect.tsx

This file was deleted.

94 changes: 94 additions & 0 deletions src/pages/RandomLetters/components/CoolTime.tsx
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

잘 쓸게요 😇😇

Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router';

import LetterWrapper from '@/components/LetterWrapper';
import { formatNumber } from '@/utils/formatNumber';

// import letterPink from '@/assets/images/letter-pink.png';

export default function CoolTime({
setCoolTime,
}: {
setCoolTime: React.Dispatch<React.SetStateAction<boolean>>;
}) {
const navigate = useNavigate();

const TIME_STAMP = '2025-02-26T22:13:25.262045608';

const COMPLETED_DATE = new Date(TIME_STAMP);

const END_DATE = new Date(COMPLETED_DATE);
END_DATE.setHours(COMPLETED_DATE.getHours() + 1);

const NOW_DATE = new Date();

const endTime = END_DATE.getTime() - NOW_DATE.getTime();

const [endTimes, setEndTimes] = useState({
hours: Math.floor((endTime / (1000 * 60 * 60)) % 24),
minutes: Math.floor((endTime / (1000 * 60)) % 60),
seconds: Math.floor((endTime / 1000) % 60),
});

useEffect(() => {
if (endTimes.hours < 0 || endTimes.minutes < 0 || endTimes.seconds < 0) {
setEndTimes({ hours: 0, minutes: 0, seconds: 0 });
}
if (endTimes.hours === 0 && endTimes.minutes === 0 && endTimes.seconds === 0) {
setCoolTime(false);
return;
}
const endTimeFlow = setInterval(() => {
setEndTimes((currentTime) => {
if (currentTime.seconds > 0) {
return { ...currentTime, seconds: currentTime.seconds - 1 };
} //
else {
if (currentTime.minutes > 0) {
return { ...currentTime, minutes: currentTime.minutes - 1, seconds: 59 };
} //
else {
if (currentTime.hours > 0) {
return { hours: currentTime.hours - 1, minutes: 59, seconds: 59 };
} //
else {
setCoolTime(false);
return { ...currentTime };
}
}
}
});
if (endTimes.hours === 0 && endTimes.minutes === 0 && endTimes.seconds === 0) {
clearInterval(endTimeFlow);
}
}, 1000);

return () => {
clearInterval(endTimeFlow);
};
}, [endTimes, setCoolTime]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

endTimes 를 의존성 배열에 넣으신 이유가 있을까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lint가 그렇게 하라고 하네요...😅 저도 왜 넣어야하는진 모르겠지만 일단 넣었습니당 ㅎ..

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useEffect에 상태값이 들어가면 무조건 dependency에 넣으라고 하더라구용

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하 알겠습니당!

return (
<div className="mt-20 flex flex-col items-center justify-center">
<div className="body-m flex flex-col items-center justify-center">
<p className="text-gray-60">랜덤 편지 활성화 까지</p>
<p className="text-gray-80">
{formatNumber(endTimes.hours)} : {formatNumber(endTimes.minutes)} :{' '}
{formatNumber(endTimes.seconds)}
</p>
<div className="mt-2 w-75">
<LetterWrapper>
<div className="flex h-50 w-full max-w-[300px] flex-col gap-[35px] p-4"></div>
</LetterWrapper>
</div>
<button
className="bg-primary-3 body-m mt-12.5 w-full rounded-lg py-2"
onClick={() => {
navigate('/');
}}
>
홈으로 돌아가기
</button>
</div>
</div>
);
}
Loading