feat: version 4.3.0 -- Sesiones activas y pagina Mi cuenta

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Milton Gonzalez
2026-10-26 16:42:19 -05:00
parent 544928d04a
commit a6cc41666e
34 changed files with 464 additions and 110 deletions
+14 -6
View File
@@ -12,6 +12,7 @@ export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const [ready, setReady] = useState(false);
const userRef = useRef(null);
const lastPingRef = useRef(0);
userRef.current = user;
const logout = useCallback((options = {}) => {
@@ -19,21 +20,22 @@ export function AuthProvider({ children }) {
// (los borradores ya estan guardados en el navegador).
setGuardBypass(true);
if (!options.preserveDrafts) clearUserDrafts(userRef.current?.id);
if (options.remote) api.post('/auth/logout').catch(() => {});
api.setToken(null);
setUser(null);
}, []);
// Vencimiento: recuerda donde estaba el usuario (para volver ahi tras el login) y marca el
// aviso que muestra la pantalla de login. Idempotente.
const expireSession = useCallback(() => {
const expireSession = useCallback((info = {}) => {
if (!localStorage.getItem('plc_token')) return;
if (userRef.current) saveReturnContext(userRef.current.id);
markSessionExpired();
saveReturnContext(userRef.current?.id || tokenSubject(localStorage.getItem('plc_token')));
markSessionExpired(info.code === 'SESSION_REVOKED');
logout({ preserveDrafts: true });
}, [logout]);
useEffect(() => {
setUnauthorizedHandler(() => expireSession());
setUnauthorizedHandler((info) => expireSession(info));
}, [expireSession]);
useEffect(() => {
@@ -47,9 +49,10 @@ export function AuthProvider({ children }) {
setReady(true);
return;
}
lastPingRef.current = Date.now();
api.get('/auth/me')
.then((me) => setUser(me))
.catch(() => logout())
.catch((error) => { if (error.status !== 401) logout(); })
.finally(() => setReady(true));
}, [logout]);
@@ -59,7 +62,11 @@ export function AuthProvider({ children }) {
useEffect(() => {
if (!user) return undefined;
const check = () => {
if (isTokenExpired(localStorage.getItem('plc_token'), 0)) expireSession();
if (isTokenExpired(localStorage.getItem('plc_token'), 0)) { expireSession(); return; }
if (document.visibilityState === 'visible' && Date.now() - lastPingRef.current >= 60000) {
lastPingRef.current = Date.now();
api.get('/auth/me').catch(() => {});
}
};
const exp = tokenExpiresAt(localStorage.getItem('plc_token'));
const timer = exp ? setTimeout(check, Math.min(Math.max(exp - Date.now(), 0) + 500, MAX_TIMEOUT_MS)) : null;
@@ -81,6 +88,7 @@ export function AuthProvider({ children }) {
// Devuelve la ruta a la que volver tras iniciar sesion (solo si la dejo este mismo usuario).
const startSession = useCallback((token, sessionUser) => {
api.setToken(token);
lastPingRef.current = Date.now();
clearSessionExpiredFlag();
setGuardBypass(false);
setUser(sessionUser);