From fa36f172c2fc8f91fb50f858607071d1a392c0ec Mon Sep 17 00:00:00 2001 From: Akshith <33996844+akshith312@users.noreply.github.com> Date: Fri, 16 Jan 2026 20:41:35 -0500 Subject: [PATCH 1/3] feat: Added Pagination to ActivityList --- .../Activities/ActivityList.jsx | 33 +++++++++++++++++-- .../Activities/ActivityList.module.css | 12 +++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/components/CommunityPortal/Activities/ActivityList.jsx b/src/components/CommunityPortal/Activities/ActivityList.jsx index a348920086..634e578a41 100644 --- a/src/components/CommunityPortal/Activities/ActivityList.jsx +++ b/src/components/CommunityPortal/Activities/ActivityList.jsx @@ -2,6 +2,7 @@ import { useState, useEffect } from 'react'; import { useSelector } from 'react-redux'; import styles from './ActivityList.module.css'; +import { Button } from 'reactstrap'; // import { useHistory } from 'react-router-dom'; function ActivityList() { @@ -13,6 +14,9 @@ function ActivityList() { location: '', }); + const [currentPage, setCurrentPage] = useState(1); + const itemsPerPage = 10; + useEffect(() => { // Fetch activities (mock or replace with API call) const fetchedActivities = [ @@ -146,6 +150,11 @@ function ActivityList() { }); }; + const totalPages = Math.ceil(filteredActivities.length / itemsPerPage); + const startIndex = (currentPage - 1) * itemsPerPage; + + const paginatedActivities = filteredActivities.slice(startIndex, startIndex + itemsPerPage); + return (

Activity List

