fix: LOW priority — GPU hints, CSRF cleanup, redundant query removal, mobile perf

- Add will-change to .hero-glow-orb (filter, transform) and .team-card-glitter::before (background-position)
- Clear CSRF cookie on logout alongside auth cookie
- Add max array length (100) validation on team reorder endpoint
- Remove redundant isOpenDayClassBookedByPhone pre-check (DB UNIQUE constraint handles it)
- Extract Schedule grid layout calculation into useMemo
- Reduce HeroLogo sparkle animations on mobile (15 → 8 via hidden sm:block)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-19 14:28:35 +03:00
parent 5cd23473c8
commit 9e0aa5b5dc
6 changed files with 27 additions and 13 deletions

View File

@@ -5,8 +5,8 @@ import { revalidatePath } from "next/cache";
export async function PUT(request: NextRequest) {
const { ids } = await request.json() as { ids: number[] };
if (!Array.isArray(ids) || ids.length === 0 || !ids.every((id) => Number.isInteger(id) && id > 0)) {
return NextResponse.json({ error: "ids must be a non-empty array of positive integers" }, { status: 400 });
if (!Array.isArray(ids) || ids.length === 0 || ids.length > 100 || !ids.every((id) => Number.isInteger(id) && id > 0)) {
return NextResponse.json({ error: "ids must be a non-empty array of positive integers (max 100)" }, { status: 400 });
}
reorderTeamMembers(ids);

View File

@@ -1,5 +1,5 @@
import { NextResponse } from "next/server";
import { COOKIE_NAME } from "@/lib/auth";
import { COOKIE_NAME, CSRF_COOKIE_NAME } from "@/lib/auth";
export async function POST() {
const response = NextResponse.json({ ok: true });
@@ -8,5 +8,9 @@ export async function POST() {
path: "/",
maxAge: 0,
});
response.cookies.set(CSRF_COOKIE_NAME, "", {
path: "/",
maxAge: 0,
});
return response;
}

View File

@@ -1,7 +1,6 @@
import { NextRequest, NextResponse } from "next/server";
import {
addOpenDayBooking,
isOpenDayClassBookedByPhone,
getPersonOpenDayBookings,
getOpenDayEvent,
} from "@/lib/db";
@@ -35,11 +34,6 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ error: "Телефон обязателен" }, { status: 400 });
}
// Check not already booked
if (isOpenDayClassBookedByPhone(classId, cleanPhone)) {
return NextResponse.json({ error: "Вы уже записаны на это занятие" }, { status: 409 });
}
const id = addOpenDayBooking(classId, eventId, {
name: cleanName,
phone: cleanPhone,