diff --git a/src/components/CommunityPortal/Activities/ActivityList.jsx b/src/components/CommunityPortal/Activities/ActivityList.jsx
index 4e7f3137b5..41fdf72c57 100644
--- a/src/components/CommunityPortal/Activities/ActivityList.jsx
+++ b/src/components/CommunityPortal/Activities/ActivityList.jsx
@@ -1,6 +1,6 @@
// Activity List Component
import { useState, useEffect, useMemo } from 'react';
-import { useSelector, useStore } from 'react-redux';
+import { useSelector } from 'react-redux';
import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from 'reactstrap';
import styles from './ActivityList.module.css';
// import { useHistory } from 'react-router-dom';
@@ -13,16 +13,22 @@ function ActivityList() {
const [error, setError] = useState(null);
const [selectedActivity, setSelectedActivity] = useState(null);
const [modalOpen, setModalOpen] = useState(false);
+
const darkMode = useSelector(state => state.theme.darkMode);
+
const [filter, setFilter] = useState({
type: '',
date: '',
location: '',
- pastEvents: false,
});
+
const [sortOrder, setSortOrder] = useState('earliest');
const [showPastEvents, setShowPastEvents] = useState(false);
+ const [currentPage, setCurrentPage] = useState(1);
+ const itemsPerPage = 10;
+
+ // Dark mode body class
useEffect(() => {
if (darkMode) {
document.body.classList.add('activity-list-dark-body');
@@ -35,18 +41,22 @@ function ActivityList() {
};
}, [darkMode]);
+ // Fetch activities (mock fallback)
useEffect(() => {
const fetchActivities = async () => {
try {
setLoading(true);
setError(null);
+
throw new Error('API not implemented yet');
} catch (err) {
setError(err.message);
+
const parsed = mockActivities.map(a => ({
...a,
_dateObj: new Date(`${a.date}T00:00:00`),
}));
+
setActivities(parsed);
} finally {
setLoading(false);
@@ -56,9 +66,14 @@ function ActivityList() {
fetchActivities();
}, []);
+ // Reset pagination on filter/sort change
+ useEffect(() => {
+ setCurrentPage(1);
+ }, [filter, sortOrder, showPastEvents]);
+
const handleFilterChange = e => {
const { name, value } = e.target;
- setFilter({ ...filter, [name]: value });
+ setFilter(prev => ({ ...prev, [name]: value }));
};
const handleSortChange = e => {
@@ -70,9 +85,9 @@ function ActivityList() {
type: '',
date: '',
location: '',
- showPastEvents: false,
});
setShowPastEvents(false);
+ setCurrentPage(1);
};
const handleActivityClick = activity => {
@@ -99,9 +114,7 @@ function ActivityList() {
}
});
- return [...typeOrder.keys()].sort(
- (typeA, typeB) => typeOrder.get(typeA) - typeOrder.get(typeB),
- );
+ return [...typeOrder.keys()].sort((a, b) => typeOrder.get(a) - typeOrder.get(b));
}, [activities]);
const filteredActivities = activities
@@ -120,6 +133,13 @@ function ActivityList() {
return sortOrder === 'earliest' ? dateA - dateB : dateB - dateA;
});
+ // Pagination
+ const totalPages = Math.ceil(filteredActivities.length / itemsPerPage);
+ const safePage = Math.min(currentPage, totalPages || 1);
+ const startIndex = (safePage - 1) * itemsPerPage;
+
+ const paginatedActivities = filteredActivities.slice(startIndex, startIndex + itemsPerPage);
+ const hasActivities = paginatedActivities.length > 0;
return (
+ {/* Activity List */}
- {loading ? (
-
Loading activities...
- ) : filteredActivities.length > 0 ? (
+ {loading &&
Loading activities...
}
+
+ {!loading && hasActivities && (
- {filteredActivities.map(activity => (
+ {paginatedActivities.map(activity => (
-
-
+
-
{activity.name}
{activity.type} – {activity.date} – {activity.location}
@@ -236,16 +255,39 @@ function ActivityList() {
))}
- ) : (
+ )}
+
+ {!loading && !hasActivities && (
No activities found
)}
- {/* Modal for activity details */}
+ {/* Pagination */}
+ {totalPages > 1 && (
+
+
+
+ {Array.from({ length: totalPages }, (_, i) => i + 1).map(page => (
+
+ ))}
+
+
+
+ )}
+
+ {/* Modal */}
-
- {selectedActivity ? selectedActivity.name : ''}
-
+ {selectedActivity?.name}
{selectedActivity && (
@@ -264,7 +306,6 @@ function ActivityList() {
Description: {selectedActivity.description}
- {/* Add more details as needed */}
)}
diff --git a/src/components/CommunityPortal/Activities/ActivityList.module.css b/src/components/CommunityPortal/Activities/ActivityList.module.css
index e0003a31aa..e9f44282b5 100644
--- a/src/components/CommunityPortal/Activities/ActivityList.module.css
+++ b/src/components/CommunityPortal/Activities/ActivityList.module.css
@@ -1,4 +1,6 @@
/* stylelint-disable no-descending-specificity */
+
+/* Container */
.activityListContainer {
padding: 20px;
min-height: calc(100vh - 140px);
@@ -9,6 +11,7 @@
padding-bottom: 40px;
}
+/* Heading */
.heading {
text-align: center;
margin: 20px 0;
@@ -17,6 +20,7 @@
font-weight: 600;
}
+/* Filters */
.filters {
display: flex;
justify-content: center;
@@ -50,6 +54,7 @@
color: #1f2937;
}
+/* Inputs */
.filters input,
.filters select,
.darkModeFilters input,
@@ -64,6 +69,11 @@
color: #333;
}
+.filters select {
+ height: 48px;
+}
+
+/* Dark mode input */
.darkModeInput {
background-color: #1e2a3a !important;
color: #fff !important;
@@ -71,23 +81,14 @@
color-scheme: dark;
}
-.filters select {
- padding: 10px;
- height: 48px;
- border: 1px solid #d1d5db;
- border-radius: 6px;
- margin-top: 5px;
- font-size: 1rem;
- background: #fff;
-}
-
-/* Dark mode date input - style the calendar icon */
.darkModeInput[type="date"]::-webkit-calendar-picker-indicator {
filter: invert(1);
cursor: pointer;
}
-.filters input:focus {
+/* Focus */
+.filters input:focus,
+.filters select:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 8px rgb(59 130 246 / 30%);
@@ -102,10 +103,7 @@
color: #a0a0a0;
}
-.darkFilters input[type="date"]::-webkit-calendar-picker-indicator {
- filter: invert(1);
-}
-
+/* Activity List */
.activityList {
max-width: 900px;
margin: 0 auto;
@@ -120,7 +118,6 @@
box-shadow: none;
border: 1px solid #3a4a5c;
border-radius: 0;
- margin: 0 auto;
}
.activityList ul {
@@ -128,6 +125,7 @@
padding: 0;
}
+/* Activity Item */
.activityItem {
display: flex;
flex-direction: column;
@@ -137,8 +135,15 @@
border: 1px solid #e5e7eb;
border-radius: 8px;
background-color: #f9fafb;
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
}
+.activityItem:hover {
+ transform: translateY(-3px);
+ box-shadow: 0 4px 8px rgb(0 0 0 / 10%);
+}
+
+/* Dark item */
.darkModeItem {
background-color: #1e2a3a !important;
border: 1px solid #3a4a5c !important;
@@ -146,16 +151,12 @@
border-radius: 0;
}
-.activityList li:hover {
- transform: translateY(-3px);
- box-shadow: 0 4px 8px rgb(0 0 0 / 10%);
-}
-
.darkModeItem:hover {
background-color: #3d4f62 !important;
box-shadow: none !important;
}
+/* Text */
.activityItem strong {
color: #1e3a8a;
font-size: 1.2rem;
@@ -178,6 +179,7 @@
color: #d1d5db !important;
}
+/* Empty state */
.activityList p {
text-align: center;
color: #6b7280;
@@ -185,7 +187,8 @@
margin: 20px 0;
}
-.clearButtonWrapper{
+/* Clear Button */
+.clearButtonWrapper {
display: flex;
justify-content: center;
gap: 30px;
@@ -214,10 +217,8 @@
.clearFiltersButton:hover:not(:disabled) {
transform: scale(1.05);
- background-color: #f9fafb;
}
-
.clearFiltersButtonDark {
border: 1px solid #fff;
background: #0f172a;
@@ -228,7 +229,6 @@
background: #111c33;
}
-
/* Suggestions */
.suggestions {
position: absolute;
@@ -269,6 +269,7 @@
background-color: #334155;
}
+/* Show Past Toggle */
.showPastToggle {
display: inline-flex;
align-items: center;
@@ -297,24 +298,51 @@
accent-color: #60a5fa;
}
+/* Focus-visible accessibility */
.showPastToggle input[type="checkbox"]:focus-visible {
- outline: none;
- border-radius: 4px;
+ outline: 2px solid #3b82f6;
+ outline-offset: 2px;
+}
+
+/* Pagination */
+.pagination {
+ display: flex;
+ gap: 8px;
+ justify-content: center;
+ margin-top: 16px;
+}
+
+.pagination button {
+ border-radius: 6px;
+ padding: 6px 12px;
+}
+
+.activePage {
+ font-weight: bold;
+ background-color: #2563eb;
+ color: white;
}
/* Responsive */
@media (width <= 768px) {
- .filters {
+ .filters,
+ .darkModeFilters {
flex-direction: column;
align-items: center;
gap: 20px;
}
- .filters label {
+ .filters label,
+ .darkModeFilters label {
width: 100%;
}
.activityList {
padding: 20px;
}
+
+ .activityItem {
+ flex-direction: column;
+ padding: 10px;
+ }
}
\ No newline at end of file