@@ -187,9 +196,9 @@ function ActivityList() {
- {filteredActivities.length > 0 ? ( + {paginatedActivities.length > 0 ? (
+ + {totalPages > 1 && ( +
+ + {Array.from({ length: totalPages }, (_, i) => i + 1).map(page => ( + + ))} + +
+ )} ); } diff --git a/src/components/CommunityPortal/Activities/ActivityList.module.css b/src/components/CommunityPortal/Activities/ActivityList.module.css index 0c5bc8b0d5..2bab1acbc1 100644 --- a/src/components/CommunityPortal/Activities/ActivityList.module.css +++ b/src/components/CommunityPortal/Activities/ActivityList.module.css @@ -152,3 +152,15 @@ padding: 10px; } } + +.pagination{ + display: flex; + gap: 8px; + justify-content: center; + margin-top: 16px; +} + +.activePage{ + font-weight: bold; + text-decoration: underline; +} \ No newline at end of file From 0e2aec7dd81751dee2d26614b6588a51b12d6d50 Mon Sep 17 00:00:00 2001 From: Akshith <33996844+akshith312@users.noreply.github.com> Date: Sat, 2 May 2026 10:32:30 -0700 Subject: [PATCH 2/3] fix: Resolve merge conflicts --- .../Activities/ActivityList.jsx | 380 +++++++++++------- .../Activities/ActivityList.module.css | 282 ++++++++++--- .../Activities/mockActivities.js | 182 +++++++++ 3 files changed, 636 insertions(+), 208 deletions(-) create mode 100644 src/components/CommunityPortal/Activities/mockActivities.js diff --git a/src/components/CommunityPortal/Activities/ActivityList.jsx b/src/components/CommunityPortal/Activities/ActivityList.jsx index 634e578a41..9e0a0e3a66 100644 --- a/src/components/CommunityPortal/Activities/ActivityList.jsx +++ b/src/components/CommunityPortal/Activities/ActivityList.jsx @@ -1,146 +1,83 @@ // Activity List Component -import { useState, useEffect } from 'react'; +import { useState, useEffect, useMemo } from 'react'; import { useSelector } from 'react-redux'; +import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from 'reactstrap'; import styles from './ActivityList.module.css'; -import { Button } from 'reactstrap'; -// import { useHistory } from 'react-router-dom'; +import { mockActivities } from './mockactivities'; function ActivityList() { const [activities, setActivities] = useState([]); + const [loading, setLoading] = useState(true); + 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: '', }); + 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'); + } else { + document.body.classList.remove('activity-list-dark-body'); + } + + return () => { + document.body.classList.remove('activity-list-dark-body'); + }; + }, [darkMode]); + + // Fetch activities (mock fallback) useEffect(() => { - // Fetch activities (mock or replace with API call) - const fetchedActivities = [ - { - id: 1, - name: 'Yoga Class', - type: 'Fitness', - date: '2024-01-10', - location: 'Community Center', - }, - { - id: 2, - name: 'Book Club', - type: 'Social', - date: '2024-01-12', - location: 'Library', - }, - { - id: 3, - name: 'Coding Workshop', - type: 'Educational', - date: '2023-12-30', - location: 'Tech Hub', - }, - { - id: 4, - name: 'Painting Session', - type: 'Art', - date: '2024-01-15', - location: 'Art Studio', - }, - { - id: 5, - name: 'Dance Class', - type: 'Fitness', - date: '2024-01-10', - location: 'Community Center', - }, - { - id: 6, - name: 'Gardening Meetup', - type: 'Social', - date: '2024-01-20', - location: 'Botanical Garden', - }, - { - id: 7, - name: 'Cooking Class', - type: 'Educational', - date: '2024-01-18', - location: 'Culinary School', - }, - { - id: 8, - name: 'Photography Walk', - type: 'Art', - date: '2023-12-30', - location: 'City Park', - }, - { - id: 9, - name: 'Marathon Training', - type: 'Fitness', - date: '2024-02-01', - location: 'Stadium', - }, - { - id: 10, - name: 'Chess Tournament', - type: 'Social', - date: '2024-01-12', - location: 'Library', - }, - { - id: 11, - name: 'Tech Talk', - type: 'Educational', - date: '2024-01-15', - location: 'Tech Hub', - }, - { - id: 12, - name: 'Sculpture Workshop', - type: 'Art', - date: '2024-01-25', - location: 'Art Studio', - }, - { - id: 13, - name: 'Pilates Class', - type: 'Fitness', - date: '2024-01-20', - location: 'Community Center', - }, - { - id: 14, - name: 'Film Screening', - type: 'Social', - date: '2024-01-18', - location: 'Library', - }, - { - id: 15, - name: 'Robotics Expo', - type: 'Educational', - date: '2024-01-10', - location: 'Tech Hub', - }, - ]; - setActivities(fetchedActivities); + const fetchActivities = async () => { + try { + setLoading(true); + setError(null); + + // Simulated API failure fallback + 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); + } + }; + + fetchActivities(); }, []); + // Reset page 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 filteredActivities = activities.filter(activity => { - return ( - (!filter.type || activity.type.toLowerCase().includes(filter.type.toLowerCase())) && - (!filter.date || activity.date === filter.date) && - (!filter.location || activity.location.toLowerCase().includes(filter.location.toLowerCase())) - ); - }); + const handleSortChange = e => { + setSortOrder(e.target.value); + }; const handleClearFilters = () => { setFilter({ @@ -148,35 +85,112 @@ function ActivityList() { date: '', location: '', }); + setShowPastEvents(false); + setCurrentPage(1); + }; + + const handleActivityClick = activity => { + setSelectedActivity(activity); + setModalOpen(true); + }; + + const handleCloseModal = () => { + setModalOpen(false); }; + const startOfToday = useMemo(() => { + const d = new Date(); + d.setHours(0, 0, 0, 0); + return d; + }, []); + + const activityTypes = useMemo(() => { + const typeOrder = new Map(); + + activities.forEach(activity => { + if (activity.type && !typeOrder.has(activity.type)) { + typeOrder.set(activity.type, typeOrder.size); + } + }); + + return [...typeOrder.keys()].sort((a, b) => typeOrder.get(a) - typeOrder.get(b)); + }, [activities]); + + const filteredActivities = activities + .filter(activity => showPastEvents || activity._dateObj >= startOfToday) + .filter(activity => { + return ( + (!filter.type || activity.type === filter.type) && + (!filter.date || activity.date === filter.date) && + (!filter.location || + activity.location.toLowerCase().startsWith(filter.location.toLowerCase())) + ); + }) + .sort((a, b) => { + const dateA = new Date(a.date); + const dateB = new Date(b.date); + return sortOrder === 'earliest' ? dateA - dateB : dateB - dateA; + }); + + // Pagination (AFTER filtering) const totalPages = Math.ceil(filteredActivities.length / itemsPerPage); - const startIndex = (currentPage - 1) * itemsPerPage; + const safePage = Math.min(currentPage, totalPages || 1); + const startIndex = (safePage - 1) * itemsPerPage; const paginatedActivities = filteredActivities.slice(startIndex, startIndex + itemsPerPage); return ( -
-

Activity List

+
+

Activity List

-
-