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:
54
src/_data/eventsJson.js
Normal file
54
src/_data/eventsJson.js
Normal file
@@ -0,0 +1,54 @@
|
||||
module.exports = { normalizedEvents: [
|
||||
{
|
||||
"calid": "3521964000000010003",
|
||||
"title": "Gardening 101 with Bethany Bloom",
|
||||
"uid": "6788b6fe00ef48d18749a55366207c76@zoho.com",
|
||||
"start": "20250909T183000-0500",
|
||||
"end": "20250909T203000-0500",
|
||||
"isallday": false,
|
||||
"location": "Bloom Valley Nursery",
|
||||
"displayDate": "Tuesday, September 9, 2025 • 6:30 PM – 8:30 PM",
|
||||
"color": "#FC6060",
|
||||
"description": "Join Bethany Bloom as she shares her tips for creating a themed decor through-out the home that you will be delighted to share with your guests!\n\n\n\n**This is a demo event for demonstration purposes only.**\n\n",
|
||||
"category": "workshop"
|
||||
},
|
||||
{
|
||||
"calid": "3521964000000010003",
|
||||
"title": "Labor Day Sale",
|
||||
"uid": "1ae512d837304fcc91c8920aa90a1f44@zoho.com",
|
||||
"start": "20250901",
|
||||
"end": "20250902",
|
||||
"isallday": true,
|
||||
"location": "Bloom Valley Nursery",
|
||||
"displayDate": "Monday, September 1, 2025",
|
||||
"color": "#7CAA56",
|
||||
"description": "Celebrate Labor Day with Bloom Valley Nursery! Enjoy special discounts on select plants, gardening tools, and seasonal decor. This one-day event is a perfect opportunity to stock up on everything you need to make your home and garden thrive. \n\n**This is a demo event for demonstration purposes only—no actual sales will take place.**\n\n",
|
||||
"category": "sales"
|
||||
},
|
||||
{
|
||||
"calid": "3521964000000010003",
|
||||
"title": "Landscaping 101 with Vincent Bloom",
|
||||
"uid": "60085fc27f5045a5bf462c38c02677b0@zoho.com",
|
||||
"start": "20250916T183000-0500",
|
||||
"end": "20250916T203000-0500",
|
||||
"isallday": false,
|
||||
"location": "Bloom Valley Nursery",
|
||||
"displayDate": "Tuesday, September 16, 2025 • 6:30 PM – 8:30 PM",
|
||||
"color": "#FC6060",
|
||||
"description": "Come learn from Vincent Bloom, one of Bloom Valley Nursery's family owners, as he guides you through the art and science of landscaping. This workshop is designed for community members who want to create beautiful, sustainable outdoor spaces. We'll explore local plant varieties, discuss eco-friendly landscaping methods, and share tips for a garden that not only looks great but also supports our local ecosystem.\n\n",
|
||||
"category": "workshop"
|
||||
},
|
||||
{
|
||||
"calid": "3521964000000010003",
|
||||
"title": "Johnny Appleseed Day",
|
||||
"uid": "e0394985af2845fd8c1de4b782c139fb@zoho.com",
|
||||
"start": "20250926T173000-0500",
|
||||
"end": "20250926T193000-0500",
|
||||
"isallday": false,
|
||||
"location": "Bloom Valley Nursery",
|
||||
"displayDate": "Friday, September 26, 2025 • 5:30 PM – 7:30 PM",
|
||||
"color": "#FFC464",
|
||||
"description": "Celebrate the legacy of Johnny Appleseed with us! Join our hands-on workshop where you'll get to pick fresh, crisp apples right from our orchard and then learn how to properly plant your very own apple tree sapling. Our expert growers will share tips on nurturing your tree so it can thrive for years to come. This is a wonderful, educational event for the whole family to connect with nature and grow something beautiful.\n\n",
|
||||
"category": "community"
|
||||
}
|
||||
] };
|
@@ -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) {
|
||||
|
@@ -13,6 +13,7 @@ stylesheet:
|
||||
fontAwesome: "https://kit.fontawesome.com/c42448086d.js"
|
||||
currentPage: "community"
|
||||
pageScripts:
|
||||
- "/scripts/events-carousel.js"
|
||||
- "/scripts/cart.js"
|
||||
- "/scripts/newsletter.js"
|
||||
---
|
||||
@@ -20,25 +21,50 @@ pageScripts:
|
||||
<h1>Mark Your Calendars!</h1>
|
||||
<div id="calendar-events-container">
|
||||
<section class="events" aria-label="List of upcoming local events">
|
||||
|
||||
<div class="upcoming-events">
|
||||
<h2>Upcoming Events</h2>
|
||||
{% for event in zohoCalendarEvents %}
|
||||
<div id="{{ event.uid }}" class="zoho-event">
|
||||
{% if event.title %}
|
||||
<h3 class="title">{{ event.title }}</h3>
|
||||
{% endif %}
|
||||
<p class="display-date">{{ event.displayDate }}</p>
|
||||
{% if event.location %}
|
||||
<p class="location">Location: {{ event.location }}</p>
|
||||
{% endif %}
|
||||
{% if event.description %}
|
||||
<p class="description">{{ event.description }}</p>
|
||||
{% endif %}
|
||||
<div id="events-navigation">
|
||||
<ul class="event-categories">
|
||||
<li class="workshops-btn enav"><a href="/community/?category=workshop#" class="cat-btn">Workshops</a></li>
|
||||
<li class="celebrations-btn enav"><a href="/community/?category=community#" class="cat-btn ">Community Celebrations</a></li>
|
||||
<li class="sales-btn enav"><a href="/community/?category=sales#" class="cat-btn">Plant Sales</a></li>
|
||||
<li class="all-btn enav"><a href="/community/?category=all#" class="cat-btn">All Events</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="interactive-events">
|
||||
<div class="events-left">
|
||||
<div class="calendar">
|
||||
<iframe src="https://calendar.zoho.com/zc/ui/embed/#calendar=zz0801123006fa33fd29e1610f845b1a39bac3a52e92215b45d6a6f982e3a69c351d4e7b0be038133d1988f6ed212d5f2bd86e7bef&title=Bloom%20Valley%20Nursery&type=1&language=en&timezone=America%2FChicago&showTitle=1&showTimezone=1&startingDayOfWeek=0&timeFormat=0&view=month&showDetail=1&theme=1&showAttendee=0&showSwitchingViews=0&expandAllday=0&eventColorType=light&showAllEvents=0" title="Bloom Valley Nursery"width=650 height=500 frameBorder="0" scrolling="no"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="events-right">
|
||||
<div class="scroll-direction">
|
||||
<button
|
||||
id="scroll-up"
|
||||
aria-label="Scroll events up"
|
||||
aria-controls="event-carousel"
|
||||
class="fa-solid fa-chevron-up"
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
<div id="event-list">
|
||||
<!-- Event List will be populated here -->
|
||||
</div>
|
||||
<div class="scroll-direction">
|
||||
<button
|
||||
id="scroll-down"
|
||||
aria-label="Scroll events down"
|
||||
aria-controls="event-carousel"
|
||||
class="fa-solid fa-chevron-down"
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="calendar">
|
||||
<iframe src="https://calendar.zoho.com/zc/ui/embed/#calendar=zz0801123006fa33fd29e1610f845b1a39bac3a52e92215b45d6a6f982e3a69c351d4e7b0be038133d1988f6ed212d5f2bd86e7bef&title=Bloom%20Valley%20Nursery&type=1&language=en&timezone=America%2FChicago&showTitle=1&showTimezone=1&startingDayOfWeek=0&timeFormat=0&view=month&showDetail=1&theme=1&showAttendee=0&showSwitchingViews=0&expandAllday=0&eventColorType=light&showAllEvents=0" title="Bloom Valley Nursery"width=650 height=500 frameBorder="0" scrolling="no"></iframe>
|
||||
</div>
|
||||
</section>
|
||||
<div class="add-events">
|
||||
|
4
src/events.json.njk
Normal file
4
src/events.json.njk
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
permalink: /data/events.json
|
||||
---
|
||||
{{ eventsJson.normalizedEvents | dump | safe}}
|
201
src/scripts/events-carousel.js
Normal file
201
src/scripts/events-carousel.js
Normal file
@@ -0,0 +1,201 @@
|
||||
// events-carousel.js
|
||||
|
||||
// --- State Variables ---
|
||||
let allEvents = [];
|
||||
let selectedEvents = [];
|
||||
let currentIndex = 0;
|
||||
|
||||
// --- Helpers ---
|
||||
const parseZohoTimestamp = (raw) => {
|
||||
if (!raw && raw !== 0) return new Date(0);
|
||||
const s = String(raw).trim();
|
||||
|
||||
let m = s.match(/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})([+-]\d{4}|Z)?$/i);
|
||||
if (m) {
|
||||
const [, Y, Mo, D, hh, mm, ss, tz] = m;
|
||||
let tzPart = '';
|
||||
if (tz && tz.toUpperCase() !== 'Z') tzPart = tz.slice(0,3) + ':' + tz.slice(3);
|
||||
else if (tz && tz.toUpperCase() === 'Z') tzPart = 'Z';
|
||||
const iso = `${Y}-${Mo}-${D}T${hh}:${mm}:${ss}${tzPart}`;
|
||||
const d = new Date(iso);
|
||||
if (!isNaN(d)) return d;
|
||||
}
|
||||
|
||||
m = s.match(/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})([+-]\d{4}|Z)?$/i);
|
||||
if (m) {
|
||||
const [, Y, Mo, D, hh, mm, tz] = m;
|
||||
let tzPart = '';
|
||||
if (tz && tz.toUpperCase() !== 'Z') tzPart = tz.slice(0,3) + ':' + tz.slice(3);
|
||||
else if (tz && tz.toUpperCase() === 'Z') tzPart = 'Z';
|
||||
const iso = `${Y}-${Mo}-${D}T${hh}:${mm}:00${tzPart}`;
|
||||
const d = new Date(iso);
|
||||
if (!isNaN(d)) return d;
|
||||
}
|
||||
|
||||
m = s.match(/^(\d{4})(\d{2})(\d{2})$/);
|
||||
if (m) {
|
||||
const [, Y, Mo, D] = m;
|
||||
return new Date(Number(Y), Number(Mo) - 1, Number(D));
|
||||
}
|
||||
|
||||
const tryDate = new Date(s);
|
||||
if (!isNaN(tryDate)) return tryDate;
|
||||
|
||||
const mmdd = s.match(/^(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2,4})$/);
|
||||
if (mmdd) {
|
||||
let month = parseInt(mmdd[1], 10);
|
||||
let day = parseInt(mmdd[2], 10);
|
||||
let year = parseInt(mmdd[3], 10);
|
||||
if (year < 100) year += 2000;
|
||||
return new Date(year, month - 1, day);
|
||||
}
|
||||
|
||||
return new Date(0);
|
||||
};
|
||||
|
||||
const eventTimestamp = (ev) => {
|
||||
if (!ev) return 0;
|
||||
const candidate = ev.start || ev.displayDate || ev.date || ev.eventDate || ev.createdAt || ev.created;
|
||||
return parseZohoTimestamp(candidate).getTime();
|
||||
};
|
||||
|
||||
// --- Render the visible items ---
|
||||
const renderEvents = () => {
|
||||
const eventList = document.getElementById("event-list");
|
||||
if (!eventList) return;
|
||||
eventList.innerHTML = "";
|
||||
|
||||
if (selectedEvents.length === 0) {
|
||||
eventList.innerHTML = `<p class="no-events-message">No events found for this category.</p>`;
|
||||
return;
|
||||
}
|
||||
|
||||
const lastIndex = selectedEvents.length - 1;
|
||||
let visibleIndexes = [];
|
||||
|
||||
if (selectedEvents.length <= 3) {
|
||||
visibleIndexes = Array.from({ length: selectedEvents.length }, (_, i) => i);
|
||||
} else if (currentIndex === 0) {
|
||||
visibleIndexes = [0, 1, 2];
|
||||
} else if (currentIndex === lastIndex) {
|
||||
visibleIndexes = [lastIndex - 2, lastIndex - 1, lastIndex];
|
||||
} else {
|
||||
visibleIndexes = [currentIndex - 1, currentIndex, currentIndex + 1];
|
||||
}
|
||||
|
||||
visibleIndexes = visibleIndexes.filter(i => i >= 0 && i <= lastIndex);
|
||||
|
||||
visibleIndexes.forEach((index) => {
|
||||
const event = selectedEvents[index];
|
||||
if (!event) return;
|
||||
|
||||
const card = document.createElement("div");
|
||||
card.className = "event-card";
|
||||
|
||||
card.addEventListener('click', () => {
|
||||
if (index !== currentIndex) {
|
||||
currentIndex = index;
|
||||
renderEvents();
|
||||
}
|
||||
});
|
||||
|
||||
if (index === currentIndex) {
|
||||
card.classList.add("is-expanded");
|
||||
card.innerHTML = `
|
||||
<h3 class="event-title ${event.category}">${event.title || ''}</h3>
|
||||
<p class="event-date">${event.displayDate || event.start || ''}</p>
|
||||
<p class="event-location">${event.location ? `Location: ${event.location}` : ''}</p>
|
||||
<p class="event-description">${event.description ? event.description : ''}</p>
|
||||
`;
|
||||
} else {
|
||||
card.classList.add("is-collapsed");
|
||||
card.innerHTML = `
|
||||
<h3 class="event-title ${event.category}">${event.title || ''}</h3>
|
||||
<p class="event-date">${event.displayDate || event.start || ''}</p>
|
||||
`;
|
||||
card.style.cursor = 'pointer';
|
||||
}
|
||||
|
||||
eventList.appendChild(card);
|
||||
});
|
||||
};
|
||||
|
||||
// --- Navigation Functions ---
|
||||
const scrollUp = () => {
|
||||
if (currentIndex > 0) {
|
||||
currentIndex--;
|
||||
renderEvents();
|
||||
}
|
||||
};
|
||||
|
||||
const scrollDown = () => {
|
||||
if (currentIndex < selectedEvents.length - 1) {
|
||||
currentIndex++;
|
||||
renderEvents();
|
||||
}
|
||||
};
|
||||
|
||||
// --- Category Update and Filtering ---
|
||||
const updateEventList = (category) => {
|
||||
const scrollUpButton = document.getElementById('scroll-up');
|
||||
const scrollDownButton = document.getElementById('scroll-down');
|
||||
if (scrollUpButton) scrollUpButton.removeEventListener('click', scrollUp);
|
||||
if (scrollDownButton) scrollDownButton.removeEventListener('click', scrollDown);
|
||||
|
||||
if (category === 'all') {
|
||||
selectedEvents = allEvents.slice();
|
||||
} else {
|
||||
selectedEvents = allEvents.filter(event => event.category === category);
|
||||
}
|
||||
|
||||
selectedEvents.sort((a, b) => eventTimestamp(a) - eventTimestamp(b));
|
||||
|
||||
currentIndex = 0;
|
||||
renderEvents();
|
||||
|
||||
if (scrollUpButton) scrollUpButton.addEventListener('click', scrollUp);
|
||||
if (scrollDownButton) scrollDownButton.addEventListener('click', scrollDown);
|
||||
};
|
||||
|
||||
// --- Initialization ---
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
fetch("../data/events.json")
|
||||
.then(response => {
|
||||
if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
allEvents = Array.isArray(data) ? data : (data.normalizedEvents || []);
|
||||
console.log("Events data loaded successfully:", allEvents);
|
||||
|
||||
const categoryButtons = document.querySelectorAll(".cat-btn");
|
||||
categoryButtons.forEach(button => {
|
||||
button.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
// --- Active button logic ---
|
||||
categoryButtons.forEach(btn => btn.parentElement.classList.remove('active'));
|
||||
button.parentElement.classList.add('active');
|
||||
|
||||
const url = new URL(button.href);
|
||||
const category = url.searchParams.get('category');
|
||||
updateEventList(category);
|
||||
});
|
||||
});
|
||||
|
||||
// Set default category and active button
|
||||
const currentUrl = new URL(window.location.href);
|
||||
const defaultCategory = currentUrl.searchParams.get('category') || 'all';
|
||||
updateEventList(defaultCategory);
|
||||
categoryButtons.forEach(btn => {
|
||||
const url = new URL(btn.href);
|
||||
const btnCategory = url.searchParams.get('category');
|
||||
if (btnCategory === defaultCategory) btn.parentElement.classList.add('active');
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Problem fetching events data:', error);
|
||||
const eventList = document.getElementById("event-list");
|
||||
if (eventList) eventList.innerHTML = `<p class="error-message">Failed to load events. Please try again later.</p>`;
|
||||
});
|
||||
});
|
@@ -2,9 +2,10 @@
|
||||
.community {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
max-width: 900px;
|
||||
max-width: 1000px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@@ -27,9 +28,106 @@ h1 {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.upcoming-events {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 25px;
|
||||
}
|
||||
|
||||
#events-navigation {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
}
|
||||
|
||||
ul.event-categories {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
list-style-type: none;
|
||||
gap: 50px;
|
||||
margin: 10px auto;
|
||||
}
|
||||
|
||||
li.enav {
|
||||
display: flex;
|
||||
width: auto;
|
||||
margin: 0;
|
||||
border: solid 1px var(--color-dark-green);
|
||||
background-color: var(--color-destin-sand);
|
||||
border-radius: 10px;
|
||||
white-space: nowrap;
|
||||
box-shadow: var(--shadow-medium);
|
||||
transition: background-color 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
.cat-btn {
|
||||
display: block;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
padding: 2px 50px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: var(--color-dark-green);
|
||||
font-size: 1.4rem;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.sales-btn:hover {
|
||||
background-color: rgba(124, 170, 86, 0.5); /*#7CAA56*/
|
||||
}
|
||||
|
||||
.celebrations-btn:hover {
|
||||
background: rgba(255, 196, 100, 0.5); /*#FFC464*/
|
||||
}
|
||||
|
||||
.workshops-btn:hover {
|
||||
background: rgba(252, 96, 96, 0.5); /*#FC6060*/
|
||||
}
|
||||
|
||||
.all-btn:hover {
|
||||
background: var(--color-light-teal);
|
||||
}
|
||||
|
||||
/* --- Active button states --- */
|
||||
.event-categories li.enav.active {}
|
||||
.workshops-btn.active {
|
||||
background-color: rgba(252, 96, 96, 0.5);
|
||||
}
|
||||
.celebrations-btn.active {
|
||||
background-color: rgba(255, 196, 100, 0.5);
|
||||
}
|
||||
.sales-btn.active {
|
||||
background-color: rgba(124, 170, 86, 0.5);
|
||||
}
|
||||
.all-btn.active {
|
||||
background-color: var(--color-light-teal);
|
||||
}
|
||||
|
||||
.interactive-events {
|
||||
display:flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.events-left {
|
||||
width: 50%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.calendar iframe {
|
||||
width: 975px;
|
||||
height: 750px;
|
||||
width: 600px;
|
||||
height: 550px;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 20px;
|
||||
background-color: var(--color-light-teal);
|
||||
@@ -37,26 +135,56 @@ h1 {
|
||||
box-shadow: var(--shadow-subtle);
|
||||
}
|
||||
|
||||
.upcoming-events {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 25px;
|
||||
.events-right {
|
||||
width: 50%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.events {
|
||||
.scroll-direction {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
#scroll-up, #scroll-down {
|
||||
cursor: pointer;
|
||||
background-color: var(--color-dark-green);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
border-radius: 50%;
|
||||
font-size: 1.5rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#event-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
width: auto;
|
||||
height: 450px;
|
||||
overflow-y: hidden;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.event-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
background-color: var(--color-soft-golden);
|
||||
background-color: var(--color-destin-sand);
|
||||
border: solid var(--color-dark-green);
|
||||
border-radius: 15px;
|
||||
padding: 10px;
|
||||
width: 80vw;
|
||||
width: 600px;
|
||||
box-shadow: var(--shadow-subtle);
|
||||
}
|
||||
|
||||
.events h2 {
|
||||
.upcoming-events h2 {
|
||||
font-size: 1.875rem;
|
||||
text-align: center;
|
||||
text-shadow: 0.5px 0.5px .5px var(--color-dark-green),
|
||||
@@ -67,6 +195,8 @@ h1 {
|
||||
background-color: var(--color-mid-green);
|
||||
border: solid var(--color-destin-sand);
|
||||
border-radius: 10px;
|
||||
margin-top: 20px;
|
||||
margin-botom: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: fit-content;
|
||||
@@ -88,65 +218,37 @@ h1 {
|
||||
box-shadow: var(--shadow-subtle);
|
||||
}
|
||||
|
||||
.zoho-event {
|
||||
background-color: var(--color-destin-sand);
|
||||
border: solid var(--color-dark-green) 2px;
|
||||
border-radius: 15px;
|
||||
box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.8);
|
||||
max-width: 1200px;
|
||||
.event-card h3,
|
||||
.event-card p {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.zoho-event h3 {
|
||||
font-size: 1.875rem;
|
||||
text-align: center;
|
||||
text-shadow: 0.5px 0.5px .5px var(--color-destin-sand),
|
||||
-0.5px -0.5px .5px var(--color-destin-sand),
|
||||
-0.5px 0.5px .5px var(--color-destin-sand),
|
||||
0.5px -0.5px .5px var(--color-destin-sand);
|
||||
color: var(--color-dark-green);
|
||||
background-color: var(--color-light-teal);
|
||||
border: solid var(--color-destin-sand);
|
||||
.event-card h3 {
|
||||
border: solid 0.5px var(--color-dark-green);
|
||||
border-radius: 10px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: fit-content;
|
||||
padding: 0 50px;
|
||||
box-shadow: var(--shadow-medium);
|
||||
padding: 2px 20px;
|
||||
}
|
||||
|
||||
.zoho-event p {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
.event-card h3.workshop {
|
||||
background-color: rgba(252, 96, 96, 0.5);
|
||||
}
|
||||
|
||||
.display-date, .location, .add-events {
|
||||
font-weight: heavy;
|
||||
font-size: 1.5rem;
|
||||
.event-card h3.community {
|
||||
background-color: rgba(255, 196, 100, 0.5);
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 1.3rem;
|
||||
width: 80%;
|
||||
height: auto;
|
||||
.event-card h3.sales {
|
||||
background-color: rgba(124, 170, 86, 0.5);
|
||||
}
|
||||
|
||||
.event-list ul {
|
||||
list-style-type: none;
|
||||
.event-card.is-collapsed:hover {
|
||||
cursor: pointer;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.event-list li {
|
||||
background-color: var(--color-destin-sand);
|
||||
border: solid var(--color-light-teal);
|
||||
border-radius: 15px;
|
||||
text-align: center;
|
||||
padding: 5px 10px;
|
||||
margin-bottom: 10px;
|
||||
box-shadow: var(--shadow-subtle);
|
||||
}
|
||||
|
||||
.events strong {
|
||||
color: var(--color-dark-green);
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
/* | ↑-↑-↑ End Community.html ↑-↑-↑--| */
|
||||
.add-events p {
|
||||
font-size: 1.2rem;
|
||||
}
|
Reference in New Issue
Block a user