feat: add support for canceled events in event management and UI updatesfor consistancy in buttons

This commit is contained in:
viiivo 2026-04-23 22:04:28 +02:00
parent d46b65aa73
commit 3b65e392fe
5 changed files with 150 additions and 42 deletions

View File

@ -121,5 +121,39 @@
"https://i.pinimg.com/1200x/b1/fb/3a/b1fb3a7809f4046843904ac8800daacc.jpg",
"https://i.pinimg.com/1200x/c6/93/42/c69342ec621333e853c35bda891d8bc6.jpg"
]
},
{
"id": 4,
"title": "Mexican Fiesta",
"location": "Basel",
"address": "Münsterplatz 10, 4051 Basel",
"date": "28. April. 2026",
"time": "18:00 UHR",
"category": "Dinner",
"diet": "Omnivore",
"spots": 6,
"status": "canceled",
"host": {
"name": "Carlos",
"initial": "C"
},
"hostMessage": [
"Hallo zusammen! Leider muss ich dieses Event absagen, da mir etwas Wichtiges dazwischengekommen ist.",
"Ich hoffe, wir können das bald nachholen!"
],
"menu": [
"Guacamole & Nachos",
"Tacos al Pastor",
"Churros"
],
"specifications": [],
"participants": [
"Carlos",
"Vivien",
"Test"
],
"gallery": [
"https://i.pinimg.com/1200x/e2/6a/f5/e26af5c24b805081a3f304d240818302.jpg"
]
}
]

View File

