Implement POST /api/cycle/period endpoint (P1.2)
Add period logging endpoint that allows users to record their period start date. This is a critical path item that unblocks GET /api/cycle/current and GET /api/today. Features: - Protected with withAuth middleware - Validates startDate is present, valid format (YYYY-MM-DD), and not in future - Updates user.lastPeriodDate in PocketBase - Creates PeriodLog record for historical tracking - Returns updated cycle information (cycleDay, phase) Tests: 8 tests covering authentication, validation, database operations, and error handling. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,96 @@
|
||||
// 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";
|
||||
|
||||
export async function POST() {
|
||||
// TODO: Implement period logging
|
||||
return NextResponse.json({ message: "Not implemented" }, { status: 501 });
|
||||
import { withAuth } from "@/lib/auth-middleware";
|
||||
import { getCycleDay, getPhase } from "@/lib/cycle";
|
||||
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);
|
||||
|
||||
return NextResponse.json({
|
||||
message: "Period start date logged successfully",
|
||||
lastPeriodDate: body.startDate,
|
||||
cycleDay,
|
||||
phase,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Period logging error:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Failed to update period date" },
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user