@@ -249,7 +286,7 @@ document.addEventListener('DOMContentLoaded', () => {
${isFull ? 'AUSGEBUCHT' : `${freePlaces} Plätze FREI`}
- ${isFull ? '' : ''}
+ ${actionMarkup}
`;
diff --git a/js/login.js b/js/login.js
index e1c059c..5ba97fe 100644
--- a/js/login.js
+++ b/js/login.js
@@ -4,6 +4,42 @@ const passwortInput = document.getElementById('passwort');
const emailError = document.getElementById('emailError');
const passwortError = document.getElementById('passwortError');
+const USERS_STORAGE_KEY = 'socialCookingUsers';
+const CURRENT_USER_KEY = 'socialCookingCurrentUser';
+
+// Liest alle registrierten Benutzer robust aus localStorage.
+function getStoredUsers() {
+ try {
+ const raw = localStorage.getItem(USERS_STORAGE_KEY);
+ return raw ? JSON.parse(raw) : [];
+ } catch (error) {
+ console.error('Benutzerdaten konnten nicht gelesen werden.', error);
+ return [];
+ }
+}
+
+// Speichert den aktiven Benutzer fuer nachfolgende Seiten.
+function setCurrentUser(user) {
+ localStorage.setItem(CURRENT_USER_KEY, JSON.stringify(user));
+}
+
+// Erstellt einen Demo-Benutzer, falls fuer die E-Mail noch kein Account existiert.
+function createFallbackUser(email, passwort) {
+ const localPart = email.split('@')[0] || 'Gast';
+ const normalized = localPart.replace(/[._-]/g, ' ').trim();
+ const guessedVorname = normalized ? normalized.split(' ')[0] : 'Gast';
+
+ return {
+ id: Date.now(),
+ vorname: guessedVorname.charAt(0).toUpperCase() + guessedVorname.slice(1),
+ nachname: '',
+ email,
+ passwort,
+ createdAt: new Date().toISOString(),
+ source: 'login-fallback'
+ };
+}
+
// Validierungsfunktion
function validateForm(event) {
event.preventDefault();
@@ -43,11 +79,21 @@ function validateForm(event) {
passwortGroup.classList.remove('has-error');
}
- // Wenn alle Validierungen bestanden, Form absenden
+ // Wenn alle Validierungen bestanden, Benutzer pruefen und Session speichern.
if (isValid) {
- //alert('Login erfolgreich! (Dies ist eine Demo)');
+ const users = getStoredUsers();
+ const matchedUser = users.find(user => user.email?.toLowerCase() === emailValue.toLowerCase());
- // Weiterleitung zur event overview Page
+ if (matchedUser && matchedUser.passwort !== passwortValue) {
+ passwortGroup.classList.add('has-error');
+ passwortError.textContent = 'Das Passwort ist nicht korrekt.';
+ return;
+ }
+
+ const userToLogin = matchedUser || createFallbackUser(emailValue, passwortValue);
+ setCurrentUser(userToLogin);
+
+ // Weiterleitung zur Event-Overview-Seite.
window.location.href = 'event_overview.html';
}
}
diff --git a/js/my_profil.js b/js/my_profil.js
new file mode 100644
index 0000000..9d7ee5f
--- /dev/null
+++ b/js/my_profil.js
@@ -0,0 +1,367 @@
+document.addEventListener('DOMContentLoaded', () => {
+ const EVENTS_STORAGE_KEY = 'socialCookingEvents';
+ const USERS_STORAGE_KEY = 'socialCookingUsers';
+ const CURRENT_USER_KEY = 'socialCookingCurrentUser';
+ const REGISTRATION_STORAGE_KEY = 'socialCookingRegistrations';
+
+ // Zentrale DOM-Referenzen fuer klare, testbare Funktionen.
+ const loggedOutState = document.getElementById('logged-out-state');
+ const loggedInContent = document.getElementById('logged-in-content');
+ const profileHeadline = document.getElementById('profile-headline');
+ const profileSubline = document.getElementById('profile-subline');
+ const logoutButton = document.getElementById('logout-button');
+
+ const myEventsCount = document.getElementById('my-events-count');
+ const myRegistrationsCount = document.getElementById('my-registrations-count');
+ const myEventsList = document.getElementById('my-events-list');
+ const myRegistrationsList = document.getElementById('my-registrations-list');
+
+ const profileForm = document.getElementById('profile-form');
+ const profileFeedback = document.getElementById('profile-feedback');
+ const vornameInput = document.getElementById('vorname');
+ const nachnameInput = document.getElementById('nachname');
+ const emailInput = document.getElementById('email');
+ const passwortInput = document.getElementById('passwort');
+
+ let currentUser = getCurrentUser();
+ let allEvents = [];
+
+ init();
+
+ async function init() {
+ if (!currentUser) {
+ renderLoggedOutState();
+ return;
+ }
+
+ renderLoggedInState(currentUser);
+ bindFormHandlers();
+
+ allEvents = await loadAllEvents();
+ renderMyEvents(allEvents, currentUser);
+ renderMyRegistrations(allEvents, currentUser);
+ }
+
+ // Liest den aktuell eingeloggten Benutzer robust aus dem Storage.
+ function getCurrentUser() {
+ try {
+ const raw = localStorage.getItem(CURRENT_USER_KEY);
+ return raw ? JSON.parse(raw) : null;
+ } catch (error) {
+ console.error('Der aktuelle Benutzer konnte nicht geladen werden.', error);
+ return null;
+ }
+ }
+
+ // Liest lokal erstellte Events aus dem Storage.
+ function getStoredEvents() {
+ try {
+ const raw = localStorage.getItem(EVENTS_STORAGE_KEY);
+ return raw ? JSON.parse(raw) : [];
+ } catch (error) {
+ console.error('Lokale Events konnten nicht gelesen werden.', error);
+ return [];
+ }
+ }
+
+ // Liest den Anmeldestatus pro Benutzer-E-Mail.
+ function getRegistrationMap() {
+ try {
+ const raw = localStorage.getItem(REGISTRATION_STORAGE_KEY);
+ return raw ? JSON.parse(raw) : {};
+ } catch (error) {
+ console.error('Anmeldedaten konnten nicht gelesen werden.', error);
+ return {};
+ }
+ }
+
+ // Schreibt den gesamten Registrierungszustand in localStorage.
+ function setRegistrationMap(registrationMap) {
+ localStorage.setItem(REGISTRATION_STORAGE_KEY, JSON.stringify(registrationMap));
+ }
+
+ // Fuehrt JSON-Daten und lokal erstellte Events in einer Liste zusammen.
+ async function loadAllEvents() {
+ try {
+ const response = await fetch('data/events.json');
+ const apiEvents = await response.json();
+ return [...getStoredEvents(), ...apiEvents];
+ } catch (error) {
+ console.error('Events konnten nicht geladen werden.', error);
+ return getStoredEvents();
+ }
+ }
+
+ // Schaltet in den ausgeloggten Zustand und blendet geschuetzte Inhalte aus.
+ function renderLoggedOutState() {
+ loggedOutState.classList.remove('hidden');
+ loggedInContent.classList.add('hidden');
+ logoutButton.classList.add('hidden');
+ profileHeadline.textContent = 'Mein Profil';
+ profileSubline.textContent = 'Bitte logge dich ein, um deinen Bereich zu sehen.';
+ }
+
+ // Fuellt Ueberschriften und Formular mit den aktuellen Benutzerdaten.
+ function renderLoggedInState(user) {
+ loggedOutState.classList.add('hidden');
+ loggedInContent.classList.remove('hidden');
+ logoutButton.classList.remove('hidden');
+
+ profileHeadline.textContent = `Hallo ${user.vorname || 'Gast'}`;
+ profileSubline.textContent = 'Hier kannst du deine Events und Anmeldungen verwalten.';
+
+ vornameInput.value = user.vorname || '';
+ nachnameInput.value = user.nachname || '';
+ emailInput.value = user.email || '';
+ }
+
+ // Bindet Submit-, Input- und Logout-Verhalten an die Profilseite.
+ function bindFormHandlers() {
+ profileForm.addEventListener('submit', handleProfileSubmit);
+ myRegistrationsList.addEventListener('click', handleRegistrationListClick);
+
+ [vornameInput, nachnameInput, emailInput, passwortInput].forEach(input => {
+ input.addEventListener('input', () => {
+ input.parentElement.classList.remove('has-error');
+ profileFeedback.textContent = '';
+ });
+ });
+
+ logoutButton.addEventListener('click', () => {
+ localStorage.removeItem(CURRENT_USER_KEY);
+ window.location.href = 'login.html';
+ });
+ }
+
+ // Reagiert auf Aktionen in der Liste "Meine Anmeldungen" per Event Delegation.
+ function handleRegistrationListClick(event) {
+ const target = event.target;
+ if (!(target instanceof HTMLElement)) {
+ return;
+ }
+
+ const unregisterButton = target.closest('[data-unregister-id]');
+ if (!unregisterButton || !currentUser?.email) {
+ return;
+ }
+
+ const eventId = Number(unregisterButton.getAttribute('data-unregister-id'));
+ if (!Number.isFinite(eventId)) {
+ return;
+ }
+
+ unregisterFromEvent(eventId, currentUser.email);
+ }
+
+ // Entfernt eine Event-ID aus der Benutzerliste und aktualisiert die UI sofort.
+ function unregisterFromEvent(eventId, userEmail) {
+ const registrationMap = getRegistrationMap();
+ const currentIds = Array.isArray(registrationMap[userEmail]) ? registrationMap[userEmail] : [];
+ const nextIds = currentIds
+ .map(id => Number(id))
+ .filter(id => Number.isFinite(id) && id !== eventId);
+
+ registrationMap[userEmail] = nextIds;
+ setRegistrationMap(registrationMap);
+
+ renderMyRegistrations(allEvents, currentUser);
+ profileFeedback.textContent = 'Du wurdest von dem Event abgemeldet.';
+ }
+
+ // Validiert Profildaten konsistent und liefert true/false zur Submit-Steuerung.
+ function validateProfileForm() {
+ let isValid = true;
+
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+
+ if (!vornameInput.value.trim()) {
+ vornameInput.parentElement.classList.add('has-error');
+ isValid = false;
+ }
+
+ if (!nachnameInput.value.trim()) {
+ nachnameInput.parentElement.classList.add('has-error');
+ isValid = false;
+ }
+
+ if (!emailRegex.test(emailInput.value.trim())) {
+ emailInput.parentElement.classList.add('has-error');
+ isValid = false;
+ }
+
+ if (passwortInput.value && passwortInput.value.length < 6) {
+ passwortInput.parentElement.classList.add('has-error');
+ isValid = false;
+ }
+
+ return isValid;
+ }
+
+ // Speichert Profilaenderungen lokal und synchronisiert auch den Benutzerkatalog.
+ function handleProfileSubmit(event) {
+ event.preventDefault();
+
+ if (!validateProfileForm()) {
+ profileFeedback.textContent = 'Bitte pruefe die markierten Felder.';
+ return;
+ }
+
+ const previousEmail = currentUser.email;
+ const nextUser = {
+ ...currentUser,
+ vorname: vornameInput.value.trim(),
+ nachname: nachnameInput.value.trim(),
+ email: emailInput.value.trim(),
+ passwort: passwortInput.value ? passwortInput.value : currentUser.passwort,
+ updatedAt: new Date().toISOString()
+ };
+
+ currentUser = nextUser;
+ localStorage.setItem(CURRENT_USER_KEY, JSON.stringify(nextUser));
+ syncUserInUserStore(previousEmail, nextUser);
+
+ // Falls sich die E-Mail geaendert hat, verschieben wir bestehende Anmeldungen auf die neue E-Mail.
+ migrateRegistrationEmail(previousEmail, nextUser.email);
+
+ passwortInput.value = '';
+ profileHeadline.textContent = `Hallo ${nextUser.vorname}`;
+ profileFeedback.textContent = 'Profil erfolgreich gespeichert.';
+ }
+
+ // Synchronisiert einen Benutzer im zentralen User-Array.
+ function syncUserInUserStore(previousEmail, nextUser) {
+ let users = [];
+
+ try {
+ const raw = localStorage.getItem(USERS_STORAGE_KEY);
+ users = raw ? JSON.parse(raw) : [];
+ } catch (error) {
+ console.error('Benutzerdaten konnten nicht gelesen werden.', error);
+ }
+
+ const nextUsers = users.filter(user => user.email !== previousEmail && user.email !== nextUser.email);
+ nextUsers.unshift(nextUser);
+ localStorage.setItem(USERS_STORAGE_KEY, JSON.stringify(nextUsers));
+ }
+
+ // Migriert bestehende Registrierungen, falls die E-Mail aktualisiert wurde.
+ function migrateRegistrationEmail(previousEmail, nextEmail) {
+ if (!previousEmail || !nextEmail || previousEmail === nextEmail) {
+ return;
+ }
+
+ const map = getRegistrationMap();
+ const existingRegistrations = Array.isArray(map[previousEmail]) ? map[previousEmail] : [];
+ const alreadyPresent = Array.isArray(map[nextEmail]) ? map[nextEmail] : [];
+
+ map[nextEmail] = Array.from(new Set([...alreadyPresent, ...existingRegistrations]));
+ delete map[previousEmail];
+
+ localStorage.setItem(REGISTRATION_STORAGE_KEY, JSON.stringify(map));
+ }
+
+ // Ermittelt gehostete Events anhand Host-E-Mail oder Host-Vorname.
+ function getMyHostedEvents(events, user) {
+ const userFirstName = normalizeText(user.vorname);
+
+ return events.filter(event => {
+ const hostEmail = normalizeText(event.hostEmail || '');
+ const hostName = normalizeText(event.host?.name || '');
+
+ if (hostEmail && hostEmail === normalizeText(user.email)) {
+ return true;
+ }
+
+ return userFirstName && hostName === userFirstName;
+ });
+ }
+
+ // Ermittelt angemeldete Events ueber die Registration-Map.
+ 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)));
+ }
+
+ // Rendert gehostete Events inkl. Zaehler.
+ function renderMyEvents(events, user) {
+ const hostedEvents = getMyHostedEvents(events, user);
+ myEventsCount.textContent = String(hostedEvents.length);
+ renderEventCards(myEventsList, hostedEvents, 'Du hast noch kein eigenes Event erstellt.', false);
+ }
+
+ // Rendert angemeldete Events inkl. Zaehler.
+ function renderMyRegistrations(events, user) {
+ const registeredEvents = getMyRegisteredEvents(events, user);
+ myRegistrationsCount.textContent = String(registeredEvents.length);
+ renderEventCards(myRegistrationsList, registeredEvents, 'Du bist aktuell bei keinem Event angemeldet.', true);
+ }
+
+ // Baut die Eventkarten fuer beide Listen in einheitlichem Markup.
+ function renderEventCards(container, events, emptyText, withUnregisterButton) {
+ container.innerHTML = '';
+
+ if (events.length === 0) {
+ const emptyElement = document.createElement('p');
+ emptyElement.className = 'profile-empty';
+ emptyElement.textContent = emptyText;
+ container.appendChild(emptyElement);
+ return;
+ }
+
+ events.forEach(event => {
+ const card = document.createElement('article');
+ card.className = 'profile-event-card';
+
+ const actionMarkup = withUnregisterButton
+ ? `
+
+ `
+ : `
Zum Event`;
+
+ card.innerHTML = `
+
+
${event.title}
+
${event.location} | ${formatEventDate(event.date)} | ${formatEventTime(event.time)}
+
+ ${actionMarkup}
+ `;
+
+ container.appendChild(card);
+ });
+ }
+
+ // Formatiert ein Eventdatum konsistent fuer die Profilkarten.
+ function formatEventDate(dateString) {
+ if (!dateString) {
+ return 'Kein Datum';
+ }
+
+ if (/^\d{4}-\d{2}-\d{2}$/.test(dateString)) {
+ const [year, month, day] = dateString.split('-');
+ const monthLabel = ['Januar', 'Februar', 'Maerz', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'][Number(month) - 1];
+ return `${Number(day)}. ${monthLabel} ${year}`;
+ }
+
+ return dateString;
+ }
+
+ // Vereinheitlicht die Zeitanzeige fuer die Profilseite.
+ function formatEventTime(timeString) {
+ if (!timeString) {
+ return 'Keine Uhrzeit';
+ }
+
+ return timeString.includes('UHR') ? timeString.replace('UHR', 'Uhr').trim() : timeString;
+ }
+
+ // Normalisiert Vergleichswerte fuer robuste String-Matches.
+ function normalizeText(value) {
+ return String(value || '').trim().toLowerCase();
+ }
+});
diff --git a/js/navigation.js b/js/navigation.js
new file mode 100644
index 0000000..ffe8264
--- /dev/null
+++ b/js/navigation.js
@@ -0,0 +1,63 @@
+document.addEventListener('DOMContentLoaded', () => {
+ const CURRENT_USER_KEY = 'socialCookingCurrentUser';
+ const navContainers = document.querySelectorAll('.nav-tab-links');
+ const currentPage = (window.location.pathname.split('/').pop() || 'index.html').toLowerCase();
+
+ // Beendet frueh, falls auf einer Seite keine Hauptnavigation vorhanden ist.
+ if (!navContainers.length) {
+ return;
+ }
+
+ // Liest den aktiven Benutzer robust aus localStorage.
+ 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;
+ }
+ }
+
+ // Baut die Navigation fuer ausgeloggte Besucher.
+ function buildLoggedOutNavigation() {
+ const loginIsActive = currentPage === 'login.html';
+ const signupIsActive = currentPage === 'signup.html';
+
+ return `
+
+ Login
+
+
+ Signup
+
+ `;
+ }
+
+ // Baut die Navigation fuer eingeloggte Benutzer.
+ function buildLoggedInNavigation() {
+ return `
+
Event finden
+
Event erstellen
+
Mein Profil
+ `;
+ }
+
+ const currentUser = getCurrentUser();
+ const nextMarkup = currentUser ? buildLoggedInNavigation() : buildLoggedOutNavigation();
+
+ // Wendet das passende Markup auf alle vorhandenen Kopf-Navigationen an.
+ navContainers.forEach(container => {
+ container.innerHTML = nextMarkup;
+ });
+});
diff --git a/js/signup.js b/js/signup.js
index f158cd4..87a1b64 100644
--- a/js/signup.js
+++ b/js/signup.js
@@ -5,6 +5,30 @@ const emailInput = document.getElementById('email');
const passwortInput = document.getElementById('passwort');
const welcomeModal = document.getElementById('welcomeModal');
+const USERS_STORAGE_KEY = 'socialCookingUsers';
+const CURRENT_USER_KEY = 'socialCookingCurrentUser';
+
+// Liest bestehende Benutzerliste robust aus localStorage.
+function getStoredUsers() {
+ try {
+ const raw = localStorage.getItem(USERS_STORAGE_KEY);
+ return raw ? JSON.parse(raw) : [];
+ } catch (error) {
+ console.error('Benutzerdaten konnten nicht gelesen werden.', error);
+ return [];
+ }
+}
+
+// Schreibt die komplette Benutzerliste in localStorage.
+function setStoredUsers(users) {
+ localStorage.setItem(USERS_STORAGE_KEY, JSON.stringify(users));
+}
+
+// Speichert den aktiven Benutzer fuer nachfolgende Seiten.
+function setCurrentUser(user) {
+ localStorage.setItem(CURRENT_USER_KEY, JSON.stringify(user));
+}
+
// Funktion zum Öffnen des Welcome Modals
function openWelcomeModal() {
welcomeModal.classList.add('show');
@@ -78,12 +102,35 @@ function validateForm(event) {
passwortGroup.classList.remove('has-error');
}
- // Wenn alle Validierungen bestanden, Modal anzeigen
+ // Wenn alle Validierungen bestanden, Benutzer speichern und Session setzen.
if (isValid) {
+ const existingUsers = getStoredUsers();
+ const emailLower = emailValue.toLowerCase();
+ const emailAlreadyUsed = existingUsers.some(user => user.email?.toLowerCase() === emailLower);
+
+ if (emailAlreadyUsed) {
+ emailGroup.classList.add('has-error');
+ document.getElementById('emailError').textContent = 'Diese E-Mail ist bereits registriert. Bitte nutze den Login.';
+ return;
+ }
+
+ const newUser = {
+ id: Date.now(),
+ vorname: vornameValue,
+ nachname: nachnameValue,
+ email: emailValue,
+ passwort: passwortValue,
+ createdAt: new Date().toISOString(),
+ source: 'signup'
+ };
+
+ setStoredUsers([newUser, ...existingUsers]);
+ setCurrentUser(newUser);
+
openWelcomeModal();
- // Hier würde später die Registrierung zum Backend gesendet
+ // Hier würde spaeter die Registrierung zum Backend gesendet.
- // Weiterleitung zur event overview Page
+ // Weiterleitung zur Event-Overview-Seite.
window.location.href = 'event_overview.html';
}
}
diff --git a/login.html b/login.html
index 16d2ea7..67f3daa 100644
--- a/login.html
+++ b/login.html
@@ -9,6 +9,7 @@
+
@@ -20,9 +21,8 @@
diff --git a/my_profil.html b/my_profil.html
new file mode 100644
index 0000000..f5610a9
--- /dev/null
+++ b/my_profil.html
@@ -0,0 +1,102 @@
+
+
+
+