Skip to content

Commit 1d0e411

Browse files
authored
merge: notification 기능
refactor: notification 기능
2 parents 94a4d5f + 28cd3e0 commit 1d0e411

6 files changed

Lines changed: 161 additions & 93 deletions

File tree

src/components/Card/index.jsx

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

src/components/Header/index.jsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import styled from '@emotion/styled';
22
import { useNavigate } from 'react-router-dom';
33
import { Icon, Text, FixedContainer } from 'components';
44
import theme from 'styles/theme';
5-
import { memo } from 'react';
5+
import { memo, useEffect } from 'react';
6+
import Badge from 'components/basic/Badge';
7+
import useLocalToken from 'hooks/useLocalToken';
8+
import { useState } from 'react';
9+
import { getNotifications } from 'utils/apis/userApi';
610

711
const { headerHeight, pagePadding } = theme.value;
812
const { borderLight } = theme.color;
@@ -39,10 +43,16 @@ const InnerRight = styled.div`
3943

4044
export const Header = ({ prev, title, info, complete, onComplete }) => {
4145
const navigate = useNavigate();
42-
4346
const onClickPrev = () => {
4447
navigate(-1);
4548
};
49+
const [isSeen, setIsSeen] = useState(true);
50+
const [token] = useLocalToken();
51+
const initNotifications = async () => {
52+
const fetchedNotifications = await getNotifications(token);
53+
setIsSeen(fetchedNotifications.data[0].seen);
54+
};
55+
initNotifications();
4656

4757
return (
4858
<HeaderContainer top height={headerHeight}>
@@ -53,7 +63,9 @@ export const Header = ({ prev, title, info, complete, onComplete }) => {
5363
<InnerRight>
5464
{info && (
5565
<>
56-
<Icon.Link to="/user/notification" name="NOTIFICATION" size={30} />
66+
<Badge dot={isSeen}>
67+
<Icon.Link to="/user/notification" name="NOTIFICATION" size={30} />
68+
</Badge>
5769
<Icon.Link to="/user/myinfo" name="MY_INFO" size={30} />
5870
</>
5971
)}

src/components/NotificationCard/index.jsx

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,77 @@
11
import styled from '@emotion/styled';
22
import theme from 'styles/theme';
3-
import { Card } from 'components';
4-
import displayedAt from 'utils/functions/displayedAt';
3+
import { Avatar, Text } from 'components';
4+
import { IMAGE_URLS } from 'utils/constants/images';
5+
import { setNotificationSeen } from 'utils/apis/postApi';
6+
import useLocalToken from 'hooks/useLocalToken';
7+
8+
const NotificationText = styled(Text)`
9+
margin-bottom: 7px;
10+
`;
11+
12+
const Container = styled.div`
13+
width: 100%;
14+
display: flex;
15+
align-items: center;
16+
`;
17+
18+
const Div = styled.div`
19+
display: flex;
20+
flex-direction: column;
21+
justify-content: center;
22+
margin-left: ${({ gap }) => gap};
23+
`;
24+
25+
const CardWrapper = styled.div`
26+
background-color: ${theme.color.mainWhite};
27+
width: 100%;
28+
height: 129px;
29+
border-radius: 15px;
30+
padding: 35px 65px 35px 30px;
31+
margin-bottom: 16px;
32+
display: flex;
33+
justify-content: center;
34+
`;
535

636
const NotificationCard = ({
7-
notificationId,
8-
postId,
9-
message,
37+
size = 60,
38+
gap = '25px',
39+
color,
40+
fontSize = 18,
1041
fullName,
11-
userId,
1242
isSeen,
13-
img,
14-
createdAt,
43+
message,
44+
children,
45+
img = IMAGE_URLS.PROFILE_IMG,
46+
...props
1547
}) => {
16-
const CardWrapper = styled.div`
17-
background-color: ${theme.color.mainWhite};
18-
width: 100%;
19-
height: 129px;
20-
border-radius: 15px;
21-
padding: 35px 65px 35px 30px;
22-
margin-bottom: 16px;
23-
display: flex;
24-
justify-content: center;
25-
`;
48+
const [token] = useLocalToken();
49+
const handleClick = async () => {
50+
await setNotificationSeen(token);
51+
};
2652
return (
27-
<CardWrapper>
28-
<Card src={img} fullName={fullName} message={message}>
29-
<span>{displayedAt(createdAt)}</span>
30-
</Card>
31-
</CardWrapper>
53+
!isSeen && (
54+
<CardWrapper onClick={handleClick}>
55+
<Container {...props}>
56+
<Avatar src={img} alt="유저 프로필 이미지" size={size} />
57+
<Div gap={gap}>
58+
<NotificationText
59+
style={{ wordBreak: 'keep-all' }}
60+
color={color}
61+
lineHeight={'24.52px'}
62+
>
63+
<Text fontWeight={600} fontSize={fontSize}>
64+
{fullName}
65+
</Text>
66+
<Text fontSize={fontSize}>{message}</Text>
67+
</NotificationText>
68+
<Text color={theme.color.fontNormal} fontSize={16}>
69+
{children}
70+
</Text>
71+
</Div>
72+
</Container>
73+
</CardWrapper>
74+
)
3275
);
3376
};
3477

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import styled from '@emotion/styled';
2+
3+
const BadgeContainer = styled.div`
4+
position: relative;
5+
display: inline-block;
6+
`;
7+
8+
const Super = styled.sup`
9+
position: absolute;
10+
top: 0;
11+
right: 0;
12+
display: inline-flex;
13+
align-items: center;
14+
height: 20px;
15+
padding: 0 8px;
16+
font-size: 12px;
17+
color: white;
18+
border-radius: 20px;
19+
background-color: #f44;
20+
transform: translate(50%, -50%);
21+
&.dot {
22+
padding: 0;
23+
width: 6px;
24+
height: 6px;
25+
border-radius: 50%;
26+
}
27+
`;
28+
29+
const Badge = ({
30+
children,
31+
count,
32+
maxCount,
33+
showZero,
34+
dot,
35+
backgroundColor,
36+
textColor,
37+
...props
38+
}) => {
39+
const colorStyle = {
40+
backgroundColor,
41+
color: textColor,
42+
};
43+
44+
let badge = null;
45+
if (count) {
46+
badge = (
47+
<Super style={colorStyle}>{maxCount && count > maxCount ? `${maxCount}+` : count}</Super>
48+
);
49+
} else {
50+
if (count !== undefined) {
51+
badge = showZero ? <Super style={colorStyle}>0</Super> : null;
52+
} else if (!dot) {
53+
badge = <Super className="dot" style={colorStyle} />;
54+
}
55+
}
56+
57+
return (
58+
<BadgeContainer {...props}>
59+
{children}
60+
{badge}
61+
</BadgeContainer>
62+
);
63+
};
64+
65+
export default Badge;

src/components/index.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ export { default as PageWrapper } from './basic/PageWrapper';
77
export { default as Tab } from './basic/Tab';
88
export { default as Text } from './basic/Text';
99

10-
export { default as Card } from './Card';
1110
export { default as ChangeNameForm } from './ChangeNameForm';
1211
export { default as ChangePasswordForm } from './ChangePasswordForm';
1312
export { default as ChangeProfileModal } from './ChangeProfileModal';

src/pages/NotificationPage/index.jsx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import useLocalToken from 'hooks/useLocalToken';
44
import { useEffect, useState } from 'react';
55
import { Link } from 'react-router-dom';
66
import styled from '@emotion/styled';
7-
import { useUserContext } from 'contexts/UserContext';
87
import theme from 'styles/theme';
8+
import displayedAt from 'utils/functions/displayedAt';
9+
import { setNotificationSeen } from 'utils/apis/postApi';
910

1011
const NotificationsWrapper = styled.div`
1112
background-color: ${theme.color.backgroundLight};
@@ -17,7 +18,6 @@ const NotificationsWrapper = styled.div`
1718
const NotificationPage = () => {
1819
const [token] = useLocalToken();
1920
const [notifications, setNotifications] = useState([]);
20-
const { currentUser } = useUserContext();
2121
useEffect(() => {
2222
const initNotifications = async () => {
2323
const fetchedNotifications = await getNotifications(token);
@@ -44,23 +44,19 @@ const NotificationPage = () => {
4444
);
4545
};
4646
initNotifications();
47+
return () => {
48+
const readNotifications = async () => {
49+
setNotificationSeen(token);
50+
};
51+
readNotifications();
52+
};
4753
}, []);
4854
return (
4955
<>
5056
<PageWrapper title="알림" header prev>
5157
<NotificationsWrapper>
5258
{notifications.map(
53-
({
54-
notificationId,
55-
postId,
56-
fullName,
57-
message,
58-
userId,
59-
authorId,
60-
isSeen,
61-
img,
62-
createdAt,
63-
}) =>
59+
({ notificationId, postId, fullName, message, authorId, isSeen, img, createdAt }) =>
6460
message &&
6561
(postId ? (
6662
<Link to={`/post/detail/${postId}`} key={notificationId}>
@@ -71,7 +67,9 @@ const NotificationPage = () => {
7167
message={message}
7268
img={img}
7369
createdAt={createdAt}
74-
></NotificationCard>
70+
>
71+
<span>{displayedAt(createdAt)}</span>
72+
</NotificationCard>
7573
</Link>
7674
) : (
7775
<Link to={`/user/${authorId}`} key={notificationId}>
@@ -82,7 +80,9 @@ const NotificationPage = () => {
8280
message={message}
8381
img={img}
8482
createdAt={createdAt}
85-
></NotificationCard>
83+
>
84+
<span>{displayedAt(createdAt)}</span>
85+
</NotificationCard>
8686
</Link>
8787
)),
8888
)}

0 commit comments

Comments
 (0)