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 ? (