Add snackbar feedback, logout modal, profile pill nav, calendar styling, fix image paths and signup flow
This commit is contained in:
parent
221aa90649
commit
4b54c48311
8
.vscode/settings.json
vendored
Normal file
8
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"chat.tools.terminal.autoApprove": {
|
||||
"git remote": true,
|
||||
"git push": true,
|
||||
"ssh": true,
|
||||
"git add": true
|
||||
}
|
||||
}
|
||||
@ -147,6 +147,33 @@
|
||||
outline-offset: 1px;
|
||||
}
|
||||
|
||||
.meta-filter input[type="date"] {
|
||||
color-scheme: light;
|
||||
accent-color: var(--olive);
|
||||
}
|
||||
|
||||
.meta-filter input[type="date"]::-webkit-calendar-picker-indicator {
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
filter: invert(35%) sepia(60%) saturate(600%) hue-rotate(22deg) brightness(90%) contrast(95%);
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.meta-filter input[type="date"]::-webkit-calendar-picker-indicator:hover {
|
||||
background-color: var(--olive-light);
|
||||
}
|
||||
|
||||
.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='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%236B6B05' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 12px center;
|
||||
padding-right: 36px;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
Overview Event Cards
|
||||
--------------------------------------------------------- */
|
||||
|
||||
@ -327,6 +327,114 @@ p {
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
/* Modal / Popup */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
animation: modalFadeIn 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes modalFadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
.modal.show {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: var(--white);
|
||||
padding: 40px;
|
||||
border-radius: var(--radius-lg);
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
||||
max-width: 500px;
|
||||
width: 90%;
|
||||
text-align: center;
|
||||
animation: modalSlideIn 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes modalSlideIn {
|
||||
from { transform: translateY(-50px); opacity: 0; }
|
||||
to { transform: translateY(0); opacity: 1; }
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
position: relative;
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.modal-header h2 {
|
||||
color: var(--olive);
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
font-size: 28px;
|
||||
color: var(--black);
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
color: var(--black);
|
||||
font-size: 1rem;
|
||||
line-height: 1.6;
|
||||
margin-bottom: var(--space-6);
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
gap: var(--space-2);
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Snackbar */
|
||||
.snackbar {
|
||||
position: fixed;
|
||||
bottom: 30px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) translateY(100px);
|
||||
background: var(--olive);
|
||||
color: var(--white);
|
||||
padding: var(--space-3) var(--space-6);
|
||||
border-radius: var(--radius-pill);
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
font-family: var(--font-main);
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
|
||||
opacity: 0;
|
||||
transition: transform 0.4s ease, opacity 0.4s ease;
|
||||
z-index: 9999;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.snackbar--visible {
|
||||
transform: translateX(-50%) translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.snackbar--danger {
|
||||
background: var(--tomato);
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.footer {
|
||||
display: flex;
|
||||
|
||||
@ -64,8 +64,13 @@
|
||||
<section id="event-grid" class="event-list"></section>
|
||||
</main>
|
||||
|
||||
<!-- Page logic: data loading, filtering and card rendering -->
|
||||
<!-- Seitenlogik: Daten laden, filtern und Event-Karten rendern -->
|
||||
<script src="js/event_overview.js"></script>
|
||||
|
||||
<!-- Snackbar: Feedback bei An-/Abmeldung -->
|
||||
<div class="snackbar" id="snackbar"></div>
|
||||
|
||||
<!-- Instagram Einladung -->
|
||||
<div class="instagram-invite">
|
||||
<a href="https://www.instagram.com" target="_blank" rel="noopener noreferrer" class="instagram-invite__link">
|
||||
<img src="assets/Icon_instagram.png" alt="Instagram" class="instagram-invite__icon" />
|
||||
|
||||
@ -9,7 +9,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const filterButtons = document.querySelectorAll('.category-item');
|
||||
const locationFilter = document.getElementById('location-filter');
|
||||
const dateFilter = document.getElementById('date-filter');
|
||||
const locationIconPath = 'assets/location-pin.svg';
|
||||
const locationIconPath = 'assets/icon_location-pin.svg';
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// In-memory state for fetched events and currently active category.
|
||||
@ -329,7 +329,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
<div class="empty-state">
|
||||
<p class="empty-state-kicker">Keine Treffer</p>
|
||||
<h3>Schade, aktuell gibt es hier keine Events.</h3>
|
||||
<p>Starte dein eigenes Dinner und bringe die Community an deinen Tisch.</p>
|
||||
<p>Starte dein eigenes Event und bringe die Community an deinen Tisch.</p>
|
||||
<a class="empty-state-link" href="event_create.html">
|
||||
<button class="empty-state-btn" type="button">Event erstellen</button>
|
||||
</a>
|
||||
@ -435,12 +435,29 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
: [];
|
||||
const idSet = new Set(currentIds);
|
||||
|
||||
// Abmeldung: Benutzer vom Event entfernen und Snackbar anzeigen.
|
||||
if (action === 'unregister') {
|
||||
idSet.delete(Number(event.id));
|
||||
const snackbar = document.getElementById('snackbar');
|
||||
if (snackbar) {
|
||||
snackbar.textContent = 'Du wurdest erfolgreich abgemeldet.';
|
||||
snackbar.classList.add('snackbar--danger', 'snackbar--visible');
|
||||
setTimeout(() => {
|
||||
snackbar.classList.remove('snackbar--visible');
|
||||
setTimeout(() => snackbar.classList.remove('snackbar--danger'), 400);
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
// Anmeldung: Benutzer zum Event hinzufuegen und Snackbar anzeigen.
|
||||
if (action === 'register' && !isFull && !isRegistrationClosed) {
|
||||
idSet.add(Number(event.id));
|
||||
const snackbar = document.getElementById('snackbar');
|
||||
if (snackbar) {
|
||||
snackbar.textContent = 'Du wurdest erfolgreich angemeldet.';
|
||||
snackbar.classList.add('snackbar--visible');
|
||||
setTimeout(() => snackbar.classList.remove('snackbar--visible'), 3000);
|
||||
}
|
||||
}
|
||||
|
||||
nextRegistrationMap[currentUser.email] = Array.from(idSet);
|
||||
|
||||
@ -148,11 +148,24 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
|
||||
logoutButton.addEventListener('click', () => {
|
||||
localStorage.removeItem(CURRENT_USER_KEY);
|
||||
window.location.href = 'login.html';
|
||||
const logoutModal = document.getElementById('logoutModal');
|
||||
logoutModal.classList.add('show');
|
||||
document.body.style.overflow = 'hidden';
|
||||
});
|
||||
}
|
||||
|
||||
// Globale Funktionen fuer das Logout-Modal.
|
||||
window.closeLogoutModal = function() {
|
||||
const logoutModal = document.getElementById('logoutModal');
|
||||
logoutModal.classList.remove('show');
|
||||
document.body.style.overflow = 'auto';
|
||||
};
|
||||
|
||||
window.confirmLogout = function() {
|
||||
localStorage.removeItem(CURRENT_USER_KEY);
|
||||
window.location.href = 'index.html';
|
||||
};
|
||||
|
||||
// Reagiert auf Aktionen in der Liste "Meine Events" per Event Delegation.
|
||||
function handleHostedListClick(event) {
|
||||
const target = event.target;
|
||||
@ -219,6 +232,17 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
|
||||
unregisterFromEvent(eventId, currentUser.email);
|
||||
|
||||
// Snackbar: Feedback bei erfolgreicher Abmeldung.
|
||||
const snackbar = document.getElementById('snackbar');
|
||||
if (snackbar) {
|
||||
snackbar.textContent = 'Du wurdest erfolgreich abgemeldet.';
|
||||
snackbar.classList.add('snackbar--danger', 'snackbar--visible');
|
||||
setTimeout(() => {
|
||||
snackbar.classList.remove('snackbar--visible');
|
||||
setTimeout(() => snackbar.classList.remove('snackbar--danger'), 400);
|
||||
}, 3000);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -31,8 +31,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const signupIsActive = currentPage === 'signup.html';
|
||||
const isIndex = currentPage === 'index.html' || currentPage === '';
|
||||
|
||||
// Auf der Startseite nur Login anzeigen.
|
||||
if (isIndex) {
|
||||
// Auf der Startseite, Login und Signup nur Login anzeigen.
|
||||
if (isIndex || loginIsActive || signupIsActive) {
|
||||
return `
|
||||
<a
|
||||
class="button-small"
|
||||
@ -61,20 +61,23 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
>
|
||||
Signup
|
||||
</a>
|
||||
`;`;
|
||||
`;
|
||||
}
|
||||
|
||||
// Baut die Navigation fuer eingeloggte Benutzer.
|
||||
function buildLoggedInNavigation() {
|
||||
function buildLoggedInNavigation(user) {
|
||||
const initial = (user.vorname || 'U').charAt(0).toUpperCase();
|
||||
const isEventOverview = currentPage === 'event_overview.html';
|
||||
|
||||
return `
|
||||
<a class="nav-tab" href="event_overview.html">Event finden</a>
|
||||
<a class="nav-tab" href="event_create.html">Event erstellen</a>
|
||||
<a class="button-small" href="my_profil.html" aria-label="Mein Profil">Mein Profil</a>
|
||||
${isEventOverview ? '' : '<a class="nav-tab" href="event_overview.html">Event finden</a>'}
|
||||
<a class="button-small" href="event_create.html">Event erstellen</a>
|
||||
<a class="profile-pill" href="my_profil.html" aria-label="Mein Profil" title="${user.vorname || 'Profil'}">${initial}</a>
|
||||
`;
|
||||
}
|
||||
|
||||
const currentUser = getCurrentUser();
|
||||
const nextMarkup = currentUser ? buildLoggedInNavigation() : buildLoggedOutNavigation();
|
||||
const nextMarkup = currentUser ? buildLoggedInNavigation(currentUser) : buildLoggedOutNavigation();
|
||||
|
||||
// Wendet das passende Markup auf alle vorhandenen Kopf-Navigationen an.
|
||||
navContainers.forEach(container => {
|
||||
|
||||
@ -46,6 +46,7 @@ function openWelcomeModal() {
|
||||
function closeWelcomeModal() {
|
||||
welcomeModal.classList.remove('show');
|
||||
document.body.style.overflow = 'auto';
|
||||
window.location.href = 'event_overview.html';
|
||||
}
|
||||
|
||||
// Hauptfunktion fuer Formularvalidierung und Speicherung.
|
||||
@ -138,10 +139,7 @@ function validateForm(event) {
|
||||
setCurrentUser(newUser);
|
||||
|
||||
openWelcomeModal();
|
||||
// Hier koennte spaeter ein echter API-Call zum Backend stehen.
|
||||
|
||||
// Weiterleitung zur Event-Overview-Seite.
|
||||
window.location.href = 'event_overview.html';
|
||||
// Weiterleitung erfolgt beim Klick auf "Weiter zu den Events".
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -20,8 +20,7 @@
|
||||
<img src="assets/logo_invite.svg" alt="Invité">
|
||||
</a>
|
||||
<nav class="nav-tab-links" aria-label="Hauptnavigation">
|
||||
<a class="button-small auth-nav-button auth-nav-button--active" href="login.html" aria-label="Login" aria-current="page">Login</a>
|
||||
<a class="button-small auth-nav-button auth-nav-button--default" href="signup.html" aria-label="Signup">Signup</a>
|
||||
<a class="button-small" href="login.html" aria-label="Login">Login</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
@ -30,7 +29,7 @@
|
||||
<div class="main-content">
|
||||
<div class="container">
|
||||
<div class="image-section">
|
||||
<img src="assets/cooking.jpg" alt="Social Cooking">
|
||||
<img src="assets/index_cooking.jpg" alt="Social Cooking">
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
|
||||
@ -103,6 +103,26 @@
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<!-- Logout Confirmation Modal -->
|
||||
<div id="logoutModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close-btn" onclick="closeLogoutModal()">×</button>
|
||||
<h2>Abmelden?</h2>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Bist du sicher, dass du dich abmelden möchtest?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="button button--outline" type="button" onclick="closeLogoutModal()">Abbrechen</button>
|
||||
<button class="button" type="button" onclick="confirmLogout()">Abmelden</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Snackbar: Feedback bei Abmeldung von Events -->
|
||||
<div class="snackbar" id="snackbar"></div>
|
||||
|
||||
<script src="js/my_profil.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
11
signup.html
11
signup.html
@ -20,8 +20,7 @@
|
||||
<img src="assets/logo_invite.svg" alt="Invite Logo">
|
||||
</a>
|
||||
<nav class="nav-tab-links" aria-label="Hauptnavigation">
|
||||
<a class="button-small auth-nav-button auth-nav-button--default" href="login.html" aria-label="Login">Login</a>
|
||||
<a class="button-small auth-nav-button auth-nav-button--active" href="signup.html" aria-label="Signup" aria-current="page">Signup</a>
|
||||
<a class="button-small" href="login.html" aria-label="Login">Login</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
@ -30,7 +29,7 @@
|
||||
<div class="main-content">
|
||||
<div class="container">
|
||||
<div class="image-section">
|
||||
<img src="assets/cooking.jpg" alt="Social Cooking">
|
||||
<img src="assets/index_cooking.jpg" alt="Social Cooking">
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
@ -81,13 +80,13 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close-btn" onclick="closeWelcomeModal()">×</button>
|
||||
<h2>🎉 Willkommen bei Invité!</h2>
|
||||
<h2>Konto erfolgreich erstellt!</h2>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Hier findest du die Übersicht zu den aktuellsten Events.
|
||||
Willkommen bei Invité! Dein Account wurde erfolgreich erstellt. Entdecke jetzt die neuesten Events in deiner Nähe.
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-primary" onclick="closeWelcomeModal()">Weiter zu den Events</button>
|
||||
<button class="button" onclick="closeWelcomeModal()">Weiter zu den Events</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user