// ABOUTME: API route for logging period start dates. // ABOUTME: Recalculates all phase dates when period is logged. import type { NextRequest } from "next/server"; import { NextResponse } from "next/server"; import { withAuth } from "@/lib/auth-middleware"; import { getCycleDay, getPhase } from "@/lib/cycle"; import { logger } from "@/lib/logger"; import { createPocketBaseClient } from "@/lib/pocketbase"; interface PeriodLogRequest { startDate?: string; } /** * Validates a date string is in YYYY-MM-DD format and represents a valid date. */ function isValidDateFormat(dateStr: string): boolean { const regex = /^\d{4}-\d{2}-\d{2}$/; if (!regex.test(dateStr)) { return false; } const date = new Date(dateStr); return !Number.isNaN(date.getTime()); } /** * Checks if a date is in the future (after today). */ function isFutureDate(dateStr: string): boolean { const inputDate = new Date(dateStr); const today = new Date(); today.setHours(0, 0, 0, 0); inputDate.setHours(0, 0, 0, 0); return inputDate > today; } export const POST = withAuth(async (request: NextRequest, user) => { try { const body = (await request.json()) as PeriodLogRequest; // Validate startDate is present if (!body.startDate) { return NextResponse.json( { error: "startDate is required" }, { status: 400 }, ); } // Validate date format if (!isValidDateFormat(body.startDate)) { return NextResponse.json( { error: "Invalid date format. Use YYYY-MM-DD" }, { status: 400 }, ); } // Validate date is not in the future if (isFutureDate(body.startDate)) { return NextResponse.json( { error: "startDate cannot be in the future" }, { status: 400 }, ); } const pb = createPocketBaseClient(); // Update user's lastPeriodDate await pb.collection("users").update(user.id, { lastPeriodDate: body.startDate, }); // Create PeriodLog record await pb.collection("period_logs").create({ user: user.id, startDate: body.startDate, }); // Calculate updated cycle information const lastPeriodDate = new Date(body.startDate); const cycleDay = getCycleDay(lastPeriodDate, user.cycleLength, new Date()); const phase = getPhase(cycleDay); // Log successful period logging per observability spec logger.info({ userId: user.id, date: body.startDate }, "Period logged"); return NextResponse.json({ message: "Period start date logged successfully", lastPeriodDate: body.startDate, cycleDay, phase, }); } catch (error) { logger.error({ err: error, userId: user.id }, "Period logging error"); return NextResponse.json( { error: "Failed to update period date" }, { status: 500 }, ); } });