phase 2
This commit is contained in:
71
src/store/auth-store.ts
Normal file
71
src/store/auth-store.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { create } from 'zustand'
|
||||
import { supabase } from '@/lib/supabase'
|
||||
import type { User } from '@/types'
|
||||
|
||||
interface AuthState {
|
||||
user: User | null
|
||||
isLoading: boolean
|
||||
login: (email: string, password: string) => Promise<void>
|
||||
register: (name: string, email: string, password: string) => Promise<void>
|
||||
logout: () => Promise<void>
|
||||
initialize: () => Promise<void>
|
||||
}
|
||||
|
||||
function sessionToUser(session: { user: { id: string; email?: string; user_metadata?: { name?: string } } } | null): User | null {
|
||||
if (!session) return null
|
||||
const { id, email, user_metadata } = session.user
|
||||
const name = user_metadata?.name ?? email?.split('@')[0] ?? 'Người dùng'
|
||||
return { id, email: email ?? '', name }
|
||||
}
|
||||
|
||||
export const useAuthStore = create<AuthState>((set) => ({
|
||||
user: null,
|
||||
isLoading: true,
|
||||
|
||||
initialize: async () => {
|
||||
set({ isLoading: true })
|
||||
|
||||
// Restore existing session (JWT in localStorage via Supabase SDK)
|
||||
const { data: { session } } = await supabase.auth.getSession()
|
||||
set({ user: sessionToUser(session), isLoading: false })
|
||||
|
||||
// Keep state in sync across tabs and token refresh
|
||||
supabase.auth.onAuthStateChange((_event, newSession) => {
|
||||
set({ user: sessionToUser(newSession), isLoading: false })
|
||||
})
|
||||
},
|
||||
|
||||
login: async (email, password) => {
|
||||
const { error } = await supabase.auth.signInWithPassword({ email, password })
|
||||
if (error) throw new Error(mapAuthError(error.message))
|
||||
// onAuthStateChange fires and updates user state
|
||||
},
|
||||
|
||||
register: async (name, email, password) => {
|
||||
const { error } = await supabase.auth.signUp({
|
||||
email,
|
||||
password,
|
||||
options: { data: { name } },
|
||||
})
|
||||
if (error) throw new Error(mapAuthError(error.message))
|
||||
// onAuthStateChange fires and updates user state
|
||||
},
|
||||
|
||||
logout: async () => {
|
||||
await supabase.auth.signOut()
|
||||
// onAuthStateChange fires → user set to null
|
||||
},
|
||||
}))
|
||||
|
||||
function mapAuthError(msg: string): string {
|
||||
if (msg.includes('already registered') || msg.includes('already exists')) {
|
||||
return 'Email này đã được sử dụng. Vui lòng đăng nhập.'
|
||||
}
|
||||
if (msg.includes('Invalid login credentials') || msg.includes('invalid_credentials')) {
|
||||
return 'Sai email hoặc mật khẩu. Vui lòng kiểm tra lại.'
|
||||
}
|
||||
if (msg.includes('Email not confirmed')) {
|
||||
return 'Email chưa được xác nhận.'
|
||||
}
|
||||
return 'Đã có lỗi xảy ra. Vui lòng thử lại.'
|
||||
}
|
||||
Reference in New Issue
Block a user