Adresse
${event.address}
document.addEventListener('DOMContentLoaded', async () => { const EVENTS_STORAGE_KEY = 'socialCookingEvents'; const CURRENT_USER_KEY = 'socialCookingCurrentUser'; const USERS_STORAGE_KEY = 'socialCookingUsers'; const REGISTRATION_STORAGE_KEY = 'socialCookingRegistrations'; const detailcontainer = document.getElementById('detail-view'); const locationIconPath = 'assets/icon_location.svg'; const calendarIconPath = 'assets/icon_calendar.svg'; const gastIconPath = 'assets/icon_gast.svg'; const currentUser = getCurrentUser(); const params = new URLSearchParams(window.location.search); const eventId = parseInt(params.get('id')); if (!eventId) { window.location.href = 'event_overview.html'; return; } function getStoredEvents() { try { const stored = localStorage.getItem(EVENTS_STORAGE_KEY); return stored ? JSON.parse(stored) : []; } catch (error) { console.error('Lokale Events konnten nicht gelesen werden.', error); return []; } } function getCurrentUser() { try { const stored = localStorage.getItem(CURRENT_USER_KEY); return stored ? JSON.parse(stored) : null; } catch (error) { console.error('Aktueller Benutzer konnte nicht gelesen werden.', error); return null; } } function getRegistrationMap() { try { const stored = localStorage.getItem(REGISTRATION_STORAGE_KEY); return stored ? JSON.parse(stored) : {}; } catch (error) { console.error('Anmeldedaten konnten nicht gelesen werden.', error); return {}; } } 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(); const fullName = `${firstName} ${lastName}`.trim(); return (fullName || firstName || 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 getParticipantNameForViewer(name, canSeeLastName) { const rawName = String(name || '').trim(); if (!rawName) return ''; if (canSeeLastName) return rawName; 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)); } function getRegistrationIdsForUser(registrationMap, user) { const userEmail = String(user?.email || '').trim().toLowerCase(); if (!userEmail) return []; const matchingIds = Object.entries(registrationMap || {}) .filter(([email]) => String(email || '').trim().toLowerCase() === userEmail) .flatMap(([, ids]) => (Array.isArray(ids) ? ids : [])) .map(id => Number(id)) .filter(id => Number.isFinite(id)); return Array.from(new Set(matchingIds)); } function parseEventDateTime(event) { if (!event?.date) return null; const dateValue = String(event.date).trim(); const isoDateMatch = dateValue.match(/^(\d{4})-(\d{2})-(\d{2})$/); let year, month, day; if (isoDateMatch) { year = Number(isoDateMatch[1]); month = Number(isoDateMatch[2]); day = Number(isoDateMatch[3]); } else { const monthMap = { jan: 1, januar: 1, feb: 2, februar: 2, 'mär': 3, mrz: 3, mar: 3, maerz: 3, märz: 3, apr: 4, april: 4, mai: 5, jun: 6, juni: 6, jul: 7, juli: 7, aug: 8, august: 8, sep: 9, sept: 9, september: 9, okt: 10, oktober: 10, nov: 11, november: 11, dez: 12, dezember: 12 }; const localizedMatch = dateValue.match(/^(\d{1,2})\.\s*([A-Za-zÄÖÜäöü]{3,9})\.?\s*(\d{4})$/); if (!localizedMatch) return null; day = Number(localizedMatch[1]); month = monthMap[String(localizedMatch[2]).toLowerCase()]; year = Number(localizedMatch[3]); if (!month) return null; } const timeMatch = String(event.time || '').match(/(\d{1,2}):(\d{2})/); const hours = timeMatch ? Number(timeMatch[1]) : 0; const minutes = timeMatch ? Number(timeMatch[2]) : 0; return new Date(year, month - 1, day, hours, minutes, 0, 0); } function isRegistrationClosedForEvent(event) { const eventDateTime = parseEventDateTime(event); if (!eventDateTime || Number.isNaN(eventDateTime.getTime())) return false; const msUntilStart = eventDateTime.getTime() - Date.now(); return msUntilStart <= 24 * 60 * 60 * 1000; } function getDeregistrationInfo(event) { const eventDateTime = parseEventDateTime(event); if (!eventDateTime || Number.isNaN(eventDateTime.getTime())) return { daysLeft: null, isClosed: false }; const oneDayMs = 24 * 60 * 60 * 1000; const msUntilDeadline = (eventDateTime.getTime() - oneDayMs) - Date.now(); if (msUntilDeadline <= 0) return { daysLeft: 0, isClosed: true }; return { daysLeft: Math.ceil(msUntilDeadline / oneDayMs), isClosed: false }; } function isAddressVisibleWindow(event) { const eventDateTime = parseEventDateTime(event); if (!eventDateTime || Number.isNaN(eventDateTime.getTime())) return false; const now = Date.now(); const start = eventDateTime.getTime(); const revealStart = start - (24 * 60 * 60 * 1000); const revealEnd = start + (1 * 60 * 60 * 1000); return now >= revealStart && now <= revealEnd; } function isEventPastAddressWindow(event) { const eventDateTime = parseEventDateTime(event); if (!eventDateTime || Number.isNaN(eventDateTime.getTime())) return false; const revealEnd = eventDateTime.getTime() + (1 * 60 * 60 * 1000); return Date.now() > revealEnd; } function isEventOwnedByCurrentUser(event, user) { if (!event || !user) return false; const userEmail = String(user.email || '').trim().toLowerCase(); const hostEmail = String(event.hostEmail || '').trim().toLowerCase(); if (userEmail && hostEmail) return userEmail === hostEmail; const userFirstName = String(user.vorname || '').trim().toLowerCase(); const hostName = String(event.host?.name || '').trim().toLowerCase(); return Boolean(userFirstName && hostName && userFirstName === hostName); } function isUserListedInEventParticipants(event, user) { if (!event || !user || !Array.isArray(event.participants)) return false; const participantSet = new Set( event.participants.map(name => String(name || '').trim().toLowerCase()).filter(Boolean) ); const userFirstName = String(user.vorname || '').trim().toLowerCase(); const userFullName = `${String(user.vorname || '').trim()} ${String(user.nachname || '').trim()}`.trim().toLowerCase(); return Boolean( (userFirstName && participantSet.has(userFirstName)) || (userFullName && participantSet.has(userFullName)) ); } function formatEventDate(dateString) { if (/^\d{4}-\d{2}-\d{2}$/.test(dateString)) { const [year, month, day] = dateString.split('-'); return `${Number(day)}. ${['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'][Number(month)-1]} ${year}`; } const labels = { JAN:'Januar', FEB:'Februar', 'MÄR':'März', MRZ:'März', APR:'April', MAI:'Mai', JUN:'Juni', JUL:'Juli', AUG:'August', SEP:'September', OKT:'Oktober', NOV:'November', DEZ:'Dezember' }; const match = dateString.match(/^(\d{1,2})\.\s*([A-ZÄÖÜ]{3})\.\s*(\d{4})$/); if (!match) return dateString; const monthLabel = labels[match[2]]; return monthLabel ? `${Number(match[1])}. ${monthLabel} ${match[3]}` : dateString; } function formatEventTime(timeString) { return timeString.replace('UHR', 'Uhr').trim(); } function getDietLabel(diet) { const labels = { FLEISCH:'Fleisch', FISCH:'Fisch', VEGGIE:'Vegetarisch', VEGAN:'Vegan' }; return labels[diet] || diet; } function getPlaceholderImageByEventType(event) { const rawType = String(event?.eventType || event?.category || '') .trim() .toLowerCase() .normalize('NFD') .replace(/[\u0300-\u036f]/g, '') .replace(/[+&/_-]/g, ' ') .replace(/\s+/g, ' '); if (rawType.includes('brunch')) { return 'assets/platzhalter_brunch.jpeg'; } if (rawType.includes('lunch')) { return 'assets/platzhalter_lunch.jpeg'; } if ( rawType.includes('kaffee') || rawType.includes('coffee') || rawType.includes('cafe') || rawType.includes('kuchen') ) { return 'assets/platzhalter_kaffee.jpeg'; } if (rawType.includes('dinner')) { return 'assets/platzhalter_dinner.jpeg'; } return 'assets/platzhalter_dinner.jpeg'; } // Fetch data source and resolve the matching event record. try { const response = await fetch('data/events.json'); const apiEvents = await response.json(); const allEvents = [...getStoredEvents(), ...apiEvents]; const event = allEvents.find(e => e.id === eventId); if (event) { renderDetailPage(event); } else { detailcontainer.innerHTML = "
${event.address}
${addressMessage}
${paragraph}
`).join('')}