diff --git a/backend/src/app.ts b/backend/src/app.ts index 1a80316..7433c0c 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -306,15 +306,6 @@ 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, @@ -4103,11 +4094,6 @@ 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, diff --git a/backend/src/repositories/birdRepository.ts b/backend/src/repositories/birdRepository.ts index e82ff12..a25b500 100644 --- a/backend/src/repositories/birdRepository.ts +++ b/backend/src/repositories/birdRepository.ts @@ -925,7 +925,13 @@ export const updateWeightForBird = async ( notes = $5 WHERE id = $1 AND bird_id = $2 - AND recorded_on >= CURRENT_DATE - (2 * INTERVAL '1 day') + AND id IN ( + SELECT recent.id + FROM weight_records recent + WHERE recent.bird_id = $2 + ORDER BY recent.recorded_on DESC, recent.created_at DESC + LIMIT 3 + ) 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 5399d85..80b7d98 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -876,13 +876,8 @@ 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 getEditableWeights = (entries: WeightRecord[]) => + [...entries].sort((left, right) => right.recordedOn.localeCompare(left.recordedOn)).slice(0, 3); const daysBetweenDates = (startDate: string, endDate: string) => Math.abs(parseDateValue(endDate).getTime() - parseDateValue(startDate).getTime()) / (24 * 60 * 60 * 1000); const addYearsToDate = (date: Date, years: number) => { @@ -1735,6 +1730,8 @@ function App() { ), [allBirdWeights, birds, overviewWindowStartDate], ); + const editableWeights = useMemo(() => getEditableWeights(weights), [weights]); + const editableWeightIds = useMemo(() => new Set(editableWeights.map((weight) => weight.id)), [editableWeights]); const showFlockDetailColumn = bulkWeightOpen || birdEditorOpen || Boolean(selectedBird); @@ -3418,8 +3415,8 @@ function App() { }; const handleEditWeight = (weight: WeightRecord) => { - if (!isWeightEditable(weight)) { - setError('Weight entries can only be edited for the last 3 days.'); + if (!editableWeightIds.has(weight.id)) { + setError('Only the 3 most recent weight entries can be edited.'); return; } @@ -6564,8 +6561,7 @@ function App() { setWeightForm({ ...weightForm, recordedOn: event.target.value })} + onChange={(event) => setWeightForm({ ...weightForm, recordedOn: event.target.value })} required /> @@ -6590,10 +6586,8 @@ function App() {
- {[...weights] - .filter(isWeightEditable) - .sort((left, right) => right.recordedOn.localeCompare(left.recordedOn)) - .map((weight) => ( + {editableWeights + .map((weight) => (
{formatWeight(weight.weightGrams)} {formatDate(weight.recordedOn)} @@ -6605,7 +6599,7 @@ function App() {
))} - {!weights.some(isWeightEditable) ?

No editable weight entries from the last 3 days.

: null} + {!editableWeights.length ?

No weight entries recorded yet.

: null}