From b5e9f4c01c75d0c50911904621fd2964bf27f676 Mon Sep 17 00:00:00 2001 From: Romas Bitinas <93491714+pupixipup@users.noreply.github.com> Date: Sat, 24 Feb 2024 21:35:35 +0100 Subject: [PATCH] feat: add friend notification --- .../[username]/profile/ui/friends/friends.tsx | 20 +++--- .../features/friend-button/friend-button.tsx | 29 +++++---- .../notification-item/friend-notification.tsx | 62 +++++++++++++++++++ .../notification-item.module.scss | 4 ++ .../notification-item/notification-item.tsx | 3 + 5 files changed, 100 insertions(+), 18 deletions(-) create mode 100644 client/src/widgets/sidebar/ui/notification-item/friend-notification.tsx diff --git a/client/src/app/(main)/[username]/profile/ui/friends/friends.tsx b/client/src/app/(main)/[username]/profile/ui/friends/friends.tsx index 58e6a0ce9..e6f29d959 100644 --- a/client/src/app/(main)/[username]/profile/ui/friends/friends.tsx +++ b/client/src/app/(main)/[username]/profile/ui/friends/friends.tsx @@ -8,6 +8,7 @@ import { ArrowRightIcon } from '@/shared/assets'; import { useState } from 'react'; import layoutStyles from '../../layout.module.scss'; import { FriendsModal } from './friends-modal'; +import { IUserBase } from '@teameights/types'; export const Friends = () => { const { username } = useParams(); @@ -26,14 +27,19 @@ export const Friends = () => { ); if (friendshipList.length) { - const friendsList = friendshipList - .map(friendship => { + const friendsList = friendshipList.reduce((accumulator, friendship) => { + if (friendship.status === 'accepted') { const { receiver, creator } = friendship; - if (receiver.id !== user?.id) return receiver; - return creator; - }) - .filter((friend, i, arr) => arr.findIndex(item => item.id === friend.id) === i); - // filter out duplicates, since there can be two similar friendships with different creators + const friend = receiver.id !== user?.id ? receiver : creator; + + const existingFriendIndex = accumulator.findIndex(item => item?.id === friend.id); + // filter out duplicates, since there can be two similar friendships with different creators + if (existingFriendIndex === -1) { + accumulator.push(friend); + } + } + return accumulator; + }, []); const noun = friendsList.length === 1 ? 'friend' : 'friends'; friendsContainer = ( diff --git a/client/src/features/friend-button/friend-button.tsx b/client/src/features/friend-button/friend-button.tsx index 4ed7a638e..967808231 100644 --- a/client/src/features/friend-button/friend-button.tsx +++ b/client/src/features/friend-button/friend-button.tsx @@ -8,9 +8,16 @@ import { useHandleFriendshipRequest } from '@/entities/session/api/useHandleFrie interface FriendButtonProps { myId?: number; userId: number; + short?: boolean; + size?: 'm' | 'l' | 's'; } -export const FriendButton = ({ myId, userId }: FriendButtonProps) => { +function getText(text: string, short: boolean) { + if (short) return text; + return text + ' friend'; +} + +export const FriendButton = ({ myId, userId, short = false, size = 'm' }: FriendButtonProps) => { const { mutate: addFriend } = useAddFriend(myId, userId); const { mutate: removeFriend } = useRemoveFriend(userId); const { mutate: declineFriend } = useHandleFriendshipRequest(myId, userId, 'rejected'); @@ -28,10 +35,10 @@ export const FriendButton = ({ myId, userId }: FriendButtonProps) => { friendship.status !== 'rejected' ); - if (!ourFriendshipIndex || ourFriendshipIndex === -1) { + if (ourFriendshipIndex === undefined || ourFriendshipIndex === -1) { return ( - ); @@ -45,22 +52,22 @@ export const FriendButton = ({ myId, userId }: FriendButtonProps) => { switch (friendshipStatus) { case 'accepted': return ( - ); case 'pending': return ourFriendship.creator.id !== myId ? ( <> - - ) : ( - ); diff --git a/client/src/widgets/sidebar/ui/notification-item/friend-notification.tsx b/client/src/widgets/sidebar/ui/notification-item/friend-notification.tsx new file mode 100644 index 000000000..8af5540d2 --- /dev/null +++ b/client/src/widgets/sidebar/ui/notification-item/friend-notification.tsx @@ -0,0 +1,62 @@ +import React from 'react'; + +import { Flex } from '@/shared/ui'; +import { LightningIcon } from '@/shared/assets'; +import { getElapsedTime } from '@/shared/lib'; + +import styles from './notification-item.module.scss'; +import { IFriendNotification } from '@teameights/types'; +import { FriendButton } from '@/features/friend-button'; +import { useGetFriends } from '@/entities/session'; + +interface SystemNotificationProps { + notification: IFriendNotification; +} + +/** + * SidebarFriendNotification component renders system notification content. + * + * @component + * @param {Object} props - The properties object. + * @param {SystemNotification} props.notification - The system notification object. + * + * @example + * + */ +export const SidebarFriendNotification: React.FC = props => { + const { notification } = props; + + const myId = notification.receiver.id; + const userId = notification.data.creator.id; + const { data: friendships } = useGetFriends(userId); + + const isPending = friendships?.data.some( + friendship => + (friendship.creator.id === myId || friendship.receiver.id === myId) && + friendship.status === 'pending' + ); + + return ( + <> + +
+ {!notification.read &&
} + +
+ +

+ {notification.data.creator.username} sent you friend request! +

+ {isPending && ( + + + + )} +
+ +

{getElapsedTime(notification.createdAt)}

+ + ); +}; diff --git a/client/src/widgets/sidebar/ui/notification-item/notification-item.module.scss b/client/src/widgets/sidebar/ui/notification-item/notification-item.module.scss index efae86c22..9771bdc34 100644 --- a/client/src/widgets/sidebar/ui/notification-item/notification-item.module.scss +++ b/client/src/widgets/sidebar/ui/notification-item/notification-item.module.scss @@ -83,3 +83,7 @@ opacity: 0.8; } } + +.notification_button { + width: 85px; +} \ No newline at end of file diff --git a/client/src/widgets/sidebar/ui/notification-item/notification-item.tsx b/client/src/widgets/sidebar/ui/notification-item/notification-item.tsx index c2fb2d006..deb7f666c 100644 --- a/client/src/widgets/sidebar/ui/notification-item/notification-item.tsx +++ b/client/src/widgets/sidebar/ui/notification-item/notification-item.tsx @@ -4,6 +4,7 @@ import { SidebarSystemNotification } from './system-notification'; import styles from './notification-item.module.scss'; import { NotificationType } from '@teameights/types'; +import { SidebarFriendNotification } from './friend-notification'; export interface NotificationProps { /** @@ -46,6 +47,8 @@ export const SidebarNotificationsItem: React.FC = props => { switch (notification.type) { case 'system': return ; + case 'friend_request': + return ; // case 'team_invite': // return ( //