diff --git a/assets/css/map/markers/_vehicle_marker.scss b/assets/css/map/markers/_vehicle_marker.scss index aa630d165..6557c80ee 100644 --- a/assets/css/map/markers/_vehicle_marker.scss +++ b/assets/css/map/markers/_vehicle_marker.scss @@ -33,6 +33,25 @@ stroke-width: 1.5; filter: drop-shadow(1px 1px 4px $color-eggplant-400); } + + &.c-vehicle-marker--shuttle { + // Shuttle Colors + &.c-vehicle-marker--blue { + fill: var(--color-blue-line); + } + &.c-vehicle-marker--orange { + fill: var(--color-orange-line); + } + &.c-vehicle-marker--green { + fill: var(--color-green-line); + } + &.c-vehicle-marker--red { + fill: var(--color-red-line); + } + &.c-vehicle-marker--cr { + fill: var(--color-cr-line); + } + } } .c-vehicle-map__label { diff --git a/assets/src/components/map/markers/vehicleMarker.tsx b/assets/src/components/map/markers/vehicleMarker.tsx index de21ec1fa..20efe3612 100644 --- a/assets/src/components/map/markers/vehicleMarker.tsx +++ b/assets/src/components/map/markers/vehicleMarker.tsx @@ -2,16 +2,19 @@ import { LatLngExpression, Marker } from "leaflet" import React, { PropsWithChildren, useContext, + useEffect, useRef, useState, - useEffect, } from "react" import { StateDispatchContext } from "../../../contexts/stateDispatchContext" import { joinClasses } from "../../../helpers/dom" import { vehicleLabel } from "../../../helpers/vehicleLabel" -import { statusClasses, drawnStatus } from "../../../models/vehicleStatus" - +import { + shuttleVariantFromRunId, + ShuttleVariant, +} from "../../../models/shuttle" +import { drawnStatus, statusClasses } from "../../../models/vehicleStatus" import { Vehicle } from "../../../realtime" import { ReactMarker } from "../utilities/reactMarker" @@ -24,6 +27,41 @@ interface VehicleMarkerProps extends PropsWithChildren { onShouldShowPopupChange?: (newValue: boolean) => void } +/** + * If the supplied {@linkcode vehicle} is a shuttle, returns + * classes to more specifically style shuttles matching certain conditions. + * For example, specific styles depending on Rapid Transit Line the shuttle is + * associated with. + * + * @param vehicle The vehicle to return styles for + * @returns Array of classes to add to a vehicle marker + */ +const stylesForShuttle = (vehicle: Vehicle) => { + // If this vehicle isn't a shuttle, return no styles + if (vehicle.isShuttle === false) { + return [] + } + + // Otherwise return a generic shuttle class and any more + // specific styles for the shuttle. + const classFor = (variant: string) => `c-vehicle-marker--${variant}` + const shuttleClasses = ["c-vehicle-marker--shuttle"] + switch (vehicle.runId && shuttleVariantFromRunId(vehicle.runId)) { + case ShuttleVariant.Blue: + return shuttleClasses.concat(classFor("blue")) + case ShuttleVariant.CommuterRail: + return shuttleClasses.concat(classFor("cr")) + case ShuttleVariant.Green: + return shuttleClasses.concat(classFor("green")) + case ShuttleVariant.Orange: + return shuttleClasses.concat(classFor("orange")) + case ShuttleVariant.Red: + return shuttleClasses.concat(classFor("red")) + default: + return shuttleClasses + } +} + export const VehicleMarker = ({ children, vehicle, @@ -95,7 +133,10 @@ export const VehicleMarker = ({ }} icon={ { + switch (runId) { + case "999-0501": + return ShuttleVariant.Blue + case "999-0502": + return ShuttleVariant.Green + case "999-0503": + return ShuttleVariant.Orange + case "999-0504": + return ShuttleVariant.Red + case "999-0505": + return ShuttleVariant.CommuterRail + case "999-0555": + return ShuttleVariant.Special + default: + return null + } +} export const formattedRunNumber = ({ runId }: Vehicle): string => { if (runId === null) { diff --git a/assets/tests/components/__snapshots__/shuttleMapPage.test.tsx.snap b/assets/tests/components/__snapshots__/shuttleMapPage.test.tsx.snap index 9a84593e4..053ab3313 100644 --- a/assets/tests/components/__snapshots__/shuttleMapPage.test.tsx.snap +++ b/assets/tests/components/__snapshots__/shuttleMapPage.test.tsx.snap @@ -214,7 +214,7 @@ exports[`Shuttle Map Page renders 1`] = ` tabindex="0" > ( @@ -38,4 +38,75 @@ describe("VehicleMarker", () => { expect(container.querySelector(".c-vehicle-map__icon")).toBeInTheDocument() expect(screen.getByText("101")).toBeInTheDocument() }) + + describe.each([ + { + forRunId: "999-0501", + assertSpecialClass: ".c-vehicle-marker--blue", + }, + { + forRunId: "999-0502", + assertSpecialClass: ".c-vehicle-marker--green", + }, + { + forRunId: "999-0503", + assertSpecialClass: ".c-vehicle-marker--orange", + }, + { + forRunId: "999-0504", + assertSpecialClass: ".c-vehicle-marker--red", + }, + { + forRunId: "999-0505", + assertSpecialClass: ".c-vehicle-marker--cr", + }, + { + forRunId: "999-0555", + assertSpecialClass: null, + }, + { + forRunId: "101", + assertSpecialClass: null, + }, + ])( + "when vehicle is shuttle with runId:`$forRunId`", + ({ forRunId, assertSpecialClass }) => { + test("should render with shuttle class", () => { + const { container } = render( + , + { + wrapper: TestMap, + } + ) + + expect( + container.querySelector(".c-vehicle-marker--shuttle") + ).toBeInTheDocument() + }) + + assertSpecialClass !== null && + test(`should render with class \`${assertSpecialClass}\``, () => { + const { container } = render( + , + { + wrapper: TestMap, + } + ) + + expect( + container.querySelector(assertSpecialClass) + ).toBeInTheDocument() + }) + } + ) })