Skip to content

Commit f14d139

Browse files
committed
feat:알림 컨텐츠 상호작용, 라우팅 기능 구현
1 parent 5ca4f51 commit f14d139

File tree

6 files changed

+116
-26
lines changed

6 files changed

+116
-26
lines changed

src/apis/notification.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import client from './client';
2+
3+
const getTimeLines = async (getNoti: React.Dispatch<React.SetStateAction<Noti[]>>) => {
4+
try {
5+
const res = await client.get('/api/timelines');
6+
if (!res) throw new Error('타임라인을 받아오는 도중 오류가 발생했습니다.');
7+
getNoti(res.data.data);
8+
console.log(res);
9+
} catch (error) {
10+
console.error(error);
11+
}
12+
};
13+
14+
export { getTimeLines };

src/pages/Notifications/components/NotificationItem.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import { NOTIFICATION_ICON } from '../constants';
55
interface NotificationItemProps {
66
type: string;
77
message: string;
8-
isRead: boolean;
8+
read: boolean;
99
onClick: () => void;
1010
}
1111

12-
const NotificationItem = ({ type, message, isRead, onClick }: NotificationItemProps) => {
12+
const NotificationItem = ({ type, message, read, onClick }: NotificationItemProps) => {
1313
const Icon = NOTIFICATION_ICON[type];
1414

1515
const handleClick = (e: React.MouseEvent<HTMLElement>) => {
@@ -18,9 +18,9 @@ const NotificationItem = ({ type, message, isRead, onClick }: NotificationItemPr
1818
};
1919

2020
return (
21-
<LetterWrapper isSender={type === 'warning'} onClick={handleClick}>
21+
<LetterWrapper isSender={type === 'REPORT'} onClick={handleClick}>
2222
<div className="flex items-center gap-3">
23-
{isRead && <div className="absolute inset-0 z-10 bg-white/60" />}
23+
{read && <div className="absolute inset-0 z-10 bg-white/60" />}
2424
<Icon className="z-0 h-6 w-6 text-white" />
2525
<p className="body-m text-gray-80 z-0">{message}</p>
2626
</div>

src/pages/Notifications/components/WarningModal.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import ModalOverlay from '@/components/ModalOverlay';
44

55
interface WarningModalProps {
66
isOpen: boolean;
7+
adminText: string;
78
onClose: () => void;
89
}
910

10-
const WarningModal = ({ isOpen, onClose }: WarningModalProps) => {
11+
const WarningModal = ({ isOpen, adminText, onClose }: WarningModalProps) => {
1112
if (!isOpen) return null;
1213

1314
return (
@@ -20,11 +21,15 @@ const WarningModal = ({ isOpen, onClose }: WarningModalProps) => {
2021
>
2122
<div className="absolute inset-0 h-full w-full bg-white/90 blur-[25px]" />
2223
<div className="relative">
24+
<h2 className="body-sb mb-1.5 text-gray-100">관리자 코멘트</h2>
25+
<p className="caption-r mb-5 text-black">{adminText}</p>
26+
2327
<h2 className="body-sb mb-1.5 text-gray-100">경고 안내</h2>
2428
<p className="caption-r mb-5 text-black">
2529
따사로운 서비스 이용을 위해, 부적절하다고 판단되는 편지는 반려하고 있어요. 서로를
2630
존중하는 따뜻한 공간을 만들기 위해 협조 부탁드립니다.
2731
</p>
32+
2833
<h2 className="body-sb mb-1.5 text-gray-100">경고 규칙</h2>
2934
<p className="caption-r text-black">
3035
1회 경고: 주의 안내

src/pages/Notifications/constants/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ export const NOTIFICATION_ICON: Record<
44
string,
55
React.ComponentType<React.SVGProps<SVGSVGElement>>
66
> = {
7-
letter: EnvelopeIcon,
8-
warning: SirenFilledIcon,
9-
board: BoardIcon,
7+
LETTER: EnvelopeIcon,
8+
REPORT: SirenFilledIcon,
9+
SHARE: BoardIcon,
10+
POSTED: BoardIcon,
1011
};

src/pages/Notifications/index.tsx

Lines changed: 81 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,113 @@
1-
import { useState } from 'react';
1+
import { useEffect, useState } from 'react';
2+
import { useNavigate } from 'react-router';
23

4+
import { getTimeLines } from '@/apis/notification';
35
import PageTitle from '@/components/PageTitle';
46

57
import NotificationItem from './components/NotificationItem';
68
import WarningModal from './components/WarningModal';
79

8-
const DUMMY_NOTI = [
9-
{ id: 1, type: 'letter', message: '12E31님이 편지를 보냈습니다.', isRead: false },
10-
{ id: 2, type: 'warning', message: '따숨님, 욕설로 인해 경고를 받으셨어요.', isRead: false },
11-
{ id: 3, type: 'letter', message: '12E31님이 편지를 보냈습니다.', isRead: false },
12-
{ id: 4, type: 'letter', message: '12E31님이 편지를 보냈습니다.', isRead: true },
13-
{ id: 5, type: 'letter', message: '12E31님이 편지를 보냈습니다.', isRead: false },
14-
{ id: 6, type: 'board', message: '12E31님과의 대화가 게시판에 공유되었어요.', isRead: false },
10+
const DUMMY_NOTI: Noti[] = [
1511
{
16-
id: 7,
17-
type: 'board',
12+
timelineId: 1,
13+
alarmType: 'LETTER',
14+
content: 1,
15+
message: '12E31님이 편지를 보냈습니다.',
16+
read: false,
17+
},
18+
{
19+
timelineId: 2,
20+
alarmType: 'REPORT',
21+
content: '욕설 확인되어 경고 조치함.',
22+
message: '따숨님, 욕설로 인해 경고를 받으셨어요.',
23+
read: false,
24+
},
25+
{
26+
timelineId: 3,
27+
alarmType: 'LETTER',
28+
content: 1,
29+
message: '12E31님이 편지를 보냈습니다.',
30+
read: false,
31+
},
32+
{
33+
timelineId: 4,
34+
alarmType: 'LETTER',
35+
content: 1,
36+
message: '12E31님이 편지를 보냈습니다.',
37+
read: true,
38+
},
39+
{
40+
timelineId: 5,
41+
alarmType: 'LETTER',
42+
content: 1,
43+
message: '12E31님이 편지를 보냈습니다.',
44+
read: false,
45+
},
46+
{
47+
timelineId: 6,
48+
alarmType: 'POSTED',
49+
content: 1,
50+
message: '12E31님과의 대화가 게시판에 공유되었어요.',
51+
read: false,
52+
},
53+
{
54+
timelineId: 7,
55+
alarmType: 'SHARE',
56+
content: 1,
1857
message: '12E31님과의 게시글에 대한 공유요청을 보냈어요.',
19-
isRead: false,
58+
read: false,
2059
},
2160
];
2261

2362
const NotificationsPage = () => {
63+
const navigate = useNavigate();
64+
65+
const [noti, getNoti] = useState<Noti[]>([]);
66+
2467
const [isOpenWarningModal, setIsOpenWarningModal] = useState(false);
2568

26-
const handleClickItem = (type: string) => {
27-
if (type === 'warning') {
69+
const [adminText, setAdmintext] = useState<string>('');
70+
71+
const handleClickItem = (alarmType: string, content?: string | number) => {
72+
if (alarmType === 'LETTER') {
73+
navigate(`/letter/${content}`);
74+
}
75+
if (alarmType === 'REPORT') {
2876
setIsOpenWarningModal(true);
77+
if (typeof content === 'string') setAdmintext(content);
78+
}
79+
if (alarmType === 'SHARE') {
80+
navigate(`/board/letter/${content}`, { state: { isShareLetterPreview: true } });
81+
}
82+
if (alarmType === 'POSTED') {
83+
navigate(`/board/letter/${content}`);
2984
}
3085
};
3186

87+
useEffect(() => {
88+
getTimeLines(getNoti);
89+
}, []);
90+
3291
return (
3392
<>
34-
<WarningModal isOpen={isOpenWarningModal} onClose={() => setIsOpenWarningModal(false)} />
93+
<WarningModal
94+
isOpen={isOpenWarningModal}
95+
adminText={adminText}
96+
onClose={() => setIsOpenWarningModal(false)}
97+
/>
3598
<main className="flex grow flex-col items-center px-5 pt-20 pb-9">
3699
<PageTitle className="mb-10">알림</PageTitle>
37100
<button type="button" className="body-sb text-gray-60 place-self-end">
38101
모두 읽음
39102
</button>
40103
<ul className="mt-2 flex h-full w-full flex-col gap-2 pb-10">
41104
{DUMMY_NOTI.map((notification) => (
42-
<li key={notification.id}>
105+
<li key={notification.timelineId}>
43106
<NotificationItem
44-
type={notification.type}
107+
type={notification.alarmType}
45108
message={notification.message}
46-
isRead={notification.isRead}
47-
onClick={() => handleClickItem(notification.type)}
109+
read={notification.read}
110+
onClick={() => handleClickItem(notification.alarmType, notification.content)}
48111
/>
49112
</li>
50113
))}

src/types/notifications.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
interface Noti {
2+
timelineId: number;
3+
alarmType: string;
4+
content: string | number;
5+
message: string;
6+
read: boolean;
7+
}

0 commit comments

Comments
 (0)