Refactor database handling to require PostgreSQL connection, removing fallback to JSON. Implement error handling for database unavailability in key files. Update .env.example to reflect mandatory DATABASE_URL for local development. Remove Firebase configuration and related code from the project.
This commit is contained in:
+16
-92
@@ -61,37 +61,23 @@
|
||||
})();
|
||||
|
||||
|
||||
// ── Newsletter subscription logic ──────────────────────────
|
||||
// ── Newsletter (mailto) ────────────────────────────────────
|
||||
function handleSubscribe(e) {
|
||||
e.preventDefault();
|
||||
var emailInput = document.getElementById('newsletterEmail');
|
||||
var feedback = document.getElementById('newsletterFeedback');
|
||||
var form = document.getElementById('newsletterForm');
|
||||
var btn = form.querySelector('button');
|
||||
var email = emailInput.value.trim();
|
||||
|
||||
if (!email) return;
|
||||
|
||||
btn.disabled = true;
|
||||
feedback.className = 'newsletter-feedback';
|
||||
feedback.textContent = '';
|
||||
var subject = encodeURIComponent('FlixCooks Newsletter');
|
||||
var body = encodeURIComponent('Please add me to the newsletter: ' + email);
|
||||
window.location.href = 'mailto:<?php echo e($contactEmail); ?>?subject=' + subject + '&body=' + body;
|
||||
|
||||
window.db.collection('subscribers').doc(email.toLowerCase()).set({
|
||||
email: email.toLowerCase(),
|
||||
subscribedAt: firebase.firestore.FieldValue.serverTimestamp(),
|
||||
status: 'active'
|
||||
})
|
||||
.then(function() {
|
||||
form.classList.add('success');
|
||||
emailInput.disabled = true;
|
||||
feedback.className = 'newsletter-feedback success';
|
||||
feedback.textContent = '<?php echo $langCode === "de" ? "Erfolgreich abonniert!" : "Successfully subscribed!"; ?>';
|
||||
})
|
||||
.catch(function(error) {
|
||||
btn.disabled = false;
|
||||
feedback.className = 'newsletter-feedback error';
|
||||
feedback.textContent = '<?php echo $langCode === "de" ? "Fehler: " : "Error: "; ?>' + error.message;
|
||||
});
|
||||
form.classList.add('success');
|
||||
feedback.className = 'newsletter-feedback success';
|
||||
feedback.textContent = '<?php echo $langCode === "de" ? "E-Mail-Programm geöffnet – bitte absenden." : "Email client opened — please send."; ?>';
|
||||
}
|
||||
|
||||
// ── Guest Modal Logic ──────────────────────────────────────
|
||||
@@ -121,33 +107,12 @@ document.addEventListener('click', function(e) {
|
||||
}
|
||||
});
|
||||
|
||||
// ── Favorites Toggle & Management ───────────────────────────
|
||||
var currentUser = null;
|
||||
var userFavSlugs = new Set();
|
||||
|
||||
function syncFavorites(uid) {
|
||||
window.db.collection('user_favorites').where('userId', '==', uid).get()
|
||||
.then(function(snapshot) {
|
||||
userFavSlugs.clear();
|
||||
snapshot.forEach(function(doc) {
|
||||
userFavSlugs.add(doc.data().recipeSlug);
|
||||
});
|
||||
updateHeartStates();
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.error("Error syncing favorites: ", err);
|
||||
});
|
||||
}
|
||||
|
||||
function clearFavorites() {
|
||||
userFavSlugs.clear();
|
||||
updateHeartStates();
|
||||
}
|
||||
|
||||
// ── Favorites (localStorage) ───────────────────────────────
|
||||
function updateHeartStates() {
|
||||
if (!window.fcLocal) return;
|
||||
document.querySelectorAll('.btn-favorite').forEach(function(btn) {
|
||||
var slug = btn.getAttribute('data-slug');
|
||||
if (userFavSlugs.has(slug)) {
|
||||
if (slug && window.fcLocal.hasFavorite(slug)) {
|
||||
btn.classList.add('active');
|
||||
} else {
|
||||
btn.classList.remove('active');
|
||||
@@ -156,43 +121,12 @@ function updateHeartStates() {
|
||||
}
|
||||
|
||||
function toggleFavorite(slug, btn) {
|
||||
if (!currentUser) {
|
||||
if (!window.fcLocal) {
|
||||
openGuestModal();
|
||||
return;
|
||||
}
|
||||
|
||||
var docId = currentUser.uid + '_' + slug;
|
||||
var docRef = window.db.collection('user_favorites').doc(docId);
|
||||
|
||||
if (userFavSlugs.has(slug)) {
|
||||
// Optimistic UI update
|
||||
userFavSlugs.delete(slug);
|
||||
btn.classList.remove('active');
|
||||
|
||||
docRef.delete()
|
||||
.catch(function(err) {
|
||||
console.error("Error removing favorite: ", err);
|
||||
// Rollback
|
||||
userFavSlugs.add(slug);
|
||||
btn.classList.add('active');
|
||||
});
|
||||
} else {
|
||||
// Optimistic UI update
|
||||
userFavSlugs.add(slug);
|
||||
btn.classList.add('active');
|
||||
|
||||
docRef.set({
|
||||
userId: currentUser.uid,
|
||||
recipeSlug: slug,
|
||||
createdAt: firebase.firestore.FieldValue.serverTimestamp()
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.error("Error adding favorite: ", err);
|
||||
// Rollback
|
||||
userFavSlugs.delete(slug);
|
||||
btn.classList.remove('active');
|
||||
});
|
||||
}
|
||||
window.fcLocal.toggleFavorite(slug);
|
||||
updateHeartStates();
|
||||
}
|
||||
|
||||
// Hook up event listeners to all favorite buttons dynamically
|
||||
@@ -206,18 +140,8 @@ document.addEventListener('click', function(e) {
|
||||
}
|
||||
});
|
||||
|
||||
// Setup Auth state observer for favorites
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
if (window.auth) {
|
||||
window.auth.onAuthStateChanged(function(user) {
|
||||
currentUser = user;
|
||||
if (user) {
|
||||
syncFavorites(user.uid);
|
||||
} else {
|
||||
clearFavorites();
|
||||
}
|
||||
});
|
||||
}
|
||||
updateHeartStates();
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@@ -228,10 +152,10 @@ window.addEventListener('DOMContentLoaded', function() {
|
||||
<button class="guest-modal-close" onclick="closeGuestModal()" aria-label="Close modal">×</button>
|
||||
<div class="guest-modal-icon">❤️</div>
|
||||
<h3><?php echo $langCode === 'de' ? 'Lieblingsrezept speichern' : 'Save your favorite recipe'; ?></h3>
|
||||
<p><?php echo $langCode === 'de' ? 'Erstelle ein kostenloses Konto oder melde dich an, um Rezepte in deinen Favoriten zu speichern und deine Ernährungsziele zu verwalten.' : 'Create a free account or login to save recipes to your favorites and manage your dietary goals.'; ?></p>
|
||||
<p><?php echo $langCode === 'de' ? 'Speichere Rezepte lokal in deinem Browser und verwalte dein Ernährungsziel im Profil.' : 'Save recipes locally in your browser and manage your dietary goal in your profile.'; ?></p>
|
||||
<div class="guest-modal-actions">
|
||||
<a class="btn-reveal" href="/login.php<?php echo $langSuffix; ?>">
|
||||
<span class="btn-reveal-text"><?php echo $langCode === 'de' ? 'Jetzt Anmelden' : 'Login / Register'; ?></span>
|
||||
<span class="btn-reveal-text"><?php echo $langCode === 'de' ? 'Zum Profil' : 'Go to profile'; ?></span>
|
||||
<span class="btn-reveal-arrow">→</span>
|
||||
</a>
|
||||
<button class="underline-link" onclick="closeGuestModal()"><?php echo $langCode === 'de' ? 'Später' : 'Maybe later'; ?></button>
|
||||
|
||||
Reference in New Issue
Block a user