Skip to content

Commit

Permalink
feat: Added route ladders to new minimal ladders page (#2583)
Browse files Browse the repository at this point in the history
* Added route ladders to new minimal ladders page

* Removed unused `findSelectedVehicleOrGhost`
  • Loading branch information
hannahpurcell authored May 8, 2024
1 parent 2d0b9b6 commit 3de1f3f
Show file tree
Hide file tree
Showing 9 changed files with 557 additions and 386 deletions.
4 changes: 3 additions & 1 deletion assets/src/components/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ export const AppRoutes = () => {
}, [path, setPath])

const vehiclesByRouteIdNeeded =
openView === OpenView.Late || location.pathname === "/"
openView === OpenView.Late ||
location.pathname === "/" ||
location.pathname === "/minimal"

const { socket } = useContext(SocketContext)
const vehiclesByRouteId: ByRouteId<(VehicleInScheduledService | Ghost)[]> =
Expand Down
44 changes: 1 addition & 43 deletions assets/src/components/ladderPage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import React, { ReactElement, useContext, useState, useEffect } from "react"
import RoutesContext from "../contexts/routesContext"
import { StateDispatchContext } from "../contexts/stateDispatchContext"
import useTimepoints from "../hooks/useTimepoints"
import {
RouteTab,
currentRouteTab,
Expand All @@ -10,10 +8,7 @@ import {
isPreset,
tabName,
} from "../models/routeTab"
import { allVehiclesAndGhosts } from "../models/vehiclesByRouteId"
import PickerContainer from "./pickerContainer"
import { Ghost, VehicleId, VehicleInScheduledService } from "../realtime.d"
import { ByRouteId, Route, RouteId, TimepointsByRouteId } from "../schedule.d"
import { Notifications } from "./notifications"
import Presets from "./presets"
import RouteLadders from "./routeLadders"
Expand All @@ -31,27 +26,11 @@ import {
import OldCloseButton from "./oldCloseButton"
import { SaveIcon, PlusThinIcon } from "../helpers/icon"
import { tagManagerEvent } from "../helpers/googleTagManager"
import useAlerts from "../hooks/useAlerts"
import { SocketContext } from "../contexts/socketContext"
import { fullStoryEvent } from "../helpers/fullStory"
import { usePanelStateFromStateDispatchContext } from "../hooks/usePanelState"

type DrawerContent = "route_picker" | "presets"

export const findRouteById = (
routes: Route[] | null,
routeId: RouteId
): Route | undefined => (routes || []).find((route) => route.id === routeId)

export const findSelectedVehicleOrGhost = (
vehiclesByRouteId: ByRouteId<(VehicleInScheduledService | Ghost)[]>,
selectedVehicleId: VehicleId | undefined
): VehicleInScheduledService | Ghost | undefined => {
return allVehiclesAndGhosts(vehiclesByRouteId).find(
(bus) => bus.id === selectedVehicleId
)
}

const LadderTab = ({
tab,
selectTab,
Expand Down Expand Up @@ -156,27 +135,8 @@ const LadderPage = (): ReactElement<HTMLDivElement> => {
ladderCrowdingToggles: {},
}

const routes: Route[] | null = useContext(RoutesContext)
const timepointsByRouteId: TimepointsByRouteId =
useTimepoints(selectedRouteIds)

const { socket } = useContext(SocketContext)
const alerts = useAlerts(socket, selectedRouteIds)
const routesWithAlerts = []

for (const routeId in alerts) {
if (alerts[routeId].length > 0) {
routesWithAlerts.push(routeId)
}
}

const [currentDrawerContent, setCurrentDrawerContent] =
useState<DrawerContent>("route_picker")

const selectedRoutes: Route[] = selectedRouteIds
.map((routeId) => findRouteById(routes, routeId))
.filter((route) => route) as Route[]

const pickerContainerVisibleClass = pickerContainerIsVisible
? "c-ladder-page--picker-container-visible"
: "c-ladder-page--picker-container-hidden"
Expand Down Expand Up @@ -248,8 +208,7 @@ const LadderPage = (): ReactElement<HTMLDivElement> => {
</div>

<RouteLadders
routes={selectedRoutes}
timepointsByRouteId={timepointsByRouteId}
selectedRouteIds={selectedRouteIds}
selectedVehicleId={selectedVehicleOrGhost?.id}
deselectRoute={(routeId) => dispatch(deselectRouteInTab(routeId))}
reverseLadder={(routeId) => dispatch(flipLadderInTab(routeId))}
Expand All @@ -258,7 +217,6 @@ const LadderPage = (): ReactElement<HTMLDivElement> => {
}
ladderDirections={ladderDirections}
ladderCrowdingToggles={ladderCrowdingToggles}
routesWithAlerts={routesWithAlerts}
/>
</div>
</div>
Expand Down
35 changes: 33 additions & 2 deletions assets/src/components/minimalLadderPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
import React from "react"
import React, { useContext } from "react"
import RouteLadders from "./routeLadders"
import { currentRouteTab } from "../models/routeTab"
import { StateDispatchContext } from "../contexts/stateDispatchContext"
import {
deselectRouteInTab,
flipLadderInTab,
toggleLadderCrowdingInTab,
} from "../state"

export const MinimalLadderPage = () => {
return <div>Placeholder for Minimal Route Ladders Page</div>
const [{ routeTabs }, dispatch] = useContext(StateDispatchContext)

const { selectedRouteIds, ladderDirections, ladderCrowdingToggles } =
currentRouteTab(routeTabs) || {
selectedRouteIds: [] as string[],
ladderDirections: {},
ladderCrowdingToggles: {},
}

return (
<div className="c-ladder-page__tab-bar-and-ladders">
<RouteLadders
selectedRouteIds={selectedRouteIds}
selectedVehicleId={undefined}
deselectRoute={(routeId) => dispatch(deselectRouteInTab(routeId))}
reverseLadder={(routeId) => dispatch(flipLadderInTab(routeId))}
toggleCrowding={(routeId) =>
dispatch(toggleLadderCrowdingInTab(routeId))
}
ladderDirections={ladderDirections}
ladderCrowdingToggles={ladderCrowdingToggles}
/>
</div>
)
}
36 changes: 29 additions & 7 deletions assets/src/components/routeLadders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,34 @@ import { ByRouteId, Route, TimepointsByRouteId, RouteId } from "../schedule.d"
import RouteLadder from "./routeLadder"
import { LadderDirections } from "../models/ladderDirection"
import { LadderCrowdingToggles } from "../models/ladderCrowdingToggle"
import RoutesContext from "../contexts/routesContext"
import useTimepoints from "../hooks/useTimepoints"
import { SocketContext } from "../contexts/socketContext"
import useAlerts from "../hooks/useAlerts"

export const findRouteById = (
routes: Route[] | null,
routeId: RouteId
): Route | undefined => (routes || []).find((route) => route.id === routeId)

interface Props {
routes: Route[]
timepointsByRouteId: TimepointsByRouteId
selectedRouteIds: string[]
selectedVehicleId: VehicleId | undefined
deselectRoute: (routeId: RouteId) => void
reverseLadder: (routeId: RouteId) => void
toggleCrowding: (routeId: RouteId) => void
ladderDirections: LadderDirections
ladderCrowdingToggles: LadderCrowdingToggles
routesWithAlerts: RouteId[]
}

const RouteLadders = ({
routes,
timepointsByRouteId,
selectedRouteIds,
selectedVehicleId,
deselectRoute,
reverseLadder,
toggleCrowding,
ladderDirections,
ladderCrowdingToggles,
routesWithAlerts,
}: Props) => {
const vehiclesByRouteId: ByRouteId<(VehicleInScheduledService | Ghost)[]> =
useContext(VehiclesByRouteIdContext)
Expand All @@ -41,14 +46,31 @@ const RouteLadders = ({
}
}

const routes: Route[] | null = useContext(RoutesContext)
const selectedRoutes: Route[] = selectedRouteIds
.map((routeId) => findRouteById(routes, routeId))
.filter((route) => route) as Route[]
const timepointsByRouteId: TimepointsByRouteId =
useTimepoints(selectedRouteIds)

const { socket } = useContext(SocketContext)
const alerts = useAlerts(socket, selectedRouteIds)
const routesWithAlerts: RouteId[] = []

for (const routeId in alerts) {
if (alerts[routeId].length > 0) {
routesWithAlerts.push(routeId)
}
}

return (
<div
className="c-route-ladders"
ref={laddersRef}
onWheel={onWheel}
data-testid="route-ladders-div"
>
{routes.map((route) => (
{selectedRoutes.map((route) => (
<RouteLadder
key={route.id}
route={route}
Expand Down
173 changes: 173 additions & 0 deletions assets/tests/components/__snapshots__/minimalLadderPage.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`RouteLadders renders a route ladder 1`] = `
<DocumentFragment>
<div
class="c-ladder-page__tab-bar-and-ladders"
>
<div
class="c-route-ladders"
data-testid="route-ladders-div"
>
<div
class="c-route-ladder__header"
>
<div
class="c-route-ladder__close-button-container"
>
<button
aria-label="Close"
class="c-close-button c-close-button--large c-close-button--darker"
>
<span
aria-hidden="true"
aria-label=""
role="img"
>
<svg />
</span>
</button>
</div>
<div
class="c-route-ladder__route-name"
>
1
</div>
</div>
<div
class="c-route-ladder__controls"
>
<button
class="c-route-ladder__reverse"
>
<span
class="c-route-ladder__reverse-icon"
>
<svg />
</span>
Reverse
</button>
</div>
<div
class="c-ladder"
style="width: 184px;"
>
<svg
class="c-ladder__svg"
height="0"
viewBox="-92 -55 184 0"
width="184"
>
<line
class="c-ladder__line"
x1="-40"
x2="-40"
y1="0"
y2="-110"
/>
<line
class="c-ladder__line"
x1="40"
x2="40"
y1="0"
y2="-110"
/>
<circle
class="c-ladder__stop-circle"
cx="-40"
cy="0"
r="3"
/>
<circle
class="c-ladder__stop-circle"
cx="40"
cy="0"
r="3"
/>
</svg>
<div
class="mock-tippy"
>
<div
class="mock-tippy-content"
>
WASMA Name
</div>
<text
class="c-ladder__timepoint-name"
dominant-baseline="middle"
text-anchor="middle"
x="0"
y="0"
>
WASMA
</text>
</div>
<circle
class="c-ladder__stop-circle"
cx="-40"
cy="-55"
r="3"
/>
<circle
class="c-ladder__stop-circle"
cx="40"
cy="-55"
r="3"
/>
<div
class="mock-tippy"
>
<div
class="mock-tippy-content"
>
MELWA Name
</div>
<text
class="c-ladder__timepoint-name"
dominant-baseline="middle"
text-anchor="middle"
x="0"
y="-55"
>
MELWA
</text>
</div>
<circle
class="c-ladder__stop-circle"
cx="-40"
cy="-110"
r="3"
/>
<circle
class="c-ladder__stop-circle"
cx="40"
cy="-110"
r="3"
/>
<div
class="mock-tippy"
>
<div
class="mock-tippy-content"
>
HHGAT Name
</div>
<text
class="c-ladder__timepoint-name"
dominant-baseline="middle"
text-anchor="middle"
x="0"
y="-110"
>
HHGAT
</text>
</div>
</div>
<div
class="c-incoming-box"
/>
</div>
</div>
</DocumentFragment>
`;
Loading

0 comments on commit 3de1f3f

Please sign in to comment.