diff --git a/client/src/components/Planner/TransitJourneyModal.test.tsx b/client/src/components/Planner/TransitJourneyModal.test.tsx index f0756e049..00b8829cc 100644 --- a/client/src/components/Planner/TransitJourneyModal.test.tsx +++ b/client/src/components/Planner/TransitJourneyModal.test.tsx @@ -1,4 +1,4 @@ -// FE-PLANNER-TRANSITJOURNEY-001 to 016 — the journey view for a saved transit entry. +// FE-PLANNER-TRANSITJOURNEY-001 to 018 — the journey view for a saved transit entry. import { render, screen, waitFor, fireEvent } from '../../../tests/helpers/render' import userEvent from '@testing-library/user-event' import { resetAllStores, seedStore } from '../../../tests/helpers/store' @@ -113,6 +113,21 @@ describe('TransitJourneyModal', () => { expect(onChangeRoute).toHaveBeenCalled() }) + it('FE-PLANNER-TRANSITJOURNEY-017: edit details hands off to the full transport editor', async () => { + const user = userEvent.setup() + const onEditDetails = vi.fn() + render() + await user.click(screen.getByRole('button', { name: /Edit details/ })) + expect(onEditDetails).toHaveBeenCalled() + }) + + it('FE-PLANNER-TRANSITJOURNEY-018: edit details stays hidden without the callback or edit rights', () => { + const { rerender } = render() + expect(screen.queryByRole('button', { name: /Edit details/ })).not.toBeInTheDocument() + rerender() + expect(screen.queryByRole('button', { name: /Edit details/ })).not.toBeInTheDocument() + }) + it('FE-PLANNER-TRANSITJOURNEY-004: delete asks for confirmation, then calls onDelete', async () => { const user = userEvent.setup() const onDelete = vi.fn().mockResolvedValue({}) diff --git a/client/src/components/Planner/TransitJourneyModal.tsx b/client/src/components/Planner/TransitJourneyModal.tsx index 37cda8949..c4d41e8a9 100644 --- a/client/src/components/Planner/TransitJourneyModal.tsx +++ b/client/src/components/Planner/TransitJourneyModal.tsx @@ -15,7 +15,9 @@ import type { Reservation } from '../../types' * The journey view for an automated public-transit entry (#1065): a roomy modal * around the stop-by-stop itinerary. The title renames inline right in the * header, notes get the full width with markdown support, and "Change route" - * re-enters the transit search pre-seeded with this journey's route. + * re-enters the transit search pre-seeded with this journey's route. "Edit + * details" hands off to the full transport editor for the booking fields + * (travelers, costs, files, code, status — #2148). */ interface TransitLegMeta { @@ -38,10 +40,12 @@ interface TransitJourneyModalProps { onSave: (fields: { title: string; notes: string | null }) => Promise onDelete: () => Promise onChangeRoute: () => void + /** Switch to the full transport editor (travelers, costs, files, code, status). */ + onEditDetails?: () => void canEdit: boolean } -export default function TransitJourneyModal({ reservation, onClose, onSave, onDelete, onChangeRoute, canEdit }: TransitJourneyModalProps) { +export default function TransitJourneyModal({ reservation, onClose, onSave, onDelete, onChangeRoute, onEditDetails, canEdit }: TransitJourneyModalProps) { const { t, locale } = useTranslation() const isMobile = typeof window !== 'undefined' && window.innerWidth < 768 const timeFormat = useSettingsStore(st => st.settings.time_format) || '24h' @@ -160,6 +164,15 @@ export default function TransitJourneyModal({ reservation, onClose, onSave, onDe {t('transit.changeRoute')} )} + {canEdit && onEditDetails && ( + + )} {canEdit ? (