Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions apps/web/src/components/Sidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,16 @@ const SidebarIcon = ({ icon, isDark }) => {
<path fill="currentColor" d="M7 12v1c0 1.886 0 2.828.586 3.414S9.114 17 11 17h1v1c0 1.886 0 2.828-.586 3.414S9.886 22 8 22H6c-1.886 0-2.828 0-3.414-.586S2 19.886 2 18v-2c0-1.886 0-2.828.586-3.414S4.114 12 6 12z" opacity=".4"/>
</svg>
),
favorites: (
<svg className={iconClass} xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
<path fill="currentColor" d="M17.562 21.56a1 1 0 0 1-.465-.115L12 18.765l-5.097 2.68a1 1 0 0 1-1.451-1.054l.973-5.676l-4.123-4.02a1 1 0 0 1 .554-1.705l5.699-.828l2.548-5.164a1.042 1.042 0 0 1 1.794 0l2.548 5.164l5.699.828a1 1 0 0 1 .554 1.706l-4.123 4.019l.973 5.676a1 1 0 0 1-.986 1.169"/>
</svg>
),
members: (
<svg className={iconClass} xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
<path fill="currentColor" fillRule="evenodd" d="M8 4a4 4 0 1 0 0 8a4 4 0 0 0 0-8m-2 9a4 4 0 0 0-4 4v1a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2v-1a4 4 0 0 0-4-4zm7.25-2.095c.478-.86.75-1.85.75-2.905a6 6 0 0 0-.75-2.906a4 4 0 1 1 0 5.811M15.466 20c.34-.588.535-1.271.535-2v-1a5.98 5.98 0 0 0-1.528-4H18a4 4 0 0 1 4 4v1a2 2 0 0 1-2 2z" clipRule="evenodd"/>
</svg>
),
// favorites: (
// <svg className={iconClass} xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
// <path fill="currentColor" d="M17.562 21.56a1 1 0 0 1-.465-.115L12 18.765l-5.097 2.68a1 1 0 0 1-1.451-1.054l.973-5.676l-4.123-4.02a1 1 0 0 1 .554-1.705l5.699-.828l2.548-5.164a1.042 1.042 0 0 1 1.794 0l2.548 5.164l5.699.828a1 1 0 0 1 .554 1.706l-4.123 4.019l.973 5.676a1 1 0 0 1-.986 1.169"/>
// </svg>
// ),
// members: (
// <svg className={iconClass} xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
// <path fill="currentColor" fillRule="evenodd" d="M8 4a4 4 0 1 0 0 8a4 4 0 0 0 0-8m-2 9a4 4 0 0 0-4 4v1a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2v-1a4 4 0 0 0-4-4zm7.25-2.095c.478-.86.75-1.85.75-2.905a6 6 0 0 0-.75-2.906a4 4 0 1 1 0 5.811M15.466 20c.34-.588.535-1.271.535-2v-1a5.98 5.98 0 0 0-1.528-4H18a4 4 0 0 1 4 4v1a2 2 0 0 1-2 2z" clipRule="evenodd"/>
// </svg>
// ),
admin: (
<svg className={iconClass} xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
<path fill="currentColor" d="m9.25 22l-.4-3.2q-.325-.125-.612-.3t-.563-.375L4.7 19.375l-2.75-4.75l2.575-1.95Q4.5 12.5 4.5 12.338v-.675q0-.163.025-.338L1.95 9.375l2.75-4.75l2.975 1.25q.275-.2.575-.375t.6-.3l.4-3.2h5.5l.4 3.2q.325.125.613.3t.562.375l2.975-1.25l2.75 4.75l-2.575 1.95q.025.175.025.338v.674q0 .163-.05.338l2.575 1.95l-2.75 4.75l-2.95-1.25q-.275.2-.575.375t-.6.3l-.4 3.2zm2.8-6.5q1.45 0 2.475-1.025T15.55 12t-1.025-2.475T12.05 8.5q-1.475 0-2.488 1.025T8.55 12t1.013 2.475T12.05 15.5"/>
Expand Down
40 changes: 20 additions & 20 deletions apps/web/src/config/sidebarConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ export const SIDEBAR_ITEMS = {
label: 'Mis proyectos',
icon: 'myProjects'
},
{
path: '/favorite-projects',
label: 'Mis favoritos',
icon: 'favorites'
}
// {
// path: '/favorite-projects',
// label: 'Mis favoritos',
// icon: 'favorites'
// }
],

