From f304a2849384b662b217d3e69cc5f8997eec2d87 Mon Sep 17 00:00:00 2001 From: Rafiafrzl Date: Thu, 20 Nov 2025 19:45:45 +0700 Subject: [PATCH] enhance search and pagination functionality to ListNotification component --- .../component/ListNotification.jsx | 189 +++++++++++++----- 1 file changed, 144 insertions(+), 45 deletions(-) diff --git a/src/pages/notification/component/ListNotification.jsx b/src/pages/notification/component/ListNotification.jsx index 97c3412..9967802 100644 --- a/src/pages/notification/component/ListNotification.jsx +++ b/src/pages/notification/component/ListNotification.jsx @@ -12,6 +12,8 @@ import { Modal, Tag, message, + Spin, + Pagination, } from 'antd'; import { CloseCircleFilled, @@ -33,6 +35,7 @@ import { FilePdfOutlined, PlusOutlined, ExclamationCircleOutlined, + SearchOutlined, } from '@ant-design/icons'; import { useNavigate, Link as RouterLink } from 'react-router-dom'; import { getAllNotification } from '../../../api/notification'; @@ -129,25 +132,61 @@ const ListNotification = memo(function ListNotification(props) { const [notifications, setNotifications] = useState([]); const [activeTab, setActiveTab] = useState('all'); const [searchTerm, setSearchTerm] = useState(''); + const [searchValue, setSearchValue] = useState(''); + const [loading, setLoading] = useState(false); const [modalContent, setModalContent] = useState(null); // 'user', 'log', 'details', or null const [isAddingLog, setIsAddingLog] = useState(false); const [selectedNotification, setSelectedNotification] = useState(null); + const [pagination, setPagination] = useState({ + current_page: 1, + current_limit: 10, + total_limit: 0, + total_page: 1, + }); const navigate = useNavigate(); // Fetch notifications from API const fetchNotifications = async () => { + setLoading(true); try { const response = await getAllNotification(); 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), + })); } } catch (error) { console.error('Error fetching notifications:', error); setNotifications([]); + } finally { + setTimeout(() => { + setLoading(false); + }, 500); } }; + const handlePaginationChange = (page, pageSize) => { + setPagination((prev) => ({ + ...prev, + 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); + }; + useEffect(() => { const token = localStorage.getItem('token'); if (!token) { @@ -200,6 +239,15 @@ const ListNotification = memo(function ListNotification(props) { ); }; + const handleSearch = () => { + setSearchTerm(searchValue); + }; + + const handleSearchClear = () => { + setSearchValue(''); + setSearchTerm(''); + }; + const filteredNotifications = notifications .filter((n) => { const matchesTab = @@ -210,8 +258,8 @@ const ListNotification = memo(function ListNotification(props) { }) .filter((n) => { if (!searchTerm) return true; - const searchableText = - `${n.title} ${n.issue} ${n.description} ${n.location} ${n.details}`.toLowerCase(); + // Search by title and error code name + const searchableText = `${n.title} ${n.issue}`.toLowerCase(); return searchableText.includes(searchTerm.toLowerCase()); }); @@ -230,14 +278,17 @@ const ListNotification = memo(function ListNotification(props) { transition: 'all 0.3s', }); - const renderDeviceNotifications = () => ( - - {filteredNotifications.length === 0 ? ( -
- Tidak ada notifikasi -
- ) : ( - filteredNotifications.map((notification) => { + const renderDeviceNotifications = () => { + const paginatedNotifications = getPaginatedNotifications(); + + return ( + + {filteredNotifications.length === 0 ? ( +
+ Tidak ada notifikasi +
+ ) : ( + paginatedNotifications.map((notification) => { const { IconComponent, color, bgColor } = getIconAndColor(notification.type); return ( - + {notification.link} + } + size="large" /> @@ -1135,7 +1212,29 @@ const ListNotification = memo(function ListNotification(props) { - {renderDeviceNotifications()} + + {renderDeviceNotifications()} + + + {/* PAGINATION */} + + +
+ Menampilkan {pagination.current_limit} data halaman{' '} + {pagination.current_page} dari total {pagination.total_limit} data +
+ + + + +