Skip to content

Commit

Permalink
feat: add notifications, pages content to features, add pooling(refre…
Browse files Browse the repository at this point in the history
…sh data after 5s)
  • Loading branch information
TomatoVan committed Mar 1, 2024
1 parent 3c104bb commit c599b57
Show file tree
Hide file tree
Showing 19 changed files with 390 additions and 58 deletions.
86 changes: 78 additions & 8 deletions json-server/db.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
{
"posts": [
"notifications": [
{
"id": "1",
"title": "json-server",
"title": "Уведомление 1",
"description": "Произошло какое-то событие",
"userId": "1"
},
{
"id": "2",
"title": "json-server",
"title": "Уведомление 2",
"description": "Произошло какое-то событие",
"userId": "1",
"href": "http://localhost:3000/admin"
},
{
"id": "3",
"title": "Уведомление 3",
"description": "Произошло какое-то событие",
"userId": "1",
"href": "http://localhost:3000/admin"
},
{
"id": "4",
"title": "Уведомление 4",
"description": "Произошло какое-то событие",
"userId": "1"
},
{
"id": "5",
"title": "Уведомление 1",
"description": "Произошло какое-то событие",
"userId": "2"
}
],
Expand Down Expand Up @@ -631,28 +653,76 @@
"userId": "1",
"text": "12",
"id": "r6b1z-N"
},
{
"articleId": "18",
"userId": "2",
"text": "привет",
"id": "DENfTu6"
},
{
"articleId": "7",
"userId": "2",
"text": "33",
"id": "Ps59wrg"
},
{
"articleId": "7",
"userId": "2",
"text": "123",
"id": "zzYVth3"
},
{
"articleId": "7",
"userId": "2",
"text": "123",
"id": "WjF4c_d"
},
{
"articleId": "1",
"userId": "2",
"text": "privet",
"id": "fta748h"
},
{
"articleId": "2",
"userId": "2",
"text": "питон топ",
"id": "ZlmlUrg"
},
{
"articleId": "7",
"userId": "1",
"text": "123",
"id": "KmtWJR_"
}
],
"users": [
{
"id": "1",
"username": "admin",
"password": "123",
"roles": ["ADMIN"],
"avatar": "https://avatars.mds.yandex.net/get-zen_doc/3413519/pub_5ff887b2fe4e686f6ae6ba3f_5ff887d7f906b16872a69755/scale_1200"
"roles": [
"ADMIN"
],
"avatar": "https://yakutsk.ru/wp-content/uploads/2022/07/12/bystrov_haker.jpeg"
},
{
"id": "2",
"username": "user",
"password": "123",
"roles": ["USER"],
"roles": [
"USER"
],
"avatar": "https://xakep.ru/wp-content/uploads/2018/05/171485/KuroiSH-hacker.jpg"
},
{
"id": "3",
"username": "manager",
"password": "123",
"roles": ["MANAGER"],
"roles": [
"MANAGER"
],
"avatar": "https://xakep.ru/wp-content/uploads/2018/05/171485/KuroiSH-hacker.jpg"
}
],
Expand All @@ -666,7 +736,7 @@
"country": "Belarus",
"city": "Moscow",
"username": "admin213",
"avatar": "https://avatars.mds.yandex.net/get-zen_doc/3413519/pub_5ff887b2fe4e686f6ae6ba3f_5ff887d7f906b16872a69755/scale_1200"
"avatar": "https://yt3.ggpht.com/ytc/AKedOLTYUJxG8Hu036PQ_TXpMLq2fG8Kj8NZI4h0lbn_3g=s900-c-k-c0x00ffffff-no-rj"
},
{
"id": "2",
Expand Down
14 changes: 14 additions & 0 deletions src/entities/Notification/api/notificationAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { rtkApi } from 'shared/api/rtkApi';
import { Notification } from '../model/types/notification';

const notificationApi = rtkApi.injectEndpoints({
endpoints: (build) => ({
getNotifications: build.query<Notification[], null>({
query: () => ({
url: '/notifications',
}),
}),
}),
});

export const useNotifications = notificationApi.useGetNotificationsQuery;
1 change: 1 addition & 0 deletions src/entities/Notification/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { NotificationList } from './ui/NotificationList/NotificationList';
6 changes: 6 additions & 0 deletions src/entities/Notification/model/types/notification.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface Notification {
id: string
title: string
description: string
href?: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.NotificationItem,
.link {
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';

import { NotificationItem } from './NotificationItem';

export default {
title: 'shared/NotificationItem',
component: NotificationItem,
argTypes: {
backgroundColor: { control: 'color' },
},
} as ComponentMeta<typeof NotificationItem>;

const Template: ComponentStory<typeof NotificationItem> = (args) => <NotificationItem {...args} />;

export const Normal = Template.bind({});
Normal.args = {};
42 changes: 42 additions & 0 deletions src/entities/Notification/ui/NotificationItem/NotificationItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { classNames } from 'shared/lib/classNames/classNames';
import { memo } from 'react';
import { Card, CardTheme } from 'shared/ui/Card/Card';
import { Text } from 'shared/ui/Text/Text';
import { Notification } from '../../model/types/notification';
import cls from './NotificationItem.module.scss';

interface NotificationItemProps {
className?: string;
notification?: Notification;
}

export const NotificationItem = memo((props: NotificationItemProps) => {
const { className, notification } = props;

const content = (
<Card
theme={CardTheme.OUTLINED}
className={classNames(cls.NotificationItem, {}, [className])}
>
<Text
title={notification?.title}
text={notification?.description}
/>
</Card>
);

if (notification?.href) {
return (
<a
className={cls.link}
target="_blank"
href={notification?.href}
rel="noreferrer"
>
{content}
</a>
);
}

return content;
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.NotificationList {
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';

import { NotificationList } from './NotificationList';

export default {
title: 'shared/NotificationList',
component: NotificationList,
argTypes: {
backgroundColor: { control: 'color' },
},
} as ComponentMeta<typeof NotificationList>;

const Template: ComponentStory<typeof NotificationList> = (args) => <NotificationList {...args} />;

export const Normal = Template.bind({});
Normal.args = {};
49 changes: 49 additions & 0 deletions src/entities/Notification/ui/NotificationList/NotificationList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { classNames } from 'shared/lib/classNames/classNames';
import { memo } from 'react';
import { VStack } from 'shared/ui/Stack';
import { Skeleton } from 'shared/ui/Skeleton/ui/Skeleton';
import { NotificationItem } from '../../ui/NotificationItem/NotificationItem';
import { useNotifications } from '../../api/notificationAPI';
import cls from './NotificationList.module.scss';

interface NotificationListProps {
className?: string;
}

export const NotificationList = memo((props: NotificationListProps) => {
const { className } = props;
const { isLoading, error, data: notifications } = useNotifications(null, {
pollingInterval: 5000,
});

if (isLoading) {
return (
<VStack
gap="16"
max
className={classNames(cls.NotificationList, {}, [className])}
>
<Skeleton width="100%" border="8px" height="80px" />
<Skeleton width="100%" border="8px" height="80px" />
<Skeleton width="100%" border="8px" height="80px" />
</VStack>
);
}

return (
<VStack
gap="16"
max
className={classNames(cls.NotificationList, {}, [className])}
>
{notifications?.map((notification) => (
<NotificationItem
key={notification.id}
className={cls.NotificationItem}
notification={notification}
/>

))}
</VStack>
);
});
1 change: 1 addition & 0 deletions src/features/avatarDropdown/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { AvatarDropDown } from './ui/AvatarDropDown/AvatarDropDown';
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import { ComponentMeta, ComponentStory } from '@storybook/react';

import { StoreDecorator } from 'shared/config/storybook/StoreDecorator/StoreDecorator';
import { UserRole } from '../../../../entities/User';
import { AvatarDropDown } from './AvatarDropDown';

export default {
title: 'features/AvatarDropDown',
component: AvatarDropDown,
argTypes: {
backgroundColor: { control: 'color' },
},
} as ComponentMeta<typeof AvatarDropDown>;

const Template: ComponentStory<typeof AvatarDropDown> = (args) => <AvatarDropDown />;

export const Normal = Template.bind({});
Normal.args = {};
Normal.decorators = [StoreDecorator({ user: { authData: { id: '1', username: '123', roles: [UserRole.USER, UserRole.ADMIN] } } })];
54 changes: 54 additions & 0 deletions src/features/avatarDropdown/ui/AvatarDropDown/AvatarDropDown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { memo, useCallback } from 'react';
import { Dropdown } from 'shared/ui/Popups';
import { RoutePath } from 'shared/config/routeConfig/routeConfig';
import { Avatar } from 'shared/ui/Avatar/Avatar';
import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
import { useAppDispatch } from 'shared/lib/hook/useAppDispatch/useAppDispatch';
import {
getUserAuthData,
isUserAdmin,
isUserManager,
userActions,
} from '../../../../entities/User';

export const AvatarDropDown = memo(() => {
const { t } = useTranslation();

const dispatch = useAppDispatch();

const isAdmin = useSelector(isUserAdmin);
const authData = useSelector(getUserAuthData);
const isManager = useSelector(isUserManager);

const isAdminPanelAvailable = isAdmin || isManager;

const onLogout = useCallback(() => {
dispatch(userActions.logout());
}, [dispatch]);

if (!authData) {
return null;
}

return (
<Dropdown
direction="bottom left"
items={[
...(isAdminPanelAvailable ? [{
content: t('Admin panel'),
href: RoutePath.admin_panel,
}] : []),
{
content: t('Profile'),
href: RoutePath.profile + authData.id,
},
{
content: t('Exit'),
onClick: onLogout,
},
]}
trigger={<Avatar size={30} src={authData.avatar} />}
/>
);
});
1 change: 1 addition & 0 deletions src/features/notificationButton/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { NotificationButton } from './ui/NotificationButton/NotificationButton';
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.notifications {
min-height: 150px;
max-height: 300px;
width: 500px;
overflow-y: auto;
padding-right: 15px;
}
Loading

0 comments on commit c599b57

Please sign in to comment.