Skip to content

added section for upcoming events#39

Open
Ankita-kuntal wants to merge 1 commit intogaash-lab:mainfrom
Ankita-kuntal:events-page
Open

added section for upcoming events#39
Ankita-kuntal wants to merge 1 commit intogaash-lab:mainfrom
Ankita-kuntal:events-page

Conversation

@Ankita-kuntal
Copy link
Copy Markdown
Contributor

No description provided.

@vercel
Copy link
Copy Markdown

vercel bot commented Oct 11, 2025

@Ankita-kuntal is attempting to deploy a commit to the Asma's projects Team on Vercel.

A member of the Team first needs to authorize it.

@entelligence-ai-pr-reviews
Copy link
Copy Markdown

🔒 Entelligence AI Vulnerability Scanner

❌ Security analysis failed: Security analysis failed: context deadline exceeded: This error is likely due to exceeding 'timeoutMs' — the total time a long running request (like process or directory watch) can be active. It can be modified by passing 'timeoutMs' when making the request. Use '0' to disable the timeout.

Comment on lines +13 to +20
const getEventDate = (dates) => {
if (!dates || dates.length === 0) return new Date();

// Get the latest date from the dates array for sorting
const latestDate = dates[dates.length - 1];
const [day, month, year] = latestDate.split('-');
return new Date(year, month - 1, day);
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correctness: getEventDate returns new Date() (current date) if dates is empty or falsy, causing all such events to be treated as upcoming and possibly misclassified.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In client/src/pages/Events.jsx, lines 13-20, the `getEventDate` function returns `new Date()` (the current date) if `dates` is empty or falsy. This causes events with missing/empty dates to be misclassified as upcoming. Change the function to return `null` in this case, and ensure all usages of `getEventDate` handle `null` appropriately.
📝 Committable Code Suggestion

‼️ Ensure you review the code suggestion before committing it to the branch. Make sure it replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
const getEventDate = (dates) => {
if (!dates || dates.length === 0) return new Date();
// Get the latest date from the dates array for sorting
const latestDate = dates[dates.length - 1];
const [day, month, year] = latestDate.split('-');
return new Date(year, month - 1, day);
};
const getEventDate = (dates) => {
if (!dates || dates.length === 0) return null;
// Get the latest date from the dates array for sorting
const latestDate = dates[dates.length - 1];
const [day, month, year] = latestDate.split('-');
return new Date(year, month - 1, day);
};

Comment on lines +41 to +45
const sortedEvents = data.events.sort((a, b) => {
const dateA = getEventDate(a.dates);
const dateB = getEventDate(b.dates);
return dateA - dateB;
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

performance: data.events.sort(...) mutates the original array in-place, causing side effects if data.events is reused elsewhere and breaking referential integrity for React state updates.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In client/src/pages/Events.jsx, lines 41-45, the code mutates the original `data.events` array in-place with `.sort()`, which can cause side effects and break React state update patterns. Refactor to use `[...data.events].sort(...)` to avoid mutating the original array.
📝 Committable Code Suggestion

‼️ Ensure you review the code suggestion before committing it to the branch. Make sure it replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
const sortedEvents = data.events.sort((a, b) => {
const dateA = getEventDate(a.dates);
const dateB = getEventDate(b.dates);
return dateA - dateB;
});
const sortedEvents = [...data.events].sort((a, b) => {
const dateA = getEventDate(a.dates);
const dateB = getEventDate(b.dates);
return dateA - dateB;
});

Comment on lines +76 to +77
const upcoming = filtered.filter(event => !isEventPast(event.dates));
const past = filtered.filter(event => isEventPast(event.dates));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

performance: The events are filtered twice for past/upcoming in every useEffect, causing O(n) work twice per render; this can be combined into a single pass for better efficiency on large datasets.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In client/src/pages/Events.jsx, lines 76-77, the code filters the events array twice to separate past and upcoming events, resulting in two O(n) passes. Refactor to a single loop that pushes each event into either the `upcoming` or `past` array for better performance on large datasets.
📝 Committable Code Suggestion

‼️ Ensure you review the code suggestion before committing it to the branch. Make sure it replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
const upcoming = filtered.filter(event => !isEventPast(event.dates));
const past = filtered.filter(event => isEventPast(event.dates));
const upcoming = [];
const past = [];
for (const event of filtered) {
if (isEventPast(event.dates)) {
past.push(event);
} else {
upcoming.push(event);
}
}

Comment on lines +13 to +20
const getEventDate = (dates) => {
if (!dates || dates.length === 0) return new Date();

// Get the latest date from the dates array for sorting
const latestDate = dates[dates.length - 1];
const [day, month, year] = latestDate.split('-');
return new Date(year, month - 1, day);
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

performance: The function getEventDate is called multiple times per event (in sorting, filtering, and rendering), leading to redundant date parsing and computation for each event.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In client/src/pages/Events.jsx, lines 13-20, 42-43, 76-77, and 319, the function `getEventDate` is called multiple times per event (during sorting, filtering, and rendering), causing redundant date parsing and computation. Optimize by computing and storing the parsed event date once per event (e.g., as a property on the event object) during initial processing, and reuse it throughout the component.

Comment on lines 197 to +358
<p className="text-gray-500">Try adjusting your search or filter criteria</p>
</div>
) : (
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{filteredEvents.map((event, index) => (
<motion.div
key={event.id}
className="bg-white rounded-2xl overflow-hidden shadow-lg hover:shadow-xl transition-all duration-500 hover:-translate-y-2 border-t-4 h-full"
style={{ borderTopColor: getClubColor(event.clubName) }}
initial={{ opacity: 0, y: 50 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: index * 0.1 }}
whileHover={{ scale: 1.02 }}
>
<div className="p-6 flex flex-col h-full">
{/* Event Header */}
<div className="flex items-start justify-between mb-4">
<span
className="text-xs font-semibold px-3 py-1 rounded-full text-white"
style={{ backgroundColor: getClubColor(event.clubName) }}
>
{event.clubName}
</span>
<div className="text-right">
<div className="text-sm font-semibold" style={{ color: '#1F2647' }}>
{event.date}
</div>
<div className="text-xs text-gray-500">
{formatDate(event.dates)}
</div>
</div>
<>
{/* Upcoming Events Section */}
{upcomingEvents.length > 0 ? (
<div className="mb-12">
<div className="flex items-center mb-8">
<div className="flex items-center">
<div className="w-3 h-3 rounded-full mr-3" style={{ backgroundColor: '#0D9488' }}></div>
<h2 className="text-2xl sm:text-3xl font-bold" style={{ color: '#1F2647' }}>
Upcoming Events
</h2>
</div>
<div className="flex-grow ml-4 h-px bg-gradient-to-r from-teal-300 to-transparent"></div>
<span className="ml-4 text-sm text-gray-500 bg-gray-100 px-3 py-1 rounded-full">
{upcomingEvents.length} events
</span>
</div>

<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{upcomingEvents.map((event, index) => (
<EventCard
key={event.id}
event={event}
index={index}
getClubColor={getClubColor}
formatDate={formatDate}
isPast={false}
/>
))}
</div>
</div>
) : (
<div className="mb-12">
<div className="flex items-center mb-8">
<div className="flex items-center">
<div className="w-3 h-3 rounded-full mr-3" style={{ backgroundColor: '#0D9488' }}></div>
<h2 className="text-2xl sm:text-3xl font-bold" style={{ color: '#1F2647' }}>
Upcoming Events
</h2>
</div>
<div className="flex-grow ml-4 h-px bg-gradient-to-r from-teal-300 to-transparent"></div>
</div>

<div className="text-center py-12 bg-white rounded-2xl shadow-lg border-t-4" style={{ borderTopColor: '#0D9488' }}>
<div className="text-5xl mb-4">🎉</div>
<h3 className="text-xl font-semibold mb-2" style={{ color: '#1F2647' }}>No Upcoming Events</h3>
<p className="text-gray-600 mb-6">All events have concluded. Check back soon for new exciting events!</p>
<div className="text-sm text-gray-500">
Stay tuned to our social media for updates on future events
</div>
</div>
</div>
)}

{/* Event Title */}
<h3 className="text-xl font-bold mb-3 flex-shrink-0" style={{ color: '#1F2647' }}>
{event.eventName}
</h3>

{/* Event Description */}
<p className="text-gray-600 text-sm leading-relaxed flex-grow mb-4">
{event.description}
</p>

{/* Event Footer */}
<div className="flex items-center justify-between pt-4 border-t border-gray-100">
<div className="flex items-center">
<div
className="w-8 h-8 rounded-full flex items-center justify-center text-white text-sm"
style={{ backgroundColor: getClubColor(event.clubName) }}
>
📅
</div>
<span className="ml-2 text-sm font-medium" style={{ color: '#1F2647' }}>
Don't miss out!
</span>
</div>
{/* <button
className="text-sm font-medium px-3 py-1 rounded-lg transition-colors duration-300 hover:bg-gray-100"
style={{ color: getClubColor(event.clubName) }}
>
Learn More
</button> */}
{/* Past Events Section */}
{pastEvents.length > 0 && (
<div>
<div className="flex items-center mb-8">
<div className="flex items-center">
<div className="w-3 h-3 rounded-full mr-3" style={{ backgroundColor: '#6B7280' }}></div>
<h2 className="text-2xl sm:text-3xl font-bold text-gray-600">
Past Events
</h2>
</div>
<div className="flex-grow ml-4 h-px bg-gradient-to-r from-gray-300 to-transparent"></div>
<span className="ml-4 text-sm text-gray-500 bg-gray-100 px-3 py-1 rounded-full">
{pastEvents.length} events
</span>
</div>
</motion.div>
))}
</div>

<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{pastEvents.map((event, index) => (
<EventCard
key={event.id}
event={event}
index={index}
getClubColor={getClubColor}
formatDate={formatDate}
isPast={true}
/>
))}
</div>
</div>
)}
</>
)}
</div>
</div>
);
};

