Skip to content

Commit 017589c

Browse files
authored
Merge pull request #82 from cskime/feature/#52
[#52] API 연동 (3)
2 parents 6496315 + abf5300 commit 017589c

File tree

5 files changed

+117
-22
lines changed

5 files changed

+117
-22
lines changed

src/features/message/api/messages.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import axios from "axios";
12
import { apiClient } from "../../../api/client";
23

4+
let nextPage;
5+
36
async function getMessages({ recipientId, limit, page = 1 }) {
47
const searchParams = new URLSearchParams();
58
searchParams.append("page", page);
@@ -15,7 +18,30 @@ async function getMessages({ recipientId, limit, page = 1 }) {
1518
}
1619

1720
const data = response.data;
21+
nextPage = data.next;
22+
1823
return data.results;
1924
}
2025

21-
export { getMessages };
26+
async function getNextPageMessages() {
27+
if (!nextPage) return;
28+
29+
const response = await axios.get(nextPage);
30+
if (response.status !== 200) {
31+
throw new Error("Message data를 가져오는데 실패했습니다.");
32+
}
33+
34+
const data = response.data;
35+
nextPage = data.next;
36+
37+
return data.results;
38+
}
39+
40+
async function deleteMessage({ id }) {
41+
const response = await apiClient.delete(`messages/${id}/`);
42+
if (response.status !== 204) {
43+
throw new Error("Message를 삭제하는데 실패했습니다.");
44+
}
45+
}
46+
47+
export { deleteMessage, getMessages, getNextPageMessages };
Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import { useRef } from "react";
12
import { useNavigate, useParams } from "react-router";
23
import styled from "styled-components";
3-
import Modal from "../../../../components/modal/modal.jsx";
4-
import { media } from "../../../../utils/media.js";
5-
import MessageCardAdd from "../../../message/components/message-card-add.jsx";
6-
import MessageCardDetail from "../../../message/components/message-card-detail.jsx";
7-
import MessageCard from "../../../message/components/message-card.jsx";
4+
import Modal from "../../../components/modal/modal.jsx";
5+
import { useIntersectionObserver } from "../../../hooks/use-intersection-observer.jsx";
6+
import { media } from "../../../utils/media.js";
7+
import MessageCardAdd from "./message-card-add.jsx";
8+
import MessageCardDetail from "./message-card-detail.jsx";
9+
import MessageCard from "./message-card.jsx";
810

911
const StyledRollingPaperMessagesGrid = styled.div`
1012
display: grid;
@@ -22,9 +24,16 @@ const StyledRollingPaperMessagesGrid = styled.div`
2224
}
2325
`;
2426

25-
function RollingPaperMessagesGrid({ isEditing, messages, onDelete }) {
27+
function MessagesGrid({ isEditing, messages, onDelete, onInfiniteScroll }) {
2628
const navigate = useNavigate();
2729
const { id } = useParams();
30+
const infiniteScrollTargetRef = useRef();
31+
32+
const observerCallback = (entry) => {
33+
if (!entry.isIntersecting) return;
34+
onInfiniteScroll();
35+
};
36+
useIntersectionObserver(infiniteScrollTargetRef, observerCallback);
2837

2938
const handleAddClick = () => {
3039
navigate(`/post/${id}/message`);
@@ -39,7 +48,7 @@ function RollingPaperMessagesGrid({ isEditing, messages, onDelete }) {
3948
key={message.id}
4049
isEditing={isEditing}
4150
message={message}
42-
onDelete={(event) => handleDeleteClick(event, message.id)}
51+
onDelete={() => handleDeleteClick(message.id)}
4352
/>
4453
);
4554

@@ -55,8 +64,9 @@ function RollingPaperMessagesGrid({ isEditing, messages, onDelete }) {
5564
</Modal>
5665
)
5766
)}
67+
<div ref={infiniteScrollTargetRef}></div>
5868
</StyledRollingPaperMessagesGrid>
5969
);
6070
}
6171

62-
export default RollingPaperMessagesGrid;
72+
export default MessagesGrid;

src/features/rolling-paper/api/recipients.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,11 @@ async function getRecipient({ id }) {
99
return response.data;
1010
}
1111

12-
export { getRecipient };
12+
async function deleteRecipient({ id }) {
13+
const response = await apiClient.delete(`recipients/${id}/`);
14+
if (response.status !== 204) {
15+
throw new Error("Recipient를 삭제하는데 실패했습니다.");
16+
}
17+
}
18+
19+
export { deleteRecipient, getRecipient };
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { useEffect } from "react";
2+
3+
function useIntersectionObserver(targetRef, callback) {
4+
useEffect(() => {
5+
const observer = new IntersectionObserver((entries) => {
6+
entries.forEach(callback);
7+
});
8+
9+
if (targetRef) {
10+
observer.observe(targetRef.current);
11+
}
12+
13+
return () => {
14+
observer.disconnect();
15+
};
16+
}, [targetRef, callback]);
17+
}
18+
19+
export { useIntersectionObserver };

src/pages/messages-page.jsx

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,17 @@ import styled from "styled-components";
44
import { OutlinedButton, PrimaryButton } from "../components/button/button";
55
import BUTTON_SIZE from "../components/button/button-size";
66
import BACKGROUND_COLOR from "../components/color/background-color";
7-
import { getMessages } from "../features/message/api/messages";
8-
import { getRecipient } from "../features/rolling-paper/api/recipients";
7+
import {
8+
deleteMessage,
9+
getMessages,
10+
getNextPageMessages,
11+
} from "../features/message/api/messages";
12+
import MessagesGrid from "../features/message/components/messages-grid";
13+
import {
14+
deleteRecipient,
15+
getRecipient,
16+
} from "../features/rolling-paper/api/recipients";
917
import RollingPaperHeader from "../features/rolling-paper/components/header/rolling-paper-header";
10-
import RollingPaperMessagesGrid from "../features/rolling-paper/components/messages/rolling-paper-messages-grid";
1118
import { useMedia } from "../hooks/use-media";
1219
import ContentLayout from "../layouts/content-layout";
1320
import { media } from "../utils/media";
@@ -74,7 +81,7 @@ function EditingButtons({ onDelete, onCancel }) {
7481
/>
7582
<OutlinedButton
7683
size={BUTTON_SIZE.medium}
77-
title="취소하기"
84+
title="완료하기"
7885
onClick={onCancel}
7986
/>
8087
</ButtonContainer>
@@ -98,19 +105,44 @@ function MessagesPage() {
98105
navigate("edit");
99106
};
100107

101-
const handleRollingPaperDelete = () => {
102-
// TODO: Rolling Paper 삭제
103-
console.log(`Delete Rolling Paper ${recipient.id}`);
104-
navigate(-1);
108+
const handleRollingPaperDelete = async () => {
109+
try {
110+
await deleteRecipient({ id: recipient.id });
111+
navigate(`/list`);
112+
} catch (error) {
113+
// TODO: Error 처리
114+
console.log(error);
115+
}
105116
};
106117

107118
const handleEditCancel = () => {
108119
navigate(-1);
109120
};
110121

111-
const handleMessageDelete = (messageId) => {
112-
// TODO: Message 삭제
113-
console.log(`Delete Message ${messageId}`);
122+
const handleMessageDelete = async (messageId) => {
123+
try {
124+
await deleteMessage({ id: messageId });
125+
setMessages((prev) => prev.filter((message) => message.id !== messageId));
126+
} catch (error) {
127+
// TODO: Error 처리
128+
console.log(error);
129+
}
130+
};
131+
132+
const handleInfiniteScroll = async () => {
133+
const messages = await getNextPageMessages();
134+
if (!messages) return;
135+
136+
setMessages((prev) => {
137+
const newMessages = [...prev];
138+
139+
for (const message of messages) {
140+
if (newMessages.find((value) => value.id === message.id)) continue;
141+
newMessages.push(message);
142+
}
143+
144+
return newMessages;
145+
});
114146
};
115147

116148
useEffect(() => {
@@ -155,10 +187,11 @@ function MessagesPage() {
155187
) : (
156188
<ViewerButtons onEdit={handleEditClick} />
157189
)}
158-
<RollingPaperMessagesGrid
190+
<MessagesGrid
159191
isEditing={isEditing}
160192
messages={messages}
161193
onDelete={handleMessageDelete}
194+
onInfiniteScroll={handleInfiniteScroll}
162195
/>
163196
</div>
164197
</Content>

0 commit comments

Comments
 (0)