feat: add authentication, cloud sync, and GDPR compliance
Authentication & Cloud Sync: - Add Supabase integration for auth (email/password, Google, GitHub OAuth) - Add cloud progress sync for logged-in users - Add account deletion feature with confirmation dialog - Auth is optional - anonymous users can still use localStorage UI Improvements: - Add dark-themed account section in sidebar - Show user email in header when logged in - Add signup success feedback message - Update landing page: remove cloud sync from Coming Soon, add Code Challenges - Update benefit text to mention optional cloud sync GDPR Compliance: - Add Privacy Policy dialog with full GDPR-compliant content - Add Imprint dialog with legal contact information - Add footer links for Privacy and Imprint - All legal content translated to 6 languages (en, de, pl, es, ar, uk) Files added: - src/supabase.js - Supabase client with auth and progress sync helpers - src/auth.js - Authentication logic and form handlers - supabase-setup.sql - Database schema and RLS policies
This commit is contained in:
41
src/app.js
41
src/app.js
@@ -6,6 +6,7 @@ import { initI18n, t, getLanguage, setLanguage, applyTranslations } from "./i18n
|
||||
import { parseHash, updateHash, replaceHash, getShareableUrl, RouteType, navigateTo } from "./helpers/router.js";
|
||||
import { sections, getSection, getModuleSection, getModulesBySection } from "./config/sections.js";
|
||||
import { getRandomTemplate } from "./config/playground-templates.js";
|
||||
import { initAuth } from "./auth.js";
|
||||
|
||||
// CodeMirror imports for syntax highlighting
|
||||
import { EditorState } from "@codemirror/state";
|
||||
@@ -2423,6 +2424,9 @@ function init() {
|
||||
// Initialize URL router for shareable links
|
||||
initRouter();
|
||||
|
||||
// Initialize authentication
|
||||
initAuth(lessonEngine);
|
||||
|
||||
// Sidebar controls
|
||||
elements.menuBtn.addEventListener("click", openSidebar);
|
||||
elements.closeSidebar.addEventListener("click", closeSidebar);
|
||||
@@ -2485,6 +2489,31 @@ function init() {
|
||||
});
|
||||
elements.copyUrlBtn.addEventListener("click", copyShareUrl);
|
||||
|
||||
// Legal dialogs (Privacy & Imprint)
|
||||
const privacyDialog = document.getElementById("privacy-dialog");
|
||||
const imprintDialog = document.getElementById("imprint-dialog");
|
||||
|
||||
document.querySelectorAll(".privacy-link").forEach((btn) => {
|
||||
btn.addEventListener("click", () => privacyDialog?.showModal());
|
||||
});
|
||||
document.querySelectorAll(".imprint-link").forEach((btn) => {
|
||||
btn.addEventListener("click", () => imprintDialog?.showModal());
|
||||
});
|
||||
|
||||
document.querySelector(".privacy-dialog-close")?.addEventListener("click", () => {
|
||||
privacyDialog?.close();
|
||||
});
|
||||
document.querySelector(".imprint-dialog-close")?.addEventListener("click", () => {
|
||||
imprintDialog?.close();
|
||||
});
|
||||
|
||||
privacyDialog?.addEventListener("click", (e) => {
|
||||
if (e.target === privacyDialog) privacyDialog.close();
|
||||
});
|
||||
imprintDialog?.addEventListener("click", (e) => {
|
||||
if (e.target === imprintDialog) imprintDialog.close();
|
||||
});
|
||||
|
||||
// Settings
|
||||
elements.disableFeedbackToggle.addEventListener("change", (e) => {
|
||||
state.userSettings.disableFeedbackErrors = !e.target.checked;
|
||||
@@ -2567,10 +2596,18 @@ function init() {
|
||||
// Newsletter form submission
|
||||
const newsletterForm = document.getElementById("newsletter-form");
|
||||
const newsletterThanks = document.getElementById("newsletter-thanks");
|
||||
newsletterForm?.addEventListener("submit", (e) => {
|
||||
newsletterForm?.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
const email = document.getElementById("newsletter-email")?.value;
|
||||
const emailInput = document.getElementById("newsletter-email");
|
||||
const email = emailInput?.value;
|
||||
if (email) {
|
||||
// Import newsletter helper dynamically to avoid loading Supabase if not needed
|
||||
try {
|
||||
const { newsletter } = await import("./supabase.js");
|
||||
await newsletter.subscribe(email);
|
||||
} catch (err) {
|
||||
console.error("Newsletter subscription error:", err);
|
||||
}
|
||||
track("newsletter_signup", { email: email });
|
||||
newsletterForm.classList.add("hidden");
|
||||
newsletterThanks?.classList.remove("hidden");
|
||||
|
||||
Reference in New Issue
Block a user