From 05d55b559f3d099f2c7fb1bc24bb0d2149594d3d Mon Sep 17 00:00:00 2001
From: Akshith <33996844+akshith312@users.noreply.github.com>
Date: Wed, 4 Mar 2026 12:17:59 -0800
Subject: [PATCH 1/2] feat: added pagination controls to no-show and drop-off
table
---
.../Reports/Participation/DropOffTracking.jsx | 149 ++++++++++++++++-
.../Participation/Participation.module.css | 151 ++++++++++++++++++
2 files changed, 296 insertions(+), 4 deletions(-)
diff --git a/src/components/CommunityPortal/Reports/Participation/DropOffTracking.jsx b/src/components/CommunityPortal/Reports/Participation/DropOffTracking.jsx
index 63ffd35c82..71ecf9fe9d 100644
--- a/src/components/CommunityPortal/Reports/Participation/DropOffTracking.jsx
+++ b/src/components/CommunityPortal/Reports/Participation/DropOffTracking.jsx
@@ -1,4 +1,4 @@
-import { useState } from 'react';
+import { useState, useMemo, useEffect } from 'react';
import { useSelector } from 'react-redux';
import styles from './Participation.module.css';
import mockEvents from './mockData';
@@ -6,6 +6,11 @@ import mockEvents from './mockData';
function DropOffTracking() {
const [selectedEvent, setSelectedEvent] = useState('All Events');
const [selectedTime, setSelectedTime] = useState('All Time');
+ const [currentPage, setCurrentPage] = useState(1);
+ const [pageSize, setPageSize] = useState(20);
+
+ const PAGINATION_THRESHOLD = 20;
+ const PAGE_SIZE_OPTIONS = [10, 20, 50];
const getDateRange = () => {
const today = new Date();
@@ -44,6 +49,69 @@ function DropOffTracking() {
return true;
});
+ useEffect(() => {
+ setCurrentPage(1);
+ }, [selectedEvent, selectedTime]);
+
+ const paginatedEvents = useMemo(() => {
+ const startIndex = (currentPage - 1) * pageSize;
+ const endIndex = startIndex + pageSize;
+
+ return filteredEvents.slice(startIndex, endIndex);
+ }, [filteredEvents, currentPage, pageSize]);
+
+ const totalPages = Math.ceil(filteredEvents.length / pageSize);
+ const showPagination = totalPages > 1;
+
+ const handlePageSizeChange = e => {
+ setPageSize(Number(e.target.value));
+ setCurrentPage(1);
+ };
+
+ const handlePreviousPage = () => {
+ setCurrentPage(prev => Math.max(prev - 1, 1));
+ };
+
+ const handleNextPage = () => {
+ setCurrentPage(prev => Math.min(prev + 1, totalPages));
+ };
+
+ const getVisiblePages = () => {
+ const pages = [];
+ const maxVisible = 5; // numbers in the middle section
+
+ if (totalPages <= 7) {
+ // Small page count → show everything
+ return Array.from({ length: totalPages }, (_, i) => i + 1);
+ }
+
+ const leftBound = Math.max(2, currentPage - 1);
+ const rightBound = Math.min(totalPages - 1, currentPage + 1);
+
+ // Always show first page
+ pages.push(1);
+
+ // Show left ellipsis
+ if (currentPage > 3) {
+ pages.push('left-ellipsis');
+ }
+
+ // Middle pages
+ for (let i = leftBound; i <= rightBound; i++) {
+ pages.push(i);
+ }
+
+ // Show right ellipsis
+ if (currentPage < totalPages - 2) {
+ pages.push('right-ellipsis');
+ }
+
+ // Always show last page
+ pages.push(totalPages);
+
+ return pages;
+ };
+
const darkMode = useSelector(state => state.theme.darkMode);
return (
@@ -109,17 +177,90 @@ function DropOffTracking() {
- {filteredEvents.map(event => (
+ {paginatedEvents.map(event => (
| {event.eventName} |
- {event.noShowRate} |
- {event.dropOffRate} |
+ {event.noShowRate} |
+ {event.dropOffRate} |
{event.attendees} |
))}
+
+ {/*Pagination*/}
+ {showPagination && (
+
+
+ Showing {(currentPage - 1) * pageSize + 1} to{' '}
+ {Math.min(currentPage * pageSize, filteredEvents.length)} of {filteredEvents.length}{' '}
+ records
+
+
+
+
+
+
+ {getVisiblePages().map(page =>
+ page === 'left-ellipsis' || page === 'right-ellipsis' ? (
+
+ ...
+
+ ) : (
+
+ ),
+ )}
+
+
+
+ Page {currentPage} of {totalPages}
+
+
+
+
+
+
+
+
+
+
+ )}
);
}
diff --git a/src/components/CommunityPortal/Reports/Participation/Participation.module.css b/src/components/CommunityPortal/Reports/Participation/Participation.module.css
index d250be26a1..3e2ba86a26 100644
--- a/src/components/CommunityPortal/Reports/Participation/Participation.module.css
+++ b/src/components/CommunityPortal/Reports/Participation/Participation.module.css
@@ -932,3 +932,154 @@
.insightsTabDarkMode:hover {
background-color: #374151;
}
+
+/* Pagination Styles */
+.paginationContainer {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 16px;
+ border-top: 1px solid #e0e0e0;
+ margin-top: 16px;
+ gap: 16px;
+ flex-wrap: nowrap;
+ background-color: #f9f9f9;
+ border-radius: 4px;
+ width: 100%;
+}
+
+.paginationContainerDark {
+ background-color: #1C2541;
+ border-top: 1px solid #3A506B;
+}
+
+.paginationInfo {
+ font-size: 14px;
+ color: #666;
+ min-width: 200px;
+}
+
+.paginationContainerDark .paginationInfo {
+ color: #aaa;
+}
+
+.paginationControls {
+ display: flex;
+ gap: 12px;
+ align-items: center;
+}
+
+.paginationControls button {
+ padding: 8px 16px;
+ border: 1px solid #ccc;
+ background-color: white;
+ border-radius: 4px;
+ cursor: pointer;
+ font-size: 14px;
+ transition: all 0.2s ease;
+}
+
+.paginationControls button:hover:not(:disabled) {
+ background-color: #f0f0f0;
+ border-color: #999;
+}
+
+.paginationControls button:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+.paginationContainerDark .paginationControls button {
+ background-color: #3A506B;
+ border-color: #4A607B;
+ color: #ffffff;
+}
+
+.paginationContainerDark .paginationControls button:hover:not(:disabled) {
+ background-color: #4A607B;
+ border-color: #5B708C;
+}
+.paginationButtonDark:hover:not(:disabled) {
+ background-color: #4a4a4a;
+ border-color: #777;
+}
+.paginationContainerDark .paginationControls button:disabled {
+ background-color: #2a2a2a;
+ border-color: #444;
+ color: #777;
+}
+
+.pageIndicator {
+ font-size: 14px;
+ color: #666;
+ font-weight: 500;
+ min-width: 120px;
+ text-align: center;
+}
+
+.paginationContainerDark .pageIndicator {
+ color: #aaa;
+}
+
+.pageSizeSelector {
+ display: flex;
+ gap: 8px;
+ align-items: center;
+ min-width: 200px;
+ justify-content: flex-end;
+ white-space: nowrap;
+ flex-shrink: 0;
+}
+
+.pageSizeSelector label {
+ font-size: 14px;
+ color: #666;
+}
+
+.paginationContainerDark .pageSizeSelector label {
+ color: #aaa;
+}
+
+.pageSizeSelector select {
+ padding: 6px 12px;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ background-color: white;
+ font-size: 14px;
+ cursor: pointer;
+}
+
+.pageSizeSelectorDark select {
+ background-color: #3a3a3a;
+ border-color: #555;
+ color: #fff;
+}
+
+.pageNumbers {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+
+.pageNumberButton {
+ padding: 4px 10px;
+ border-radius: 4px;
+ border: 1px solid #ccc;
+ background: white;
+ cursor: pointer;
+}
+
+.pageNumberButton:hover {
+ background: #f2f2f2;
+}
+
+.activePage {
+ background: #007bff;
+ color: white;
+ border-color: #007bff;
+}
+
+.ellipsis {
+ padding: 0 6px;
+ font-weight: bold;
+}
\ No newline at end of file
From 3c11ff868bfb0985eccaf1f1d27f6d3d72a1b5fd Mon Sep 17 00:00:00 2001
From: Akshith <33996844+akshith312@users.noreply.github.com>
Date: Wed, 4 Mar 2026 17:55:57 -0800
Subject: [PATCH 2/2] fix: sonarqube issues
---
.../Reports/Participation/DropOffTracking.jsx | 8 --------
.../Participation/Participation.module.css | 20 +++++++++++++------
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/src/components/CommunityPortal/Reports/Participation/DropOffTracking.jsx b/src/components/CommunityPortal/Reports/Participation/DropOffTracking.jsx
index 71ecf9fe9d..73c9370959 100644
--- a/src/components/CommunityPortal/Reports/Participation/DropOffTracking.jsx
+++ b/src/components/CommunityPortal/Reports/Participation/DropOffTracking.jsx
@@ -9,7 +9,6 @@ function DropOffTracking() {
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(20);
- const PAGINATION_THRESHOLD = 20;
const PAGE_SIZE_OPTIONS = [10, 20, 50];
const getDateRange = () => {
@@ -78,35 +77,28 @@ function DropOffTracking() {
const getVisiblePages = () => {
const pages = [];
- const maxVisible = 5; // numbers in the middle section
if (totalPages <= 7) {
- // Small page count → show everything
return Array.from({ length: totalPages }, (_, i) => i + 1);
}
const leftBound = Math.max(2, currentPage - 1);
const rightBound = Math.min(totalPages - 1, currentPage + 1);
- // Always show first page
pages.push(1);
- // Show left ellipsis
if (currentPage > 3) {
pages.push('left-ellipsis');
}
- // Middle pages
for (let i = leftBound; i <= rightBound; i++) {
pages.push(i);
}
- // Show right ellipsis
if (currentPage < totalPages - 2) {
pages.push('right-ellipsis');
}
- // Always show last page
pages.push(totalPages);
return pages;
diff --git a/src/components/CommunityPortal/Reports/Participation/Participation.module.css b/src/components/CommunityPortal/Reports/Participation/Participation.module.css
index 3e2ba86a26..94220890ab 100644
--- a/src/components/CommunityPortal/Reports/Participation/Participation.module.css
+++ b/src/components/CommunityPortal/Reports/Participation/Participation.module.css
@@ -294,6 +294,7 @@
border-radius: 10px;
padding: 10px;
background: #fff;
+ margin-bottom: 20px;
}
.trackingListContainerDark {
max-height: 600px;
@@ -1004,9 +1005,10 @@
border-color: #777;
}
.paginationContainerDark .paginationControls button:disabled {
- background-color: #2a2a2a;
- border-color: #444;
- color: #777;
+ background-color: #2E3B4E;
+ border-color: #3A506B;
+ color: #C5D1E0;
+ opacity: 0.7;
}
.pageIndicator {
@@ -1040,6 +1042,12 @@
color: #aaa;
}
+.paginationContainerDark .pageSizeSelector select {
+ background-color: #3A506B;
+ border-color: #4A607B;
+ color: #ffffff;
+}
+
.pageSizeSelector select {
padding: 6px 12px;
border: 1px solid #ccc;
@@ -1074,9 +1082,9 @@
}
.activePage {
- background: #007bff;
- color: white;
- border-color: #007bff;
+ background: #1E40AF;
+ color: #ffffff;
+ border-color: #1E40AF;
}
.ellipsis {