Токен хранится в sessionStorage (design D-9; без Redux): живёт до закрытия вкладки, все обращения к хранилищу в try/catch с запасным токеном в памяти.
apiFetch подставляет Bearer, на 401 сбрасывает токен и шлёт событие armka:unauthorized, ошибки разбирает по трём формам detail (строка / {code,message} / массив 422).
useMe не ходит в /me без токена и отбрасывает устаревшие ответы (флаг cancelled), AuthGate показывает вход, пока профиля нет.
Форма DevLogin вырезается из production-сборки по литералу process.env.NODE_ENV; через Config это не работает: process.env там заменён объектом REACT_APP_*.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
19 lines
691 B
TypeScript
19 lines
691 B
TypeScript
import { Spin } from 'antd';
|
|
import type { ReactNode } from 'react';
|
|
import { DevLogin } from './DevLogin';
|
|
import { MeContext } from './MeContext';
|
|
import { useMe } from './useMe';
|
|
|
|
// Пока профиль не загружен — вход (или индикатор загрузки); после входа дети получают профиль через `useCurrentUser`.
|
|
export function AuthGate({ children }: { children: ReactNode }) {
|
|
const { me, loading, error, reload } = useMe();
|
|
|
|
if (loading) {
|
|
return <Spin fullscreen />;
|
|
}
|
|
if (!me) {
|
|
return <DevLogin onLogin={reload} error={error} />;
|
|
}
|
|
return <MeContext.Provider value={me}>{children}</MeContext.Provider>;
|
|
}
|