Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
5a92b12
feat: add general purpose disclaimer card
vesameskanen Jan 21, 2026
cc8de76
feat: use new disclaimer in city bike view
vesameskanen Jan 22, 2026
332be1e
fix: lint
vesameskanen Jan 22, 2026
dc6bdb0
fix: add space between elements
vesameskanen Jan 22, 2026
44db6ea
fix: close icon position to the right end
vesameskanen Jan 22, 2026
9ba4edf
feat: use new diclaimer component for nearyou city bikes
vesameskanen Jan 22, 2026
b1def3b
feat: hover style for disclaimer link
vesameskanen Jan 22, 2026
2d0d1d5
chore: update park & ride disclaimer translations
vesameskanen Jan 22, 2026
31e8b69
feat: add hover style to fully clickable park near you items
vesameskanen Jan 22, 2026
62c57ca
chore: remove some unused styles, rename
vesameskanen Jan 22, 2026
8d7e07d
feat: hover style for disclaimer closing cross
vesameskanen Jan 23, 2026
c06b005
feat: allow definition of all content parts as translation ids.
vesameskanen Jan 23, 2026
5ef08e6
feat: park disclaimer in nearyou page
vesameskanen Jan 23, 2026
427d953
Merge branch 'v3' into AB#74-2
vesameskanen Jan 23, 2026
05ccd0e
fix: put language to config
vesameskanen Jan 23, 2026
a94ceb2
feat: show park info link
vesameskanen Jan 23, 2026
8917474
feat: use the new disclaimer in park views
vesameskanen Jan 23, 2026
78a2f84
fix: use new context provides in Disclaimer
vesameskanen Jan 23, 2026
f031602
fix: remove unused styles
vesameskanen Jan 23, 2026
70ff75c
feat: optional separator under card header, tune styles
vesameskanen Jan 26, 2026
63d34bd
chore: remove duplicated mobile styles for parkride and bike stations
vesameskanen Jan 27, 2026
d9dc342
fix: improve park & bike station styles
vesameskanen Jan 27, 2026
6aef742
chore: refactor parkride config, tune styles further
vesameskanen Jan 28, 2026
6937ed9
fix: refactor parkride view
vesameskanen Jan 28, 2026
fc6bc0c
fix: park view separator lines, indentations, value placement
vesameskanen Jan 28, 2026
c9c615b
fix: remove preferences store and old context from city bike station …
vesameskanen Jan 29, 2026
f46c9eb
feat: add and update park related translations
vesameskanen Jan 29, 2026
3010b4c
feat: add headers to all park detail blocks
vesameskanen Jan 29, 2026
e7dc2cb
feat: style park detail values
vesameskanen Jan 29, 2026
dea2c17
fix: font weights as designed
vesameskanen Jan 29, 2026
fcd4f70
fix: large park header in dedicated views
vesameskanen Jan 29, 2026
48645ed
chore: remove old context use from park view
vesameskanen Jan 29, 2026
790fd06
fix: no separator line under park header in mobile
vesameskanen Jan 29, 2026
f81469b
feat: translate OSM opening hours
vesameskanen Jan 29, 2026
d261662
feat: add wheelchair accessibility to park features
vesameskanen Jan 29, 2026
2043210
chore: new sass stuff
vesameskanen Jan 30, 2026
49dbe47
fix: bike station card header font size
vesameskanen Jan 30, 2026
3f4b57c
fix: console warnings
vesameskanen Jan 30, 2026
b9db359
fix: remove old context use from some nearyou components
vesameskanen Jan 30, 2026
cc9a88f
chore: tune styles
vesameskanen Jan 30, 2026
65a661f
chore: reduce react context use in nearyou view
vesameskanen Jan 31, 2026
06bb887
chore: tune disclaimer styles
vesameskanen Jan 31, 2026
f1c4682
feat: dash line connection in opeing hours
vesameskanen Jan 31, 2026
a2b5060
fix: nearyou park search filtering works now
vesameskanen Jan 31, 2026
c8d95ae
fix: restore error handling in parking view
vesameskanen Jan 31, 2026
c639d27
fix: nearyou button accessibility issues
vesameskanen Feb 2, 2026
054ecc5
feat: don't display favourites near you if the tab is empty
vesameskanen Feb 4, 2026
fa2b83f
fix: don't define new function components in react render
vesameskanen Feb 4, 2026
212faf6
fix: remove use of deprecated child context in itinerary legs
vesameskanen Feb 4, 2026
118483f
fix: routing to nearest park uses correct street mode
vesameskanen Feb 4, 2026
b9241d1
fix: TransitLeg unit tests
vesameskanen Feb 4, 2026
53a29d8
fix: TransitLeg unit tests
vesameskanen Feb 4, 2026
892403c
fix: convert SwipeableTabs to a function
vesameskanen Feb 5, 2026
5d354a6
fix: replace unreliable tabIndex fix after child mounting by key even…
vesameskanen Feb 5, 2026
abfa766
fix: remove dead click handler
vesameskanen Feb 5, 2026
2035e4e
Merge branch 'v3' into AB#74-2
vesameskanen Feb 5, 2026
c3820fb
fix: walk routing to neares city bike station
vesameskanen Feb 6, 2026
ece8b8a
Merge branch 'v3' into AB#74-2
vesameskanen Feb 6, 2026
858c04a
fix: update walk/bike/car route after new stop search
vesameskanen Feb 6, 2026
2071542
chore: reorder HSL near you
vesameskanen Feb 11, 2026
ecf3525
Merge branch 'v3' into AB#74-2
vesameskanen Feb 12, 2026
f0a4455
fix: render near you shimmers while favourites load
vesameskanen Feb 12, 2026
25a51c2
fix: include favouriteStatus in IndexPage memo
vesameskanen Feb 13, 2026
c9d6088
fix: alert icon position in nearyou buttons, wrong border color
vesameskanen Feb 13, 2026
01daf6e
fix: wrong border colors
vesameskanen Feb 13, 2026
99c38cf
fix: wrong border colors in nearyou view
vesameskanen Feb 13, 2026
e8f4499
fix: broken icon
vesameskanen Feb 13, 2026
4ef43bb
fix: wrong border colors
vesameskanen Feb 13, 2026
d8978c1
fix: default color, waltti disclaimer color
vesameskanen Feb 13, 2026
bf79e4f
fix: nearyou border radius
vesameskanen Feb 13, 2026
f21733e
fix: nearyou border and hover colors
vesameskanen Feb 13, 2026
32f7b8e
chore: sass changes from next
vesameskanen Feb 13, 2026
d5f1634
fix: latest scss names
vesameskanen Feb 13, 2026
d9f8364
chore: update some dependencies
vesameskanen Feb 16, 2026
0e56b01
fixx: use longer street routing limit for car and bike parks near you
vesameskanen Feb 16, 2026
2f2aa07
fix: remove strange 3 digit limitation from route search
vesameskanen Feb 19, 2026
bdf922c
chore: update near you translations
vesameskanen Mar 3, 2026
2b07da9
fix: remove lots of unused translations
vesameskanen Mar 3, 2026
11bce8f
Merge branch 'v3' into AB#74-2
vesameskanen Mar 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions app/component/Disclaimer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import React, { useState } from 'react';
import { FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types';
import Icon from './Icon';
import { useDeepLink } from '../util/vehicleRentalUtils';
import { useConfigContext } from '../configurations/ConfigContext';
import { useTranslationsContext } from '../util/useTranslationsContext';

export default function Disclaimer({
header,
headerId,
text,
textId,
linkLabel,
linkLabelId,
values,
href,
useLinkButton,
closable,
onClose, // hook e.g. for remembering closing
}) {
const { colors } = useConfigContext();
const intl = useTranslationsContext();

const [showCard, setShowCard] = useState(true);

const handleClose = () => {
setShowCard(false);
if (onClose) {
onClose();
}
};

const onClick = href?.startsWith('http')
? () => {
window.open(href, '_blank', 'noopener,noreferrer');
}
: () => useDeepLink(href, window.location.href);

if (!showCard) {
return null;
}
const hdr = headerId ? (
<FormattedMessage id={headerId} values={values} />
) : (
header
);
const txt = textId ? <FormattedMessage id={textId} values={values} /> : text;
const label = linkLabelId ? (
<FormattedMessage id={linkLabelId} values={values} />
) : (
linkLabel
);

return (
<div className="disclaimer-container">
<Icon className="info" img="icon_info" />
<div className="disclaimer">
<div className="disclaimer-header">
{hdr && <h3>{hdr}</h3>}
{closable && (
<button
className="disclaimer-close"
aria-label={intl.formatMessage({ id: 'close' })}
onClick={handleClose}
type="button"
>
<Icon color={colors.primary} img="icon_close" />
</button>
)}
</div>
{txt}
{href && useLinkButton && (
<button
type="button"
className="external-link-button"
onClick={e => {
e.stopPropagation();
onClick(e);
}}
>
{label}
</button>
)}
{href && !useLinkButton && (
<a
className="external-link"
href={href}
target="_blank"
rel="noreferrer"
>
{label}
<Icon className="arrow" img="icon_arrow-collapse--right" />
</a>
)}
</div>
</div>
);
}

Disclaimer.propTypes = {
header: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
headerId: PropTypes.string,
text: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
textId: PropTypes.string,
linkLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
linkLabelId: PropTypes.string,
values: PropTypes.objectOf(PropTypes.string),
href: PropTypes.string,
useLinkButton: PropTypes.bool,
closable: PropTypes.bool,
onClose: PropTypes.func,
};

Disclaimer.defaultProps = {
header: null,
headerId: undefined,
text: null,
textId: undefined,
linkLabel: null,
linkLabelId: undefined,
values: {},
href: undefined,
useLinkButton: false,
closable: false,
onClose: undefined,
};
55 changes: 29 additions & 26 deletions app/component/IndexPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
checkPositioningPermission,
startLocationWatch,
} from '../action/PositionActions';
import FavouriteStore from '../store/FavouriteStore';

