Ревью: корректность фронтенда
Находки прохода /code-review high по frontend/src: - CreateMatchPage: барабан рандома, таймеры и строки адресовались по индексу, а удаление строки индексы сдвигает — фракция могла записаться соседу или потеряться. Строки получили стабильный id. - AdminAccountsPage: переключение «активен» глотало ошибку и всё равно показывало «Сохранено». - useServerEvents/useFinishMatch: завершение чужой партии не инвалидировало историю игр и публичные профили — открытый профиль показывал состав до завершения. - guards/useMe: обрыв связи не отличался от «нет сессии», и мигание сети выкидывало авторизованного пользователя на /login. Транспортные ошибки повторяем, гварды показывают сообщение вместо редиректа. - format: fallback на нераспознанную дату не работал (new Date не бросает исключение), и в интерфейс попадало «NaN.NaN NaN:NaN». - PlaceEditor: без onPointerCancel прерванный перенос оставлял блок с классом dragging и сдвигом, которые React не снимает — они выставлены в обход него. - AdminFactionsPage: refetch после сохранения одной фракции затирал несохранённый ввод в остальных. - MatchDetailPage: nav(-1) после удаления уводил из приложения при открытии партии по прямой ссылке; id из URL мог быть NaN и уходил в запрос. #8 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186Fk74jkkszahEHSjBzTjD
This commit is contained in:
@@ -23,7 +23,9 @@ const REASON_OPTIONS = WIN_REASONS.map((w) => ({ id: w.code, label: w.label }));
|
||||
|
||||
export function MatchDetailPage() {
|
||||
const { matchId } = useParams();
|
||||
const id = matchId ? Number(matchId) : null;
|
||||
// Number("abc") — NaN, а не null: без проверки запрос уходил бы на /api/matches/NaN.
|
||||
const parsed = matchId ? Number(matchId) : NaN;
|
||||
const id = Number.isInteger(parsed) ? parsed : null;
|
||||
const { data: match, isLoading, refetch } = useMatch(id);
|
||||
const finish = useFinishMatch();
|
||||
const del = useDeleteMatch();
|
||||
@@ -105,7 +107,9 @@ export function MatchDetailPage() {
|
||||
try {
|
||||
await del.mutateAsync({ matchId: id, expectedVersion: match.version });
|
||||
toast.show(inProgress ? "Партия отменена" : "Партия удалена");
|
||||
navigate(-1);
|
||||
// Не navigate(-1): партию часто открывают по прямой ссылке, и «назад»
|
||||
// уводит из приложения вместо возврата к группе.
|
||||
navigate("/group", { replace: true });
|
||||
} catch (e) {
|
||||
if (isStale(e)) {
|
||||
toast.show("Партия изменилась на другом устройстве — обновлено");
|
||||
|
||||
Reference in New Issue
Block a user