Skip to content
Merged
10 changes: 3 additions & 7 deletions src/apis/incomingLetters.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import client from './client';

export const getIncomingLetters = async (token: string) => {
export const getIncomingLetters = async () => {
try {
const { data } = await client.get('/api/letters?status=delivery', {
headers: {
Authorization: `Bearer ${token}`,
},
});
console.log('불러온 데이터', data);
const { data } = await client.get('/api/letters?status=delivery');
console.log('오고있는 편지 데이터', data);
return data;
} catch (error) {
console.error('❌오고 있는 편지 목록을 불러오던 중 에러 발생', error);
Expand Down
24 changes: 23 additions & 1 deletion src/apis/share.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface SharePost {
letters: ShareLetter[];
}

// 페이징 포함
// 공유 게시글 목록 조회 - 페이징 포함
export interface SharePostResponse {
content: SharePost[];
currentPage: number;
Expand All @@ -30,6 +30,15 @@ export interface SharePostResponse {
totalPages: number;
}

// 편지 공유 요청 수신 조회
export interface ShareProposal {
shareProposalId: number;
requesterZipCode: string;
recipientZipCode: string;
message: string;
status: 'REJECTED' | 'APPROVED' | 'PENDING';
}

Comment on lines +34 to +41
Copy link
Collaborator

Choose a reason for hiding this comment

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

나중에 이렇게 만들어진 인터페이스들 따로 파일로 빼두면 좋을 것 같아요! 그치만 지금은 안 급하니 패스합니당~

Copy link
Collaborator

Choose a reason for hiding this comment

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

저는 이렇게 인터페이스 두는 방식이 멋져보여서 따라한 곳들이 있는데 저도 수정해야겠군요 허허🥕

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

중간 점검 때 강사님이 .d.ts 파일로 빼는 게 좋다고 하셨으니 기능 구현 후 리팩토링 때 해보겠습니다!!

// 편지 공유 수락 / 거절
export interface SharePostApproval {
shareProposalId: number;
Expand Down Expand Up @@ -84,6 +93,19 @@ export const postShareProposals = async (
}
};

// 편지 공유 요청 수신 조회
export const getShareProposalList = async () => {
try {
const response = await client.get('/api/share-proposals/inbox');
console.log(`🌟공유 요청 목록`, response.data);

return response.data.data;
} catch (error) {
console.error('❌ 편지 공유 요청을 조회하던 중 에러가 발생했습니다', error);
throw error;
Comment on lines +104 to +105
Copy link
Collaborator

Choose a reason for hiding this comment

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

에러코드 가져오시는거군용

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

정확합니다~

}
};

// 편지 공유 수락 / 거절
export const postShareProposalApproval = async (
shareProposalId: number,
Expand Down
30 changes: 17 additions & 13 deletions src/pages/Home/components/ShowDraftModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,26 @@ const ShowDraftModal = ({ onClose }: ShowDraftModalProps) => {
<p className="caption-r text-black">로그아웃 시 임시 저장된 편지는 사라집니다</p>
</div>
<div className="mt-6 flex max-h-60 min-h-auto w-[251px] flex-col gap-[10px] overflow-y-scroll [&::-webkit-scrollbar]:hidden">
{draftLetters.map((draft) => (
<div
className="text-gray-80 body-m flex h-10 w-full items-center justify-between gap-1 rounded-lg bg-white p-3"
key={draft.letterId}
// onClick={() => handleNavigation(draft.letterId)}
>
<p className="truncate">{draft.title}</p>
{draftLetters.length > 0 ? (
draftLetters.map((draft) => (
<div
className="text-gray-20 active:text-gray-600"
tabIndex={0}
onClick={() => handleDeleteDraftLetters(draft.letterId)}
className="text-gray-80 body-m flex h-10 w-full items-center justify-between gap-1 rounded-lg bg-white p-3"
key={draft.letterId}
// onClick={() => handleNavigation(draft.letterId)}
>
<DeleteOutlineRoundedIcon />
<p className="truncate">{draft.title}</p>
<div
className="text-gray-20 active:text-gray-600"
tabIndex={0}
onClick={() => handleDeleteDraftLetters(draft.letterId)}
>
<DeleteOutlineRoundedIcon />
</div>
</div>
</div>
))}
))
) : (
<p className="caption-m text-center text-gray-50">작성 중인 편지가 없어요</p>
)}
</div>
</ModalBackgroundWrapper>
</div>
Expand Down
22 changes: 13 additions & 9 deletions src/pages/Home/components/ShowIncomingLettersModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,19 @@ const ShowIncomingLettersModal = ({ onClose }: ShowIncomingLettersModalProps) =>
<p className="caption-r text-black">시간은 실제 시간을 기반으로 책정됩니다.</p>
</div>
<div className="mt-6 flex max-h-60 min-h-auto w-[251px] flex-col gap-[10px] overflow-y-scroll [&::-webkit-scrollbar]:hidden">
{data.map((letter) => (
<div
className="text-gray-80 body-m flex h-10 w-full items-center justify-between gap-1 rounded-lg bg-white p-3"
key={letter.letterId}
>
<p className="truncate">{letter.title}</p>
<p>{letter.remainingTime}</p>
</div>
))}
{data.length > 0 ? (
data.map((letter) => (
<div
className="text-gray-80 body-m flex h-10 w-full items-center justify-between gap-1 rounded-lg bg-white p-3"
key={letter.letterId}
>
<p className="truncate">{letter.title}</p>
<p>{letter.remainingTime}</p>
</div>
))
) : (
<p className="caption-m text-center text-gray-50">오고 있는 편지가 없어요</p>
)}
</div>
</ModalBackgroundWrapper>
</div>
Expand Down
70 changes: 30 additions & 40 deletions src/pages/Home/components/ShowShareAccessModal.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router';

import { getSharePostDetail, getSharePostList } from '@/apis/share';
import { SharePostResponse, SharePost } from '@/apis/share';
import { getSharePostDetail } from '@/apis/share';
import { getShareProposalList } from '@/apis/share';
import { ShareProposal } from '@/apis/share';

import ModalBackgroundWrapper from '@/components/ModalBackgroundWrapper';
import ModalOverlay from '@/components/ModalOverlay';

Expand All @@ -14,35 +16,22 @@ interface ShowShareAccessModalProps {
const ShowShareAccessModal = ({ onClose }: ShowShareAccessModalProps) => {
const navigate = useNavigate();

const [sharePosts, setSharePosts] = useState<SharePost[]>([]);
const [currentPage, setCurrentPage] = useState(1);
const [hasMore, setHasMore] = useState(true);

const fetchPosts = async (page: number) => {
try {
const data: SharePostResponse = await getSharePostList(page, 10);
setSharePosts((prev) => [...prev, ...data.content]);
setHasMore(page < data.totalPages);
} catch (error) {
console.error('❌ 게시글 목록을 불러오는 데 실패했습니다.', error);
}
};
const [shareProposals, setShareProposals] = useState<ShareProposal[]>([]);

useEffect(() => {
fetchPosts(currentPage);
}, [currentPage]);

const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
if (scrollTop + clientHeight >= scrollHeight - 10 && hasMore) {
setCurrentPage((prev) => prev + 1);
}
};
getShareProposalList()
.then((data) => {
setShareProposals(data || []);
})
.catch((error) => {
console.error('❌ 공유 요청 목록을 불러오는 데 실패했습니다.', error);
});
}, []);

const handleNavigation = async (sharePostId: number) => {
const handleNavigation = async (shareProposalId: number) => {
try {
const postDetail = await getSharePostDetail(sharePostId);
navigate(`/board/letter/${sharePostId}`, {
const postDetail = await getSharePostDetail(shareProposalId);
navigate(`/board/letter/${shareProposalId}`, {
state: { postDetail, isShareLetterPreview: true },
});
} catch (error) {
Expand All @@ -65,19 +54,20 @@ const ShowShareAccessModal = ({ onClose }: ShowShareAccessModalProps) => {
허락 여부를 체크해주세요!
</p>
</div>
<div
className="mt-6 flex max-h-60 min-h-auto w-[251px] flex-col gap-[10px] overflow-y-scroll [&::-webkit-scrollbar]:hidden"
onScroll={handleScroll}
>
{sharePosts?.map((post) => (
<button
className="text-gray-80 body-m flex h-10 w-full items-center justify-between gap-1 rounded-lg bg-white p-3"
key={post.sharePostId}
onClick={() => handleNavigation(post.sharePostId)}
>
<p>{post.writerZipCode}님의 공유 요청</p>
</button>
))}
<div className="mt-6 flex max-h-60 min-h-auto w-[251px] flex-col gap-[10px] overflow-y-scroll [&::-webkit-scrollbar]:hidden">
{shareProposals.length > 0 ? (
shareProposals.map((proposal) => (
<button
className="text-gray-80 body-m flex h-10 w-full items-center justify-between gap-1 rounded-lg bg-white p-3"
key={proposal.shareProposalId}
onClick={() => handleNavigation(proposal.shareProposalId)}
>
<p>{proposal.requesterZipCode}님의 공유 요청</p>
</button>
))
) : (
<p className="caption-m text-center text-gray-50">새로운 공유 요청이 없어요</p>
)}
</div>
</ModalBackgroundWrapper>
</div>
Expand Down
32 changes: 19 additions & 13 deletions src/stores/incomingLettersStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ interface IncomingLetters {

interface IncomingLettersStore {
data: IncomingLetters[];
arrivedCount: number;
message: string;
timestamp: string;
fetchIncomingLetters: () => void;
}

Expand All @@ -36,31 +33,40 @@ const calculatingRemainingTime = (deliveryCompletedAt: string): string => {

export const useIncomingLettersStore = create<IncomingLettersStore>((set) => ({
data: [],
arrivedCount: 0,
message: '',
timestamp: '',
fetchIncomingLetters: async () => {
try {
const token = localStorage.getItem('token') || '';
const data = await getIncomingLetters(token);
const data = await getIncomingLetters();

let arrivedCount = 0;
const updatedLetters = data.data.map((letter: IncomingLetters) => {
const remainingTime = calculatingRemainingTime(letter.deliveryCompletedAt);
if (remainingTime === '00:00:00') arrivedCount += 1; // 도착한 편지 카운트

return { ...letter, remainingTime };
});

const inProgressLetters = updatedLetters.filter(
(letter: IncomingLetters) => letter.remainingTime !== '00:00:00',
);

set({
data: inProgressLetters,
arrivedCount,
message: data.message,
timestamp: data.timestamp,
});

setInterval(() => {
set((state) => {
const updatedLetters = state.data.map((letter: IncomingLetters) => {
const remainingTime = calculatingRemainingTime(letter.deliveryCompletedAt);
return { ...letter, remainingTime };
});

const filteredLetters = updatedLetters.filter(
(letter) => letter.remainingTime !== '00:00:00',
);

return {
data: filteredLetters,
};
});
}, 1000);
} catch (error) {
console.error('❌오고 있는 편지 목록을 불러오던 중 에러 발생', error);
}
Expand Down