Files
mercadodevida/project/apps/admin/src/features/auth/components/AuthProvider.tsx
2026-08-17 22:23:10 +02:00

69 lines
1.9 KiB
TypeScript

'use client';
import { createContext, useContext, useState, useEffect, useCallback } from 'react';
import type { AuthUser, Role } from '@/types';
import { authApi } from '@/lib/api-client';
interface AuthContextValue {
user: AuthUser | null;
loading: boolean;
login: (email: string, password: string) => Promise<{ ok: boolean; error?: string }>;
logout: () => Promise<void>;
}
const AuthContext = createContext<AuthContextValue | null>(null);
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<AuthUser | null>(null);
const [loading, setLoading] = useState(true);
// Load session on mount
useEffect(() => {
authApi
.me()
.then((data) => {
if ('id' in data) {
setUser({ id: data.id, email: data.email, role: data.role as Role });
}
})
.catch(() => setUser(null))
.finally(() => setLoading(false));
}, []);
const login = useCallback(async (email: string, password: string) => {
try {
const data = await authApi.login(email, password);
// The backend sets the session cookie via Set-Cookie header.
// We also set it client-side for immediate access.
setUser({ id: data.id, email: data.email, role: data.role as Role });
return { ok: true };
} catch (err: unknown) {
const msg =
err instanceof Error
? (err as { message?: string }).message ?? 'Error de login'
: 'Error de login';
return { ok: false, error: msg };
}
}, []);
const logout = useCallback(async () => {
try {
await authApi.logout();
} catch {
// ignore
}
setUser(null);
}, []);
return (
<AuthContext.Provider value={{ user, loading, login, logout }}>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error('useAuth must be used within AuthProvider');
return ctx;
}