Skip to content

Commit

Permalink
Merge pull request #305 from hlxsites/feature/event-page-implementation
Browse files Browse the repository at this point in the history
Feature/event page implementation
  • Loading branch information
shivangi1422 authored May 8, 2024
2 parents ea06e70 + 338b840 commit 721fe83
Show file tree
Hide file tree
Showing 6 changed files with 648 additions and 0 deletions.
48 changes: 48 additions & 0 deletions blocks/events/events.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
* {
box-sizing: border-box;
}

main .section > div {
margin: 0 auto;
padding: 0 15px;
}

.section.events-container .events-wrapper {
padding-top: 0;
}

.events .list .filter .select .dropdown-menu.open {
max-height: initial;
}

.events .list .filter .select.open .dropdown-toggle,
.events .list .filter .select .dropdown-toggle:hover {
color: inherit;
}

.events label {
display: block;
padding: 0 0 0 37px;
margin: 0 0 20px;
position: relative;
cursor: pointer;
}

.events input[type="checkbox"].filter-item {
display: none;
}

.events label span::before {
content: "";
width: 18px;
height: 18px;
position: absolute;
left: 9px;
background: none;
border: 2px solid #adb3b7;
}

.events input[type="checkbox"].filter-item:checked+span::before {
background-color: var(--primary-color);
border-color: var(--primary-color);
}
319 changes: 319 additions & 0 deletions blocks/events/events.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,319 @@
import { createOptimizedPicture, capitalizeWords, toClassName } from '../../scripts/aem.js';
import {
div, a, p, ul, li, article, span,
label, input, h2,
h3,
nav,
button,
} from '../../scripts/dom-builder.js';
import { formatDateRange } from '../../scripts/scripts.js';

const REGIONS = [
'Europe',
'North America',
];

const TYPES = [
'Conference',
'Events',
'Webinar',
];

async function fetchPostData() {
try {
const response = await fetch('/query-index.json');
const jsonData = await response.json();
return jsonData.data;
} catch (error) {
return [];
}
}

let currentPageNumber = 1;
const itemsPerPage = 10;

// Function to sort events based on their start dates
function sortEventsByDate(events) {
// Sort events based on their start dates
events.sort((dateA, dateB) => {
// Convert start dates to Date objects for comparison
const dateAnew = new Date(dateA.startdate * 1000);
const dateBnew = new Date(dateB.startdate * 1000);

// Compare dates
if (dateAnew < dateBnew) {
return -1; // dateA comes before dateB
} if (dateAnew > dateBnew) {
return 1; // dateA comes after dateB
}
return 0; // dates are equal
});

return events;
}

// Function to separate events based on current date and class parameter
function separateEventsByDate(events, currentDate, classParameter) {
const futureEvents = [];
const archivedEvents = [];
events.forEach((event) => {
const startDate = new Date(event.startdate * 1000);
const endDate = new Date(event.enddate * 1000);

if (startDate > currentDate || endDate > currentDate) {
futureEvents.push(event);
} else if (endDate < currentDate) {
archivedEvents.push(event);
}
});

return classParameter === 'future' ? futureEvents : archivedEvents;
}

async function generateEventDetails(articles) {
const articleElements = articles.map((art) => {
let date = '';
if (art.startdate && art.enddate) {
const endDate = new Date(art.enddate * 1000).toLocaleDateString('en-Us', { month: 'short', day: '2-digit', year: 'numeric' });
const eventDate = art.startdate === art.enddate
? endDate : formatDateRange(art.startdate, art.enddate);
date = (art.eventtime !== '') ? `${eventDate} ${art.eventtime}` : eventDate;
}
return article(
{ class: 'item' },
div(
{ class: 'image' },
a({
href: art.path,
title: art.title,
}, createOptimizedPicture(art.image, art.title)),
),
div(
{ class: 'content' },
date ? p({ class: 'cite' }, date) : '',
p(
a({
class: 'title',
title: art.title,
href: art.path,
}, capitalizeWords(art.title)),
),
ul(
{ class: 'keyword-list' },
li({ class: 'item' }, art.type),
li({ class: 'item' }, art.address !== art.region ? art.address : art.region),
(art.address !== art.region ? li({ class: 'item' }, art.region) : ''),
),
),
);
});
return articleElements;
}

