import { supabase } from './supabase' import type { Profile } from './database.types' import { autoJoinActiveCampaigns } from './participants' // --- Sign up / Sign in --- export async function signInWithKakao() { // Kakao's account_email scope requires business app verification (비즈 앱). // For the pilot we skip it and only request nickname + profile image. // Profile.email stays null for Kakao users; ensureProfile handles that. const { data, error } = await supabase.auth.signInWithOAuth({ provider: 'kakao', options: { redirectTo: `${window.location.origin}/auth/callback`, scopes: 'profile_nickname profile_image', }, }) if (error) throw error return data } // Ensure a profile row exists for the current user. // Used after OAuth sign-in (Kakao) where signUpWithEmail's upsert path is skipped. export async function ensureProfile( userId: string, fallbackEmail: string | null, metadata: Record = {} ): Promise { const { data: existing } = await supabase .from('profiles') .select('*') .eq('id', userId) .maybeSingle() if (existing) return existing as Profile const displayName = (metadata.name as string) || (metadata.full_name as string) || (metadata.nickname as string) || (metadata.user_name as string) || (fallbackEmail ? fallbackEmail.split('@')[0] : '익명') const profile: Profile = { id: userId, display_name: displayName, email: fallbackEmail, region: '제주', role: 'citizen', created_at: new Date().toISOString(), updated_at: new Date().toISOString(), } await upsertProfile(profile) // Auto-join active campaigns for new users autoJoinActiveCampaigns(userId).catch(console.error) return profile } export async function signInWithEmail(email: string, password: string) { const { data, error } = await supabase.auth.signInWithPassword({ email, password, }) if (error) throw error return data } export async function signUpWithEmail( email: string, password: string, displayName: string ) { const { data, error } = await supabase.auth.signUp({ email, password, options: { data: { display_name: displayName }, }, }) if (error) throw error // Create profile row + auto-join active campaigns if (data.user) { await upsertProfile({ id: data.user.id, display_name: displayName, email, region: '제주', role: 'citizen', created_at: new Date().toISOString(), updated_at: new Date().toISOString(), }) autoJoinActiveCampaigns(data.user.id).catch(console.error) } return data } export async function signOut() { const { error } = await supabase.auth.signOut() if (error) throw error } // --- Profile --- export async function getProfile(): Promise { const { data: { user }, } = await supabase.auth.getUser() if (!user) return null const { data, error } = await supabase .from('profiles') .select('*') .eq('id', user.id) .single() if (error) return null return data as Profile } async function upsertProfile(profile: Profile) { const { error } = await supabase.from('profiles').upsert(profile) if (error) throw error } // --- Auth state listener --- export function onAuthStateChange( callback: (event: string, session: unknown) => void ) { return supabase.auth.onAuthStateChange(callback) }