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:
2026-01-16 12:37:22 +01:00
parent ea57ce6d28
commit 68407fe12b
12 changed files with 1520 additions and 26 deletions

View File

@@ -4,6 +4,20 @@
*/
import { validateUserCode } from "../helpers/validator.js";
// Auth sync - lazy loaded to avoid circular dependencies
let authModule = null;
async function getAuthModule() {
if (!authModule) {
try {
authModule = await import("../auth.js");
} catch (e) {
// Auth module not available, skip cloud sync
return null;
}
}
return authModule;
}
export class LessonEngine {
constructor() {
this.currentLesson = null;
@@ -484,7 +498,7 @@ export class LessonEngine {
}
/**
* Save progress to localStorage
* Save progress to localStorage and optionally sync to cloud
*/
saveUserProgress() {
try {
@@ -494,11 +508,24 @@ export class LessonEngine {
timestamp: new Date().toISOString()
};
localStorage.setItem("codeCrispies.progress", JSON.stringify(progressData));
// Trigger cloud sync if logged in (debounced)
this.triggerCloudSync();
} catch (e) {
console.error("Error saving progress:", e);
}
}
/**
* Trigger cloud sync if user is logged in (debounced)
*/
async triggerCloudSync() {
const auth = await getAuthModule();
if (auth?.isLoggedIn()) {
auth.debouncedSyncToCloud();
}
}
/**
* Load progress from localStorage
*/
@@ -521,11 +548,14 @@ export class LessonEngine {
}
/**
* Save user code to localStorage
* Save user code to localStorage and optionally sync to cloud
*/
saveUserCodeToStorage() {
try {
localStorage.setItem("codeCrispies.userCode", JSON.stringify(Array.from(this.userCodeMap.entries())));
// Trigger cloud sync if logged in (debounced)
this.triggerCloudSync();
} catch (e) {
console.error("Error saving user code:", e);
}