// Function to update the events displayed based on filtering
function updateEvents(events) {
// Clear the existing event list
const itemsContainer = document.querySelector('.items');
itemsContainer.innerHTML = '';

// Generate and append new event details
generateEventDetails(events).then((eventContent) => {
const pageTitle = document.title;
itemsContainer.appendChild(h2({ class: 'event-title' }, pageTitle));
if (eventContent.length === 0) {
const noEventsMesage = h3({ class: 'no-result' }, 'No Events Found');
itemsContainer.appendChild(noEventsMesage);
} else {
eventContent.forEach((element) => {
itemsContainer.appendChild(element);
});
}
});
}

// Event listener function to handle checkbox changes
function handleCheckboxChange(event, eventData) {
const checkedCheckboxes = document.querySelectorAll('.filter-item:checked');
const selectedOptions = Array.from(checkedCheckboxes)
.map((checkbox) => checkbox.nextSibling.textContent);
let filteredEvents;
// Filter events based on selected options
const eventTypes = [];
const regions = [];

if (selectedOptions.length > 0) {
selectedOptions.forEach((option) => {
if (eventData.some((data) => data.type === option)) {
eventTypes.push(option);
} else if (eventData.some((data) => data.region === option)) {
regions.push(option);
}
});

if (eventTypes.length > 0 && regions.length === 0) {
filteredEvents = eventData.filter((data) => eventTypes.includes(data.type));
} else if (eventTypes.length === 0 && regions.length > 0) {
filteredEvents = eventData.filter((data) => regions.includes(data.region));
} else {
filteredEvents = eventData.filter((data) => eventTypes
.includes(data.type) && regions.includes(data.region));
}
} else {
filteredEvents = eventData;
}
updateEvents(filteredEvents);
const paginationContainer = document.querySelector('.pagination');
if (filteredEvents.length <= itemsPerPage) {
paginationContainer.style.display = 'none';
} else {
paginationContainer.style.display = 'block';
}
}

function createEventsDropdown(eventName, options) {
const container = div({ class: 'select' });
container.setAttribute('name', eventName);

const btn = div({
type: 'button',
class: 'dropdown-toggle',
value: '',
}, eventName);
// btn.addEventListener('click', toggleFilter, false);
container.append(btn);

const dropDown = div({ class: 'dropdown-menu' });
options.forEach((option) => {
const fieldName = toClassName(option.toString());
dropDown.append(label(
{ for: fieldName },
input({
type: 'checkbox',
name: fieldName,
id: fieldName,
class: 'filter-item',
}),
span(option),
));
});
container.append(dropDown);

return container;
}

function createLink(text, currentPage) {
const linkHref = currentPage === 'events' ? '/about-us/archived-events' : '/about-us/events';
const link = p(a({ href: linkHref, title: text }, text));
return link;
}

async function buildSidePanel(currentPage, eventData) {
const sidePanel = div({ class: 'filter' });
const panelTitle = p({ class: 'panel-title' }, 'Filter By:');

// Dropdowns
const eventTypeDropdown = createEventsDropdown('Event Type', TYPES);
const regionDropdown = createEventsDropdown('Region', REGIONS);

// Append dropdowns to filter div
const linkText = currentPage === 'events' ? 'Archived Events' : 'Upcoming Events';
const link = createLink(linkText, currentPage);

// Append filter div to side panel
sidePanel.appendChild(panelTitle);
sidePanel.appendChild(eventTypeDropdown);
sidePanel.appendChild(regionDropdown);
sidePanel.appendChild(link);

const checkboxes = sidePanel.querySelectorAll('.select .dropdown-menu .filter-item');
checkboxes.forEach((checkbox) => {
checkbox.addEventListener('change', (event) => {
handleCheckboxChange(event, eventData);
});
});

return sidePanel;
}

