Skip to content

Commit

Permalink
feat(ts/hooks/usePanelState): add setTabMode API
Browse files Browse the repository at this point in the history
  • Loading branch information
firestack committed Nov 14, 2023
1 parent 3c65e3f commit 1bf2b0a
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 130 deletions.
18 changes: 16 additions & 2 deletions assets/src/components/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import MapPage from "./mapPage"
import SearchPage from "./searchPage"
import { OpenView, isPagePath } from "../state/pagePanelState"
import { usePanelStateFromStateDispatchContext } from "../hooks/usePanelState"
import PropertiesPanel from "./propertiesPanel"
import { isVehicleInScheduledService } from "../models/vehicle"

export const AppRoutes = () => {
useAppcues()
Expand All @@ -36,6 +38,8 @@ export const AppRoutes = () => {

const {
setPath,
setTabMode,
closeView,
currentView: { openView, selectedVehicleOrGhost, vppTabMode },
} = usePanelStateFromStateDispatchContext()

Expand Down Expand Up @@ -73,8 +77,18 @@ export const AppRoutes = () => {
<>
<Outlet />
<RightPanel
selectedVehicleOrGhost={selectedVehicleOrGhost}
initialTab={vppTabMode}
openView={openView}
propertiesPanel={
selectedVehicleOrGhost &&
isVehicleInScheduledService(selectedVehicleOrGhost) ? (
<PropertiesPanel
selectedVehicleOrGhost={selectedVehicleOrGhost}
tabMode={vppTabMode ?? "status"}
onChangeTabMode={setTabMode}
onClosePanel={closeView}
/>
) : undefined
}
/>
</>
}
Expand Down
39 changes: 13 additions & 26 deletions assets/src/components/rightPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,29 @@
import React, { ReactElement } from "react"
import { Ghost, Vehicle } from "../realtime.d"
import React, { ReactElement, ReactNode } from "react"
import NotificationDrawer from "./notificationDrawer"
import PropertiesPanel from "./propertiesPanel"
import SwingsView from "./swingsView"
import { OpenView } from "../state/pagePanelState"
import { usePanelStateFromStateDispatchContext } from "../hooks/usePanelState"
import { TabMode } from "./propertiesPanel/tabPanels"
import LateView from "./lateView"

const RightPanel = ({
selectedVehicleOrGhost,
initialTab,
}: {
selectedVehicleOrGhost?: Vehicle | Ghost | null
initialTab?: TabMode
}): ReactElement<HTMLElement> | null => {
const {
currentView: { openView },
closeView,
} = usePanelStateFromStateDispatchContext()
type RightPanelProps = {
openView: OpenView
propertiesPanel?: ReactNode
}

if (selectedVehicleOrGhost) {
return (
<PropertiesPanel.WithTabState
selectedVehicleOrGhost={selectedVehicleOrGhost}
onClosePanel={closeView}
initialTab={initialTab}
/>
)
const RightPanel = ({
openView,
propertiesPanel,
}: RightPanelProps): ReactElement | null => {
if (propertiesPanel !== undefined) {
return <>{propertiesPanel}</>
} else if (openView === OpenView.Swings) {
return <SwingsView />
} else if (openView === OpenView.Late) {
return <LateView />
} else if (openView === OpenView.NotificationDrawer) {
return <NotificationDrawer />
} else {
return null
}

return null
}

export default RightPanel
8 changes: 4 additions & 4 deletions assets/src/hooks/usePanelState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
openSwingsView,
selectVehicle,
setPath,
setTabMode,
} from "../state/pagePanelState"

/**
Expand Down Expand Up @@ -43,10 +44,9 @@ export const usePanelStateForViewState = (
dispatch(setPath(path))
}
},
openVehiclePropertiesPanel: (
vehicle: VehicleType,
initialView?: TabMode
) => dispatch(selectVehicle(vehicle, initialView ?? "status")),
setTabMode: (tabMode: TabMode) => dispatch(setTabMode(tabMode)),
openVehiclePropertiesPanel: (vehicle: VehicleType, initialView?: TabMode) =>
dispatch(selectVehicle(vehicle, initialView ?? "status")),
openLateView: () => dispatch(openLateView()),
openSwingsView: () => dispatch(openSwingsView()),
openNotificationDrawer: () => dispatch(openNotificaitonDrawer()),
Expand Down
21 changes: 21 additions & 0 deletions assets/src/state/pagePanelState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@ const openViewPanelReducer = (
vppTabMode,
}
}
case "SET_TAB_MODE": {
return state.selectedVehicleOrGhost
? {
...state,
vppTabMode: action.payload.tabMode,
}
: state
}
case "OPEN_NOTIFICATION_DRAWER":
return openView === OpenView.NotificationDrawer
? state
Expand Down Expand Up @@ -176,6 +184,13 @@ export const selectVehicle = (vehicle: VehicleType, tabMode: TabMode): SelectVeh
}
}

export const setTabMode = (tabMode: TabMode): SetVppTabMode => {
return {
type: "SET_TAB_MODE",
payload: { tabMode },
}
}

export const setPath = (path: PagePath): SetCurrentPath => {
return {
type: "SET_CURRENT_PATH",
Expand Down Expand Up @@ -228,6 +243,7 @@ export type PanelViewAction =
// Vehicles
| SelectVehicleAction
| SelectVehicleFromNotificationAction
| SetVppTabMode
// Views
| OpenNotificationDrawerAction
| OpenSwingsViewAction
Expand All @@ -240,6 +256,11 @@ interface SetCurrentPath {
payload: { path: PagePath }
}

interface SetVppTabMode {
type: "SET_TAB_MODE"
payload: { tabMode: TabMode }
}

interface SelectVehicleAction {
type: "SELECT_VEHICLE"
payload: {
Expand Down
95 changes: 13 additions & 82 deletions assets/tests/components/rightPanel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,14 @@ import { BrowserRouter } from "react-router-dom"
import "@testing-library/jest-dom/jest-globals"
import renderer from "react-test-renderer"
import RightPanel from "../../src/components/rightPanel"
import { StateDispatchProvider } from "../../src/contexts/stateDispatchContext"
import { State } from "../../src/state"
import * as dateTime from "../../src/util/dateTime"

import ghostFactory from "../factories/ghost"
import vehicleFactory from "../factories/vehicle"
import stateFactory from "../factories/applicationState"
import { RunFactory } from "../factories/run"
import { OpenView } from "../../src/state/pagePanelState"
import { viewFactory } from "../factories/pagePanelStateFactory"

const ghost = ghostFactory.build({ runId: "ghostrun-1" })
const vehicle = vehicleFactory.build()

jest
.spyOn(dateTime, "now")
Expand All @@ -30,7 +25,7 @@ describe("rightPanel", () => {
const tree = renderer
.create(
<BrowserRouter>
<RightPanel />
<RightPanel openView={OpenView.None} />
</BrowserRouter>
)
.toJSON()
Expand All @@ -40,112 +35,48 @@ describe("rightPanel", () => {
test("shows a selected vehicle", () => {
const { id: runId } = RunFactory.build()
const vehicle = vehicleFactory.build({ runId })
const state = stateFactory.build({
view: viewFactory
.currentState({ selectedVehicleOrGhost: vehicle })
.build(),
})

const result = render(
<StateDispatchProvider state={state} dispatch={jest.fn()}>
<BrowserRouter>
<RightPanel selectedVehicleOrGhost={vehicle} />
</BrowserRouter>
</StateDispatchProvider>
<RightPanel
openView={OpenView.None}
propertiesPanel={<button>{vehicle.runId!}</button>}
/>
)

expect(result.queryByRole("button", { name: vehicle.runId! })).toBeVisible()
})

test("shows a selected ghost", () => {
const state: State = stateFactory.build({
view: viewFactory
.currentState({
selectedVehicleOrGhost: ghost,
})
.build(),
})
const result = render(
<StateDispatchProvider state={state} dispatch={jest.fn()}>
<BrowserRouter>
<RightPanel selectedVehicleOrGhost={ghost} />
</BrowserRouter>
</StateDispatchProvider>
<RightPanel openView={OpenView.None} propertiesPanel={ghost.runId!} />
)
expect(result.queryByText(ghost.runId!)).toBeVisible()
})

test("shows notification drawer", () => {
const state: State = stateFactory.build({
view: viewFactory
.currentState({
openView: OpenView.NotificationDrawer,
})
.build(),
})
const result = render(
<StateDispatchProvider state={state} dispatch={jest.fn()}>
<BrowserRouter>
<RightPanel />
</BrowserRouter>
</StateDispatchProvider>
)
const result = render(<RightPanel openView={OpenView.NotificationDrawer} />)
expect(result.getByText("Notifications")).toBeVisible()
})

test("prefers VPP to notification drawer", () => {
const state: State = stateFactory.build({
view: viewFactory
.withVehicle()
.currentState({
openView: OpenView.NotificationDrawer,
})
.build(),
})
const result = render(
<StateDispatchProvider state={state} dispatch={jest.fn()}>
<BrowserRouter>
<RightPanel selectedVehicleOrGhost={vehicle} />
</BrowserRouter>
</StateDispatchProvider>
<RightPanel
openView={OpenView.NotificationDrawer}
propertiesPanel="Vehicles"
/>
)
expect(result.queryByText("Vehicles")).toBeVisible()
expect(result.queryByText("Notifications")).toBeNull()
})

test("shows swings view", () => {
const state: State = stateFactory.build({
view: viewFactory
.currentState({
openView: OpenView.Swings,
})
.build(),
})
const result = render(
<StateDispatchProvider state={state} dispatch={jest.fn()}>
<BrowserRouter>
<RightPanel />
</BrowserRouter>
</StateDispatchProvider>
)
const result = render(<RightPanel openView={OpenView.Swings} />)
expect(result.queryByText("Swings")).toBeVisible()
})

test("prefers VPP to swings view", () => {
const state: State = stateFactory.build({
view: viewFactory
.currentState({
selectedVehicleOrGhost: vehicle,
openView: OpenView.Swings,
})
.build(),
})
const result = render(
<StateDispatchProvider state={state} dispatch={jest.fn()}>
<BrowserRouter>
<RightPanel selectedVehicleOrGhost={vehicle} />
</BrowserRouter>
</StateDispatchProvider>
<RightPanel openView={OpenView.Swings} propertiesPanel="Vehicles" />
)
expect(result.queryByText("Vehicles")).toBeVisible()
expect(result.queryByText("Swings")).toBeNull()
Expand Down
8 changes: 4 additions & 4 deletions assets/tests/hooks/usePanelState.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
openSwingsView,
selectVehicle,
setPath,
setTabMode,
} from "../../src/state/pagePanelState"
import {
pageViewFactory,
Expand All @@ -39,14 +40,13 @@ describe("usePanelStateForViewState", () => {

test("sends TabMode", () => {
const mock = jest.fn()
const vehicle = vehicleFactory.build()
const tabMode = "block"

const cb = usePanelStateForViewState(viewFactory.build(), mock)

const tabMode = "block"
cb.openVehiclePropertiesPanel(vehicle, tabMode)
cb.setTabMode(tabMode)

expect(mock).toHaveBeenCalledWith(selectVehicle(vehicle, tabMode))
expect(mock).toHaveBeenCalledWith(setTabMode(tabMode))
})
})

Expand Down
Loading

0 comments on commit 1bf2b0a

Please sign in to comment.