this repo has no description
1import { createContext, useState, useEffect, useCallback, type ReactNode } from 'react';
2import { apiClient } from '../api/client';
3
4const TOKEN_KEY = 'ayos_token';
5
6export interface UserResponse {
7 id: string;
8 username: string;
9 email: string;
10}
11
12interface AuthState {
13 user: UserResponse | null;
14 token: string | null;
15 loading: boolean;
16}
17
18export interface AuthContextValue extends AuthState {
19 login: (email: string, password: string) => Promise<void>;
20 register: (username: string, email: string, password: string) => Promise<void>;
21 logout: () => void;
22}
23
24export const AuthContext = createContext<AuthContextValue | null>(null);
25
26interface LoginResponse {
27 token: string;
28 user: UserResponse;
29}
30
31interface RegisterResponse {
32 token: string;
33 user: UserResponse;
34}
35
36export function AuthProvider({ children }: { children: ReactNode }) {
37 const [state, setState] = useState<AuthState>({
38 user: null,
39 token: localStorage.getItem(TOKEN_KEY),
40 loading: true,
41 });
42
43 useEffect(() => {
44 const token = localStorage.getItem(TOKEN_KEY);
45 if (!token) {
46 setState({ user: null, token: null, loading: false });
47 return;
48 }
49
50 apiClient
51 .get<UserResponse>('/api/me')
52 .then((user) => {
53 setState({ user, token, loading: false });
54 })
55 .catch(() => {
56 localStorage.removeItem(TOKEN_KEY);
57 setState({ user: null, token: null, loading: false });
58 });
59 }, []);
60
61 const login = useCallback(async (email: string, password: string) => {
62 const data = await apiClient.post<LoginResponse>('/api/login', {
63 email,
64 password,
65 });
66 localStorage.setItem(TOKEN_KEY, data.token);
67 setState({ user: data.user, token: data.token, loading: false });
68 }, []);
69
70 const register = useCallback(
71 async (username: string, email: string, password: string) => {
72 const data = await apiClient.post<RegisterResponse>('/api/register', {
73 username,
74 email,
75 password,
76 });
77 localStorage.setItem(TOKEN_KEY, data.token);
78 setState({ user: data.user, token: data.token, loading: false });
79 },
80 [],
81 );
82
83 const logout = useCallback(() => {
84 localStorage.removeItem(TOKEN_KEY);
85 setState({ user: null, token: null, loading: false });
86 }, []);
87
88 return (
89 <AuthContext.Provider
90 value={{
91 user: state.user,
92 token: state.token,
93 loading: state.loading,
94 login,
95 register,
96 logout,
97 }}
98 >
99 {children}
100 </AuthContext.Provider>
101 );
102}