function updatePaginationButtons(currentPage) {
document.querySelectorAll('.pagination .pager-item').forEach((data) => {
data.classList.remove('active');
if (parseInt(data.textContent, 10) === currentPage) {
data.classList.add('active');
}
});
}

function displayPage(page, events) {
const startIndex = (page - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const currentPageEvents = events.slice(startIndex, endIndex);
updateEvents(currentPageEvents);
}

function handlePagination(page, events) {
currentPageNumber = page;
displayPage(currentPageNumber, events); // Update UI with new page
}

function generatePaginationButtons(totalPages, currentPage, events) {
const paginationContainer = nav({ class: 'pagination' });
for (let i = 1; i <= totalPages; i += 1) {
const pageButton = button({ class: 'pager-item' }, i);
if (i === currentPage) {
pageButton.classList.add('active');
}
pageButton.addEventListener('click', () => {
handlePagination(i, events);
updatePaginationButtons(i);
});
paginationContainer.appendChild(pageButton);
}
return paginationContainer;
}

function getTotalPages(events) {
return Math.ceil(events.length / itemsPerPage);
}

export default async function decorate(block) {
const outerBlock = document.querySelector('.section');
outerBlock.classList.add('outer');
const postData = await fetchPostData();
const page = window.location.pathname.includes('/events');
const currentPage = page ? 'events' : 'archived-events';
const filteredResults = postData.filter((item) => /events\/.*$/.test(item.path.toLowerCase()));
const sortedEvents = sortEventsByDate(filteredResults);
const currentDate = new Date();
const classParameter = document.querySelector('.events.future') ? 'future' : 'archive';
const eventsToshow = separateEventsByDate(sortedEvents, currentDate, classParameter);
const itemsContainer = div({ class: 'items' });

const eventContent = await generateEventDetails(eventsToshow);
const sidePanel = await buildSidePanel(currentPage, eventsToshow);

const wrapper = div({ class: 'list' });
const pageTitle = document.title;
const title = h2({ class: 'event-title' }, pageTitle);
itemsContainer.append(title);
wrapper.appendChild(sidePanel);
if (eventContent && eventContent.length > 0) {
eventContent.forEach((element) => {
itemsContainer.appendChild(element);
});
} else {
const noEventMessage = currentPage === 'events' ? 'No Upcoming Events' : 'No Archived Events';
const noResults = h3({ class: 'no-result' }, noEventMessage);
itemsContainer.appendChild(noResults);
block.appendChild(itemsContainer);
}

wrapper.appendChild(itemsContainer);
block.appendChild(wrapper);
if (eventsToshow.length > itemsPerPage) {
const totalPages = getTotalPages(eventsToshow);
wrapper.appendChild(generatePaginationButtons(totalPages, currentPageNumber, eventsToshow));

displayPage(currentPageNumber, eventsToshow);
}
}
1 change: 1 addition & 0 deletions head.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
<link rel="stylesheet" href="/styles/responsive.css"/>
<link rel="stylesheet" href="/styles/gcse.css"/>
<link rel="stylesheet" href="/styles/styles_2020.css"/>
<link rel="stylesheet" href="/styles/list.css"/>
6 changes: 6 additions & 0 deletions scripts/dom-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,9 @@ export function tr(...items) { return domEl('tr', ...items); }
export function td(...items) { return domEl('td', ...items); }
export function th(...items) { return domEl('th', ...items); }
export function time(...items) { return domEl('time', ...items); }

export function checkbox(attributes, labelContent) {
const checkboxInput = input({ type: 'checkbox', ...attributes });
const labelElement = label(labelContent, checkboxInput);
return div(labelElement);
}
Loading

0 comments on commit 721fe83

Please sign in to comment.