Skip to content

Commit 8378b1d

Browse files
wldnjs990tifsyAAminhanirii00
authored
deploy : 2차 배포 (#118)
* feat: 임시저장된 편지 삭제 기능 구현 (#84) * fix: 공유 게시글 목록 페이지네이션에서 무한 스크롤로 전환 * refactor: 필요없는 코드 삭제 * feat: 임시저장된 편지 삭제 기능 구현 * design: 임시저장 편지 삭제 아이콘 클릭 시 색상 변경 * feat: 롤링페이퍼 배포된 api로 연결 수정 (#85) * style:롤링페이퍼 공지 애니메이션 수정 * fix: 롤링페이퍼가 진행되지 않을 때 화면에 보여지지 않도록 처리 * feat: 새로운 롤링페이퍼 생성 api 연동 * feat: 롤링페이퍼 목록 조회 api 연동 * feat: 롤링페이퍼 삭제 api 연동 * feat: 롤링페이퍼 사용여부 변경 api 연동 * feat: 롤링페이퍼 코멘트 목록 조회 api 연동 * feat: 롤링페이퍼 등록 및 삭제 api 연동 - api 응답 구조 수정 * feat : 알림 2차 기능 구현 (#81) * feat:알림 컨텐츠 상호작용, 라우팅 기능 구현 * feat : SSE구현시도 * feat : SSE전역변수로 관리할지 store 하나 만들어서 만들면서 고민중 * feat : 알림구독 테스트용 App.tsx에 훅 호출한 코드 * fix: 자잘한 이슈 수정 (#86) * fix: 401 에러가 아닌 경우 바로 로그아웃 되는 문제 해결 * fix: 토큰 만료로 reissue 실패시 로그아웃 안되는 문제 해결 * fix: reissue 에러 시 에러 처리 안되는 문제 해결 - client.ts의 interceptors.response.use 구문 내에서 api 호출및 데이터 가공을 함수 밖으로 꺼냄 * fix: mailbox에서 isClosed 옵션 반대로 보여주는 문제 해결 - isClosed 상태를 반대로 받아와서 상태를 잘못 보여주는 문제 해결 * fix: mailBox 배포 api에 따른 수정 작업 - sharePost 요청 요청자 id 삭제 - 상세 페이지 api 경로 수정 - 우편함 상세체이지 날짜 잘못표기하는 에러 수정 * fix: reissue시 access token을 사용하지 않도록 수정 * feat: 신고 모달 파라미터 변경으로 인한, 파라미터 추가(게시판 상세) * fix: 마이페이지 api 수정 * feat: 임시저장된 편지 삭제 기능 구현 (#84) * fix: 공유 게시글 목록 페이지네이션에서 무한 스크롤로 전환 * refactor: 필요없는 코드 삭제 * feat: 임시저장된 편지 삭제 기능 구현 * design: 임시저장 편지 삭제 아이콘 클릭 시 색상 변경 * feat: 롤링페이퍼 배포된 api로 연결 수정 (#85) * style:롤링페이퍼 공지 애니메이션 수정 * fix: 롤링페이퍼가 진행되지 않을 때 화면에 보여지지 않도록 처리 * feat: 새로운 롤링페이퍼 생성 api 연동 * feat: 롤링페이퍼 목록 조회 api 연동 * feat: 롤링페이퍼 삭제 api 연동 * feat: 롤링페이퍼 사용여부 변경 api 연동 * feat: 롤링페이퍼 코멘트 목록 조회 api 연동 * feat: 롤링페이퍼 등록 및 삭제 api 연동 - api 응답 구조 수정 * fix: type 에러 수정 * fix: 데이터가 없는 경우 컴포넌트 에러가 나는 부분 수정 - 배열이 없거나, 길이가 0이면 placeholder를 보여줌 * Update index.tsx 이상한 import 지움 --------- Co-authored-by: nirii00 <[email protected]> Co-authored-by: Seungyeon Han (Tiffany) <[email protected]> Co-authored-by: Minha Ahn <[email protected]> * feat : 재사용 가능한 페이지네이션 구현 (#92) * feat: 편지 공유 요청 수신 조회 기능 구현 (#90) * feat: 편지 공유 요청 수신 조회 기능 구현 * refactor: incomingLetters.ts 코드 리팩토링 * refactor: incomingLettersStore.ts에서 필요 없는 필드 정리 * feat: 오고 있는 편지 도착까지 걸리는 시간 카운트다운 기능 구현 * design: 오고 있는 편지 모달에서 데이터가 없을 때 대체 텍스트 추가 * design: 임시저장된 편지 모달에서 데이터가 없을 때 대체 텍스트 추가 * design: 편지 공유 요청 수신 조회 모달에서 데이터가 없을 때 대체 텍스트 추가 * feat : 편지작성, 랜덤편지, 상세페이지 3차 기능구현 (#94) * feat : 게시글 신고기능 구현 * feat : 카테고리 전체 선택 안되는 오류 수정 + 답장 전송시 도착시간 1시간으로 텍스트 고정 * feat : getPrevLetter api 엔드포인트 변경 * feat : 디테일 페이지 답장버튼 분기처리 * feat : 편지상세페이지 zipCode바인딩 * refactor : 편지상세 페이지 컴포넌트 분리 * feat : 편지 상세 컴포넌트 추가 분리 + 편지 평가 기능 구현 완료 * refactor : 신고모달 타입에서 null 제거 + 이전편지 가져오기, 타입 조금 수정 * feat : 랜덤편지 편지 없을 경우 예외처리 UI 추가 * design : 편지작성, 편지상세 resize속성 제거 * feat : 랜덤편지 데이터가 없을시 예외처리 UI 추가 + 쿨타임 상태일때 예외처리 UI 수정 * chore : 랜덤편지 api console 제거 * feat : 임시저장 api 생성(연결 테스트 아직 안함) * feat : 편지 작성 페이지 임시저장 버튼 구현 * feat : 편지 임시저장 80% 구현(승연님 작업 이후 임시저장 업데이트 분기 나눠야함) * feat : 임시저장 최초답장 예외처리 * feat: 롤링페이퍼 추가 기능 구현 (#95) * fix: 더미데이터 제거 * feat: 롤링페이퍼 무한 스크롤 적용 * feat: 관리자 페이지 롤링 페이퍼 설정 화면에 페이지네이션 적용 * design: 롤링페이퍼 작성 버튼 위치 수정 * fix: 데이터 변경 후 캐싱 초기화 하는 조건 수정 * design: 하단 언덕 이미지 깨지는 문제 해결 --------- Co-authored-by: wldnjs990 <[email protected]> * feat: 임시저장 편지 조회 기능 완성 (#97) * design: 편지 공유 요청 모달 텍스트 수정 * fix: 임시저장 편지 조회 데이터 구조 수정 * feat: 임시저장 편지 작성 페이지로 데이터 넘겨주기 * design: 홈 페이지에서 새 이미지를 눌러도 랜덤응원메시지가 바뀌도록 --------- Co-authored-by: wldnjs990 <[email protected]> * feat : 토스트 UI 구현 + 알림 페이지 코드 작업 90% 완료 + 실시간 알림, 편지 작성 예외처리에 토스트UI 연결 (#98) * feat : 알림 타입에 SENDING 추가 * feat : 알림 페이지 타임라인 데이터바인딩 + 알림타입에 따른 UI작업 완료(구독 UI작업만 남음) * feat : 토스트UI 작업중 * feat : SSE훅 호출 위치 App에서 PrivateRouter로 이동 + Home 라우트 PrivateRouter 안으로 이동 * feat : 토스트 기능 1차 구현(알림기능 알림도착, 편지작성 내용 미입력시 토스트 넣어둠) * feat : 토스트알림 최대넓이 지정 * feat : 토스트 컨텐츠 타입별 이모지 추가 * refactor : 토스트UI 알림 1개만 표시 => 알림 1개 이상 표시 되도록 업그레이드(단일 객체 -> 객체 배열로 데이터값 수정) * refactor : 토스트UI position 타입 수정 * fix: reissue 문제, 내 편지함 data 최신화 문제 해결 (#100) * fix: 에러나는 경우 무조건 로그아웃되는 현상 해결 * fix: client.ts 주석 제거 * fix: 탈퇴시 로그아웃 자동적으로 되도록 수정 * feat: 탈퇴 에러시 alert 추가 * fix: 마이페이지, 내 공유 게시물 데이터 없을때 자잘한 에러 수정 * fix: 편치 쿼리 갱신 로직 추가 - queryClient.invalidateQueries로 쿼리를 갱신 * fix: 에러시 alert 추가 * fix: 탈퇴한 회원 로직 추가, 온보딩 from 왼쪽 정렬 * fix: 편지 전송/삭제 시 편지함에서 바로 수정사항 반영되도록 함 - 편지 삭제/전송시 queryClient.invalidateQueries 적용 * fix: 게시판에서 response 없을 경우 페이지 로딩이 안되는 문제 해결 - 추후 지속적으로 확인 예정 * fix: 파비콘, 사이트 이름 수정 * feat: ToastUI 적용 -내 편지함의 alert를 toastUI로 변경했습니다. * fix: reissue token 담기지 않는 문제 해결 * fix: letterBoard length 없음 문제 해결 - 계속 확인 필 --------- Co-authored-by: nirii00 <[email protected]> * feat : 알림 페이지 알림 확인 처리 안되던 현상 수정 + 신고페이지 4차 구현 (#101) * refactor : API 일부 리팩토링 * feat : 알림페이지 알림 단일확인시 읽음알림으로 처리되지않던 현상 수정 * feat : 신고 페이지 status 필터링 임시 구현(수정해야함) * feat: 공유 요청 상세 조회 기능 구현 (#106) * refactor: SharePostApproval을 ShareProposalApproval 으로 변경 * fix: 따숨온도가 100도일 때 텍스트가 안 보이는 오류 해결 * feat: 공유 요청 페이지 라우팅 추가 * feat: 공유 요청 상세 조회 기능 구현 * fix: 임시저장 편지 작성 페이지 이동 경로 문제 해결 (#109) * feat : 신고 등록 API + ReportModal 수정 (#111) * fix: QA 반영 (#112) * feat: ToastUI 적용 -내 편지함의 alert를 toastUI로 변경했습니다. * fix: letterBoard length 없음 문제 해결 - 계속 확인 필 * Fix: - 헤더 뒤로가기를 홈으로 가기로 변경 - 편지함 캐싱 수정 -> 새로고침시 데이터 잘 불러와짐 - 신고 타입 수정 - mailbox 타입 분리 - mailBox 공유시 id를 상대방 id로 수정 * fix: 추가 커밋 * fix: 내 게시물 삭제 아이콘 표시, query key 중복 오류 해결 * fix: 파비콘 경로 수정 * fix: 새로고침시 데이터 바로 반영 * fix: 탈퇴한 회원 로그인 페이지로 리디렉션 * Feat: Menu 버튼 추가 * fix: build 오류 해결 --------- Co-authored-by: nirii00 <[email protected]> * feat : 알림 기능 구현 + QA (#114) * feat : 안읽은 알림 count갯수 ui 밑작업(전역변수 만듬) * feat : 알림 안읽은 메시지 UI처리 + SSE로직 1차 수정 * feat : 알림 토스트UI에 담기는 제목 바인딩 * feat : 알림 받을시의 코드 오류 수정 * feat : SSE 에러 5번 발생시 재귀 중지 코드 추가 * feat : 실시간 알림, UI 구현 완료 + 신고 모달 토스트UI 적용 * chore : 편지 받아올떄마다 console 출력하는 코드 주석처리 * feat : 임시저장 데이터 바인딩 및 임시저장 덮어씌우기 작업 완료 (#115) * refactor: 2차 QA 반영 (#116) * feat: 마이페이지에서 신고 횟수 조회 기능 구현 * design: button에 aria-label 추가하기 * design: 마이페이지 신고 횟수 조회 텍스트 수정 * perf: 오고 있는 편지가 존재하지 않을 때는 오고 있는 편지 모달 내에서 렌더링되지 않도록 * feat: 마이페이지에서 신고 횟수 클릭 시 신고 안내 모달이 뜨도록 * fix: 마이페이지에서 신고 횟수 조회 텍스트 오류 수정 --------- Co-authored-by: Seungyeon Han (Tiffany) <[email protected]> Co-authored-by: Minha Ahn <[email protected]> Co-authored-by: Sebin Kim <[email protected]> Co-authored-by: nirii00 <[email protected]>
1 parent 6071f76 commit 8378b1d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+606
-230
lines changed

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="kr">
33
<head>
44
<meta charset="UTF-8" />
5-
<link rel="icon" type="image/svg+xml" href="/public/favicon.ico" />
5+
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<title>36.5</title>
88
<link

src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import OnboardingPage from './pages/Onboarding';
2626
import RandomLettersPage from './pages/RandomLetters';
2727
import RollingPaperPage from './pages/RollingPaper';
2828
import WritePage from './pages/Write';
29+
import ShareApprovalPage from './pages/Share';
2930

3031
const App = () => {
3132
useViewport();
@@ -56,6 +57,7 @@ const App = () => {
5657
<Route path="letter" element={<LetterBoardPage />} />
5758
</Route>
5859
<Route path="letter/:id" element={<LetterBoardDetailPage />} />
60+
<Route path="share/:shareProposalId" element={<ShareApprovalPage />} />
5961
</Route>
6062
<Route path="mypage" element={<Layout />}>
6163
<Route index element={<MyPage />} />

src/apis/admin.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const postReports = async (postReportRequest: PostReportRequest) => {
77
return res;
88
} catch (error) {
99
console.error(error);
10+
return null;
1011
}
1112
};
1213

src/apis/notification.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,15 @@ const patchReadNotificationAll = async () => {
3131
}
3232
};
3333

34-
export { getTimeLines, patchReadNotification, patchReadNotificationAll };
34+
const getNotReadCount = async () => {
35+
try {
36+
const res = await client.get('/api/notifications/not-read');
37+
if (!res) throw new Error('안 읽은 알림 수를 가져오는 도중 오류가 발생했습니다.');
38+
console.log(res);
39+
return res;
40+
} catch (error) {
41+
console.error(error);
42+
}
43+
};
44+
45+
export { getTimeLines, patchReadNotification, patchReadNotificationAll, getNotReadCount };

src/apis/share.ts

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,26 @@ export interface ShareProposal {
3939
status: 'REJECTED' | 'APPROVED' | 'PENDING';
4040
}
4141

42+
//편지 공유 요청 상세 조회
43+
export interface ShareProposalLetter {
44+
id: number;
45+
content: string;
46+
writerZipCode: string;
47+
receiverZipCode: string;
48+
createdAt: string;
49+
}
50+
51+
export interface ShareProposalDetail {
52+
shareProposalId: number;
53+
requesterZipCode: string;
54+
recipientZipCode: string;
55+
message: string;
56+
status: 'PENDING' | 'ACCEPTED' | 'REJECTED';
57+
letters: ShareProposalLetter[];
58+
}
59+
4260
// 편지 공유 수락 / 거절
43-
export interface SharePostApproval {
61+
export interface ShareProposalApproval {
4462
shareProposalId: number;
4563
status: 'APPROVED' | 'REJECTED';
4664
sharePostId: number;
@@ -106,13 +124,27 @@ export const getShareProposalList = async () => {
106124
}
107125
};
108126

127+
// 편지 공유 요청 상세 조회
128+
export const getShareProposalDetail = async (
129+
shareProposalId: number,
130+
): Promise<ShareProposalDetail> => {
131+
try {
132+
const response = await client.get(`/api/share-proposals/${shareProposalId}`);
133+
console.log(`😎공유 요청 상세 조회 데이터 `, response.data);
134+
return response.data.data;
135+
} catch (error) {
136+
console.error('❌ 편지 공유 요청을 상세 조회하던 중 에러가 발생했습니다', error);
137+
throw error;
138+
}
139+
};
140+
109141
// 편지 공유 수락 / 거절
110142
export const postShareProposalApproval = async (
111143
shareProposalId: number,
112144
action: 'approve' | 'reject',
113-
): Promise<SharePostApproval> => {
145+
): Promise<ShareProposalApproval> => {
114146
try {
115-
const response = await client.patch(`/api/share-proposal/${shareProposalId}/${action}`);
147+
const response = await client.patch(`/api/share-proposals/${shareProposalId}/${action}`);
116148
return response.data;
117149
} catch (error) {
118150
console.error(

src/components/HomeButton.tsx

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/components/MenuButton.tsx

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import MenuRoundedIcon from '@mui/icons-material/MenuRounded';
2+
import EditNoteRoundedIcon from '@mui/icons-material/EditNoteRounded';
3+
import MarkunreadOutlinedIcon from '@mui/icons-material/MarkunreadOutlined';
4+
import CalendarTodayOutlinedIcon from '@mui/icons-material/CalendarTodayOutlined';
5+
6+
import { useState } from 'react';
7+
import { Link } from 'react-router';
8+
import { twMerge } from 'tailwind-merge';
9+
10+
export default function MenuButton() {
11+
const [isOpen, setIsOpen] = useState(false);
12+
13+
return (
14+
<>
15+
<div className="flex w-full max-w-150 justify-end pr-5 text-center">
16+
<Link
17+
to="/letter/box"
18+
className={twMerge(
19+
'bg-primary-3 fixed bottom-[220px] z-50 h-12 w-12 rotate-360 content-center rounded-full text-white transition-all duration-200 hover:scale-105 active:scale-90',
20+
isOpen
21+
? 'translate-y-0 rotate-0 opacity-100'
22+
: 'translate-y-[120%] rotate-180 opacity-0',
23+
)}
24+
>
25+
<MarkunreadOutlinedIcon fontSize="small" onClick={() => setIsOpen(false)} />
26+
</Link>
27+
<Link
28+
to="/board/letter"
29+
className={twMerge(
30+
'bg-primary-3 fixed bottom-[160px] z-50 h-12 w-12 rotate-360 content-center rounded-full text-white transition-all duration-200 hover:scale-105 active:scale-90',
31+
isOpen
32+
? 'translate-y-0 rotate-0 opacity-100'
33+
: 'translate-y-[120%] rotate-180 opacity-0',
34+
)}
35+
>
36+
<CalendarTodayOutlinedIcon fontSize="small" onClick={() => setIsOpen(false)} />
37+
</Link>
38+
<Link
39+
to="/letter/write"
40+
className={twMerge(
41+
'bg-primary-3 fixed bottom-[100px] z-50 h-12 w-12 rotate-360 content-center rounded-full text-white transition-all duration-200 hover:scale-105 active:scale-90',
42+
isOpen
43+
? 'translate-y-0 rotate-0 opacity-100'
44+
: 'translate-y-[120%] rotate-180 opacity-0',
45+
)}
46+
>
47+
<EditNoteRoundedIcon fontSize="medium" onClick={() => setIsOpen(false)} />
48+
</Link>
49+
50+
<div
51+
className={twMerge(
52+
'bg-primary-3 fixed bottom-[30px] z-50 h-13 w-13 content-center rounded-full text-white transition-all duration-200 hover:scale-105 active:scale-90',
53+
isOpen ? 'rotate-90' : 'rotate-0',
54+
)}
55+
>
56+
<MenuRoundedIcon onClick={() => setIsOpen((state) => !state)} />
57+
</div>
58+
</div>
59+
</>
60+
);
61+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { getNotReadCount } from '@/apis/notification';
2+
import { AlarmIcon } from '@/assets/icons';
3+
import useNotificationStore from '@/stores/notificationStore';
4+
import { useEffect } from 'react';
5+
import { Link } from 'react-router';
6+
import { twMerge } from 'tailwind-merge';
7+
8+
export default function NotificationButton() {
9+
const notReadCount = useNotificationStore((state) => state.notReadCount);
10+
const setNotReadCount = useNotificationStore((state) => state.setNotReadCount);
11+
const notReadStyle = twMerge(
12+
`absolute -right-1 -bottom-1 flex h-3.5 w-3.5 items-center justify-center rounded-full bg-red-400 text-[8px] text-white`,
13+
notReadCount >= 100 && 'w-4 h-4',
14+
);
15+
16+
const handleGetNotReadCount = async () => {
17+
const res = await getNotReadCount();
18+
if (res?.status === 200) {
19+
const updateNotReadCount: number = res.data.data.notReadCount;
20+
setNotReadCount(updateNotReadCount);
21+
}
22+
};
23+
24+
useEffect(() => {
25+
handleGetNotReadCount();
26+
});
27+
28+
return (
29+
<Link to="/mypage/notifications" className="relative">
30+
{notReadCount > 0 && (
31+
<div className={notReadStyle}>{notReadCount < 100 ? notReadCount : '99+'}</div>
32+
)}
33+
<AlarmIcon className="h-6 w-6 text-white" />
34+
</Link>
35+
);
36+
}

src/components/ReportModal.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { postReports } from '@/apis/admin';
55

66
import ConfirmModal from './ConfirmModal';
77
import TextareaField from './TextareaField';
8+
import useToastStore from '@/stores/toastStore';
89

910
interface ReportModalProps {
1011
reportType: ReportType;
@@ -29,7 +30,9 @@ const ReportModal = ({ reportType, letterId, onClose }: ReportModalProps) => {
2930
reportType: reportType,
3031
reasonType: '',
3132
reason: '',
32-
letterId: letterId,
33+
letterId: reportType === 'LETTER' ? letterId : null,
34+
sharePostId: reportType === 'SHARE_POST' ? letterId : null,
35+
eventCommentId: reportType === 'EVENT_COMMENT' ? letterId : null,
3336
});
3437

3538
const handleReasonClick = (reason: Reason) => {
@@ -38,14 +41,16 @@ const ReportModal = ({ reportType, letterId, onClose }: ReportModalProps) => {
3841
else setPostReportRequest((cur) => ({ ...cur, reasonType: reason }));
3942
};
4043

44+
const setToastActive = useToastStore((state) => state.setToastActive);
45+
4146
const handleSubmit = async () => {
4247
const res = await postReports(postReportRequest);
4348
if (res?.status === 200) {
44-
alert('신고 처리되었습니다.');
49+
setToastActive({ title: '신고가 접수되었습니다.', toastType: 'Success' });
4550
console.log(res);
4651
onClose();
47-
} else if (res?.status === 409) {
48-
alert('신고한 이력이 있습니다.');
52+
} else {
53+
setToastActive({ title: '신고한 이력이 있습니다.', toastType: 'Error' });
4954
onClose();
5055
}
5156
};

src/components/ToastItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default function ToastItem({ toastObj, index }: { toastObj: ToastObj; ind
2626

2727
const animation = `toast-blink ${toastObj.time}s ease-in-out forwards`;
2828
const toastStyle = twMerge(
29-
'fixed bottom-5 left-1/2 z-40 flex h-[40px] max-w-150 min-w-[300px] w-[100%] -translate-1/2 items-center justify-center rounded-lg caption-sb shadow-[0_1px_6px_rgba(200,200,200,0.2)]',
29+
'fixed bottom-5 left-1/2 z-40 flex h-[40px] max-w-150 min-w-[300px] w-[80%] -translate-1/2 items-center justify-center rounded-lg caption-sb shadow-[0_1px_6px_rgba(200,200,200,0.2)]',
3030
TOAST_POSITION[toastObj.position],
3131
TOAST_DESIGN[toastObj.toastType].style,
3232
);

0 commit comments

Comments
 (0)