weight edit fixes
Deploy / deploy-dev (push) Successful in 3m1s
Deploy / deploy-prod (push) Has been skipped

This commit is contained in:
Corey Blais
2026-06-16 15:28:01 -04:00
parent 4d3ab0b143
commit 1140be8f32
3 changed files with 17 additions and 31 deletions
-14
View File
@@ -318,15 +318,6 @@ const weightSchema = z.object({
recordedOn: dateStringSchema, recordedOn: dateStringSchema,
notes: z.string().trim().max(280).optional().or(z.literal('')), 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({ const vetVisitSchema = z.object({
visitedOn: dateStringSchema, visitedOn: dateStringSchema,
@@ -4185,11 +4176,6 @@ app.put(
return; 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( const weight = await updateWeightForBird(
req.params.weightId, req.params.weightId,
req.params.birdId, req.params.birdId,
+7 -1
View File
@@ -909,7 +909,13 @@ export const updateWeightForBird = async (
notes = $5 notes = $5
WHERE id = $1 WHERE id = $1
AND bird_id = $2 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`, RETURNING id, bird_id, weight_grams, recorded_on::text, notes`,
[weightId, birdId, weightGrams, recordedOn, notes], [weightId, birdId, weightGrams, recordedOn, notes],
); );
+10 -16
View File
@@ -917,13 +917,8 @@ const formatAuditAction = (value: string) =>
const formatWeight = (value: number | null) => (value ? `${value.toFixed(1)} g` : 'Pending'); 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 formatRange = (minGrams: number, maxGrams: number) => `${minGrams.toFixed(0)}-${maxGrams.toFixed(0)} g`;
const parseDateValue = (value: string) => new Date(`${value}T00:00:00`); const parseDateValue = (value: string) => new Date(`${value}T00:00:00`);
const WEIGHT_EDIT_WINDOW_DAYS = 3; const getEditableWeights = (entries: WeightRecord[]) =>
const getWeightEditEarliestDate = () => { [...entries].sort((left, right) => right.recordedOn.localeCompare(left.recordedOn)).slice(0, 3);
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) => const daysBetweenDates = (startDate: string, endDate: string) =>
Math.abs(parseDateValue(endDate).getTime() - parseDateValue(startDate).getTime()) / (24 * 60 * 60 * 1000); Math.abs(parseDateValue(endDate).getTime() - parseDateValue(startDate).getTime()) / (24 * 60 * 60 * 1000);
const addYearsToDate = (date: Date, years: number) => { const addYearsToDate = (date: Date, years: number) => {
@@ -1750,6 +1745,8 @@ function App() {
), ),
[allBirdWeights, birds, overviewWindowStartDate], [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); const showFlockDetailColumn = bulkWeightOpen || birdEditorOpen || Boolean(selectedBird);
@@ -3692,8 +3689,8 @@ function App() {
}; };
const handleEditWeight = (weight: WeightRecord) => { const handleEditWeight = (weight: WeightRecord) => {
if (!isWeightEditable(weight)) { if (!editableWeightIds.has(weight.id)) {
setError('Weight entries can only be edited for the last 3 days.'); setError('Only the 3 most recent weight entries can be edited.');
return; return;
} }
@@ -7068,8 +7065,7 @@ function App() {
<input <input
type="date" type="date"
value={weightForm.recordedOn} value={weightForm.recordedOn}
min={editingWeightId ? getWeightEditEarliestDate() : undefined} onChange={(event) => setWeightForm({ ...weightForm, recordedOn: event.target.value })}
onChange={(event) => setWeightForm({ ...weightForm, recordedOn: event.target.value })}
required required
/> />
</label> </label>
@@ -7094,10 +7090,8 @@ function App() {
</div> </div>
</form> </form>
<div className="recent-list"> <div className="recent-list">
{[...weights] {editableWeights
.filter(isWeightEditable) .map((weight) => (
.sort((left, right) => right.recordedOn.localeCompare(left.recordedOn))
.map((weight) => (
<article className="vet-visit-card" key={weight.id}> <article className="vet-visit-card" key={weight.id}>
<strong>{formatWeight(weight.weightGrams)}</strong> <strong>{formatWeight(weight.weightGrams)}</strong>
<span>{formatDate(weight.recordedOn)}</span> <span>{formatDate(weight.recordedOn)}</span>
@@ -7109,7 +7103,7 @@ function App() {
</div> </div>
</article> </article>
))} ))}
{!weights.some(isWeightEditable) ? <p className="muted">No editable weight entries from the last 3 days.</p> : null} {!editableWeights.length ? <p className="muted">No weight entries recorded yet.</p> : null}
</div> </div>
</section> </section>
</div> </div>