// Separate EventCard component for reusability
const EventCard = ({ event, index, getClubColor, formatDate, isPast }) => {
return (
<motion.div
className={`bg-white rounded-2xl overflow-hidden shadow-lg hover:shadow-xl transition-all duration-500 hover:-translate-y-2 border-t-4 h-full ${isPast ? 'opacity-75' : ''}`}
style={{ borderTopColor: getClubColor(event.clubName) }}
initial={{ opacity: 0, y: 50 }}
animate={{ opacity: isPast ? 0.75 : 1, y: 0 }}
transition={{ duration: 0.5, delay: index * 0.1 }}
whileHover={{ scale: 1.02, opacity: 1 }}
>
<div className="p-6 flex flex-col h-full">
{/* Event Header */}
<div className="flex items-start justify-between mb-4">
<div className="flex items-center">
<span
className="text-xs font-semibold px-3 py-1 rounded-full text-white"
style={{ backgroundColor: getClubColor(event.clubName) }}
>
{event.clubName}
</span>
{isPast && (
<span className="ml-2 text-xs bg-gray-200 text-gray-600 px-2 py-1 rounded-full">
Past
</span>
)}
</div>
<div className="text-right">
<div className="text-xs text-gray-500">
{formatDate(event.dates)}
</div>
</div>
</div>

{/* Event Title */}
<h3 className="text-xl font-bold mb-3 flex-shrink-0" style={{ color: isPast ? '#6B7280' : '#1F2647' }}>
{event.eventName}
</h3>

{/* Event Description */}
<p className={`text-sm leading-relaxed flex-grow mb-4 ${isPast ? 'text-gray-500' : 'text-gray-600'}`}>
{event.description}
</p>

{/* Event Footer */}
<div className="flex items-center justify-between pt-4 border-t border-gray-100">
<div className="flex items-center">
<div
className="w-8 h-8 rounded-full flex items-center justify-center text-white text-sm"
style={{ backgroundColor: isPast ? '#6B7280' : getClubColor(event.clubName) }}
>
📅
</div>
<span className={`ml-2 text-sm font-medium ${isPast ? 'text-gray-500' : ''}`} style={{ color: isPast ? '#6B7280' : '#1F2647' }}>
{isPast ? 'Event completed' : "Don't miss out!"}
</span>
</div>
<button
className={`text-sm font-medium px-3 py-1 rounded-lg transition-colors duration-300 hover:bg-gray-100 ${isPast ? 'text-gray-500' : ''}`}
style={{ color: isPast ? '#6B7280' : getClubColor(event.clubName) }}
>
{isPast ? 'View Details' : 'Learn More'}
</button>
</div>
</div>
</motion.div>
);
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

performance: The main component function is over 350 lines and contains substantial logic and rendering, making it difficult to maintain and reason about; this is a major maintainability issue.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In client/src/pages/Events.jsx, lines 1-358, the main Events component is very large and contains substantial logic, state, and rendering, making it hard to maintain. Refactor by extracting major sections (such as filtering logic, event section rendering, and helper functions) into separate components or hooks to improve maintainability and readability.

Comment on lines +429 to +430
{formatEventDate(event.dates)}
</span>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correctness: formatEventDate is referenced in JSX but its definition was deleted, causing a runtime ReferenceError and breaking event date display.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In client/src/pages/Home.jsx, lines 429-430, the code references `formatEventDate(event.dates)` but the `formatEventDate` function was deleted, causing a runtime ReferenceError and breaking event date display. Restore the date formatting logic inline or as a helper so that event dates render correctly and the app does not crash.
📝 Committable Code Suggestion

‼️ Ensure you review the code suggestion before committing it to the branch. Make sure it replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
{formatEventDate(event.dates)}
</span>
<span className="text-sm text-gray-500">
{(() => {
if (!event.dates || event.dates.length === 0) return 'Date TBD';
if (event.dates.length === 1) {
const [day, month, year] = event.dates[0].split('-');
const date = new Date(year, month - 1, day);
return date.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric'
});
} else {
const [startDay, startMonth, startYear] = event.dates[0].split('-');
const [endDay, endMonth, endYear] = event.dates[event.dates.length - 1].split('-');
const startDate = new Date(startYear, startMonth - 1, startDay);
const endDate = new Date(endYear, endMonth - 1, endDay);
return `${startDate.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric'
})} - ${endDate.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric'
})}`;
}
})()}

