diff --git a/src/apis/incomingLetters.ts b/src/apis/incomingLetters.ts new file mode 100644 index 0000000..12f8040 --- /dev/null +++ b/src/apis/incomingLetters.ts @@ -0,0 +1,16 @@ +import { client } from '@/apis/client'; + +export const fetchIncomingLettersApi = async (token: string) => { + try { + const { data } = await client.get('/api/letters?status=delivery', { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + console.log('불러온 데이터', data); + return data; + } catch (error) { + console.error('❌오고 있는 편지 목록을 불러오던 중 에러 발생', error); + throw error; + } +}; diff --git a/src/pages/Home/components/FloatingLetters.tsx b/src/pages/Home/components/FloatingLetters.tsx index b2e8a98..3403883 100644 --- a/src/pages/Home/components/FloatingLetters.tsx +++ b/src/pages/Home/components/FloatingLetters.tsx @@ -1,5 +1,6 @@ -import { useEffect, useRef } from 'react'; import gsap from 'gsap'; +import { useEffect, useRef } from 'react'; + import letter1 from '@/assets/images/letter-1.png'; import letter2 from '@/assets/images/letter-2.png'; import letter3 from '@/assets/images/letter-3.png'; diff --git a/src/pages/Home/components/GoToLetterBoard.tsx b/src/pages/Home/components/GoToLetterBoard.tsx index 329307b..7275cfd 100644 --- a/src/pages/Home/components/GoToLetterBoard.tsx +++ b/src/pages/Home/components/GoToLetterBoard.tsx @@ -1,4 +1,5 @@ import { Link } from 'react-router'; + import goToLetterBoard from '@/assets/images/go-to-letter-board.png'; const GoToLetterBoard = () => { diff --git a/src/pages/Home/components/GoToLetterBox.tsx b/src/pages/Home/components/GoToLetterBox.tsx index 691ed55..436da23 100644 --- a/src/pages/Home/components/GoToLetterBox.tsx +++ b/src/pages/Home/components/GoToLetterBox.tsx @@ -1,10 +1,11 @@ import { Link } from 'react-router'; + import goToLetterBoxNewLetters from '@/assets/images/go-to-letter-box-new-letters.png'; import goToLetterBox from '@/assets/images/go-to-letter-box.png'; const GoToLetterBox = () => { //TODO : hasNewLetters 전역으로 상태 관리하기 - let hasNewLetters = true; + const hasNewLetters = true; return (
diff --git a/src/pages/Home/components/GoToRandomLetter.tsx b/src/pages/Home/components/GoToRandomLetter.tsx index 51db971..2154e7e 100644 --- a/src/pages/Home/components/GoToRandomLetter.tsx +++ b/src/pages/Home/components/GoToRandomLetter.tsx @@ -1,4 +1,5 @@ import { Link } from 'react-router'; + import goToRandomLetter from '@/assets/images/go-to-random-letter.png'; const GoToRandomLetter = () => { diff --git a/src/pages/Home/components/HomeBackgroundLeft.tsx b/src/pages/Home/components/HomeBackgroundLeft.tsx index b8855e2..43b9f91 100644 --- a/src/pages/Home/components/HomeBackgroundLeft.tsx +++ b/src/pages/Home/components/HomeBackgroundLeft.tsx @@ -1,5 +1,5 @@ -import BackgroundImageWrapper from '@/components/BackgroundImageWrapper'; import homeLeftMountain from '@/assets/images/home-left-mountain.png'; +import BackgroundImageWrapper from '@/components/BackgroundImageWrapper'; const HomeBackgroundLeft = () => { return ( diff --git a/src/pages/Home/components/HomeBackgroundRightBottom.tsx b/src/pages/Home/components/HomeBackgroundRightBottom.tsx index 3833ac4..6b55d0c 100644 --- a/src/pages/Home/components/HomeBackgroundRightBottom.tsx +++ b/src/pages/Home/components/HomeBackgroundRightBottom.tsx @@ -1,5 +1,6 @@ -import BackgroundImageWrapper from '@/components/BackgroundImageWrapper'; import homeRightMountainBottom from '@/assets/images/home-right-mountain-bottom.png'; +import BackgroundImageWrapper from '@/components/BackgroundImageWrapper'; + const HomeBackgroundRightBottom = () => { return ( { return ( { return ( diff --git a/src/pages/Home/components/HomeRight.tsx b/src/pages/Home/components/HomeRight.tsx index 226bf4e..e8b32dc 100644 --- a/src/pages/Home/components/HomeRight.tsx +++ b/src/pages/Home/components/HomeRight.tsx @@ -1,18 +1,24 @@ +import { useEffect } from 'react'; + +import { useIncomingLettersStore } from '@/stores/incomingLettersStore'; + import FloatingLetters from './FloatingLetters'; import GoToLetterBoard from './GoToLetterBoard'; import GoToLetterBox from './GoToLetterBox'; import NewLetterModal from './NewLetterModal'; const HomeRight = () => { - //TODO : hasNewLetters 전역으로 상태 관리할지 - let hasNewLetters = true; + const { arrivedCount, fetchIncomingLetters } = useIncomingLettersStore(); + useEffect(() => { + fetchIncomingLetters(); + }, []); return (
- {hasNewLetters && } + {arrivedCount !== 0 && } - {hasNewLetters && } + {arrivedCount !== 0 && }
); }; diff --git a/src/pages/Home/components/LetterActions.tsx b/src/pages/Home/components/LetterActions.tsx index 0fa98ee..a7259cd 100644 --- a/src/pages/Home/components/LetterActions.tsx +++ b/src/pages/Home/components/LetterActions.tsx @@ -1,9 +1,10 @@ -import { useState } from 'react'; -import SendOutlinedIcon from '@mui/icons-material/SendOutlined'; import DriveFileRenameOutlineOutlinedIcon from '@mui/icons-material/DriveFileRenameOutlineOutlined'; +import SendOutlinedIcon from '@mui/icons-material/SendOutlined'; import ShareOutlinedIcon from '@mui/icons-material/ShareOutlined'; -import ShowIncomingLettersModal from './ShowIncomingLettersModal'; +import { useState } from 'react'; + import ShowDraftModal from './ShowDraftModal'; +import ShowIncomingLettersModal from './ShowIncomingLettersModal'; import ShowShareAccessModal from './ShowShareAccessModal'; const LetterActions = () => { @@ -26,17 +27,19 @@ const LetterActions = () => { }, ]; return ( -
-
- {arr.map((item, index) => ( - - ))} + <> +
+
+ {arr.map((item, index) => ( + + ))} +
{activeModal === 'incomingLetters' && ( setActiveModal(null)} /> @@ -45,7 +48,7 @@ const LetterActions = () => { {activeModal === 'shareAccess' && ( setActiveModal(null)} /> )} -
+ ); }; diff --git a/src/pages/Home/components/LetterPreview.tsx b/src/pages/Home/components/LetterPreview.tsx deleted file mode 100644 index 37aaf23..0000000 --- a/src/pages/Home/components/LetterPreview.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react'; - -const LetterPreview = () => { - return
LetterPreview
; -}; - -export default LetterPreview; diff --git a/src/pages/Home/components/NewLetterModal.tsx b/src/pages/Home/components/NewLetterModal.tsx index 40c1c41..5a33817 100644 --- a/src/pages/Home/components/NewLetterModal.tsx +++ b/src/pages/Home/components/NewLetterModal.tsx @@ -1,11 +1,18 @@ -import { useState } from 'react'; +import { useEffect } from 'react'; +import { useIncomingLettersStore } from '@/stores/incomingLettersStore'; + +//TODO: 내 편지함 상세 조회에서 해당 편지를 조회하면 arrivedCount가 1 감소하도록 const NewLetterModal = () => { - const [newLetterCount, setNewLetterCount] = useState(0); + const { arrivedCount, fetchIncomingLetters } = useIncomingLettersStore(); + + useEffect(() => { + fetchIncomingLetters(); + }, []); return (

- {newLetterCount}통의 편지가 도착했어요! + {arrivedCount}통의 편지가 도착했어요!

); }; diff --git a/src/pages/Home/components/RandomCheer.tsx b/src/pages/Home/components/RandomCheer.tsx index 73bce3d..83e96c6 100644 --- a/src/pages/Home/components/RandomCheer.tsx +++ b/src/pages/Home/components/RandomCheer.tsx @@ -13,7 +13,7 @@ const RandomCheer = () => { const [randomCheer, setRandomCheer] = useState(getRandomCheer()); return ( -
+
setRandomCheer(getRandomCheer())} diff --git a/src/pages/Home/components/ShowIncomingLettersModal.tsx b/src/pages/Home/components/ShowIncomingLettersModal.tsx index 376d021..2259854 100644 --- a/src/pages/Home/components/ShowIncomingLettersModal.tsx +++ b/src/pages/Home/components/ShowIncomingLettersModal.tsx @@ -1,21 +1,29 @@ -import React from 'react'; - +import React, { useEffect } from 'react'; +import { useNavigate } from 'react-router'; import ModalBackgroundWrapper from '@/components/ModalBackgroundWrapper'; import ModalOverlay from '@/components/ModalOverlay'; +import { useIncomingLettersStore } from '@/stores/incomingLettersStore'; interface ShowIncomingLettersModalProps { children?: React.ReactNode; onClose: () => void; } -const DUMMY_INCOMING_LETTERS = [ - { id: 1, title: '취업 때문에 고민이 많아요!!', time: '12:00:00' }, - { id: 2, title: '배고파서 죽을 거 같아요 😭', time: '00:00:03' }, - { id: 3, title: '개발하니까 밖에 나갈 일이 없어서 너무 심심하고 피곤해요', time: '00:00:03' }, - { id: 4, title: '마라샹궈 먹고 싶어요', time: '00:00:03' }, -]; - const ShowIncomingLettersModal = ({ onClose }: ShowIncomingLettersModalProps) => { + const navigate = useNavigate(); + + const handleNavigation = (incomingId: number) => { + navigate(`/board/letter/${incomingId}`, { + state: { isShareLetterPreview: false }, + }); + }; + + const { data, fetchIncomingLetters } = useIncomingLettersStore(); + + useEffect(() => { + fetchIncomingLetters(); + }); + return (
@@ -28,14 +36,15 @@ const ShowIncomingLettersModal = ({ onClose }: ShowIncomingLettersModalProps) =>

오고 있는 편지

시간은 실제 시간을 기반으로 책정됩니다.

-
- {DUMMY_INCOMING_LETTERS.map((letter) => ( +
+ {data.map((letter) => (
handleNavigation(letter.letterId)} >

{letter.title}

-

{letter.time}

+

{letter.remainingTime}

))}
diff --git a/src/stores/incomingLettersStore.ts b/src/stores/incomingLettersStore.ts new file mode 100644 index 0000000..1ea9433 --- /dev/null +++ b/src/stores/incomingLettersStore.ts @@ -0,0 +1,68 @@ +import { create } from 'zustand'; + +import { fetchIncomingLettersApi } from '@/apis/incomingLetters'; + +interface IncomingLetters { + letterId: number; + title: string; + deliveryStartedAt: string; + deliveryCompletedAt: string; + remainingTime: string; +} + +interface IncomingLettersStore { + data: IncomingLetters[]; + arrivedCount: number; + message: string; + timestamp: string; + fetchIncomingLetters: () => void; +} + +const formatTime = (time: number): string => (time < 10 ? `0${time}` : `${time}`); + +const calculatingRemainingTime = (deliveryCompletedAt: string): string => { + const completedAt = new Date(deliveryCompletedAt).getTime(); + const now = new Date().getTime(); + const diff = completedAt - now; + + if (diff <= 0) return '00:00:00'; + + const hours = Math.floor(diff / (1000 * 60 * 60)); + const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((diff % (1000 * 60)) / 1000); + + return `${formatTime(hours)}:${formatTime(minutes)}:${formatTime(seconds)}`; +}; + +export const useIncomingLettersStore = create((set) => ({ + data: [], + arrivedCount: 0, + message: '', + timestamp: '', + fetchIncomingLetters: async () => { + try { + const token = localStorage.getItem('token') || ''; + const data = await fetchIncomingLettersApi(token); + + 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, + }); + } catch (error) { + console.error('❌오고 있는 편지 목록을 불러오던 중 에러 발생', error); + } + }, +}));