diff --git a/client/lib/mock-auth.ts b/client/lib/mock-auth.ts new file mode 100644 index 00000000..1bdc468f --- /dev/null +++ b/client/lib/mock-auth.ts @@ -0,0 +1,161 @@ +// Mock authentication service for development when Supabase is not available +interface MockUser { + id: string; + email: string; + created_at: string; +} + +interface MockSession { + user: MockUser; + access_token: string; +} + +interface MockProfile { + id: string; + username: string; + email: string; + role: string; + onboarded: boolean; + full_name?: string; + bio?: string; + level: number; + total_xp: number; + avatar_url?: string; + created_at: string; + updated_at: string; +} + +class MockAuthService { + private currentUser: MockUser | null = null; + private currentSession: MockSession | null = null; + private profiles: Map = new Map(); + + constructor() { + // Load from localStorage if available + const savedUser = localStorage.getItem('mock_user'); + const savedProfile = localStorage.getItem('mock_profile'); + + if (savedUser) { + this.currentUser = JSON.parse(savedUser); + if (this.currentUser) { + this.currentSession = { + user: this.currentUser, + access_token: 'mock_token_' + Date.now() + }; + } + } + + if (savedProfile) { + const profile = JSON.parse(savedProfile); + this.profiles.set(profile.id, profile); + } + } + + async signInWithPassword(email: string, password: string) { + // Mock validation - accept any email/password for demo + if (!email || !password) { + throw new Error('Email and password are required'); + } + + const user: MockUser = { + id: 'mock_user_' + email.replace(/[^a-z0-9]/gi, '_'), + email, + created_at: new Date().toISOString() + }; + + this.currentUser = user; + this.currentSession = { + user, + access_token: 'mock_token_' + Date.now() + }; + + // Save to localStorage + localStorage.setItem('mock_user', JSON.stringify(user)); + + return { + data: { + user, + session: this.currentSession + }, + error: null + }; + } + + async signOut() { + this.currentUser = null; + this.currentSession = null; + localStorage.removeItem('mock_user'); + localStorage.removeItem('mock_profile'); + + return { error: null }; + } + + async getUser() { + return { + data: { user: this.currentUser }, + error: null + }; + } + + async getSession() { + return { + data: { session: this.currentSession }, + error: null + }; + } + + // Mock database operations + async getUserProfile(userId: string): Promise { + return this.profiles.get(userId) || null; + } + + async updateProfile(userId: string, updates: Partial): Promise { + let profile = this.profiles.get(userId); + + if (!profile) { + // Create new profile + profile = { + id: userId, + username: updates.username || this.currentUser?.email?.split('@')[0] || 'user', + email: this.currentUser?.email || '', + role: 'member', + onboarded: true, + level: 1, + total_xp: 0, + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + ...updates + }; + } else { + // Update existing + profile = { + ...profile, + ...updates, + updated_at: new Date().toISOString() + }; + } + + this.profiles.set(userId, profile); + localStorage.setItem('mock_profile', JSON.stringify(profile)); + + return profile; + } + + onAuthStateChange(callback: (event: string, session: MockSession | null) => void) { + // Immediately call with current state + setTimeout(() => { + callback(this.currentSession ? 'SIGNED_IN' : 'SIGNED_OUT', this.currentSession); + }, 100); + + // Return unsubscribe function + return { + data: { + subscription: { + unsubscribe: () => {} + } + } + }; + } +} + +export const mockAuth = new MockAuthService();