diff --git a/src/api/event.ts b/src/api/event.ts index c786cd95..06b1164a 100644 --- a/src/api/event.ts +++ b/src/api/event.ts @@ -55,8 +55,10 @@ export const deleteEvent = (eid: string) => Delete<{}>('event/' + eid); export const getUpcomingEvents = (): Promise => get('event/upcoming'); -export const getPastEvents = (): Promise => - get('event/past-events'); +export const getPastEvents = (skip: number, limit: number): Promise => + get(`event/past-events?skip=${skip}&limit=${limit}`); +export const getPastEventsCount = (): Promise<{ count: number }> => + get<{ count: number }>('event/past-events/count'); export const getJoinedEvents = (): Promise => get('event/joined-events'); diff --git a/src/components/pages/events/eventOverview/eventOverview.scss b/src/components/pages/events/eventOverview/eventOverview.scss index 768a8055..1aadcf85 100644 --- a/src/components/pages/events/eventOverview/eventOverview.scss +++ b/src/components/pages/events/eventOverview/eventOverview.scss @@ -39,7 +39,7 @@ .eventOverview { display: flex; flex-direction: column; - min-height: 100vh; + min-height: 50vh; } .eventContent { @@ -92,6 +92,41 @@ padding-left: 1rem; } } +.headerButton { + border: none; + border-radius: 0.5rem; + padding: 0.5rem 1rem; + cursor: pointer; + margin-right: 0.5rem; +} +.paginationControls { + display: flex; + justify-content: center; + align-items: center; + gap: 1rem; + margin-top: 20px; +} +.pageButton { + background: none; + border: 1px solid #ccc; + color: white; + padding: 0.25rem 0.5rem; + cursor: pointer; + min-width: 2rem; + text-align: center; +} + +.pageButton.active { + background-color: #2b2c3d; + color: white; + border: 1px solid white; +} +.disabled { + opacity: 0.5; + cursor: not-allowed; + pointer-events: none; +} + @media screen and (max-width: 768px) { .eventOverviewContainer { width: 95%; diff --git a/src/components/pages/events/eventOverview/eventOverview.tsx b/src/components/pages/events/eventOverview/eventOverview.tsx index a9c454b4..df4863c5 100644 --- a/src/components/pages/events/eventOverview/eventOverview.tsx +++ b/src/components/pages/events/eventOverview/eventOverview.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from 'react'; import './eventOverview.scss'; +import Icon from 'components/atoms/icons/icon'; import EventPreview from 'components/molecules/event/eventPreview/EventPreview'; import useUpcomingEvents from 'hooks/useEvents'; import LoadingWrapper from 'components/atoms/loadingWrapper/LoadingWrapper'; @@ -9,6 +10,7 @@ import { Event } from 'models/apiModels'; import { getJoinedEvents, getPastEvents } from 'api'; import { sortDate } from 'utils/sorting'; import { useToast } from 'hooks/useToast'; +import { getPastEventsCount } from 'api'; interface IEventOverview { events: Event[]; @@ -46,6 +48,11 @@ const EventOverview: React.FC = () => { const [pastEvents, setPastEvents] = useState(); const [pastErrorMsg, setPastErrorMsg] = useState(''); const { addToast } = useToast(); + const [skip, setSkip] = useState(0); + const [limit] = useState(10); + const [totalEvents, setTotalEvents] = useState(0); + const totalPages = Math.ceil(totalEvents / limit); + const currentPage = Math.floor(skip / limit) + 1; const fetchEvents = async () => { try { @@ -61,7 +68,7 @@ const EventOverview: React.FC = () => { } try { /* Get past events */ - const past = await getPastEvents(); + const past = await getPastEvents(skip, limit); past.sort((a: Event, b: Event) => sortDate(new Date(b.date), new Date(a.date)) ); @@ -70,6 +77,25 @@ const EventOverview: React.FC = () => { setPastErrorMsg('En ukjent feil skjedde'); } }; + useEffect(() => { + fetchEvents(); + }, [skip]); + useEffect(() => { + const fetchTotalEvents = async () => { + try { + const data = await getPastEventsCount(); + setTotalEvents(data.count); + } catch (error) { + console.error('Error fetching total past events:', error); + setTotalEvents(0); + addToast({ + title: 'Failed to fetch past events count', + status: 'error', + }); + } + }; + fetchTotalEvents(); + }, []); useEffect(() => { if (eventContent === 'my events' && joinedErrorMsg.length) { @@ -87,10 +113,48 @@ const EventOverview: React.FC = () => { } }, [eventContent, joinedErrorMsg, pastErrorMsg, addToast]); - useEffect(() => { - fetchEvents(); - }, []); + const handleNextPage = () => { + if (currentPage < totalPages) { + setSkip((prevSkip) => prevSkip + limit); + } + }; + + const handlePreviousPage = () => { + if (currentPage > 1) { + setSkip((prevSkip) => Math.max(prevSkip - limit, 0)); + } + }; + const generatePages = () => { + const pages = []; + + // Always show the first page + pages.push(1); + + // Show ellipsis if there are several pages between the first and the current page + if (currentPage > 3) { + pages.push('...'); + } + + // Add pages around the current page + for ( + let i = Math.max(2, currentPage - 1); + i <= Math.min(totalPages - 1, currentPage + 1); + i++ + ) { + pages.push(i); + } + + // Add ellipsis and the last page if necessary + if (currentPage < totalPages - 2) { + pages.push('...'); + } + if (totalPages > 1) { + pages.push(totalPages); + } + + return pages; + }; return (
@@ -132,6 +196,57 @@ const EventOverview: React.FC = () => { /> )} +
+ {eventContent === 'past events' && ( + <> +
+ +
+ + {generatePages().map((page, index) => + page === '...' ? ( + + ... + + ) : ( + + ) + )} + +
+ +
+ + )} +