Skip to content

Commit

Permalink
Merge pull request #4881 from HSLdevcom/DT-5325
Browse files Browse the repository at this point in the history
DT-5904 (DT-5325) CO2 emissions
  • Loading branch information
optionsome authored Nov 22, 2023
2 parents d65ad5f + eee619d commit 4467949
Show file tree
Hide file tree
Showing 28 changed files with 585 additions and 11 deletions.
86 changes: 86 additions & 0 deletions app/component/Emissions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import PropTypes from 'prop-types';
import React from 'react';
import cx from 'classnames';
import { FormattedMessage } from 'react-intl';
import Icon from './Icon';
import ItineraryShape from '../prop-types/ItineraryShape';
import { getCo2Value } from '../util/itineraryUtils';

const Emissions = ({ itinerary, carItinerary, emissionsInfolink }) => {
const co2value = getCo2Value(itinerary);
const itineraryIsCar = itinerary.legs.every(
leg => leg.mode === 'CAR' || leg.mode === 'WALK',
);
const carCo2Value =
!itineraryIsCar && carItinerary
? Math.round(carItinerary?.emissionsPerPerson?.co2)
: null;
const useCo2SimpleDesc = !carCo2Value || itineraryIsCar;
const co2DescriptionId = useCo2SimpleDesc
? 'itinerary-co2.description-simple'
: 'itinerary-co2.description';

return (
co2value !== null &&
co2value >= 0 && (
<div className="itinerary-co2-comparison">
<div className="itinerary-co2-line">
<div className={cx('divider-top')} />
<div className="co2-container">
<div className="co2-description-container">
<Icon img="icon-icon_co2_leaf" className="co2-leaf" />
<span
className={cx('itinerary-co2-description', {
simple: useCo2SimpleDesc,
})}
>
<span aria-hidden="true">
<FormattedMessage
id={co2DescriptionId}
defaultMessage={`CO₂ emissions for this route: ${co2value} g`}
values={{
co2value,
carCo2Value,
}}
/>
</span>
<span className="sr-only">
<FormattedMessage
id={`${co2DescriptionId}-sr`}
defaultMessage={`Carbondioxide emissions for this route: ${co2value} g`}
values={{
co2value,
carCo2Value,
}}
/>
</span>
{emissionsInfolink && (
<a
className="emissions-info-link"
href={`${emissionsInfolink}`}
target="_blank"
rel="noreferrer"
>
<FormattedMessage
id="itinerary-co2.link"
defaultMessage="Näin vähennämme päästöjä ›"
/>
</a>
)}
</span>
</div>
</div>
<div className={cx('divider-bottom')} />
</div>
</div>
)
);
};

Emissions.propTypes = {
itinerary: ItineraryShape.isRequired,
carItinerary: ItineraryShape.isRequired,
emissionsInfolink: PropTypes.string.isRequired,
};

export default Emissions;
51 changes: 51 additions & 0 deletions app/component/EmissionsInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import PropTypes from 'prop-types';
import React from 'react';
import cx from 'classnames';
import { FormattedMessage } from 'react-intl';
import Icon from './Icon';
import ItineraryShape from '../prop-types/ItineraryShape';
import { getCo2Value } from '../util/itineraryUtils';

const EmissionsInfo = ({ itinerary, isMobile }) => {
const co2value = getCo2Value(itinerary);
return (
co2value !== null &&
co2value >= 0 && (
<div
className={cx('itinerary-co2-information', {
mobile: isMobile,
})}
>
<div className="itinerary-co2-line">
<div className={cx('co2-container', { mobile: isMobile })}>
<div className="co2-title-container">
<Icon img="icon-icon_co2_leaf" className="co2-leaf" />
<span aria-hidden="true" className="itinerary-co2-title">
<FormattedMessage
id="itinerary-co2.title"
defaultMessage="CO2 emissions for this route"
/>
</span>
<span className="sr-only">
<FormattedMessage
id="itinerary-co2.title-sr"
defaultMessage="CO2 emissions for this route"
/>
</span>
</div>
<div className="itinerary-co2-value-container">
<div className="itinerary-co2-value">{co2value} g</div>
</div>
</div>
</div>
</div>
)
);
};

