feat: enhance notification fetching with pagination and filtering options
This commit is contained in:
@@ -1,9 +1,21 @@
|
||||
import { SendRequest } from '../components/Global/ApiRequest';
|
||||
|
||||
export const getAllNotification = async () => {
|
||||
const getAllNotification = async (queryParams) => {
|
||||
const response = await SendRequest({
|
||||
method: 'get',
|
||||
prefix: 'notification',
|
||||
prefix: `notification?${queryParams.toString()}`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
};
|
||||
|
||||
const getNotificationById = async (id) => {
|
||||
const response = await SendRequest({
|
||||
method: 'get',
|
||||
prefix: `notification/${id}`,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export { getAllNotification, getNotificationById };
|
||||
|
||||
@@ -146,22 +146,44 @@ const ListNotification = memo(function ListNotification(props) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Fetch notifications from API
|
||||
const fetchNotifications = async () => {
|
||||
const fetchNotifications = async (page = 1, limit = 10, isRead = null) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await getAllNotification();
|
||||
const queryParams = new URLSearchParams({
|
||||
page: page.toString(),
|
||||
limit: limit.toString(),
|
||||
});
|
||||
|
||||
if (isRead !== null) {
|
||||
queryParams.append('is_read', isRead.toString());
|
||||
}
|
||||
|
||||
const response = await getAllNotification(queryParams);
|
||||
if (response && response.data) {
|
||||
const transformedData = transformNotificationData(response.data);
|
||||
setNotifications(transformedData);
|
||||
|
||||
// Update pagination with mock data (since API doesn't provide pagination info)
|
||||
// Update pagination with API response or calculate from data
|
||||
if (response.paging) {
|
||||
setPagination({
|
||||
current_page: response.paging.current_page || page,
|
||||
current_limit: response.paging.current_limit || limit,
|
||||
total_limit: response.paging.total_limit || transformedData.length,
|
||||
total_page:
|
||||
response.paging.total_page || Math.ceil(transformedData.length / limit),
|
||||
});
|
||||
} else {
|
||||
// Fallback: calculate pagination from data
|
||||
const totalItems = transformedData.length;
|
||||
setPagination((prev) => ({
|
||||
...prev,
|
||||
current_page: page,
|
||||
current_limit: limit,
|
||||
total_limit: totalItems,
|
||||
total_page: Math.ceil(totalItems / prev.current_limit),
|
||||
total_page: Math.ceil(totalItems / limit),
|
||||
}));
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching notifications:', error);
|
||||
setNotifications([]);
|
||||
@@ -178,13 +200,10 @@ const ListNotification = memo(function ListNotification(props) {
|
||||
current_page: page,
|
||||
current_limit: pageSize,
|
||||
}));
|
||||
};
|
||||
|
||||
// Get paginated notifications
|
||||
const getPaginatedNotifications = () => {
|
||||
const startIndex = (pagination.current_page - 1) * pagination.current_limit;
|
||||
const endIndex = startIndex + pagination.current_limit;
|
||||
return filteredNotifications.slice(startIndex, endIndex);
|
||||
// Fetch notifications with new pagination
|
||||
const isReadFilter = activeTab === 'read' ? true : activeTab === 'unread' ? false : null;
|
||||
fetchNotifications(page, pageSize, isReadFilter);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -194,9 +213,10 @@ const ListNotification = memo(function ListNotification(props) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch notifications on component mount
|
||||
fetchNotifications();
|
||||
}, []);
|
||||
// Fetch notifications on component mount and when tab changes
|
||||
const isReadFilter = activeTab === 'read' ? true : activeTab === 'unread' ? false : null;
|
||||
fetchNotifications(pagination.current_page, pagination.current_limit, isReadFilter);
|
||||
}, [activeTab]);
|
||||
|
||||
const getIconAndColor = (type) => {
|
||||
switch (type) {
|
||||
@@ -248,22 +268,17 @@ const ListNotification = memo(function ListNotification(props) {
|
||||
setSearchTerm('');
|
||||
};
|
||||
|
||||
const filteredNotifications = notifications
|
||||
.filter((n) => {
|
||||
const matchesTab =
|
||||
activeTab === 'all' ||
|
||||
(activeTab === 'unread' && !n.isRead) ||
|
||||
(activeTab === 'read' && n.isRead);
|
||||
return matchesTab;
|
||||
})
|
||||
.filter((n) => {
|
||||
if (!searchTerm) return true;
|
||||
const getUnreadCount = () => notifications.filter((n) => !n.isRead).length;
|
||||
|
||||
// Filter notifications based on search term
|
||||
const getFilteredNotifications = () => {
|
||||
if (!searchTerm) return notifications;
|
||||
// Search by title and error code name
|
||||
return notifications.filter((n) => {
|
||||
const searchableText = `${n.title} ${n.issue}`.toLowerCase();
|
||||
return searchableText.includes(searchTerm.toLowerCase());
|
||||
});
|
||||
|
||||
const getUnreadCount = () => notifications.filter((n) => !n.isRead).length;
|
||||
};
|
||||
|
||||
const tabButtonStyle = (isActive) => ({
|
||||
padding: '12px 16px',
|
||||
@@ -279,8 +294,7 @@ const ListNotification = memo(function ListNotification(props) {
|
||||
});
|
||||
|
||||
const renderDeviceNotifications = () => {
|
||||
const paginatedNotifications = getPaginatedNotifications();
|
||||
|
||||
const filteredNotifications = getFilteredNotifications();
|
||||
return (
|
||||
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
|
||||
{filteredNotifications.length === 0 ? (
|
||||
@@ -288,8 +302,10 @@ const ListNotification = memo(function ListNotification(props) {
|
||||
Tidak ada notifikasi
|
||||
</div>
|
||||
) : (
|
||||
paginatedNotifications.map((notification) => {
|
||||
const { IconComponent, color, bgColor } = getIconAndColor(notification.type);
|
||||
filteredNotifications.map((notification) => {
|
||||
const { IconComponent, color, bgColor } = getIconAndColor(
|
||||
notification.type
|
||||
);
|
||||
return (
|
||||
<Card
|
||||
key={notification.id}
|
||||
@@ -300,7 +316,13 @@ const ListNotification = memo(function ListNotification(props) {
|
||||
}}
|
||||
onClick={() => handleMarkAsRead(notification.id)}
|
||||
>
|
||||
<div style={{ display: 'flex', gap: '16px', alignItems: 'flex-start' }}>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
gap: '16px',
|
||||
alignItems: 'flex-start',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: '40px',
|
||||
@@ -357,10 +379,17 @@ const ListNotification = memo(function ListNotification(props) {
|
||||
}}
|
||||
>
|
||||
<MailOutlined
|
||||
style={{ marginTop: '4px', color: '#1890ff' }}
|
||||
style={{
|
||||
marginTop: '4px',
|
||||
color: '#1890ff',
|
||||
}}
|
||||
/>
|
||||
<Paragraph
|
||||
style={{ color: '#595959', margin: 0, flex: 1 }}
|
||||
style={{
|
||||
color: '#595959',
|
||||
margin: 0,
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
{notification.details}
|
||||
</Paragraph>
|
||||
@@ -1212,16 +1241,15 @@ const ListNotification = memo(function ListNotification(props) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Spin spinning={loading}>
|
||||
{renderDeviceNotifications()}
|
||||
</Spin>
|
||||
<Spin spinning={loading}>{renderDeviceNotifications()}</Spin>
|
||||
|
||||
{/* PAGINATION */}
|
||||
<Row justify="space-between" align="middle" style={{ marginTop: '16px' }}>
|
||||
<Col>
|
||||
<div>
|
||||
Menampilkan {pagination.current_limit} data halaman{' '}
|
||||
{pagination.current_page} dari total {pagination.total_limit} data
|
||||
{pagination.current_page} dari total {pagination.total_limit}{' '}
|
||||
data
|
||||
</div>
|
||||
</Col>
|
||||
<Col>
|
||||
|
||||
Reference in New Issue
Block a user