Update event dates and participant handling; adjust visibility window to 24 hours
This commit is contained in:
parent
fa8a7f1fc2
commit
e3ac1a11f0
@ -4,11 +4,11 @@
|
||||
"title": "Italienische Tavolata",
|
||||
"location": "Luzern",
|
||||
"address": "Pilatusstrasse 18, 6003 Luzern",
|
||||
"date": "11. APR. 2026",
|
||||
"date": "22. APR. 2026",
|
||||
"time": "15:30 UHR",
|
||||
"category": "Dinner",
|
||||
"diet": "Vegetarisch",
|
||||
"spots": 6,
|
||||
"spots": 8,
|
||||
"host": {
|
||||
"name": "Ferdinando",
|
||||
"initial": "F"
|
||||
@ -45,7 +45,7 @@
|
||||
"title": "Noche Peruana",
|
||||
"location": "Chur",
|
||||
"address": "Obere Gasse 41, 7000 Chur",
|
||||
"date": "16. Juni 2026",
|
||||
"date": "12. April 2026",
|
||||
"time": "19:00 UHR",
|
||||
"category": "Dinner",
|
||||
"diet": "Omnivore",
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const EVENTS_STORAGE_KEY = 'socialCookingEvents';
|
||||
const CURRENT_USER_KEY = 'socialCookingCurrentUser';
|
||||
const USERS_STORAGE_KEY = 'socialCookingUsers';
|
||||
const REGISTRATION_STORAGE_KEY = 'socialCookingRegistrations';
|
||||
// -------------------------------------------------------------
|
||||
// DOM entry point and shared asset path.
|
||||
@ -50,6 +51,57 @@
|
||||
}
|
||||
}
|
||||
|
||||
function getStoredUsers() {
|
||||
try {
|
||||
const stored = localStorage.getItem(USERS_STORAGE_KEY);
|
||||
return stored ? JSON.parse(stored) : [];
|
||||
} catch (error) {
|
||||
console.error('Benutzerdaten konnten nicht gelesen werden.', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function getUserDisplayName(user) {
|
||||
if (!user) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const firstName = String(user.vorname || '').trim();
|
||||
const lastName = String(user.nachname || '').trim();
|
||||
|
||||
return (firstName || `${firstName} ${lastName}`.trim() || String(user.email || '').trim()).trim();
|
||||
}
|
||||
|
||||
function getResolvedParticipants(event, registrationMap) {
|
||||
const baseParticipants = Array.isArray(event.participants)
|
||||
? event.participants.map(name => String(name || '').trim()).filter(Boolean)
|
||||
: [];
|
||||
const usersByEmail = new Map(
|
||||
getStoredUsers().map(user => [String(user.email || '').trim().toLowerCase(), user])
|
||||
);
|
||||
const participantLookup = new Set(baseParticipants.map(name => name.toLowerCase()));
|
||||
|
||||
Object.entries(registrationMap || {}).forEach(([email, ids]) => {
|
||||
const isRegisteredForEvent = Array.isArray(ids)
|
||||
&& ids.map(id => Number(id)).includes(Number(event.id));
|
||||
|
||||
if (!isRegisteredForEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
const user = usersByEmail.get(String(email || '').trim().toLowerCase());
|
||||
const displayName = getUserDisplayName(user) || String(email || '').trim();
|
||||
const normalizedName = displayName.toLowerCase();
|
||||
|
||||
if (displayName && !participantLookup.has(normalizedName)) {
|
||||
baseParticipants.push(displayName);
|
||||
participantLookup.add(normalizedName);
|
||||
}
|
||||
});
|
||||
|
||||
return baseParticipants;
|
||||
}
|
||||
|
||||
function setRegistrationMap(registrationMap) {
|
||||
localStorage.setItem(REGISTRATION_STORAGE_KEY, JSON.stringify(registrationMap));
|
||||
}
|
||||
@ -114,7 +166,7 @@
|
||||
}
|
||||
|
||||
const msUntilStart = eventDateTime.getTime() - Date.now();
|
||||
const twentyfourHoursInMs = 12 * 60 * 60 * 1000;
|
||||
const twentyfourHoursInMs = 24 * 60 * 60 * 1000;
|
||||
|
||||
return msUntilStart <= twentyfourHoursInMs;
|
||||
}
|
||||
@ -138,7 +190,7 @@
|
||||
return { daysLeft, isClosed: false };
|
||||
}
|
||||
|
||||
// Adresse ist nur im 12h-Fenster VOR Eventstart sichtbar.
|
||||
// Adresse ist nur im 24h-Fenster VOR Eventstart sichtbar.
|
||||
function isAddressVisibleWindow(event) {
|
||||
const eventDateTime = parseEventDateTime(event);
|
||||
if (!eventDateTime || Number.isNaN(eventDateTime.getTime())) {
|
||||
@ -146,7 +198,7 @@
|
||||
}
|
||||
|
||||
const msUntilStart = eventDateTime.getTime() - Date.now();
|
||||
const twentyfourHoursInMs = 12 * 60 * 60 * 1000;
|
||||
const twentyfourHoursInMs = 24 * 60 * 60 * 1000;
|
||||
|
||||
return msUntilStart >= 0 && msUntilStart <= twentyfourHoursInMs;
|
||||
}
|
||||
@ -283,16 +335,26 @@
|
||||
const specifications = Array.isArray(event.specifications) && event.specifications.length > 0
|
||||
? event.specifications
|
||||
: [];
|
||||
const participants = Array.isArray(event.participants) ? event.participants : [];
|
||||
const galleryImages = Array.isArray(event.gallery) && event.gallery.length > 0
|
||||
? event.gallery
|
||||
: [event.image, event.image, event.image];
|
||||
const visibleParticipants = participants.slice(0, 6);
|
||||
const registrationMap = getRegistrationMap();
|
||||
const extraRegistrations = countRegistrationsForEvent(registrationMap, event.id);
|
||||
const remainingParticipants = Math.max(0, participants.length + extraRegistrations - visibleParticipants.length);
|
||||
const participants = getResolvedParticipants(event, registrationMap);
|
||||
const galleryImages = Array.isArray(event.gallery)
|
||||
? event.gallery.filter(Boolean)
|
||||
: [];
|
||||
const galleryMarkup = galleryImages.length > 0
|
||||
? `
|
||||
<div class="detail-gallery detail-gallery-large">
|
||||
${galleryImages.slice(0, 9).map((img, index) => `
|
||||
<button class="detail-gallery-item" type="button" aria-label="Bild ${index + 1} gross anzeigen" data-fullsrc="${img}">
|
||||
<img src="${img}" alt="${event.title} Bild ${index + 1}" class="detail-gallery-image">
|
||||
</button>
|
||||
`).join('')}
|
||||
</div>
|
||||
`
|
||||
: '';
|
||||
const visibleParticipants = participants.slice(0, 6);
|
||||
const remainingParticipants = Math.max(0, participants.length - visibleParticipants.length);
|
||||
const totalGuests = Number.isFinite(event.spots) ? event.spots : 0;
|
||||
const confirmedGuests = participants.length + extraRegistrations;
|
||||
const confirmedGuests = participants.length;
|
||||
const freePlaces = Math.max(0, totalGuests - confirmedGuests);
|
||||
const isFull = freePlaces === 0;
|
||||
const isRegistrationClosed = isRegistrationClosedForEvent(event);
|
||||
@ -331,7 +393,12 @@
|
||||
<p>${event.address}</p>
|
||||
</article>
|
||||
`
|
||||
: '';
|
||||
: `
|
||||
<article class="detail-panel">
|
||||
<h2 class="detail-section-title">Adresse</h2>
|
||||
<p>Vielen Dank für die Anmeldung! Die Adresse für diesen Event wird 24 Stunden vorher genau hier sichtbar sein.</p>
|
||||
</article>
|
||||
`;
|
||||
const detailChips = [
|
||||
`<span class="event-tag">${eventCategory}</span>`,
|
||||
...event.diet.split(', ').filter(d => d.trim() && d !== 'Keine Angabe').map(d => `<span class="event-tag">${getDietLabel(d.trim())}</span>`),
|
||||
@ -401,13 +468,7 @@
|
||||
${addressPanelMarkup}
|
||||
</div>
|
||||
|
||||
<div class="detail-gallery detail-gallery-large">
|
||||
${galleryImages.slice(0, 9).map((img, index) => `
|
||||
<button class="detail-gallery-item" type="button" aria-label="Bild ${index + 1} gross anzeigen" data-fullsrc="${img}">
|
||||
<img src="${img}" alt="${event.title} Bild ${index + 1}" class="detail-gallery-image">
|
||||
</button>
|
||||
`).join('')}
|
||||
</div>
|
||||
${galleryMarkup}
|
||||
</section>
|
||||
|
||||
<section class="detail-action-bar">
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const EVENTS_STORAGE_KEY = 'socialCookingEvents';
|
||||
const CURRENT_USER_KEY = 'socialCookingCurrentUser';
|
||||
const USERS_STORAGE_KEY = 'socialCookingUsers';
|
||||
const REGISTRATION_STORAGE_KEY = 'socialCookingRegistrations';
|
||||
const INFO_MODAL_SHOWN_KEY = 'infoModalShownOnFirstLogin';
|
||||
// -------------------------------------------------------------
|
||||
@ -73,6 +74,57 @@
|
||||
}
|
||||
}
|
||||
|
||||
function getStoredUsers() {
|
||||
try {
|
||||
const stored = localStorage.getItem(USERS_STORAGE_KEY);
|
||||
return stored ? JSON.parse(stored) : [];
|
||||
} catch (error) {
|
||||
console.error('Benutzerdaten konnten nicht gelesen werden.', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function getUserDisplayName(user) {
|
||||
if (!user) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const firstName = String(user.vorname || '').trim();
|
||||
const lastName = String(user.nachname || '').trim();
|
||||
|
||||
return (firstName || `${firstName} ${lastName}`.trim() || String(user.email || '').trim()).trim();
|
||||
}
|
||||
|
||||
function getResolvedParticipants(event, registrationMap) {
|
||||
const baseParticipants = Array.isArray(event.participants)
|
||||
? event.participants.map(name => String(name || '').trim()).filter(Boolean)
|
||||
: [];
|
||||
const usersByEmail = new Map(
|
||||
getStoredUsers().map(user => [String(user.email || '').trim().toLowerCase(), user])
|
||||
);
|
||||
const participantLookup = new Set(baseParticipants.map(name => name.toLowerCase()));
|
||||
|
||||
Object.entries(registrationMap || {}).forEach(([email, ids]) => {
|
||||
const isRegisteredForEvent = Array.isArray(ids)
|
||||
&& ids.map(id => Number(id)).includes(Number(event.id));
|
||||
|
||||
if (!isRegisteredForEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
const user = usersByEmail.get(String(email || '').trim().toLowerCase());
|
||||
const displayName = getUserDisplayName(user) || String(email || '').trim();
|
||||
const normalizedName = displayName.toLowerCase();
|
||||
|
||||
if (displayName && !participantLookup.has(normalizedName)) {
|
||||
baseParticipants.push(displayName);
|
||||
participantLookup.add(normalizedName);
|
||||
}
|
||||
});
|
||||
|
||||
return baseParticipants;
|
||||
}
|
||||
|
||||
function setRegistrationMap(registrationMap) {
|
||||
localStorage.setItem(REGISTRATION_STORAGE_KEY, JSON.stringify(registrationMap));
|
||||
}
|
||||
@ -392,10 +444,9 @@
|
||||
const displayTime = formatEventTime(event.time);
|
||||
|
||||
// Capacity logic:
|
||||
// spots = total capacity, participants.length = booked seats.
|
||||
const baseParticipants = Array.isArray(event.participants) ? event.participants.length : 0;
|
||||
const extraRegistrations = countRegistrationsForEvent(registrationMap, event.id);
|
||||
const bookedSeats = baseParticipants + extraRegistrations;
|
||||
// spots = total capacity, resolved participants = booked seats.
|
||||
const resolvedParticipants = getResolvedParticipants(event, registrationMap);
|
||||
const bookedSeats = resolvedParticipants.length;
|
||||
const totalCapacity = event.spots;
|
||||
const freePlaces = Math.max(0, totalCapacity - bookedSeats);
|
||||
const isFull = freePlaces === 0;
|
||||
|
||||
@ -538,7 +538,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
// Gibt true zurück, wenn ein Event innerhalb der nächsten 12 Stunden startet.
|
||||
// Gibt true zurück, wenn ein Event innerhalb der nächsten 24 Stunden startet.
|
||||
function isAddressVisibleWindow(event) {
|
||||
const eventDateTime = parseEventDateTime(event);
|
||||
if (!eventDateTime || Number.isNaN(eventDateTime.getTime())) {
|
||||
@ -546,7 +546,7 @@
|
||||
}
|
||||
|
||||
const msUntilStart = eventDateTime.getTime() - Date.now();
|
||||
const twentyfourHoursInMs = 12 * 60 * 60 * 1000;
|
||||
const twentyfourHoursInMs = 24 * 60 * 60 * 1000;
|
||||
|
||||
return msUntilStart >= 0 && msUntilStart <= twentyfourHoursInMs;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user