AuthContext.tsx 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'
  2. import { api } from './api'
  3. import type { User } from './types'
  4. type AuthContextType = {
  5. user: User | null
  6. loading: boolean
  7. authenticate: (mode: 'login' | 'register', phone: string, password: string, contactName?: string, inviteToken?: string) => Promise<void>
  8. adminLogin: (phone: string, password: string) => Promise<User>
  9. logout: () => Promise<void>
  10. setUser: (u: User) => void
  11. }
  12. const AuthContext = createContext<AuthContextType>(null!)
  13. export function AuthProvider({ children }: { children: ReactNode }) {
  14. const [user, setUser] = useState<User | null>(null)
  15. const [loading, setLoading] = useState(true)
  16. useEffect(() => {
  17. const load = () =>
  18. localStorage.getItem('xinghen_token')
  19. ? api
  20. .me()
  21. .then((r) => setUser(r.user))
  22. .catch(() => setUser(null))
  23. .finally(() => setLoading(false))
  24. : setLoading(false)
  25. load()
  26. addEventListener('auth-expired', load)
  27. return () => removeEventListener('auth-expired', load)
  28. }, [])
  29. async function authenticate(mode: 'login' | 'register', phone: string, password: string, contactName?: string, inviteToken?: string) {
  30. const r = mode === 'register' ? await api.register(phone, password, contactName || '', inviteToken) : await api.login(phone, password)
  31. localStorage.setItem('xinghen_token', r.token)
  32. setUser(r.user)
  33. }
  34. async function adminLogin(phone: string, password: string) {
  35. const r = await api.admin.login(phone, password)
  36. localStorage.setItem('xinghen_token', r.token)
  37. setUser(r.user)
  38. return r.user
  39. }
  40. async function logout() {
  41. await api.logout().catch(() => {})
  42. localStorage.removeItem('xinghen_token')
  43. setUser(null)
  44. }
  45. return (
  46. <AuthContext.Provider value={{ user, loading, authenticate, adminLogin, logout, setUser }}>
  47. {children}
  48. </AuthContext.Provider>
  49. )
  50. }
  51. export const useAuth = () => useContext(AuthContext)