@ -345,29 +345,34 @@
const isRegistered = userRegistrations.includes(Number(event.id));
const isListedParticipant = isUserListedInEventParticipants(event, currentUser);
const hasAddressAccess = isRegistered || isListedParticipant || isOwnEvent;
const isCanceled = event.status === 'canceled';
const actionButtonLabel = isOwnEvent ? 'Dein Event!'
const actionButtonLabel = isCanceled ? 'Abgesagt'
: isOwnEvent ? 'Dein Event!'
: !currentUser ? 'Einloggen'
: isRegistered ? (deregInfo.isClosed ? 'Abmeldung geschlossen' : 'Abmelden')
: isRegistrationClosed ? 'Anmeldung geschlossen'
: 'Anmelden';
const actionButtonDisabled = isOwnEvent
const actionButtonDisabled = isCanceled
|| isOwnEvent
|| (!isRegistered && (isFull || isRegistrationClosed))
|| (isRegistered && deregInfo.isClosed);
const actionButtonVariantClass = isOwnEvent ? ' button-primary-eigener-event'
: isRegistered ? ' button-primary-abmelden '
: (isRegistered || isRegistrationClosed) ? ' button-primary-abmelden '
: ' button-primary ';
const shouldRevealAddress = Boolean(event.address) && isAddressVisibleWindow(event) && hasAddressAccess;
let addressMessage = 'Wenn du dich anmeldest, wird die Adresse für diesen Event wird 24 Stunden vorher genau hier sichtbar sein.';
if (isOwnEvent) {
if (isCanceled) {
addressMessage = 'Dieses Event wurde leider vom Gastgeber abgesagt.';
} else if (isOwnEvent) {
addressMessage = 'Deine Adresse für diesen Event wird 24 Stunden vorher genau hier für alle Teilnehmer sichtbar sein';
} else if (hasAddressAccess) {
addressMessage = 'Vielen Dank für die Anmeldung! Die Adresse für diesen Event wird 24 Stunden vorher genau hier sichtbar sein.';
}
if (isEventPastAddressWindow(event)) {
if (!isCanceled && isEventPastAddressWindow(event)) {
addressMessage = 'Vielen Dank, dass du an diesem Event teilgenommen hast.';
}

View File

@ -397,6 +397,8 @@
});
const filtered = allEvents.filter(event => {
if (event.status === 'canceled') return false;
const categoryMatch = activeCategory === 'ALLE' || event.category === activeCategory;
// Diet filter: if no diets selected, show all. Otherwise, event MUST have at least one selected diet.
@ -413,7 +415,6 @@
return categoryMatch && dietMatch && allergieMatch && locationMatch && dateMatch;
});
renderEvents(filtered);
sessionStorage.setItem('activeFilter', activeCategory);
@ -473,6 +474,11 @@
const isOwnEvent = isEventOwnedByCurrentUser(event, currentUser);
const isRegistered = userRegistrationSet.has(Number(event.id));
const isRegistrationClosed = isRegistrationClosedForEvent(event);
const isCanceled = event.status === 'canceled';
if (isCanceled) {
card.style.opacity = '0.6';
}
// Build optional specification chips only when data exists.
const specsChips = event.specifications && event.specifications.length > 0
@ -484,19 +490,31 @@
? event.diet.split(', ').map(d => `<span class="event-tag">${d.trim()}</span>`).join('')
: '';
const actionMarkup = isOwnEvent
? '<button class="button-primary-eigener-event" type="button" data-registration-action="own" disabled>Dein Event!</button>'
: isRegistered
? (isRegistrationClosed
? '<button class="button-primary button-primary-abmelden" type="button" disabled>Abmeldung geschlossen</button>'
: '<button class="button-primary button-primary-abmelden" type="button" data-registration-action="unregister">Abmelden</button>')
: isRegistrationClosed
? '<button class="button-primary" button-plaetze" type="button" data-registration-action="closed" disabled>Anmeldung geschlossen</button>'
: isFull
? ''
: !currentUser
? '<button class="button-primary btn-primary-register" type="button" data-registration-action="login">Anmelden</button>'
: '<button class="button-primary btn-primary-register" type="button" data-registration-action="register">Anmelden</button>';
let actionMarkup = '';
if (isCanceled) {
actionMarkup = '<button class="button-primary" type="button" disabled>Abgesagt</button>';
} else if (isOwnEvent) {
actionMarkup = '<button class="button-primary-eigener-event" type="button" data-registration-action="own" disabled>Dein Event!</button>';
} else if (isRegistered) {
actionMarkup = isRegistrationClosed
? '<button class="button-primary-abmelden" type="button" disabled>Abmeldung geschlossen</button>'
: '<button class="button-primary-abmelden" type="button" data-registration-action="unregister">Abmelden</button>';
} else if (isRegistrationClosed) {
actionMarkup = '<button class="button-primary-abmelden" type="button" data-registration-action="closed" disabled>Anmeldung geschlossen</button>';
} else if (!isFull) {
if (!currentUser) {
actionMarkup = '<button class="button-primary btn-primary-register" type="button" data-registration-action="login">Anmelden</button>';
} else {
actionMarkup = '<button class="button-primary btn-primary-register" type="button" data-registration-action="register">Anmelden</button>';
}
}
let sideInfoMarkup = '';
if (isCanceled) {
sideInfoMarkup = '<span class="button-plaetze">Event abgesagt</span>';
} else if (!isRegistrationClosed) {
sideInfoMarkup = `<span class="button-plaetze${isFull ? ' event-spots-full' : ''}">${isFull ? 'Ausgebucht' : `${freePlaces} Plätze frei`}</span>`;
}
card.innerHTML = `
<div class="event-main">
@ -517,7 +535,7 @@
</div>
</div>
<div class="event-side${isFull ? ' event-side-full' : ''}">
${isRegistrationClosed ? '' : `<span class="button-plaetze${isFull ? ' event-spots-full' : ''}">${isFull ? 'Ausgebucht' : `${freePlaces} Plätze frei`}</span>`}
${sideInfoMarkup}
${actionMarkup}
</div>
`;

View File

