mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 04:46:40 +07:00
notifications: added tabs to notification screen
This commit is contained in:
parent
7135d06673
commit
f9e0ecdd0c
10 changed files with 148 additions and 21 deletions
25
src/components/input/LoaderScreen/index.tsx
Normal file
25
src/components/input/LoaderScreen/index.tsx
Normal file
|
@ -0,0 +1,25 @@
|
|||
import React, { FC } from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { LoaderCircle } from '../LoaderCircle';
|
||||
|
||||
import styles from './styles.module.scss';
|
||||
|
||||
interface LoaderScreenProps {
|
||||
className?: string;
|
||||
align?: 'top' | 'middle';
|
||||
}
|
||||
|
||||
const LoaderScreen: FC<LoaderScreenProps> = ({
|
||||
className,
|
||||
align = 'middle',
|
||||
}) => (
|
||||
<div
|
||||
className={classNames(styles.screen, styles[`align-${align}`], className)}
|
||||
>
|
||||
<LoaderCircle size={32} />
|
||||
</div>
|
||||
);
|
||||
|
||||
export { LoaderScreen };
|
14
src/components/input/LoaderScreen/styles.module.scss
Normal file
14
src/components/input/LoaderScreen/styles.module.scss
Normal file
|
@ -0,0 +1,14 @@
|
|||
@import 'src/styles/variables';
|
||||
|
||||
.screen {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: $gap;
|
||||
|
||||
&.align-top {
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ interface HorizontalMenuItemProps {
|
|||
icon?: string;
|
||||
color?: 'green' | 'orange' | 'yellow';
|
||||
active?: boolean;
|
||||
stretchy?: boolean;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
|
@ -31,6 +32,7 @@ HorizontalMenu.Item = ({
|
|||
children,
|
||||
isLoading,
|
||||
active,
|
||||
stretchy,
|
||||
onClick,
|
||||
}: PropsWithChildren<HorizontalMenuItemProps>) => {
|
||||
if (isLoading) {
|
||||
|
@ -44,7 +46,11 @@ HorizontalMenu.Item = ({
|
|||
|
||||
return (
|
||||
<div
|
||||
className={classNames(styles.item, { [styles.active]: active }, styles[color])}
|
||||
className={classNames(
|
||||
styles.item,
|
||||
{ [styles.active]: active, [styles.stretchy]: stretchy },
|
||||
styles[color],
|
||||
)}
|
||||
onClick={onClick}
|
||||
>
|
||||
{!!icon && <Icon icon={icon} size={24} />}
|
||||
|
|
|
@ -57,6 +57,11 @@
|
|||
background: $warning_gradient;
|
||||
}
|
||||
}
|
||||
|
||||
&.stretchy {
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, { FC, useCallback } from 'react';
|
||||
|
||||
import { Card } from '~/components/containers/Card';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { Zone } from '~/components/containers/Zone';
|
||||
import { Button } from '~/components/input/Button';
|
||||
|
@ -49,11 +50,16 @@ const NotificationSettingsForm: FC<NotificationSettingsFormProps> = ({
|
|||
|
||||
return (
|
||||
<Group>
|
||||
<Zone title="Уведомления">
|
||||
<Card>
|
||||
<InputRow className={styles.row} input={toggle('enabled')}>
|
||||
Получать уведомления
|
||||
</InputRow>
|
||||
</Card>
|
||||
|
||||
<div />
|
||||
|
||||
<Zone title="Типы уведомлений">
|
||||
<Group>
|
||||
<InputRow className={styles.row} input={toggle('enabled')}>
|
||||
Включены
|
||||
</InputRow>
|
||||
<InputRow
|
||||
className={styles.row}
|
||||
input={toggle('flow', !values.enabled)}
|
||||
|
@ -70,7 +76,9 @@ const NotificationSettingsForm: FC<NotificationSettingsFormProps> = ({
|
|||
</Group>
|
||||
</Zone>
|
||||
|
||||
<Zone title="Уведомления">
|
||||
<div />
|
||||
|
||||
<Zone title="Способы доставки">
|
||||
<Group>
|
||||
<InputRow
|
||||
className={styles.row}
|
||||
|
|
|
@ -1,25 +1,62 @@
|
|||
import { VFC } from 'react';
|
||||
import { useState, VFC } from 'react';
|
||||
|
||||
import { Padder } from '~/components/containers/Padder';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { Button } from '~/components/input/Button';
|
||||
import { Icon } from '~/components/input/Icon';
|
||||
import { HorizontalMenu } from '~/components/menu/HorizontalMenu';
|
||||
import { useStackContext } from '~/components/sidebar/SidebarStack';
|
||||
import { SidebarStackCard } from '~/components/sidebar/SidebarStackCard';
|
||||
import { NotificationList } from '~/containers/notifications/NotificationList';
|
||||
import { NotificationSettings } from '~/containers/notifications/NotificationSettings';
|
||||
import { useNotificationSettings } from '~/hooks/notifications/useNotificationSettings';
|
||||
|
||||
import styles from './styles.module.scss';
|
||||
|
||||
interface ProfileSidebarNotificationsProps {}
|
||||
|
||||
enum Tabs {
|
||||
List,
|
||||
Settings,
|
||||
}
|
||||
|
||||
const ProfileSidebarNotifications: VFC<
|
||||
ProfileSidebarNotificationsProps
|
||||
> = () => {
|
||||
const { closeAllTabs } = useStackContext();
|
||||
const [tab, setTab] = useState(Tabs.List);
|
||||
const { loading } = useNotificationSettings();
|
||||
|
||||
return (
|
||||
<SidebarStackCard
|
||||
width={400}
|
||||
headerFeature="back"
|
||||
title="Уведомления"
|
||||
onBackPress={closeAllTabs}
|
||||
>
|
||||
<NotificationSettings />
|
||||
<SidebarStackCard width={400} onBackPress={closeAllTabs}>
|
||||
<div className={styles.grid}>
|
||||
<Group className={styles.head} horizontal>
|
||||
<HorizontalMenu className={styles.tabs}>
|
||||
<HorizontalMenu.Item
|
||||
active={tab === Tabs.List}
|
||||
isLoading={loading}
|
||||
onClick={() => setTab(Tabs.List)}
|
||||
stretchy
|
||||
>
|
||||
Уведомления
|
||||
</HorizontalMenu.Item>
|
||||
|
||||
<HorizontalMenu.Item
|
||||
active={tab === Tabs.Settings}
|
||||
isLoading={loading}
|
||||
onClick={() => setTab(Tabs.Settings)}
|
||||
stretchy
|
||||
>
|
||||
Настройки
|
||||
</HorizontalMenu.Item>
|
||||
</HorizontalMenu>
|
||||
|
||||
<Button iconLeft="right" color="link" onClick={closeAllTabs} />
|
||||
</Group>
|
||||
|
||||
<div className={styles.list}>
|
||||
{tab === Tabs.List ? <NotificationList /> : <NotificationSettings />}
|
||||
</div>
|
||||
</div>
|
||||
</SidebarStackCard>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
@import 'src/styles/variables';
|
||||
|
||||
.grid {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
z-index: 4;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.head {
|
||||
@include row_shadow;
|
||||
|
||||
width: 100%;
|
||||
padding: $gap;
|
||||
flex: 0;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.list {
|
||||
@include row_shadow;
|
||||
|
||||
overflow-y: auto;
|
||||
flex: 1 1;
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import React, { FC, useEffect } from 'react';
|
||||
import { FC, useEffect } from 'react';
|
||||
|
||||
import { LoaderCircle } from '~/components/input/LoaderCircle';
|
||||
import { LoaderScreen } from '~/components/input/LoaderScreen';
|
||||
import { NotificationComment } from '~/components/notifications/NotificationComment';
|
||||
import { useNotificationsList } from '~/hooks/notifications/useNotificationsList';
|
||||
import { useNotifications } from '~/utils/providers/NotificationProvider';
|
||||
|
@ -18,7 +18,7 @@ const NotificationList: FC<NotificationListProps> = () => {
|
|||
}, []);
|
||||
|
||||
if (isLoading) {
|
||||
return <LoaderCircle />;
|
||||
return <LoaderScreen align="top" />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -14,13 +14,13 @@ export const useNotificationSettings = () => {
|
|||
enabled: settingsEnabled,
|
||||
lastSeen,
|
||||
lastDate,
|
||||
isLoading: isLoadingSettings,
|
||||
isLoading,
|
||||
update,
|
||||
refresh,
|
||||
settings,
|
||||
} = useNotificationSettingsRequest();
|
||||
|
||||
const enabled = !isLoadingSettings && !settingsError && settingsEnabled;
|
||||
const enabled = !isLoading && !settingsError && settingsEnabled;
|
||||
|
||||
const hasNew =
|
||||
enabled && !!lastDate && (!lastSeen || isAfter(lastDate, lastSeen));
|
||||
|
@ -47,5 +47,6 @@ export const useNotificationSettings = () => {
|
|||
markAsRead,
|
||||
refresh,
|
||||
update,
|
||||
loading: isLoading,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -66,7 +66,7 @@ export const useNotificationSettingsRequest = () => {
|
|||
const refresh = useCallback(() => mutate(), [mutate]);
|
||||
|
||||
return {
|
||||
isLoading,
|
||||
isLoading: isLoading && !data,
|
||||
error,
|
||||
lastSeen:
|
||||
data?.lastSeen && isValid(parseISO(data.lastSeen))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue