Files
erp-nutzfahrzeuge/frontend/lib/auth.ts
T
Leopoldadmin d89304845a feat(T01): auth + user management + RBAC + base frontend + i18n
- Backend: FastAPI, JWT auth (HS256), bcrypt, RBAC middleware
- User CRUD (admin-only), soft-delete, pagination
- Pydantic BaseSettings config, async SQLAlchemy 2.0
- 50 backend tests, 88% coverage
- Frontend: Next.js 14 App Router, Tailwind, design tokens
- Login page, auth context, API client with auto-refresh
- i18n: next-intl, DE/EN (31 keys each)
- 6 base UI components (Button, Input, Card, Table, Modal, Toast)
- 12 frontend tests, npm build success
2026-07-14 11:51:32 +02:00

81 lines
1.9 KiB
TypeScript

'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;
}