@ -457,13 +457,27 @@
});
}
// Ermittelt angemeldete Events über die Registration-Map.
// Ermittelt angemeldete Events über die Registration-Map und participants-Liste.
function getMyRegisteredEvents(events, user) {
const registrationMap = getRegistrationMap();
const registeredIds = Array.isArray(registrationMap[user.email]) ? registrationMap[user.email] : [];
const idSet = new Set(registeredIds.map(id => Number(id)));
return events.filter(event => idSet.has(Number(event.id)));
const userFirstName = String(user.vorname || '').trim().toLowerCase();
const userFullName = `${String(user.vorname || '').trim()} ${String(user.nachname || '').trim()}`.trim().toLowerCase();
return events.filter(event => {
if (idSet.has(Number(event.id))) {
return true;
}
if (Array.isArray(event.participants)) {
const participantSet = new Set(event.participants.map(name => String(name || '').trim().toLowerCase()).filter(Boolean));
if ((userFirstName && participantSet.has(userFirstName)) || (userFullName && participantSet.has(userFullName))) {
return true;
}
}
return false;
});
}
// Rendert angemeldete Events inkl. Zähler.
@ -584,46 +598,81 @@
const card = document.createElement('article');
card.className = 'profile-event-card profile-event-card-clickable';
card.setAttribute('data-event-id', String(event.id));
const isCanceled = event.status === 'canceled';
if (isCanceled) {
card.style.opacity = '0.6';
}
let addressMessage = 'Vielen Dank für die Anmeldung! Die Adresse für diesen Event wird 24 Stunden vorher genau hier sichtbar sein.';
if (isEventPastAddressWindow(event)) {
addressMessage = 'Vielen Dank, dass du an diesem Event teilgenommen hast.';
}
const addressMarkup = mode === 'registrations' && event.address
? (isAddressVisibleWindow(event)
? `
let addressMarkup = '';
if (mode === 'registrations' && event.address) {
if (isCanceled) {
addressMarkup = `
<div class="profile-event-address-block" aria-label="Hinweis zur Adresse">
<p class="profile-event-address-label">Adresse</p>
<p class="profile-event-address">Dieses Event wurde leider vom Gastgeber abgesagt.</p>
</div>
`;
} else if (isAddressVisibleWindow(event)) {
addressMarkup = `
<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>
`
: `
`;
} else {
addressMarkup = `
<div class="profile-event-address-block" aria-label="Hinweis zur Adresse">
<p class="profile-event-address-label">Adresse</p>
<p class="profile-event-address">${addressMessage}</p>
</div>
`)
: '';
`;
}
}
const isDeregClosed = isDeregistrationClosed(event);
const actionMarkup = mode === 'registrations'
? (isDeregClosed
? `
let actionMarkup = '';
if (mode === 'registrations') {
if (isCanceled) {
actionMarkup = `
<div class="event-side">
<button class="button-primary-abmelden" type="button" disabled>Abgesagt</button>
</div>
`;
} else if (isDeregClosed) {
actionMarkup = `
<div class="event-side">
<button class="button-primary-abmelden" type="button" disabled>Abmeldung geschlossen</button>
</div>
`
: `
`;
} else {
actionMarkup = `
<div class="event-side">
<button class="button-primary-abmelden" type="button" data-unregister-id="${event.id}">Abmelden</button>
</div>
`)
: `
`;
}
} else {
if (isCanceled) {
actionMarkup = `
<div class="event-side">
<button class="button-primary-eigener-event" type="button" disabled>Abgesagt</button>
</div>
`;
} else {
actionMarkup = `
<div class="event-side">
<button class="button-primary-eigener-event" type="button" data-cancel-event-id="${event.id}">Event absagen</button>
</div>
`;
`;
}
}
card.innerHTML = `
<div>
@ -640,6 +689,7 @@
// Gibt true zurück, wenn die Adresse sichtbar sein soll (24h vor bis 1h nach Start).
function isAddressVisibleWindow(event) {
if (event.status === 'canceled') return false;
const eventDateTime = parseEventDateTime(event);
if (!eventDateTime || Number.isNaN(eventDateTime.getTime())) return false;
const now = Date.now();

View File

@ -74,6 +74,7 @@ document.addEventListener('DOMContentLoaded', () => {
}
function isAddressVisibleWindow(event) {
if (event.status === 'canceled') return false;
const eventDateTime = parseEventDateTime(event);
if (!eventDateTime || Number.isNaN(eventDateTime.getTime())) return false;
const now = Date.now();