trello_fake/hooks/use-auth.tsx

144 lines
3.3 KiB
TypeScript
Raw Normal View History

"use client";
import {
createContext,
useContext,
useState,
useEffect,
useCallback,
ReactNode,
} from "react";
import { useRouter, usePathname } from "next/navigation";
import {
AuthUser,
AuthState,
LoginCredentials,
login as authLogin,
logout as authLogout,
getAuthState,
verifyToken,
} from "@/lib/authService";
// Rutas públicas que no requieren autenticación
const PUBLIC_ROUTES = ["/login"];
interface AuthContextType {
user: AuthUser | null;
isAuthenticated: boolean;
isLoading: boolean;
login: (credentials: LoginCredentials) => Promise<{ success: boolean; error?: string }>;
logout: () => Promise<void>;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
interface AuthProviderProps {
children: ReactNode;
}
export function AuthProvider({ children }: AuthProviderProps) {
const router = useRouter();
const pathname = usePathname();
const [authState, setAuthState] = useState<AuthState>({
isAuthenticated: false,
user: null,
token: null,
});
const [isLoading, setIsLoading] = useState(true);
// Verificar autenticación al cargar
useEffect(() => {
async function checkAuth() {
setIsLoading(true);
// Obtener estado guardado
const storedState = getAuthState();
if (storedState.isAuthenticated) {
// Verificar que el token sigue siendo válido
const isValid = await verifyToken();
if (isValid) {
setAuthState(storedState);
} else {
// Token inválido, limpiar
setAuthState({
isAuthenticated: false,
user: null,
token: null,
});
}
}
setIsLoading(false);
}
checkAuth();
}, []);
// Redirección basada en autenticación
useEffect(() => {
if (isLoading) return;
const isPublicRoute = PUBLIC_ROUTES.includes(pathname);
if (!authState.isAuthenticated && !isPublicRoute) {
// No autenticado y en ruta privada -> redirigir a login
router.push("/login");
} else if (authState.isAuthenticated && pathname === "/login") {
// Autenticado y en login -> redirigir a home
router.push("/");
}
}, [authState.isAuthenticated, isLoading, pathname, router]);
// Login
const login = useCallback(async (credentials: LoginCredentials) => {
const result = await authLogin(credentials);
if (result.success) {
setAuthState({
isAuthenticated: true,
user: result.user || null,
token: result.token || null,
});
return { success: true };
}
return { success: false, error: result.error };
}, []);
// Logout
const logout = useCallback(async () => {
await authLogout();
setAuthState({
isAuthenticated: false,
user: null,
token: null,
});
router.push("/login");
}, [router]);
const value: AuthContextType = {
user: authState.user,
isAuthenticated: authState.isAuthenticated,
isLoading,
login,
logout,
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
/**
* Hook para acceder al contexto de autenticación
*/
export function useAuth(): AuthContextType {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
}