feat: Refactor Community Events page

Refactored Community Events page to be dynamic and API-driven.

Implemented a vertical carousel with category filtering and color-coded event cards.

Added new data pipeline to fetch event details from Zoho Calendar API at build time.

Fixed infinite rebuild loop in Eleventy by configuring the file watcher to ignore the intermediary data file.
This commit is contained in:
2025-09-09 14:52:48 -05:00
parent c5fd50bd35
commit 5477191d39
6 changed files with 488 additions and 82 deletions

View File

@@ -83,7 +83,7 @@ module.exports = async function() {
const eventsListUrl = `${zohoApiUrl}/events?range={"start":"${startDate}","end":"${endDate}"}`;
console.log(`Making initial API call to: ${eventsListUrl}`);
console.log(`Using access token`);
let response = await fetch(eventsListUrl, {
headers: { Authorization: `Zoho-oauthtoken ${accessToken}` }
});
@@ -115,36 +115,55 @@ module.exports = async function() {
isallday: event.isallday,
location: event.location,
displayDate: formatEventDate(event.dateandtime.start, event.dateandtime.end, event.isallday),
color: event.color,
};
console.log(`Processing event with UID: ${basicEvent.uid}`);
// This logic is necessary to get the description from a second API call
if (basicEvent.uid) {
const eventDetailsUrl = `${zohoApiUrl}/events/${basicEvent.uid}`;
console.log(`Making details API call to: ${eventDetailsUrl}`);
const detailsResponse = await fetch(eventDetailsUrl, {
headers: { Authorization: `Zoho-oauthtoken ${accessToken}` }
});
if (detailsResponse.ok) {
const detailsData = await detailsResponse.json();
console.log(`Details API call for UID ${basicEvent.uid} successful. Received data:`, detailsData);
if (detailsData.events && detailsData.events.length > 0) {
basicEvent.description = detailsData.events[0].description;
console.log(`Description added for event UID: ${basicEvent.uid}`);
}
} else {
console.warn(`Failed to fetch details for event UID: ${basicEvent.uid}`);
console.log(`Details response status: ${detailsResponse.status}`);
}
}
// Assign category based on color
switch (basicEvent.color) {
case '#7CAA56':
basicEvent.category = 'sales';
break;
case '#FC6060':
basicEvent.category = 'workshop';
break;
case '#FFC464':
basicEvent.category = 'community';
break;
default:
basicEvent.category = 'uncategorized';
}
return basicEvent;
});
const normalizedEvents = await Promise.all(normalizedEventsPromises);
console.log("All events processed. Final normalized events array:", normalizedEvents);
const filePath = path.resolve(__dirname, '..', '_data', 'eventsJson.js');
const fileContents = `module.exports = { normalizedEvents: ${JSON.stringify(normalizedEvents, null, 2)} };`;
fs.writeFileSync(filePath, fileContents, 'utf-8');
console.log(`Data successfully written to ${filePath}`);
return normalizedEvents;
} catch (error) {