mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-22 06:56:35 +00:00
fix(trips): count trip dates in calendar days, the same on REST and MCP
Filling in a missing end date and keeping a trip's length when its start moved both shifted a local-time Date, so a trip crossing a DST change lost or gained a day. Both now use addIsoDays. The one-date-makes-a-week default moves from the REST controller into TripsService.create, so the MCP create_trip tool no longer stores a half-dated trip, and the trip and its days are written in one transaction.
This commit is contained in:
@@ -442,6 +442,20 @@ describe('TripFormModal', () => {
|
||||
}));
|
||||
});
|
||||
|
||||
it('FE-COMP-TRIPFORM-038: moving the start across a DST change keeps the trip length in calendar days', async () => {
|
||||
const user = userEvent.setup();
|
||||
const onSave = vi.fn().mockResolvedValue({});
|
||||
const trip = buildTrip({ id: 1, title: 'Spring Trip', start_date: '2026-03-20', end_date: '2026-03-29' });
|
||||
render(<TripFormModal {...defaultProps} trip={trip} onSave={onSave} />);
|
||||
|
||||
await changeStartDate(user, '2026-03-25');
|
||||
await user.click(screen.getByRole('button', { name: /Update/i }));
|
||||
await user.click(await screen.findByRole('button', { name: /Update/i }));
|
||||
|
||||
await waitFor(() => expect(onSave).toHaveBeenCalled());
|
||||
expect(onSave).toHaveBeenCalledWith(expect.objectContaining({ start_date: '2026-03-25', end_date: '2026-04-03' }));
|
||||
});
|
||||
|
||||
it('FE-COMP-TRIPFORM-036: picking "Shift everything" sends shift_all', async () => {
|
||||
const user = userEvent.setup();
|
||||
const onSave = vi.fn().mockResolvedValue({});
|
||||
|
||||
@@ -11,7 +11,7 @@ import { useTranslation } from '../../i18n'
|
||||
import { CustomDatePicker } from '../shared/CustomDateTimePicker'
|
||||
import { normalizeImageFile } from '../../utils/convertHeic'
|
||||
import { getApiErrorMessage, type Trip } from '../../types'
|
||||
import { MAX_TRIP_DAYS, tripSpanDays, type TripCreateRequest } from '@trek/shared'
|
||||
import { MAX_TRIP_DAYS, addIsoDays, tripSpanDays, type TripCreateRequest } from '@trek/shared'
|
||||
import { NumericInput } from '../shared/NumericInput'
|
||||
import { currenciesWith, SYMBOLS } from '../Budget/BudgetPanel.constants'
|
||||
import TripDateReview, { dateReviewIsWide } from './TripDateReview'
|
||||
@@ -373,12 +373,9 @@ export default function TripFormModal({ isOpen, onClose, onSave, trip, onCoverUp
|
||||
if (!prev.end_date || prev.end_date < value) {
|
||||
next.end_date = value
|
||||
} else if (prev.start_date) {
|
||||
const oldStart = new Date(prev.start_date + 'T00:00:00Z')
|
||||
const oldEnd = new Date(prev.end_date + 'T00:00:00Z')
|
||||
const duration = Math.round((oldEnd.getTime() - oldStart.getTime()) / 86400000)
|
||||
const newEnd = new Date(value + 'T00:00:00Z')
|
||||
newEnd.setDate(newEnd.getDate() + duration)
|
||||
next.end_date = newEnd.toISOString().split('T')[0]
|
||||
// Keep the trip's length, counted in UTC calendar days: a local-time
|
||||
// shift across a DST change used to drop or add a day.
|
||||
next.end_date = addIsoDays(value, tripSpanDays(prev.start_date, prev.end_date) - 1)
|
||||
}
|
||||
}
|
||||
return next
|
||||
|
||||
Reference in New Issue
Block a user