|
|
import { createContext, useContext, useState, useEffect, type ReactNode } from 'react'; |
|
|
import type { User } from '../types'; |
|
|
import { api } from '../api/client'; |
|
|
|
|
|
interface UserContextType { |
|
|
user: User | null; |
|
|
isLoading: boolean; |
|
|
error: string | null; |
|
|
login: (firstName: string, lastName: string) => Promise<void>; |
|
|
loginWithId: (userId: string) => Promise<void>; |
|
|
logout: () => void; |
|
|
} |
|
|
|
|
|
const UserContext = createContext<UserContextType | null>(null); |
|
|
|
|
|
const USER_STORAGE_KEY = 'project_memory_user'; |
|
|
|
|
|
export function UserProvider({ children }: { children: ReactNode }) { |
|
|
const [user, setUser] = useState<User | null>(null); |
|
|
const [isLoading, setIsLoading] = useState(true); |
|
|
const [error, setError] = useState<string | null>(null); |
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
const stored = localStorage.getItem(USER_STORAGE_KEY); |
|
|
if (stored) { |
|
|
try { |
|
|
const userData = JSON.parse(stored) as User; |
|
|
|
|
|
api.getUser(userData.id) |
|
|
.then(user => { |
|
|
setUser(user); |
|
|
setIsLoading(false); |
|
|
}) |
|
|
.catch(() => { |
|
|
|
|
|
localStorage.removeItem(USER_STORAGE_KEY); |
|
|
setIsLoading(false); |
|
|
}); |
|
|
} catch { |
|
|
localStorage.removeItem(USER_STORAGE_KEY); |
|
|
setIsLoading(false); |
|
|
} |
|
|
} else { |
|
|
setIsLoading(false); |
|
|
} |
|
|
}, []); |
|
|
|
|
|
const login = async (firstName: string, lastName: string) => { |
|
|
setIsLoading(true); |
|
|
setError(null); |
|
|
try { |
|
|
const newUser = await api.createUser({ firstName, lastName }); |
|
|
setUser(newUser); |
|
|
localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(newUser)); |
|
|
} catch (err) { |
|
|
setError(err instanceof Error ? err.message : 'Failed to create user'); |
|
|
throw err; |
|
|
} finally { |
|
|
setIsLoading(false); |
|
|
} |
|
|
}; |
|
|
|
|
|
const loginWithId = async (userId: string) => { |
|
|
setIsLoading(true); |
|
|
setError(null); |
|
|
try { |
|
|
const existingUser = await api.getUser(userId); |
|
|
setUser(existingUser); |
|
|
localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(existingUser)); |
|
|
} catch (err) { |
|
|
setError(err instanceof Error ? err.message : 'User not found'); |
|
|
throw err; |
|
|
} finally { |
|
|
setIsLoading(false); |
|
|
} |
|
|
}; |
|
|
|
|
|
const logout = () => { |
|
|
setUser(null); |
|
|
localStorage.removeItem(USER_STORAGE_KEY); |
|
|
}; |
|
|
|
|
|
return ( |
|
|
<UserContext.Provider value={{ user, isLoading, error, login, loginWithId, logout }}> |
|
|
{children} |
|
|
</UserContext.Provider> |
|
|
); |
|
|
} |
|
|
|
|
|
export function useUser() { |
|
|
const context = useContext(UserContext); |
|
|
if (!context) { |
|
|
throw new Error('useUser must be used within a UserProvider'); |
|
|
} |
|
|
return context; |
|
|
} |
|
|
|