Enhance event overview layout and styling; update event date and improve participant name handling. Pop-Up that Events are free. Explenation for Event Adresse.
This commit is contained in:
parent
21d96597cc
commit
7ecc2cf91a
@ -21,6 +21,17 @@
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.overview-title-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
.overview-title-row .overview-title {
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
@ -122,6 +133,7 @@
|
||||
|
||||
.meta-filter select {
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='currentColor' stroke-width='1.5' fill='none' stroke-linecap='butt' stroke-linejoin='miter'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
@ -752,6 +764,13 @@
|
||||
font-size: 34px;
|
||||
}
|
||||
|
||||
.overview-info-button {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
flex-basis: 44px;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.top-nav-links {
|
||||
gap: 8px;
|
||||
}
|
||||
@ -878,6 +897,19 @@
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.overview-title-row {
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.overview-info-button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
flex-basis: 40px;
|
||||
font-size: 1.35rem;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.top-nav-links {
|
||||
width: auto;
|
||||
justify-content: flex-end;
|
||||
|
||||
@ -682,23 +682,82 @@ label {
|
||||
animation: modalSlideIn 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-info {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
flex: 0 0 48px;
|
||||
border: 1.5px solid var(--olive);
|
||||
border-radius: 999px;
|
||||
background: var(--butter-light);
|
||||
color: var(--olive);
|
||||
font-family: "Bagel Fat One", cursive;
|
||||
font-size: 1.7rem;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
box-shadow: var(--shadow-interaction);
|
||||
transition: background-color 0.2s ease, transform 0.2s ease, border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-info:hover,
|
||||
.btn-info:focus-visible {
|
||||
background: var(--butter);
|
||||
border-color: var(--olive-dark);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn-info:focus-visible {
|
||||
outline: 2px solid var(--olive-dark);
|
||||
}
|
||||
|
||||
@keyframes modalSlideIn {
|
||||
from { transform: translateY(-50px); opacity: 0; }
|
||||
to { transform: translateY(0); opacity: 1; }
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
.modal-header h2 {
|
||||
padding: var(--space-20)var(--space-20) 0 var(--space-20);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
flex: 0 0 32px;
|
||||
margin-left: auto;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--olive);
|
||||
font-size: 2rem;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
transition: color 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.modal-close:hover,
|
||||
.modal-close:focus-visible {
|
||||
color: var(--olive-dark);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.modal-close:focus-visible {
|
||||
outline: 2px solid var(--olive-dark);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
font-size: 28px;
|
||||
color: var(--black);
|
||||
background: none;
|
||||
@ -712,7 +771,9 @@ label {
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: var(--space-20) var(--space-20) var(--space-4) var(--space-20);
|
||||
padding: var(--space-4) 0 0;
|
||||
text-align: left;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
"title": "Italienische Tavolata",
|
||||
"location": "Luzern",
|
||||
"address": "Pilatusstrasse 18, 6003 Luzern",
|
||||
"date": "22. APR. 2026",
|
||||
"date": "23. APR. 2026",
|
||||
"time": "15:30 UHR",
|
||||
"category": "Dinner",
|
||||
"diet": "Vegetarisch",
|
||||
|
||||
@ -30,7 +30,10 @@
|
||||
<main class="container layout-wide">
|
||||
<!-- Page headline -->
|
||||
<p class="badge margin-bottom-40">Event finden</p>
|
||||
<h1>Was darf es sein?</h1>
|
||||
<div class="overview-title-row">
|
||||
<h1 class="overview-title">Was darf es sein?</h1>
|
||||
<button type="button" id="info-button" class="btn-info" aria-label="Informationen zu kostenlosen Events">?</button>
|
||||
</div>
|
||||
|
||||
<!-- Filter section: category chips + location/date filters -->
|
||||
<section class="filter-section">
|
||||
|
||||
@ -68,8 +68,9 @@
|
||||
|
||||
const firstName = String(user.vorname || '').trim();
|
||||
const lastName = String(user.nachname || '').trim();
|
||||
const fullName = `${firstName} ${lastName}`.trim();
|
||||
|
||||
return (firstName || `${firstName} ${lastName}`.trim() || String(user.email || '').trim()).trim();
|
||||
return (fullName || firstName || String(user.email || '').trim()).trim();
|
||||
}
|
||||
|
||||
function getResolvedParticipants(event, registrationMap) {
|
||||
@ -102,6 +103,24 @@
|
||||
return baseParticipants;
|
||||
}
|
||||
|
||||
function getParticipantNameForViewer(name, canSeeLastName) {
|
||||
const rawName = String(name || '').trim();
|
||||
if (!rawName) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (canSeeLastName) {
|
||||
return rawName;
|
||||
}
|
||||
|
||||
// Bei E-Mail-Fallback nur den lokalen Teil anzeigen.
|
||||
if (rawName.includes('@')) {
|
||||
return rawName.split('@')[0].trim() || rawName;
|
||||
}
|
||||
|
||||
return rawName.split(/\s+/)[0];
|
||||
}
|
||||
|
||||
function setRegistrationMap(registrationMap) {
|
||||
localStorage.setItem(REGISTRATION_STORAGE_KEY, JSON.stringify(registrationMap));
|
||||
}
|
||||
@ -337,6 +356,10 @@
|
||||
: [];
|
||||
const registrationMap = getRegistrationMap();
|
||||
const participants = getResolvedParticipants(event, registrationMap);
|
||||
const isOwnEvent = isEventOwnedByCurrentUser(event, currentUser);
|
||||
const participantNamesForView = participants
|
||||
.map(name => getParticipantNameForViewer(name, isOwnEvent))
|
||||
.filter(Boolean);
|
||||
const galleryImages = Array.isArray(event.gallery)
|
||||
? event.gallery.filter(Boolean)
|
||||
: [];
|
||||
@ -351,14 +374,13 @@
|
||||
</div>
|
||||
`
|
||||
: '';
|
||||
const visibleParticipants = participants.slice(0, 6);
|
||||
const remainingParticipants = Math.max(0, participants.length - visibleParticipants.length);
|
||||
const visibleParticipants = participantNamesForView.slice(0, 6);
|
||||
const remainingParticipants = Math.max(0, participantNamesForView.length - visibleParticipants.length);
|
||||
const totalGuests = Number.isFinite(event.spots) ? event.spots : 0;
|
||||
const confirmedGuests = participants.length;
|
||||
const freePlaces = Math.max(0, totalGuests - confirmedGuests);
|
||||
const isFull = freePlaces === 0;
|
||||
const isRegistrationClosed = isRegistrationClosedForEvent(event);
|
||||
const isOwnEvent = isEventOwnedByCurrentUser(event, currentUser);
|
||||
const deregInfo = getDeregistrationInfo(event);
|
||||
const userRegistrations = currentUser?.email && Array.isArray(registrationMap[currentUser.email])
|
||||
? registrationMap[currentUser.email].map(id => Number(id))
|
||||
@ -456,7 +478,7 @@
|
||||
${remainingParticipants > 0 ? `<span class="participant-more">+${remainingParticipants}</span>` : ''}
|
||||
</div>
|
||||
<div class="detail-participants-full hidden" data-participants-full>
|
||||
${participants.map(name => `
|
||||
${participantNamesForView.map(name => `
|
||||
<div class="detail-participant-item">
|
||||
<span class="participant-name">${name}</span>
|
||||
</div>
|
||||
|
||||
@ -36,6 +36,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
function getInfoModalShownKeyForUser(user) {
|
||||
const email = String(user?.email || '').trim().toLowerCase();
|
||||
return email ? `${INFO_MODAL_SHOWN_KEY}:${email}` : INFO_MODAL_SHOWN_KEY;
|
||||
}
|
||||
|
||||
// Prüft, ob ein Event dem aktuellen Benutzer gehört.
|
||||
function isEventOwnedByCurrentUser(event, user) {
|
||||
if (!event || !user) {
|
||||
@ -91,8 +96,9 @@
|
||||
|
||||
const firstName = String(user.vorname || '').trim();
|
||||
const lastName = String(user.nachname || '').trim();
|
||||
const fullName = `${firstName} ${lastName}`.trim();
|
||||
|
||||
return (firstName || `${firstName} ${lastName}`.trim() || String(user.email || '').trim()).trim();
|
||||
return (fullName || firstName || String(user.email || '').trim()).trim();
|
||||
}
|
||||
|
||||
function getResolvedParticipants(event, registrationMap) {
|
||||
@ -640,10 +646,11 @@
|
||||
|
||||
// Auto-open info modal on first login
|
||||
if (currentUser && infoModal) {
|
||||
const hasShownInfoModal = localStorage.getItem(INFO_MODAL_SHOWN_KEY);
|
||||
const userInfoModalKey = getInfoModalShownKeyForUser(currentUser);
|
||||
const hasShownInfoModal = localStorage.getItem(userInfoModalKey);
|
||||
if (!hasShownInfoModal) {
|
||||
infoModal.classList.add('show');
|
||||
localStorage.setItem(INFO_MODAL_SHOWN_KEY, 'true');
|
||||
localStorage.setItem(userInfoModalKey, 'true');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -515,13 +515,20 @@
|
||||
const card = document.createElement('article');
|
||||
card.className = 'profile-event-card profile-event-card-clickable';
|
||||
card.setAttribute('data-event-id', String(event.id));
|
||||
const addressMarkup = mode === 'registrations' && event.address && isAddressVisibleWindow(event)
|
||||
? `
|
||||
<div class="profile-event-address-block" aria-label="Event Adresse">
|
||||
<p class="profile-event-address-label">Adresse</p>
|
||||
<p class="profile-event-address">${event.address}</p>
|
||||
</div>
|
||||
`
|
||||
const addressMarkup = mode === 'registrations' && event.address
|
||||
? (isAddressVisibleWindow(event)
|
||||
? `
|
||||
<div class="profile-event-address-block" aria-label="Event Adresse">
|
||||
<p class="profile-event-address-label">Adresse</p>
|
||||
<p class="profile-event-address">${event.address}</p>
|
||||
</div>
|
||||
`
|
||||
: `
|
||||
<div class="profile-event-address-block" aria-label="Hinweis zur Adresse">
|
||||
<p class="profile-event-address-label">Adresse</p>
|
||||
<p class="profile-event-address">Vielen Dank für die Anmeldung! Die Adresse für diesen Event wird 24 Stunden vorher genau hier sichtbar sein.</p>
|
||||
</div>
|
||||
`)
|
||||
: '';
|
||||
|
||||
const actionMarkup = mode === 'registrations'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user