const StopRouteSearch = withSearchContext(DTAutoSuggest);
const LocationSearch = withSearchContext(DTAutosuggestPanel);
Expand All @@ -63,26 +64,22 @@ class IndexPage extends React.Component {
breakpoint: PropTypes.string.isRequired,
origin: locationShape.isRequired,
destination: locationShape.isRequired,
lang: PropTypes.string,
currentTime: PropTypes.number.isRequired,
// eslint-disable-next-line
query: PropTypes.object.isRequired,
favouriteModalAction: PropTypes.string,
fromMap: PropTypes.string,
locationState: locationShape.isRequired,
favouriteStatus: PropTypes.string.isRequired,
// eslint-disable-next-line
favourites: PropTypes.array.isRequired,
};

static defaultProps = {
lang: 'fi',
favouriteModalAction: '',
fromMap: undefined,
};

constructor(props, context) {
super(props, context);
this.state = {};
}

componentDidMount() {
const { from, to } = this.context.match.params;
/* initialize stores from URL params */
Expand Down Expand Up @@ -226,9 +223,10 @@ class IndexPage extends React.Component {

NearStops() {
const { intl, config } = this.context;
const { colors, fontWeights } = config;
const { lang } = this.props;
const nearYouModes = getNearYouModes(config);
const { colors, fontWeights, language } = config;

const nearYouModes = getNearYouModes(config, this.props.favourites);

// If nearYouModes is configured, display those. Otherwise, display all configured transport modes
const modeArray =
nearYouModes.length > 0
Expand All @@ -255,9 +253,13 @@ class IndexPage extends React.Component {
<CtrlPanel.NearStopsAndRoutes
appElement="#app"
modeArray={modeArray}
loading={
this.props.favouriteStatus ===
FavouriteStore.STATUS_FETCHING_OR_UPDATING
}
modeSet={config.iconModeSet}
urlPrefix={`/${PREFIX_NEARYOU}`}
language={lang}
language={language}
title={config.nearYouTitle}
alertsContext={alertsContext}
origin={this.props.origin}
Expand All @@ -284,7 +286,7 @@ class IndexPage extends React.Component {
render() {
const { intl, config } = this.context;
const { trafficNowLink, colors, fontWeights } = config;
const { breakpoint, lang } = this.props;
const { breakpoint } = this.props;
const origin = this.pendingOrigin || this.props.origin;
const destination = this.pendingDestination || this.props.destination;
const locationSources = ['History', 'Datasource'];
Expand Down Expand Up @@ -313,7 +315,7 @@ class IndexPage extends React.Component {
appElement: '#app',
origin,
destination,
lang,
lang: config.language,
sources: locationSources,
targets,
refPoint,
Expand Down Expand Up @@ -341,7 +343,7 @@ class IndexPage extends React.Component {
selectHandler: this.onSelectStopRoute,
getAutoSuggestIcons: config.getAutoSuggestIcons,
value: '',
lang,
lang: config.language,
sources,
targets: stopAndRouteSearchTargets,
fontWeights,
Expand Down Expand Up @@ -383,15 +385,15 @@ class IndexPage extends React.Component {
<DatetimepickerContainer
realtime
color={colors.primary}
lang={lang}
lang={config.language}
/>
</div>
{!config.hideFavourites && (
<>
<FavouritesContainer
favouriteModalAction={this.props.favouriteModalAction}
onClickFavourite={this.clickFavourite}
lang={lang}
lang={config.language}
/>
<CtrlPanel.SeparatorLine usePaddingBottom20 />
</>
Expand All @@ -404,9 +406,9 @@ class IndexPage extends React.Component {
<CtrlPanel.SeparatorLine />
</>
)}
{trafficNowLink?.[lang] && (
{trafficNowLink?.[config.language] && (
<TrafficNowLink
lang={lang}
lang={config.language}
handleClick={this.trafficNowHandler}
/>
)}
Expand Down Expand Up @@ -437,12 +439,12 @@ class IndexPage extends React.Component {
<DatetimepickerContainer
realtime
color={colors.primary}
lang={lang}
lang={config.language}
/>
</div>
<FavouritesContainer
onClickFavourite={this.clickFavourite}
lang={lang}
lang={config.language}
isMobile
/>
<CtrlPanel.SeparatorLine />
Expand All @@ -452,9 +454,9 @@ class IndexPage extends React.Component {
</div>
<CtrlPanel.SeparatorLine usePaddingBottom20 />
{!trafficNowLink ||
(trafficNowLink[lang] !== '' && (
(trafficNowLink[config.language] !== '' && (
<TrafficNowLink
lang={lang}
lang={config.language}
handleClick={this.trafficNowHandler}
fontWeights={fontWeights}
/>
Expand All @@ -473,9 +475,9 @@ const Index = memo(
isEqual(nextProps.origin, props.origin) &&
isEqual(nextProps.destination, props.destination) &&
isEqual(nextProps.breakpoint, props.breakpoint) &&
isEqual(nextProps.lang, props.lang) &&
isEqual(nextProps.query, props.query) &&
isEqual(nextProps.locationState, props.locationState),
isEqual(nextProps.locationState, props.locationState) &&
isEqual(nextProps.favouriteStatus, props.favouriteStatus),
);

const IndexPageWithBreakpoint = withBreakpoint(Index);
Expand All @@ -486,8 +488,8 @@ const IndexPageWithStores = connectToStores(
'OriginStore',
'DestinationStore',
'TimeStore',
'PreferencesStore',
'PositionStore',
'FavouriteStore',
],
(context, props) => {
const origin = context.getStore('OriginStore').getOrigin();
Expand All @@ -507,9 +509,10 @@ const IndexPageWithStores = connectToStores(
}
newProps.origin = origin;
newProps.destination = destination;
newProps.lang = context.getStore('PreferencesStore').getLanguage();
newProps.currentTime = context.getStore('TimeStore').getCurrentTime();
newProps.query = query; // defines itinerary search time & arriveBy
newProps.favouriteStatus = context.getStore('FavouriteStore').getStatus();
newProps.favourites = context.getStore('FavouriteStore').getFavourites();

return newProps;
},
Expand Down
Loading
Loading