Skip to content

Commit

Permalink
Merge pull request #5169 from HSLdevcom/DT-6548
Browse files Browse the repository at this point in the history
DT-6548: Wait card
  • Loading branch information
vesameskanen authored Nov 21, 2024
2 parents 4f77b0c + f10b669 commit 33dd350
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 119 deletions.
4 changes: 4 additions & 0 deletions app/component/itinerary/PlanConnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ const planConnection = graphql`
name
lat
lon
vehicleMode
code
platformCode
zoneId
parentStation {
name
}
Expand Down
42 changes: 36 additions & 6 deletions app/component/itinerary/navigator/NaviCard.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types';
import { legShape } from '../../../util/shapes';
import Icon from '../../Icon';
Expand All @@ -20,18 +21,42 @@ const iconMap = {
FERRY: 'icon-icon_ferry',
};

export default function NaviCard({ leg, nextLeg, legType, cardExpanded }) {
export default function NaviCard({
leg,
nextLeg,
legType,
cardExpanded,
startTime,
}) {
if (legType === LEGTYPE.PENDING) {
return (
<FormattedMessage
id="navigation-journey-start"
values={{ time: startTime }}
/>
);
}
if (legType === LEGTYPE.END) {
return <FormattedMessage id="navigation-journey-end" />;
}
if (!leg && !nextLeg) {
return null;
}
const iconName = legType === LEGTYPE.WAIT ? iconMap.WAIT : iconMap[leg.mode];
let instructions = `navileg-${leg.mode.toLowerCase()}`;

let instructions = '';
if (legType === LEGTYPE.TRANSIT) {
instructions = `navileg-in-transit`;
} else if (isRental(leg, nextLeg)) {
} else if (legType !== LEGTYPE.WAIT && isRental(leg, nextLeg)) {
if (leg.mode === 'WALK' && nextLeg?.mode === 'SCOOTER') {
instructions = `navileg-rent-scooter`;
} else {
instructions = `navileg-rent-cycle`;
instructions = 'rent-cycle-at';
}
} else if (legType === LEGTYPE.MOVE) {
instructions = `navileg-${leg?.mode.toLowerCase()}`;
}

return (
<div className="navi-top-card">
<div className="main-card">
Expand All @@ -51,18 +76,23 @@ export default function NaviCard({ leg, nextLeg, legType, cardExpanded }) {
</div>
</div>
</div>
{cardExpanded && <NaviCardExtension legType={legType} leg={leg} />}
{cardExpanded && (
<NaviCardExtension legType={legType} leg={leg} nextLeg={nextLeg} />
)}
</div>
);
}

NaviCard.propTypes = {
leg: legShape.isRequired,
leg: legShape,
nextLeg: legShape,
legType: PropTypes.string.isRequired,
cardExpanded: PropTypes.bool,
startTime: PropTypes.string,
};
NaviCard.defaultProps = {
cardExpanded: false,
leg: undefined,
nextLeg: undefined,
startTime: '',
};
77 changes: 36 additions & 41 deletions app/component/itinerary/navigator/NaviCardContainer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, useState, useRef } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage, intlShape } from 'react-intl';
import { 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';
Expand All @@ -21,7 +21,9 @@ function getFirstLastLegs(legs) {
const last = legs[legs.length - 1];
return { first, last };
}

function getNextLeg(legs, time) {
return legs.find(leg => legTime(leg.start) > time);
}
function NaviCardContainer(
{ focusToLeg, time, realTimeLegs, position },
{ intl, config },
Expand All @@ -35,11 +37,25 @@ function NaviCardContainer(
const focusRef = useRef(false);
// Destination counter. How long user has been at the destination. * 10 seconds
const destCountRef = useRef(0);
const [topPosition, setTopPosition] = useState(0);
const cardRef = useRef(null);

const handleRemove = index => {
setActiveMessages(activeMessages.filter((_, i) => i !== index));
};

const handleClick = () => {
setCardExpanded(!cardExpanded);
};

useEffect(() => {
if (cardRef.current) {
const contentHeight = cardRef.current.clientHeight;
// Navistack top position depending on main card height.
setTopPosition(contentHeight + 86);
}
}, [currentLeg, cardExpanded]);

useEffect(() => {
const newLeg = realTimeLegs.find(leg => {
return legTime(leg.start) <= time && time <= legTime(leg.end);
Expand All @@ -60,9 +76,8 @@ function NaviCardContainer(
const l = currentLeg || newLeg;

if (l) {
const nextLeg = realTimeLegs.find(
leg => legTime(leg.start) > legTime(l.start),
);
const nextLeg = getNextLeg(realTimeLegs, legTime(l.start));

if (nextLeg?.transitLeg) {
// Messages for NaviStack.
const transitLegState = getTransitLegState(nextLeg, intl, messages);
Expand Down Expand Up @@ -143,18 +158,12 @@ function NaviCardContainer(

const { first, last } = getFirstLastLegs(realTimeLegs);
let legType;
let naviTopContent;
const t = currentLeg ? legTime(currentLeg.start) : time;
const nextLeg = getNextLeg(realTimeLegs, t);

if (time < legTime(first.start)) {
naviTopContent = (
<FormattedMessage
id="navigation-journey-start"
values={{ time: legTimeStr(first.start) }}
/>
);
legType = LEGTYPE.PENDING;
} else if (currentLeg) {
const nextLeg = realTimeLegs.find(leg => {
return legTime(leg.start) > legTime(currentLeg.start);
});
if (!currentLeg.transitLeg) {
if (destCountRef.current >= TIME_AT_DESTINATION) {
legType = LEGTYPE.WAIT;
Expand All @@ -164,33 +173,11 @@ function NaviCardContainer(
} else {
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" />;
legType = LEGTYPE.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';
legType = LEGTYPE.WAIT;
}
const handleRemove = index => {
setActiveMessages(activeMessages.filter((_, i) => i !== index));
};

return (
<>
Expand All @@ -199,13 +186,21 @@ function NaviCardContainer(
className={`navitop ${cardExpanded ? 'expanded' : ''}`}
onClick={handleClick}
>
<div className="content">{naviTopContent}</div>
<div className="content" ref={cardRef}>
<NaviCard
leg={currentLeg}
nextLeg={nextLeg}
cardExpanded={cardExpanded}
legType={legType}
startTime={legTimeStr(first.start)}
/>
</div>
</button>
{activeMessages.length > 0 && (
<NaviStack
messages={activeMessages}
handleRemove={handleRemove}
classPostfix={classPostfix}
topPosition={topPosition}
/>
)}
</>
Expand Down
30 changes: 20 additions & 10 deletions app/component/itinerary/navigator/NaviCardExtension.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,43 +12,51 @@ import { getDestinationProperties, LEGTYPE } from './NaviUtils';

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

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

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

if (legType === LEGTYPE.TRANSIT) {
const { intermediatePlaces } = leg;
const { intermediatePlaces, headsign, trip } = leg;
const hs = headsign || trip.tripHeadsign;
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';
const mode = leg.mode.toLowerCase();
return (
<div className="extension">
<div className="extension-divider" />
<div className="extension-routenumber">
<RouteNumberContainer
className={cx('line', vehicleMode.toLowerCase())}
className={cx('line', mode)}
route={leg.route}
mode={leg.mode.toLowerCase()}
mode={mode}
isTransitLeg
vertical
withBar
/>
<div className="dest-name">{leg.to.name}</div>
<div className="headsign">{hs}</div>
</div>
<div className="stop-count">
<FormattedMessage
Expand All @@ -60,7 +68,6 @@ const NaviCardExtension = ({ legType, leg }, { config }) => {
</div>
);
}

return (
<div className="extension">
<div className="extension-divider" />
Expand Down Expand Up @@ -98,12 +105,15 @@ const NaviCardExtension = ({ legType, leg }, { config }) => {
};

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

NaviCardExtension.defaultProps = {
legType: '',
leg: undefined,
nextLeg: undefined,
};

NaviCardExtension.contextTypes = {
Expand Down
Loading

0 comments on commit 33dd350

Please sign in to comment.