1d22adc42e
Backend (Express + MariaDB) y frontend (React + Vite, identidad Fluent/Windows) con el nucleo funcional: seguridad, organizacion, proyectos, actividades, subtareas, dependencias, dashboard, calendario, gantt, comentarios, adjuntos, notificaciones in-app y catalogos. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
45 lines
1.3 KiB
React
45 lines
1.3 KiB
React
import { createContext, useContext, useEffect, useMemo, useState, useCallback } from 'react';
|
|
import { api, setUnauthorizedHandler } from '../services/api.js';
|
|
|
|
const AuthContext = createContext(null);
|
|
|
|
export function AuthProvider({ children }) {
|
|
const [user, setUser] = useState(null);
|
|
const [ready, setReady] = useState(false);
|
|
|
|
const logout = useCallback(() => {
|
|
api.setToken(null);
|
|
setUser(null);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
setUnauthorizedHandler(() => logout());
|
|
}, [logout]);
|
|
|
|
useEffect(() => {
|
|
const token = localStorage.getItem('plc_token');
|
|
if (!token) { setReady(true); return; }
|
|
api.get('/auth/me')
|
|
.then((me) => setUser(me))
|
|
.catch(() => logout())
|
|
.finally(() => setReady(true));
|
|
}, [logout]);
|
|
|
|
const login = useCallback(async (email, password) => {
|
|
const result = await api.post('/auth/login', { email, password });
|
|
api.setToken(result.token);
|
|
setUser(result.user);
|
|
return result.user;
|
|
}, []);
|
|
|
|
const value = useMemo(() => ({ user, ready, login, logout }), [user, ready, login, logout]);
|
|
|
|
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
|
}
|
|
|
|
export function useAuth() {
|
|
const ctx = useContext(AuthContext);
|
|
if (!ctx) throw new Error('useAuth debe usarse dentro de AuthProvider');
|
|
return ctx;
|
|
}
|