blob: 4b7fc9eccba2984bd3405cefecad677cf896d172 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { useState, useEffect } from 'react';
import { Row, Col, ButtonGroup, Button, Nav } from 'react-bootstrap';
import { useTranslation } from 'react-i18next';
import { useParams, useNavigate, Link } from 'react-router-dom';
import classNames from 'classnames';
import { usePageTags } from '@/hooks';
import {
useQueryNotifications,
clearUnreadNotification,
clearNotificationStatus,
readNotification,
} from '@/services';
import { floppyNavigation } from '@/utils';
import { Inbox, Achievements } from './components';
import './index.scss';
const PAGE_SIZE = 10;
const Notifications = () => {
const [page, setPage] = useState(1);
const [notificationData, setNotificationData] = useState<any>([]);
const { t } = useTranslation('translation', { keyPrefix: 'notifications' });
const inboxTypeNavs = ['all', 'posts', 'invites', 'votes'];
const { type = 'inbox', subType = inboxTypeNavs[0] } = useParams();
const queryParams: {
type: string;
inbox_type?: string;
page: number;
page_size: number;
} = {
type,
page,
page_size: PAGE_SIZE,
};
if (type === 'inbox') {
queryParams.inbox_type = subType;
}
const { data, mutate } = useQueryNotifications(queryParams);
useEffect(() => {
clearNotificationStatus(type);
}, []);
useEffect(() => {
if (!data) {
return;
}
if (page > 1) {
setNotificationData([...notificationData, ...(data?.list || [])]);
} else {
setNotificationData(data?.list);
}
}, [data]);
const navigate = useNavigate();
const handleTypeChange = (evt, val) => {
if (!floppyNavigation.shouldProcessLinkClick(evt)) {
return;
}
evt.preventDefault();
if (type === val) {
return;
}
setPage(1);
setNotificationData([]);
navigate(`/users/notifications/${val}`);
};
const handleLoadMore = () => {
setPage(page + 1);
};
const handleUnreadNotification = async () => {
await clearUnreadNotification(type);
mutate();
};
const handleReadNotification = (id) => {
readNotification(id);
};
usePageTags({
title: t('notifications', { keyPrefix: 'page_title' }),
});
return (
<Row className="pt-4 mb-5">
<Col className="page-main flex-auto">
<h3 className="mb-4">{t('title')}</h3>
<div className="d-flex justify-content-between mb-3">
<ButtonGroup size="sm">
<Button
as="a"
href="/users/notifications/inbox"
variant="outline-secondary"
active={type === 'inbox'}
onClick={(evt) => handleTypeChange(evt, 'inbox')}>
{t('inbox')}
</Button>
<Button
as="a"
href="/users/notifications/achievement"
variant="outline-secondary"
active={type === 'achievement'}
onClick={(evt) => handleTypeChange(evt, 'achievement')}>
{t('achievement')}
</Button>
</ButtonGroup>
<Button
size="sm"
variant="outline-secondary"
onClick={handleUnreadNotification}>
{t('all_read')}
</Button>
</div>
{type === 'inbox' && (
<>
<Nav className="inbox-nav small">
{inboxTypeNavs.map((nav) => {
const navLinkHref = `/users/notifications/inbox/${nav}`;
const navLinkName = t(`inbox_type.${nav}`);
return (
<Nav.Item key={nav}>
<Link
to={navLinkHref}
onClick={() => {
setPage(1);
}}
className={classNames('nav-link', {
disabled: nav === subType,
})}>
{navLinkName}
</Link>
</Nav.Item>
);
})}
</Nav>
<Inbox
data={notificationData}
handleReadNotification={handleReadNotification}
/>
</>
)}
{type === 'achievement' && (
<Achievements
data={notificationData}
handleReadNotification={handleReadNotification}
/>
)}
{(data?.count || 0) > PAGE_SIZE * page && (
<div className="d-flex justify-content-center align-items-center py-3">
<Button
variant="link"
className="btn-no-border"
onClick={handleLoadMore}>
{t('show_more')}
</Button>
</div>
)}
</Col>
<Col className="page-right-side" />
</Row>
);
};
export default Notifications;