Skip to content

Commit 5b4d4ba

Browse files
AAminhawldnjs990
andauthored
feat: 롤링페이퍼 추가 기능 구현 (#95)
* fix: 더미데이터 제거 * feat: 롤링페이퍼 무한 스크롤 적용 * feat: 관리자 페이지 롤링 페이퍼 설정 화면에 페이지네이션 적용 * design: 롤링페이퍼 작성 버튼 위치 수정 * fix: 데이터 변경 후 캐싱 초기화 하는 조건 수정 * design: 하단 언덕 이미지 깨지는 문제 해결 --------- Co-authored-by: wldnjs990 <[email protected]>
1 parent a0f576b commit 5b4d4ba

File tree

11 files changed

+142
-92
lines changed

11 files changed

+142
-92
lines changed

src/apis/rolling.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,18 @@ export const getCurrentRollingPaper = async (): Promise<RollingPaperInformation>
99

1010
export const getRollingPaperDetail = async (
1111
rollingPaperId: string | number,
12+
page: number,
13+
size: number,
1214
): Promise<RollingPaper> => {
1315
const {
1416
data: { data },
15-
} = await client.get(`/api/event-posts/${rollingPaperId}`);
17+
} = await client.get(`/api/event-posts/${rollingPaperId}`, {
18+
params: {
19+
page,
20+
size,
21+
},
22+
});
23+
console.log(data);
1624
return data;
1725
};
1826

@@ -49,11 +57,19 @@ export const postNewRollingPaper = async (title: string) => {
4957
}
5058
};
5159

52-
export const getRollingPaperList = async (): Promise<RollingPaperList> => {
60+
export const getRollingPaperList = async (
61+
page: string | number,
62+
size: number,
63+
): Promise<RollingPaperList> => {
5364
try {
5465
const {
5566
data: { data },
56-
} = await client.get('/api/admin/event-posts');
67+
} = await client.get('/api/admin/event-posts', {
68+
params: {
69+
page,
70+
size,
71+
},
72+
});
5773
return data;
5874
} catch (error) {
5975
console.error(error);

src/components/BackgroundBottom.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const BackgroundBottom = () => {
66
return (
77
<BackgroundImageWrapper
88
as="div"
9-
className="fixed bottom-[-40px] left-1/2 z-[-10] h-42 w-full -translate-x-1/2 opacity-70"
9+
className="fixed bottom-[-40px] left-1/2 h-42 w-full -translate-x-1/2 opacity-70"
1010
imageUrl={BgItem}
1111
/>
1212
);

src/components/ConfirmModal.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const ConfirmModal = ({
2222
onCancel,
2323
onConfirm,
2424
}: ConfirmModalProps) => {
25-
// TODO: 전역 상태로 관리해야하는지 고민
2625
return (
2726
<ModalOverlay>
2827
<div className="w-73">

src/pages/Admin/RollingPaper.tsx

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,28 @@ import PageTitle from './components/AdminPageTitle';
99
import RollingPaperItem from './components/RollingPaperItem';
1010
import WrapperFrame from './components/WrapperFrame';
1111
import WrapperTitle from './components/WrapperTitle';
12+
import PagenationNavigation from './components/PagenationNavigation';
13+
14+
const SIZE = 10;
1215

1316
export default function AdminRollingPaper() {
1417
const [activeModal, setActiveModal] = useState(false);
15-
const { data, isLoading, isSuccess } = useQuery({
16-
queryKey: ['admin-rolling-paper'],
17-
queryFn: getRollingPaperList,
18+
const [currentPage, setCurrentPage] = useState<string>('1');
19+
const { data, isLoading, isSuccess, refetch } = useQuery({
20+
queryKey: ['admin-rolling-paper', currentPage],
21+
queryFn: () => getRollingPaperList(currentPage ?? 1, SIZE),
1822
});
1923

24+
const handleNowPage = (page: string) => {
25+
setCurrentPage(page);
26+
refetch();
27+
};
28+
2029
return (
2130
<>
22-
{activeModal && <AddRollingPaperModal onClose={() => setActiveModal(false)} />}
31+
{activeModal && (
32+
<AddRollingPaperModal currentPage={currentPage} onClose={() => setActiveModal(false)} />
33+
)}
2334
<PageTitle>게시판 관리 / 롤링 페이퍼 설정</PageTitle>
2435
<WrapperFrame>
2536
<section className="flex items-center">
@@ -47,7 +58,11 @@ export default function AdminRollingPaper() {
4758
</thead>
4859
<tbody>
4960
{data.content.map((rollingPaper) => (
50-
<RollingPaperItem key={rollingPaper.eventPostId} information={rollingPaper} />
61+
<RollingPaperItem
62+
key={rollingPaper.eventPostId}
63+
information={rollingPaper}
64+
currentPage={currentPage}
65+
/>
5166
))}
5267
</tbody>
5368
</table>
@@ -58,7 +73,11 @@ export default function AdminRollingPaper() {
5873
)}
5974
</>
6075
)}
61-
{/* TODO: 페이지네이션 적용 */}
76+
<PagenationNavigation
77+
totalPage={Number(data?.totalPages)}
78+
buttonLength={5}
79+
handlePageNumberButtonClick={handleNowPage}
80+
/>
6281
</WrapperFrame>
6382
</>
6483
);

src/pages/Admin/components/AddRollingPaperModal.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ import { postNewRollingPaper } from '@/apis/rolling';
55
import ModalOverlay from '@/components/ModalOverlay';
66

77
interface AddRollingPaperModalProps {
8+
currentPage: number | string;
89
onClose: () => void;
910
}
1011

11-
export default function AddRollingPaperModal({ onClose }: AddRollingPaperModalProps) {
12+
export default function AddRollingPaperModal({ currentPage, onClose }: AddRollingPaperModalProps) {
1213
const [title, setTitle] = useState('');
1314
const [error, setError] = useState('');
1415
const queryClient = useQueryClient();
@@ -19,8 +20,7 @@ export default function AddRollingPaperModal({ onClose }: AddRollingPaperModalPr
1920
setTitle('');
2021
setError('');
2122
onClose();
22-
// TODO: 페이지네이션 적용 후, 현재 page에 대한 캐싱 날리는 방식으로 변경
23-
queryClient.invalidateQueries({ queryKey: ['admin-rolling-paper'] });
23+
queryClient.invalidateQueries({ queryKey: ['admin-rolling-paper', currentPage] });
2424
},
2525
onError: () => {
2626
setError('편지 작성에 실패했어요. 다시 시도해주세요.');

src/pages/Admin/components/PagenationNavigation.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ export default function PagenationNavigation({
5050
}
5151
};
5252

53-
const buttonStyle = 'border bg-white px-2 py-1 disabled:bg-gray-20';
53+
const buttonStyle = 'rounded-full bg-white w-8 h-8 disabled:bg-gray-20';
5454

5555
return (
5656
<div className="mt-5 flex h-10 w-full items-center justify-center">
57-
<div className="flex items-center">
57+
<div className="flex items-center gap-2">
5858
<button
59-
className={twMerge(buttonStyle)}
59+
className={twMerge(buttonStyle, 'w-14')}
6060
disabled={nowSection <= 0}
6161
onClick={() => {
6262
handlePrevButtonClick();
@@ -69,7 +69,7 @@ export default function PagenationNavigation({
6969
return (
7070
<button
7171
key={num}
72-
className={twMerge(buttonStyle, nowPageNumberAt === num && 'bg-accent-3')}
72+
className={twMerge(buttonStyle, nowPageNumberAt === num && 'bg-primary-2/50')}
7373
onClick={() => {
7474
handlePageButtonClick(num);
7575
}}
@@ -79,7 +79,7 @@ export default function PagenationNavigation({
7979
);
8080
})}
8181
<button
82-
className={twMerge(buttonStyle)}
82+
className={twMerge(buttonStyle, 'w-14')}
8383
disabled={nowSection >= totalSection}
8484
onClick={() => {
8585
handleNextButtonClick();

src/pages/Admin/components/RollingPaperItem.tsx

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,22 @@ import { AxiosError } from 'axios';
33

44
import { deleteRollingPaper, patchRollingPaper } from '@/apis/rolling';
55
import { DeleteIcon } from '@/assets/icons';
6+
import { useState } from 'react';
7+
import ConfirmModal from '@/components/ConfirmModal';
68

79
interface RollingPaperItemProps {
810
information: AdminRollingPaperInformation;
11+
currentPage: string | number;
912
}
1013

11-
export default function RollingPaperItem({ information }: RollingPaperItemProps) {
14+
export default function RollingPaperItem({ information, currentPage }: RollingPaperItemProps) {
15+
const [activeDeleteModal, setActiveDeleteModal] = useState(false);
1216
const queryClient = useQueryClient();
1317

1418
const { mutate: deleteMutate } = useMutation({
1519
mutationFn: () => deleteRollingPaper(information.eventPostId),
1620
onSuccess: () => {
17-
// TODO: 페이지네이션 적용 후, 현재 page에 대한 캐싱 날리는 방식으로 변경
18-
queryClient.invalidateQueries({ queryKey: ['admin-rolling-paper'] });
21+
queryClient.invalidateQueries({ queryKey: ['admin-rolling-paper', currentPage] });
1922
},
2023
onError: (err) => {
2124
console.error(err);
@@ -25,9 +28,7 @@ export default function RollingPaperItem({ information }: RollingPaperItemProps)
2528
const { mutate: toggleStatus } = useMutation({
2629
mutationFn: () => patchRollingPaper(information.eventPostId),
2730
onSuccess: () => {
28-
// TODO: 기존 데이터 수정하는 방식으로 ㄱㄱㄱㄱㄱㄱㄱ
29-
// 일단 임시로 캐싱 날리기
30-
queryClient.invalidateQueries({ queryKey: ['admin-rolling-paper'] });
31+
queryClient.invalidateQueries({ queryKey: ['admin-rolling-paper', currentPage] });
3132
},
3233
onError: (err: AxiosError<{ code: string; message: string }>) => {
3334
if (err.response?.data.code === 'EVENT-004') {
@@ -37,40 +38,53 @@ export default function RollingPaperItem({ information }: RollingPaperItemProps)
3738
},
3839
});
3940

40-
// TODO: 진짜 삭제하겠냐고 물어보기
4141
return (
42-
<tr className="border-gray-40 h-14 border-b">
43-
<td className="w-14 text-center">{information.eventPostId}</td>
44-
<td className="text-left">
45-
<div>
46-
{information.used && (
47-
<span className="mr-2 rounded-full border border-amber-500 bg-amber-100/70 px-3 py-0.5 whitespace-nowrap text-amber-500">
48-
진행 중
49-
</span>
50-
)}
51-
{information.title}
52-
</div>
53-
</td>
54-
<td className="text-center">
55-
<button
56-
type="button"
57-
className="hover:bg-gray-10 text-gray-60 rounded-md px-3 py-1 hover:text-black"
58-
onClick={() => toggleStatus()}
59-
>
60-
{information.used ? '중단하기' : '진행하기'}
61-
</button>
62-
</td>
63-
<td className="w-6">
64-
{!information.used && (
42+
<>
43+
{activeDeleteModal && (
44+
<ConfirmModal
45+
title="정말 롤링페이퍼를 삭제하시겠어요?"
46+
description="롤링페이퍼를 삭제하는 경우 복구가 불가능합니다!"
47+
cancelText="되돌아가기"
48+
confirmText="삭제하기"
49+
onCancel={() => {
50+
setActiveDeleteModal(false);
51+
}}
52+
onConfirm={deleteMutate}
53+
/>
54+
)}
55+
<tr className="border-gray-40 h-14 border-b">
56+
<td className="w-14 text-center">{information.eventPostId}</td>
57+
<td className="text-left">
58+
<div>
59+
{information.used && (
60+
<span className="mr-2 rounded-full border border-amber-500 bg-amber-100/70 px-3 py-0.5 whitespace-nowrap text-amber-500">
61+
진행 중
62+
</span>
63+
)}
64+
{information.title}
65+
</div>
66+
</td>
67+
<td className="text-center">
6568
<button
6669
type="button"
67-
className="text-gray-60 flex items-center justify-center p-1 hover:text-black"
68-
onClick={() => deleteMutate()}
70+
className="hover:bg-gray-10 text-gray-60 rounded-md px-3 py-1 hover:text-black"
71+
onClick={() => toggleStatus()}
6972
>
70-
<DeleteIcon className="h-5 w-5" />
73+
{information.used ? '중단하기' : '진행하기'}
7174
</button>
72-
)}
73-
</td>
74-
</tr>
75+
</td>
76+
<td className="w-6">
77+
{!information.used && (
78+
<button
79+
type="button"
80+
className="text-gray-60 flex items-center justify-center p-1 hover:text-black"
81+
onClick={() => setActiveDeleteModal(true)}
82+
>
83+
<DeleteIcon className="h-5 w-5" />
84+
</button>
85+
)}
86+
</td>
87+
</tr>
88+
</>
7589
);
7690
}

src/pages/LetterBoard/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const LetterBoardPage = () => {
5656

5757
return (
5858
<>
59-
<main className="mt-[-25px] flex grow flex-col px-5 pt-20 pb-10">
59+
<main className="z-1 mt-[-25px] flex grow flex-col px-5 pt-20 pb-10">
6060
<>
6161
<NoticeRollingPaper />
6262
<PageTitle className="mx-auto mt-4">게시판</PageTitle>

src/pages/MyPage/components/MyBoardPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const MyBoardPage = () => {
3939
}
4040
return (
4141
<>
42-
<main className={twMerge('flex grow flex-col px-5 pt-20 pb-10')}>
42+
<main className={twMerge('z-1 flex grow flex-col px-5 pt-20 pb-10')}>
4343
<PageTitle className="mx-auto mb-11">내가 올린 게시물</PageTitle>
4444
{isLoading ? (
4545
<p>loading</p>

src/pages/RollingPaper/components/WriteCommentButton.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import { useState } from 'react';
44
import { postRollingPaperComment } from '@/apis/rolling';
55
import EnvelopeImg from '@/assets/images/closed-letter.png';
66
import MessageModal from '@/components/MessageModal';
7-
8-
const DUMMY_USER_ZIP_CODE = '1DR41';
7+
import useAuthStore from '@/stores/authStore';
98

109
interface WriteCommentButtonProps {
1110
rollingPaperId: string;
@@ -15,12 +14,12 @@ const WriteCommentButton = ({ rollingPaperId }: WriteCommentButtonProps) => {
1514
const [activeMessageModal, setActiveMessageModal] = useState(false);
1615
const [newMessage, setNewMessage] = useState('');
1716
const [error, setError] = useState<string | null>(null);
17+
const zipCode = useAuthStore((props) => props.zipCode);
1818
const queryClient = useQueryClient();
1919

2020
const { mutate } = useMutation({
2121
mutationFn: (content: string) => postRollingPaperComment(rollingPaperId, content),
22-
onSuccess: (data) => {
23-
console.log(data);
22+
onSuccess: () => {
2423
queryClient.invalidateQueries({ queryKey: ['rolling-paper', rollingPaperId] });
2524
setNewMessage('');
2625
setError(null);
@@ -37,7 +36,6 @@ const WriteCommentButton = ({ rollingPaperId }: WriteCommentButtonProps) => {
3736

3837
const handleAddComment = () => {
3938
console.log(rollingPaperId);
40-
// 추가 가능한지 조건 확인
4139
if (newMessage.trim() === '') {
4240
setError('편지를 작성해주세요.');
4341
return;
@@ -59,12 +57,12 @@ const WriteCommentButton = ({ rollingPaperId }: WriteCommentButtonProps) => {
5957
onComplete={handleAddComment}
6058
>
6159
<p className="body-r text-accent-1 mt-1">{error}</p>
62-
<p className="body-r mt-5 text-end text-black">From. {DUMMY_USER_ZIP_CODE}</p>
60+
<p className="body-r mt-5 text-end text-black">From. {zipCode}</p>
6361
</MessageModal>
6462
)}
6563
<button
6664
type="button"
67-
className="fixed bottom-7.5 left-5 overflow-hidden rounded-sm"
65+
className="sticky bottom-8 z-10 mt-4 -mb-4 self-start overflow-hidden rounded-sm"
6866
onClick={() => setActiveMessageModal(true)}
6967
>
7068
<img src={EnvelopeImg} alt="편지지 이미지" className="h-12 w-auto opacity-70" />

0 commit comments

Comments
 (0)