diff --git a/client/src/components/Planner/DayPlanSidebar.test.tsx b/client/src/components/Planner/DayPlanSidebar.test.tsx index 6da09aeee..3c29bb8c0 100644 --- a/client/src/components/Planner/DayPlanSidebar.test.tsx +++ b/client/src/components/Planner/DayPlanSidebar.test.tsx @@ -353,6 +353,38 @@ describe('DayPlanSidebar', () => { expect(onOpenTransit).toHaveBeenCalledWith(expect.objectContaining({ id: 300 })) }) + it('FE-PLANNER-DAYPLAN-105: the transit row folds its itinerary out inline (#1065)', async () => { + const user = userEvent.setup() + const day = buildDay({ id: 10, date: '2025-06-01', title: 'Day 1' }) + const res = { + ...buildReservation({ id: 301, type: 'transit', title: 'A → B', reservation_time: '2025-06-01T08:30:00', day_id: 10 }), + metadata: { + transit: { + provider: 'transitous', duration: 1800, transfers: 1, walk_seconds: 240, + legs: [ + { mode: 'WALK', duration: 240, from: { name: 'Start' }, to: { name: 'Alexanderplatz' } }, + { mode: 'SUBWAY', line: 'U2', line_color: '#FF3300', headsign: 'Ruhleben', duration: 1440, stops: 6, from: { name: 'Alexanderplatz', time: '08:36', track: '2' }, to: { name: 'Zoo', time: '09:00' } }, + ], + }, + }, + endpoints: [ + { role: 'from', sequence: 0, name: 'A', code: null, lat: 1, lng: 2, timezone: null, local_date: null, local_time: null }, + { role: 'to', sequence: 1, name: 'B', code: null, lat: 3, lng: 4, timezone: null, local_date: null, local_time: null }, + ], + } + const onToggleConnection = vi.fn() + render() + // No map-connections toggle on transit rows — the expander replaces it. + expect(screen.queryByTitle(/connections/i)).not.toBeInTheDocument() + // Collapsed: no stop names beyond the chips. + expect(screen.queryByText('Alexanderplatz')).not.toBeInTheDocument() + await user.click(screen.getByLabelText('Expand')) + expect(await screen.findByText('Alexanderplatz')).toBeInTheDocument() + expect(screen.getByText(/Platform 2/)).toBeInTheDocument() + await user.click(screen.getByLabelText('Collapse')) + expect(screen.queryByText('Alexanderplatz')).not.toBeInTheDocument() + }) + // ── Day info button ───────────────────────────────────────────────────── it('FE-PLANNER-DAYPLAN-018: clicking day header calls onDayDetail', async () => { diff --git a/client/src/components/Planner/DayPlanSidebar.tsx b/client/src/components/Planner/DayPlanSidebar.tsx index f78ab874e..f28b8a118 100644 --- a/client/src/components/Planner/DayPlanSidebar.tsx +++ b/client/src/components/Planner/DayPlanSidebar.tsx @@ -37,7 +37,7 @@ import { DayPlanSidebarToolbar } from './DayPlanSidebarToolbar' import { DayPlanSidebarNoteModal } from './DayPlanSidebarNoteModal' import { DayPlanSidebarTimeConfirmModal } from './DayPlanSidebarTimeConfirmModal' import { DayPlanSidebarTransportDetailModal } from './DayPlanSidebarTransportDetailModal' -import { TransitTitle, TransitLegChips } from './transitDisplay' +import { TransitTitle, TransitLegChips, TransitItineraryInline } from './transitDisplay' import { DayPlanSidebarFooter } from './DayPlanSidebarFooter' import type { Trip, Day, Place, Category, Assignment, Accommodation, Reservation, AssignmentsMap, RouteResult, RouteSegment, DayNote } from '../../types' import { getGoogleMapsUrlForPlace } from './placeGoogleMaps' @@ -187,6 +187,8 @@ function useDayPlanSidebar(props: DayPlanSidebarProps) { const [pdfHover, setPdfHover] = useState(false) const [icsHover, setIcsHover] = useState(false) const [hoveredAssignmentId, setHoveredAssignmentId] = useState(null) + // Transit rows fold their itinerary out inline (#1065). + const [expandedTransitIds, setExpandedTransitIds] = useState>(new Set()) const [dropTargetKey, _setDropTargetKey] = useState(null) const dropTargetRef = useRef(null) const setDropTargetKey = (key) => { dropTargetRef.current = key; _setDropTargetKey(key) } @@ -1010,6 +1012,8 @@ function useDayPlanSidebar(props: DayPlanSidebarProps) { onPlanTransit, onOpenTransit, onEditTransport, + expandedTransitIds, + setExpandedTransitIds, onEditReservation, onAddBookingToAssignment, initialScrollTop, @@ -1173,6 +1177,8 @@ const DayPlanSidebar = React.memo(function DayPlanSidebar(props: DayPlanSidebarP onPlanTransit, onOpenTransit, onEditTransport, + expandedTransitIds, + setExpandedTransitIds, onEditReservation, onAddBookingToAssignment, initialScrollTop, @@ -2097,7 +2103,34 @@ const DayPlanSidebar = React.memo(function DayPlanSidebar(props: DayPlanSidebarP )} - {onToggleConnection && (!res.__leg || res.__leg.index === 0) && (res.endpoints || []).length >= 2 && (() => { + {transitMeta && (() => { + const expanded = expandedTransitIds.has(res.id) + return ( + + ) + })()} + {!transitMeta && onToggleConnection && (!res.__leg || res.__leg.index === 0) && (res.endpoints || []).length >= 2 && (() => { const active = visibleConnectionIds.includes(res.id) return (