Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DT-6532: In vehicle cards #5160

Merged
merged 12 commits into from
Nov 14, 2024
4 changes: 2 additions & 2 deletions app/component/itinerary/ItineraryPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ import {
updateClient,
} from './ItineraryPageUtils';
import ItineraryTabs from './ItineraryTabs';
import NaviContainer from './NaviContainer';
import NavigatorIntroModal from './NavigatorIntro/NavigatorIntroModal';
import NaviContainer from './Navigator/NaviContainer';
import NavigatorIntroModal from './Navigator/NavigatorIntro/NavigatorIntroModal';
import planConnection from './PlanConnection';

const MAX_QUERY_COUNT = 4; // number of attempts to collect enough itineraries
Expand Down
68 changes: 0 additions & 68 deletions app/component/itinerary/NaviCardExtension.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import PropTypes from 'prop-types';
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { configShape } from '../../util/shapes';
import { epochToTime } from '../../util/timeUtils';
import { configShape } from '../../../util/shapes';
import { epochToTime } from '../../../util/timeUtils';

export default function NaviBottom({ setNavigation, arrival }, { config }) {
const remainingDuration = Math.ceil((arrival - Date.now()) / 60000); // ms to minutes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
import React from 'react';
import PropTypes from 'prop-types';
import { legShape } from '../../util/shapes';
import Icon from '../Icon';
import { isRental } from '../../util/legUtils';
import { legShape } from '../../../util/shapes';
import Icon from '../../Icon';
import { isRental } from '../../../util/legUtils';
import NaviInstructions from './NaviInstructions';
import NaviCardExtension from './NaviCardExtension';
import { LEGTYPE } from './NaviUtils';

const iconMap = {
BICYCLE: 'icon-icon_cyclist',
CAR: 'icon-icon_car-withoutBox',
SCOOTER: 'icon-icon_scooter_rider',
WALK: 'icon-icon_walk',
WAIT: 'icon-icon_navigation_wait',
BUS: 'icon-icon_bus',
RAIL: 'icon-icon_rail',
SUBWAY: 'icon-icon_subway',
TRAM: 'icon-icon_tram',
FERRY: 'icon-icon_ferry',
};

export default function NaviCard({ leg, nextLeg, legType, cardExpanded }) {
const iconName = legType === 'wait' ? iconMap.WAIT : iconMap[leg.mode];
const iconName = legType === LEGTYPE.WAIT ? iconMap.WAIT : iconMap[leg.mode];
let instructions = `navileg-${leg.mode.toLowerCase()}`;

if (isRental(leg, nextLeg)) {
if (legType === LEGTYPE.TRANSIT) {
instructions = `navileg-in-transit`;
} else if (isRental(leg, nextLeg)) {
if (leg.mode === 'WALK' && nextLeg?.mode === 'SCOOTER') {
instructions = `navileg-rent-scooter`;
} else {
Expand All @@ -28,8 +35,8 @@ export default function NaviCard({ leg, nextLeg, legType, cardExpanded }) {
return (
<div className="navi-top-card">
<div className="main-card">
<Icon img={iconName} color="black" className="mode" />
<div className="instructions">
<Icon img={iconName} className="mode" />
<div className={`instructions ${cardExpanded ? 'expanded' : ''}`}>
<NaviInstructions
leg={leg}
nextLeg={nextLeg}
Expand All @@ -44,17 +51,18 @@ export default function NaviCard({ leg, nextLeg, legType, cardExpanded }) {
</div>
</div>
</div>
{cardExpanded && <NaviCardExtension leg={leg} />}
{cardExpanded && <NaviCardExtension legType={legType} leg={leg} />}
</div>
);
}

NaviCard.propTypes = {
leg: legShape.isRequired,
nextLeg: legShape.isRequired,
nextLeg: legShape,
legType: PropTypes.string.isRequired,
cardExpanded: PropTypes.bool,
};
NaviCard.defaultProps = {
cardExpanded: false,
nextLeg: undefined,
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import React, { useEffect, useState, useRef } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage, intlShape } from 'react-intl';
import distance from '@digitransit-search-util/digitransit-search-util-distance';
import { legShape, configShape } from '../../util/shapes';
import { legTime, legTimeStr } from '../../util/legUtils';
import { legShape, configShape } from '../../../util/shapes';
import { legTime, legTimeStr } from '../../../util/legUtils';
import NaviCard from './NaviCard';
import NaviStack from './NaviStack';
import {
getItineraryAlerts,
getTransitLegState,
getAdditionalMessages,
LEGTYPE,
} from './NaviUtils';

const DESTINATION_RADIUS = 20; // meters
Expand Down Expand Up @@ -141,7 +142,7 @@ function NaviCardContainer(
}, [time]);

const { first, last } = getFirstLastLegs(realTimeLegs);

let legType;
let naviTopContent;
if (time < legTime(first.start)) {
naviTopContent = (
Expand All @@ -151,32 +152,42 @@ function NaviCardContainer(
/>
);
} else if (currentLeg) {
const nextLeg = realTimeLegs.find(leg => {
return legTime(leg.start) > legTime(currentLeg.start);
});
if (!currentLeg.transitLeg) {
const nextLeg = realTimeLegs.find(leg => {
return legTime(leg.start) > legTime(currentLeg.start);
});
let legType;
if (destCountRef.current >= TIME_AT_DESTINATION) {
legType = 'wait';
legType = LEGTYPE.WAIT;
} else {
legType = 'move';
legType = LEGTYPE.MOVE;
}
naviTopContent = (
<NaviCard
leg={currentLeg}
nextLeg={nextLeg}
cardExpanded={cardExpanded}
legType={legType}
/>
);
} else {
naviTopContent = `Tracking ${currentLeg?.mode} leg`;
legType = LEGTYPE.TRANSIT;
}
naviTopContent = (
<NaviCard
leg={currentLeg}
nextLeg={nextLeg}
cardExpanded={cardExpanded}
legType={legType}
/>
);
} else if (time > legTime(last.end)) {
naviTopContent = <FormattedMessage id="navigation-journey-end" />;
} else {
naviTopContent = <FormattedMessage id="navigation-wait" />;
}

// Card has 4 sizes: first leg collapsed, expanded
// and in transit collapsed, expanded.
let classPostfix = '';
if (legType === LEGTYPE.TRANSIT && cardExpanded) {
classPostfix = 'expand-transit';
} else if (legType === LEGTYPE.TRANSIT) {
classPostfix = 'transit';
} else if (cardExpanded) {
classPostfix = 'expanded';
}
const handleRemove = index => {
setActiveMessages(activeMessages.filter((_, i) => i !== index));
};
Expand All @@ -193,8 +204,8 @@ function NaviCardContainer(
{activeMessages.length > 0 && (
<NaviStack
messages={activeMessages}
cardExpanded={cardExpanded}
handleRemove={handleRemove}
classPostfix={classPostfix}
/>
)}
</>
Expand Down
113 changes: 113 additions & 0 deletions app/component/itinerary/Navigator/NaviCardExtension.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import React from 'react';
import cx from 'classnames';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import Icon from '../../Icon';
import StopCode from '../../StopCode';
import PlatformNumber from '../../PlatformNumber';
import { getZoneLabel, legTime } from '../../../util/legUtils';
import ZoneIcon from '../../ZoneIcon';
import { legShape, configShape } from '../../../util/shapes';
import { getDestinationProperties, LEGTYPE } from './NaviUtils';

import RouteNumberContainer from '../../RouteNumberContainer';

const NaviCardExtension = ({ legType, leg }, { config }) => {
const { stop, name } = leg.to;
const { code, platformCode, zoneId, vehicleMode } = stop || {};
const [place, address] = name?.split(/, (.+)/) || [];

let destination = {};
if (stop) {
destination = getDestinationProperties(leg, stop, config);
destination.name = stop.name;
} else {
destination.iconId = 'icon-icon_mapMarker-to';
destination.className = 'place';
destination.name = place;
}

if (legType === LEGTYPE.TRANSIT) {
const { intermediatePlaces } = leg;
const now = Date.now();
const idx = intermediatePlaces.findIndex(p => legTime(p.arrival) > now);

const count = idx > -1 ? intermediatePlaces.length - idx : 0;
const stopCount = <span className="realtime"> {count} </span>;
const translationId =
count === 1 ? 'navileg-one-stop-remaining' : 'navileg-stops-remaining';
return (
<div className="extension">
<div className="extension-divider" />
<div className="extension-routenumber">
<RouteNumberContainer
className={cx('line', vehicleMode.toLowerCase())}
route={leg.route}
mode={leg.mode.toLowerCase()}
isTransitLeg
vertical
withBar
/>
<div className="dest-name">{leg.to.name}</div>
</div>
<div className="stop-count">
<FormattedMessage
id={translationId}
values={{ stopCount }}
defaultMessage="{nrStopsRemaining} stops remaining"
/>
</div>
</div>
);
}

return (
<div className="extension">
<div className="extension-divider" />
<div className="extension-walk">
<Icon img="navi-expand" className="icon-expand" />
<Icon
img={destination.iconId}
height={2}
width={2}
className={`destination-icon ${destination.className}`}
/>
<div className="destination">
{destination.name}
<div className="details">
{!stop && address && <div className="address">{address}</div>}
{code && <StopCode code={code} />}
{platformCode && (
<PlatformNumber
number={platformCode}
short
isRailOrSubway={
vehicleMode === 'RAIL' || vehicleMode === 'SUBWAY'
}
/>
)}
<ZoneIcon
zoneId={getZoneLabel(zoneId, config)}
showUnknown={false}
/>
</div>
</div>
</div>
</div>
);
};

NaviCardExtension.propTypes = {
leg: legShape.isRequired,
legType: PropTypes.string,
};

NaviCardExtension.defaultProps = {
legType: '',
};

NaviCardExtension.contextTypes = {
config: configShape.isRequired,
};

export default NaviCardExtension;
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import PropTypes from 'prop-types';
import React from 'react';
import { legTime } from '../../util/legUtils';
import { itineraryShape, relayShape } from '../../util/shapes';
import { legTime } from '../../../util/legUtils';
import { itineraryShape, relayShape } from '../../../util/shapes';
import NaviBottom from './NaviBottom';
import NaviCardContainer from './NaviCardContainer';
import { useRealtimeLegs } from './hooks/useRealtimeLegs';
import { useRealtimeLegs } from '../hooks/useRealtimeLegs';

function NaviContainer(
{ itinerary, focusToLeg, relayEnvironment, setNavigation, mapRef },
Expand Down
Loading
Loading