improve(events): show 6 upcoming events with type filter and color coding
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions

Display 6 events instead of 4 on homepage. Add filter buttons (All/Norda/External)
and green gradient for external events with source badge.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maciej Pienczyn 2026-03-20 10:41:33 +01:00
parent 4ac39471f6
commit a8f5dfa4ab
2 changed files with 78 additions and 2 deletions

View File

@ -123,7 +123,7 @@ def index():
'user_registered': registered,
'user_can_attend': can_attend,
})
if len(upcoming_events) >= 4:
if len(upcoming_events) >= 6:
break
# Backward compat — next_event used by other parts

View File

@ -140,6 +140,59 @@
background: #15803d;
}
/* Events filter buttons */
.events-filter {
display: flex;
align-items: center;
gap: var(--spacing-sm);
margin-bottom: var(--spacing-md);
}
.events-filter-label {
font-size: var(--font-size-sm);
color: var(--text-muted);
font-weight: 500;
}
.events-filter-btn {
padding: var(--spacing-xs) var(--spacing-md);
border-radius: var(--radius-btn);
border: 1.5px solid #cbd5e1;
background: white;
color: var(--text-secondary);
font-size: var(--font-size-sm);
font-weight: 500;
cursor: pointer;
transition: var(--transition);
}
.events-filter-btn:hover {
border-color: var(--primary);
color: var(--primary);
}
.events-filter-btn.active {
background: var(--primary);
color: white;
border-color: var(--primary);
}
.event-banner[data-event-type="external"] {
background: linear-gradient(135deg, #1a3a2a 0%, #2d5a3e 100%);
}
.event-banner[data-event-type="external"]:hover {
box-shadow: 0 10px 30px rgba(45, 90, 62, 0.25);
}
.event-banner[data-event-type="external"] .btn-light {
color: #2d5a3e;
}
.event-banner.hidden-by-filter {
display: none;
}
@media (max-width: 768px) {
.events-row {
grid-template-columns: 1fr;
@ -947,10 +1000,16 @@
<!-- Event Banners - Najbliższe wydarzenia -->
{% if upcoming_events %}
<div class="events-filter" data-animate="fadeIn">
<span class="events-filter-label">Pokaż:</span>
<button class="events-filter-btn active" data-filter="all" onclick="filterEvents('all', this)">Wszystkie</button>
<button class="events-filter-btn" data-filter="norda" onclick="filterEvents('norda', this)">🏢 Norda Biznes</button>
<button class="events-filter-btn" data-filter="external" onclick="filterEvents('external', this)">🌐 Zewnętrzne</button>
</div>
<div class="events-row" data-animate="fadeIn">
{% for ue in upcoming_events %}
{% set ev = ue.event %}
<a href="{{ url_for('calendar.calendar_event', event_id=ev.id) }}" class="event-banner">
<a href="{{ url_for('calendar.calendar_event', event_id=ev.id) }}" class="event-banner" data-event-type="{{ 'external' if ev.is_external else 'norda' }}">
<div class="event-banner-top">
<div class="event-banner-icon">📅</div>
<div class="event-banner-content">
@ -959,6 +1018,9 @@
{% endif %}
<div class="event-banner-title">
{{ ev.title }} →
{% if ev.is_external and ev.external_source %}
<span style="display:inline-block; background:rgba(255,255,255,0.2); color:#fff; font-size:10px; padding:2px 6px; border-radius:4px; font-weight:600; vertical-align:middle; margin-left:6px;">🌐 {{ ev.external_source }}</span>
{% endif %}
{% if ev.access_level == 'admin_only' %}
<span style="display:inline-block; background:#ef4444; color:#fff; font-size:10px; padding:2px 6px; border-radius:4px; font-weight:600; vertical-align:middle; margin-left:6px;">UKRYTE</span>
{% elif ev.access_level == 'rada_only' %}
@ -1259,6 +1321,20 @@
{% endblock %}
{% block extra_js %}
// Filter events by type
function filterEvents(type, btn) {
document.querySelectorAll('.events-filter-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('.event-banner').forEach(banner => {
if (type === 'all' || banner.dataset.eventType === type) {
banner.classList.remove('hidden-by-filter');
} else {
banner.classList.add('hidden-by-filter');
}
});
}
// RSVP and redirect to event
async function rsvpAndGo(e, eventId) {
e.preventDefault();