{% liquid
assign wrapper_id = section.settings.wrapper_id
assign wrapper_class = section.settings.wrapper_class
%}
<div
{% if wrapper_id != blank %}
id="{{ wrapper_id | escape }}"
{% endif %}
class="event-listing-section {{ wrapper_class }}"
>
<div class="page-width">
<div id="event-month-nav" class="event-month-nav"></div>
<div id="event-list"></div>
</div>
</div>
<style>
.event-listing-section {
margin: 40px 0;
}
.event-month {
margin-bottom: 50px;
}
.event-month__title {
margin: 0 0 25px;
padding-bottom: 10px;
border-bottom: 2px solid #e5e5e5;
}
.event-item {
padding: 20px;
margin-bottom: 20px;
border: 1px solid #ececec;
border-radius: 8px;
}
.event-item__header {
display: flex;
gap: 15px;
flex-wrap: wrap;
margin-bottom: 10px;
}
.event-item__date {
font-weight: 700;
}
.event-item__title {
margin: 0 0 10px;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
}
.event-item__description {
display: none;
margin-top: 15px;
}
.event-item.active .event-item__description {
display: block;
}
.event-item__icon {
font-size: 24px;
line-height: 1;
transition: transform .3s ease;
}
.event-item.active .event-item__icon {
transform: rotate(45deg);
}
.event-link {
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 5px;
color: #2f419b;
}
.event-link:hover {
color: #fc3125;
}
.event-month-nav {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 40px;
position: sticky;
top: 0;
z-index: 10;
background: #eff0f5;
padding: 15px 0;
}
.event-month-nav__link {
padding: 8px 16px;
border-radius: 30px;
text-decoration: none;
background: #fc3125;
color: #fff;
}
.event-month-nav__link:hover {
transform: translateY(-1px);
}
.align-center {
display: flex;
align-items: center;
gap: 5px;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', async function() {
const apiUrl = '{{ section.settings.api_url }}';
try {
const response = await fetch(apiUrl);
const events = await response.json();
const eventList = document.getElementById('event-list');
const monthNav = document.getElementById('event-month-nav');
const grouped = {};
events.forEach(function(event){
const date = new Date(event.start_date);
const month = date.toLocaleString('en-US', {
month: 'long',
year: 'numeric'
});
if (!grouped[month]) {
grouped[month] = [];
}
grouped[month].push(event);
});
Object.keys(grouped).forEach(function(month){
const monthId = month.toLowerCase().replace(/\s+/g, '-');
monthNav.insertAdjacentHTML(
'beforeend',
'<a href="#' + monthId + '" class="event-month-nav__link">' + month + '</a>'
);
let html = '';
html += '<div id="' + monthId + '" class="event-month">';
html += '<h2 class="event-month__title">' + month + '</h2>';
grouped[month].forEach(function(event){
const formattedDate = new Date(
event.start_date
).toLocaleDateString('en-US',{
month:'long',
day:'numeric',
year:'numeric'
});
html += `
<div class="event-item">
<h3 class="event-item__title js-event-toggle">
${event.title}
<span class="event-item__icon">+</span>
</h3>
<div class="event-item__header">
<div class="event-item__date align-center">
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
<path d="M19 4h-1V2h-2v2H8V2H6v2H5a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 15H5V9h14z"/>
</svg>
${formattedDate}
</div>
<div class="event-item__location align-center">
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5A2.5 2.5 0 1 1 12 6.5a2.5 2.5 0 0 1 0 5z"/>
</svg>
${event.location}
</div>
<div class="event-item__source align-center">
<a href="${event.source_url}" target="_blank" class="event-link">
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
<path d="M14 3h7v7h-2V6.41l-9.29 9.3-1.42-1.42 9.3-9.29H14V3z"></path>
<path d="M5 5h6v2H7v10h10v-4h2v6H5V5z"></path>
</svg>
Source
</a>
</div>
</div>
<div class="event-item__description">
${event.description}
</div>
</div>`;
});
html += '</div>';
eventList.insertAdjacentHTML(
'beforeend',
html
);
});
document.addEventListener('click', function(e){
const title = e.target.closest('.js-event-toggle');
if (!title) {
return;
}
const item = title.closest('.event-item');
const isOpen = item.classList.contains('active');
document.querySelectorAll('.event-item.active').forEach(function(el){
el.classList.remove('active');
});
if (!isOpen) {
item.classList.add('active');
}
});
} catch(error) {
console.error('Event API Error', error);
}
});
</script>
{% schema %}
{
"name": "Event Listing API",
"settings": [
{
"type": "text",
"id": "wrapper_id",
"label": "Wrapper ID"
},
{
"type": "text",
"id": "wrapper_class",
"label": "Wrapper Class"
},
{
"type": "text",
"id": "api_url",
"label": "Events API URL",
"default": "https://yourdomain.com/wp-json/vw-events/v1/events"
}
],
"presets": [
{
"name": "Event Listing API"
}
]
}
{% endschema %}
Jagdish Sarma Asked question 2 minutes ago