67 lines
1.7 KiB
JavaScript
67 lines
1.7 KiB
JavaScript
'use client';
|
|
|
|
/**
|
|
* Client hook to fetch the current user from the API.
|
|
* Uses session cookie (credentials: 'include'); safe to use in client components.
|
|
*
|
|
* @returns {{ user: Object|null, loading: boolean, error: string|null, refetch: function }}
|
|
*
|
|
* @example
|
|
* const { user, loading, error, refetch } = useCurrentUser();
|
|
* if (loading) return <Spinner />;
|
|
* if (error) return <div>Error: {error}</div>;
|
|
* if (!user) return <Link href="/auth/login">Log in</Link>;
|
|
* return <span>Hello, {user.name}</span>;
|
|
*/
|
|
|
|
import { useState, useEffect, useCallback } from 'react';
|
|
|
|
const API_BASE = '/zen/api';
|
|
|
|
export function useCurrentUser() {
|
|
const [user, setUser] = useState(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState(null);
|
|
|
|
const fetchUser = useCallback(async () => {
|
|
setLoading(true);
|
|
setError(null);
|
|
try {
|
|
const res = await fetch(`${API_BASE}/users/me`, {
|
|
method: 'GET',
|
|
credentials: 'include',
|
|
headers: { Accept: 'application/json' },
|
|
});
|
|
const data = await res.json();
|
|
|
|
if (!res.ok) {
|
|
if (res.status === 401) {
|
|
setUser(null);
|
|
return;
|
|
}
|
|
setError(data.message || data.error || 'Failed to load user');
|
|
setUser(null);
|
|
return;
|
|
}
|
|
|
|
if (data.user) {
|
|
setUser(data.user);
|
|
} else {
|
|
setUser(null);
|
|
}
|
|
} catch (err) {
|
|
console.error('[useCurrentUser]', err);
|
|
setError(err.message || 'Failed to load user');
|
|
setUser(null);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
fetchUser();
|
|
}, [fetchUser]);
|
|
|
|
return { user, loading, error, refetch: fetchUser };
|
|
}
|