From 5cd23473c89e81e27d6fc93132397a345fcdee3d Mon Sep 17 00:00:00 2001 From: "diana.dolgolyova" Date: Thu, 19 Mar 2026 14:19:39 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20MEDIUM=20=E2=80=94=20Cache-Control=20hea?= =?UTF-8?q?ders=20on=20admin=20GETs,=20Open=20Day=20past=20date=20validati?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Cache-Control headers to admin GET endpoints (sections 60s, team 60s, bookings 30s, unread 15s, open-day 60s) - Validate Open Day date is not in the past on both create (POST) and update (PUT) Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app/api/admin/group-bookings/route.ts | 4 +++- src/app/api/admin/open-day/route.ts | 15 ++++++++++++++- src/app/api/admin/sections/[key]/route.ts | 4 +++- src/app/api/admin/team/route.ts | 4 +++- src/app/api/admin/unread-counts/route.ts | 4 +++- 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/app/api/admin/group-bookings/route.ts b/src/app/api/admin/group-bookings/route.ts index 6fa5fb4..1d134f5 100644 --- a/src/app/api/admin/group-bookings/route.ts +++ b/src/app/api/admin/group-bookings/route.ts @@ -3,7 +3,9 @@ import { getGroupBookings, toggleGroupBookingNotification, deleteGroupBooking } export async function GET() { const bookings = getGroupBookings(); - return NextResponse.json(bookings); + return NextResponse.json(bookings, { + headers: { "Cache-Control": "private, max-age=30" }, + }); } export async function PUT(request: NextRequest) { diff --git a/src/app/api/admin/open-day/route.ts b/src/app/api/admin/open-day/route.ts index ff89cf2..30b7fec 100644 --- a/src/app/api/admin/open-day/route.ts +++ b/src/app/api/admin/open-day/route.ts @@ -16,7 +16,9 @@ export async function GET(request: NextRequest) { if (!event) return NextResponse.json({ error: "Not found" }, { status: 404 }); return NextResponse.json(event); } - return NextResponse.json(getOpenDayEvents()); + return NextResponse.json(getOpenDayEvents(), { + headers: { "Cache-Control": "private, max-age=60" }, + }); } export async function POST(request: NextRequest) { @@ -25,6 +27,11 @@ export async function POST(request: NextRequest) { if (!body.date || typeof body.date !== "string") { return NextResponse.json({ error: "date is required" }, { status: 400 }); } + // Warn if date is in the past + const eventDate = new Date(body.date + "T23:59:59"); + if (eventDate < new Date()) { + return NextResponse.json({ error: "Дата не может быть в прошлом" }, { status: 400 }); + } const id = createOpenDayEvent(body); return NextResponse.json({ ok: true, id }); } catch (err) { @@ -38,6 +45,12 @@ export async function PUT(request: NextRequest) { const body = await request.json(); if (!body.id) return NextResponse.json({ error: "id is required" }, { status: 400 }); const { id, ...data } = body; + if (data.date) { + const eventDate = new Date(data.date + "T23:59:59"); + if (eventDate < new Date()) { + return NextResponse.json({ error: "Дата не может быть в прошлом" }, { status: 400 }); + } + } updateOpenDayEvent(id, data); return NextResponse.json({ ok: true }); } catch (err) { diff --git a/src/app/api/admin/sections/[key]/route.ts b/src/app/api/admin/sections/[key]/route.ts index 5b5a17e..75956a5 100644 --- a/src/app/api/admin/sections/[key]/route.ts +++ b/src/app/api/admin/sections/[key]/route.ts @@ -24,7 +24,9 @@ export async function GET(_request: NextRequest, { params }: Params) { } } - return NextResponse.json(data); + return NextResponse.json(data, { + headers: { "Cache-Control": "private, max-age=60" }, + }); } export async function PUT(request: NextRequest, { params }: Params) { diff --git a/src/app/api/admin/team/route.ts b/src/app/api/admin/team/route.ts index fe5d8af..9068da6 100644 --- a/src/app/api/admin/team/route.ts +++ b/src/app/api/admin/team/route.ts @@ -5,7 +5,9 @@ import type { RichListItem, VictoryItem } from "@/types/content"; export async function GET() { const members = getTeamMembers(); - return NextResponse.json(members); + return NextResponse.json(members, { + headers: { "Cache-Control": "private, max-age=60" }, + }); } export async function POST(request: NextRequest) { diff --git a/src/app/api/admin/unread-counts/route.ts b/src/app/api/admin/unread-counts/route.ts index eb21d82..1431bf7 100644 --- a/src/app/api/admin/unread-counts/route.ts +++ b/src/app/api/admin/unread-counts/route.ts @@ -2,5 +2,7 @@ import { NextResponse } from "next/server"; import { getUnreadBookingCounts } from "@/lib/db"; export async function GET() { - return NextResponse.json(getUnreadBookingCounts()); + return NextResponse.json(getUnreadBookingCounts(), { + headers: { "Cache-Control": "private, max-age=15" }, + }); }