diff --git a/client/src/pages/TripPlannerPage.test.tsx b/client/src/pages/TripPlannerPage.test.tsx index 8f314c70..4babedc4 100644 --- a/client/src/pages/TripPlannerPage.test.tsx +++ b/client/src/pages/TripPlannerPage.test.tsx @@ -1160,7 +1160,7 @@ describe('TripPlannerPage', () => { }); describe('FE-PAGE-PLANNER-041: handleSaveReservation edit path covers update reservation', () => { - it('preserves the reservation day_id on edit so it stays in the Plan (#1237)', async () => { + it('does not force a day_id on edit so the server keeps/derives it (#1237)', async () => { vi.useFakeTimers(); seedTripStore({ id: 42 }); @@ -1196,12 +1196,10 @@ describe('TripPlannerPage', () => { }); }); - // The booking must keep its own day_id (not be nulled to the selected day). - expect(updateReservationSpy).toHaveBeenCalledWith( - expect.anything(), - 1, - expect.objectContaining({ day_id: 7 }), - ); + // The client must NOT send a day_id (no forcing to the selected day, no + // stale value) — the server keeps/derives it from the booking's date. + expect(updateReservationSpy).toHaveBeenCalled(); + expect(updateReservationSpy.mock.calls[0][2]).not.toHaveProperty('day_id'); }); }); diff --git a/client/src/pages/tripPlanner/useTripPlanner.ts b/client/src/pages/tripPlanner/useTripPlanner.ts index aef9c6a6..02bae54f 100644 --- a/client/src/pages/tripPlanner/useTripPlanner.ts +++ b/client/src/pages/tripPlanner/useTripPlanner.ts @@ -568,10 +568,12 @@ export function useTripPlanner() { const handleSaveReservation = async (data: Record & { title: string }) => { try { if (editingReservation) { - // Keep the reservation on its own day. Forcing selectedDayId here dropped - // the booking out of the Plan when edited from the Book tab (no day - // selected -> selectedDayId null -> day_id nulled). - const r = await tripActions.updateReservation(tripId, editingReservation.id, { ...data, day_id: editingReservation.day_id ?? null }) + // Don't force a day here. The old code pinned it to the (often empty) + // selected day, which dropped the booking out of the Plan; preserving the + // old day_id instead left it stale when the date changed. Omitting it lets + // the server derive the day from the booking's date, or keep the current + // one when there is no date. + const r = await tripActions.updateReservation(tripId, editingReservation.id, data) toast.success(t('trip.toast.reservationUpdated')) setShowReservationModal(false) setEditingReservation(null) diff --git a/server/tests/integration/reservations.test.ts b/server/tests/integration/reservations.test.ts index 9ff7fcc4..36c08f3a 100644 --- a/server/tests/integration/reservations.test.ts +++ b/server/tests/integration/reservations.test.ts @@ -200,6 +200,29 @@ describe('Update reservation', () => { expect(res.body.reservation.day_id).toBe(day2.id); }); + it('RESV-004c — re-dating a booking moves it to the matching day (start + end) (#1237)', async () => { + const { user } = createUser(testDb); + const trip = createTrip(testDb, user.id); + const day1 = createDay(testDb, trip.id, { date: '2025-10-01' }); + const day3 = createDay(testDb, trip.id, { date: '2025-10-03' }); + + // Booking sits on day 1 (start + end). + const created = await request(app) + .post(`/api/trips/${trip.id}/reservations`) + .set('Cookie', authCookie(user.id)) + .send({ title: 'Event', type: 'event', day_id: day1.id, reservation_time: '2025-10-01T09:00', reservation_end_time: '2025-10-01T10:00' }); + const rid = created.body.reservation.id; + + // Re-date to day 3 WITHOUT sending day_id (the modal omits it) — both ends follow. + const res = await request(app) + .put(`/api/trips/${trip.id}/reservations/${rid}`) + .set('Cookie', authCookie(user.id)) + .send({ title: 'Event', type: 'event', reservation_time: '2025-10-03T00:00', reservation_end_time: '2025-10-03T14:00' }); + expect(res.status).toBe(200); + expect(res.body.reservation.day_id).toBe(day3.id); + expect(res.body.reservation.end_day_id).toBe(day3.id); + }); + it('RESV-004 — PUT on non-existent reservation returns 404', async () => { const { user } = createUser(testDb); const trip = createTrip(testDb, user.id);