Comment on lines +82 to +103
const isEventUpcoming = (dates) => {
if (!dates || dates.length === 0) return true;

const latestDate = dates[dates.length - 1];
const [day, month, year] = latestDate.split('-');
const eventDate = new Date(year, month - 1, day);
const today = new Date();
today.setHours(0, 0, 0, 0);

return eventDate >= today;
};

// Filter for upcoming events and sort by date
const upcomingEvents = data.events
.filter(event => isEventUpcoming(event.dates))
.sort((a, b) => {
const getDate = (dates) => {
const [day, month, year] = dates[0].split('-');
return new Date(year, month - 1, day);
};
return getDate(a.dates) - getDate(b.dates);
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

performance: The isEventUpcoming and sorting logic in fetchEvents repeatedly parses date strings for every event, leading to O(n) redundant date parsing and object creation on each fetch; this can cause noticeable performance degradation as the number of events grows.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

Optimize date parsing in client/src/pages/Home.jsx lines 82-103. Currently, date strings are parsed multiple times per event during filtering and sorting, causing O(n) redundant computations. Refactor to precompute start and end Date objects for each event before filtering and sorting, so each event's dates are parsed only once. This will significantly improve performance for large event lists.
📝 Committable Code Suggestion

‼️ Ensure you review the code suggestion before committing it to the branch. Make sure it replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
const isEventUpcoming = (dates) => {
if (!dates || dates.length === 0) return true;
const latestDate = dates[dates.length - 1];
const [day, month, year] = latestDate.split('-');
const eventDate = new Date(year, month - 1, day);
const today = new Date();
today.setHours(0, 0, 0, 0);
return eventDate >= today;
};
// Filter for upcoming events and sort by date
const upcomingEvents = data.events
.filter(event => isEventUpcoming(event.dates))
.sort((a, b) => {
const getDate = (dates) => {
const [day, month, year] = dates[0].split('-');
return new Date(year, month - 1, day);
};
return getDate(a.dates) - getDate(b.dates);
})
// Precompute event dates to avoid repeated parsing
const today = new Date();
today.setHours(0, 0, 0, 0);
const eventsWithParsedDates = data.events.map(event => {
const startDateParts = event.dates && event.dates[0] ? event.dates[0].split('-') : null;
const endDateParts = event.dates && event.dates.length > 0 ? event.dates[event.dates.length - 1].split('-') : null;
return {
...event,
startDate: startDateParts ? new Date(startDateParts[2], startDateParts[1] - 1, startDateParts[0]) : null,
endDate: endDateParts ? new Date(endDateParts[2], endDateParts[1] - 1, endDateParts[0]) : null,
};
});
const upcomingEvents = eventsWithParsedDates
.filter(event => !event.endDate || event.endDate >= today)
.sort((a, b) => (a.startDate ? a.startDate - b.startDate : 0))
.slice(0, 6); // Show only first 6 upcoming events
setEvents(upcomingEvents);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant