Files
erp-nutzfahrzeuge/frontend/lib/auth.ts
T

81 lines
1.9 KiB
TypeScript
Raw Normal View History

'use client';
import { useRouter } from 'next/navigation';
import { useEffect, useState, useCallback } from 'react';
import {
login as apiLogin,
getCurrentUser,
setTokens,
clearTokens,
isAuthenticated,
type UserResponse,
type ApiError,
} from './api';
export interface AuthState {
user: UserResponse | null;
loading: boolean;
error: string | null;
}
export function useAuth() {
const [state, setState] = useState<AuthState>({
user: null,
loading: true,
error: null,
});
const fetchUser = useCallback(async () => {
if (!isAuthenticated()) {
setState({ user: null, loading: false, error: null });
return;
}
try {
const user = await getCurrentUser();
setState({ user, loading: false, error: null });
} catch {
clearTokens();
setState({ user: null, loading: false, error: 'Session expired' });
}
}, []);
useEffect(() => {
fetchUser();
}, [fetchUser]);
const login = useCallback(async (email: string, password: string) => {
setState({ user: null, loading: true, error: null });
try {
const tokens = await apiLogin(email, password);
setTokens(tokens);
const user = await getCurrentUser();
setState({ user, loading: false, error: null });
return user;
} catch (err) {
const message = (err as ApiError)?.error?.message || 'Login failed';
setState({ user: null, loading: false, error: message });
throw err;
}
}, []);
const logout = useCallback(() => {
clearTokens();
setState({ user: null, loading: false, error: null });
}, []);
return { ...state, login, logout, refresh: fetchUser };
}
export function useRequireAuth() {
const auth = useAuth();
const router = useRouter();
useEffect(() => {
if (!auth.loading && !auth.user) {
router.push('/login');
}
}, [auth.loading, auth.user, router]);
return auth;
}