Cesar Mendivil a501d398ff chore: update tailwindcss to version 4.1.0 across admin, broadcast, landing, and studio panels
refactor: remove unnecessary React import in AuthButton component due to new JSX transform

refactor: simplify imports in LanguageSelector component

fix: remove unused AuthResponse type import in useAuth hook

fix: access Vite environment variables in a type-safe manner in api utility
2025-11-09 19:02:50 -07:00

142 lines
3.6 KiB
TypeScript

import { useState, useEffect, useCallback } from 'react';
import type { User, AuthTokens, LoginCredentials, RegisterData } from '@avanzacast/shared-types';
import {
saveTokens,
saveUser,
getTokens,
getUser,
clearAuth,
isAuthenticated as checkAuth
} from '@avanzacast/shared-utils';
import { apiClient } from '@avanzacast/shared-utils';
interface UseAuthReturn {
user: User | null;
tokens: AuthTokens | null;
isAuthenticated: boolean;
isLoading: boolean;
login: (credentials: LoginCredentials) => Promise<{ success: boolean; error?: string }>;
register: (data: RegisterData) => Promise<{ success: boolean; error?: string }>;
logout: () => void;
refreshAuth: () => Promise<void>;
}
/**
* Hook compartido para manejar autenticación en todos los módulos
*/
export function useAuth(): UseAuthReturn {
const [user, setUser] = useState<User | null>(null);
const [tokens, setTokens] = useState<AuthTokens | null>(null);
const [isLoading, setIsLoading] = useState(true);
// Cargar datos de autenticación al montar
useEffect(() => {
const loadAuth = () => {
const savedUser = getUser();
const savedTokens = getTokens();
if (savedUser && savedTokens && checkAuth()) {
setUser(savedUser);
setTokens(savedTokens);
}
setIsLoading(false);
};
loadAuth();
}, []);
// Login
const login = useCallback(async (credentials: LoginCredentials) => {
setIsLoading(true);
try {
const response = await apiClient.login(credentials);
if (response.success && response.data) {
const { user: userData, tokens: tokenData } = response.data;
setUser(userData);
setTokens(tokenData);
saveUser(userData);
saveTokens(tokenData);
return { success: true };
}
return {
success: false,
error: response.error?.message || 'Error al iniciar sesión'
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Error desconocido'
};
} finally {
setIsLoading(false);
}
}, []);
// Register
const register = useCallback(async (data: RegisterData) => {
setIsLoading(true);
try {
const response = await apiClient.register(data);
if (response.success && response.data) {
const { user: userData, tokens: tokenData } = response.data;
setUser(userData);
setTokens(tokenData);
saveUser(userData);
saveTokens(tokenData);
return { success: true };
}
return {
success: false,
error: response.error?.message || 'Error al registrarse'
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Error desconocido'
};
} finally {
setIsLoading(false);
}
}, []);
// Logout
const logout = useCallback(() => {
setUser(null);
setTokens(null);
clearAuth();
// Llamar al endpoint de logout en segundo plano
apiClient.logout().catch(console.error);
}, []);
// Refresh auth (actualizar datos del usuario)
const refreshAuth = useCallback(async () => {
if (!tokens) return;
try {
const response = await apiClient.getProfile();
if (response.success && response.data) {
setUser(response.data);
saveUser(response.data);
}
} catch (error) {
console.error('Error refreshing auth:', error);
}
}, [tokens]);
return {
user,
tokens,
isAuthenticated: !!user && !!tokens,
isLoading,
login,
register,
logout,
refreshAuth,
};
}