From e8fbba236d2c933059c2e981ba34303a5f0932af Mon Sep 17 00:00:00 2001 From: Maurice Date: Thu, 29 Oct 2026 15:50:09 +0100 Subject: [PATCH] refactor(bookings): hand the notes and link to the shared lower part as form fields The booking and transport dialogs each spelled out the notes and the link as four value and change props, and with the saving flag the two calls became one copied block. The shared lower part now takes the form and its setter, as the dialogs hold them, and writes the two fields itself. --- .../Planner/BookingNotesFilesCosts.test.tsx | 11 +++++----- .../Planner/BookingNotesFilesCosts.tsx | 20 ++++++++----------- .../components/Planner/ReservationModal.tsx | 6 ++---- .../src/components/Planner/TransportModal.tsx | 6 ++---- 4 files changed, 17 insertions(+), 26 deletions(-) diff --git a/client/src/components/Planner/BookingNotesFilesCosts.test.tsx b/client/src/components/Planner/BookingNotesFilesCosts.test.tsx index 37e88f3f5..741631fb4 100644 --- a/client/src/components/Planner/BookingNotesFilesCosts.test.tsx +++ b/client/src/components/Planner/BookingNotesFilesCosts.test.tsx @@ -28,10 +28,8 @@ function setup(overrides: Partial = {}) { linkAndFiles.mockClear(); costs.mockClear(); const props: Props = { - notes: 'Gate B', - onNotesChange: vi.fn(), - url: 'https://example.com', - onUrlChange: vi.fn(), + form: { notes: 'Gate B', url: 'https://example.com' }, + set: vi.fn(), reservationId: 9, tripFiles: [], pendingFiles: [], @@ -61,7 +59,7 @@ describe('BookingNotesFilesCosts', () => { const area = screen.getByPlaceholderText('Additional notes...'); expect(area).toHaveValue('Gate B'); fireEvent.change(area, { target: { value: 'Gate C' } }); - expect(props.onNotesChange).toHaveBeenCalledWith('Gate C'); + expect(props.set).toHaveBeenCalledWith('notes', 'Gate C'); }); it('FE-PLANNER-NOTESFILESCOSTS-002: hands the link, the files and the costs their parts of the booking', () => { @@ -70,7 +68,6 @@ describe('BookingNotesFilesCosts', () => { expect(linkAndFiles).toHaveBeenCalledWith( expect.objectContaining({ url: 'https://example.com', - onUrlChange: props.onUrlChange, reservationId: 9, canAttach: true, uploading: false, @@ -80,6 +77,8 @@ describe('BookingNotesFilesCosts', () => { onDetached: props.attach.detachFile, }) ); + linkAndFiles.mock.calls[0][0].onUrlChange('https://example.org'); + expect(props.set).toHaveBeenCalledWith('url', 'https://example.org'); expect(costs).toHaveBeenCalledWith( expect.objectContaining({ reservationId: 9, diff --git a/client/src/components/Planner/BookingNotesFilesCosts.tsx b/client/src/components/Planner/BookingNotesFilesCosts.tsx index fe7584f9a..2d45b08ea 100644 --- a/client/src/components/Planner/BookingNotesFilesCosts.tsx +++ b/client/src/components/Planner/BookingNotesFilesCosts.tsx @@ -13,10 +13,8 @@ import type { useBookingFileAttach } from './useBookingFileAttach'; * files row, and the costs linked to this booking when the budget addon is on. */ export function BookingNotesFilesCosts({ - notes, - onNotesChange, - url, - onUrlChange, + form, + set, reservationId, tripFiles, pendingFiles, @@ -28,10 +26,8 @@ export function BookingNotesFilesCosts({ pendingExpense, expense, }: { - notes: string; - onNotesChange: (notes: string) => void; - url: string; - onUrlChange: (url: string) => void; + form: { notes: string; url: string }; + set: (field: 'notes' | 'url', value: string) => void; /** The saved booking; unset while it is being created. */ reservationId: number | undefined; tripFiles: TripFile[]; @@ -50,8 +46,8 @@ export function BookingNotesFilesCosts({ <>