Skip to content

Commit

Permalink
feat(events): Implement Events page and separate data
Browse files Browse the repository at this point in the history
- Implemented Events page with dynamic event listing.
- Separated event data into a dedicated file.
- Automatically hides past events.
- Added archiving functionality for events.
- Automatically sorts events by date.
- Added functionality to highlight and scroll to the current event.
  • Loading branch information
TKanX committed Nov 29, 2024
1 parent 8c4a23f commit e3f8575
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 1 deletion.
18 changes: 18 additions & 0 deletions data/events.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* @fileoverview Events Data
* @description Data for the events page.
*/

/**
* @type {Event[]}
* @typedef {Object} Event
* @property {string} title The title of the event.
* @property {string} date The date of the event. Must be in ISO 8601 format.
* @property {string} thumbnail The path to the thumbnail image of the event. Must be in the public/images/events directory.
* @property {string} description The description of the event. Should be a brief summary.
* @property {string} link The link to the event page. Must be in the /events directory.
* @property {boolean} archived Whether the event is archived or not. Archived events are not displayed on the events page.
*/
const eventsData = [];

export default eventsData;
2 changes: 1 addition & 1 deletion pages/about.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* @fileoverview About page
* @fileoverview About Page
* @description The about page of the website.
*/

Expand Down
121 changes: 121 additions & 0 deletions pages/events.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/**
* @fileoverview Events Page
* @description The events page of the website. (NOTE: Data is imported from data/events.mjs)
*/

import { useEffect, useState, useRef } from 'react';
import eventsData from '../data/events.mjs';

export default function EventsPage() {
const [currentEvent, setCurrentEvent] = useState(null);
const eventsRef = useRef([]);

// Sort the events and filter out archived ones
const sortedEvents = eventsData
.filter((event) => !event.archived) // Only show events that are not archived
.sort((a, b) => new Date(a.date) - new Date(b.date)); // Sort events by date

useEffect(() => {
const now = new Date().toISOString();
// Find the first upcoming event
const upcomingEvent = sortedEvents.find(
(event) => new Date(event.date) > new Date(now),
);
setCurrentEvent(upcomingEvent); // Set the current event to be the first upcoming one

// Scroll to the current event in the list
const currentEventElement =
eventsRef.current[sortedEvents.indexOf(upcomingEvent)];
if (currentEventElement) {
setTimeout(() => {
currentEventElement.scrollIntoView({
behavior: 'smooth',
block: 'center', // Scroll to the center of the event
});
}, 200);
}
}, [sortedEvents]); // Re-run when the sorted events change

return (
<div className='p-8'>
<h1 className='text-3xl font-bold mb-6 text-primary'>Events</h1>
<div className='space-y-8'>
{sortedEvents.length > 0 ? (
// Map through the sorted events and display each one
sortedEvents.map((event, index) => {
const eventDate = new Date(event.date);
const isPastEvent = eventDate < new Date(); // Check if the event is in the past

return (
<div
key={event.date}
ref={(el) => (eventsRef.current[index] = el)} // Save a reference to the event element
className='relative group transition-all duration-500'
>
{/* Event Thumbnail */}
<div
className='w-full h-64 bg-cover bg-center relative'
style={{
backgroundImage: event.thumbnail
? `url(${event.thumbnail})`
: 'none', // Use event's thumbnail if available
filter: isPastEvent ? 'grayscale(100%) blur(2px)' : 'none', // Apply grayscale and blur for past events
backgroundPosition: 'center',
backgroundSize: 'cover',
backgroundColor: event.thumbnail
? 'transparent'
: '#f0f0f0', // Set background color if no thumbnail
}}
>
{/* Show a gray overlay for events without a thumbnail */}
{!event.thumbnail && (
<div className='absolute inset-0 bg-gray-200 opacity-50'></div>
)}
{/* Gradient overlay */}
<div className='absolute rounded-lg inset-0 bg-gradient-to-r from-black to-transparent opacity-50'></div>
</div>

{/* Event Title and Description */}
<div
className={`absolute top-0 left-0 w-full h-full flex justify-center items-center ${isPastEvent ? 'opacity-40 hover:opacity-80' : 'opacity-80 hover:opacity-100'} transition-opacity duration-300`}
>
<div className='text-center text-light px-4 py-6'>
<h3 className='text-2xl font-semibold'>{event.title}</h3>
<p className='text-md mt-2'>{event.description}</p>
<p className='text-sm mt-2'>
{/* Format and display event date */}
{eventDate.toLocaleString('en-US', {
weekday: 'short',
month: 'short',
day: 'numeric',
year: 'numeric',
})}
</p>
{event.link && (
// Link to event details, if available
<a
href={event.link}
className='inline-block mt-2 text-accent hover:text-accent-600'
aria-label={`Learn more about ${event.title}`}
>
Learn More
</a>
)}
</div>
</div>
</div>
);
})
) : (
// Display message when no upcoming events are available
<div className='text-center text-light-800 p-8'>
<h3 className='text-2xl font-semibold'>No Upcoming Events</h3>
<p className='text-md mt-2'>
All events are either archived or no events are scheduled.
</p>
</div>
)}
</div>
</div>
);
}

0 comments on commit e3f8575

Please sign in to comment.