From 53b7d3452047f401758c3cb431f3f817a88d0f79 Mon Sep 17 00:00:00 2001 From: Corey Blais Date: Tue, 16 Jun 2026 10:00:50 -0400 Subject: [PATCH] trimmed weight edit --- backend/src/app.ts | 16 +++++- backend/src/repositories/birdRepository.ts | 1 + frontend/src/App.tsx | 59 +++++++++++++++------- 3 files changed, 56 insertions(+), 20 deletions(-) diff --git a/backend/src/app.ts b/backend/src/app.ts index 468de15..1a80316 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -306,6 +306,15 @@ const weightSchema = z.object({ recordedOn: dateStringSchema, notes: z.string().trim().max(280).optional().or(z.literal('')), }); +const weightEditWindowDays = 3; + +const getWeightEditEarliestDate = () => { + const earliestDate = new Date(); + earliestDate.setDate(earliestDate.getDate() - (weightEditWindowDays - 1)); + return earliestDate.toISOString().slice(0, 10); +}; + +const isWeightDateEditable = (recordedOn: string) => recordedOn >= getWeightEditEarliestDate(); const vetVisitSchema = z.object({ visitedOn: dateStringSchema, @@ -4094,6 +4103,11 @@ app.put( return; } + if (!isWeightDateEditable(parsed.data.recordedOn)) { + res.status(409).json({ error: 'Weight entries can only be edited for the last 3 days.' }); + return; + } + const weight = await updateWeightForBird( req.params.weightId, req.params.birdId, @@ -4103,7 +4117,7 @@ app.put( ); if (!weight) { - res.status(404).json({ error: 'Weight entry not found.' }); + res.status(404).json({ error: 'Weight entry not found or no longer editable.' }); return; } diff --git a/backend/src/repositories/birdRepository.ts b/backend/src/repositories/birdRepository.ts index 991975d..e82ff12 100644 --- a/backend/src/repositories/birdRepository.ts +++ b/backend/src/repositories/birdRepository.ts @@ -925,6 +925,7 @@ export const updateWeightForBird = async ( notes = $5 WHERE id = $1 AND bird_id = $2 + AND recorded_on >= CURRENT_DATE - (2 * INTERVAL '1 day') RETURNING id, bird_id, weight_grams, recorded_on::text, notes`, [weightId, birdId, weightGrams, recordedOn, notes], ); diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 6435066..53fa6da 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -876,6 +876,13 @@ const formatAuditAction = (value: string) => const formatWeight = (value: number | null) => (value ? `${value.toFixed(1)} g` : 'Pending'); const formatRange = (minGrams: number, maxGrams: number) => `${minGrams.toFixed(0)}-${maxGrams.toFixed(0)} g`; const parseDateValue = (value: string) => new Date(`${value}T00:00:00`); +const WEIGHT_EDIT_WINDOW_DAYS = 3; +const getWeightEditEarliestDate = () => { + const earliestDate = new Date(); + earliestDate.setDate(earliestDate.getDate() - (WEIGHT_EDIT_WINDOW_DAYS - 1)); + return earliestDate.toISOString().slice(0, 10); +}; +const isWeightEditable = (weight: WeightRecord) => weight.recordedOn >= getWeightEditEarliestDate(); const daysBetweenDates = (startDate: string, endDate: string) => Math.abs(parseDateValue(endDate).getTime() - parseDateValue(startDate).getTime()) / (24 * 60 * 60 * 1000); const addYearsToDate = (date: Date, years: number) => { @@ -3411,6 +3418,11 @@ function App() { }; const handleEditWeight = (weight: WeightRecord) => { + if (!isWeightEditable(weight)) { + setError('Weight entries can only be edited for the last 3 days.'); + return; + } + setEditingWeightId(weight.id); setWeightForm({ weightGrams: String(weight.weightGrams), @@ -6550,11 +6562,12 @@ function App() {