feat: creats frontend for the project

This commit is contained in:
vakabunga
2026-03-02 00:33:09 +03:00
parent 4d67636633
commit cd56e2bf9d
37 changed files with 3762 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
import {
createContext,
useContext,
useState,
useEffect,
useCallback,
type ReactNode,
} from 'react';
import { getMe, login as apiLogin, logout as apiLogout } from '../api/auth';
import { setOnUnauthorized } from '../api/client';
interface AuthState {
user: { login: string } | null;
loading: boolean;
error: string | null;
login: (username: string, password: string) => Promise<void>;
logout: () => Promise<void>;
}
const AuthContext = createContext<AuthState | null>(null);
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<{ login: string } | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const clearUser = useCallback(() => {
setUser(null);
}, []);
useEffect(() => {
setOnUnauthorized(clearUser);
getMe()
.then((me) => setUser({ login: me.login }))
.catch(() => setUser(null))
.finally(() => setLoading(false));
}, [clearUser]);
const login = useCallback(async (username: string, password: string) => {
setError(null);
try {
await apiLogin({ login: username, password });
const me = await getMe();
setUser({ login: me.login });
} catch (e: unknown) {
const msg =
e instanceof Error ? e.message : 'Ошибка входа';
setError(msg);
throw e;
}
}, []);
const logout = useCallback(async () => {
try {
await apiLogout();
} finally {
setUser(null);
}
}, []);
return (
<AuthContext.Provider value={{ user, loading, error, login, logout }}>
{children}
</AuthContext.Provider>
);
}
export function useAuth(): AuthState {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error('useAuth must be used within AuthProvider');
return ctx;
}