feat(web): анонимный вход для школьников — только школа и класс
Школьники не должны придумывать пароль, чтобы пройти тест. Бэкенд уже
поддерживал это: POST /polls/{poll_id}/responses принимает user_id как
Optional, а Response.group_id/organization_id — самостоятельные nullable
снимки школы/класса, не завязанные на аккаунт. Не хватало только
фронтенда — все роуты были жёстко завёрнуты в ProtectedRoute с
обязательным JWT.
- AuthContext: параллельная "анонимная идентичность" (org+group в
localStorage, без токена и без запроса к API)
- ProtectedRoute пускает по токену ИЛИ анонимной сессии; новый
AccountRoute — строго по токену, для /my-tests, /profile,
/response/:id (у анонимной сессии нет истории — её негде хранить)
- Новая страница /anonymous — выбор школы+класса тем же
SearchableDropdown, что и в регистрации
- PollPage при отправке ответа берёт org/group из анонимной сессии,
если пользователь не залогинен
- HomePage скрывает "Мои тесты" и профиль для анонимов, добавлена
кнопка выхода из анонимного режима
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,8 +3,26 @@ import type { ReactNode } from "react";
|
||||
import { useAuth } from "../auth/AuthContext";
|
||||
import { Spinner } from "./ui";
|
||||
|
||||
// Пускает дальше только при наличии токена. Пока идёт первичная проверка — спиннер.
|
||||
// Пускает дальше при наличии токена ИЛИ анонимной идентичности (школа+класс,
|
||||
// без аккаунта). Используется для страниц, которые школьник может пройти
|
||||
// анонимно: главная, список тестов, прохождение теста.
|
||||
export function ProtectedRoute({ children }: { children: ReactNode }) {
|
||||
const { token, anon, ready } = useAuth();
|
||||
if (!ready) {
|
||||
return (
|
||||
<div className="spinner-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (!token && !anon) return <Navigate to="/login" replace />;
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
// Строже: пускает дальше только при реальном токене (не анонимной сессии).
|
||||
// Для страниц, которым нужен настоящий аккаунт: история тестов, профиль,
|
||||
// просмотр конкретного результата.
|
||||
export function AccountRoute({ children }: { children: ReactNode }) {
|
||||
const { token, ready } = useAuth();
|
||||
if (!ready) {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user