chore: estructura inicial del MVP

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>
This commit is contained in:
Milton Gonzalez
2026-09-03 08:37:58 -05:00
commit 1d22adc42e
135 changed files with 10913 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
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;
}