This commit is contained in:
2026-04-12 18:54:59 +07:00
parent 28e866a64e
commit ec3d400e8a
71 changed files with 7888 additions and 333 deletions

71
src/store/auth-store.ts Normal file
View 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.'
}