From 14f8a5d472cf951a4857287f2b809acccbb02402 Mon Sep 17 00:00:00 2001 From: Rafiafrzl Date: Wed, 26 Nov 2025 11:44:50 +0700 Subject: [PATCH] feat: enhance notification fetching with pagination and filtering options --- src/api/notification.jsx | 16 +- .../component/ListNotification.jsx | 428 ++++++++++-------- 2 files changed, 242 insertions(+), 202 deletions(-) diff --git a/src/api/notification.jsx b/src/api/notification.jsx index 9aab0c5..fe38523 100644 --- a/src/api/notification.jsx +++ b/src/api/notification.jsx @@ -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 }; diff --git a/src/pages/notification/component/ListNotification.jsx b/src/pages/notification/component/ListNotification.jsx index 89441b8..30e3623 100644 --- a/src/pages/notification/component/ListNotification.jsx +++ b/src/pages/notification/component/ListNotification.jsx @@ -146,21 +146,43 @@ 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) - const totalItems = transformedData.length; - setPagination((prev) => ({ - ...prev, - total_limit: totalItems, - total_page: Math.ceil(totalItems / prev.current_limit), - })); + // 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 / limit), + })); + } } } catch (error) { console.error('Error fetching notifications:', error); @@ -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; - // Search by title and error code name + 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 ( {filteredNotifications.length === 0 ? ( @@ -288,200 +302,215 @@ const ListNotification = memo(function ListNotification(props) { Tidak ada notifikasi ) : ( - paginatedNotifications.map((notification) => { - const { IconComponent, color, bgColor } = getIconAndColor(notification.type); - return ( - handleMarkAsRead(notification.id)} - > -
+ filteredNotifications.map((notification) => { + const { IconComponent, color, bgColor } = getIconAndColor( + notification.type + ); + return ( + handleMarkAsRead(notification.id)} + >
- -
-
- - -
-
- {notification.title} -
- - {notification.issue} - +
+ +
+
+ + +
+
+ {notification.title} +
+ + {notification.issue} + +
+ {!notification.isRead && ( + + )}
- {!notification.isRead && ( - + +
+ - )} -
- - -
- - - {notification.details} - -
- - - - - {notification.timestamp} - - - - - - {notification.location} - - - - - - {notification.link} - - + {notification.details} + +
+ + + + + {notification.timestamp} + + + + + + {notification.location} + + + + + + {notification.link} + + + - - - - + -
-
- - ); - }) - )} + + ); + }) + )} ); }; @@ -1212,16 +1241,15 @@ const ListNotification = memo(function ListNotification(props) {
- - {renderDeviceNotifications()} - + {renderDeviceNotifications()} {/* PAGINATION */}
Menampilkan {pagination.current_limit} data halaman{' '} - {pagination.current_page} dari total {pagination.total_limit} data + {pagination.current_page} dari total {pagination.total_limit}{' '} + data