// STUDENT - Puede explorar y aplicar a proyectos
Expand All @@ -54,11 +54,11 @@ export const SIDEBAR_ITEMS = {
label: 'Mis proyectos',
icon: 'myProjects'
},
{
path: '/favorite-projects',
label: 'Mis favoritos',
icon: 'favorites'
}
// {
// path: '/favorite-projects',
// label: 'Mis favoritos',
// icon: 'favorites'
// }
],

// PROFESSOR - Puede explorar, solicitar y gestionar proyectos
Expand Down Expand Up @@ -88,16 +88,16 @@ export const SIDEBAR_ITEMS = {
label: 'Mis proyectos',
icon: 'myProjects'
},
{
path: '/favorite-projects',
label: 'Mis favoritos',
icon: 'favorites'
},
{
path: '/members',
label: 'Miembros',
icon: 'members'
}
// {
// path: '/favorite-projects',
// label: 'Mis favoritos',
// icon: 'favorites'
// },
// {
// path: '/members',
// label: 'Miembros',
// icon: 'members'
// }
],

// ADMIN - Acceso completo + panel de administración
Expand Down
66 changes: 58 additions & 8 deletions apps/web/src/features/auth/hooks/useCurrentUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,71 @@ const API_URL = import.meta.env.VITE_API_URL;
* Hook para obtener la sesión actual del usuario autenticado
* @returns {Object} { user, role, isLoading, error }
*/
// Variables globales para caché y deduplicación
let cachedUser = null;
let cachedRole = null;
let fetchPromise = null;
let lastFetchTime = 0;
const CACHE_DURATION = 60000; // 1 minuto de caché

/**
* Hook para obtener la sesión actual del usuario autenticado
* Implementa caché y deduplicación para evitar errores 429
* @returns {Object} { user, role, isLoading, error }
*/
export default function useCurrentUser() {
const [user, setUser] = useState(null);
const [role, setRole] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [user, setUser] = useState(cachedUser);
const [role, setRole] = useState(cachedRole);
const [isLoading, setIsLoading] = useState(!cachedUser);
const [error, setError] = useState(null);

useEffect(() => {
const fetchCurrentUser = async () => {
// Si tenemos datos en caché y son recientes, no hacer nada
const now = Date.now();
if (cachedUser && (now - lastFetchTime < CACHE_DURATION)) {
setUser(cachedUser);
setRole(cachedRole);
setIsLoading(false);
return;
}

// Si ya hay una petición en curso, esperar a que termine
if (fetchPromise) {
try {
const data = await fetchPromise;
setUser(data.user);
setRole(data.role);
} catch (err) {
setError(err.message);
} finally {
setIsLoading(false);
}
return;
}

// Inicia una nueva petición
setIsLoading(true);
fetchPromise = fetchWithAuth(`${API_URL}/auth/me`)
.then(response => {
cachedUser = response.data.user;
cachedRole = response.data.role;
lastFetchTime = Date.now();
return { user: cachedUser, role: cachedRole };
})
.catch(err => {
console.error("Error fetching current user:", err);
throw err;
})
.finally(() => {
fetchPromise = null; // Limpia la promesa al terminar
});

try {
const response = await fetchWithAuth(`${API_URL}/auth/me`);

setUser(response.data.user);
setRole(response.data.role);
const data = await fetchPromise;
setUser(data.user);
setRole(data.role);
} catch (err) {
console.error("Error fetching current user:", err);
setError(err.message);
} finally {
setIsLoading(false);
Expand Down
Loading
Loading