Files
blackheart-website/src/app/api/group-booking/route.ts
diana.dolgolyova b1adbbfe3d fix: MEDIUM priority — shared validation, content caching, Schedule useReducer, stable keys
- Extract shared sanitization to src/lib/validation.ts, apply to all 3 registration routes (#2)
- Replace key={index} with stable keys in About and News (#4)
- Add 5-min in-memory content cache in content.ts, invalidate on admin section save (#6)
- Refactor Schedule from 8 useState calls to useReducer — single dispatch, fewer re-renders (#8)
- Remove Hero scroll indicator, add auto-scroll to next section on wheel/swipe

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:17:24 +03:00

42 lines
1.4 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { addGroupBooking } from "@/lib/db";
import { checkRateLimit, getClientIp } from "@/lib/rateLimit";
import { sanitizeName, sanitizePhone, sanitizeHandle, sanitizeText } from "@/lib/validation";
export async function POST(request: NextRequest) {
const ip = getClientIp(request);
if (!checkRateLimit(ip, 5, 60_000)) {
return NextResponse.json(
{ error: "Слишком много запросов. Попробуйте через минуту." },
{ status: 429 }
);
}
try {
const body = await request.json();
const { name, phone, groupInfo, instagram, telegram } = body;
const cleanName = sanitizeName(name);
if (!cleanName) {
return NextResponse.json({ error: "Имя обязательно" }, { status: 400 });
}
const cleanPhone = sanitizePhone(phone);
if (!cleanPhone) {
return NextResponse.json({ error: "Телефон обязателен" }, { status: 400 });
}
const id = addGroupBooking(
cleanName,
cleanPhone,
sanitizeText(groupInfo),
sanitizeHandle(instagram),
sanitizeHandle(telegram)
);
return NextResponse.json({ ok: true, id });
} catch (err) {
console.error("[group-booking] POST error:", err);
return NextResponse.json({ error: "Internal error" }, { status: 500 });
}
}