EmissionsInfo.propTypes = {
itinerary: ItineraryShape.isRequired,
isMobile: PropTypes.bool.isRequired,
};

export default EmissionsInfo;
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ function ItinerarySummaryListContainer(
itineraries.length > 0 &&
!itineraries.includes(undefined)
) {
const lowestCo2value = Math.round(
itineraries
.filter(itinerary => itinerary.emissionsPerPerson?.co2 >= 0)
.reduce((a, b) => {
return a.emissionsPerPerson?.co2 < b.emissionsPerPerson?.co2 ? a : b;
}, 0).emissionsPerPerson?.co2,
);
const summaries = itineraries.map((itinerary, i) => (
<SummaryRow
refTime={searchTime}
Expand All @@ -72,6 +79,7 @@ function ItinerarySummaryListContainer(
zones={
config.zones.stops && itinerary.legs ? getZones(itinerary.legs) : []
}
lowestCo2value={lowestCo2value}
/>
));
if (
Expand Down Expand Up @@ -334,6 +342,9 @@ const containerComponent = createFragmentContainer(
walkDistance
startTime
endTime
emissionsPerPerson {
co2
}
legs {
realTime
realtimeState
Expand Down
18 changes: 17 additions & 1 deletion app/component/ItineraryTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import {
import CityBikeDurationInfo from './CityBikeDurationInfo';
import { getCityBikeNetworkId } from '../util/citybikes';
import { FareShape } from '../util/shapes';
import Emissions from './Emissions';
import EmissionsInfo from './EmissionsInfo';
import FareDisclaimer from './FareDisclaimer';

const AlertShape = PropTypes.shape({ alertSeverityLevel: PropTypes.string });
Expand All @@ -66,6 +68,9 @@ const ItineraryShape = PropTypes.shape({
}),
),
fares: PropTypes.arrayOf(FareShape),
emissionsPerPerson: PropTypes.shape({
co2: PropTypes.number,
}),
});

/* eslint-disable prettier/prettier */
Expand All @@ -80,6 +85,7 @@ class ItineraryTab extends React.Component {
isMobile: PropTypes.bool.isRequired,
currentTime: PropTypes.number.isRequired,
hideTitle: PropTypes.bool,
carItinerary: ItineraryShape,
currentLanguage: PropTypes.string,
changeHash: PropTypes.func,
};
Expand Down Expand Up @@ -183,7 +189,6 @@ class ItineraryTab extends React.Component {
if (!itinerary || !itinerary.legs[0]) {
return null;
}

const fares = getFares(itinerary.fares, getRoutes(itinerary.legs), config);
const extraProps = this.setExtraProps(itinerary);
const legsWithRentalBike = compressLegs(itinerary.legs).filter(leg =>
Expand Down Expand Up @@ -349,6 +354,7 @@ class ItineraryTab extends React.Component {
legs={itinerary.legs}
/>
)),
config.showCO2InItinerarySummary && <EmissionsInfo itinerary={itinerary} isMobile={this.props.isMobile} />,
<div
className={cx('momentum-scroll itinerary-tabs__scroll', {
multirow: extraProps.isMultiRow,
Expand All @@ -371,6 +377,13 @@ class ItineraryTab extends React.Component {
/>
{config.showRouteInformation && <RouteInformation />}
</div>
{config.showCO2InItinerarySummary &&
<Emissions
config={config}
itinerary={itinerary}
carItinerary={this.props.carItinerary}
emissionsInfolink={config.URL.EMISSIONS_INFO?.[currentLanguage]}
/>}
{this.shouldShowDisclaimer(config) && (
<div className="itinerary-disclaimer">
<FormattedMessage
Expand Down Expand Up @@ -421,6 +434,9 @@ const withRelay = createFragmentContainer(
}
type
}
emissionsPerPerson {
co2
}
legs {
mode
nextLegs(
Expand Down
3 changes: 3 additions & 0 deletions app/component/MobileItineraryWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { matchShape, routerShape } from 'found';
import { FormattedMessage, intlShape } from 'react-intl';
import ItineraryTab from './ItineraryTab';
import SwipeableTabs from './SwipeableTabs';
import ItineraryShape from '../prop-types/ItineraryShape';

const MobileItineraryWrapper = (props, context) => {
const index = props.params.secondHash
Expand Down Expand Up @@ -41,6 +42,7 @@ const MobileItineraryWrapper = (props, context) => {
focusToLeg={props.focusToLeg}
changeHash={props.changeHash}
isMobile
carItinerary={props.carItinerary}
/>
</div>
);
Expand Down Expand Up @@ -73,6 +75,7 @@ MobileItineraryWrapper.propTypes = {
plan: PropTypes.object,
serviceTimeRange: PropTypes.object.isRequired,
onSwipe: PropTypes.func,
carItinerary: ItineraryShape,
changeHash: PropTypes.func,
};

Expand Down
17 changes: 17 additions & 0 deletions app/component/SummaryPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,9 @@ class SummaryPage extends React.Component {
endTime
...ItineraryTab_itinerary
...SummaryPlanContainer_itineraries
emissionsPerPerson {
co2
}
legs {
mode
...ItineraryLine_legs
Expand Down Expand Up @@ -790,6 +793,9 @@ class SummaryPage extends React.Component {
endTime
...ItineraryTab_itinerary
...SummaryPlanContainer_itineraries
emissionsPerPerson {
co2
}
legs {
mode
...ItineraryLine_legs
Expand Down Expand Up @@ -849,6 +855,9 @@ class SummaryPage extends React.Component {
endTime
...ItineraryTab_itinerary
...SummaryPlanContainer_itineraries
emissionsPerPerson {
co2
}
legs {
mode
...ItineraryLine_legs
Expand Down Expand Up @@ -1029,6 +1038,9 @@ class SummaryPage extends React.Component {
endTime
...ItineraryTab_itinerary
...SummaryPlanContainer_itineraries
emissionsPerPerson {
co2
}
legs {
mode
...ItineraryLine_legs
Expand Down Expand Up @@ -2501,6 +2513,7 @@ class SummaryPage extends React.Component {
focusToPoint={this.focusToPoint}
focusToLeg={this.focusToLeg}
isMobile={false}
carItinerary={carPlan?.itineraries[0]}
/>
</div>
);
Expand Down Expand Up @@ -2732,6 +2745,7 @@ class SummaryPage extends React.Component {
serviceTimeRange={this.props.serviceTimeRange}
focusToLeg={this.focusToLeg}
onSwipe={this.changeHash}
carItinerary={carPlan?.itineraries[0]}
changeHash={this.changeHash}
>
{this.props.content &&
Expand Down Expand Up @@ -2961,6 +2975,9 @@ const containerComponent = createRefetchContainer(
endTime
...ItineraryTab_itinerary
...SummaryPlanContainer_itineraries
emissionsPerPerson {
co2
}
legs {
mode
...ItineraryLine_legs
Expand Down
6 changes: 6 additions & 0 deletions app/component/SummaryPlanContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,9 @@ const connectedContainer = createFragmentContainer(
itineraries {
startTime
endTime
emissionsPerPerson {
co2
}
legs {
mode
...ItineraryLine_legs
Expand Down Expand Up @@ -401,6 +404,9 @@ const connectedContainer = createFragmentContainer(
...ItinerarySummaryListContainer_itineraries
endTime
startTime
emissionsPerPerson {
co2
}
legs {
mode
to {
Expand Down
Loading

0 comments on commit 4467949

Please sign in to comment.